Skip to content

Commit 166eba5

Browse files
committed
feat: add option to specify serverPath to write route to server configuration
1 parent cf23421 commit 166eba5

File tree

4 files changed

+128
-39
lines changed

4 files changed

+128
-39
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"handlebars-helpers": "^0.10.0",
4242
"isomorphic-fetch": "^2.2.1",
4343
"mkdirp": "^0.5.1",
44+
"recast": "^0.18.1",
4445
"sprintf-js": "^1.1.1"
4546
},
4647
"scripts": {

src/generators/NextGenerator.js

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import chalk from "chalk";
22
import fs from "fs";
33
import BaseGenerator from "./BaseGenerator";
4+
import { parse, print, types } from "recast";
45

56
export default class NextGenerator extends BaseGenerator {
67
constructor(params) {
78
super(params);
89

10+
this.routeAddedtoServer = false;
911
this.registerTemplates(`next/`, [
1012
// components
1113
"components/common/ReferenceLinks.tsx",
@@ -29,7 +31,7 @@ export default class NextGenerator extends BaseGenerator {
2931
]);
3032
}
3133

32-
checkDependencies(dir) {
34+
checkDependencies(dir, serverPath) {
3335
const dependencies = this.getTargetDependencies(dir);
3436

3537
if (!dependencies.length) {
@@ -51,11 +53,23 @@ export default class NextGenerator extends BaseGenerator {
5153
)
5254
);
5355
}
56+
57+
if (serverPath) {
58+
if (!fs.existsSync(serverPath)) {
59+
console.log(chalk.red("Express server file doesn't exists."));
60+
return;
61+
}
62+
63+
const { mode } = fs.statSync(serverPath);
64+
if ("200" !== (mode & parseInt("200", 8)).toString(8)) {
65+
console.log(chalk.red("Express server file is not writable."));
66+
}
67+
}
5468
}
5569

5670
checkImports(directory, imports, extension = ".ts") {
5771
imports.forEach(({ file }) => {
58-
if (!fs.existsSync(directory + file + extension)) {
72+
if (fs.existsSync(directory + file + extension)) {
5973
return;
6074
}
6175

@@ -79,18 +93,16 @@ export default class NextGenerator extends BaseGenerator {
7993
this.checkImports(`${dir}/interfaces/`, imports);
8094

8195
// server route configuration
82-
const lc = resource.title.toLowerCase();
83-
console.log("Paste the following route to your server configuration file:");
84-
console.log(
85-
chalk.green(`
86-
server.get('/${lc}/:id', (req, res) => {
87-
return app.render(req, res, '/${lc}', { id: req.params.id })
88-
});
89-
`)
90-
);
96+
if (!this.routeAddedtoServer) {
97+
const lc = resource.title.toLowerCase();
98+
console.log(
99+
"Paste the following route to your server configuration file:"
100+
);
101+
console.log(chalk.green(this.getShowRoute(lc)));
102+
}
91103
}
92104

93-
generate(api, resource, dir) {
105+
generate(api, resource, dir, serverPath) {
94106
const lc = resource.title.toLowerCase();
95107
const ucf = this.ucFirst(resource.title);
96108
const { fields, imports } = this.parseFields(resource);
@@ -157,6 +169,48 @@ server.get('/${lc}/:id', (req, res) => {
157169

158170
// API config
159171
this.createEntrypoint(api.entrypoint, `${dir}/config/entrypoint.ts`);
172+
173+
if (serverPath) {
174+
this.createExpressRoute(serverPath, lc, this.getShowRoute(lc));
175+
}
176+
}
177+
178+
getShowRoute(name) {
179+
return `server.get('/${name}/:id', (req, res) => {
180+
return app.render(req, res, '/${name}', { id: req.params.id })
181+
});`;
182+
}
183+
184+
createExpressRoute(path, resourceName, toInsert) {
185+
const content = fs.readFileSync(path, "utf-8");
186+
const code = parse(content);
187+
const { namedTypes } = types;
188+
189+
types.visit(code, {
190+
visitExpressionStatement: function(path) {
191+
const args = path.value.expression.arguments;
192+
if (
193+
2 === args.length &&
194+
namedTypes.Literal.check(args[0]) &&
195+
"*" === args[0].value &&
196+
namedTypes.ArrowFunctionExpression.check(args[1])
197+
) {
198+
// insert route before "*" route
199+
path.parent.value.body.splice(path.name, 0, toInsert);
200+
201+
return false;
202+
}
203+
204+
this.traverse(path);
205+
}
206+
});
207+
208+
fs.writeFileSync(path, print(code).code);
209+
console.log(
210+
chalk.green("'Show' route for %s has been added to your server"),
211+
resourceName
212+
);
213+
this.routeAddedtoServer = true;
160214
}
161215

162216
getDescription(field) {

src/index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ program
2424
)
2525
.option(
2626
"-g, --generator [generator]",
27-
'The generator to use, one of "react", "react-native", "vue", "admin-on-rest", "typescript"',
27+
'The generator to use, one of "react", "react-native", "vue", "admin-on-rest", "typescript", "next"',
2828
"react"
2929
)
3030
.option(
@@ -33,6 +33,10 @@ program
3333
`${__dirname}/../templates/`
3434
)
3535
.option("-f, --format [hydra|swagger]", '"hydra" or "swagger', "hydra")
36+
.option(
37+
"-s, --server-path [serverPath]",
38+
"Path to express server file to allow route dynamic addition (Next.js generator only)"
39+
)
3640
.parse(process.argv);
3741

3842
if (
@@ -59,6 +63,7 @@ const generator = generators(program.generator)({
5963
const resourceToGenerate = program.resource
6064
? program.resource.toLowerCase()
6165
: null;
66+
const serverPath = program.serverPath ? program.serverPath.toLowerCase() : null;
6267

6368
const parser = entrypointWithSlash => {
6469
const parseDocumentation =
@@ -70,7 +75,7 @@ const parser = entrypointWithSlash => {
7075
};
7176

7277
// check generator dependencies
73-
generator.checkDependencies(outputDirectory);
78+
generator.checkDependencies(outputDirectory, serverPath);
7479

7580
parser(entrypointWithSlash)
7681
.then(ret => {
@@ -94,7 +99,7 @@ parser(entrypointWithSlash)
9499
resource.readableFields = filterDeprecated(resource.readableFields);
95100
resource.writableFields = filterDeprecated(resource.writableFields);
96101

97-
generator.generate(ret.api, resource, outputDirectory);
102+
generator.generate(ret.api, resource, outputDirectory, serverPath);
98103

99104
return resource;
100105
})

yarn.lock

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
# yarn lockfile v1
33

44

5-
"@api-platform/api-doc-parser@^0.5.0":
6-
version "0.5.0"
7-
resolved "https://registry.yarnpkg.com/@api-platform/api-doc-parser/-/api-doc-parser-0.5.0.tgz#c8d2d860937d5c795577dec33f7914567f5ec9eb"
8-
integrity sha512-P5JwdVLji2nb/llO+usY6IGgkLNBcGsVFON7k3ube8uePz2KRrjyslKUsrmSKUW1aoUwSke9NXQUh600er8Ukg==
5+
"@api-platform/api-doc-parser@^0.7.2":
6+
version "0.7.2"
7+
resolved "https://registry.yarnpkg.com/@api-platform/api-doc-parser/-/api-doc-parser-0.7.2.tgz#c5ca5913fa6ee319016a635df5225e0db5ecc9ab"
8+
integrity sha512-FHzAldq1/ZZZhRyI8sgfxIrf3NtKLNgaW6P8Z12cjK3qWDuYCjsQZ1H2Z4WGZk0tGhDxA3lVJXcw4HHD5kjTrQ==
99
dependencies:
1010
babel-runtime "^6.23.0"
11-
jsonld "^0.4.11"
11+
jsonld "^1.5.0"
1212
lodash.get "^4.4.2"
13+
lodash.uniq "^4.5.0"
1314

1415
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35":
1516
version "7.0.0"
@@ -518,6 +519,11 @@ assign-symbols@^1.0.0:
518519
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
519520
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
520521

522+
523+
version "0.13.1"
524+
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.1.tgz#9461428a270c5a27fda44b738dd3bab2e9353003"
525+
integrity sha512-b+EeK0WlzrSmpMw5jktWvQGxblpWnvMrV+vOp69RLjzGiHwWV0vgq75DPKtUjppKni3yWwSW8WLGV3Ch/XIWcQ==
526+
521527
astral-regex@^1.0.0:
522528
version "1.0.0"
523529
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
@@ -1911,11 +1917,6 @@ es-to-primitive@^1.2.0:
19111917
is-date-object "^1.0.1"
19121918
is-symbol "^1.0.2"
19131919

1914-
es6-promise@^2.0.0:
1915-
version "2.3.0"
1916-
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-2.3.0.tgz#96edb9f2fdb01995822b263dd8aadab6748181bc"
1917-
integrity sha1-lu258v2wGZWCKyY92KratnSBgbw=
1918-
19191920
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
19201921
version "1.0.5"
19211922
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
@@ -2063,7 +2064,7 @@ esprima@^3.1.3:
20632064
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
20642065
integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
20652066

2066-
esprima@^4.0.0:
2067+
esprima@^4.0.0, esprima@~4.0.0:
20672068
version "4.0.1"
20682069
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
20692070
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
@@ -3590,14 +3591,14 @@ json5@^0.5.1:
35903591
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
35913592
integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
35923593

3593-
jsonld@^0.4.11:
3594-
version "0.4.12"
3595-
resolved "https://registry.yarnpkg.com/jsonld/-/jsonld-0.4.12.tgz#a02f205d5341414df1b6d8414f1b967a712073e8"
3596-
integrity sha1-oC8gXVNBQU3xtthBTxuWenEgc+g=
3594+
jsonld@^1.5.0:
3595+
version "1.6.2"
3596+
resolved "https://registry.yarnpkg.com/jsonld/-/jsonld-1.6.2.tgz#d81620dccf75fd7bc7501709eeec5da77ecc45e9"
3597+
integrity sha512-eMzFHqhF2kPMrMUjw8+Lz9IF1QkrxTOIfVndkP/OpuoZs31VdDtfDs8mLa5EOC/ROdemFTQGLdYPZbRtmMe2Yw==
35973598
dependencies:
3598-
es6-promise "^2.0.0"
3599-
pkginfo "~0.4.0"
3600-
request "^2.61.0"
3599+
rdf-canonize "^1.0.2"
3600+
request "^2.88.0"
3601+
semver "^5.6.0"
36013602
xmldom "0.1.19"
36023603

36033604
jsprim@^1.2.2:
@@ -3710,6 +3711,11 @@ lodash.sortby@^4.7.0:
37103711
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
37113712
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
37123713

3714+
lodash.uniq@^4.5.0:
3715+
version "4.5.0"
3716+
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
3717+
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
3718+
37133719
lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5:
37143720
version "4.17.11"
37153721
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
@@ -3978,6 +3984,11 @@ node-fetch@^1.0.1:
39783984
encoding "^0.1.11"
39793985
is-stream "^1.0.1"
39803986

3987+
node-forge@^0.8.1:
3988+
version "0.8.4"
3989+
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.8.4.tgz#d6738662b661be19e2711ef01aa3b18212f13030"
3990+
integrity sha512-UOfdpxivIYY4g5tqp5FNRNgROVNxRACUxxJREntJLFaJr1E0UEqFtUIk0F/jYx/E+Y6sVXd0KDi/m5My0yGCVw==
3991+
39813992
node-int64@^0.4.0:
39823993
version "0.4.0"
39833994
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
@@ -4340,11 +4351,6 @@ pkg-dir@^2.0.0:
43404351
dependencies:
43414352
find-up "^2.1.0"
43424353

4343-
pkginfo@~0.4.0:
4344-
version "0.4.1"
4345-
resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff"
4346-
integrity sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=
4347-
43484354
pluralize@^7.0.0:
43494355
version "7.0.0"
43504356
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
@@ -4450,6 +4456,14 @@ rc@^1.2.7:
44504456
minimist "^1.2.0"
44514457
strip-json-comments "~2.0.1"
44524458

4459+
rdf-canonize@^1.0.2:
4460+
version "1.0.3"
4461+
resolved "https://registry.yarnpkg.com/rdf-canonize/-/rdf-canonize-1.0.3.tgz#71dc56bb808a39d12e3ca17674c15f881cad648a"
4462+
integrity sha512-piLMOB5Q6LJSVx2XzmdpHktYVb8TmVTy8coXJBFtdkcMC96DknZOuzpAYqCWx2ERZX7xEW+mMi8/wDuMJS/95w==
4463+
dependencies:
4464+
node-forge "^0.8.1"
4465+
semver "^5.6.0"
4466+
44534467
read-pkg-up@^1.0.1:
44544468
version "1.0.1"
44554469
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
@@ -4513,6 +4527,16 @@ realpath-native@^1.0.0:
45134527
dependencies:
45144528
util.promisify "^1.0.0"
45154529

4530+
recast@^0.18.1:
4531+
version "0.18.1"
4532+
resolved "https://registry.yarnpkg.com/recast/-/recast-0.18.1.tgz#dd1788cfa403be8be06a10f201317f881adc602b"
4533+
integrity sha512-Ri42yIOwHetqKgEhQSS4N1B9wSLn+eYcyLoQfuSpvd661Jty1Q3P0FXkzjIQ9XxTN+3+kRu1JFXbRmUCUmde5Q==
4534+
dependencies:
4535+
ast-types "0.13.1"
4536+
esprima "~4.0.0"
4537+
private "^0.1.8"
4538+
source-map "~0.6.1"
4539+
45164540
regenerate@^1.2.1:
45174541
version "1.4.0"
45184542
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
@@ -4631,7 +4655,7 @@ request-promise-native@^1.0.5:
46314655
stealthy-require "^1.1.0"
46324656
tough-cookie ">=2.3.3"
46334657

4634-
request@^2.61.0, request@^2.87.0:
4658+
request@^2.87.0, request@^2.88.0:
46354659
version "2.88.0"
46364660
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
46374661
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
@@ -4788,6 +4812,11 @@ self-closing-tags@^1.0.1:
47884812
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
47894813
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
47904814

4815+
semver@^5.6.0:
4816+
version "5.7.0"
4817+
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
4818+
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
4819+
47914820
set-blocking@^2.0.0, set-blocking@~2.0.0:
47924821
version "2.0.0"
47934822
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"

0 commit comments

Comments
 (0)