From a2bd9869d403b1aec746ce9a07b6ac3031c17e1c Mon Sep 17 00:00:00 2001 From: Arthur de Moulins Date: Mon, 13 Dec 2021 12:29:54 +0100 Subject: [PATCH 1/2] fix typescript template identifiers with dash --- .../TypescriptInterfaceGenerator.js | 9 ++- .../TypescriptInterfaceGenerator.test.js | 58 +++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/generators/TypescriptInterfaceGenerator.js b/src/generators/TypescriptInterfaceGenerator.js index 5a6bec3e..361f55bf 100644 --- a/src/generators/TypescriptInterfaceGenerator.js +++ b/src/generators/TypescriptInterfaceGenerator.js @@ -18,14 +18,19 @@ export default class TypescriptInterfaceGenerator extends BaseGenerator { const dest = `${dir}/interfaces`; const { fields, imports } = this.parseFields(resource); + const normalizeJs = (name) => name.replace(/-/g, "_"); + this.createDir(dest, false); this.createFile( "interface.ts", `${dest}/${resource.title.toLowerCase()}.ts`, { - fields, + fields: fields.map((f) => ({ + ...f, + name: normalizeJs(f.name), + })), imports, - name: resource.title, + name: normalizeJs(resource.title), } ); } diff --git a/src/generators/TypescriptInterfaceGenerator.test.js b/src/generators/TypescriptInterfaceGenerator.test.js index 98358dca..f61705a9 100644 --- a/src/generators/TypescriptInterfaceGenerator.test.js +++ b/src/generators/TypescriptInterfaceGenerator.test.js @@ -173,3 +173,61 @@ test("Generate a typescript interface with an explicit id field in the readableF tmpobj.removeCallback(); }); + +test("Generate a typescript interface with normalized JS identifiers", () => { + const generator = new TypescriptInterfaceGenerator({ + templateDirectory: `${__dirname}/../../templates`, + }); + const tmpobj = tmp.dirSync({ unsafeCleanup: true }); + + const resource = new Resource("abc", "http://example.com/foos", { + id: "foo", + title: "Foo-foo", + readableFields: [ + new Field("bar-bar", { + id: "http://schema.org/url", + range: "http://www.w3.org/2001/XMLSchema#string", + reference: null, + required: true, + description: "An URL", + }), + new Field("id", { + id: "http://schema.org/url", + range: "http://www.w3.org/2001/XMLSchema#string", + reference: null, + required: false, + description: "Id", + }), + ], + writableFields: [ + new Field("foo-foo", { + id: "http://schema.org/url", + range: "http://www.w3.org/2001/XMLSchema#datetime", + reference: null, + required: true, + description: "An URL", + }), + ], + }); + const api = new Api("http://example.com", { + entrypoint: "http://example.com:8080", + title: "My API", + resources: [resource], + }); + generator.generate(api, resource, tmpobj.name); + + expect(fs.existsSync(tmpobj.name + "/interfaces/foo-foo.ts")).toBe(true); + + const res = `export interface Foo_foo { + "@id"?: string; + foo_foo: any; + readonly bar_bar: string; + readonly id?: string; +} +`; + expect( + fs.readFileSync(tmpobj.name + "/interfaces/foo-foo.ts").toString() + ).toEqual(res); + + tmpobj.removeCallback(); +}); From c650efe2dfed5344db72993fd73e12e2190273c3 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Tue, 23 Aug 2022 11:28:13 +0200 Subject: [PATCH 2/2] fix: minor fixes --- package.json | 9 +++++---- src/generators/TypescriptInterfaceGenerator.js | 15 +++++++++------ .../TypescriptInterfaceGenerator.test.js | 8 ++++---- templates/typescript/interface.ts | 8 +++++--- yarn.lock | 10 +++++----- 5 files changed, 28 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 697edd20..a85bdf8b 100644 --- a/package.json +++ b/package.json @@ -37,19 +37,20 @@ "jest-light-runner": "^0.3.0", "lint-staged": "^13.0.0", "start-server-and-test": "^1.14.0", - "tmp": "^0.2.1" + "tmp": "^0.2.0" }, "dependencies": { "@api-platform/api-doc-parser": "^0.15.0", "@babel/runtime": "^7.0.0", "chalk": "^5.0.0", "commander": "^9.4.0", - "handlebars": "^4.0.12", + "esutils": "^2.0.0", + "handlebars": "^4.0.0", "handlebars-helpers": "^0.10.0", "isomorphic-fetch": "^3.0.0", - "mkdirp": "^1.0.4", + "mkdirp": "^1.0.0", "prettier": "^2.7.0", - "sprintf-js": "^1.1.1" + "sprintf-js": "^1.1.0" }, "scripts": { "prepare": "husky install", diff --git a/src/generators/TypescriptInterfaceGenerator.js b/src/generators/TypescriptInterfaceGenerator.js index 361f55bf..930af81f 100644 --- a/src/generators/TypescriptInterfaceGenerator.js +++ b/src/generators/TypescriptInterfaceGenerator.js @@ -1,3 +1,5 @@ +import handlebars from "handlebars"; +import { keyword } from "esutils"; import BaseGenerator from "./BaseGenerator.js"; export default class TypescriptInterfaceGenerator extends BaseGenerator { @@ -5,6 +7,10 @@ export default class TypescriptInterfaceGenerator extends BaseGenerator { super(params); this.registerTemplates(`typescript/`, ["interface.ts"]); + + handlebars.registerHelper("isIdentifier", (name) => + keyword.isIdentifierES5(name) + ); } help(resource) { @@ -18,19 +24,16 @@ export default class TypescriptInterfaceGenerator extends BaseGenerator { const dest = `${dir}/interfaces`; const { fields, imports } = this.parseFields(resource); - const normalizeJs = (name) => name.replace(/-/g, "_"); + const normalizeTypeName = (name) => name.replace(/-/g, "_"); this.createDir(dest, false); this.createFile( "interface.ts", `${dest}/${resource.title.toLowerCase()}.ts`, { - fields: fields.map((f) => ({ - ...f, - name: normalizeJs(f.name), - })), + fields, imports, - name: normalizeJs(resource.title), + name: normalizeTypeName(resource.title), } ); } diff --git a/src/generators/TypescriptInterfaceGenerator.test.js b/src/generators/TypescriptInterfaceGenerator.test.js index f61705a9..66b744dd 100644 --- a/src/generators/TypescriptInterfaceGenerator.test.js +++ b/src/generators/TypescriptInterfaceGenerator.test.js @@ -174,9 +174,9 @@ test("Generate a typescript interface with an explicit id field in the readableF tmpobj.removeCallback(); }); -test("Generate a typescript interface with normalized JS identifiers", () => { +test("Generate a typescript interface with invalid JS identifiers for fields and title", () => { const generator = new TypescriptInterfaceGenerator({ - templateDirectory: `${__dirname}/../../templates`, + templateDirectory: `${dirname}/../../templates`, }); const tmpobj = tmp.dirSync({ unsafeCleanup: true }); @@ -220,8 +220,8 @@ test("Generate a typescript interface with normalized JS identifiers", () => { const res = `export interface Foo_foo { "@id"?: string; - foo_foo: any; - readonly bar_bar: string; + "foo-foo": any; + readonly "bar-bar": string; readonly id?: string; } `; diff --git a/templates/typescript/interface.ts b/templates/typescript/interface.ts index 04a5178f..68bbabf5 100644 --- a/templates/typescript/interface.ts +++ b/templates/typescript/interface.ts @@ -1,6 +1,8 @@ export interface {{{name}}} { '@id'?: string; -{{#each fields}} - {{#if readonly}} readonly{{/if}} {{{name}}}{{#if notrequired}}?{{/if}}: {{{type}}}; -{{/each}} + {{#each fields}} + {{#if readonly}} readonly{{/if}} {{#unless (isIdentifier name)}}"{{/unless}} + {{~ name ~}} + {{#unless (isIdentifier name)}}"{{/unless}}{{#if notrequired}}?{{/if}}: {{{type}}}; + {{/each}} } diff --git a/yarn.lock b/yarn.lock index 82eae736..b12f393e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2809,7 +2809,7 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -esutils@^2.0.2: +esutils@^2.0.0, esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== @@ -3283,7 +3283,7 @@ handlebars-utils@^1.0.2, handlebars-utils@^1.0.4, handlebars-utils@^1.0.6: kind-of "^6.0.0" typeof-article "^0.1.1" -handlebars@^4.0.11, handlebars@^4.0.12: +handlebars@^4.0.0, handlebars@^4.0.11: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== @@ -4608,7 +4608,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^1.0.4: +mkdirp@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -5454,7 +5454,7 @@ split@0.3: dependencies: through "2" -sprintf-js@^1.1.1: +sprintf-js@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== @@ -5683,7 +5683,7 @@ time-stamp@^1.0.1: resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" integrity sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw== -tmp@^0.2.1: +tmp@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==