@simitgroup/simpleapp-generator 2.0.0-t-alpha → 2.0.0-v-alpha

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 (33) hide show
  1. package/ReleaseNote.md +16 -1
  2. package/dist/generate.d.ts.map +1 -1
  3. package/dist/generate.js +49 -26
  4. package/dist/generate.js.map +1 -1
  5. package/package.json +1 -1
  6. package/src/generate.ts +116 -93
  7. package/templates/basic/miniApi/resource.controller.ts.eta +14 -0
  8. package/templates/basic/miniApi/resource.service.ts.eta +6 -0
  9. package/templates/basic/nest/controller.ts.eta +70 -76
  10. package/templates/basic/nuxt/pages.form.vue.eta +2 -2
  11. package/templates/basic/nuxt/pages.landing.vue.eta +2 -2
  12. package/templates/nest/src/main.ts._eta +14 -19
  13. package/templates/nest/src/simple-app/_core/features/mini-app/developer-portal/developer-portal.service.ts.eta +9 -25
  14. package/templates/nest/src/simple-app/_core/features/user-context/user.context.ts.eta +1 -4
  15. package/templates/nest/src/simple-app/_core/framework/base/simple-app.controller.ts.eta +12 -2
  16. package/templates/nest/src/simple-app/_core/framework/base/simple-app.service.ts.eta +76 -3
  17. package/templates/nest/src/simple-app/_core/framework/schemas/others.schema.ts.eta +12 -1
  18. package/templates/nuxt/components/simpleApp/SimpleAppFormToolBar.vue._eta +1 -1
  19. package/templates/nuxt/server/api/[xorg]/[...].ts._eta +76 -121
  20. package/templates/nest/src/simple-app/features/print/api/.gitignore.eta +0 -4
  21. package/templates/nest/src/simple-app/features/print/api/.npmignore.eta +0 -1
  22. package/templates/nest/src/simple-app/features/print/api/.openapi-generator/FILES.eta +0 -8
  23. package/templates/nest/src/simple-app/features/print/api/.openapi-generator/VERSION.eta +0 -1
  24. package/templates/nest/src/simple-app/features/print/api/.openapi-generator-ignore.eta +0 -23
  25. package/templates/nest/src/simple-app/features/print/api/api.ts.eta +0 -223
  26. package/templates/nest/src/simple-app/features/print/api/base.ts.eta +0 -86
  27. package/templates/nest/src/simple-app/features/print/api/common.ts.eta +0 -150
  28. package/templates/nest/src/simple-app/features/print/api/configuration.ts.eta +0 -110
  29. package/templates/nest/src/simple-app/features/print/api/git_push.sh.eta +0 -57
  30. package/templates/nest/src/simple-app/features/print/api/index.ts.eta +0 -18
  31. package/templates/nest/src/simple-app/features/print/api/openapitools.json.eta +0 -7
  32. package/templates/nest/src/simple-app/features/print/print.module.ts.eta +0 -15
  33. package/templates/nest/src/simple-app/features/print/print.service.ts.eta +0 -41
package/src/generate.ts CHANGED
@@ -30,8 +30,27 @@ import _ from 'lodash';
30
30
  import * as buildinschemas from './buildinschemas';
31
31
  import { JSONSchema7 } from 'json-schema';
32
32
  import { generatePrintformat } from './processors/jrxmlbuilder';
33
- const skipIsolationDocument = ['tenant','organization','branch','permission','user']
34
- const systemResources = ['user','tenant','organization','branch','permission','keyvaluepair','customfield','miniapp','miniappinstallation','systemmessage','queuejob','documentnoformat']
33
+ const skipIsolationDocument = [
34
+ 'tenant',
35
+ 'organization',
36
+ 'branch',
37
+ 'permission',
38
+ 'user'
39
+ ];
40
+ const systemResources = [
41
+ 'user',
42
+ 'tenant',
43
+ 'organization',
44
+ 'branch',
45
+ 'permission',
46
+ 'keyvaluepair',
47
+ 'customfield',
48
+ 'miniapp',
49
+ 'miniappinstallation',
50
+ 'systemmessage',
51
+ 'queuejob',
52
+ 'documentnoformat'
53
+ ];
35
54
  const { Eta } = require('eta');
36
55
  const { capitalizeFirstLetter } = require('./libs');
37
56
  // const X_DOCUMENT_TYPE='x-document-type'
@@ -106,18 +125,18 @@ export const run = async (
106
125
  for (let j = 0; j < files.length; j++) {
107
126
  const file = files[j];
108
127
  const filenamearr = file.split('.');
109
- if (_.last(filenamearr) != 'json'){
110
- log.warn(file," skip")
128
+ if (_.last(filenamearr) != 'json') {
129
+ log.warn(file, ' skip');
111
130
  continue;
112
131
  }
113
-
132
+
114
133
  const fullfilename = `${configs.jsonschemaFolder}/${file}`;
115
134
  try {
116
135
  const jsoncontent = readFileSync(fullfilename, 'utf-8');
117
136
  // log.info("Process ",fullfilename)
118
137
  // console.log("=====>>>>>",fullfilename)
119
138
  const jsonschema = JSON.parse(jsoncontent);
120
- const schemaconfig:SchemaConfig = jsonschema['x-simpleapp-config'];
139
+ const schemaconfig: SchemaConfig = jsonschema['x-simpleapp-config'];
121
140
  if (schemaconfig['printFormats']) {
122
141
  const formats: SchemaPrintFormat[] = schemaconfig['printFormats'];
123
142
  for (let formatno = 0; formatno < formats.length; formatno++) {
@@ -173,7 +192,7 @@ const processSchema = async (schemaname: string, jsondata: JSONSchema7) => {
173
192
  const config: SchemaConfig = jsondata['x-simpleapp-config'];
174
193
  let doctype = config.documentType;
175
194
  let docname = config.documentName;
176
- let resourceName = config.resourceName
195
+ let resourceName = config.resourceName;
177
196
  const rendertype = 'basic';
178
197
  jsonschemas[docname] = jsondata;
179
198
  const copyofjsonschema = { ...jsondata };
@@ -184,23 +203,22 @@ const processSchema = async (schemaname: string, jsondata: JSONSchema7) => {
184
203
  (item) => item.doctype == doctype
185
204
  );
186
205
  if (moduleindex < 0) {
187
-
188
- const api = config.additionalApis ?? []
189
- if(copyofjsonschema['x-simpleapp-config']['printFormats']){
190
- api.push({
191
- "action": "runPrint",
192
- "method": RESTMethods.get,
193
- "entryPoint": ":id/print/:formatId",
194
- "responseType": "String",
195
- "requiredRole": ["User"],
196
- "description": "print pdf"
197
- })
206
+ const api = config.additionalApis ?? [];
207
+ if (copyofjsonschema['x-simpleapp-config']['printFormats']) {
208
+ api.push({
209
+ action: 'runPrint',
210
+ method: RESTMethods.get,
211
+ entryPoint: ':id/print/:formatId',
212
+ responseType: 'String',
213
+ requiredRole: ['User'],
214
+ description: 'print pdf'
215
+ });
198
216
  }
199
217
  activatemodules.push({
200
218
  doctype: doctype,
201
219
  docname: capitalizeFirstLetter(docname),
202
220
  resourcename: resourceName,
203
- typename:capitalizeFirstLetter(resourceName),
221
+ typename: capitalizeFirstLetter(resourceName),
204
222
  pagetype: config.pageType ?? '',
205
223
  api: api,
206
224
  schema: copyofjsonschema
@@ -232,45 +250,46 @@ const generateSchema = (
232
250
  const finalizefolder = `${constants.templatedir}/nest`;
233
251
  const modelname = _.upperFirst(docname);
234
252
  const currentmodel = allmodels[modelname];
235
- const xconfig:SchemaConfig = jsonschemas[docname]?.['x-simpleapp-config']
236
- const apiSettings = currentmodel.apiSettings?? []
253
+ const xconfig: SchemaConfig = jsonschemas[docname]?.['x-simpleapp-config'];
254
+ const apiSettings = currentmodel.apiSettings ?? [];
237
255
  const resourceName = xconfig?.resourceName ?? docname;
238
- if(xconfig.getPhoto){
239
- apiSettings.push( {
240
- action: 'getPhoto',
241
- entryPoint: ':id/photo',
242
- requiredRole: ['Everyone'],
243
- method: RESTMethods.get,
244
- responseType: 'String',
245
- description: 'Get photo'
246
- },)
247
- jsonschemas['imageUrl']={type:'string'}
256
+ if (xconfig.getPhoto) {
257
+ apiSettings.push({
258
+ action: 'getPhoto',
259
+ entryPoint: ':id/photo',
260
+ requiredRole: ['Everyone'],
261
+ method: RESTMethods.get,
262
+ responseType: 'String',
263
+ description: `Get ${capitalizeFirstLetter(resourceName)} photo`
264
+ });
265
+ jsonschemas['imageUrl'] = { type: 'string' };
248
266
  }
249
- if(xconfig.uploadPhoto){
250
- apiSettings.push( {
251
- action: 'uploadPhoto',
252
- entryPoint: ':id/photo',
253
- requiredRole: [capitalizeFirstLetter(resourceName)+'_create'],
254
- schema: 'KeyValue',
255
- method: RESTMethods.post,
256
- responseType: 'String',
257
- description: 'upload photo'
258
- },)
267
+
268
+ if (xconfig.uploadPhoto) {
269
+ apiSettings.push({
270
+ action: 'uploadPhoto',
271
+ entryPoint: ':id/photo',
272
+ requiredRole: [capitalizeFirstLetter(resourceName) + '_create'],
273
+ schema: 'UploadPhoto',
274
+ method: RESTMethods.post,
275
+ responseType: 'String',
276
+ description: `Upload ${capitalizeFirstLetter(resourceName)} photo`
277
+ });
259
278
  }
260
-
261
- if(Array.isArray(xconfig.printFormats) && xconfig.printFormats.length>0){
262
- apiSettings.push( {
263
- action: 'print',
264
- entryPoint: ':id/print/:formatId',
265
- requiredRole: [capitalizeFirstLetter(resourceName)+'_print'],
266
- method: RESTMethods.get,
267
- responseType: 'String',
268
- description: 'obtain base64 pdf'
269
- },)
279
+
280
+ if (Array.isArray(xconfig.printFormats) && xconfig.printFormats.length > 0) {
281
+ apiSettings.push({
282
+ action: 'print',
283
+ entryPoint: ':id/print/:formatId',
284
+ requiredRole: [capitalizeFirstLetter(resourceName) + '_print'],
285
+ method: RESTMethods.get,
286
+ responseType: 'String',
287
+ description: 'obtain base64 pdf'
288
+ });
270
289
  }
271
290
  // if(xconfig)
272
-
273
- const resourceFileName = camelToKebab(resourceName)
291
+
292
+ const resourceFileName = camelToKebab(resourceName);
274
293
  //console.log("---^^^^^------",modelname,docname, doctype, rendertype,currentmodel,allmodels)
275
294
 
276
295
  const miniAppWhitelistApis =
@@ -281,7 +300,7 @@ const generateSchema = (
281
300
  doctype: doctype,
282
301
  models: allmodels,
283
302
  getPhoto: xconfig.getPhoto,
284
- uploadPhoto:xconfig.uploadPhoto,
303
+ uploadPhoto: xconfig.uploadPhoto,
285
304
  autocompletecode: currentmodel.codeField ?? '',
286
305
  autocompletename: currentmodel.nameField ?? '',
287
306
  moreAutoComplete: currentmodel.moreAutoComplete ?? [],
@@ -310,7 +329,6 @@ const generateSchema = (
310
329
  hasMiniAppWhitelistedApi: Object.keys(miniAppWhitelistApis).length > 0
311
330
  }
312
331
  };
313
-
314
332
 
315
333
  const templatefolder = `${constants.templatedir}/${rendertype}`;
316
334
  // log.info(`- Generate ${docname}, ${doctype}, ${templatefolder}`)
@@ -330,7 +348,7 @@ const generateSchema = (
330
348
  //generate code for every schema
331
349
  const generateTemplatefolder = `${constants.templatedir}/basic/${foldertype}`;
332
350
  const allfiles = readdirSync(generateTemplatefolder, { recursive: true });
333
-
351
+
334
352
  for (let j = 0; j < allfiles.length; j++) {
335
353
  const filename: string = String(allfiles[j]);
336
354
  const templatepath = `${generateTemplatefolder}/${filename}`;
@@ -363,8 +381,8 @@ const generateSchema = (
363
381
  if (autogeneratetypes.includes(filecategory)) {
364
382
  //multiple files in folder, append s at folder name
365
383
  let storein = `${backendTargetFolder}/_resources/${resourceFileName}`;
366
- if(systemResources.includes(docname)){
367
- storein=`${backendTargetFolder}/_core/resources/${resourceFileName}`
384
+ if (systemResources.includes(docname)) {
385
+ storein = `${backendTargetFolder}/_core/resources/${resourceFileName}`;
368
386
  }
369
387
  const targetfile = `${storein}/${resourceFileName}.${filecategory}.${filetype}`;
370
388
  if (!existsSync(storein)) {
@@ -374,21 +392,21 @@ const generateSchema = (
374
392
  const filecontent = eta.render(templatepath, variables);
375
393
  writeFileSync(targetfile, filecontent);
376
394
  // console.log("Write complete")
377
- } else if(['api'].includes(filecategory)){
378
- //if no define additional api, then no prepare additional api
395
+ } else if (['api'].includes(filecategory)) {
396
+ //if no define additional api, then no prepare additional api
379
397
  // continue
380
- if(variables.apiSettings.length==0){
381
- continue;
382
- }else{
383
- log.info("process additional api",docname);
398
+ if (variables.apiSettings.length == 0) {
399
+ continue;
400
+ } else {
401
+ log.info('process additional api', docname);
384
402
  }
385
403
 
386
- const arrcategory = filename.split('.')
404
+ const arrcategory = filename.split('.');
387
405
  // console.log("process",docname, arrcategory);
388
- const subcategory = arrcategory[0]
389
- const subcategoryscope = arrcategory[1]
390
- const subcategorytype = arrcategory[2]
391
-
406
+ const subcategory = arrcategory[0];
407
+ const subcategoryscope = arrcategory[1];
408
+ const subcategorytype = arrcategory[2];
409
+
392
410
  const targetfolder = `${simpleappTargetFolder}/${subcategory}s/${resourceFileName}-api`;
393
411
  const targetfile = `${targetfolder}/${resourceFileName}-api.${subcategoryscope}.${subcategorytype}`;
394
412
  if (!existsSync(targetfolder)) {
@@ -396,10 +414,12 @@ const generateSchema = (
396
414
  }
397
415
 
398
416
  //if controller will always override
399
- if ( targetfile.includes('controller') || targetfile.includes('resolver') ||
400
- (!existsSync(targetfile) ||
417
+ if (
418
+ targetfile.includes('controller') ||
419
+ targetfile.includes('resolver') ||
420
+ !existsSync(targetfile) ||
401
421
  readFileSync(targetfile, 'utf-8').includes(
402
- '--remove-this-line-to-prevent-override--')
422
+ '--remove-this-line-to-prevent-override--'
403
423
  )
404
424
  ) {
405
425
  // log.info("Write ",targetfile)
@@ -408,14 +428,14 @@ const generateSchema = (
408
428
  } else {
409
429
  // log.info("skip ",targetfile)
410
430
  }
411
- }else if (['event'].includes(filecategory)) {
431
+ } else if (['event'].includes(filecategory)) {
412
432
  //service file won't override if exists
413
- const arrcategory = filename.split('.')
414
- console.log("process",docname, arrcategory);
415
- const subcategory = arrcategory[0]
416
- const subcategoryscope = arrcategory[1]
417
- const subcategorytype = arrcategory[2]
418
-
433
+ const arrcategory = filename.split('.');
434
+ console.log('process', docname, arrcategory);
435
+ const subcategory = arrcategory[0];
436
+ const subcategoryscope = arrcategory[1];
437
+ const subcategorytype = arrcategory[2];
438
+
419
439
  const targetfolder = `${simpleappTargetFolder}/${subcategory}s/${resourceFileName}`;
420
440
  const targetfile = `${targetfolder}/${resourceFileName}.${subcategoryscope}.${subcategorytype}`;
421
441
  if (!existsSync(targetfolder)) {
@@ -423,10 +443,11 @@ const generateSchema = (
423
443
  }
424
444
 
425
445
  //if controller will always override
426
- if ( targetfile.includes('controller.ts') ||
427
- (!existsSync(targetfile) ||
446
+ if (
447
+ targetfile.includes('controller.ts') ||
448
+ !existsSync(targetfile) ||
428
449
  readFileSync(targetfile, 'utf-8').includes(
429
- '--remove-this-line-to-prevent-override--')
450
+ '--remove-this-line-to-prevent-override--'
430
451
  )
431
452
  ) {
432
453
  // log.info("Write ",targetfile)
@@ -742,7 +763,7 @@ const processPlatformFileMiniApi = (
742
763
  ) => {
743
764
  const mapfiles = {
744
765
  'resource.service.ts.eta': {
745
- to: `src/mini-app/resource/resources/${_.kebabCase(resourceName)}`,
766
+ to: `src/modules/resource/resources/${_.kebabCase(resourceName)}`,
746
767
  as: `${_.kebabCase(resourceName)}.service.ts`,
747
768
  validate: (targetfile: string, isexists: boolean) => {
748
769
  const {
@@ -757,7 +778,7 @@ const processPlatformFileMiniApi = (
757
778
  }
758
779
  },
759
780
  'resource.controller.ts.eta': {
760
- to: `src/mini-app/resource/resources/${_.kebabCase(resourceName)}`,
781
+ to: `src/modules/resource/resources/${_.kebabCase(resourceName)}`,
761
782
  as: `${_.kebabCase(resourceName)}.controller.ts`,
762
783
  validate: (targetfile: string, isexists: boolean) => {
763
784
  const {
@@ -772,7 +793,7 @@ const processPlatformFileMiniApi = (
772
793
  }
773
794
  },
774
795
  'resource.module.ts.eta': {
775
- to: `src/mini-app/resource/resources/${_.kebabCase(resourceName)}`,
796
+ to: `src/modules/resource/resources/${_.kebabCase(resourceName)}`,
776
797
  as: `${_.kebabCase(resourceName)}.module.ts`,
777
798
  validate: (targetfile: string, isexists: boolean) => {
778
799
  const {
@@ -905,11 +926,10 @@ const prepareRoles = (groupsettings) => {
905
926
  };
906
927
 
907
928
  function camelToKebab(key) {
908
- var result = key.replace( /([A-Z])/g, " $1" );
909
- return result.split(' ').join('-').toLowerCase();
929
+ var result = key.replace(/([A-Z])/g, ' $1');
930
+ return result.split(' ').join('-').toLowerCase();
910
931
  }
911
932
 
912
-
913
933
  const getCodeGenHelper = () =>
914
934
  'const capitalizeFirstLetter = (str) => !str ? `Object` : str.slice(0, 1).toUpperCase() + str.slice(1);' +
915
935
  'const initType=(str)=>{return ["string","number","boolean","array","object"].includes(str) ? capitalizeFirstLetter(str) : str;};' +
@@ -918,8 +938,11 @@ const getCodeGenHelper = () =>
918
938
  'const camelToKebab = (value) => { return value.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(); };' +
919
939
  'const removeSuffix = (input, suffix) => { return input.endsWith(suffix) ? input.slice(0, -suffix.length) : input };' +
920
940
  'const isWhitelistedMiniApp = (actionName, it) => { return it.miniApp.whitelistApis?.[actionName] === true };' +
921
- 'const titleCase = (value) => { return value.replace(/([a-z])([A-Z])/g, "$1 $2"); }; '+
922
- 'const systemType = () => [ "String","Number","Boolean","Array","Object"];'+
923
- 'const toTypeName = (resName,fieldName)=>{return ["string","number","boolean","array","object"].includes(fieldName.toLowerCase())? capitalizeFirstLetter(fieldName) :upperFirstCase(resName) + fieldName.slice(resName.length)};'+
924
- 'const skipIsolationDocument = () => ' + JSON.stringify(skipIsolationDocument)+';'+
925
- 'const getSystemResources = () => '+JSON.stringify(systemResources);
941
+ 'const titleCase = (value) => { return value.replace(/([a-z])([A-Z])/g, "$1 $2"); }; ' +
942
+ 'const systemType = () => [ "String","Number","Boolean","Array","Object"];' +
943
+ 'const toTypeName = (resName,fieldName)=>{return ["string","number","boolean","array","object"].includes(fieldName.toLowerCase())? capitalizeFirstLetter(fieldName) :upperFirstCase(resName) + fieldName.slice(resName.length)};' +
944
+ 'const skipIsolationDocument = () => ' +
945
+ JSON.stringify(skipIsolationDocument) +
946
+ ';' +
947
+ 'const getSystemResources = () => ' +
948
+ JSON.stringify(systemResources);
@@ -120,6 +120,20 @@ export class <%= pascalName %>Controller {
120
120
  ) {
121
121
  return await this.<%= serviceVariable %>.patch(headers, id, resourceDto);
122
122
  }
123
+ <% } else if(action === 'patchMany') { %>
124
+ @Patch('patchMany')
125
+ @ApiOperation({ operationId: 'patchMany' })
126
+ @ApiBody({ type: SimtrainSchema.PatchManyRequestDto, required: true })
127
+ @ApiResponse({ status: 200, description: 'Success', type: SimtrainSchema.UpdateManyResponseDto })
128
+ @ApiResponse({ status: 400, description: 'Bad Request' })
129
+ @ApiResponse({ status: 404, description: 'Not Found' })
130
+ @ApiResponse({ status: 500, description: 'Internal Error' })
131
+ async patchMany(
132
+ @Headers() headers: ApiHeader,
133
+ @Body() resourceDto: any,
134
+ ) {
135
+ return await this.<%= serviceVariable %>.patchMany(headers, resourceDto);
136
+ }
123
137
  <% } else if(action === 'delete') { %>
124
138
  @Delete(':id')
125
139
  @ApiOperation({ operationId: 'delete' })
@@ -86,6 +86,12 @@ export class <%= pascalName %>Service {
86
86
  const resp = await api.runPatch(id, resourceDto);
87
87
  return resp.data;
88
88
  }
89
+ <% } else if(action === 'patchMany') { %>
90
+ async patchMany(headers: ApiHeader, resourceDto: any) {
91
+ const api = this.getApi(headers);
92
+ const resp = await api.runPatchMany(resourceDto);
93
+ return resp.data;
94
+ }
89
95
  <% } else if(action === 'delete') { %>
90
96
  async delete(headers: ApiHeader, id: string) {
91
97
  const api = this.getApi(headers);
@@ -81,52 +81,6 @@ export class <%= it.typename %>Controller extends SimpleAppController<
81
81
  async runDefault(@AppUser() appuser: UserContext) {
82
82
  return await this.service.runDefault(appuser)
83
83
  }
84
- //autocomplete shall above :id
85
- @Post('/autocomplete')
86
- <%if(superadmindoctype.includes(it.doctype)){%>
87
- @Roles(Role.SuperAdmin,Role.<%= `${it.typename}_search`%>)
88
- <%}else{%>
89
- @Roles(Role.SuperAdmin,Role.SuperUser,Role.User)
90
- <%}%>
91
- @ApiResponse({
92
- status: 200,
93
- description: 'Found',
94
- type: schemas.<%= it.typename %>AutoComplete,
95
- isArray: true,
96
- })
97
- @ApiResponse({ status: 500, description: 'Internal error' })
98
- @ApiQuery({ name: 'keyword', type:String})
99
- @ApiBody({ description: 'Data', type: ()=>Object})
100
- @ApiOperation({ operationId: 'autoComplete',description:"retrieve array of {_id, code, name}" })
101
- <%~ drawMiniAppScope('autoComplete') %>
102
- async autoComplete(@AppUser() appuser: UserContext,
103
- @Query('keyword') keyword:string,
104
- @Body() data: schemas.<%=it.typename%>,
105
- ) {
106
- return this._autocomplete(appuser, keyword,data);
107
- }
108
-
109
-
110
-
111
- @Post()
112
- <%if(superadmindoctype.includes(it.doctype)){%>
113
- @Roles(Role.SuperAdmin,Role.<%= `${it.typename}_create`%>)
114
- <%}else{%>
115
- @Roles(Role.SuperAdmin,Role.SuperUser,Role.<%= `${it.typename}_create`%>)
116
- <%}%>
117
- @ApiResponse({
118
- status: 201,
119
- description: 'success',
120
- type: schemas.<%= it.typename%>
121
- })
122
- @ApiResponse({ status: 400, description: 'bad request' })
123
- @ApiResponse({ status: 500, description: 'internal error' })
124
- @ApiBody({ description: 'Data',type:schemas.<%= it.typename%> })
125
- @ApiOperation({ operationId: 'runCreate' })
126
- <%~ drawMiniAppScope('create') %>
127
- async create(@AppUser() appuser: UserContext,@Body() data: schemas.<%= it.typename%>) {
128
- return await this._create(appuser,data)
129
- }
130
84
 
131
85
  @Post('/search')
132
86
  @HttpCode(200)
@@ -149,7 +103,6 @@ export class <%= it.typename %>Controller extends SimpleAppController<
149
103
  return await this._search(appuser,data)
150
104
  }
151
105
 
152
-
153
106
  <% if(simpleappconfig.search !==undefined){%>
154
107
  @Post('/fulltextsearch')
155
108
  @HttpCode(200)
@@ -171,33 +124,6 @@ export class <%= it.typename %>Controller extends SimpleAppController<
171
124
  }
172
125
  <%}%>
173
126
 
174
-
175
- @Patch('bulk-patch')
176
- @ApiResponse({ status: 200, description: 'success',})
177
- @Roles(Role.SuperAdmin, Role.SuperUser, Role.<%= it.typename%>_update)
178
- @ApiResponse({ status: 404, description: 'Document not found' })
179
- @ApiResponse({ status: 500, description: 'Internal error' })
180
- @ApiBody({ description: 'Data', type: schemas.PatchManyRequest<schemas.<%= it.typename%>> })
181
- @ApiOperation({ operationId: 'runPatchMany' })
182
- <%~ drawMiniAppScope('patch-many') %>
183
- async patchMany(@AppUser() appuser: UserContext, @Param('id') id: string, @Body() patchManyData: schemas.PatchManyRequest<schemas.<%= it.typename%>>) {
184
- return await this._patchMany(appuser, id, patchManyData);
185
- }
186
-
187
-
188
- /***************************** start status control api definitions *****************************************/
189
- <%for(let s=0; s<it.docStatusSettings.length; s++){ %>
190
- <%let statusconf = it.docStatusSettings[s]%>
191
- <%let statusname = statusconf['status']%>
192
- @Post(':id/set-<%=statusname%>')
193
- @ApiBody({ description: 'Document data', type: Object })
194
- @Roles(Role.SuperAdmin,Role.<%= `${it.typename}_${statusname}`%>)
195
- async setStatus<%=capitalizeFirstLetter(statusname)%>(@AppUser() appuser: UserContext,@Param('id') id: string, @Body() data:any,){
196
- return await this.service.setDocumentStatus(appuser,id,data,'<%=statusname%>',)
197
- }
198
- <%}%>
199
- /***************************** end status control api definitions *****************************************/
200
-
201
127
  @Get(':id')
202
128
  <%if(superadmindoctype.includes(it.doctype)){%>
203
129
  @Roles(Role.SuperAdmin,Role.<%= `${it.typename}_search`%>)
@@ -221,8 +147,52 @@ export class <%= it.typename %>Controller extends SimpleAppController<
221
147
  return data
222
148
  }
223
149
  }
224
-
225
150
 
151
+ //autocomplete shall above :id
152
+ @Post('/autocomplete')
153
+ <%if(superadmindoctype.includes(it.doctype)){%>
154
+ @Roles(Role.SuperAdmin,Role.<%= `${it.typename}_search`%>)
155
+ <%}else{%>
156
+ @Roles(Role.SuperAdmin,Role.SuperUser,Role.User)
157
+ <%}%>
158
+ @ApiResponse({
159
+ status: 200,
160
+ description: 'Found',
161
+ type: schemas.<%= it.typename %>AutoComplete,
162
+ isArray: true,
163
+ })
164
+ @ApiResponse({ status: 500, description: 'Internal error' })
165
+ @ApiQuery({ name: 'keyword', type:String})
166
+ @ApiBody({ description: 'Data', type: ()=>Object})
167
+ @ApiOperation({ operationId: 'autoComplete',description:"retrieve array of {_id, code, name}" })
168
+ <%~ drawMiniAppScope('autoComplete') %>
169
+ async autoComplete(@AppUser() appuser: UserContext,
170
+ @Query('keyword') keyword:string,
171
+ @Body() data: schemas.<%=it.typename%>,
172
+ ) {
173
+ return this._autocomplete(appuser, keyword,data);
174
+ }
175
+
176
+ @Post()
177
+ <%if(superadmindoctype.includes(it.doctype)){%>
178
+ @Roles(Role.SuperAdmin,Role.<%= `${it.typename}_create`%>)
179
+ <%}else{%>
180
+ @Roles(Role.SuperAdmin,Role.SuperUser,Role.<%= `${it.typename}_create`%>)
181
+ <%}%>
182
+ @ApiResponse({
183
+ status: 201,
184
+ description: 'success',
185
+ type: schemas.<%= it.typename%>
186
+ })
187
+ @ApiResponse({ status: 400, description: 'bad request' })
188
+ @ApiResponse({ status: 500, description: 'internal error' })
189
+ @ApiBody({ description: 'Data',type:schemas.<%= it.typename%> })
190
+ @ApiOperation({ operationId: 'runCreate' })
191
+ <%~ drawMiniAppScope('create') %>
192
+ async create(@AppUser() appuser: UserContext,@Body() data: schemas.<%= it.typename%>) {
193
+ return await this._create(appuser,data)
194
+ }
195
+
226
196
  @Put(':id')
227
197
  @ApiResponse({
228
198
  status: 200,
@@ -241,6 +211,7 @@ export class <%= it.typename %>Controller extends SimpleAppController<
241
211
  async update(@AppUser() appuser: UserContext,@Param('id') id: string, @Body() data: schemas.<%= it.typename%>) {
242
212
  return await this._update(appuser,id, data) ;
243
213
  }
214
+
244
215
  @Patch(':id')
245
216
  @ApiResponse({
246
217
  status: 200,
@@ -260,6 +231,18 @@ export class <%= it.typename %>Controller extends SimpleAppController<
260
231
  return await this._patch(appuser,id, data) ;
261
232
  }
262
233
 
234
+ @Patch('bulk-patch')
235
+ @ApiResponse({ status: 200, description: 'success', type: schemas.UpdateManyResponse})
236
+ @Roles(Role.SuperAdmin, Role.SuperUser, Role.<%= it.typename%>_update)
237
+ @ApiResponse({ status: 404, description: 'Document not found' })
238
+ @ApiResponse({ status: 500, description: 'Internal error' })
239
+ @ApiBody({ description: 'Data', type: schemas.PatchManyRequest<schemas.<%= it.typename%>> })
240
+ @ApiOperation({ operationId: 'runPatchMany' })
241
+ <%~ drawMiniAppScope('patch-many') %>
242
+ async patchMany(@AppUser() appuser: UserContext, @Body() patchManyData: schemas.PatchManyRequest<schemas.<%= it.typename%>>) {
243
+ return await this._patchMany(appuser, patchManyData);
244
+ }
245
+
263
246
  @Delete(':id')
264
247
  <%if(superadmindoctype.includes(it.doctype)){%>
265
248
  @Roles(Role.SuperAdmin,Role.<%= `${it.typename}_delete`%>)
@@ -279,6 +262,17 @@ export class <%= it.typename %>Controller extends SimpleAppController<
279
262
  return this._delete(appuser,id);
280
263
  }
281
264
 
282
-
265
+ /***************************** start status control api definitions *****************************************/
266
+ <%for(let s=0; s<it.docStatusSettings.length; s++){ %>
267
+ <%let statusconf = it.docStatusSettings[s]%>
268
+ <%let statusname = statusconf['status']%>
269
+ @Post(':id/set-<%=statusname%>')
270
+ @ApiBody({ description: 'Document data', type: Object })
271
+ @Roles(Role.SuperAdmin,Role.<%= `${it.typename}_${statusname}`%>)
272
+ async setStatus<%=capitalizeFirstLetter(statusname)%>(@AppUser() appuser: UserContext,@Param('id') id: string, @Body() data:any,){
273
+ return await this.service.setDocumentStatus(appuser,id,data,'<%=statusname%>',)
274
+ }
275
+ <%}%>
276
+ /***************************** end status control api definitions *****************************************/
283
277
 
284
278
  }
@@ -146,10 +146,10 @@
146
146
  */
147
147
  import { SimpleAppInputType,FormCrudEvent } from "~/types";
148
148
  import { <%= it.typename %> } from "~/simpleapp/generate/types";
149
- import { <%= it.typename %>Doc} from "~/simpleapp/docs/<%= capitalizeFirstLetter(it.name) %>Doc"
149
+ import { <%= capitalizeFirstLetter(it.name) %>Doc} from "~/simpleapp/docs/<%= capitalizeFirstLetter(it.name) %>Doc"
150
150
 
151
151
 
152
- const props = defineProps<{ _id?: string, doc?: <%= it.typename %>Doc , paras?:<%= it.typename %>}>();
152
+ const props = defineProps<{ _id?: string, doc?: <%= capitalizeFirstLetter(it.name) %>Doc , paras?:<%= it.typename %>}>();
153
153
  const doc = props.doc ?? useNuxtApp().$<%= capitalizeFirstLetter(it.name) %>Doc()
154
154
  const data = doc.getReactiveData();
155
155
  const emits = defineEmits(["after"]);
@@ -19,8 +19,8 @@
19
19
  import { <%= it.typename %> } from '~/simpleapp/generate/openapi';
20
20
 
21
21
 
22
- const {$<%= it.typename %>Doc,$listen } = useNuxtApp();
23
- const doc = $<%= it.typename %>Doc()
22
+ const {$<%= capitalizeFirstLetter(it.name) %>Doc,$listen } = useNuxtApp();
23
+ const doc = $<%= capitalizeFirstLetter(it.name) %>Doc()
24
24
  const docdata = doc.getReactiveData();
25
25
  type <%= it.typename %>Key = keyof <%= it.typename %>
26
26