From a24a361d9d2ca2a89d47417d9fb6fe9fb184e249 Mon Sep 17 00:00:00 2001 From: Mark Potter Date: Wed, 23 Nov 2022 12:05:45 +0000 Subject: [PATCH 01/25] create json template --- package-lock.json | 45 ++++++++++++++++++++++ package.json | 1 + template/[entryPoint].json | 14 +++++++ template/attributes/heading.json | 8 ++++ template/examples/content.json | 3 ++ template/paths/information.json | 10 +++++ template/responses/informationSuccess.json | 10 +++++ template/schemas/information.json | 16 ++++++++ 8 files changed, 107 insertions(+) create mode 100644 template/[entryPoint].json create mode 100644 template/attributes/heading.json create mode 100644 template/examples/content.json create mode 100644 template/paths/information.json create mode 100644 template/responses/informationSuccess.json create mode 100644 template/schemas/information.json diff --git a/package-lock.json b/package-lock.json index ad9db91..a878f9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { + "json-to-pretty-yaml": "^1.2.2", "prompts": "^2.4.2" }, "bin": { @@ -4493,6 +4494,18 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-to-pretty-yaml": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz", + "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==", + "dependencies": { + "remedial": "^1.0.7", + "remove-trailing-spaces": "^1.0.6" + }, + "engines": { + "node": ">= 0.2.0" + } + }, "node_modules/json5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", @@ -5458,6 +5471,19 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/remedial": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", + "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==", + "engines": { + "node": "*" + } + }, + "node_modules/remove-trailing-spaces": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz", + "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -9755,6 +9781,15 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "json-to-pretty-yaml": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz", + "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==", + "requires": { + "remedial": "^1.0.7", + "remove-trailing-spaces": "^1.0.6" + } + }, "json5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", @@ -10430,6 +10465,16 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "remedial": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", + "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==" + }, + "remove-trailing-spaces": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz", + "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==" + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", diff --git a/package.json b/package.json index dbd5f73..ea5f86b 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "typescript": "^4.9.3" }, "dependencies": { + "json-to-pretty-yaml": "^1.2.2", "prompts": "^2.4.2" }, "lint-staged": { diff --git a/template/[entryPoint].json b/template/[entryPoint].json new file mode 100644 index 0000000..72744e9 --- /dev/null +++ b/template/[entryPoint].json @@ -0,0 +1,14 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "Welcome to PATIOS", + "description": "Manage large Open API specifications and automatically generate TypeScript definitions", + "version": "1.0" + }, + "servers": [{ "url": "https://github.com/theappbusiness/patios/" }], + "paths": { + "/v1/information": { + "$ref": "./paths/information.json" + } + } +} diff --git a/template/attributes/heading.json b/template/attributes/heading.json new file mode 100644 index 0000000..0320f5c --- /dev/null +++ b/template/attributes/heading.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "properties": { + "heading": { + "type": "string" + } + } +} diff --git a/template/examples/content.json b/template/examples/content.json new file mode 100644 index 0000000..29f3ac6 --- /dev/null +++ b/template/examples/content.json @@ -0,0 +1,3 @@ +{ + "heading": "Welcome to PATIOS" +} diff --git a/template/paths/information.json b/template/paths/information.json new file mode 100644 index 0000000..2056fe8 --- /dev/null +++ b/template/paths/information.json @@ -0,0 +1,10 @@ +{ + "get": { + "description": "An example path providing information about PATIOS", + "responses": { + "200": { + "$ref": "../responses/informationSuccess.json" + } + } + } +} diff --git a/template/responses/informationSuccess.json b/template/responses/informationSuccess.json new file mode 100644 index 0000000..d606618 --- /dev/null +++ b/template/responses/informationSuccess.json @@ -0,0 +1,10 @@ +{ + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "../schemas/information.json" + } + } + } +} diff --git a/template/schemas/information.json b/template/schemas/information.json new file mode 100644 index 0000000..37c8864 --- /dev/null +++ b/template/schemas/information.json @@ -0,0 +1,16 @@ +{ + "type": "object", + "properties": { + "content": { + "type": "object", + "allOf": [ + { + "$ref": "../attributes/heading.json" + } + ], + "example": { + "$ref": "../examples/content.json" + } + } + } +} From 9d56f707d7060db17d9f1ca9d9478d06b3771fd5 Mon Sep 17 00:00:00 2001 From: Mark Potter Date: Wed, 23 Nov 2022 17:30:39 +0000 Subject: [PATCH 02/25] write json and yaml to bin postbuild --- json-to-pretty-yaml.d.ts | 3 ++ package-lock.json | 14 ++++-- package.json | 7 +-- src/write-yaml-template.ts | 45 +++++++++++++++++++ .../json}/[entryPoint].json | 0 .../json}/attributes/heading.json | 0 .../json}/examples/content.json | 0 .../json}/paths/information.json | 0 .../json}/responses/informationSuccess.json | 0 .../json}/schemas/information.json | 0 10 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 json-to-pretty-yaml.d.ts create mode 100644 src/write-yaml-template.ts rename {template => templates/json}/[entryPoint].json (100%) rename {template => templates/json}/attributes/heading.json (100%) rename {template => templates/json}/examples/content.json (100%) rename {template => templates/json}/paths/information.json (100%) rename {template => templates/json}/responses/informationSuccess.json (100%) rename {template => templates/json}/schemas/information.json (100%) diff --git a/json-to-pretty-yaml.d.ts b/json-to-pretty-yaml.d.ts new file mode 100644 index 0000000..83c702d --- /dev/null +++ b/json-to-pretty-yaml.d.ts @@ -0,0 +1,3 @@ +declare module 'json-to-pretty-yaml' { + function stringify(json: string): string +} diff --git a/package-lock.json b/package-lock.json index a878f9c..01b0e33 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "json-to-pretty-yaml": "^1.2.2", "prompts": "^2.4.2" }, "bin": { @@ -29,6 +28,7 @@ "eslint-plugin-prettier": "^4.2.1", "husky": "^8.0.2", "jest": "^29.3.1", + "json-to-pretty-yaml": "^1.2.2", "lint-staged": "^13.0.3", "node-dev": "^7.4.3", "prettier": "^2.7.1", @@ -4498,6 +4498,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz", "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==", + "dev": true, "dependencies": { "remedial": "^1.0.7", "remove-trailing-spaces": "^1.0.6" @@ -5475,6 +5476,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==", + "dev": true, "engines": { "node": "*" } @@ -5482,7 +5484,8 @@ "node_modules/remove-trailing-spaces": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz", - "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==" + "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==", + "dev": true }, "node_modules/require-directory": { "version": "2.1.1", @@ -9785,6 +9788,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz", "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==", + "dev": true, "requires": { "remedial": "^1.0.7", "remove-trailing-spaces": "^1.0.6" @@ -10468,12 +10472,14 @@ "remedial": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", - "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==" + "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==", + "dev": true }, "remove-trailing-spaces": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz", - "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==" + "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==", + "dev": true }, "require-directory": { "version": "2.1.1", diff --git a/package.json b/package.json index ea5f86b..f7cf429 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,9 @@ "main": "src/index.ts", "scripts": { "test": "jest", - "dev": "node-dev src/index.ts", + "dev": "node-dev src/write-yaml-template.ts", "build": "tsc", + "postbuild": "node bin/write-yaml-template.js", "format": "prettier -w .", "lint": "eslint --ignore-path .prettierignore \"**/*.ts\"", "lint:fix": "eslint --fix --ignore-path .prettierignore \"**/*.ts\"", @@ -41,6 +42,7 @@ "eslint-plugin-prettier": "^4.2.1", "husky": "^8.0.2", "jest": "^29.3.1", + "json-to-pretty-yaml": "^1.2.2", "lint-staged": "^13.0.3", "node-dev": "^7.4.3", "prettier": "^2.7.1", @@ -48,12 +50,11 @@ "typescript": "^4.9.3" }, "dependencies": { - "json-to-pretty-yaml": "^1.2.2", "prompts": "^2.4.2" }, "lint-staged": { "*.{js,ts}": [ - "npm run typecheck", + "npm run typecheck -- --lib ESNext", "npm run format", "npm run lint:fix" ] diff --git a/src/write-yaml-template.ts b/src/write-yaml-template.ts new file mode 100644 index 0000000..a387c3a --- /dev/null +++ b/src/write-yaml-template.ts @@ -0,0 +1,45 @@ +import * as fs from 'fs' +import * as path from 'path' +import { stringify } from 'json-to-pretty-yaml' + +const walk = (dir: string, prevResults?: string[]): string[] => { + const list = fs.readdirSync(dir) + const results = prevResults || [] + list.forEach((file) => { + file = path.resolve(dir, file) + const stat = fs.statSync(file) + if (stat && stat.isDirectory()) { + walk(file, results) + } else { + results.push(file) + } + }) + return results +} + +;((): void => { + fs.mkdirSync('./bin/templates') + const jsonPaths = walk('./templates/json') + jsonPaths.forEach((jsonPath) => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const json = require(jsonPath) + const data = stringify(json) + const binJsonTemplatesPath = jsonPath.replace( + '/templates/', + '/bin/templates/', + ) + const binYamlTemplatesPath = binJsonTemplatesPath.replaceAll('json', 'yaml') + const jsonDirname = path.dirname(binJsonTemplatesPath) + const yamlDirname = path.dirname(binYamlTemplatesPath) + const jsonStat = fs.statSync(jsonDirname, { throwIfNoEntry: false }) + const yamlStat = fs.statSync(jsonDirname, { throwIfNoEntry: false }) + if (!jsonStat?.isDirectory()) { + fs.mkdirSync(jsonDirname) + } + if (!yamlStat?.isDirectory()) { + fs.mkdirSync(yamlDirname) + } + fs.writeFileSync(binJsonTemplatesPath, data) + fs.writeFileSync(binYamlTemplatesPath, data) + }) +})() diff --git a/template/[entryPoint].json b/templates/json/[entryPoint].json similarity index 100% rename from template/[entryPoint].json rename to templates/json/[entryPoint].json diff --git a/template/attributes/heading.json b/templates/json/attributes/heading.json similarity index 100% rename from template/attributes/heading.json rename to templates/json/attributes/heading.json diff --git a/template/examples/content.json b/templates/json/examples/content.json similarity index 100% rename from template/examples/content.json rename to templates/json/examples/content.json diff --git a/template/paths/information.json b/templates/json/paths/information.json similarity index 100% rename from template/paths/information.json rename to templates/json/paths/information.json diff --git a/template/responses/informationSuccess.json b/templates/json/responses/informationSuccess.json similarity index 100% rename from template/responses/informationSuccess.json rename to templates/json/responses/informationSuccess.json diff --git a/template/schemas/information.json b/templates/json/schemas/information.json similarity index 100% rename from template/schemas/information.json rename to templates/json/schemas/information.json From cc8be87155b87749979f45b35c763a7a5a6aefc0 Mon Sep 17 00:00:00 2001 From: Mark Potter <35689158+Si3rr4wow@users.noreply.github.com> Date: Thu, 24 Nov 2022 16:49:44 +0000 Subject: [PATCH 03/25] Update src/write-yaml-template.ts Co-authored-by: Rob Morgan <46483646+robmorgan-tab@users.noreply.github.com> --- src/write-yaml-template.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/write-yaml-template.ts b/src/write-yaml-template.ts index a387c3a..0a5f92e 100644 --- a/src/write-yaml-template.ts +++ b/src/write-yaml-template.ts @@ -32,7 +32,7 @@ const walk = (dir: string, prevResults?: string[]): string[] => { const jsonDirname = path.dirname(binJsonTemplatesPath) const yamlDirname = path.dirname(binYamlTemplatesPath) const jsonStat = fs.statSync(jsonDirname, { throwIfNoEntry: false }) - const yamlStat = fs.statSync(jsonDirname, { throwIfNoEntry: false }) + const yamlStat = fs.statSync(yamlDirname, { throwIfNoEntry: false }) if (!jsonStat?.isDirectory()) { fs.mkdirSync(jsonDirname) } From 64186f3cbaeef26f6ee927aa77fc7ca60329c34a Mon Sep 17 00:00:00 2001 From: Mark Potter <35689158+Si3rr4wow@users.noreply.github.com> Date: Thu, 24 Nov 2022 16:50:24 +0000 Subject: [PATCH 04/25] Update src/write-yaml-template.ts Co-authored-by: Rob Morgan <46483646+robmorgan-tab@users.noreply.github.com> --- src/write-yaml-template.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/write-yaml-template.ts b/src/write-yaml-template.ts index 0a5f92e..0029a62 100644 --- a/src/write-yaml-template.ts +++ b/src/write-yaml-template.ts @@ -22,7 +22,7 @@ const walk = (dir: string, prevResults?: string[]): string[] => { const jsonPaths = walk('./templates/json') jsonPaths.forEach((jsonPath) => { // eslint-disable-next-line @typescript-eslint/no-var-requires - const json = require(jsonPath) + const json = fs.readFileSync(jsonPath) const data = stringify(json) const binJsonTemplatesPath = jsonPath.replace( '/templates/', From 7c9d32a53741dac323c3d2cdf4e5a2afa03ffbb8 Mon Sep 17 00:00:00 2001 From: Mark Potter Date: Fri, 25 Nov 2022 09:41:36 +0000 Subject: [PATCH 05/25] fix engines and declaration. neater build --- package.json | 5 ++--- src/write-yaml-template.ts | 6 +++++- tsconfig.json | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 4913a1c..4a049d7 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,12 @@ "description": "Manage large Open API specifications and automatically generate TypeScript definitions from them.", "main": "src/index.ts", "engines": { - "node": ">18.12.1" + "node": ">=18.12.1" }, "scripts": { "test": "jest", "dev": "node-dev src/write-yaml-template.ts", - "build": "tsc", - "postbuild": "node bin/write-yaml-template.js", + "build": "tsc && node bin/write-yaml-template.js", "format": "prettier -w .", "lint": "eslint --ignore-path .prettierignore \"**/*.ts\"", "lint:fix": "eslint --fix --ignore-path .prettierignore \"**/*.ts\"", diff --git a/src/write-yaml-template.ts b/src/write-yaml-template.ts index a387c3a..7f56ec7 100644 --- a/src/write-yaml-template.ts +++ b/src/write-yaml-template.ts @@ -8,7 +8,7 @@ const walk = (dir: string, prevResults?: string[]): string[] => { list.forEach((file) => { file = path.resolve(dir, file) const stat = fs.statSync(file) - if (stat && stat.isDirectory()) { + if (stat.isDirectory()) { walk(file, results) } else { results.push(file) @@ -18,6 +18,10 @@ const walk = (dir: string, prevResults?: string[]): string[] => { } ;((): void => { + const binTemplatesStat = fs.statSync('./bin/templates') + if (binTemplatesStat.isDirectory()) { + fs.rmSync('./bin/templates', { recursive: true }) + } fs.mkdirSync('./bin/templates') const jsonPaths = walk('./templates/json') jsonPaths.forEach((jsonPath) => { diff --git a/tsconfig.json b/tsconfig.json index 67a0690..db4cff0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,5 +10,6 @@ "allowSyntheticDefaultImports": true }, "include": ["src"], - "exclude": ["node_modules", "*.test.*", "bin"] + "exclude": ["node_modules", "src/*.test.*", "src/test-utils", "bin"], + "files": ["json-to-pretty-yaml.d.ts"] } From a710e3c5373a661984602ef179ad116bd02d8dec Mon Sep 17 00:00:00 2001 From: Mark Potter Date: Mon, 28 Nov 2022 14:04:30 +0000 Subject: [PATCH 06/25] it's alive! --- package-lock.json | 265 +----------------- package.json | 4 +- src/wizard.ts | 15 +- ...yaml-template.ts => write-bin-template.ts} | 6 +- 4 files changed, 21 insertions(+), 269 deletions(-) rename src/{write-yaml-template.ts => write-bin-template.ts} (92%) diff --git a/package-lock.json b/package-lock.json index 01b0e33..83e021b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,9 @@ "prettier": "^2.7.1", "ts-jest": "^29.0.3", "typescript": "^4.9.3" + }, + "engines": { + "node": ">=18.12.1" } }, "node_modules/@ampproject/remapping": { @@ -620,20 +623,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@eslint/eslintrc": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", @@ -1174,38 +1163,6 @@ "@sinonjs/commons": "^1.7.0" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/@types/babel__core": { "version": "7.1.20", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", @@ -1619,17 +1576,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -1711,14 +1657,6 @@ "node": ">= 8" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -2206,14 +2144,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2306,17 +2236,6 @@ "node": ">=8" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/diff-sequences": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", @@ -6027,51 +5946,6 @@ "node": ">=10" } }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, "node_modules/tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -6231,14 +6105,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/v8-to-istanbul": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", @@ -6414,17 +6280,6 @@ "node": ">=12" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -6881,17 +6736,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - } - }, "@eslint/eslintrc": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", @@ -7327,38 +7171,6 @@ "@sinonjs/commons": "^1.7.0" } }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true, - "optional": true, - "peer": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "optional": true, - "peer": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "optional": true, - "peer": true - }, - "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true, - "optional": true, - "peer": true - }, "@types/babel__core": { "version": "7.1.20", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", @@ -7663,14 +7475,6 @@ "dev": true, "requires": {} }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "optional": true, - "peer": true - }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -7727,14 +7531,6 @@ "picomatch": "^2.0.4" } }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "optional": true, - "peer": true - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -8089,14 +7885,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "optional": true, - "peer": true - }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -8163,14 +7951,6 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "optional": true, - "peer": true - }, "diff-sequences": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", @@ -10859,29 +10639,6 @@ } } }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, "tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -10990,14 +10747,6 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "optional": true, - "peer": true - }, "v8-to-istanbul": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", @@ -11136,14 +10885,6 @@ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "optional": true, - "peer": true - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 4a049d7..86ce7ba 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ }, "scripts": { "test": "jest", - "dev": "node-dev src/write-yaml-template.ts", - "build": "tsc && node bin/write-yaml-template.js", + "dev": "node-dev src/write-bin-template.ts", + "build": "tsc && node bin/write-bin-template.js", "format": "prettier -w .", "lint": "eslint --ignore-path .prettierignore \"**/*.ts\"", "lint:fix": "eslint --fix --ignore-path .prettierignore \"**/*.ts\"", diff --git a/src/wizard.ts b/src/wizard.ts index d036d42..cd7be70 100644 --- a/src/wizard.ts +++ b/src/wizard.ts @@ -67,14 +67,23 @@ const getProjectOptions = async ( const makeBoilerplate = ( processDirectory: string, - { entryPoint, projectName }: ProjectOptions, + { documentSyntax, entryPoint, projectName }: ProjectOptions, ): void => { let writeDirectory = '.' if (processDirectory !== projectName) { + // TODO: add a nice error message for if this dir already exists fs.mkdirSync(projectName) - writeDirectory += `/${projectName}` + writeDirectory = path.join(writeDirectory, projectName) } - fs.writeFileSync(path.join(writeDirectory, entryPoint), 'Hello Spec!') + fs.cpSync( + path.join(__dirname, './templates/', documentSyntax), + writeDirectory, + { recursive: true }, + ) + fs.renameSync( + path.join(writeDirectory, `[entryPoint].${documentSyntax}`), + path.join(writeDirectory, entryPoint), + ) } export const init = async (): Promise => { diff --git a/src/write-yaml-template.ts b/src/write-bin-template.ts similarity index 92% rename from src/write-yaml-template.ts rename to src/write-bin-template.ts index 7f56ec7..322f685 100644 --- a/src/write-yaml-template.ts +++ b/src/write-bin-template.ts @@ -18,8 +18,10 @@ const walk = (dir: string, prevResults?: string[]): string[] => { } ;((): void => { - const binTemplatesStat = fs.statSync('./bin/templates') - if (binTemplatesStat.isDirectory()) { + const binTemplatesStat = fs.statSync('./bin/templates', { + throwIfNoEntry: false, + }) + if (binTemplatesStat) { fs.rmSync('./bin/templates', { recursive: true }) } fs.mkdirSync('./bin/templates') From 35ea45f238cd0fa322224cd998b0c7ba7976c6aa Mon Sep 17 00:00:00 2001 From: Mark Potter Date: Mon, 28 Nov 2022 14:17:35 +0000 Subject: [PATCH 07/25] deconflictify ts and eslint --- package.json | 2 +- src/write-bin-template.ts | 3 +-- tsconfig.build.json | 4 ++++ tsconfig.json | 5 ++--- json-to-pretty-yaml.d.ts => types/json-to-pretty-yaml.d.ts | 0 5 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 tsconfig.build.json rename json-to-pretty-yaml.d.ts => types/json-to-pretty-yaml.d.ts (100%) diff --git a/package.json b/package.json index 8427d78..9a9f5bf 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "test": "jest", "dev": "node-dev src/write-bin-template.ts", - "build": "tsc && node bin/write-bin-template.js", + "build": "tsc --project tsconfig.build.json && node bin/write-bin-template.js", "format": "prettier -w .", "lint": "eslint --ignore-path .prettierignore \"**/*.ts\"", "lint:fix": "eslint --fix --ignore-path .prettierignore \"**/*.ts\"", diff --git a/src/write-bin-template.ts b/src/write-bin-template.ts index 0930e2f..ba06319 100644 --- a/src/write-bin-template.ts +++ b/src/write-bin-template.ts @@ -27,8 +27,7 @@ const walk = (dir: string, prevResults?: string[]): string[] => { fs.mkdirSync('./bin/templates') const jsonPaths = walk('./templates/json') jsonPaths.forEach((jsonPath) => { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const json = fs.readFileSync(jsonPath) + const json = fs.readFileSync(jsonPath).toString() const data = stringify(json) const binJsonTemplatesPath = jsonPath.replace( '/templates/', diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..fe26423 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "src/*.test.*", "src/test-utils", "bin"] +} diff --git a/tsconfig.json b/tsconfig.json index db4cff0..2aa6d28 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,6 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true }, - "include": ["src"], - "exclude": ["node_modules", "src/*.test.*", "src/test-utils", "bin"], - "files": ["json-to-pretty-yaml.d.ts"] + "include": ["src", "types"], + "exclude": ["node_modules", "bin"], } diff --git a/json-to-pretty-yaml.d.ts b/types/json-to-pretty-yaml.d.ts similarity index 100% rename from json-to-pretty-yaml.d.ts rename to types/json-to-pretty-yaml.d.ts From 73b77d48b4d7f81c4eff7a2ef85daec64364672b Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Mon, 28 Nov 2022 14:39:26 +0000 Subject: [PATCH 08/25] Fix YAML content conversion --- src/write-bin-template.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/write-bin-template.ts b/src/write-bin-template.ts index ba06319..0876240 100644 --- a/src/write-bin-template.ts +++ b/src/write-bin-template.ts @@ -28,7 +28,6 @@ const walk = (dir: string, prevResults?: string[]): string[] => { const jsonPaths = walk('./templates/json') jsonPaths.forEach((jsonPath) => { const json = fs.readFileSync(jsonPath).toString() - const data = stringify(json) const binJsonTemplatesPath = jsonPath.replace( '/templates/', '/bin/templates/', @@ -44,7 +43,7 @@ const walk = (dir: string, prevResults?: string[]): string[] => { if (!yamlStat?.isDirectory()) { fs.mkdirSync(yamlDirname) } - fs.writeFileSync(binJsonTemplatesPath, data) - fs.writeFileSync(binYamlTemplatesPath, data) + fs.writeFileSync(binJsonTemplatesPath, json) + fs.writeFileSync(binYamlTemplatesPath, stringify(JSON.parse(json))) }) })() From 53628243f5d8475020d48251d66ea9f8c7b7afb6 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Mon, 28 Nov 2022 15:57:33 +0000 Subject: [PATCH 09/25] Remote TS definitions for old prompt library --- package-lock.json | 33 --------------------------------- package.json | 1 - 2 files changed, 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index 83e021b..01744a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ }, "devDependencies": { "@types/jest": "^29.2.3", - "@types/prompt": "^1.1.4", "@types/prompts": "^2.4.1", "@typescript-eslint/eslint-plugin": "^5.43.0", "@typescript-eslint/parser": "^5.43.0", @@ -1271,16 +1270,6 @@ "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", "dev": true }, - "node_modules/@types/prompt": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/prompt/-/prompt-1.1.4.tgz", - "integrity": "sha512-FLMcf+ol+eUJALeIYWLjQl0hYw86G0PIg7D5+4jJHwr/wKI8p3R0u+oKLbyRkzCxb7e0pHixyCj7UgSv7I/TJQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/revalidator": "*" - } - }, "node_modules/@types/prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.1.tgz", @@ -1290,12 +1279,6 @@ "@types/node": "*" } }, - "node_modules/@types/revalidator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@types/revalidator/-/revalidator-0.3.8.tgz", - "integrity": "sha512-q6KSi3PklLGQ0CesZ/XuLwly4DXXlnJuucYOG9lrBqrP8rKiuPZThav2h2+pFjaheNpnT0qKK3i304QWIePeJw==", - "dev": true - }, "node_modules/@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", @@ -7279,16 +7262,6 @@ "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", "dev": true }, - "@types/prompt": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/prompt/-/prompt-1.1.4.tgz", - "integrity": "sha512-FLMcf+ol+eUJALeIYWLjQl0hYw86G0PIg7D5+4jJHwr/wKI8p3R0u+oKLbyRkzCxb7e0pHixyCj7UgSv7I/TJQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/revalidator": "*" - } - }, "@types/prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.1.tgz", @@ -7298,12 +7271,6 @@ "@types/node": "*" } }, - "@types/revalidator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@types/revalidator/-/revalidator-0.3.8.tgz", - "integrity": "sha512-q6KSi3PklLGQ0CesZ/XuLwly4DXXlnJuucYOG9lrBqrP8rKiuPZThav2h2+pFjaheNpnT0qKK3i304QWIePeJw==", - "dev": true - }, "@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", diff --git a/package.json b/package.json index 9a9f5bf..e514986 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "homepage": "https://github.com/theappbusiness/patios#readme", "devDependencies": { "@types/jest": "^29.2.3", - "@types/prompt": "^1.1.4", "@types/prompts": "^2.4.1", "@typescript-eslint/eslint-plugin": "^5.43.0", "@typescript-eslint/parser": "^5.43.0", From 611ef73adc454dc036ad2be8fe7d78318c4f281a Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Mon, 28 Nov 2022 16:32:21 +0000 Subject: [PATCH 10/25] Make eslint ignore bin files --- .eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 188a0cb..08b2cb5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -68,7 +68,7 @@ module.exports = { node: true, }, extends: jsExtends, - ignorePatterns: ['**/node_modules'], + ignorePatterns: ['**/node_modules', 'bin'], parserOptions: jsParserOptions, plugins: jsPlugins, root: true, From 4e9072d88b33b77f156dec6f2072ca2f118267ec Mon Sep 17 00:00:00 2001 From: Mark Potter Date: Mon, 28 Nov 2022 17:15:20 +0000 Subject: [PATCH 11/25] ditch post build, link yaml correctly --- package.json | 1 - src/write-bin-template.ts | 73 +++++++++++++------ templates/json/[entryPoint].json | 2 +- templates/json/paths/information.json | 2 +- .../json/responses/informationSuccess.json | 2 +- templates/json/schemas/information.json | 4 +- 6 files changed, 57 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 9a9f5bf..ee7b962 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "lint:fix": "eslint --fix --ignore-path .prettierignore \"**/*.ts\"", "lint:check-rule-overlap": "npx eslint-config-prettier src/index.ts", "typecheck": "tsc --noEmit", - "postinstall": "npm run build", "prepare": "husky install" }, "bin": { diff --git a/src/write-bin-template.ts b/src/write-bin-template.ts index 0876240..824baee 100644 --- a/src/write-bin-template.ts +++ b/src/write-bin-template.ts @@ -17,7 +17,7 @@ const walk = (dir: string, prevResults?: string[]): string[] => { return results } -;((): void => { +const makeBinTemplateDirectory = (): void => { const binTemplatesStat = fs.statSync('./bin/templates', { throwIfNoEntry: false, }) @@ -25,25 +25,56 @@ const walk = (dir: string, prevResults?: string[]): string[] => { fs.rmSync('./bin/templates', { recursive: true }) } fs.mkdirSync('./bin/templates') - const jsonPaths = walk('./templates/json') - jsonPaths.forEach((jsonPath) => { - const json = fs.readFileSync(jsonPath).toString() - const binJsonTemplatesPath = jsonPath.replace( - '/templates/', - '/bin/templates/', - ) - const binYamlTemplatesPath = binJsonTemplatesPath.replaceAll('json', 'yaml') - const jsonDirname = path.dirname(binJsonTemplatesPath) - const yamlDirname = path.dirname(binYamlTemplatesPath) - const jsonStat = fs.statSync(jsonDirname, { throwIfNoEntry: false }) - const yamlStat = fs.statSync(yamlDirname, { throwIfNoEntry: false }) - if (!jsonStat?.isDirectory()) { - fs.mkdirSync(jsonDirname) - } - if (!yamlStat?.isDirectory()) { - fs.mkdirSync(yamlDirname) - } - fs.writeFileSync(binJsonTemplatesPath, json) - fs.writeFileSync(binYamlTemplatesPath, stringify(JSON.parse(json))) +} + +const getBinTargetPaths = ( + jsonPath: string, +): { jsonBinPath: string; yamlBinPath: string } => { + const jsonBinPath = jsonPath.replace('/templates/', '/bin/templates/') + const yamlBinPath = jsonBinPath.replaceAll('json', 'yaml') + return { + jsonBinPath, + yamlBinPath, + } +} + +const makeBinTemplateSubdirectory = (jsonPath: string): void => { + const { jsonBinPath, yamlBinPath } = getBinTargetPaths(jsonPath) + const jsonDirname = path.dirname(jsonBinPath) + const yamlDirname = path.dirname(yamlBinPath) + const jsonStat = fs.statSync(jsonDirname, { throwIfNoEntry: false }) + const yamlStat = fs.statSync(yamlDirname, { throwIfNoEntry: false }) + if (!jsonStat?.isDirectory()) { + fs.mkdirSync(jsonDirname) + } + if (!yamlStat?.isDirectory()) { + fs.mkdirSync(yamlDirname) + } +} + +const getTemplateStrings = ( + jsonPath: string, +): { jsonStr: string; yamlStr: string } => { + const rawTemplate = fs.readFileSync(jsonPath).toString() + const jsonStr = rawTemplate.replaceAll('$EXT', 'json') + const yamlStr = stringify(JSON.parse(rawTemplate.replaceAll('$EXT', 'yaml'))) + return { + jsonStr, + yamlStr, + } +} + +const writeTemplateFileToBin = (jsonPath: string): void => { + makeBinTemplateSubdirectory(jsonPath) + const { jsonStr, yamlStr } = getTemplateStrings(jsonPath) + const { jsonBinPath, yamlBinPath } = getBinTargetPaths(jsonPath) + fs.writeFileSync(jsonBinPath, jsonStr) + fs.writeFileSync(yamlBinPath, yamlStr) +} + +;((): void => { + makeBinTemplateDirectory() + walk('./templates/json').forEach((jsonPath) => { + writeTemplateFileToBin(jsonPath) }) })() diff --git a/templates/json/[entryPoint].json b/templates/json/[entryPoint].json index 72744e9..7bf3757 100644 --- a/templates/json/[entryPoint].json +++ b/templates/json/[entryPoint].json @@ -8,7 +8,7 @@ "servers": [{ "url": "https://github.com/theappbusiness/patios/" }], "paths": { "/v1/information": { - "$ref": "./paths/information.json" + "$ref": "./paths/information.$EXT" } } } diff --git a/templates/json/paths/information.json b/templates/json/paths/information.json index 2056fe8..87dd6e0 100644 --- a/templates/json/paths/information.json +++ b/templates/json/paths/information.json @@ -3,7 +3,7 @@ "description": "An example path providing information about PATIOS", "responses": { "200": { - "$ref": "../responses/informationSuccess.json" + "$ref": "../responses/informationSuccess.$EXT" } } } diff --git a/templates/json/responses/informationSuccess.json b/templates/json/responses/informationSuccess.json index d606618..64b1ab3 100644 --- a/templates/json/responses/informationSuccess.json +++ b/templates/json/responses/informationSuccess.json @@ -3,7 +3,7 @@ "content": { "application/json": { "schema": { - "$ref": "../schemas/information.json" + "$ref": "../schemas/information.$EXT" } } } diff --git a/templates/json/schemas/information.json b/templates/json/schemas/information.json index 37c8864..e127860 100644 --- a/templates/json/schemas/information.json +++ b/templates/json/schemas/information.json @@ -5,11 +5,11 @@ "type": "object", "allOf": [ { - "$ref": "../attributes/heading.json" + "$ref": "../attributes/heading.$EXT" } ], "example": { - "$ref": "../examples/content.json" + "$ref": "../examples/content.$EXT" } } } From 687877e2cb6146b55d1899967e9eaef9c6942e31 Mon Sep 17 00:00:00 2001 From: Mark Potter Date: Tue, 29 Nov 2022 10:59:14 +0000 Subject: [PATCH 12/25] validate templates pre push --- .husky/pre-push | 2 + package-lock.json | 430 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 + 3 files changed, 433 insertions(+), 1 deletion(-) diff --git a/.husky/pre-push b/.husky/pre-push index d1096ab..cd1e115 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -2,3 +2,5 @@ . "$(dirname "$0")/_/husky.sh" npm run test +npm run build +npm run validate-templates \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 01744a7..31136db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,6 @@ "": { "name": "@kinandcarta/patios", "version": "0.0.1", - "hasInstallScript": true, "license": "MIT", "dependencies": { "prompts": "^2.4.2" @@ -31,6 +30,7 @@ "lint-staged": "^13.0.3", "node-dev": "^7.4.3", "prettier": "^2.7.1", + "swagger-cli": "^4.0.4", "ts-jest": "^29.0.3", "typescript": "^4.9.3" }, @@ -51,6 +51,170 @@ "node": ">=6.0.0" } }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz", + "integrity": "sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg==", + "dev": true, + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.13.1" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-cli": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-cli/-/swagger-cli-4.0.4.tgz", + "integrity": "sha512-hdDT3B6GLVovCsRZYDi3+wMcB1HfetTU20l2DC8zD3iFRNMC6QNAZG5fo/6PYeHWBEv7ri4MvnlKodhNB0nt7g==", + "dev": true, + "dependencies": { + "@apidevtools/swagger-parser": "^10.0.1", + "chalk": "^4.1.0", + "js-yaml": "^3.14.0", + "yargs": "^15.4.1" + }, + "bin": { + "swagger-cli": "bin/swagger-cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-cli/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/@apidevtools/swagger-cli/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@apidevtools/swagger-cli/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/@apidevtools/swagger-cli/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@apidevtools/swagger-cli/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "dev": true + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.1.0.tgz", + "integrity": "sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw==", + "dev": true, + "dependencies": { + "@apidevtools/json-schema-ref-parser": "9.0.6", + "@apidevtools/openapi-schemas": "^2.1.0", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "ajv": "^8.6.3", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -1103,6 +1267,12 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1891,6 +2061,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2173,6 +2349,15 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -5030,6 +5215,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openapi-types": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.0.2.tgz", + "integrity": "sha512-GuTo7FyZjOIWVhIhQSWJVaws6A82sWIGyQogxxYBYKZ0NBdyP2CYSIgOwFfSB+UVoPExk/YzFpyYitHS8KVZtA==", + "dev": true, + "peer": true + }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -5398,6 +5590,21 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -5550,6 +5757,12 @@ "semver": "bin/semver.js" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5818,6 +6031,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger-cli": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/swagger-cli/-/swagger-cli-4.0.4.tgz", + "integrity": "sha512-Cp8YYuLny3RJFQ4CvOBTaqmOOgYsem52dPx1xM5S4EUWFblIh2Q8atppMZvXKUr1e9xH5RwipYpmdUzdPcxWcA==", + "dev": true, + "dependencies": { + "@apidevtools/swagger-cli": "4.0.4" + }, + "bin": { + "swagger-cli": "swagger-cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -6158,6 +6386,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -6287,6 +6521,142 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, + "@apidevtools/json-schema-ref-parser": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz", + "integrity": "sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg==", + "dev": true, + "requires": { + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.13.1" + } + }, + "@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "dev": true + }, + "@apidevtools/swagger-cli": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-cli/-/swagger-cli-4.0.4.tgz", + "integrity": "sha512-hdDT3B6GLVovCsRZYDi3+wMcB1HfetTU20l2DC8zD3iFRNMC6QNAZG5fo/6PYeHWBEv7ri4MvnlKodhNB0nt7g==", + "dev": true, + "requires": { + "@apidevtools/swagger-parser": "^10.0.1", + "chalk": "^4.1.0", + "js-yaml": "^3.14.0", + "yargs": "^15.4.1" + }, + "dependencies": { + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "dev": true + }, + "@apidevtools/swagger-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.1.0.tgz", + "integrity": "sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw==", + "dev": true, + "requires": { + "@apidevtools/json-schema-ref-parser": "9.0.6", + "@apidevtools/openapi-schemas": "^2.1.0", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "ajv": "^8.6.3", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.1" + }, + "dependencies": { + "ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, "@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -7104,6 +7474,12 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7685,6 +8061,12 @@ "get-intrinsic": "^1.0.2" } }, + "call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -7884,6 +8266,12 @@ "ms": "2.1.2" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true + }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -9990,6 +10378,13 @@ "mimic-fn": "^2.1.0" } }, + "openapi-types": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.0.2.tgz", + "integrity": "sha512-GuTo7FyZjOIWVhIhQSWJVaws6A82sWIGyQogxxYBYKZ0NBdyP2CYSIgOwFfSB+UVoPExk/YzFpyYitHS8KVZtA==", + "dev": true, + "peer": true + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -10234,6 +10629,18 @@ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -10340,6 +10747,12 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -10535,6 +10948,15 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "swagger-cli": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/swagger-cli/-/swagger-cli-4.0.4.tgz", + "integrity": "sha512-Cp8YYuLny3RJFQ4CvOBTaqmOOgYsem52dPx1xM5S4EUWFblIh2Q8atppMZvXKUr1e9xH5RwipYpmdUzdPcxWcA==", + "dev": true, + "requires": { + "@apidevtools/swagger-cli": "4.0.4" + } + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -10774,6 +11196,12 @@ "is-symbol": "^1.0.3" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", diff --git a/package.json b/package.json index 3ab3be6..629eb3c 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "lint:fix": "eslint --fix --ignore-path .prettierignore \"**/*.ts\"", "lint:check-rule-overlap": "npx eslint-config-prettier src/index.ts", "typecheck": "tsc --noEmit", + "validate-templates": "npx swagger-cli validate ./bin/templates/json/[entryPoint].json & npx swagger-cli validate ./bin/templates/yaml/[entryPoint].yaml", "prepare": "husky install" }, "bin": { @@ -46,6 +47,7 @@ "lint-staged": "^13.0.3", "node-dev": "^7.4.3", "prettier": "^2.7.1", + "swagger-cli": "^4.0.4", "ts-jest": "^29.0.3", "typescript": "^4.9.3" }, From 64a81260da6eefbde68454d842074d199707f1a9 Mon Sep 17 00:00:00 2001 From: Mark Potter Date: Thu, 1 Dec 2022 16:03:47 +0000 Subject: [PATCH 13/25] banish fs and path to top --- package.json | 2 +- src/test-utils/mock-file-system.ts | 57 +++++++++++++ src/test-utils/mock-path.ts | 30 +++++++ src/test-utils/mockify.ts | 16 ++++ src/test-utils/random.test.ts | 43 ++++------ src/test-utils/random.ts | 16 ++-- src/write-bin-template.ts | 80 ------------------- .../get-template-file-strings.test.ts.snap | 18 +++++ .../get-bin-target-paths.test.ts | 22 +++++ .../get-bin-target-paths.ts | 21 +++++ .../get-template-file-strings.test.ts | 33 ++++++++ .../get-template-file-strings.ts | 21 +++++ src/write-bin-template/index.ts | 47 +++++++++++ .../make-directory-safely.test.ts | 42 ++++++++++ .../make-directory-safely.ts | 20 +++++ src/write-bin-template/types.ts | 17 ++++ src/write-bin-template/walk.test.ts | 24 ++++++ src/write-bin-template/walk.ts | 24 ++++++ .../write-file-to-bin.test.ts | 61 ++++++++++++++ src/write-bin-template/write-file-to-bin.ts | 34 ++++++++ tsconfig.build.json | 2 +- 21 files changed, 515 insertions(+), 115 deletions(-) create mode 100644 src/test-utils/mock-file-system.ts create mode 100644 src/test-utils/mock-path.ts create mode 100644 src/test-utils/mockify.ts delete mode 100644 src/write-bin-template.ts create mode 100644 src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap create mode 100644 src/write-bin-template/get-bin-target-paths.test.ts create mode 100644 src/write-bin-template/get-bin-target-paths.ts create mode 100644 src/write-bin-template/get-template-file-strings.test.ts create mode 100644 src/write-bin-template/get-template-file-strings.ts create mode 100644 src/write-bin-template/index.ts create mode 100644 src/write-bin-template/make-directory-safely.test.ts create mode 100644 src/write-bin-template/make-directory-safely.ts create mode 100644 src/write-bin-template/types.ts create mode 100644 src/write-bin-template/walk.test.ts create mode 100644 src/write-bin-template/walk.ts create mode 100644 src/write-bin-template/write-file-to-bin.test.ts create mode 100644 src/write-bin-template/write-file-to-bin.ts diff --git a/package.json b/package.json index 629eb3c..aad86ab 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "test": "jest", "dev": "node-dev src/write-bin-template.ts", - "build": "tsc --project tsconfig.build.json && node bin/write-bin-template.js", + "build": "tsc --project tsconfig.build.json && node bin/write-bin-template/index.js", "format": "prettier -w .", "lint": "eslint --ignore-path .prettierignore \"**/*.ts\"", "lint:fix": "eslint --fix --ignore-path .prettierignore \"**/*.ts\"", diff --git a/src/test-utils/mock-file-system.ts b/src/test-utils/mock-file-system.ts new file mode 100644 index 0000000..a11bfc3 --- /dev/null +++ b/src/test-utils/mock-file-system.ts @@ -0,0 +1,57 @@ +import { FileSystem } from '../write-bin-template/types' +import { mockify } from './mockify' + +// Feel free to fill in mkdirSync and rmSync if you think of something sensible +// eslint-disable-next-line @typescript-eslint/no-empty-function +const mkdirSync = (): void => {} +// eslint-disable-next-line @typescript-eslint/no-empty-function +const rmSync = (): void => {} + +const readFileSync = (): Buffer => { + return Buffer.from('Hello Files!') +} + +const statSync = (dir: string): { isDirectory: () => boolean } => { + switch (dir) { + case '/home': + return { isDirectory: () => true } + case '/home/new_folder': + return { isDirectory: () => false } + default: + return { isDirectory: () => false } + } +} + +const readdirSync = (dir: string): string[] => { + switch (dir) { + case '/home': + return ['/a', '/b'] + case '/home/a': + return ['/index.ts'] + case '/home/b': + return ['/c'] + case '/home/b/c': + return ['/deepA.mpg', '/deepB.jpeg'] + default: + return [] + } +} + +// eslint-disable-next-line @typescript-eslint/no-empty-function +const writeFileSync = (_path: string, _data: string): void => {} + +export const makeMockFileSystem = ( + overrides?: Partial, +): FileSystem => { + const fileSystem: FileSystem = mockify({ + mkdirSync, + readdirSync, + readFileSync, + rmSync, + statSync, + writeFileSync, + ...overrides, + }) + + return fileSystem +} diff --git a/src/test-utils/mock-path.ts b/src/test-utils/mock-path.ts new file mode 100644 index 0000000..51dd654 --- /dev/null +++ b/src/test-utils/mock-path.ts @@ -0,0 +1,30 @@ +import { Path } from '../write-bin-template/types' +import { mockify } from './mockify' + +const dirname = (path: string): string => { + const fileName = path.match(/.[a-z]{2,4}$/i) + if (fileName && fileName.index) { + return path.slice(0, fileName.index - 1) + } else { + return path + } +} + +const join = (...paths: string[]): string => { + return paths.join('/') +} + +const resolve = (dir: string, file: string): string => { + return dir + file +} + +export const makeMockPath = (overrides?: Partial): Path => { + const path: Path = mockify({ + dirname, + join, + resolve, + ...overrides, + }) + + return path +} diff --git a/src/test-utils/mockify.ts b/src/test-utils/mockify.ts new file mode 100644 index 0000000..4e540cd --- /dev/null +++ b/src/test-utils/mockify.ts @@ -0,0 +1,16 @@ +export const mockify = < + // TODO figure out the smart way to use Parameters<> to derive + // the record values from typeof jest.fn so that we don't have + // an any type here + // eslint-disable-next-line @typescript-eslint/no-explicit-any + TAnalog extends Record unknown>, +>( + analog: TAnalog, +): TAnalog => { + return Object.entries(analog).reduce((acc, [key, value]) => { + return { + ...acc, + [key]: jest.fn(value), + } + }, {} as TAnalog) as TAnalog +} diff --git a/src/test-utils/random.test.ts b/src/test-utils/random.test.ts index 41ec927..777c7a9 100644 --- a/src/test-utils/random.test.ts +++ b/src/test-utils/random.test.ts @@ -1,34 +1,21 @@ -import { getRandomString, randomiseCase } from './random' - -describe('randomiseCase', () => { - const longHumanString = - "A string long enough that there's a statistically insignificant chance that none of the letters are changed" - - it('randomises randomly', () => { - expect(randomiseCase(randomiseCase(longHumanString))).not.toEqual( - randomiseCase(longHumanString), - ) - }) - - it('makes some letters uppercase', () => { - expect(randomiseCase(longHumanString.toLowerCase())).toMatch(/[A-Z]/) - }) -}) +import { getRandomString } from './random' describe('getRandomString', () => { it('randomises randomly', () => { - expect(getRandomString()).not.toEqual(getRandomString()) - }) - - it('contains uppercase letters', () => { - expect(getRandomString()).toMatch(/[A-Z]/) - }) - - it('contains lowercase letters', () => { - expect(getRandomString()).toMatch(/[a-z]/) - }) + // this takes ~580ms + for (let i = 0; i < 1000; i++) { + const sample = Array(10) + .fill(null) + .map(() => getRandomString()) + const isNotSelfSimilar = sample.every( + (string, i) => string !== sample[i - 1], + ) + expect(isNotSelfSimilar).toBe(true) - it('contains numbers', () => { - expect(getRandomString()).toMatch(/[0-9]/) + const concatenatedSample = sample.reduce((acc, cur) => acc + cur, '') + expect(concatenatedSample).toMatch(/[A-Z]/) + expect(concatenatedSample).toMatch(/[a-z]/) + expect(concatenatedSample).toMatch(/[0-9]/) + } }) }) diff --git a/src/test-utils/random.ts b/src/test-utils/random.ts index d6d498d..450beba 100644 --- a/src/test-utils/random.ts +++ b/src/test-utils/random.ts @@ -1,10 +1,16 @@ -export const randomiseCase = (text: string): string => - text +export const randomiseCase = (text: string): string => { + const pseudorandomDisplacement = Math.random() * Math.PI + return text .split('') - .map((char) => - Math.round(Math.random()) ? char.toUpperCase() : char.toLowerCase(), - ) + .map((char, i) => { + const shouldUppercase = Math.round( + Math.sin(pseudorandomDisplacement + (i * Math.PI) / text.length), + ) + + return shouldUppercase ? char.toUpperCase() : char.toLowerCase() + }) .join('') +} export const getRandomString = (): string => randomiseCase(Math.random().toString(36).substring(2)) diff --git a/src/write-bin-template.ts b/src/write-bin-template.ts deleted file mode 100644 index 824baee..0000000 --- a/src/write-bin-template.ts +++ /dev/null @@ -1,80 +0,0 @@ -import * as fs from 'fs' -import * as path from 'path' -import { stringify } from 'json-to-pretty-yaml' - -const walk = (dir: string, prevResults?: string[]): string[] => { - const list = fs.readdirSync(dir) - const results = prevResults || [] - list.forEach((file) => { - file = path.resolve(dir, file) - const stat = fs.statSync(file) - if (stat.isDirectory()) { - walk(file, results) - } else { - results.push(file) - } - }) - return results -} - -const makeBinTemplateDirectory = (): void => { - const binTemplatesStat = fs.statSync('./bin/templates', { - throwIfNoEntry: false, - }) - if (binTemplatesStat) { - fs.rmSync('./bin/templates', { recursive: true }) - } - fs.mkdirSync('./bin/templates') -} - -const getBinTargetPaths = ( - jsonPath: string, -): { jsonBinPath: string; yamlBinPath: string } => { - const jsonBinPath = jsonPath.replace('/templates/', '/bin/templates/') - const yamlBinPath = jsonBinPath.replaceAll('json', 'yaml') - return { - jsonBinPath, - yamlBinPath, - } -} - -const makeBinTemplateSubdirectory = (jsonPath: string): void => { - const { jsonBinPath, yamlBinPath } = getBinTargetPaths(jsonPath) - const jsonDirname = path.dirname(jsonBinPath) - const yamlDirname = path.dirname(yamlBinPath) - const jsonStat = fs.statSync(jsonDirname, { throwIfNoEntry: false }) - const yamlStat = fs.statSync(yamlDirname, { throwIfNoEntry: false }) - if (!jsonStat?.isDirectory()) { - fs.mkdirSync(jsonDirname) - } - if (!yamlStat?.isDirectory()) { - fs.mkdirSync(yamlDirname) - } -} - -const getTemplateStrings = ( - jsonPath: string, -): { jsonStr: string; yamlStr: string } => { - const rawTemplate = fs.readFileSync(jsonPath).toString() - const jsonStr = rawTemplate.replaceAll('$EXT', 'json') - const yamlStr = stringify(JSON.parse(rawTemplate.replaceAll('$EXT', 'yaml'))) - return { - jsonStr, - yamlStr, - } -} - -const writeTemplateFileToBin = (jsonPath: string): void => { - makeBinTemplateSubdirectory(jsonPath) - const { jsonStr, yamlStr } = getTemplateStrings(jsonPath) - const { jsonBinPath, yamlBinPath } = getBinTargetPaths(jsonPath) - fs.writeFileSync(jsonBinPath, jsonStr) - fs.writeFileSync(yamlBinPath, yamlStr) -} - -;((): void => { - makeBinTemplateDirectory() - walk('./templates/json').forEach((jsonPath) => { - writeTemplateFileToBin(jsonPath) - }) -})() diff --git a/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap b/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap new file mode 100644 index 0000000..25cd424 --- /dev/null +++ b/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`getTemplateFileStrings Converts a JSON template to stringified JSON and YAML 1`] = `"{"just-a-string":"It's just words","just-a-number":8,"an_array":["someValue",{"a nested":"object"}],"anObject":{"anotherString":"words inside an object","aReferenceToSomeExternalFile":"../wherever/it/is/referencedFileA.json","anArray":[{"some":"thing","anotherReferenceToSomeExternalFile":"../wherever/it/is/referencedFileB.json"}]}}"`; + +exports[`getTemplateFileStrings Converts a JSON template to stringified JSON and YAML 2`] = ` +"just-a-string: "It's just words" +just-a-number: 8 +an_array: + - "someValue" + - a nested: "object" +anObject: + anotherString: "words inside an object" + aReferenceToSomeExternalFile: "../wherever/it/is/referencedFileA.yaml" + anArray: + - some: "thing" + anotherReferenceToSomeExternalFile: "../wherever/it/is/referencedFileB.yaml" +" +`; diff --git a/src/write-bin-template/get-bin-target-paths.test.ts b/src/write-bin-template/get-bin-target-paths.test.ts new file mode 100644 index 0000000..f9b1bf5 --- /dev/null +++ b/src/write-bin-template/get-bin-target-paths.test.ts @@ -0,0 +1,22 @@ +import { getRandomString } from '../test-utils/random' +import { getBinTargetPathsFactory } from './get-bin-target-paths' + +describe('getBinTargetPath', () => { + it('Makes target paths for JSON and YAML templates', () => { + const sourcePathFragment = `/${getRandomString()}/${getRandomString()}/` + const targetPathFragment = `/${getRandomString()}/${getRandomString()}/` + const precedingPath = `../../${getRandomString()}/` + const fileName = `${getRandomString()}` + + const { jsonBinPath, yamlBinPath } = getBinTargetPathsFactory({ + sourcePathFragment, + targetPathFragment, + })(`${precedingPath}${sourcePathFragment}${fileName}.json`) + expect(jsonBinPath).toBe( + `${precedingPath}${targetPathFragment}${fileName}.json`, + ) + expect(yamlBinPath).toBe( + `${precedingPath}${targetPathFragment}${fileName}.yaml`, + ) + }) +}) diff --git a/src/write-bin-template/get-bin-target-paths.ts b/src/write-bin-template/get-bin-target-paths.ts new file mode 100644 index 0000000..3220fd2 --- /dev/null +++ b/src/write-bin-template/get-bin-target-paths.ts @@ -0,0 +1,21 @@ +export type GetBinTargetPaths = (jsonPath: string) => { + jsonBinPath: string + yamlBinPath: string +} + +export const getBinTargetPathsFactory = + ({ + sourcePathFragment, + targetPathFragment, + }: { + sourcePathFragment: string + targetPathFragment: string + }): GetBinTargetPaths => + (jsonPath: string): { jsonBinPath: string; yamlBinPath: string } => { + const jsonBinPath = jsonPath.replace(sourcePathFragment, targetPathFragment) + const yamlBinPath = jsonBinPath.replaceAll('json', 'yaml') + return { + jsonBinPath, + yamlBinPath, + } + } diff --git a/src/write-bin-template/get-template-file-strings.test.ts b/src/write-bin-template/get-template-file-strings.test.ts new file mode 100644 index 0000000..0334a2f --- /dev/null +++ b/src/write-bin-template/get-template-file-strings.test.ts @@ -0,0 +1,33 @@ +import { makeMockFileSystem } from '../test-utils/mock-file-system' +import { getTemplateFileStringsFactory } from './get-template-file-strings' + +const mockFile = { + 'just-a-string': "It's just words", + 'just-a-number': 8, + an_array: ['someValue', { 'a nested': 'object' }], + anObject: { + anotherString: 'words inside an object', + aReferenceToSomeExternalFile: '../wherever/it/is/referencedFileA.$EXT', + anArray: [ + { + some: 'thing', + anotherReferenceToSomeExternalFile: + '../wherever/it/is/referencedFileB.$EXT', + }, + ], + }, +} + +describe('getTemplateFileStrings', () => { + it('Converts a JSON template to stringified JSON and YAML', () => { + const mockFileSystem = makeMockFileSystem({ + readFileSync() { + return Buffer.from(JSON.stringify(mockFile)) + }, + }) + const getTemplateFileStrings = getTemplateFileStringsFactory(mockFileSystem) + const { jsonFileStr, yamlFileStr } = getTemplateFileStrings('/path') + expect(jsonFileStr).toMatchSnapshot() + expect(yamlFileStr).toMatchSnapshot() + }) +}) diff --git a/src/write-bin-template/get-template-file-strings.ts b/src/write-bin-template/get-template-file-strings.ts new file mode 100644 index 0000000..3de8855 --- /dev/null +++ b/src/write-bin-template/get-template-file-strings.ts @@ -0,0 +1,21 @@ +import { stringify } from 'json-to-pretty-yaml' +import { FileSystem } from './types' + +export type GetTemplateFileStrings = (jsonPath: string) => { + jsonFileStr: string + yamlFileStr: string +} + +export const getTemplateFileStringsFactory = + ({ readFileSync }: FileSystem) => + (jsonPath: string): { jsonFileStr: string; yamlFileStr: string } => { + const rawTemplate = readFileSync(jsonPath).toString() + const jsonFileStr = rawTemplate.replaceAll('$EXT', 'json') + const yamlFileStr = stringify( + JSON.parse(rawTemplate.replaceAll('$EXT', 'yaml')), + ) + return { + jsonFileStr, + yamlFileStr, + } + } diff --git a/src/write-bin-template/index.ts b/src/write-bin-template/index.ts new file mode 100644 index 0000000..d71c990 --- /dev/null +++ b/src/write-bin-template/index.ts @@ -0,0 +1,47 @@ +import * as nodefs from 'fs' +import * as nodepath from 'path' +import { walkFactory } from './walk' +import { makeDirectorySafelyFactory } from './make-directory-safely' +import { FileSystem, Path } from './types' +import { writeFileToBinFactory } from './write-file-to-bin' + +const spool = ( + fileSystem: FileSystem, + path: Path, + { + sourcePathFragment, + targetPathFragment, + relativeSourcePath, + relativeTargetPath, + }: { + sourcePathFragment: string + targetPathFragment: string + relativeSourcePath: string + relativeTargetPath: string + }, +): void => { + makeDirectorySafelyFactory(fileSystem)(relativeTargetPath, { + shouldEmpty: true, + }) + walkFactory( + fileSystem, + path, + )(path.join(relativeSourcePath, '/json')).forEach( + writeFileToBinFactory(fileSystem, path, { + sourcePathFragment, + targetPathFragment, + }), + ) +} + +const sourcePathFragment = '/templates' +const targetPathFragment = '/bin/templates' + +const relativeSourcePath = '.' + sourcePathFragment +const relativeTargetPath = '.' + targetPathFragment +spool(nodefs, nodepath, { + sourcePathFragment, + targetPathFragment, + relativeSourcePath, + relativeTargetPath, +}) diff --git a/src/write-bin-template/make-directory-safely.test.ts b/src/write-bin-template/make-directory-safely.test.ts new file mode 100644 index 0000000..0701a5b --- /dev/null +++ b/src/write-bin-template/make-directory-safely.test.ts @@ -0,0 +1,42 @@ +import { makeMockFileSystem } from '../test-utils/mock-file-system' +import { getRandomString } from '../test-utils/random' +import { makeDirectorySafelyFactory } from './make-directory-safely' + +describe('makeDirectorySafely', () => { + describe('Given a path to a directory that already exists', () => { + it('Does nothing', () => { + const mockFileSystem = makeMockFileSystem() + const makeDirectorySafely = makeDirectorySafelyFactory(mockFileSystem) + + makeDirectorySafely('/home') + + expect(mockFileSystem.rmSync).not.toHaveBeenCalled() + expect(mockFileSystem.mkdirSync).not.toHaveBeenCalled() + }) + + it('Removes the directory and remakes it if shouldEmpty is set', () => { + const mockFileSystem = makeMockFileSystem() + const makeDirectorySafely = makeDirectorySafelyFactory(mockFileSystem) + + makeDirectorySafely('/home', { shouldEmpty: true }) + + expect(mockFileSystem.rmSync).toHaveBeenCalledWith('/home', { + recursive: true, + }) + expect(mockFileSystem.mkdirSync).toHaveBeenCalledWith('/home') + }) + }) + + describe('given a path to a directory that does not exist', () => { + it('Makes the directory', () => { + const mockFileSystem = makeMockFileSystem() + const makeDirectorySafely = makeDirectorySafelyFactory(mockFileSystem) + + const newDirName = `/${getRandomString()}` + makeDirectorySafely(newDirName) + + expect(mockFileSystem.rmSync).not.toHaveBeenCalled() + expect(mockFileSystem.mkdirSync).toHaveBeenCalledWith(newDirName) + }) + }) +}) diff --git a/src/write-bin-template/make-directory-safely.ts b/src/write-bin-template/make-directory-safely.ts new file mode 100644 index 0000000..ac0a011 --- /dev/null +++ b/src/write-bin-template/make-directory-safely.ts @@ -0,0 +1,20 @@ +import { FileSystem } from './types' + +export type MakeDirectorySafely = ( + path: string, + options?: { shouldEmpty: boolean }, +) => void + +export const makeDirectorySafelyFactory = + ({ mkdirSync, rmSync, statSync }: FileSystem): MakeDirectorySafely => + (path: string, { shouldEmpty } = { shouldEmpty: false }): void => { + const stat = statSync(path, { + throwIfNoEntry: false, + }) + if (stat?.isDirectory() && !shouldEmpty) { + return + } else if (stat?.isDirectory() && shouldEmpty) { + rmSync(path, { recursive: true }) + } + mkdirSync(path) + } diff --git a/src/write-bin-template/types.ts b/src/write-bin-template/types.ts new file mode 100644 index 0000000..2818a3f --- /dev/null +++ b/src/write-bin-template/types.ts @@ -0,0 +1,17 @@ +export interface FileSystem { + mkdirSync: (dir: string) => void + statSync: ( + dir: string, + opts?: { throwIfNoEntry?: boolean }, + ) => { isDirectory: () => boolean } + readdirSync: (dir: string) => string[] + readFileSync: (path: string) => Buffer + rmSync: (dir: string, opts: { recursive?: boolean }) => void + writeFileSync: (path: string, data: string) => void +} + +export interface Path { + dirname: (path: string) => string + join: (...paths: string[]) => string + resolve: (dir: string, file: string) => string +} diff --git a/src/write-bin-template/walk.test.ts b/src/write-bin-template/walk.test.ts new file mode 100644 index 0000000..f0b9bed --- /dev/null +++ b/src/write-bin-template/walk.test.ts @@ -0,0 +1,24 @@ +import { makeMockFileSystem } from '../test-utils/mock-file-system' +import { makeMockPath } from '../test-utils/mock-path' +import { walkFactory } from './walk' + +export const statSync = (dir: string): { isDirectory: () => boolean } => { + return { + isDirectory: (): boolean => { + return !dir.match(/\.[a-z]{2,4}$/) + }, + } +} + +describe('walk', () => { + const walk = walkFactory(makeMockFileSystem({ statSync }), makeMockPath()) + + it("Returns a list of paths to all files within a directory and it's subdirectories", () => { + const files = walk('/home') + expect(files).toEqual([ + '/home/a/index.ts', + '/home/b/c/deepA.mpg', + '/home/b/c/deepB.jpeg', + ]) + }) +}) diff --git a/src/write-bin-template/walk.ts b/src/write-bin-template/walk.ts new file mode 100644 index 0000000..a1919a2 --- /dev/null +++ b/src/write-bin-template/walk.ts @@ -0,0 +1,24 @@ +import { FileSystem, Path } from './types' + +export type Walk = (dir: string, prevResults?: string[] | undefined) => string[] + +export const walkFactory = ( + { statSync, readdirSync }: FileSystem, + { resolve }: Path, +): Walk => { + const walk = (dir: string, prevResults?: string[]): string[] => { + const list = readdirSync(dir) + const results = prevResults || [] + list.forEach((file) => { + file = resolve(dir, file) + const stat = statSync(file) + if (stat.isDirectory()) { + walk(file, results) + } else { + results.push(file) + } + }) + return results + } + return walk +} diff --git a/src/write-bin-template/write-file-to-bin.test.ts b/src/write-bin-template/write-file-to-bin.test.ts new file mode 100644 index 0000000..4b38414 --- /dev/null +++ b/src/write-bin-template/write-file-to-bin.test.ts @@ -0,0 +1,61 @@ +import { makeMockFileSystem } from '../test-utils/mock-file-system' +import { makeMockPath } from '../test-utils/mock-path' +import { getRandomString } from '../test-utils/random' +import { + GetTemplateFileStrings, + getTemplateFileStringsFactory, +} from './get-template-file-strings' +import { writeFileToBinFactory } from './write-file-to-bin' + +jest.mock('./get-template-file-strings', () => ({ + getTemplateFileStringsFactory: jest.fn(), +})) + +const mockGetTemplateFileStringsFactory = + getTemplateFileStringsFactory as jest.Mock + +const jsonFileStr = getRandomString() +const yamlFileStr = getRandomString() + +mockGetTemplateFileStringsFactory.mockImplementation( + (): GetTemplateFileStrings => () => ({ + jsonFileStr, + yamlFileStr, + }), +) + +describe('writeFileToBin', () => { + it('Writes the template files to the target path', () => { + const fragsAndPaths = { + sourcePathFragment: `/${getRandomString()}`, + targetPathFragment: `/${getRandomString()}/${getRandomString()}`, + } + + const precedingPath = getRandomString() + const fileName = getRandomString() + + const inputPath = `/${precedingPath}/${fragsAndPaths.sourcePathFragment}/${fileName}.json` + + const expectedJsonOutputPath = `/${precedingPath}/${fragsAndPaths.targetPathFragment}/${fileName}.json` + + const expectedYamlOutputPath = `/${precedingPath}/${fragsAndPaths.targetPathFragment}/${fileName}.yaml` + + const mockFileSystem = makeMockFileSystem() + const writeFileToBin = writeFileToBinFactory( + mockFileSystem, + makeMockPath(), + fragsAndPaths, + ) + + writeFileToBin(inputPath) + + expect(mockFileSystem.writeFileSync).toHaveBeenCalledWith( + expectedJsonOutputPath, + jsonFileStr, + ) + expect(mockFileSystem.writeFileSync).toHaveBeenCalledWith( + expectedYamlOutputPath, + yamlFileStr, + ) + }) +}) diff --git a/src/write-bin-template/write-file-to-bin.ts b/src/write-bin-template/write-file-to-bin.ts new file mode 100644 index 0000000..1e3644c --- /dev/null +++ b/src/write-bin-template/write-file-to-bin.ts @@ -0,0 +1,34 @@ +import { makeDirectorySafelyFactory } from './make-directory-safely' +import { getTemplateFileStringsFactory } from './get-template-file-strings' +import { getBinTargetPathsFactory } from './get-bin-target-paths' +import { FileSystem, Path } from './types' + +export type WriteFilesToBin = (jsonPath: string) => void + +export const writeFileToBinFactory = ( + fileSystem: FileSystem, + path: Path, + { + sourcePathFragment, + targetPathFragment, + }: { + sourcePathFragment: string + targetPathFragment: string + }, +): WriteFilesToBin => { + const getBinTargetPaths = getBinTargetPathsFactory({ + sourcePathFragment, + targetPathFragment, + }) + + return (jsonPath: string): void => { + const { jsonFileStr, yamlFileStr } = + getTemplateFileStringsFactory(fileSystem)(jsonPath) + const { jsonBinPath, yamlBinPath } = getBinTargetPaths(jsonPath) + const makeDirectory = makeDirectorySafelyFactory(fileSystem) + makeDirectory(path.dirname(jsonBinPath)) + makeDirectory(path.dirname(yamlBinPath)) + fileSystem.writeFileSync(jsonBinPath, jsonFileStr) + fileSystem.writeFileSync(yamlBinPath, yamlFileStr) + } +} diff --git a/tsconfig.build.json b/tsconfig.build.json index fe26423..4561d7b 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "exclude": ["node_modules", "src/*.test.*", "src/test-utils", "bin"] + "exclude": ["node_modules", "src/**/*.test.*", "src/test-utils", "bin"] } From f5e2f10d39423e5f899c076c0f84d0ef06ee6668 Mon Sep 17 00:00:00 2001 From: Mark Potter Date: Fri, 2 Dec 2022 11:44:20 +0000 Subject: [PATCH 14/25] remove spool, I didn't like that name --- src/write-bin-template/index.ts | 34 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/write-bin-template/index.ts b/src/write-bin-template/index.ts index d71c990..a3debe5 100644 --- a/src/write-bin-template/index.ts +++ b/src/write-bin-template/index.ts @@ -1,12 +1,11 @@ -import * as nodefs from 'fs' -import * as nodepath from 'path' +import * as fs from 'fs' +import * as path from 'path' import { walkFactory } from './walk' import { makeDirectorySafelyFactory } from './make-directory-safely' import { FileSystem, Path } from './types' import { writeFileToBinFactory } from './write-file-to-bin' - -const spool = ( - fileSystem: FileSystem, +;(( + fs: FileSystem, path: Path, { sourcePathFragment, @@ -20,28 +19,21 @@ const spool = ( relativeTargetPath: string }, ): void => { - makeDirectorySafelyFactory(fileSystem)(relativeTargetPath, { + makeDirectorySafelyFactory(fs)(relativeTargetPath, { shouldEmpty: true, }) walkFactory( - fileSystem, + fs, path, - )(path.join(relativeSourcePath, '/json')).forEach( - writeFileToBinFactory(fileSystem, path, { + )(relativeSourcePath).forEach( + writeFileToBinFactory(fs, path, { sourcePathFragment, targetPathFragment, }), ) -} - -const sourcePathFragment = '/templates' -const targetPathFragment = '/bin/templates' - -const relativeSourcePath = '.' + sourcePathFragment -const relativeTargetPath = '.' + targetPathFragment -spool(nodefs, nodepath, { - sourcePathFragment, - targetPathFragment, - relativeSourcePath, - relativeTargetPath, +})(fs, path, { + sourcePathFragment: '/templates', + targetPathFragment: '/bin/templates', + relativeSourcePath: './templates/json', + relativeTargetPath: './bin/templates', }) From 3e93353c4fc2f7277399df2de0db7ba4b0c09830 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Mon, 19 Dec 2022 16:11:56 +0000 Subject: [PATCH 15/25] Use import type for TS definition imports --- src/test-utils/mock-file-system.ts | 2 +- src/write-bin-template/get-template-file-strings.ts | 2 +- src/write-bin-template/index.ts | 2 +- src/write-bin-template/make-directory-safely.ts | 2 +- src/write-bin-template/walk.ts | 2 +- src/write-bin-template/write-file-to-bin.ts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test-utils/mock-file-system.ts b/src/test-utils/mock-file-system.ts index a11bfc3..d2976ce 100644 --- a/src/test-utils/mock-file-system.ts +++ b/src/test-utils/mock-file-system.ts @@ -1,4 +1,4 @@ -import { FileSystem } from '../write-bin-template/types' +import type { FileSystem } from '../write-bin-template/types' import { mockify } from './mockify' // Feel free to fill in mkdirSync and rmSync if you think of something sensible diff --git a/src/write-bin-template/get-template-file-strings.ts b/src/write-bin-template/get-template-file-strings.ts index 3de8855..aae0cb4 100644 --- a/src/write-bin-template/get-template-file-strings.ts +++ b/src/write-bin-template/get-template-file-strings.ts @@ -1,5 +1,5 @@ import { stringify } from 'json-to-pretty-yaml' -import { FileSystem } from './types' +import type { FileSystem } from './types' export type GetTemplateFileStrings = (jsonPath: string) => { jsonFileStr: string diff --git a/src/write-bin-template/index.ts b/src/write-bin-template/index.ts index a3debe5..36c59dd 100644 --- a/src/write-bin-template/index.ts +++ b/src/write-bin-template/index.ts @@ -2,7 +2,7 @@ import * as fs from 'fs' import * as path from 'path' import { walkFactory } from './walk' import { makeDirectorySafelyFactory } from './make-directory-safely' -import { FileSystem, Path } from './types' +import type { FileSystem, Path } from './types' import { writeFileToBinFactory } from './write-file-to-bin' ;(( fs: FileSystem, diff --git a/src/write-bin-template/make-directory-safely.ts b/src/write-bin-template/make-directory-safely.ts index ac0a011..6ac1f7c 100644 --- a/src/write-bin-template/make-directory-safely.ts +++ b/src/write-bin-template/make-directory-safely.ts @@ -1,4 +1,4 @@ -import { FileSystem } from './types' +import type { FileSystem } from './types' export type MakeDirectorySafely = ( path: string, diff --git a/src/write-bin-template/walk.ts b/src/write-bin-template/walk.ts index a1919a2..039b814 100644 --- a/src/write-bin-template/walk.ts +++ b/src/write-bin-template/walk.ts @@ -1,4 +1,4 @@ -import { FileSystem, Path } from './types' +import type { FileSystem, Path } from './types' export type Walk = (dir: string, prevResults?: string[] | undefined) => string[] diff --git a/src/write-bin-template/write-file-to-bin.ts b/src/write-bin-template/write-file-to-bin.ts index 1e3644c..ef5afbc 100644 --- a/src/write-bin-template/write-file-to-bin.ts +++ b/src/write-bin-template/write-file-to-bin.ts @@ -1,7 +1,7 @@ import { makeDirectorySafelyFactory } from './make-directory-safely' import { getTemplateFileStringsFactory } from './get-template-file-strings' import { getBinTargetPathsFactory } from './get-bin-target-paths' -import { FileSystem, Path } from './types' +import type { FileSystem, Path } from './types' export type WriteFilesToBin = (jsonPath: string) => void From fe9745d0a690e239e6c2ca2600f501783fdf0ad0 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Mon, 19 Dec 2022 17:22:10 +0000 Subject: [PATCH 16/25] Move node stub TS definitions --- src/test-utils/mock-file-system.ts | 2 +- src/test-utils/mock-path.ts | 2 +- src/write-bin-template/get-template-file-strings.ts | 2 +- src/write-bin-template/index.ts | 2 +- src/write-bin-template/make-directory-safely.ts | 2 +- src/write-bin-template/walk.ts | 2 +- src/write-bin-template/write-file-to-bin.ts | 2 +- src/write-bin-template/types.ts => types/node-stub.d.ts | 0 8 files changed, 7 insertions(+), 7 deletions(-) rename src/write-bin-template/types.ts => types/node-stub.d.ts (100%) diff --git a/src/test-utils/mock-file-system.ts b/src/test-utils/mock-file-system.ts index d2976ce..e7558fb 100644 --- a/src/test-utils/mock-file-system.ts +++ b/src/test-utils/mock-file-system.ts @@ -1,4 +1,4 @@ -import type { FileSystem } from '../write-bin-template/types' +import type { FileSystem } from '../../types/node-stub.d' import { mockify } from './mockify' // Feel free to fill in mkdirSync and rmSync if you think of something sensible diff --git a/src/test-utils/mock-path.ts b/src/test-utils/mock-path.ts index 51dd654..44ab249 100644 --- a/src/test-utils/mock-path.ts +++ b/src/test-utils/mock-path.ts @@ -1,4 +1,4 @@ -import { Path } from '../write-bin-template/types' +import { Path } from '../../types/node-stub.d' import { mockify } from './mockify' const dirname = (path: string): string => { diff --git a/src/write-bin-template/get-template-file-strings.ts b/src/write-bin-template/get-template-file-strings.ts index aae0cb4..a4895d1 100644 --- a/src/write-bin-template/get-template-file-strings.ts +++ b/src/write-bin-template/get-template-file-strings.ts @@ -1,5 +1,5 @@ import { stringify } from 'json-to-pretty-yaml' -import type { FileSystem } from './types' +import type { FileSystem } from '../../types/node-stub.d' export type GetTemplateFileStrings = (jsonPath: string) => { jsonFileStr: string diff --git a/src/write-bin-template/index.ts b/src/write-bin-template/index.ts index 36c59dd..e661690 100644 --- a/src/write-bin-template/index.ts +++ b/src/write-bin-template/index.ts @@ -1,8 +1,8 @@ import * as fs from 'fs' import * as path from 'path' +import type { FileSystem, Path } from '../../types/node-stub.d' import { walkFactory } from './walk' import { makeDirectorySafelyFactory } from './make-directory-safely' -import type { FileSystem, Path } from './types' import { writeFileToBinFactory } from './write-file-to-bin' ;(( fs: FileSystem, diff --git a/src/write-bin-template/make-directory-safely.ts b/src/write-bin-template/make-directory-safely.ts index 6ac1f7c..a918112 100644 --- a/src/write-bin-template/make-directory-safely.ts +++ b/src/write-bin-template/make-directory-safely.ts @@ -1,4 +1,4 @@ -import type { FileSystem } from './types' +import type { FileSystem } from '../../types/node-stub.d' export type MakeDirectorySafely = ( path: string, diff --git a/src/write-bin-template/walk.ts b/src/write-bin-template/walk.ts index 039b814..f4e2910 100644 --- a/src/write-bin-template/walk.ts +++ b/src/write-bin-template/walk.ts @@ -1,4 +1,4 @@ -import type { FileSystem, Path } from './types' +import type { FileSystem, Path } from '../../types/node-stub.d' export type Walk = (dir: string, prevResults?: string[] | undefined) => string[] diff --git a/src/write-bin-template/write-file-to-bin.ts b/src/write-bin-template/write-file-to-bin.ts index ef5afbc..fd2839d 100644 --- a/src/write-bin-template/write-file-to-bin.ts +++ b/src/write-bin-template/write-file-to-bin.ts @@ -1,7 +1,7 @@ +import type { FileSystem, Path } from '../../types/node-stub.d' import { makeDirectorySafelyFactory } from './make-directory-safely' import { getTemplateFileStringsFactory } from './get-template-file-strings' import { getBinTargetPathsFactory } from './get-bin-target-paths' -import type { FileSystem, Path } from './types' export type WriteFilesToBin = (jsonPath: string) => void diff --git a/src/write-bin-template/types.ts b/types/node-stub.d.ts similarity index 100% rename from src/write-bin-template/types.ts rename to types/node-stub.d.ts From f2649359b16860141199def1c4bcc1c2e71aef87 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Tue, 20 Dec 2022 10:31:43 +0000 Subject: [PATCH 17/25] Fix cross-platform issues with validate-templates --- package-lock.json | 144 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 +- 2 files changed, 148 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 31136db..b6d1f7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@types/prompts": "^2.4.1", "@typescript-eslint/eslint-plugin": "^5.43.0", "@typescript-eslint/parser": "^5.43.0", + "concurrently": "^7.6.0", "eslint": "^8.27.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.26.0", @@ -2297,6 +2298,48 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/concurrently": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", + "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "date-fns": "^2.29.1", + "lodash": "^4.17.21", + "rxjs": "^7.0.0", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -2317,6 +2360,19 @@ "node": ">= 8" } }, + "node_modules/date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "dev": true, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -4860,6 +4916,12 @@ "node": ">=8" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -5784,6 +5846,15 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.4.tgz", + "integrity": "sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -5883,6 +5954,12 @@ "source-map": "^0.6.0" } }, + "node_modules/spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", + "dev": true + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6099,6 +6176,15 @@ "node": ">=8.0" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/ts-jest": { "version": "29.0.3", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz", @@ -8228,6 +8314,34 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "concurrently": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", + "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "date-fns": "^2.29.1", + "lodash": "^4.17.21", + "rxjs": "^7.0.0", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -8245,6 +8359,12 @@ "which": "^2.0.1" } }, + "date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "dev": true + }, "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -10104,6 +10224,12 @@ "p-locate": "^4.1.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -10768,6 +10894,12 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shell-quote": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.4.tgz", + "integrity": "sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw==", + "dev": true + }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -10842,6 +10974,12 @@ "source-map": "^0.6.0" } }, + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -11001,6 +11139,12 @@ "is-number": "^7.0.0" } }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, "ts-jest": { "version": "29.0.3", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz", diff --git a/package.json b/package.json index aad86ab..967d253 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,9 @@ "lint:fix": "eslint --fix --ignore-path .prettierignore \"**/*.ts\"", "lint:check-rule-overlap": "npx eslint-config-prettier src/index.ts", "typecheck": "tsc --noEmit", - "validate-templates": "npx swagger-cli validate ./bin/templates/json/[entryPoint].json & npx swagger-cli validate ./bin/templates/yaml/[entryPoint].yaml", + "validate-templates": "concurrently --kill-others-on-fail -c \"auto\" -n \"validate:\" \"npm:validate-template-*\"", + "validate-template-json": "npx swagger-cli validate ./bin/templates/json/[entryPoint].json", + "validate-template-yaml": "npx swagger-cli validate ./bin/templates/yaml/[entryPoint].yaml", "prepare": "husky install" }, "bin": { @@ -36,6 +38,7 @@ "@types/prompts": "^2.4.1", "@typescript-eslint/eslint-plugin": "^5.43.0", "@typescript-eslint/parser": "^5.43.0", + "concurrently": "^7.6.0", "eslint": "^8.27.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.26.0", From ce4f7db9cb0b5c7dc163817940304d249bd73572 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Tue, 20 Dec 2022 11:26:52 +0000 Subject: [PATCH 18/25] Add tests for mockify --- src/test-utils/mockify.test.ts | 45 ++++++++++++++++++++++++++++++++++ src/test-utils/mockify.ts | 5 ++-- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 src/test-utils/mockify.test.ts diff --git a/src/test-utils/mockify.test.ts b/src/test-utils/mockify.test.ts new file mode 100644 index 0000000..ce344e7 --- /dev/null +++ b/src/test-utils/mockify.test.ts @@ -0,0 +1,45 @@ +import { mockify } from './mockify' + +describe('mockify', () => { + const double = (input: number): number => input * 2 + const formatAsPrice = (input: number): string => `£${input.toFixed(2)}` + const primitiveValue = 999 + const nestedObject = { + foo: (): string => 'FOO!', + } + + const mocked = mockify({ + double, + formatAsPrice, + primitiveValue, + nestedObject, + }) + + it('returns a jest mock of each value that is a function of the supplied object', () => { + const doubled = mocked.double(7) + // @ts-expect-error top-level functions supplied should have a mock property https://bit.ly/3V8ImcV + expect(mocked.double.mock).toBeDefined() + expect(mocked.double).toHaveBeenCalledTimes(1) + expect(mocked.double).toHaveBeenCalledWith(7) + expect(doubled).toBe(14) + + const price1 = mocked.formatAsPrice(123.456) + const price2 = mocked.formatAsPrice(789) + // @ts-expect-error top-level functions supplied should have a mock property https://bit.ly/3V8ImcV + expect(mocked.formatAsPrice.mock).toBeDefined() + expect(mocked.formatAsPrice).toHaveBeenCalledTimes(2) + expect(price1).toBe('£123.46') + expect(price2).toBe('£789.00') + }) + + it('returns nested object values as-is', () => { + // @ts-expect-error mock properties exist Jest mock functions https://bit.ly/3V8ImcV + expect(mocked.nestedObject.foo.mock).toBeUndefined() + expect(mocked.nestedObject).toBe(nestedObject) + expect(mocked.nestedObject.foo()).toBe('FOO!') + }) + + it('returns mocked primitive values as-is', () => { + expect(mocked.primitiveValue).toBe(primitiveValue) + }) +}) diff --git a/src/test-utils/mockify.ts b/src/test-utils/mockify.ts index 4e540cd..be0e638 100644 --- a/src/test-utils/mockify.ts +++ b/src/test-utils/mockify.ts @@ -3,14 +3,15 @@ export const mockify = < // the record values from typeof jest.fn so that we don't have // an any type here // eslint-disable-next-line @typescript-eslint/no-explicit-any - TAnalog extends Record unknown>, + TAnalog extends Record, >( analog: TAnalog, ): TAnalog => { return Object.entries(analog).reduce((acc, [key, value]) => { + const newValue = typeof value === 'function' ? jest.fn(value) : value return { ...acc, - [key]: jest.fn(value), + [key]: newValue, } }, {} as TAnalog) as TAnalog } From e8d1c1883f8d730501630d5bedad2b0ccce721de Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Tue, 20 Dec 2022 11:37:02 +0000 Subject: [PATCH 19/25] Separate format assertions for getTemplateFileStrings --- .../get-template-file-strings.test.ts.snap | 4 ++-- .../get-template-file-strings.test.ts | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap b/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap index 25cd424..f8cc8dd 100644 --- a/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap +++ b/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap @@ -1,8 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`getTemplateFileStrings Converts a JSON template to stringified JSON and YAML 1`] = `"{"just-a-string":"It's just words","just-a-number":8,"an_array":["someValue",{"a nested":"object"}],"anObject":{"anotherString":"words inside an object","aReferenceToSomeExternalFile":"../wherever/it/is/referencedFileA.json","anArray":[{"some":"thing","anotherReferenceToSomeExternalFile":"../wherever/it/is/referencedFileB.json"}]}}"`; +exports[`getTemplateFileStrings Converts a JSON template to stringified JSON 1`] = `"{"just-a-string":"It's just words","just-a-number":8,"an_array":["someValue",{"a nested":"object"}],"anObject":{"anotherString":"words inside an object","aReferenceToSomeExternalFile":"../wherever/it/is/referencedFileA.json","anArray":[{"some":"thing","anotherReferenceToSomeExternalFile":"../wherever/it/is/referencedFileB.json"}]}}"`; -exports[`getTemplateFileStrings Converts a JSON template to stringified JSON and YAML 2`] = ` +exports[`getTemplateFileStrings Converts a JSON template to stringified YAML 1`] = ` "just-a-string: "It's just words" just-a-number: 8 an_array: diff --git a/src/write-bin-template/get-template-file-strings.test.ts b/src/write-bin-template/get-template-file-strings.test.ts index 0334a2f..5497025 100644 --- a/src/write-bin-template/get-template-file-strings.test.ts +++ b/src/write-bin-template/get-template-file-strings.test.ts @@ -19,15 +19,22 @@ const mockFile = { } describe('getTemplateFileStrings', () => { - it('Converts a JSON template to stringified JSON and YAML', () => { + let jsonFileStr: string, yamlFileStr: string + beforeAll(() => { const mockFileSystem = makeMockFileSystem({ readFileSync() { return Buffer.from(JSON.stringify(mockFile)) }, }) const getTemplateFileStrings = getTemplateFileStringsFactory(mockFileSystem) - const { jsonFileStr, yamlFileStr } = getTemplateFileStrings('/path') + ;({ jsonFileStr, yamlFileStr } = getTemplateFileStrings('/path')) + }) + + it('Converts a JSON template to stringified JSON', () => { expect(jsonFileStr).toMatchSnapshot() + }) + + it('Converts a JSON template to stringified YAML', () => { expect(yamlFileStr).toMatchSnapshot() }) }) From de04a440f1d241d48cfbe1535349ec3d97525442 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Tue, 20 Dec 2022 11:56:24 +0000 Subject: [PATCH 20/25] Ensure pretty output of JSON from getTemplateFileStrings --- .../get-template-file-strings.test.ts.snap | 23 ++++++++++++++++++- .../get-template-file-strings.ts | 6 ++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap b/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap index f8cc8dd..761e137 100644 --- a/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap +++ b/src/write-bin-template/__snapshots__/get-template-file-strings.test.ts.snap @@ -1,6 +1,27 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`getTemplateFileStrings Converts a JSON template to stringified JSON 1`] = `"{"just-a-string":"It's just words","just-a-number":8,"an_array":["someValue",{"a nested":"object"}],"anObject":{"anotherString":"words inside an object","aReferenceToSomeExternalFile":"../wherever/it/is/referencedFileA.json","anArray":[{"some":"thing","anotherReferenceToSomeExternalFile":"../wherever/it/is/referencedFileB.json"}]}}"`; +exports[`getTemplateFileStrings Converts a JSON template to stringified JSON 1`] = ` +"{ + "just-a-string": "It's just words", + "just-a-number": 8, + "an_array": [ + "someValue", + { + "a nested": "object" + } + ], + "anObject": { + "anotherString": "words inside an object", + "aReferenceToSomeExternalFile": "../wherever/it/is/referencedFileA.json", + "anArray": [ + { + "some": "thing", + "anotherReferenceToSomeExternalFile": "../wherever/it/is/referencedFileB.json" + } + ] + } +}" +`; exports[`getTemplateFileStrings Converts a JSON template to stringified YAML 1`] = ` "just-a-string: "It's just words" diff --git a/src/write-bin-template/get-template-file-strings.ts b/src/write-bin-template/get-template-file-strings.ts index a4895d1..0ee2483 100644 --- a/src/write-bin-template/get-template-file-strings.ts +++ b/src/write-bin-template/get-template-file-strings.ts @@ -10,7 +10,11 @@ export const getTemplateFileStringsFactory = ({ readFileSync }: FileSystem) => (jsonPath: string): { jsonFileStr: string; yamlFileStr: string } => { const rawTemplate = readFileSync(jsonPath).toString() - const jsonFileStr = rawTemplate.replaceAll('$EXT', 'json') + const jsonFileStr = JSON.stringify( + JSON.parse(rawTemplate.replaceAll('$EXT', 'json')), + null, + 2, + ) const yamlFileStr = stringify( JSON.parse(rawTemplate.replaceAll('$EXT', 'yaml')), ) From 79907928e20903ef3cccdaf1271779e5f322aa6d Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Tue, 20 Dec 2022 12:07:38 +0000 Subject: [PATCH 21/25] Reduce repetition in writeFileToBinFactory --- src/write-bin-template/write-file-to-bin.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/write-bin-template/write-file-to-bin.ts b/src/write-bin-template/write-file-to-bin.ts index fd2839d..05c0bf3 100644 --- a/src/write-bin-template/write-file-to-bin.ts +++ b/src/write-bin-template/write-file-to-bin.ts @@ -26,9 +26,12 @@ export const writeFileToBinFactory = ( getTemplateFileStringsFactory(fileSystem)(jsonPath) const { jsonBinPath, yamlBinPath } = getBinTargetPaths(jsonPath) const makeDirectory = makeDirectorySafelyFactory(fileSystem) - makeDirectory(path.dirname(jsonBinPath)) - makeDirectory(path.dirname(yamlBinPath)) - fileSystem.writeFileSync(jsonBinPath, jsonFileStr) - fileSystem.writeFileSync(yamlBinPath, yamlFileStr) + new Map([ + [jsonBinPath, jsonFileStr], + [yamlBinPath, yamlFileStr], + ]).forEach((fileContent, binPath) => { + makeDirectory(path.dirname(binPath)) + fileSystem.writeFileSync(binPath, fileContent) + }) } } From 29917bb216c0a1ab97b45c95d0c04889877f9098 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Tue, 20 Dec 2022 14:15:08 +0000 Subject: [PATCH 22/25] Tidy up of write-file-to-bin --- .../get-bin-target-paths.ts | 12 ++++++----- src/write-bin-template/write-file-to-bin.ts | 20 ++++++------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/write-bin-template/get-bin-target-paths.ts b/src/write-bin-template/get-bin-target-paths.ts index 3220fd2..25beb68 100644 --- a/src/write-bin-template/get-bin-target-paths.ts +++ b/src/write-bin-template/get-bin-target-paths.ts @@ -1,4 +1,9 @@ -export type GetBinTargetPaths = (jsonPath: string) => { +export type SourceAndTargetDirectories = { + sourcePathFragment: string + targetPathFragment: string +} + +export type BinTargetPaths = (jsonPath: string) => { jsonBinPath: string yamlBinPath: string } @@ -7,10 +12,7 @@ export const getBinTargetPathsFactory = ({ sourcePathFragment, targetPathFragment, - }: { - sourcePathFragment: string - targetPathFragment: string - }): GetBinTargetPaths => + }: SourceAndTargetDirectories): BinTargetPaths => (jsonPath: string): { jsonBinPath: string; yamlBinPath: string } => { const jsonBinPath = jsonPath.replace(sourcePathFragment, targetPathFragment) const yamlBinPath = jsonBinPath.replaceAll('json', 'yaml') diff --git a/src/write-bin-template/write-file-to-bin.ts b/src/write-bin-template/write-file-to-bin.ts index 05c0bf3..0ae88c1 100644 --- a/src/write-bin-template/write-file-to-bin.ts +++ b/src/write-bin-template/write-file-to-bin.ts @@ -2,30 +2,22 @@ import type { FileSystem, Path } from '../../types/node-stub.d' import { makeDirectorySafelyFactory } from './make-directory-safely' import { getTemplateFileStringsFactory } from './get-template-file-strings' import { getBinTargetPathsFactory } from './get-bin-target-paths' +import type { SourceAndTargetDirectories } from './get-bin-target-paths' export type WriteFilesToBin = (jsonPath: string) => void export const writeFileToBinFactory = ( fileSystem: FileSystem, path: Path, - { - sourcePathFragment, - targetPathFragment, - }: { - sourcePathFragment: string - targetPathFragment: string - }, + sourceAndTargetDirs: SourceAndTargetDirectories, ): WriteFilesToBin => { - const getBinTargetPaths = getBinTargetPathsFactory({ - sourcePathFragment, - targetPathFragment, - }) + const getBinTargetPaths = getBinTargetPathsFactory(sourceAndTargetDirs) + const templateStringFactory = getTemplateFileStringsFactory(fileSystem) + const makeDirectory = makeDirectorySafelyFactory(fileSystem) return (jsonPath: string): void => { - const { jsonFileStr, yamlFileStr } = - getTemplateFileStringsFactory(fileSystem)(jsonPath) + const { jsonFileStr, yamlFileStr } = templateStringFactory(jsonPath) const { jsonBinPath, yamlBinPath } = getBinTargetPaths(jsonPath) - const makeDirectory = makeDirectorySafelyFactory(fileSystem) new Map([ [jsonBinPath, jsonFileStr], [yamlBinPath, yamlFileStr], From 37fcd458d3b7545285a0636303077346939e8604 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Tue, 20 Dec 2022 14:20:31 +0000 Subject: [PATCH 23/25] Add dev:quick command to bypass the wizard --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 967d253..8bc4696 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ }, "scripts": { "test": "jest", - "dev": "node-dev src/write-bin-template.ts", + "dev": "node-dev src/index.ts", + "dev:quick": "node-dev src/write-bin-template.ts", "build": "tsc --project tsconfig.build.json && node bin/write-bin-template/index.js", "format": "prettier -w .", "lint": "eslint --ignore-path .prettierignore \"**/*.ts\"", From 15eab1f4c3587193e0779479fad51b373ff13145 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Tue, 20 Dec 2022 14:25:01 +0000 Subject: [PATCH 24/25] Amend BinTargetPaths type for consistency --- src/write-bin-template/get-bin-target-paths.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/write-bin-template/get-bin-target-paths.ts b/src/write-bin-template/get-bin-target-paths.ts index 25beb68..1cf1348 100644 --- a/src/write-bin-template/get-bin-target-paths.ts +++ b/src/write-bin-template/get-bin-target-paths.ts @@ -3,7 +3,7 @@ export type SourceAndTargetDirectories = { targetPathFragment: string } -export type BinTargetPaths = (jsonPath: string) => { +export type BinTargetPaths = { jsonBinPath: string yamlBinPath: string } @@ -12,8 +12,8 @@ export const getBinTargetPathsFactory = ({ sourcePathFragment, targetPathFragment, - }: SourceAndTargetDirectories): BinTargetPaths => - (jsonPath: string): { jsonBinPath: string; yamlBinPath: string } => { + }: SourceAndTargetDirectories): ((jsonPath: string) => BinTargetPaths) => + (jsonPath: string): BinTargetPaths => { const jsonBinPath = jsonPath.replace(sourcePathFragment, targetPathFragment) const yamlBinPath = jsonBinPath.replaceAll('json', 'yaml') return { From c314e4dc802e2116d805687125dfb0a205aaedc6 Mon Sep 17 00:00:00 2001 From: Rob Morgan Date: Tue, 20 Dec 2022 14:38:08 +0000 Subject: [PATCH 25/25] Write the boilerplate templates to a src directory --- src/wizard.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wizard.ts b/src/wizard.ts index cd7be70..57b3baa 100644 --- a/src/wizard.ts +++ b/src/wizard.ts @@ -75,6 +75,10 @@ const makeBoilerplate = ( fs.mkdirSync(projectName) writeDirectory = path.join(writeDirectory, projectName) } + + writeDirectory = path.join(writeDirectory, 'src') + fs.mkdirSync(writeDirectory) + fs.cpSync( path.join(__dirname, './templates/', documentSyntax), writeDirectory,