@simitgroup/simpleapp-generator 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.prettierrc +6 -0
  2. package/LICENSE +201 -0
  3. package/README.md +668 -0
  4. package/definations/person.pes.jsonschema.json +84 -0
  5. package/definations/salesinvoice.si.jsonschema.json +84 -0
  6. package/dist/app.module.ts +14 -0
  7. package/dist/constant.js +6 -0
  8. package/dist/constant.js.map +1 -0
  9. package/dist/createproject.js +123 -0
  10. package/dist/createproject.js.map +1 -0
  11. package/dist/generate.js +225 -0
  12. package/dist/generate.js.map +1 -0
  13. package/dist/index.js +65 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/libs.js +15 -0
  16. package/dist/libs.js.map +1 -0
  17. package/dist/processors/jsonschemabuilder.js +116 -0
  18. package/dist/processors/jsonschemabuilder.js.map +1 -0
  19. package/dist/type.js +13 -0
  20. package/dist/type.js.map +1 -0
  21. package/package.json +44 -0
  22. package/sampleconfig.json +6 -0
  23. package/src/constant.ts +2 -0
  24. package/src/createproject.ts +96 -0
  25. package/src/generate.ts +254 -0
  26. package/src/index.ts +73 -0
  27. package/src/libs.ts +14 -0
  28. package/src/processors/jsonschemabuilder.ts +137 -0
  29. package/src/type.ts +42 -0
  30. package/templates/SimpleAppClient.eta +111 -0
  31. package/templates/SimpleAppController.eta +66 -0
  32. package/templates/SimpleAppService.eta +134 -0
  33. package/templates/app.module.eta +15 -0
  34. package/templates/app.vue.eta +21 -0
  35. package/templates/basic/apiclient.eta +56 -0
  36. package/templates/basic/apischema.eta +29 -0
  37. package/templates/basic/backend.config.eta +1 -0
  38. package/templates/basic/beforesave.eta +7 -0
  39. package/templates/basic/controller.eta +103 -0
  40. package/templates/basic/controller2.eta +86 -0
  41. package/templates/basic/frontend.config.eta +1 -0
  42. package/templates/basic/jsonschema.eta +6 -0
  43. package/templates/basic/model-converter.etabackup +21 -0
  44. package/templates/basic/model.eta +35 -0
  45. package/templates/basic/module.eta +20 -0
  46. package/templates/basic/readme.eta +3 -0
  47. package/templates/basic/service.eta +32 -0
  48. package/templates/basic/service.etabackupe +106 -0
  49. package/templates/basic/type.eta +27 -0
  50. package/templates/basic/type.etabackup +23 -0
  51. package/templates/basic/uischema.eta +13 -0
  52. package/templates/nest.env.eta +5 -0
  53. package/templates/nest.main.eta +20 -0
  54. package/templates/nuxt.env.eta +2 -0
  55. package/tsconfig.json +17 -0
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readJsonSchemaBuilder = void 0;
4
+ const libs_1 = require("../libs");
5
+ // import { ConflictException } from '@nestjs/common';
6
+ const type_1 = require("../type");
7
+ let allmodels = {};
8
+ const readJsonSchemaBuilder = (doctype, docname, jsondata) => {
9
+ allmodels = {};
10
+ const validateddata = Object.assign({}, jsondata);
11
+ let schema;
12
+ if (jsondata && jsondata.type == 'object') {
13
+ //no _id then need add
14
+ // console.log(jsondata)
15
+ schema = processObject(doctype, docname, jsondata);
16
+ // console.log("schema",schema)
17
+ }
18
+ else if (jsondata.type == 'array') {
19
+ throw (`unsupport array type for ${docname}.${doctype}`);
20
+ }
21
+ return allmodels;
22
+ };
23
+ exports.readJsonSchemaBuilder = readJsonSchemaBuilder;
24
+ const processObject = (doctype, docname, jsondata) => {
25
+ if (!jsondata['properties']) {
26
+ throw ("Invalid json schema {doctype}.{docname}, no 'properties' defined");
27
+ }
28
+ //ensure some field exists, also override it
29
+ jsondata.properties['_id'] = { type: 'string', description: 'Control value, dont edit it', };
30
+ jsondata.properties['doctype'] = { type: 'string', default: doctype, examples: [doctype], description: 'Control value, dont edit it', };
31
+ return genSchema((0, libs_1.capitalizeFirstLetter)(docname), 'object', jsondata.properties, jsondata['required'] ? jsondata['required'] : []);
32
+ };
33
+ const genSchema = (docname, schematype, jsondata, //JSONSchema7,//|JsonSchemaProperties|JSONSchema7Definition,
34
+ requiredlist) => {
35
+ var _a, _b;
36
+ const newmodel = {};
37
+ const props = Object.getOwnPropertyNames(jsondata);
38
+ // console.log('==== requirelist', requiredlist);
39
+ for (let i = 0; i < props.length; i++) {
40
+ const key = props[i];
41
+ //below is Object.assign use for force datatype compatibility
42
+ const obj = {};
43
+ Object.assign(obj, jsondata[key]);
44
+ const objectitem = {};
45
+ Object.assign(objectitem, obj.items);
46
+ // Object.assign(objtmp,jsondata?[key]:{});
47
+ const isrequired = requiredlist && requiredlist.includes(key);
48
+ // console.log('----', key, isrequired, obj);
49
+ const newName = docname + (0, libs_1.capitalizeFirstLetter)(key);
50
+ // console.log(key);
51
+ //need create sub model
52
+ // console.log("----",key,obj.type,objectitem.type)
53
+ if (obj.type == 'object') {
54
+ genSchema(newName, obj.type, obj.properties, obj.required);
55
+ newmodel[key] = newName;
56
+ }
57
+ else if (obj.type == 'array' && obj.items && (objectitem === null || objectitem === void 0 ? void 0 : objectitem.type) == 'object') {
58
+ //array need submodel
59
+ // console.log("======",newName,key)
60
+ genSchema(newName, obj.type, objectitem === null || objectitem === void 0 ? void 0 : objectitem.properties, obj.required);
61
+ newmodel[key] = [newName];
62
+ }
63
+ else if (obj.type == 'array' && (objectitem === null || objectitem === void 0 ? void 0 : objectitem.type) != 'object') {
64
+ //array need submodel
65
+ // genSchema(newName, obj.type, obj.items.properties);
66
+ const objecttype = (_b = (_a = objectitem.type) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : 'string';
67
+ newmodel[key] = [objecttype];
68
+ }
69
+ else {
70
+ newmodel[key] = getField(key, obj, isrequired);
71
+ // console.log('--------newmodel', newmodel[key]);
72
+ }
73
+ }
74
+ allmodels[docname] = { type: schematype, model: newmodel };
75
+ return newmodel;
76
+ };
77
+ const getField = (fieldname, obj, isrequired) => {
78
+ let datatype = type_1.Fieldtypes.string;
79
+ let format = obj.format;
80
+ if (obj.type == 'integer') {
81
+ datatype = type_1.Fieldtypes.number;
82
+ format = 'integer';
83
+ }
84
+ const f = {
85
+ type: datatype,
86
+ // oritype: obj.type,
87
+ required: isrequired,
88
+ };
89
+ if (obj.title)
90
+ f.title = obj.title;
91
+ if (obj.description)
92
+ f.description = obj.description;
93
+ if (obj.format)
94
+ f.format = obj.format;
95
+ if (obj.example)
96
+ f.example = obj.example;
97
+ if (obj.examples)
98
+ f.examples = obj.examples;
99
+ if (obj.default) {
100
+ f.default = obj.default;
101
+ }
102
+ else {
103
+ if (f.type == 'string')
104
+ f.default = '';
105
+ else if (f.type == 'number' || f.type == 'integer')
106
+ f.default = 0;
107
+ else if (f.type == 'boolean')
108
+ f.default = false;
109
+ else if (f.type == 'array')
110
+ f.default = [];
111
+ else
112
+ f.default = {};
113
+ }
114
+ return f;
115
+ };
116
+ //# sourceMappingURL=jsonschemabuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonschemabuilder.js","sourceRoot":"","sources":["../../src/processors/jsonschemabuilder.ts"],"names":[],"mappings":"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"}
package/dist/type.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Fieldtypes = void 0;
4
+ var Fieldtypes;
5
+ (function (Fieldtypes) {
6
+ Fieldtypes["string"] = "string";
7
+ Fieldtypes["object"] = "object";
8
+ Fieldtypes["array"] = "array";
9
+ Fieldtypes["boolean"] = "boolean";
10
+ Fieldtypes["integer"] = "integer";
11
+ Fieldtypes["number"] = "number";
12
+ })(Fieldtypes || (exports.Fieldtypes = Fieldtypes = {}));
13
+ //# sourceMappingURL=type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type.js","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":";;;AAIA,IAAY,UAOX;AAPD,WAAY,UAAU;IACpB,+BAAmB,CAAA;IACnB,+BAAmB,CAAA;IACnB,6BAAiB,CAAA;IACjB,iCAAqB,CAAA;IACrB,iCAAqB,CAAA;IACrB,+BAAmB,CAAA;AACrB,CAAC,EAPW,UAAU,0BAAV,UAAU,QAOrB"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@simitgroup/simpleapp-generator",
3
+ "version": "1.0.1",
4
+ "description": "frontend nuxtjs and backend nests code generator using jsonschema",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "generate": "ts-node src/index.ts -c ../sampleconfig.json; pnpm exec prettier ./backend --write;pnpm exec prettier ./frontend --write",
8
+ "build": "npx tsc",
9
+ "test": "echo \"Error: no test specified\" && exit 1"
10
+ },
11
+ "keywords": [],
12
+ "author": "Ks Tan",
13
+ "license": "ISC",
14
+ "repository": {"type": "git", "url": "git://github.com/SIMITGROUP/simpleapp-generator.git"},
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "dependencies": {
19
+ "@nestjs/config": "^3.0.0",
20
+ "@nestjs/mongoose": "^10.0.1",
21
+ "@nestjs/swagger": "^7.1.8",
22
+ "ajv": "^8.12.0",
23
+ "ajv-formats": "^2.1.1",
24
+ "axios": "^1.4.0",
25
+ "child_process": "^1.0.2",
26
+ "cli-color": "^2.0.3",
27
+ "commander": "^11.0.0",
28
+ "eta": "^3.1.0",
29
+ "figlet": "^1.6.0",
30
+ "fs": "0.0.1-security",
31
+ "json-schema": "^0.4.0",
32
+ "mongoose": "^7.4.4",
33
+ "path": "^0.12.7",
34
+ "tslog": "^4.9.1"
35
+ },
36
+ "bin": {
37
+ "simpleapp-generator": "./dist/index.js"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.5.2",
41
+ "prettier": "^3.0.2",
42
+ "typescript": "^5.1.6"
43
+ }
44
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "definationsFolder":"./definations",
3
+ "backendFolder":"../backend1",
4
+ "frontendFolder":"../frontend1",
5
+ "openapi3Yaml":"../openapi.yaml"
6
+ }
@@ -0,0 +1,2 @@
1
+ export const templatedir=__dirname+'/../templates'
2
+ export const srcdir=__dirname
@@ -0,0 +1,96 @@
1
+ import { exec } from "child_process";
2
+ import {writeFileSync} from 'fs'
3
+ import * as constants from './constant'
4
+ import { Logger, ILogObj } from "tslog";
5
+ const log: Logger<ILogObj> = new Logger();
6
+
7
+ const { Eta } = require('eta');
8
+
9
+ const checkNodeJS= (callback)=>{
10
+ return exec(`npx -v`,(error, stdout, stderr)=>{
11
+ if(error){
12
+ throw ("Nodejs not exists")
13
+ }else{
14
+ callback()
15
+ }
16
+ })
17
+ }
18
+
19
+ const checkNestCli = (callback)=>{
20
+ log.info("setting up nest backend")
21
+ return exec(`npx -v`, (error, stdout, stderr)=>{
22
+ if(error){
23
+ return exec(`npm i -g @nestjs/cli`, (error, stdout, stderr)=>{
24
+ callback()
25
+ })
26
+ }else{
27
+ callback()
28
+ }
29
+ })
30
+ }
31
+ export const createNuxt= (targetfolder:string,callback)=>{
32
+ log.info("setting up nuxt frontend")
33
+ checkNodeJS( ()=>{
34
+ log.info("Nodejs ok")
35
+ exec(`npx nuxi@latest init ${targetfolder}`, (error, stdout, stderr)=>{
36
+ log.info(`frontend nuxt project "${targetfolder}" created, installing module`)
37
+ exec(`cd ${targetfolder};pnpm install`, (error, stdout, stderr)=>{
38
+ //;pnpm install
39
+ if(!error){
40
+ exec(`pnpm install ajv ajv-formats axios json-schema`, (error, stdout, stderr)=>{
41
+ const eta = new Eta({views: constants.templatedir});
42
+ const variables=[]
43
+ const txtEnv = eta.render('./nuxt.env.eta', variables);
44
+ writeFileSync(`${targetfolder}/.env`, txtEnv);
45
+ log.info("nuxt project completed")
46
+ callback()
47
+ })
48
+ }else{
49
+ throw error
50
+ }
51
+
52
+ })
53
+ if(error){
54
+ log.error(stderr)
55
+ throw error
56
+ }
57
+
58
+ })
59
+ })
60
+ }
61
+
62
+ export const createNest= (targetfolder:string,callback)=>{
63
+ checkNestCli(()=>{
64
+ exec(`nest new -p pnpm ${targetfolder}`,(error, stdout, stderr)=>{
65
+ if(error)throw stderr
66
+
67
+ log.info(`creating backend project ${targetfolder}`)
68
+ exec(`cd ${targetfolder};pnpm install --save @nestjs/swagger @nestjs/mongoose mongoose ajv ajv-formats @nestjs/config`,async (error, stdout, stderr)=>{
69
+ // log.info(`dependency installed`)
70
+ if(!error){
71
+ exec(`pnpm install ajv ajv-formats axios json-schema`, (error, stdout, stderr)=>{
72
+ const eta = new Eta({views: constants.templatedir});
73
+ const variables=[]
74
+ const txtEnv = eta.render('./nest.env.eta', variables);
75
+ const txtMain = eta.render('./nest.main.eta', variables);
76
+ writeFileSync(`${targetfolder}/.env`, txtEnv);
77
+ writeFileSync(`${targetfolder}/src/main.ts`, txtMain);
78
+ log.info("nest project completed")
79
+ callback()
80
+ })
81
+ } else{
82
+ log.error(stderr)
83
+ throw error
84
+ }
85
+ })
86
+ //
87
+ })
88
+ })
89
+ //install nestjs cli
90
+ //create nest project
91
+ //install dependency
92
+ //create empty .env
93
+ //swap nestjs src/main.ts file
94
+ //try edit the configuration files
95
+ //console log http server how to start
96
+ }
@@ -0,0 +1,254 @@
1
+ // import { readFormBuilder } from './processors/formbuilder.tsa';
2
+ // import { readJsonSchemaBuilder } from './processors/jsonschemabuilder';
3
+ import * as constants from './constant'
4
+ import {readJsonSchemaBuilder} from './processors/jsonschemabuilder'
5
+ // import { compile } from 'json-schema-to-typescript';
6
+ // import { Fieldtypes, SchemaModel, ChildModels } from './type';
7
+ import { Fieldtypes, SchemaModel, ChildModels,ModuleObject } from './type'
8
+ import { Logger, ILogObj } from "tslog";
9
+ const log: Logger<ILogObj> = new Logger();
10
+ const clc = require("cli-color");
11
+
12
+
13
+ const path = require('path');
14
+ import {mkdirSync,readdir,readFileSync,writeFileSync,existsSync,copyFileSync, readdirSync} from 'fs'
15
+ const { Eta } = require('eta');
16
+ const { capitalizeFirstLetter }= require('./libs');
17
+ const extFb = '.xfb.json';
18
+ const extHfb = '.xhfb.json';
19
+ const extjsonschema = '.jsonschema.json';
20
+ let jsonschemas = {};
21
+ const docs = [];
22
+
23
+ export const initialize = (defFolder:string,backendfolder:string,frontendfolder:string) => {
24
+ prepareEnvironments(backendfolder,frontendfolder)
25
+ let activatemodules:ModuleObject[]=[]
26
+ const files = readdirSync(defFolder)
27
+ // readdir(defFolder, (err, files) => {
28
+ // files.forEach((file) => {
29
+ for(let j = 0; j< files.length;j++){
30
+ const file = files[j]
31
+ const filearr = file.split('.');
32
+ let rendertype = 'basic';
33
+ const docname = filearr[0].toLowerCase();
34
+ const doctype = filearr[1].toLowerCase();
35
+ const jsonstring = readFileSync(defFolder +path.sep+ file, 'utf-8');
36
+ const jsondata = JSON.parse(jsonstring);
37
+ let allmodels: ChildModels = {} as ChildModels;
38
+
39
+ if (file.endsWith(extjsonschema)) {
40
+ log.info(`Load `+clc.green(file))
41
+ rendertype = 'basic';
42
+ jsonschemas[docname] = jsondata;
43
+ allmodels = readJsonSchemaBuilder(doctype, docname, jsondata);
44
+ generate(docname, doctype, rendertype, allmodels,backendfolder,frontendfolder);
45
+ activatemodules.push({doctype:doctype,docname:capitalizeFirstLetter(docname)})
46
+ } else {
47
+ log.warn(`Load `+clc.yellow(file) + ` but it is not supported`)
48
+ }
49
+
50
+ }
51
+ log.info("Activated backend modules: ")
52
+ log.info(activatemodules)
53
+ loadSimpleAppModules(activatemodules,backendfolder)
54
+ return Promise.resolve(true)
55
+ }
56
+
57
+
58
+
59
+ const generate = (
60
+ docname: string,
61
+ doctype: string,
62
+ rendertype: string,
63
+ allmodels: ChildModels,
64
+ backendfolder:string,
65
+ frontendfolder:string
66
+ ) => {
67
+ const targetfolder = `${backendfolder}/src/docs/${doctype}`;
68
+
69
+ try {
70
+
71
+ mkdirSync(targetfolder,{ recursive: true });
72
+ mkdirSync(`${frontendfolder}/server/docs/`,{ recursive: true });
73
+
74
+ } catch (err) {
75
+ //do nothing if folder exists
76
+ } finally {
77
+ const templatefolder = `${constants.templatedir}/${rendertype}`
78
+ log.info(`- Generate ${docname}, ${doctype}, ${templatefolder}`)
79
+ const eta = new Eta({
80
+ views: templatefolder,
81
+ functionHeader:
82
+ 'const capitalizeFirstLetter = (str) => str.slice(0, 1).toUpperCase() + str.slice(1);' +
83
+ 'const initType=(str)=>{return ["string","number","boolean","array","object"].includes(str) ? capitalizeFirstLetter(str) : str;}',
84
+ });
85
+
86
+ const variables = {
87
+ name: docname,
88
+ doctype: doctype,
89
+ models: allmodels,
90
+ schema: allmodels[capitalizeFirstLetter(docname)].model,
91
+ apiSchemaName: capitalizeFirstLetter(docname), //capitalizeFirstLetter(doctype) + 'ApiSchema',
92
+ typename: capitalizeFirstLetter(docname),
93
+ fullApiSchemaName:
94
+ doctype + 'apischema.' + capitalizeFirstLetter(docname),
95
+ fullTypeName: doctype + 'type.' + capitalizeFirstLetter(docname),
96
+ jsonschema: jsonschemas[docname],
97
+ bothEndCode: '',
98
+ frontEndCode: '',
99
+ backEndCode: '',
100
+ controllerCode:''
101
+ };
102
+
103
+ // console.log('generate 2', JSON.stringify(variables));
104
+
105
+ // // const txtUISchema = eta.render('./uischema', variables);
106
+
107
+ // console.log('generate 4');
108
+ // console.log('generate 2', variables);
109
+ const txtType = eta.render('./type', variables);
110
+ writeFileSync(`${targetfolder}/${doctype}.type.ts`, txtType);
111
+ // compile(jsonschemas[docname], docname).then((txtType: string) => {
112
+ // writeFileSync(`${targetfolder}/${doctype}.type.ts`, txtType);
113
+ // });
114
+
115
+ // generate jsonschema object, use for data validation
116
+ const txtJsonSchema = eta.render('./jsonschema', variables);
117
+ writeFileSync(`${targetfolder}/${doctype}.jsonschema.ts`, txtJsonSchema);
118
+
119
+ // generate before save source code, wont override after regenerate
120
+ const customizefilename = `${targetfolder}/${doctype}.beforesave.ts`;
121
+ if (!existsSync(customizefilename)) {
122
+ const txtBeforeSave = eta.render('./beforesave', variables);
123
+ writeFileSync(
124
+ `${targetfolder}/${doctype}.beforesave.ts`,
125
+ txtBeforeSave,
126
+ );
127
+ }
128
+ // write mongoose model file
129
+ const txtModel = eta.render('./model', variables);
130
+ writeFileSync(`${targetfolder}/${doctype}.model.ts`, txtModel);
131
+
132
+ // prepare openapi schema
133
+ const txtApiSchema = eta.render('./apischema', variables);
134
+ writeFileSync(`${targetfolder}/${doctype}.apischema.ts`, txtApiSchema);
135
+
136
+ // prepare backend classes
137
+ // prepare frontend api client
138
+
139
+ const servicefile = `${targetfolder}/${doctype}.service.ts`;
140
+ let bothEndCode = '';
141
+ let backEndCode = '';
142
+ if (existsSync(servicefile)) {
143
+ const servicecodes = readFileSync(servicefile).toString();
144
+
145
+ /* extract string bothend and backend, put in back */
146
+ const regex1 =
147
+ /\/\/<begin-bothend-code>([\s\S]*?)\/\/<end-bothend-code>/g;
148
+ const regex2 =
149
+ /\/\/<begin-backend-code>([\s\S]*?)\/\/<end-backend-code>/g;
150
+ const bothendresult = servicecodes.match(regex1);
151
+ const backendresult = servicecodes.match(regex2);
152
+ if (bothendresult) {
153
+ bothEndCode = bothendresult[0];
154
+ }
155
+
156
+ if (backendresult) {
157
+ backEndCode = backendresult[0];
158
+ }
159
+ }
160
+
161
+ variables.bothEndCode = bothEndCode ?? "//<begin-bothend-code>\n//<end-bothend-code>";
162
+ variables.backEndCode = backEndCode ?? "//<begin-backend-code>\n//<end-backend-code>";
163
+ const txtService = eta.render('./service', variables);
164
+ writeFileSync(`${targetfolder}/${doctype}.service.ts`, txtService);
165
+
166
+ // prepare api router, allow add more api and wont override after regenerate
167
+ const controllerfile = `${targetfolder}/${doctype}.controller.ts`;
168
+ let controllerCode = ''
169
+ if (existsSync(controllerfile)) {
170
+ /* extract customized controller, put in back */
171
+ const controllersourcecodes = readFileSync(controllerfile).toString();
172
+ const controllerregex = /\/\/<begin-controller-code>([\s\S]*?)\/\/<end-controller-code>/g;
173
+ const controllerresult = controllersourcecodes.match(controllerregex);
174
+ if (controllerresult) {
175
+ controllerCode = controllerresult[0];
176
+ }
177
+ }
178
+ variables.controllerCode = controllerCode!='' ? controllerCode : "\n//<begin-controller-code>\n//<end-controller-code>";
179
+ const txtController = eta.render('./controller', variables);
180
+ writeFileSync(controllerfile, txtController);
181
+
182
+ // prepare module
183
+ const txtModule = eta.render('./module', variables);
184
+ writeFileSync(`${targetfolder}/${doctype}.module.ts`, txtModule);
185
+
186
+ // prepare readme
187
+ const txtReadme = eta.render('./readme', variables);
188
+ writeFileSync(`${targetfolder}/README.md`, txtReadme);
189
+
190
+ const frontendfile = `${frontendfolder}/server/docs/${variables.typename}Doc.ts`;
191
+ let frontEndCode = '';
192
+ if (existsSync(frontendfile)) {
193
+ const clientcodes = readFileSync(frontendfile).toString();
194
+
195
+ /* extract string frontend code, put in back */
196
+ const regex3 =
197
+ /\/\/<begin-frontend-code>([\s\S]*?)\/\/<end-frontend-code>/g;
198
+
199
+ const frontendresult = clientcodes.match(regex3);
200
+
201
+ if (frontendresult) {
202
+ frontEndCode = frontendresult[0];
203
+ }
204
+ }
205
+ variables.frontEndCode = frontEndCode ?? '';
206
+ const txtDocClient = eta.render('./apiclient', variables);
207
+ writeFileSync(frontendfile, txtDocClient);
208
+
209
+ // // fs.writeFileSync(`${targetfolder}/${doctype}.uischema.ts`, txtUISchema);
210
+ log.info(`- write completed: `+clc.green(doctype))
211
+
212
+ //create type
213
+ //create service
214
+ //create controller
215
+ //create module
216
+ //create apischema
217
+ //create beforesave if not exists
218
+ // console.log(schema, res);
219
+ }
220
+ };
221
+
222
+ const prepareEnvironments = (backendfolder:string,frontendfolder:string)=>{
223
+ const targetfolder = `${backendfolder}/src/class`
224
+ const targetfrontendfolder = `${frontendfolder}/server/class`
225
+ try{
226
+ mkdirSync(targetfolder,{recursive:true});
227
+ mkdirSync(targetfrontendfolder);
228
+ }catch(error){
229
+ //do nothing
230
+ }
231
+
232
+ //copy over backend service class
233
+
234
+ copyFileSync(`${constants.templatedir}/SimpleAppService.eta`,`${targetfolder}/SimpleAppService.ts`)
235
+
236
+ //copy over backend controller
237
+ copyFileSync(`${constants.templatedir}/SimpleAppController.eta`,`${targetfolder}/SimpleAppController.ts`)
238
+
239
+ //copy over frontend apiabstract class
240
+ copyFileSync(`${constants.templatedir}/SimpleAppClient.eta`,`${targetfrontendfolder}/SimpleAppClient.ts`)
241
+
242
+ //prepare backend config.ts
243
+
244
+ //copy over frontend config.ts
245
+ }
246
+
247
+
248
+ const loadSimpleAppModules=(modules:ModuleObject[],targetfolder:string)=>{
249
+
250
+ const eta = new Eta({views:constants.templatedir});
251
+ const txtMainModule = eta.render('app.module.eta', modules);
252
+ writeFileSync(`${targetfolder}/src/app.module.ts`, txtMainModule);
253
+
254
+ }
package/src/index.ts ADDED
@@ -0,0 +1,73 @@
1
+ #! /usr/bin/env node
2
+ const program = require("commander") // add this line
3
+ const Fieldtypes= require( './type')
4
+ const generator= require( './generate')
5
+ const fs = require( 'fs')
6
+ const {createNuxt,createNest} =require( './createproject')
7
+ const {exec} = require( "child_process")
8
+
9
+ const capitalizeFirstLetter= require( './libs')
10
+ // const {Logger, ILogObj} = require( "tslog");
11
+
12
+ // const log: Logger = new Logger();
13
+ const figlet = require("figlet");
14
+ // const program = new Command();
15
+
16
+
17
+
18
+ program
19
+ .version("1.0.0")
20
+ .description("An simpleapp CLI tool for generate frontend (vuejs) and backend(nestjs) codes")
21
+ .option("-c, --config-file <value>", 'configuration file content such as:{"definationsFolder":"./definations", "backendFolder":"./nestproject/src/docs", "frontendFolder":"./nuxt/server"}')
22
+ .option("-s, --definations-folder <value>", "load defination files from which folder")
23
+ .option("-b, --backend-folder <value>", "Create backend code at which folder")
24
+ .option("-f, --frontend-folder <value>", "Create frontend code at which folder")
25
+ .option("-i, --openapi3-yaml <value>", 'openapi3.yaml generated by backend server')
26
+ .parse(process.argv);
27
+
28
+
29
+ const options = program.opts();
30
+ console.log(figlet.textSync("SimpleApp Generator 1"));
31
+ // console.log(options)
32
+ const configs = require(options.configFile)
33
+ console.log("configurations: ",configs)
34
+ const definationsFolder = configs.definationsFolder ?? options.definationsFolder
35
+ const backendFolder = configs.backendFolder ?? options.backendFolder
36
+ const frontendFolder = configs.frontendFolder ?? options.frontendFolder
37
+ const openapi3Yaml:string = configs.openapi3Yaml ?? options.openapi3Yaml
38
+
39
+ const runGenNext = (callback)=>{
40
+ if(!fs.existsSync(backendFolder)){
41
+ createNest(backendFolder,callback)
42
+ }else{
43
+ callback()
44
+ }
45
+ }
46
+ const runGenNuxt = (callback)=>{
47
+ if(!fs.existsSync(frontendFolder)){
48
+ createNuxt(frontendFolder,callback)
49
+ }else{
50
+ callback()
51
+ }
52
+ }
53
+ runGenNuxt(()=>{
54
+ console.log("runGenNuxt done")
55
+ runGenNext(()=>{
56
+ console.log("runGenNext done")
57
+ generator.initialize(definationsFolder,backendFolder,frontendFolder)
58
+ if(openapi3Yaml !=''){
59
+
60
+ exec(`openapi-generator generate -i ${openapi3Yaml} -o ${frontendFolder}/server/openapi -g typescript-axios --skip-validate-spec`,(error, stdout, stderr)=>{
61
+ if(error){
62
+ console.error(stderr);
63
+ }
64
+ });
65
+ }
66
+ })
67
+ })
68
+
69
+
70
+
71
+
72
+ // pnpm exec prettier ./src/docs --write
73
+ // pnpm exec prettier ./apiclients --write
package/src/libs.ts ADDED
@@ -0,0 +1,14 @@
1
+ // const clc = require("cli-color");
2
+
3
+ export const capitalizeFirstLetter = (str: string) => {
4
+ const res = str == '' ? '' : str.slice(0, 1).toUpperCase() + str.slice(1);
5
+ // const res = str;
6
+ return res;
7
+ };
8
+
9
+ // export const logsuccess = (data:any)=>console.log(clc.green(data))
10
+ // export const logerror = (data:any)=>console.log(clc.error(data))
11
+ // export const logwarn = (data:any)=>console.log(clc.yellow(data))
12
+ // export const logdefault = (data:any)=>console.log(data)
13
+
14
+