diff --git a/.gitignore b/.gitignore index 5883bfee..592ca6bd 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,6 @@ npm-debug.log node_modules *.js *.map -dist/ -dist_tests/ +dist-cjs/ +dist-esm/ yarn-error.log diff --git a/.npmignore b/.npmignore index 5088a255..8f7f6b82 100644 --- a/.npmignore +++ b/.npmignore @@ -7,7 +7,7 @@ node_modules *.map example test -dist/test +dist-esm/test circle.yml ARCHITECTURE.md CONTRIBUTING.md diff --git a/.vscode/launch.json b/.vscode/launch.json index a051834f..67696e87 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "type": "node", "request": "launch", "name": "Launch Program", - "program": "${workspaceRoot}/node_modules/.bin/ava ./dist/test/test.js", + "program": "${workspaceRoot}/node_modules/.bin/ava ./dist-esm/test/test.js", "cwd": "${workspaceRoot}" }, { diff --git a/package-lock.json b/package-lock.json index 268c0365..95538d26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,25 +1,24 @@ { "name": "json-schema-to-typescript", - "version": "14.0.2", + "version": "14.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "json-schema-to-typescript", - "version": "14.0.2", + "version": "14.0.5", "license": "MIT", "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.5.5", "@types/json-schema": "^7.0.15", - "@types/lodash": "^4.17.0", + "@types/lodash-es": "^4.17.12", "cli-color": "^2.0.4", "glob": "^10.3.12", "is-glob": "^4.0.3", "js-yaml": "^4.1.0", - "lodash": "^4.17.21", + "lodash-es": "^4.17.21", "minimist": "^1.2.8", "mkdirp": "^3.0.1", - "mz": "^2.7.0", "node-fetch": "^3.3.2", "prettier": "^3.2.5" }, @@ -492,6 +491,14 @@ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==" }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -963,7 +970,8 @@ "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true }, "node_modules/ap": { "version": "0.2.0", @@ -4144,7 +4152,13 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, "node_modules/lodash.memoize": { "version": "3.0.4", @@ -4488,16 +4502,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4595,6 +4599,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -6032,25 +6037,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", diff --git a/package.json b/package.json index 6e4e6e6f..3863b11c 100644 --- a/package.json +++ b/package.json @@ -2,19 +2,24 @@ "name": "json-schema-to-typescript", "version": "14.0.5", "description": "compile json schema to typescript typings", - "main": "dist/src/index.js", + "main": "dist-cjs/src/index.js", + "exports": { + "require": "./dist-cjs/src/index.js", + "import": "./dist-esm/src/index.js" + }, "bin": { - "json2ts": "dist/src/cli.js" + "json2ts": "dist-esm/src/cli.js" }, - "typings": "dist/src/index.d.ts", + "type": "module", + "typings": "dist-esm/src/index.d.ts", "engines": { "node": ">=16.0.0" }, "scripts": { "build": "npm run lint && npm run clean && npm run build:browser && npm run build:server", - "build:browser": "browserify src/index.ts -s jstt -p tsify > dist/bundle.js", - "build:server": "tsc -d", - "clean": "shx rm -rf dist && mkdir dist", + "build:browser": "browserify src/index.ts -s jstt -p tsify > dist-esm/bundle.js", + "build:server": "tsc -p ./tsconfig.cjs.json -d && tsc -p ./tsconfig.esm.json -d", + "clean": "shx rm -rf dist-cjs && shx rm -rf dist-esm", "format": "prettier \"{src,test}/*.ts\" --write", "format-check": "prettier \"{src,test}/*.ts\" --check", "lint": "eslint src/*.ts test/*.ts", @@ -23,7 +28,7 @@ "stresstest": "seq 1 10 | xargs -I{} npm test", "prepublishOnly": "npm test", "pre-test": "npm run clean && npm run format-check && npm run build:server", - "watch": "tsc -w", + "watch": "tsc -p ./tsconfig.esm.json -w", "watch:test": "ava -w" }, "repository": { @@ -50,15 +55,14 @@ "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.5.5", "@types/json-schema": "^7.0.15", - "@types/lodash": "^4.17.0", + "@types/lodash-es": "^4.17.12", "cli-color": "^2.0.4", "glob": "^10.3.12", "is-glob": "^4.0.3", "js-yaml": "^4.1.0", - "lodash": "^4.17.21", + "lodash-es": "^4.17.21", "minimist": "^1.2.8", "mkdirp": "^3.0.1", - "mz": "^2.7.0", "node-fetch": "^3.3.2", "prettier": "^3.2.5" }, @@ -87,7 +91,7 @@ }, "ava": { "files": [ - "./dist/test/test.js" + "./dist-esm/test/test.js" ], "snapshotDir": "./test/__snapshots__" }, diff --git a/src/cli.ts b/src/cli.ts index 217de215..defc7469 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,13 +1,13 @@ #!/usr/bin/env node import minimist from 'minimist' -import {readFile, writeFile, existsSync, lstatSync, readdirSync} from 'mz/fs' +import {existsSync, readdirSync, readFileSync, lstatSync, writeFileSync} from 'fs' import * as mkdirp from 'mkdirp' import {glob} from 'glob' import isGlob from 'is-glob' import {join, resolve, dirname} from 'path' -import {compile, DEFAULT_OPTIONS, Options} from './index' -import {pathTransform, error, parseFileAsJSONSchema, justName} from './utils' +import {compile, DEFAULT_OPTIONS, Options} from './index.js' +import {pathTransform, error, parseFileAsJSONSchema, justName} from './utils.js' main( minimist(process.argv.slice(2), { @@ -114,14 +114,14 @@ async function processDir(argIn: string, argOut: string | undefined, argv: Parti ) } -async function outputResult(result: string, outputPath: string | undefined): Promise { +function outputResult(result: string, outputPath: string | undefined): void { if (!outputPath) { process.stdout.write(result) } else { if (!isDir(dirname(outputPath))) { mkdirp.sync(dirname(outputPath)) } - return await writeFile(outputPath, result) + return writeFileSync(outputPath, result) } } @@ -150,18 +150,18 @@ async function readInput(argIn?: string): Promise<{filename: string | null; cont } return { filename: argIn, - contents: await readFile(resolve(process.cwd(), argIn), 'utf-8'), + contents: readFileSync(resolve(process.cwd(), argIn), 'utf-8'), } } async function readStream(stream: NodeJS.ReadStream): Promise { - const chunks = [] + const chunks: Uint8Array[] = [] for await (const chunk of stream) chunks.push(chunk) return Buffer.concat(chunks).toString('utf8') } function printHelp() { - const pkg = require('../../package.json') + const pkg = JSON.parse(readFileSync('../../package.json', 'utf8')) process.stdout.write( ` diff --git a/src/formatter.ts b/src/formatter.ts index 05f33628..d5712aaf 100644 --- a/src/formatter.ts +++ b/src/formatter.ts @@ -1,5 +1,5 @@ import {format as prettify} from 'prettier' -import {Options} from './' +import {Options} from './index.js' export async function format(code: string, options: Options): Promise { if (!options.format) { diff --git a/src/generator.ts b/src/generator.ts index fb8d23b0..d3fed4dd 100644 --- a/src/generator.ts +++ b/src/generator.ts @@ -1,5 +1,5 @@ -import {memoize, omit} from 'lodash' -import {DEFAULT_OPTIONS, Options} from './index' +import {memoize, omit} from 'lodash-es' +import {DEFAULT_OPTIONS, Options} from './index.js' import { AST, ASTWithStandaloneName, @@ -13,8 +13,8 @@ import { TNamedInterface, TUnion, T_UNKNOWN, -} from './types/AST' -import {log, toSafeString} from './utils' +} from './types/AST.js' +import {log, toSafeString} from './utils.js' export function generate(ast: AST, options = DEFAULT_OPTIONS): string { return ( diff --git a/src/index.ts b/src/index.ts index de22beaf..27d97756 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,23 +1,23 @@ import {readFileSync} from 'fs' import {JSONSchema4} from 'json-schema' import {ParserOptions as $RefOptions} from '@apidevtools/json-schema-ref-parser' -import {cloneDeep, endsWith, merge} from 'lodash' +import {cloneDeep, endsWith, merge} from 'lodash-es' import {dirname} from 'path' import {Options as PrettierOptions} from 'prettier' -import {format} from './formatter' -import {generate} from './generator' -import {normalize} from './normalizer' -import {optimize} from './optimizer' -import {parse} from './parser' -import {dereference} from './resolver' -import {error, stripExtension, Try, log, parseFileAsJSONSchema} from './utils' -import {validate} from './validator' +import {format} from './formatter.js' +import {generate} from './generator.js' +import {normalize} from './normalizer.js' +import {optimize} from './optimizer.js' +import {parse} from './parser.js' +import {dereference} from './resolver.js' +import {error, stripExtension, Try, log, parseFileAsJSONSchema} from './utils.js' +import {validate} from './validator.js' import {isDeepStrictEqual} from 'util' -import {link} from './linker' -import {validateOptions} from './optionValidator' -import {JSONSchema as LinkedJSONSchema} from './types/JSONSchema' +import {link} from './linker.js' +import {validateOptions} from './optionValidator.js' +import {JSONSchema as LinkedJSONSchema} from './types/JSONSchema.js' -export {EnumJSONSchema, JSONSchema, NamedEnumJSONSchema, CustomTypeJSONSchema} from './types/JSONSchema' +export {EnumJSONSchema, JSONSchema, NamedEnumJSONSchema, CustomTypeJSONSchema} from './types/JSONSchema.js' export interface Options { /** diff --git a/src/linker.ts b/src/linker.ts index eb76ae51..878b2bca 100644 --- a/src/linker.ts +++ b/src/linker.ts @@ -1,5 +1,5 @@ -import {JSONSchema, Parent, LinkedJSONSchema} from './types/JSONSchema' -import {isPlainObject} from 'lodash' +import {JSONSchema, Parent, LinkedJSONSchema} from './types/JSONSchema.js' +import {isPlainObject} from 'lodash-es' import {JSONSchema4Type} from 'json-schema' /** diff --git a/src/normalizer.ts b/src/normalizer.ts index fa3ec6ba..5726ad86 100644 --- a/src/normalizer.ts +++ b/src/normalizer.ts @@ -1,7 +1,7 @@ -import {JSONSchemaTypeName, LinkedJSONSchema, NormalizedJSONSchema, Parent} from './types/JSONSchema' -import {appendToDescription, escapeBlockComment, isSchemaLike, justName, toSafeString, traverse} from './utils' -import {Options} from './' -import {DereferencedPaths} from './resolver' +import {JSONSchemaTypeName, LinkedJSONSchema, NormalizedJSONSchema, Parent} from './types/JSONSchema.js' +import {appendToDescription, escapeBlockComment, isSchemaLike, justName, toSafeString, traverse} from './utils.js' +import {Options} from './index.js' +import {DereferencedPaths} from './resolver.js' import {isDeepStrictEqual} from 'util' type Rule = ( diff --git a/src/optimizer.ts b/src/optimizer.ts index c8e1148f..3dc59c68 100644 --- a/src/optimizer.ts +++ b/src/optimizer.ts @@ -1,8 +1,8 @@ -import {uniqBy} from 'lodash' -import {Options} from '.' -import {generateType} from './generator' -import {AST, T_ANY, T_UNKNOWN} from './types/AST' -import {log} from './utils' +import {uniqBy} from 'lodash-es' +import {Options} from './index.js' +import {generateType} from './generator.js' +import {AST, T_ANY, T_UNKNOWN} from './types/AST.js' +import {log} from './utils.js' export function optimize(ast: AST, options: Options, processed = new Set()): AST { if (processed.has(ast)) { diff --git a/src/optionValidator.ts b/src/optionValidator.ts index 5eb8f44f..774b724b 100644 --- a/src/optionValidator.ts +++ b/src/optionValidator.ts @@ -1,4 +1,4 @@ -import {Options} from '.' +import {Options} from './index.js' export function validateOptions({maxItems}: Partial): void { if (maxItems !== undefined && maxItems < -1) { diff --git a/src/parser.ts b/src/parser.ts index 7e82d7f6..a391873e 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1,8 +1,8 @@ import {JSONSchema4Type, JSONSchema4TypeName} from 'json-schema' -import {findKey, includes, isPlainObject, map, memoize, omit} from 'lodash' +import {findKey, includes, isPlainObject, map, memoize, omit} from 'lodash-es' import {format} from 'util' -import {Options} from './' -import {typesOfSchema} from './typesOfSchema' +import {Options} from './index.js' +import {typesOfSchema} from './typesOfSchema.js' import { AST, T_ANY, @@ -14,7 +14,7 @@ import { T_UNKNOWN, T_UNKNOWN_ADDITIONAL_PROPERTIES, TIntersection, -} from './types/AST' +} from './types/AST.js' import { getRootSchema, isBoolean, @@ -23,8 +23,8 @@ import { JSONSchemaWithDefinitions, SchemaSchema, SchemaType, -} from './types/JSONSchema' -import {generateName, log, maybeStripDefault, maybeStripNameHints} from './utils' +} from './types/JSONSchema.js' +import {generateName, log, maybeStripDefault, maybeStripNameHints} from './utils.js' export type Processed = Map> diff --git a/src/resolver.ts b/src/resolver.ts index 94dc5a0e..8a6755b3 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -1,6 +1,6 @@ import {$RefParser, ParserOptions as $RefOptions} from '@apidevtools/json-schema-ref-parser' -import {JSONSchema} from './types/JSONSchema' -import {log} from './utils' +import {JSONSchema} from './types/JSONSchema.js' +import {log} from './utils.js' export type DereferencedPaths = WeakMap diff --git a/src/types/JSONSchema.ts b/src/types/JSONSchema.ts index 4c644f3f..325adb18 100644 --- a/src/types/JSONSchema.ts +++ b/src/types/JSONSchema.ts @@ -1,5 +1,5 @@ import {JSONSchema4, JSONSchema4Type, JSONSchema4TypeName} from 'json-schema' -import {isPlainObject, memoize} from 'lodash' +import {isPlainObject, memoize} from 'lodash-es' export type SchemaType = | 'ALL_OF' diff --git a/src/typesOfSchema.ts b/src/typesOfSchema.ts index 7ba3f5d5..1d7dea5e 100644 --- a/src/typesOfSchema.ts +++ b/src/typesOfSchema.ts @@ -1,5 +1,5 @@ -import {isPlainObject} from 'lodash' -import {isCompound, JSONSchema, SchemaType} from './types/JSONSchema' +import {isPlainObject} from 'lodash-es' +import {isCompound, JSONSchema, SchemaType} from './types/JSONSchema.js' /** * Duck types a JSONSchema schema or property to determine which kind of AST node to parse it into. diff --git a/src/utils.ts b/src/utils.ts index c7f1f215..3f02761e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,6 @@ -import {deburr, isPlainObject, trim, upperFirst} from 'lodash' +import {deburr, isPlainObject, trim, upperFirst} from 'lodash-es' import {basename, dirname, extname, normalize, sep, posix} from 'path' -import {JSONSchema, LinkedJSONSchema, Parent} from './types/JSONSchema' +import {JSONSchema, LinkedJSONSchema, Parent} from './types/JSONSchema.js' import {JSONSchema4} from 'json-schema' import yaml from 'js-yaml' @@ -208,7 +208,7 @@ export function error(...messages: any[]): void { if (!process.env.VERBOSE) { return console.error(messages) } - console.error(getStyledTextForLogging('red')?.('error'), ...messages) + getStyledTextForLogging('red').then(text => console.error(text?.('error'), ...messages)) } type LogStyle = 'blue' | 'cyan' | 'green' | 'magenta' | 'red' | 'white' | 'yellow' @@ -221,31 +221,35 @@ export function log(style: LogStyle, title: string, ...messages: unknown[]): voi if (messages.length > 1 && typeof messages[messages.length - 1] !== 'string') { lastMessage = messages.splice(messages.length - 1, 1) } - console.info(require('cli-color').whiteBright.bgCyan('debug'), getStyledTextForLogging(style)?.(title), ...messages) - if (lastMessage) { - console.dir(lastMessage, {depth: 6, maxArrayLength: 6}) - } + import('cli-color').then(color => { + getStyledTextForLogging(style).then(text => { + console.info(color.whiteBright.bgCyan('debug'), text?.(title), ...messages) + if (lastMessage) { + console.dir(lastMessage, {depth: 6, maxArrayLength: 6}) + } + }) + }) } -function getStyledTextForLogging(style: LogStyle): ((text: string) => string) | undefined { +function getStyledTextForLogging(style: LogStyle): Promise<((text: string) => string) | undefined> { if (!process.env.VERBOSE) { - return + return Promise.resolve(undefined) } switch (style) { case 'blue': - return require('cli-color').whiteBright.bgBlue + return import('cli-color').then(color => color.whiteBright.bgBlue) case 'cyan': - return require('cli-color').whiteBright.bgCyan + return import('cli-color').then(color => color.whiteBright.bgCyan) case 'green': - return require('cli-color').whiteBright.bgGreen + return import('cli-color').then(color => color.whiteBright.bgGreen) case 'magenta': - return require('cli-color').whiteBright.bgMagenta + return import('cli-color').then(color => color.whiteBright.bgMagenta) case 'red': - return require('cli-color').whiteBright.bgRedBright + return import('cli-color').then(color => color.whiteBright.bgRedBright) case 'white': - return require('cli-color').black.bgWhite + return import('cli-color').then(color => color.black.bgWhite) case 'yellow': - return require('cli-color').whiteBright.bgYellow + return import('cli-color').then(color => color.whiteBright.bgYellow) } } diff --git a/src/validator.ts b/src/validator.ts index 69fb390d..5eb5b4a7 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -1,5 +1,5 @@ -import {JSONSchema, LinkedJSONSchema} from './types/JSONSchema' -import {traverse} from './utils' +import {JSONSchema, LinkedJSONSchema} from './types/JSONSchema.js' +import {traverse} from './utils.js' type Rule = (schema: JSONSchema) => boolean | void const rules = new Map() diff --git a/test/__snapshots__/test/test.ts.md b/test/__snapshots__/test/test.ts.md index e1c6e25d..2e191d26 100644 --- a/test/__snapshots__/test/test.ts.md +++ b/test/__snapshots__/test/test.ts.md @@ -449547,26 +449547,6 @@ Generated by [AVA](https://avajs.dev). }␊ ` -> Snapshot 5 - - './test/resources/MultiSchema/out/b.yaml.d.ts' - -> Snapshot 6 - - `/* eslint-disable */␊ - /**␊ - * This file was automatically generated by json-schema-to-typescript.␊ - * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,␊ - * and run json-schema-to-typescript to regenerate this file.␊ - */␊ - ␊ - export interface BSchema {␊ - x?: string;␊ - y: number;␊ - [k: string]: unknown;␊ - }␊ - ` - ## files in (-i), pipe out > Snapshot 1 diff --git a/test/__snapshots__/test/test.ts.snap b/test/__snapshots__/test/test.ts.snap index 6640ff0a..6982bfc8 100644 Binary files a/test/__snapshots__/test/test.ts.snap and b/test/__snapshots__/test/test.ts.snap differ diff --git a/test/e2e/customName.1.ts b/test/e2e/customName.1.ts index 378ed896..7a6858a9 100644 --- a/test/e2e/customName.1.ts +++ b/test/e2e/customName.1.ts @@ -1,4 +1,4 @@ -import {Options} from '../../src/' +import {Options} from '../../src/index.js' export const input = { type: 'object', @@ -17,8 +17,7 @@ export const input = { export const options: Partial = { customName: (_schema, keyName) => { - if (!keyName) - return undefined // Fallback to default naming + if (!keyName) return undefined // Fallback to default naming return 'CustomPrefix_' + keyName }, } diff --git a/test/e2e/options.format.ts b/test/e2e/options.format.ts index ffa4a6a5..b201e235 100644 --- a/test/e2e/options.format.ts +++ b/test/e2e/options.format.ts @@ -1,4 +1,4 @@ -import {Options} from '../../src' +import {Options} from '../../src/index.js' export const input = { title: 'Example Schema', diff --git a/test/e2e/options.style.ts b/test/e2e/options.style.ts index 332b591f..809a7ad2 100644 --- a/test/e2e/options.style.ts +++ b/test/e2e/options.style.ts @@ -1,4 +1,4 @@ -import {Options} from '../../src' +import {Options} from '../../src/index.js' export const input = { title: 'Example Schema', diff --git a/test/e2e/realWorld.fhir.ts b/test/e2e/realWorld.fhir.ts index b8bbfd62..45fab204 100644 --- a/test/e2e/realWorld.fhir.ts +++ b/test/e2e/realWorld.fhir.ts @@ -1,4 +1,4 @@ -import {Options} from '../../src' +import {Options} from '../../src/index.js' export const input = { $schema: 'http://json-schema.org/draft-06/schema#', diff --git a/test/http.ts b/test/http.ts index bbcadf4e..012565dc 100644 --- a/test/http.ts +++ b/test/http.ts @@ -1,7 +1,8 @@ import {existsSync, readFileSync, writeFileSync} from 'fs' import {get as httpGet} from 'http' import {get as httpsGet} from 'https' -import {join} from 'path' +import {dirname, join} from 'path' +import {fileURLToPath} from 'url' const CACHE_DIR = 'test/__fixtures__' @@ -27,6 +28,8 @@ function getFromFilesystem(url: string): object | undefined { } function getFilepath(url: string): string { + const __filename = fileURLToPath(import.meta.url) + const __dirname = dirname(__filename) return join(__dirname, '../../', CACHE_DIR, url.replace(/[:\/\\]/g, '-')) } diff --git a/test/test.ts b/test/test.ts index 76944331..166882e5 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,14 +1,14 @@ -import {run as runCLITests} from './testCLI' -import {run as runCompileFromFileTests} from './testCompileFromFile' -import {hasOnly, run as runE2ETests} from './testE2E' -import {run as runIdempotenceTests} from './testIdempotence' -import {run as runLinkerTests} from './testLinker' -import {run as runNormalizerTests} from './testNormalizer' -import {run as runUtilsTests} from './testUtils' +import {run as runCLITests} from './testCLI.js' +import {run as runCompileFromFileTests} from './testCompileFromFile.js' +import {hasOnly, run as runE2ETests} from './testE2E.js' +import {run as runIdempotenceTests} from './testIdempotence.js' +import {run as runLinkerTests} from './testLinker.js' +import {run as runNormalizerTests} from './testNormalizer.js' +import {run as runUtilsTests} from './testUtils.js' -runE2ETests() +await runE2ETests() -if (!hasOnly()) { +if (!(await hasOnly())) { runCompileFromFileTests() runCLITests() runIdempotenceTests() diff --git a/test/testCLI.ts b/test/testCLI.ts index 327c1004..f3f84ba6 100644 --- a/test/testCLI.ts +++ b/test/testCLI.ts @@ -1,103 +1,108 @@ import test from 'ava' import {execSync} from 'child_process' import {readFileSync, unlinkSync, readdirSync, existsSync, lstatSync} from 'fs' -import {resolve, posix} from 'path' +import {resolve, posix, dirname} from 'path' import * as rimraf from 'rimraf' +import {fileURLToPath} from 'url' export function run() { test('pipe in, pipe out', t => { t.snapshot( - execSync('shx cat ./test/resources/ReferencedType.json | node dist/src/cli.js', {encoding: 'utf-8'}).toString(), + execSync('shx cat ./test/resources/ReferencedType.json | node dist-esm/src/cli.js', { + encoding: 'utf-8', + }).toString(), ) }) test('pipe in (schema without ID), pipe out', t => { t.snapshot( - execSync('shx cat ./test/resources/ReferencedTypeWithoutID.json | node dist/src/cli.js', { + execSync('shx cat ./test/resources/ReferencedTypeWithoutID.json | node dist-esm/src/cli.js', { encoding: 'utf-8', }).toString(), ) }) test('file in (no flags), pipe out', t => { - t.snapshot(execSync('node dist/src/cli.js ./test/resources/ReferencedType.json').toString()) + t.snapshot(execSync('node dist-esm/src/cli.js ./test/resources/ReferencedType.json').toString()) }) test('file in (--input), pipe out', t => { - t.snapshot(execSync('node dist/src/cli.js --input ./test/resources/ReferencedType.json').toString()) + t.snapshot(execSync('node dist-esm/src/cli.js --input ./test/resources/ReferencedType.json').toString()) }) test('file in (-i), pipe out', t => { - t.snapshot(execSync('node dist/src/cli.js -i ./test/resources/ReferencedType.json').toString()) + t.snapshot(execSync('node dist-esm/src/cli.js -i ./test/resources/ReferencedType.json').toString()) }) test('file in (-i), unreachable definitions flag, pipe out', t => { t.snapshot( - execSync('node dist/src/cli.js -i ./test/resources/DefinitionsOnly.json --unreachableDefinitions').toString(), + execSync('node dist-esm/src/cli.js -i ./test/resources/DefinitionsOnly.json --unreachableDefinitions').toString(), ) }) test('file in (-i), style flags, pipe out', t => { t.snapshot( - execSync('node dist/src/cli.js -i ./test/resources/Enum.json --style.singleQuote --no-style.semi').toString(), + execSync('node dist-esm/src/cli.js -i ./test/resources/Enum.json --style.singleQuote --no-style.semi').toString(), ) }) test('file in (-i), pipe out (absolute path)', t => { - t.snapshot(execSync(`node dist/src/cli.js -i ${__dirname}/../../test/resources/ReferencedType.json`).toString()) + const __filename = fileURLToPath(import.meta.url) + const __dirname = dirname(__filename) + t.snapshot(execSync(`node dist-esm/src/cli.js -i ${__dirname}/../../test/resources/ReferencedType.json`).toString()) }) test('file in (yaml), pipe out', t => { - t.snapshot(execSync('node dist/src/cli.js ./test/resources/Schema.yaml').toString()) + t.snapshot(execSync('node dist-esm/src/cli.js ./test/resources/Schema.yaml').toString()) }) test('pipe in, file out (--output)', t => { - execSync('shx cat ./test/resources/ReferencedType.json | node dist/src/cli.js --output ./ReferencedType.d.ts') + execSync('shx cat ./test/resources/ReferencedType.json | node dist-esm/src/cli.js --output ./ReferencedType.d.ts') t.snapshot(readFileSync('./ReferencedType.d.ts', 'utf-8')) unlinkSync('./ReferencedType.d.ts') }) test('pipe in, file out (-o)', t => { - execSync('shx cat ./test/resources/ReferencedType.json | node dist/src/cli.js -o ./ReferencedType.d.ts') + execSync('shx cat ./test/resources/ReferencedType.json | node dist-esm/src/cli.js -o ./ReferencedType.d.ts') t.snapshot(readFileSync('./ReferencedType.d.ts', 'utf-8')) unlinkSync('./ReferencedType.d.ts') }) test('file in (no flags), file out (no flags)', t => { - execSync('node dist/src/cli.js ./test/resources/ReferencedType.json ./ReferencedType.d.ts') + execSync('node dist-esm/src/cli.js ./test/resources/ReferencedType.json ./ReferencedType.d.ts') t.snapshot(readFileSync('./ReferencedType.d.ts', 'utf-8')) unlinkSync('./ReferencedType.d.ts') }) test('file in (-i), file out (-o)', t => { - execSync('node dist/src/cli.js -i ./test/resources/ReferencedType.json -o ./ReferencedType.d.ts') + execSync('node dist-esm/src/cli.js -i ./test/resources/ReferencedType.json -o ./ReferencedType.d.ts') t.snapshot(readFileSync('./ReferencedType.d.ts', 'utf-8')) unlinkSync('./ReferencedType.d.ts') }) test('file in (--input), file out (--output)', t => { - execSync('node dist/src/cli.js --input ./test/resources/ReferencedType.json --output ./ReferencedType.d.ts') + execSync('node dist-esm/src/cli.js --input ./test/resources/ReferencedType.json --output ./ReferencedType.d.ts') t.snapshot(readFileSync('./ReferencedType.d.ts', 'utf-8')) unlinkSync('./ReferencedType.d.ts') }) test('--unknownAny', t => { t.snapshot( - execSync('node dist/src/cli.js --unknownAny=false --input ./test/resources/ReferencedType.json').toString(), + execSync('node dist-esm/src/cli.js --unknownAny=false --input ./test/resources/ReferencedType.json').toString(), ) }) test('--additionalProperties', t => { t.snapshot( execSync( - 'node dist/src/cli.js --additionalProperties=false --input ./test/resources/ReferencedType.json', + 'node dist-esm/src/cli.js --additionalProperties=false --input ./test/resources/ReferencedType.json', ).toString(), ) }) test('files in (-i), files out (-o)', t => { execSync( - `node dist/src/cli.js -i "./test/resources/MultiSchema/**/*.{json,yaml,yml}" -o ./test/resources/MultiSchema/out`, + `node dist-esm/src/cli.js -i "./test/resources/MultiSchema/**/*.{json,yaml,yml}" -o ./test/resources/MultiSchema/out`, ) readdirSync('./test/resources/MultiSchema/out').forEach(f => { @@ -110,12 +115,12 @@ export function run() { }) test('files in (-i), pipe out', t => { - t.snapshot(execSync(`node dist/src/cli.js -i "./test/resources/MultiSchema/**/*.{json,yaml,yml}"`).toString()) + t.snapshot(execSync(`node dist-esm/src/cli.js -i "./test/resources/MultiSchema/**/*.{json,yaml,yml}"`).toString()) }) test('files in (-i), files out (-o) nested dir does not exist', t => { execSync( - `node dist/src/cli.js -i "./test/resources/MultiSchema/**/*.{json,yaml,yml}" -o ./test/resources/MultiSchema/foo/bar/out`, + `node dist-esm/src/cli.js -i "./test/resources/MultiSchema/**/*.{json,yaml,yml}" -o ./test/resources/MultiSchema/foo/bar/out`, ) readdirSync('./test/resources/MultiSchema/foo/bar/out').forEach(f => { const path = `./test/resources/MultiSchema/foo/bar/out/${f}` @@ -128,7 +133,7 @@ export function run() { test('files in (-i), files out (-o) matching nested dir', t => { execSync( - `node dist/src/cli.js -i "./test/resources/../../test/resources/MultiSchema2/" -o ./test/resources/MultiSchema2/out`, + `node dist-esm/src/cli.js -i "./test/resources/../../test/resources/MultiSchema2/" -o ./test/resources/MultiSchema2/out`, ) getPaths('./test/resources/MultiSchema2/out').forEach(file => { t.snapshot(file) diff --git a/test/testCompileFromFile.ts b/test/testCompileFromFile.ts index 5a45a523..54711602 100644 --- a/test/testCompileFromFile.ts +++ b/test/testCompileFromFile.ts @@ -1,5 +1,5 @@ import test from 'ava' -import {compileFromFile} from '../src' +import {compileFromFile} from '../src/index.js' export function run() { test('compileFromFile should resolve refs from cwd option', async t => diff --git a/test/testE2E.ts b/test/testE2E.ts index dbeb00f0..d8b79ff3 100644 --- a/test/testE2E.ts +++ b/test/testE2E.ts @@ -1,13 +1,16 @@ import type {FileInfo} from '@apidevtools/json-schema-ref-parser' import test from 'ava' import {readdirSync} from 'fs' -import {find, merge} from 'lodash' -import {join} from 'path' -import {compile, JSONSchema, Options} from '../src' -import {log, stripExtension} from '../src/utils' -import {getWithCache} from './http' +import {find, merge, zip} from 'lodash-es' +import {basename, dirname, join, resolve} from 'path' +import {compile, JSONSchema, Options} from '../src/index.js' +import {log, stripExtension} from '../src/utils.js' +import {getWithCache} from './http.js' +import {fileURLToPath} from 'url' -const dir = __dirname + '/e2e' +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) +const E2E_TEST_DIR = resolve(__dirname, './e2e') type TestCase = { input: JSONSchema @@ -17,27 +20,35 @@ type TestCase = { options?: Options } -export function hasOnly() { - return readdirSync(dir) - .filter(_ => /^.*\.js$/.test(_)) - .map(_ => require(join(dir, _))) - .some(_ => _.only) +export async function hasOnly(): Promise { + const files = await Promise.all( + readdirSync(E2E_TEST_DIR) + .filter(_ => /^.*\.js$/.test(_)) + .map(_ => join(E2E_TEST_DIR, _)) + .map(_ => import(_)), + ) + return files.some(_ => _.only) } -export function run() { +export async function run() { // [filename, absolute dirname, contents][] - const modules = readdirSync(dir) + const filenames = readdirSync(E2E_TEST_DIR) .filter(_ => !_.includes('.ignore.')) .filter(_ => /^.*\.js$/.test(_)) - .map(_ => [_, require(join(dir, _))]) as [string, TestCase][] + .map(_ => resolve(E2E_TEST_DIR, _)) + const files = await Promise.all(filenames.map(_ => import(_) as Promise)) + const modules = zip( + filenames.map(_ => basename(_)), + files, + ) // exporting `const only=true` will only run that test // exporting `const exclude=true` will not run that test - const only = find(modules, _ => Boolean(_[1].only)) + const only = find(modules, _ => Boolean(_[1]!.only)) if (only) { - runOne(only[1], only[0]) + runOne(only[1]!, only[0]!) } else { - modules.filter(_ => !_[1].exclude).forEach(_ => runOne(_[1], _[0])) + modules.filter(_ => !_[1]!.exclude).forEach(_ => runOne(_[1]!, _[0]!)) } } diff --git a/test/testIdempotence.ts b/test/testIdempotence.ts index 75384c62..9c7ee0ad 100644 --- a/test/testIdempotence.ts +++ b/test/testIdempotence.ts @@ -1,7 +1,7 @@ import test from 'ava' import {JSONSchema4} from 'json-schema' -import {cloneDeep} from 'lodash' -import {compile} from '../src' +import {cloneDeep} from 'lodash-es' +import {compile} from '../src/index.js' export function run() { const SCHEMA: JSONSchema4 = { diff --git a/test/testLinker.ts b/test/testLinker.ts index a704b849..3b27757a 100644 --- a/test/testLinker.ts +++ b/test/testLinker.ts @@ -1,7 +1,7 @@ import test from 'ava' -import {link} from '../src/linker' -import {Parent} from '../src/types/JSONSchema' -import {input} from './e2e/basics' +import {link} from '../src/linker.js' +import {Parent} from '../src/types/JSONSchema.js' +import {input} from './e2e/basics.js' export function run() { test("linker should link to each node's parent schema", t => { diff --git a/test/testNormalizer.ts b/test/testNormalizer.ts index 55fa6ca9..2403125c 100644 --- a/test/testNormalizer.ts +++ b/test/testNormalizer.ts @@ -1,9 +1,9 @@ import test from 'ava' -import {readdirSync} from 'fs' +import {readFileSync, readdirSync} from 'fs' import {join} from 'path' -import {JSONSchema, Options, DEFAULT_OPTIONS} from '../src' -import {link} from '../src/linker' -import {normalize} from '../src/normalizer' +import {JSONSchema, Options, DEFAULT_OPTIONS} from '../src/index.js' +import {link} from '../src/linker.js' +import {normalize} from '../src/normalizer.js' interface JSONTestCase { name: string @@ -12,13 +12,13 @@ interface JSONTestCase { options?: Options } -const normalizerDir = __dirname + '/../../test/normalizer' +const normalizerDir = './test/normalizer' export function run() { readdirSync(normalizerDir) .filter(_ => /^.*\.json$/.test(_)) .map(_ => join(normalizerDir, _)) - .map(_ => [_, require(_)] as [string, JSONTestCase]) + .map(_ => [_, JSON.parse(readFileSync(_, 'utf8'))] as [string, JSONTestCase]) .forEach(([filename, json]: [string, JSONTestCase]) => { test(json.name, t => { const normalized = normalize(link(json.in), new WeakMap(), filename, json.options ?? DEFAULT_OPTIONS) diff --git a/test/testUtils.ts b/test/testUtils.ts index 342de47a..183306c3 100644 --- a/test/testUtils.ts +++ b/test/testUtils.ts @@ -1,7 +1,7 @@ import test from 'ava' -import {link} from '../src/linker' -import {LinkedJSONSchema} from '../src/types/JSONSchema' -import {pathTransform, generateName, isSchemaLike} from '../src/utils' +import {link} from '../src/linker.js' +import {LinkedJSONSchema} from '../src/types/JSONSchema.js' +import {pathTransform, generateName, isSchemaLike} from '../src/utils.js' export function run() { test('pathTransform', t => { diff --git a/tsconfig.cjs.json b/tsconfig.cjs.json new file mode 100644 index 00000000..84c5987d --- /dev/null +++ b/tsconfig.cjs.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "declaration": false, + "esModuleInterop": true, + "lib": [ + "DOM", + "es2015" + ], + "module": "CommonJS", + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "dist-cjs/src", + "preserveConstEnums": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "target": "es2017" + }, + "include": [ + "src" + ] +} diff --git a/tsconfig.json b/tsconfig.esm.json similarity index 76% rename from tsconfig.json rename to tsconfig.esm.json index 79d199fa..c05ae280 100644 --- a/tsconfig.json +++ b/tsconfig.esm.json @@ -4,19 +4,18 @@ "esModuleInterop": true, "lib": [ "DOM", - "es2015", + "es2015" ], - "module": "commonjs", - "moduleResolution": "node", + "module": "Node16", "noFallthroughCasesInSwitch": true, "noUnusedLocals": true, "noUnusedParameters": true, - "outDir": "dist", + "outDir": "dist-esm", "preserveConstEnums": true, "skipLibCheck": true, "sourceMap": true, "strict": true, - "target": "es6" + "target": "es2017" }, "exclude": [ "example",