@simitgroup/simpleapp-generator 1.0.46 → 1.0.47

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 (34) hide show
  1. package/dist/framework.js +2 -2
  2. package/dist/framework.js.map +1 -1
  3. package/dist/generate.js +9 -9
  4. package/dist/generate.js.map +1 -1
  5. package/dist/processors/jsonschemabuilder.d.ts.map +1 -1
  6. package/dist/processors/jsonschemabuilder.js +10 -0
  7. package/dist/processors/jsonschemabuilder.js.map +1 -1
  8. package/dist/type.d.ts +114 -22
  9. package/dist/type.d.ts.map +1 -1
  10. package/package.json +1 -1
  11. package/src/framework.ts +2 -2
  12. package/src/generate.ts +9 -9
  13. package/src/processors/jsonschemabuilder.ts +14 -1
  14. package/src/type.ts +136 -22
  15. package/templates/basic/nest/processor.ts.eta +3 -1
  16. package/templates/basic/nuxt/pages.crud.vue.eta +2 -1
  17. package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +18 -2
  18. package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +13 -2
  19. package/templates/nest/src/simpleapp/services/docno.service.ts.eta +5 -4
  20. package/templates/nuxt/components/CrudNestedDoc.vue.eta +5 -1
  21. package/templates/nuxt/components/ListView.vue.eta +52 -0
  22. package/templates/nuxt/components/SimpleAppDocumentNo.vue.eta +1 -1
  23. package/templates/nuxt/layouts/sidelistcrud.vue.eta +43 -0
  24. package/templates/nuxt/pages/[xorg]/docnoformat/index.vue.eta +290 -233
  25. package/templates/project/schemas/category.ts.eta +40 -27
  26. package/templates/project/schemas/customer.ts.eta +35 -0
  27. package/templates/project/schemas/index.ts.eta +4 -4
  28. package/templates/project/schemas/invoice.ts.eta +55 -0
  29. package/templates/project/schemas/product.ts.eta +41 -57
  30. package/templates/project/sharelibs/index.ts.eta +2 -0
  31. package/templates/project/sharelibs/money.ts.eta +17 -0
  32. package/tsconfig.tsbuildinfo +1 -1
  33. package/templates/project/shares/index.ts.eta +0 -2
  34. /package/templates/project/{shares → sharelibs}/hello.ts.eta +0 -0
package/src/type.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { JSONSchema7, JSONSchema7Definition } from 'json-schema';
1
+ import { JSONSchema7,JSONSchema7Type,JSONSchema7Version, JSONSchema7TypeName,JSONSchema7Definition } from 'json-schema';
2
2
  export type ChildModels = {
3
3
  [key: string]: {
4
4
  type: string;
@@ -78,7 +78,7 @@ apiSchemaName: string
78
78
  typename: string
79
79
  fullApiSchemaName: string
80
80
  fullTypeName:string
81
- jsonschema: JSONSchema7
81
+ jsonschema: SimpleAppJSONSchema7
82
82
  bothEndCode: string
83
83
  frontEndCode: string
84
84
  backEndCode: string
@@ -123,14 +123,14 @@ export type DocumentApi = {
123
123
  description:string //description of api
124
124
  }
125
125
  export enum IsolationType {"none"="none" , "tenant"="tenant","org"="org", "branch"="branch"}
126
- export type ImportLibs = {"lib":string,"as":string}
126
+ // export type ImportLibs = {"lib":string,"as":string}
127
127
  export type Formula = {
128
128
  "jsonpath":string //example: "$.subtotal","$.details[*]"
129
129
  "formula":string //example "jslib.getDocumentSubTotal(@F{$.details})"
130
130
  }
131
131
 
132
132
  export type SchemaConfig = {
133
- isolationType: IsolationType
133
+ isolationType: IsolationType
134
134
  requiredRoles?:string[]
135
135
  pageType?: string
136
136
  uniqueKey?:string
@@ -140,7 +140,7 @@ export type SchemaConfig = {
140
140
  allStatus?:DocumentStatus[]
141
141
  additionalApis?:DocumentApi[]
142
142
  additionalAutoCompleteFields ?: string[]
143
- libs?:ImportLibs[] // both process class and frontend client class will import same lib
143
+ // libs?:ImportLibs[] // both process class and frontend client class will import same lib
144
144
  formulas?: Formula[]
145
145
  documentType: string
146
146
  documentName: string
@@ -148,28 +148,142 @@ export type SchemaConfig = {
148
148
  foreignKeys?:MyForeignKey,
149
149
  }
150
150
 
151
- // export type DefaultSchemaDefinitions = {
152
- // [key:string]:JSONSchema7Object
153
- // }
154
- export type ForeignKeyProperty = {'x-foreignkey' ?:string}
151
+
155
152
  export type SchemaFields = {
156
- _id: JSONSchema7
157
- tenantId: JSONSchema7 & ForeignKeyProperty
158
- orgId: JSONSchema7 & ForeignKeyProperty
159
- branchId: JSONSchema7 & ForeignKeyProperty
160
- created: JSONSchema7
161
- updated: JSONSchema7
162
- createdby: JSONSchema7
163
- updatedby: JSONSchema7
164
- [key:string]:JSONSchema7 & ForeignKeyProperty
153
+ _id: SimpleAppJSONSchema7
154
+ tenantId: SimpleAppJSONSchema7
155
+ orgId: SimpleAppJSONSchema7
156
+ branchId: SimpleAppJSONSchema7
157
+ created: SimpleAppJSONSchema7
158
+ updated: SimpleAppJSONSchema7
159
+ createdby: SimpleAppJSONSchema7
160
+ updatedby: SimpleAppJSONSchema7
161
+ [key:string]:SimpleAppJSONSchema7 | SimpleAppJSONSchema7[] | undefined
162
+
165
163
  }
166
164
 
167
- export type AdditionalSchemaType = {
168
- "x-simpleapp-config":SchemaConfig
169
- properties: SchemaFields
165
+
166
+ export type SchemaType = {
167
+ type:string
168
+ definitions?:SimpleAppJSONSchema7
169
+ required?:string[]
170
+
171
+ "x-simpleapp-config":SchemaConfig
172
+ properties: SchemaFields
170
173
  }
171
174
 
172
- export type SchemaType = JSONSchema7 & AdditionalSchemaType
173
175
 
174
176
 
175
177
 
178
+ // modified from jsonschemas
179
+ export type SimpleAppJSONSchema7Definition = SimpleAppJSONSchema7 | boolean;
180
+ export interface SimpleAppJSONSchema7 {
181
+
182
+ 'x-foreignkey' ?:string
183
+ $id?: string | undefined;
184
+ $ref?: string | undefined;
185
+ $schema?: JSONSchema7Version | undefined;
186
+ $comment?: string | undefined;
187
+
188
+ /**
189
+ * @see https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-8.2.4
190
+ * @see https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00#appendix-A
191
+ */
192
+ $defs?: {
193
+ [key: string]: JSONSchema7Definition;
194
+ } | undefined;
195
+
196
+ /**
197
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1
198
+ */
199
+ type?: JSONSchema7TypeName | JSONSchema7TypeName[] | undefined;
200
+ enum?: JSONSchema7Type[] | undefined;
201
+ const?: JSONSchema7Type | undefined;
202
+
203
+ /**
204
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.2
205
+ */
206
+ multipleOf?: number | undefined;
207
+ maximum?: number | undefined;
208
+ exclusiveMaximum?: number | undefined;
209
+ minimum?: number | undefined;
210
+ exclusiveMinimum?: number | undefined;
211
+
212
+ /**
213
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.3
214
+ */
215
+ maxLength?: number | undefined;
216
+ minLength?: number | undefined;
217
+ pattern?: string | undefined;
218
+
219
+ /**
220
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.4
221
+ */
222
+ items?: SimpleAppJSONSchema7Definition | SimpleAppJSONSchema7Definition[] | undefined;
223
+ additionalItems?: JSONSchema7Definition | undefined;
224
+ maxItems?: number | undefined;
225
+ minItems?: number | undefined;
226
+ uniqueItems?: boolean | undefined;
227
+ contains?: SimpleAppJSONSchema7Definition | undefined;
228
+
229
+ /**
230
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.5
231
+ */
232
+ maxProperties?: number | undefined;
233
+ minProperties?: number | undefined;
234
+ required?: string[] | undefined;
235
+ properties?: {
236
+ [key: string]: SimpleAppJSONSchema7Definition;
237
+ } | undefined;
238
+ patternProperties?: {
239
+ [key: string]: SimpleAppJSONSchema7Definition;
240
+ } | undefined;
241
+ additionalProperties?: SimpleAppJSONSchema7Definition | undefined;
242
+ dependencies?: {
243
+ [key: string]: SimpleAppJSONSchema7Definition | string[];
244
+ } | undefined;
245
+ propertyNames?: SimpleAppJSONSchema7Definition | undefined;
246
+
247
+ /**
248
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.6
249
+ */
250
+ if?: SimpleAppJSONSchema7Definition | undefined;
251
+ then?: SimpleAppJSONSchema7Definition | undefined;
252
+ else?: SimpleAppJSONSchema7Definition | undefined;
253
+
254
+ /**
255
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.7
256
+ */
257
+ allOf?: SimpleAppJSONSchema7Definition[] | undefined;
258
+ anyOf?: SimpleAppJSONSchema7Definition[] | undefined;
259
+ oneOf?: SimpleAppJSONSchema7Definition[] | undefined;
260
+ not?: SimpleAppJSONSchema7Definition | undefined;
261
+
262
+ /**
263
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-7
264
+ */
265
+ format?: string | undefined;
266
+
267
+ /**
268
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-8
269
+ */
270
+ contentMediaType?: string | undefined;
271
+ contentEncoding?: string | undefined;
272
+
273
+ /**
274
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-9
275
+ */
276
+ definitions?: {
277
+ [key: string]: JSONSchema7Definition;
278
+ } | undefined;
279
+
280
+ /**
281
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-10
282
+ */
283
+ title?: string | undefined;
284
+ description?: string | undefined;
285
+ default?: JSONSchema7Type | undefined;
286
+ readOnly?: boolean | undefined;
287
+ writeOnly?: boolean | undefined;
288
+ examples?: JSONSchema7Type | undefined;
289
+ }
@@ -27,7 +27,9 @@ import { <%Object.keys(it.models).forEach(function(modelname) { %> Default<%=mo
27
27
  export class <%= it.typename %>Processor extends SimpleAppService<<%= it.typename %>> {
28
28
  protected documentIdentityCode='<%~ it.autocompletecode %>'
29
29
  protected documentIdentityLabel='<%~ it.autocompletename %>'
30
- protected withDocNumberFormat= <%= it.hasdocformat %>
30
+ <%if(it.jsonschema['x-simpleapp-config']['generateDocumentNumber']){%>
31
+ protected withDocNumberFormat = true
32
+ <%}%>
31
33
 
32
34
  protected foreignkeys = <%~ JSON.stringify(it.foreignkeys)%>
33
35
 
@@ -125,8 +125,9 @@
125
125
  <%let tablefields = Object.keys(obj.items.properties) %>
126
126
  <% for(let a=0;a<tablefields.length;a++){%>
127
127
  <%let col= tablefields[a] %>
128
+ <% if(skipcolumns.includes(col)){ continue}%>
128
129
  <%let subobj = obj.items.properties[col] %>
129
- <column field="<%=col%>" #body="{index}" :header="camelCaseToWords('<%=col%>')">
130
+ <column field="<%=col%>" #body="{index}" :header="camelCaseToWords('<%=col%>')">
130
131
  <%if(subobj['x-foreignkey']){%>
131
132
  <SimpleAppAutocomplete v-model="data.<%=key%>[index].<%=col%>"
132
133
  :setting="o.getField('#/properties/<%=key%>/items/properties/<%=col%>')"
@@ -5,7 +5,9 @@
5
5
  * last change 2023-09-23
6
6
  * Author: Ks Tan
7
7
  */
8
- import _ from 'lodash'
8
+ import _ from 'lodash'
9
+ import * as sharelibs from '../sharelibs'
10
+ import * as jsonpath from 'jsonpath'
9
11
  import { SimpleAppClient } from "./SimpleAppClient";
10
12
  import {
11
13
  <%Object.keys(it.models).forEach(function(modelname) { %> Default<%=modelname%>, <%})%>
@@ -47,6 +49,9 @@ export class <%= it.typename%>Client extends SimpleAppClient<<%= it.typename%>,<
47
49
  public readonly schema= <%~ JSON.stringify(it.jsonschema) %>;
48
50
  protected documentIdentityCode='<%~ it.autocompletecode %>'
49
51
  protected documentIdentityName='<%~ it.autocompletename %>'
52
+ <%if(it.jsonschema['x-simpleapp-config']['generateDocumentNumber']){%>
53
+ protected withDocNumberFormat = true
54
+ <%}%>
50
55
  constructor() {
51
56
  const {$event,$listen,$axios}=useNuxtApp()
52
57
  let xorg = useRoute().params.xorg
@@ -137,7 +142,18 @@ export class <%= it.typename%>Client extends SimpleAppClient<<%= it.typename%>,<
137
142
  reCalculateValue(){
138
143
  console.log('trigger new recalculate')
139
144
  const data = this.getData()
145
+
146
+ <% if(it.jsonschema['x-simpleapp-config']['formulas']){ %>
147
+ <%Object.keys(it.jsonschema['x-simpleapp-config']['formulas']).forEach(function(index) { %>
148
+ <% let fml = it.jsonschema['x-simpleapp-config']['formulas'][index] %>
149
+ // <%~ JSON.stringify(fml) %>
150
+ //const tmp = jsonpath.query(vdata,fieldpath).filter((item:string)=>item!='')
151
+
152
+ jsonpath.apply(data, '<%~ fml.jsonpath %>', function(value) { return <%~fml.formula %> });
140
153
 
154
+ <%}) %>
155
+ <%} %>
156
+ /*
141
157
  <%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
142
158
  <%let obj = it.jsonschema.properties[key]%>
143
159
  <%if(obj['x-compute']){%> //x-compute first level field
@@ -207,6 +223,6 @@ export class <%= it.typename%>Client extends SimpleAppClient<<%= it.typename%>,<
207
223
  <%}) %>
208
224
  }
209
225
  <%} /*process compute for 2nd level sub tables*/%>
210
- <%}) %>
226
+ <%}) %> */
211
227
  }
212
228
  }
@@ -255,6 +255,8 @@ export class SimpleAppService<T extends { _id?: string }> {
255
255
  if(!data._id){
256
256
  data._id = crypto.randomUUID()
257
257
  }
258
+
259
+ this.logger.debug('this.withDocNumberFormat :' + this.withDocNumberFormat + ' && ' + '!data[this.documentIdentityCode] ==' + !data[this.documentIdentityCode])
258
260
  if(this.withDocNumberFormat && !data[this.documentIdentityCode]){
259
261
  await this.genNewDocNo(appuser,data)
260
262
  }
@@ -277,7 +279,14 @@ export class SimpleAppService<T extends { _id?: string }> {
277
279
  this.applyNestedDateTime(appuser,data,'create')
278
280
  const newdoc = new this.doc(data);
279
281
 
280
- result = await newdoc.save({session:appuser.getDBSession()})
282
+ try{
283
+ result = await newdoc.save({session:appuser.getDBSession()})
284
+ }catch(err){
285
+ this.logger.error(err)
286
+ throw new InternalServerErrorException(err)
287
+ }
288
+
289
+
281
290
 
282
291
  // this.doc.create(data)
283
292
  // this.doc
@@ -327,7 +336,7 @@ export class SimpleAppService<T extends { _id?: string }> {
327
336
 
328
337
  ajv.addKeyword({ keyword: 'x-foreignkey', schemaType: 'string' });
329
338
  ajv.addKeyword({ keyword: 'x-simpleapp-config', schemaType: 'object' });
330
-
339
+
331
340
  const issuccess = await this.hook(appuser,HookType.beforeValidation, data);
332
341
  if (!issuccess) {
333
342
  const errormsg: string[] = [];
@@ -522,7 +531,9 @@ export class SimpleAppService<T extends { _id?: string }> {
522
531
 
523
532
 
524
533
  async genNewDocNo(appuser:UserContext,data:T){
534
+ this.logger.debug("genNewDocNo")
525
535
  const result = await this.docnogenerator.generateNextNumberFromDocument(appuser,this.documentType,data)
536
+ this.logger.debug(result,"genNewDocNo")
526
537
  data[this.documentIdentityCode]=result
527
538
  }
528
539
 
@@ -21,7 +21,7 @@ export class DocnoformatService extends DocnoformatProcessor {
21
21
  @InjectModel('Docnoformat') mydoc: Model<Docnoformat>,
22
22
  docnogenerator: DocNumberFormatGenerator,
23
23
  ) {
24
- super(mydoc,docnogenerator);
24
+ super(mydoc, docnogenerator);
25
25
  }
26
26
 
27
27
  // hook = async (type: string, data?: any) => {
@@ -68,10 +68,11 @@ export class DocnoformatService extends DocnoformatProcessor {
68
68
  doctype = doctype.toUpperCase();
69
69
  const searchresult = await this.search(
70
70
  appuser,
71
- { docNoType: doctype },
72
- { default: 'desc' },
71
+ { docNoType:doctype},
72
+ undefined,
73
+ {default:'desc'}
73
74
  );
74
- console.log(searchresult);
75
+ console.log('searchresult',searchresult);
75
76
  let data: any = [];
76
77
  for (let i = 0; i < searchresult.length; i++) {
77
78
  const s = searchresult[i];
@@ -53,7 +53,11 @@ defineShortcuts({
53
53
  'ctrl_enter': () => newData()
54
54
  })
55
55
  const refresh = () => {
56
- obj.list().then((res:any) => {
56
+ const searchbody: SearchBody = {
57
+ fields: props.listColumns.concat(['created']),
58
+ // sorts:props.sorts
59
+ }
60
+ obj.search(searchbody).then((res:any) => {
57
61
  recordlist.value = res;
58
62
  disabled.value=false
59
63
  });
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <div>
3
+ <input
4
+ autofocus
5
+ placeholder="search"
6
+ v-model="searchvalue"
7
+ class="w-full border p-2"
8
+ type="search" />
9
+ </div>
10
+ <div class="max-h-screen overflow-auto">
11
+ <ul >
12
+
13
+ <li v-for="item in filterlist">
14
+
15
+ <div :class="getSelectedCSS(item)">
16
+ <a class="flex flex-row " @click="clickRow(item)">
17
+ <div class="mr-2">{{item.name }}</div>
18
+ <div class="font font-bold text-right">{{item.code}}</div>
19
+ </a>
20
+ </div>
21
+
22
+ </li>
23
+ </ul>
24
+ </div>
25
+ </template>
26
+ <script setup lang="ts">
27
+ import {ref} from 'vue'
28
+ import {ListItem} from '~/types/listview'
29
+ const props = defineProps<{list:any[]}>()
30
+ const emit = defineEmits(['clickitem'])
31
+ const searchvalue = ref('')
32
+ const selecteditem =ref('')
33
+ const clickRow=(item:ListItem)=>{
34
+ emit('clickitem',item)
35
+ selecteditem.value = item.code
36
+ }
37
+ const filterlist = computed(()=>{
38
+ const newlist =props.list.filter(item=>
39
+ String(item.name).toLowerCase().includes(searchvalue.value.toLowerCase()))
40
+
41
+ return newlist
42
+ })
43
+ const getSelectedCSS= (item:ListItem)=>{
44
+ if(selecteditem.value == item.code){
45
+ return "p-2 border bg-sky-200"
46
+ }else{
47
+ return "p-2 border hover-list-primary"
48
+ }
49
+
50
+ }
51
+
52
+ </script>
@@ -1,7 +1,7 @@
1
1
 
2
2
  <template>
3
3
  <FieldContainer :hidelabel="hidelabel" v-model="modelValue" :label="label" :description="description" :setting="setting" :instancepath="instancepath" :error="error" #default="slotprops">
4
- <div class="p-inputgroup flex-1 ">
4
+ <div class="p-inputgroup ">
5
5
  <InputText class="simpleapp-inputfield"
6
6
  :inputId="slotprops.uuid"
7
7
  v-model="modelValue"
@@ -0,0 +1,43 @@
1
+ <script lang="ts" setup>
2
+ /**
3
+ * This file was automatically generated by simpleapp generator during initialization.
4
+ * You may modify it
5
+ * last change 2023-09-09
6
+ * author: Ks Tan
7
+ */
8
+
9
+ import Menus from '~/components/Menus.vue'
10
+ const {$listen,$event} = useNuxtApp()
11
+ const primarylist = ref()
12
+
13
+ primarylist.value = []
14
+
15
+ // $listen('*',(type:any,data:any)=>{ //simple use case, use any to prevent error
16
+ $listen('listloaded',(newlist)=>{
17
+ primarylist.value = newlist
18
+ })
19
+
20
+ const selectItem=(item:any)=>{
21
+ $event('itemselected',item)
22
+ }
23
+
24
+ </script>
25
+ <template>
26
+ <div>
27
+
28
+ <Menus />
29
+ <Invitation/>
30
+ <div class="grid grid-cols-4">
31
+ <div class="col col-span-1 ">
32
+ <ListView :list="primarylist" @clickitem="selectItem"></ListView>
33
+ </div>
34
+ <div class="col-span-3">
35
+ <slot>
36
+
37
+ </slot>
38
+ </div>
39
+
40
+ </div>
41
+
42
+ </div>
43
+ </template>