From db1d4c5ae40b761442cba2b1517919e7249af437 Mon Sep 17 00:00:00 2001 From: Colin Eberhardt Date: Tue, 24 Jan 2023 15:36:23 +0000 Subject: [PATCH] feat: allow specification of module style (esm / cjs) * feat: allow specification of module style (es6 / cjs) * chore: rename module format options * chore: fix linting issues * docs: updated readme * fix: remove .js extension from cjs require statements --- README.md | 23 +++++++++++++++++++ config.json | 6 +++++ helpers/export.js | 11 +++++++++ helpers/import.js | 15 ++++++++++++ helpers/setVarBlock.js | 9 ++++++++ partials/modelIncludes.handlebars | 5 ++-- template/api.js.handlebars | 11 +++++---- template/configuration.js.handlebars | 4 +--- template/{fetch.js => fetch.js.handlebars} | 2 +- template/info.js.handlebars | 4 ++-- template/model.js.handlebars | 2 +- ...lder.js => parameterBuilder.js.handlebars} | 6 ++--- .../{request.js => request.js.handlebars} | 2 +- template/serializer.js.handlebars | 4 ++-- 14 files changed, 84 insertions(+), 20 deletions(-) create mode 100644 config.json create mode 100644 helpers/export.js create mode 100644 helpers/import.js create mode 100644 helpers/setVarBlock.js rename template/{fetch.js => fetch.js.handlebars} (88%) rename template/{parameterBuilder.js => parameterBuilder.js.handlebars} (94%) rename template/{request.js => request.js.handlebars} (98%) diff --git a/README.md b/README.md index 50f5590..6cacb0d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,16 @@ https://github.com/ScottLogic/openapi-forge The client API it generates is suitable for running in the browser (after being bundled appropriately), or via node. The generated code uses the Fetch API, and as a result you'll need to use node v18 or greater. +- [OpenAPI Forge - JavaScript](#openapi-forge---javascript) + - [Example](#example) + - [Running with node (\>= v18)](#running-with-node--v18) + - [Running in the browser](#running-in-the-browser) + - [Configuration](#configuration) + - [Development](#development) + - [Running](#running) + - [Testing](#testing) + - [Linting](#linting) + ## Example You should consult the [OpenAPI Forge](https://github.com/ScottLogic/openapi-forge) repository for a complete user guide. The following is a very brief example that quikcly gets you up-and-running with this generator. @@ -73,6 +83,19 @@ Next create a simple HTML file that loads this script: Load the above page in a browser and you should see `Fido` logged to the console. +## Configuration + +OpenAPI Forge is opinionated in its approach, we don't provide a vast range of configuration options, just the essentials! You can list the generator-specific configuration options by running the `generate-options` command as follows: + +``` +% openapi-forge generator-options openapi-forge-javascript +This generator has a number of additional options which can be supplied when executing the 'forge' command. + +Options: + --generator.moduleFormat The module format to use for the generated code. (choices: "commonjs", "esmodule", + default: "commonjs") +``` + ## Development The OpenAPI Forge project [details the process for creating a new generator](https://github.com/ScottLogic/openapi-forge#generator-development). The documentation gives a few generator-specific instructions. diff --git a/config.json b/config.json new file mode 100644 index 0000000..5c875b0 --- /dev/null +++ b/config.json @@ -0,0 +1,6 @@ +{ + "moduleFormat": { + "choices": ["commonjs", "esmodule"], + "description": "The module format to use for the generated code." + } +} diff --git a/helpers/export.js b/helpers/export.js new file mode 100644 index 0000000..45523fe --- /dev/null +++ b/helpers/export.js @@ -0,0 +1,11 @@ +function exportHelper(isDefault = true) { + switch (process.env.moduleFormat) { + case "esmodule": + return `export ${isDefault ? "default " : ""}`; + case "commonjs": + default: + return `module.exports = `; + } +} + +module.exports = exportHelper; diff --git a/helpers/import.js b/helpers/import.js new file mode 100644 index 0000000..0e68656 --- /dev/null +++ b/helpers/import.js @@ -0,0 +1,15 @@ +function importHelper(type, file) { + switch (process.env.moduleFormat) { + case "esmodule": + return `import ${type} from "./${file}"`; + case "commonjs": + default: { + if (type && type.startsWith("* as")) { + type = type.replace("* as", ""); + } + return `const ${type} = require("./${file}")`; + } + } +} + +module.exports = importHelper; diff --git a/helpers/setVarBlock.js b/helpers/setVarBlock.js new file mode 100644 index 0000000..c30d0f6 --- /dev/null +++ b/helpers/setVarBlock.js @@ -0,0 +1,9 @@ +function setVar(varName, options) { + if (!options.data.root) { + options.data.root = {}; + } + options.data.root[varName] = options.fn(this); + return ""; +} + +module.exports = setVar; diff --git a/partials/modelIncludes.handlebars b/partials/modelIncludes.handlebars index eab439f..77f2874 100644 --- a/partials/modelIncludes.handlebars +++ b/partials/modelIncludes.handlebars @@ -1,5 +1,6 @@ {{#if models }} -const { +{{#setVarBlock "imports"}}{ {{#each models}}{{@key}}, {{/each}} -} = require("./model"); +}{{/setVarBlock}} +{{{import @root.imports "model"}}}; {{/if}} \ No newline at end of file diff --git a/template/api.js.handlebars b/template/api.js.handlebars index b514591..96a8846 100644 --- a/template/api.js.handlebars +++ b/template/api.js.handlebars @@ -1,9 +1,10 @@ -const Configuration = require("./configuration"); + {{>modelIncludes models=components.schemas options=_options}} {{>modelIncludes models=components.inlineObjects options=_options}} -const request = require("./request"); -const ParameterBuilder = require("./parameterBuilder"); -const { deserialize, serialize } = require("./serializer"); +{{{import "Configuration" "configuration"}}}; +{{{import "request" "request"}}}; +{{{import "ParameterBuilder" "parameterBuilder"}}}; +{{{import "{deserialize, serialize}" "serializer"}}}; /** * {{_info.title}} @@ -67,4 +68,4 @@ class Api{{_tag.name}} { {{/each}} } -module.exports = Api{{_tag.name}}; +{{{export}}} Api{{_tag.name}}; diff --git a/template/configuration.js.handlebars b/template/configuration.js.handlebars index 7991ce9..7aa6d7a 100644 --- a/template/configuration.js.handlebars +++ b/template/configuration.js.handlebars @@ -1,5 +1,3 @@ -const { RequestParameters } = require("./request"); - /** * Configures the API * @@ -29,4 +27,4 @@ class Configuration { } } -module.exports = Configuration; \ No newline at end of file +{{{export}}} Configuration; \ No newline at end of file diff --git a/template/fetch.js b/template/fetch.js.handlebars similarity index 88% rename from template/fetch.js rename to template/fetch.js.handlebars index 2244cb5..aaf598c 100644 --- a/template/fetch.js +++ b/template/fetch.js.handlebars @@ -6,4 +6,4 @@ async function transport(params) { return await response.json(); } -module.exports = transport; +{{{export}}} transport; diff --git a/template/info.js.handlebars b/template/info.js.handlebars index 913d7d8..4b54c13 100644 --- a/template/info.js.handlebars +++ b/template/info.js.handlebars @@ -1,4 +1,4 @@ -export const Info = { +const Info = { {{#each _info}} {{@key}}: {{#if (isObj this) }} @@ -12,4 +12,4 @@ export const Info = { {{/each}} }; -module.exports = Info; +{{{export}}} Info; diff --git a/template/model.js.handlebars b/template/model.js.handlebars index 55a86c5..efed820 100644 --- a/template/model.js.handlebars +++ b/template/model.js.handlebars @@ -17,7 +17,7 @@ const models = [ {{/each}} ]; -module.exports = { +{{{export false}}} { {{#each components.schemas}} {{@key}}, {{/each}} diff --git a/template/parameterBuilder.js b/template/parameterBuilder.js.handlebars similarity index 94% rename from template/parameterBuilder.js rename to template/parameterBuilder.js.handlebars index a7b8cb9..65807ae 100644 --- a/template/parameterBuilder.js +++ b/template/parameterBuilder.js.handlebars @@ -1,5 +1,5 @@ -const model = require("./model"); -const { serialize } = require("./serializer"); +{{{import "* as model" "model"}}}; +{{{import "{ serialize }" "serializer"}}}; // builds the request parameters from the API method arguments, handling // serialisation and 'exploding' of object properties @@ -74,4 +74,4 @@ class ParameterBuilder { } } -module.exports = ParameterBuilder; +{{{export}}} ParameterBuilder; diff --git a/template/request.js b/template/request.js.handlebars similarity index 98% rename from template/request.js rename to template/request.js.handlebars index 9f84253..850adec 100644 --- a/template/request.js +++ b/template/request.js.handlebars @@ -60,4 +60,4 @@ async function request(config, path, method, params) { return await config.transport(requestParams); } -module.exports = request; +{{{export}}} request; diff --git a/template/serializer.js.handlebars b/template/serializer.js.handlebars index 7d4e424..ddb058c 100644 --- a/template/serializer.js.handlebars +++ b/template/serializer.js.handlebars @@ -1,4 +1,4 @@ -const model = require("./model"); +{{{import "* as model" "model"}}}; // takes a JSON response and deserializes it into the required model objects / types function deserialize(json, type) { @@ -50,6 +50,6 @@ function serialize(item, type) { return typeof item === "object" ? JSON.stringify(item) : item.toString(); } -module.exports = { +{{{export false}}} { deserialize, serialize };