@simitgroup/simpleapp-generator 1.0.31 → 1.0.33

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 (46) hide show
  1. package/README.md +97 -12
  2. package/dist/framework.js +9 -3
  3. package/dist/framework.js.map +1 -1
  4. package/dist/generate.js +21 -4
  5. package/dist/generate.js.map +1 -1
  6. package/dist/index.js +4 -3
  7. package/dist/index.js.map +1 -1
  8. package/dist/processors/jsonschemabuilder.js +91 -15
  9. package/dist/processors/jsonschemabuilder.js.map +1 -1
  10. package/dist/type.js.map +1 -1
  11. package/documentation/designconcept.bpmn +349 -0
  12. package/documentation/documentation.png +0 -0
  13. package/documentation/infra.drawio +141 -0
  14. package/documentation/infra.png +0 -0
  15. package/documentation/management.drawio +57 -0
  16. package/documentation/stack.drawio +106 -0
  17. package/package.json +1 -1
  18. package/src/framework.ts +9 -3
  19. package/src/generate.ts +29 -6
  20. package/src/index.ts +4 -3
  21. package/src/processors/jsonschemabuilder.ts +113 -22
  22. package/src/type.ts +44 -1
  23. package/templates/basic/controller.eta +34 -17
  24. package/templates/basic/model.eta +2 -1
  25. package/templates/basic/pageindex.vue.eta +4 -3
  26. package/templates/basic/service.eta +2 -1
  27. package/templates/basic/simpleappclient.eta +23 -1
  28. package/templates/nest/SimpleAppService.eta +141 -70
  29. package/templates/nest/TenantMiddleware.eta +8 -13
  30. package/templates/nest/UserProvider.eta +127 -0
  31. package/templates/nest/Workflow.eta +75 -0
  32. package/templates/nest/app.controller.eta +12 -0
  33. package/templates/nest/app.module.eta +6 -2
  34. package/templates/nest/app.service.eta +8 -0
  35. package/templates/nest/nest.env.eta +7 -0
  36. package/templates/nuxt/components.debugdocdata.vue.eta +1 -1
  37. package/templates/nuxt/components.menus.vue.eta +43 -7
  38. package/templates/nuxt/composables.stringHelper.ts.eta +5 -0
  39. package/templates/nuxt/nuxt.config.ts.eta +1 -1
  40. package/templates/nuxt/pages.[xorg].index.vue.eta +13 -9
  41. package/templates/nuxt/pages.index.vue.eta +58 -8
  42. package/templates/nuxt/plugins.simpleapp.ts.eta +10 -1
  43. package/templates/nuxt/server.api.ts.eta +2 -1
  44. package/templates/nuxt/tailwind.css.eta +14 -1
  45. package/tsconfig.json +4 -1
  46. package/templates/nest/User.eta +0 -115
@@ -0,0 +1,106 @@
1
+ <mxfile host="65bd71144e">
2
+ <diagram id="g2NRvyCy43iObyQwmQN3" name="Page-1">
3
+ <mxGraphModel dx="1092" dy="595" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
4
+ <root>
5
+ <mxCell id="0"/>
6
+ <mxCell id="1" parent="0"/>
7
+ <mxCell id="8" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="2" target="7">
8
+ <mxGeometry relative="1" as="geometry"/>
9
+ </mxCell>
10
+ <mxCell id="11" style="edgeStyle=none;html=1;" edge="1" parent="1" source="2" target="10">
11
+ <mxGeometry relative="1" as="geometry"/>
12
+ </mxCell>
13
+ <mxCell id="13" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="2" target="12">
14
+ <mxGeometry relative="1" as="geometry"/>
15
+ </mxCell>
16
+ <mxCell id="37" style="edgeStyle=none;html=1;" edge="1" parent="1" source="2" target="36">
17
+ <mxGeometry relative="1" as="geometry"/>
18
+ </mxCell>
19
+ <mxCell id="2" value="npm" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
20
+ <mxGeometry x="230" y="40" width="110" height="30" as="geometry"/>
21
+ </mxCell>
22
+ <mxCell id="4" value="Nuxt Frontend" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
23
+ <mxGeometry x="80" y="140" width="200" height="200" as="geometry"/>
24
+ </mxCell>
25
+ <mxCell id="7" value="simpleapp-vue-component" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="4">
26
+ <mxGeometry x="30" y="40" width="110" height="30" as="geometry"/>
27
+ </mxCell>
28
+ <mxCell id="21" style="edgeStyle=none;html=1;" edge="1" parent="4" source="14" target="19">
29
+ <mxGeometry relative="1" as="geometry"/>
30
+ </mxCell>
31
+ <mxCell id="14" value="pages &amp;amp; client libs" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="4">
32
+ <mxGeometry x="40" y="90" width="110" height="30" as="geometry"/>
33
+ </mxCell>
34
+ <mxCell id="19" value="api-client" style="whiteSpace=wrap;html=1;rounded=1;" vertex="1" parent="4">
35
+ <mxGeometry x="40" y="150" width="75" height="35" as="geometry"/>
36
+ </mxCell>
37
+ <mxCell id="5" value="Nest Backend" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
38
+ <mxGeometry x="310" y="140" width="200" height="200" as="geometry"/>
39
+ </mxCell>
40
+ <mxCell id="23" value="mongoose-schema" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="5">
41
+ <mxGeometry x="40" y="155" width="110" height="30" as="geometry"/>
42
+ </mxCell>
43
+ <mxCell id="24" value="doc-service" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="5">
44
+ <mxGeometry x="40" y="125" width="110" height="30" as="geometry"/>
45
+ </mxCell>
46
+ <mxCell id="25" value="api-countroller" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="5">
47
+ <mxGeometry x="40" y="95" width="110" height="30" as="geometry"/>
48
+ </mxCell>
49
+ <mxCell id="36" value="backend-libs" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="5">
50
+ <mxGeometry x="40" y="30" width="110" height="30" as="geometry"/>
51
+ </mxCell>
52
+ <mxCell id="6" value="Nest BPMN" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
53
+ <mxGeometry x="530" y="140" width="200" height="200" as="geometry"/>
54
+ </mxCell>
55
+ <mxCell id="10" value="bpmn-server" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="6">
56
+ <mxGeometry x="30" y="40" width="110" height="30" as="geometry"/>
57
+ </mxCell>
58
+ <mxCell id="15" value="" style="edgeStyle=none;html=1;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="12" target="4">
59
+ <mxGeometry relative="1" as="geometry"/>
60
+ </mxCell>
61
+ <mxCell id="17" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="12" target="16">
62
+ <mxGeometry relative="1" as="geometry"/>
63
+ </mxCell>
64
+ <mxCell id="26" style="edgeStyle=none;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="12" target="5">
65
+ <mxGeometry relative="1" as="geometry"/>
66
+ </mxCell>
67
+ <mxCell id="27" style="edgeStyle=none;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="12" target="6">
68
+ <mxGeometry relative="1" as="geometry"/>
69
+ </mxCell>
70
+ <mxCell id="35" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="12" target="34">
71
+ <mxGeometry relative="1" as="geometry"/>
72
+ </mxCell>
73
+ <mxCell id="12" value="simpleapp-generator" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
74
+ <mxGeometry x="250" y="430" width="110" height="30" as="geometry"/>
75
+ </mxCell>
76
+ <mxCell id="20" style="edgeStyle=none;html=1;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="16" target="19">
77
+ <mxGeometry relative="1" as="geometry"/>
78
+ </mxCell>
79
+ <mxCell id="16" value="openapi-generator" style="whiteSpace=wrap;html=1;rounded=1;" vertex="1" parent="1">
80
+ <mxGeometry x="140" y="380" width="75" height="35" as="geometry"/>
81
+ </mxCell>
82
+ <mxCell id="32" style="edgeStyle=none;html=1;" edge="1" parent="1" source="28" target="12">
83
+ <mxGeometry relative="1" as="geometry"/>
84
+ </mxCell>
85
+ <mxCell id="28" value="jsonschema" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
86
+ <mxGeometry x="175" y="550" width="120" height="80" as="geometry"/>
87
+ </mxCell>
88
+ <mxCell id="31" style="edgeStyle=none;html=1;" edge="1" parent="1" source="29" target="12">
89
+ <mxGeometry relative="1" as="geometry"/>
90
+ </mxCell>
91
+ <mxCell id="29" value="bpmn" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
92
+ <mxGeometry x="340" y="550" width="120" height="80" as="geometry"/>
93
+ </mxCell>
94
+ <mxCell id="33" style="edgeStyle=none;html=1;entryX=0.916;entryY=1.003;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="30" target="12">
95
+ <mxGeometry relative="1" as="geometry"/>
96
+ </mxCell>
97
+ <mxCell id="30" value="UI Design (One day)" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
98
+ <mxGeometry x="490" y="550" width="120" height="80" as="geometry"/>
99
+ </mxCell>
100
+ <mxCell id="34" value="mobile app (One day)" style="whiteSpace=wrap;html=1;rounded=1;" vertex="1" parent="1">
101
+ <mxGeometry x="600" y="415" width="120" height="60" as="geometry"/>
102
+ </mxCell>
103
+ </root>
104
+ </mxGraphModel>
105
+ </diagram>
106
+ </mxfile>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simitgroup/simpleapp-generator",
3
- "version": "1.0.31",
3
+ "version": "1.0.33",
4
4
  "description": "frontend nuxtjs and backend nests code generator using jsonschema",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/framework.ts CHANGED
@@ -6,7 +6,8 @@ import {Eta} from 'eta';
6
6
  const log: Logger<ILogObj> = new Logger();
7
7
 
8
8
  let config = {
9
- "definationsFolder":"./definations",
9
+ "jsonschemaFolder":"./jsonschemaFolder",
10
+ "bpmnFolder":"./bpmn",
10
11
  "backendFolder":"./mybackend",
11
12
  "backendPort":"8000",
12
13
  "mongoConnectStr":'mongodb://<user>:<pass>@<host>:<port>/<db>?authMechanism=DEFAULT',
@@ -20,6 +21,11 @@ let config = {
20
21
  "OAUTH2_CLIENTID":"client-id",
21
22
  "OAUTH2_CLIENTSECRET":"client-secret-value",
22
23
  "AUTH_SECRET_KEY":"my-secret",
24
+ },
25
+ "bpmnsetting":{
26
+ "BPMN_HOST":"127.0.0.1",
27
+ "BPMN_PORT":"9000",
28
+ "BPMN_API_KEY":"12345"
23
29
  }
24
30
  }
25
31
 
@@ -61,7 +67,7 @@ export const prepareNest = (callback:Function)=>{
61
67
  if(!fs.existsSync(`${targetfolder}/.env`)){
62
68
 
63
69
 
64
- exec(`cd ${targetfolder};pnpm install --save nest-keycloak-connect keycloak-connect @nestjs/serve-static jsonwebtoken axios @darkwolf/base64url json-schema @wearenova/mongoose-tenant @nestjs/swagger @nestjs/mongoose mongoose ajv ajv-formats ajv-errors @nestjs/config`,async (error, stdout, stderr)=>{
70
+ exec(`cd ${targetfolder};pnpm install --save nest-keycloak-connect keycloak-connect bpmn-client @nestjs/serve-static jsonwebtoken axios @darkwolf/base64url json-schema @wearenova/mongoose-tenant @nestjs/swagger @nestjs/mongoose mongoose ajv ajv-formats ajv-errors @nestjs/config`,async (error, stdout, stderr)=>{
65
71
  // log.info(`dependency installed`)
66
72
  if(!error){
67
73
  fs.mkdirSync(`${targetfolder}/public_html`,{recursive:true})
@@ -101,7 +107,7 @@ export const prepareNuxt = (callback:Function)=>{
101
107
  exec(`cd ${targetfolder};pnpm install;pnpm install -D @sidebase/nuxt-auth @nuxt/ui @types/node @vueuse/nuxt @sidebase/nuxt-auth @vueuse/core nuxt-security prettier `, (error, stdout, stderr)=>{
102
108
  //;pnpm install
103
109
  console.log(error, stdout, stderr)
104
- exec(`cd ${targetfolder};pnpm install --save next-auth@4.21.1 @darkwolf/base64url @nuxt/ui ajv ajv-formats ajv-errors dotenv @fullcalendar/core @fullcalendar/vue3 quill uuid primeflex primeicons prettier primevue axios json-schema mitt @simitgroup/simpleapp-vue-component@latest`, (error, stdout, stderr)=>{
110
+ exec(`cd ${targetfolder};pnpm install --save @darkwolf/base64url next-auth@4.21.1 @darkwolf/base64url @nuxt/ui ajv ajv-formats ajv-errors dotenv @fullcalendar/core @fullcalendar/vue3 quill uuid primeflex primeicons prettier primevue axios json-schema mitt @simitgroup/simpleapp-vue-component@latest`, (error, stdout, stderr)=>{
105
111
  console.log(error, stdout, stderr)
106
112
 
107
113
  fs.mkdirSync(`${targetfolder}/assets/css/`,{recursive:true})
package/src/generate.ts CHANGED
@@ -15,16 +15,22 @@ const path = require('path');
15
15
  import {mkdirSync, readdir,readFileSync,writeFileSync,existsSync,copyFileSync, readdirSync} from 'fs'
16
16
  const { Eta } = require('eta');
17
17
  const { capitalizeFirstLetter }= require('./libs');
18
+ const X_DOCUMENT_TYPE='x-document-type'
19
+ const X_DOCUMENT_NAME='x-document-name'
20
+ const X_COLLECTION_NAME='x-collection-name'
18
21
  const extFb = '.xfb.json';
19
22
  const extHfb = '.xhfb.json';
20
23
  const extjsonschema = '.jsonschema.json';
21
24
  let jsonschemas = {};
22
25
  const docs = [];
23
26
 
24
- export const initialize = async (defFolder:string,backendfolder:string,frontendfolder:string,callback:Function) => {
27
+ export const initialize = async (defFolder:string,bpmnFolder:string,backendfolder:string,frontendfolder:string,callback:Function) => {
25
28
  prepareEnvironments(backendfolder,frontendfolder)
26
29
  let activatemodules:ModuleObject[]=[]
27
30
  //
31
+ /*
32
+ load available bpmn into array
33
+ */
28
34
  const files = readdirSync(defFolder)
29
35
  // log.warn("all schemas:",files)
30
36
  // readdir(defFolder, (err, files) => {
@@ -34,19 +40,21 @@ export const initialize = async (defFolder:string,backendfolder:string,frontend
34
40
  log.info(`Load `+clc.green(file))
35
41
  const filearr = file.split('.');
36
42
  let rendertype = 'basic';
37
- const docname = filearr[0].toLowerCase();
38
- const doctype = filearr[1].toLowerCase();
43
+ let docname = filearr[0].toLowerCase();
44
+ let doctype = filearr[1].toLowerCase();
45
+
39
46
  const jsonstring = readFileSync(defFolder +path.sep+ file, 'utf-8');
40
47
  let allmodels: ChildModels = {} as ChildModels;
41
48
 
42
49
  if (file.endsWith(extjsonschema)) {
43
- const jsondata = JSON.parse(jsonstring);
50
+ const jsondata = JSON.parse(jsonstring);
44
51
  rendertype = 'basic';
45
52
  jsonschemas[docname] = jsondata;
53
+
46
54
  // foreignkeys:
47
55
  // tmpforeignkeys:TypeForeignKey
48
56
  allmodels = await readJsonSchemaBuilder(doctype, docname, jsondata,foreignkeys);
49
-
57
+
50
58
  //foreignkeycatalogues
51
59
  // foreignkeys
52
60
  generate(docname, doctype, rendertype, allmodels,backendfolder,frontendfolder);
@@ -110,6 +118,10 @@ const generate = (
110
118
  backEndCode: '',
111
119
  controllerCode:'',
112
120
  apiSchemaCode:'',
121
+ docStatusSettings:allmodels[capitalizeFirstLetter(docname)].docStatusSettings,
122
+ apiSettings:allmodels[capitalizeFirstLetter(docname)].apiSettings,
123
+ requireautocomplete:allmodels[capitalizeFirstLetter(docname)].requireautocomplete,
124
+ isolationtype:allmodels[capitalizeFirstLetter(docname)].isolationtype
113
125
  };
114
126
 
115
127
  // console.log('generate 2', JSON.stringify(variables));
@@ -271,8 +283,9 @@ const prepareEnvironments = (backendfolder:string,frontendfolder:string)=>{
271
283
 
272
284
  copyFileSync(`${constants.templatedir}/nest/SimpleAppService.eta`,`${targetfolder}/SimpleAppService.ts`)
273
285
  copyFileSync(`${constants.templatedir}/nest/SimpleAppController.eta`,`${targetfolder}/SimpleAppController.ts`)
286
+ copyFileSync(`${constants.templatedir}/nest/Workflow.eta`,`${targetfolder}/Workflow.ts`)
274
287
  copyFileSync(`${constants.templatedir}/nest/TenantMiddleware.eta`,`${targetfolder}/TenantMiddleware.ts`)
275
- copyFileSync(`${constants.templatedir}/nest/User.eta`,`${targetfolder}/User.ts`)
288
+ copyFileSync(`${constants.templatedir}/nest/UserProvider.eta`,`${targetfolder}/UserProvider.ts`)
276
289
 
277
290
  //copy over frontend apiabstract class
278
291
  // copyFileSync(`${constants.templatedir}/nuxt.apigateway.eta`,`${targetfrontendfolder}/[...].ts`)
@@ -291,6 +304,12 @@ const finalize=(modules:ModuleObject[],backendfolder:string,frontendfolder:strin
291
304
  const eta = new Eta({views:constants.templatedir});
292
305
  const txtMainModule = eta.render('./nest/app.module.eta', modules);
293
306
  writeFileSync(`${backendfolder}/src/app.module.ts`, txtMainModule);
307
+
308
+ const txtMainService = eta.render('./nest/app.service.eta', modules);
309
+ writeFileSync(`${backendfolder}/src/app.service.ts`, txtMainService);
310
+
311
+ const txtAppController = eta.render('./nest/app.controller.eta', modules);
312
+ writeFileSync(`${backendfolder}/src/app.controller.ts`, txtAppController);
294
313
 
295
314
  const foreignkeyfile =`${backendfolder}/src/dicts/foreignkeys.json`
296
315
  writeFileSync(foreignkeyfile, JSON.stringify(foreignkeys));
@@ -301,5 +320,9 @@ const finalize=(modules:ModuleObject[],backendfolder:string,frontendfolder:strin
301
320
 
302
321
  const txtMenus = eta.render('./nuxt/composables.getmenus.ts.eta', modules);
303
322
  writeFileSync(`${frontendfolder}/composables/getMenus.ts`, txtMenus);
323
+
324
+ const txtStringHelper= eta.render('./nuxt/composables.stringHelper.ts.eta', modules);
325
+ writeFileSync(`${frontendfolder}/composables/stringHelper.ts`, txtStringHelper);
326
+
304
327
 
305
328
  }
package/src/index.ts CHANGED
@@ -22,7 +22,7 @@ let version=pj.version
22
22
  program
23
23
  .version(version)
24
24
  .description("An simpleapp CLI tool for generate frontend (vuejs) and backend(nestjs) codes")
25
- .option("-c, --config-file <value>", 'configuration file content such as:{"definationsFolder":"./definations", "backendFolder":"./nestproject/src/docs", "frontendFolder":"./nuxt/server"}')
25
+ .option("-c, --config-file <value>", 'configuration file')
26
26
  .parse(process.argv);
27
27
 
28
28
  let path=''
@@ -44,7 +44,8 @@ if(!options.configFile){
44
44
  }
45
45
  const configs = require(path)
46
46
  console.log("configurations: ",configs)
47
- const definationsFolder = configs.definationsFolder
47
+ const jsonschemaFolder = configs.jsonschemaFolder
48
+ const bpmnFolder = configs.bpmnFolder
48
49
  const backendFolder = configs.backendFolder
49
50
  const frontendFolder = configs.frontendFolder
50
51
  const openapi3Yaml = configs.openapi3Yaml
@@ -55,7 +56,7 @@ const run = async()=>{
55
56
  fw.runCreateNest(()=>{
56
57
  fw.prepareNest(()=>{
57
58
  fw.prepareNuxt(()=>{
58
- generate.initialize(definationsFolder,backendFolder,frontendFolder,()=>{
59
+ generate.initialize(jsonschemaFolder,bpmnFolder,backendFolder,frontendFolder,()=>{
59
60
  fw.prepareOpenApiClient()
60
61
  fw.prettyNuxt()
61
62
  fw.prettyNest()
@@ -13,32 +13,64 @@ import {
13
13
  ChildModels,
14
14
  SchemaModel,
15
15
  TypeForeignKey,
16
- TypeForeignKeyCatalogue
16
+ TypeForeignKeyCatalogue,
17
+ DocSetting,ApiSetting,DocStatusSetting,
18
+
17
19
  } from '../type';
18
20
  import { json } from 'stream/consumers';
19
21
  const log: Logger<ILogObj> = new Logger();
22
+
20
23
  const X_DOCUMENT_NO='x-document-no'
21
- const X_DOCUMENT_NAME='x-document-name'
24
+ const X_DOCUMENT_LABEL='x-document-label'
22
25
  const X_AUTOCOMPLETE_FIELD='x-autocomplete-field'
26
+ const X_DOCUMENT_NAME='x-document-name'
27
+ const X_DOCUMENT_TYPE='x-document-type'
28
+ const X_COLLECTION_NAME='x-document-collection'
29
+ const X_DOCUMENT_STATUS='x-document-status'
30
+ const X_DOCUMENT_API='x-document-api'
31
+ const X_IGNORE_AUTOCOMPLETE='x-ignore-autocomplete'
23
32
  const FOREIGNKEY_PROPERTY='x-foreignkey'
24
-
25
33
  const X_TEL_NO='x-tel'
34
+ const X_ISOLATION_TYPE='x-isolation-type'
35
+
36
+ let docSetting:DocSetting={} as DocSetting
37
+
38
+
39
+
26
40
  let allmodels: ChildModels = {};
27
41
  let fullschema={}
28
- let fieldAutoCompleteCode=''
29
- let fieldAutoCompleteName=''
42
+ // let fieldAutoCompleteCode=''
43
+ // let fieldAutoCompleteName=''
30
44
  let moreAutoComplete:string[]=[]
45
+
46
+
47
+ const newDocSetting=(doctype:string,docname:string):DocSetting=>{
48
+ return {
49
+ docName:docname, //done
50
+ docType:doctype, //done
51
+ colDocNo:'', //done
52
+ colDocLabel:'', //done
53
+ collectionName:docname, //done
54
+ autocompleteFields:[],
55
+ docStatusSettings:[],
56
+ apiSettings:[],
57
+ requireautocomplete:true,
58
+ isolationtype:"org"
59
+
60
+ }
61
+ }
31
62
  export const readJsonSchemaBuilder = async (
32
63
  doctype: string,
33
64
  docname: string,
34
65
  orijsondata:JSONSchema7,
35
66
  allforeignkeys:TypeForeignKeyCatalogue
36
67
  ) => {
37
-
38
- fieldAutoCompleteCode=''
39
- fieldAutoCompleteName=''
68
+ docSetting=newDocSetting(doctype,docname)
69
+ // fieldAutoCompleteCode=''
70
+ // fieldAutoCompleteName=''
40
71
  moreAutoComplete=[]
41
72
  allmodels = {};
73
+
42
74
  const validateddata: JSONSchema7 = { ...orijsondata };
43
75
  let schema: SchemaModel | SchemaModel[];
44
76
  const tmpjsondata = await $RefParser.dereference(orijsondata).then((schema)=>{
@@ -56,12 +88,12 @@ export const readJsonSchemaBuilder = async (
56
88
  } else if (jsondata.type == 'array') {
57
89
  throw(`unsupport array type for ${docname}.${doctype}`)
58
90
  }
59
- if(fieldAutoCompleteCode=='') {
91
+ if(docSetting.colDocNo=='' && docSetting.requireautocomplete) {
60
92
  log.error(`you shall define 1 field with format:'${X_DOCUMENT_NO}'`)
61
93
  throw "missing field format"
62
94
  }
63
- if(fieldAutoCompleteName=='') {
64
- log.error(`you shall define 1 field with format: '${X_DOCUMENT_NAME}'}`)
95
+ if(docSetting.colDocLabel=='' && docSetting.requireautocomplete) {
96
+ log.error(`you shall define 1 field with format: '${X_DOCUMENT_LABEL}'}`)
65
97
  throw "missing field format"
66
98
  }
67
99
 
@@ -86,6 +118,50 @@ const processObject = (doctype: string,
86
118
  jsondata.properties['updated'] = {type: 'string',description: 'Control value, dont edit it',};
87
119
  jsondata.properties['createdby'] = {type: 'string',description: 'Control value, dont edit it',};
88
120
  jsondata.properties['updatedby'] = {type: 'string',description: 'Control value, dont edit it',};
121
+
122
+ if(jsondata[X_ISOLATION_TYPE] && ['none','tenant','org','branch'].includes(jsondata[X_ISOLATION_TYPE]) ){
123
+ docSetting.isolationtype=jsondata[X_ISOLATION_TYPE]
124
+ }
125
+ if(jsondata[X_IGNORE_AUTOCOMPLETE] && jsondata[X_IGNORE_AUTOCOMPLETE]==true){
126
+ docSetting.requireautocomplete=false
127
+ }
128
+ if(jsondata[X_DOCUMENT_API] && Array.isArray(jsondata[X_DOCUMENT_API])){
129
+ log.warn("x-document-api exists:")
130
+ log.warn(jsondata[X_DOCUMENT_API])
131
+ for(let i=0; i<jsondata[X_DOCUMENT_API].length;i++){
132
+ const tmp:ApiSetting =jsondata[X_DOCUMENT_API][i]
133
+ if(!tmp.action){
134
+ const errmsg = "x-document-api defined but undefine property 'action'"
135
+ log.error(errmsg)
136
+
137
+ throw errmsg
138
+ }
139
+ if(!tmp.method){
140
+ const errmsg = "x-document-api defined but undefine property 'method'"
141
+ log.error(errmsg)
142
+ throw errmsg
143
+ }
144
+ docSetting.apiSettings.push(tmp)
145
+ }
146
+ }
147
+ if(jsondata[X_DOCUMENT_STATUS] && Array.isArray(jsondata[X_DOCUMENT_STATUS])){
148
+ for(let i=0; i<jsondata[X_DOCUMENT_STATUS].length;i++){
149
+ const tmp:DocStatusSetting =jsondata[X_DOCUMENT_STATUS][i]
150
+ if(tmp.statusCode ===undefined){
151
+ const errmsg = "x-document-status defined but undefine property 'statusCode'"
152
+ log.error(errmsg)
153
+ throw errmsg
154
+ }
155
+ if(!tmp.statusName ===undefined){
156
+ const errmsg = "x-document-status defined but undefine property 'statusName'"
157
+ log.error(errmsg)
158
+ throw errmsg
159
+ }
160
+ docSetting.docStatusSettings.push(tmp)
161
+ }
162
+ }
163
+
164
+
89
165
  return genSchema(
90
166
  capitalizeFirstLetter(docname),
91
167
  'object',
@@ -94,12 +170,8 @@ const processObject = (doctype: string,
94
170
  );
95
171
  }
96
172
 
97
- const genSchema = (
98
- docname: string,
99
- schematype: string,
100
- jsondata: JsonSchemaProperties,//JSONSchema7,//|JsonSchemaProperties|JSONSchema7Definition,
101
- requiredlist: string[] | undefined,
102
- ): SchemaModel => {
173
+ const genSchema = (docname: string,schematype: string,jsondata: JsonSchemaProperties,
174
+ requiredlist: string[] | undefined): SchemaModel => {
103
175
  const newmodel: SchemaModel = {};
104
176
  const props = Object.getOwnPropertyNames(jsondata ??{});
105
177
  // console.log('==== jsondata', jsondata);
@@ -116,18 +188,25 @@ const genSchema = (
116
188
  const isrequired = requiredlist && requiredlist.includes(key);
117
189
  const newName: string = docname + capitalizeFirstLetter(key);
118
190
  if(obj.format && obj.format==X_DOCUMENT_NO){
119
- fieldAutoCompleteCode=key
191
+ docSetting.colDocNo=key
120
192
  obj.minLength=obj.minLength??1
121
193
  jsondata[key]['minLength']=obj.minLength
122
194
  }
123
- if(obj.format && obj.format==X_DOCUMENT_NAME){
124
- fieldAutoCompleteName=key
195
+ if(obj.format && obj.format==X_DOCUMENT_LABEL){
196
+ docSetting.colDocLabel=key
125
197
  obj.minLength=obj.minLength??1
126
198
  jsondata[key]['minLength']=obj.minLength
127
199
  }
200
+
201
+ if(obj[X_COLLECTION_NAME]){
202
+ docSetting.collectionName=key
203
+ }
204
+
205
+
128
206
  if(obj[X_AUTOCOMPLETE_FIELD]){
129
- moreAutoComplete.push(key)
207
+ docSetting.autocompleteFields.push(key)
130
208
  }
209
+
131
210
 
132
211
  // if(obj.format && obj.format==X_TEL_NO){
133
212
  // obj.pattern=obj.pattern ?? '/^\d{7,15}$/gm'
@@ -177,7 +256,18 @@ const genSchema = (
177
256
  // console.log(key,'--------newmodel',obj, newmodel[key]);
178
257
  }
179
258
  }
180
- allmodels[docname] = { type: schematype, model: newmodel,codeField: fieldAutoCompleteCode ,nameField: fieldAutoCompleteName,moreAutoComplete:moreAutoComplete };
259
+ allmodels[docname] = {
260
+ type: schematype,
261
+ model: newmodel,
262
+ codeField: docSetting.colDocNo ,
263
+ nameField: docSetting.colDocLabel,
264
+ moreAutoComplete:docSetting.autocompleteFields,
265
+ docStatusSettings:docSetting.docStatusSettings,
266
+ apiSettings:docSetting.apiSettings,
267
+ requireautocomplete:docSetting.requireautocomplete,
268
+ isolationtype:docSetting.isolationtype
269
+ };
270
+ // console.warn(docname,docSetting.isolationtype)
181
271
  return newmodel;
182
272
  };
183
273
 
@@ -216,3 +306,4 @@ const getField = (
216
306
  }
217
307
  return f;
218
308
  };
309
+
package/src/type.ts CHANGED
@@ -1,6 +1,16 @@
1
1
  import { JSONSchema7, JSONSchema7Definition } from 'json-schema';
2
2
  export type ChildModels = {
3
- [key: string]: { type: string; model: SchemaModel,codeField:string,nameField:string,moreAutoComplete:string[] };
3
+ [key: string]: {
4
+ type: string;
5
+ model: SchemaModel,
6
+ codeField:string,
7
+ nameField:string,
8
+ moreAutoComplete:string[],
9
+ docStatusSettings:DocStatusSetting[],
10
+ apiSettings:ApiSetting[],
11
+ requireautocomplete: boolean
12
+ isolationtype:string
13
+ };
4
14
  };
5
15
  export enum Fieldtypes {
6
16
  'string' = 'string',
@@ -63,4 +73,37 @@ frontEndCode: string
63
73
  backEndCode: string
64
74
  controllerCode:string
65
75
  apiSchemaCode:string
76
+ docStatusSettings:DocStatusSetting[],
77
+ apiSettings:ApiSetting[],
78
+ requireautocomplete:boolean,
79
+ isolationtype:string
80
+ }
81
+
82
+ export type DocStatusSetting = {
83
+ statusCode:string,
84
+ statusName:string,
85
+ allowApi:string[],
86
+ readonly?:boolean,
87
+ description?:''
88
+ }
89
+
90
+ export type ApiSetting = {
91
+ method:string,
92
+ action:string,
93
+ setDocStatus?:'',
94
+ description?:'',
95
+ bpmnApi?:'',
96
+ data?:any
97
+ }
98
+ export type DocSetting = {
99
+ docName:string,
100
+ docType:string,
101
+ colDocNo:string,
102
+ colDocLabel:string,
103
+ collectionName:string,
104
+ autocompleteFields:string[],
105
+ docStatusSettings:DocStatusSetting[],
106
+ apiSettings:ApiSetting[],
107
+ requireautocomplete:boolean
108
+ isolationtype:string
66
109
  }
@@ -2,7 +2,7 @@
2
2
  * This file was automatically generated by simpleapp generator. Every
3
3
  * MODIFICATION OVERRIDE BY GENERATEOR Except content between:
4
4
  * <begin-controller-code><end-controller-code>
5
- * last change 2023-09-09
5
+ * last change 2023-09-18
6
6
  * Author: Ks Tan
7
7
  */
8
8
  import {
@@ -59,20 +59,6 @@ export class <%= it.typename %>Controller extends SimpleAppController<
59
59
  }
60
60
 
61
61
 
62
- @Get(':id')
63
- @ApiResponse({
64
- status: 200,
65
- description: 'Founds',
66
- type: <%= it.fullApiSchemaName%>
67
- })
68
- @ApiResponse({ status: 404, description: 'Document not found' })
69
- @ApiResponse({ status: 500, description: 'Internal error' })
70
- @ApiOperation({ operationId: 'runFindOne' })
71
- async findOne(@Param('id') id: string) {
72
- return await this._findOne(id);
73
- }
74
-
75
-
76
62
 
77
63
  @Post()
78
64
  @ApiResponse({
@@ -102,6 +88,38 @@ export class <%= it.typename %>Controller extends SimpleAppController<
102
88
  return await this._search(data)
103
89
  }
104
90
 
91
+
92
+ /***************************** x-document-api definations *****************************************/
93
+
94
+ <% for(let i=0;i<it.apiSettings.length;i++){%>
95
+ <% let api = it.apiSettings[i] %>
96
+ <%~ `@${capitalizeFirstLetter(api.method)}('${api.action}')`%>
97
+ @ApiResponse({status: 200,description: '<%=api.description%>',type: () =><%~JSON.stringify(api.returntype)%> })
98
+ @ApiOperation({ operationId: '<%=api.execute%>' })
99
+ async <%=api.execute%>(){
100
+ return await this.service.<%=api.execute%>()
101
+ }
102
+ <%}%>
103
+
104
+ /*****************************customized code begin here *****************************************/
105
+ <%~ it.controllerCode %>
106
+
107
+ /*****************************customized code end here *****************************************/
108
+
109
+ @Get(':id')
110
+ @ApiResponse({
111
+ status: 200,
112
+ description: 'Founds',
113
+ type: <%= it.fullApiSchemaName%>
114
+ })
115
+ @ApiResponse({ status: 404, description: 'Document not found' })
116
+ @ApiResponse({ status: 500, description: 'Internal error' })
117
+ @ApiOperation({ operationId: 'runFindOne' })
118
+ async findOne(@Param('id') id: string) {
119
+ return await this._findOne(id);
120
+ }
121
+
122
+
105
123
  @Put(':id')
106
124
  @ApiResponse({
107
125
  status: 200,
@@ -129,7 +147,6 @@ export class <%= it.typename %>Controller extends SimpleAppController<
129
147
  }
130
148
 
131
149
 
132
- /*****************************customized code begin here *****************************************/
133
- <%~ it.controllerCode %>
150
+
134
151
 
135
152
  }
@@ -29,6 +29,7 @@ const schemasetting = {
29
29
  };
30
30
 
31
31
  export const <%= it.doctype %>MongoSchema = new Schema(schemasetting,{collection: '<%= it.name %>'})
32
+ <%if(it.requireautocomplete){%>
32
33
  .index({<%=it.autocompletecode%>:1,orgId:1},{unique:true})
33
34
  .index({<%=it.autocompletename%>:1,orgId:1});
34
-
35
+ <%}%>
@@ -36,7 +36,7 @@
36
36
  ]
37
37
  <%}%>
38
38
  <%})%>
39
-
39
+ //end
40
40
  </script>
41
41
  <template>
42
42
  <div>
@@ -46,7 +46,8 @@
46
46
  :listColumns="columns">
47
47
 
48
48
  <%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
49
- <% let obj=it.jsonschema.properties[key] %>
49
+
50
+ <% let obj=it.jsonschema.properties[key] %>
50
51
  <% if(skipcolumns.indexOf(key)>=0){ %>
51
52
  <% } else if(obj.type=='boolean'){ %>
52
53
  <SimpleAppCheckbox autofocus :setting="o.getField('#/properties/<%= key %>')" v-model="data.<%= key %>"/>
@@ -55,7 +56,7 @@
55
56
  <% } else if(obj.type=='array' && obj.items && obj.items.type =='string' ){ %>
56
57
  <SimpleAppChip autofocus :setting="o.getField('#/properties/<%= key %>')" v-model="data.<%= key %>"/>
57
58
  <% } else if(obj.type=='object' && typeof obj['x-foreignkey']!='undefined'){ %>
58
- <SimpleAppAutocomplete :getAutocomplete="getAutocomplete" :setting="o.getField('#/properties/<%= key %>')"
59
+ <SimpleAppAutocomplete :setting="o.getField('#/properties/<%= key %>')"
59
60
  v-model="data.<%= key %>" optionLabel="label" :remote-src="getAutocomplete('<%=obj['x-foreignkey']%>')"/>
60
61
  <% } else if(obj.type=='string'){ %>
61
62
  <% if(obj.format=='date'){ %>