@simitgroup/simpleapp-generator 1.0.21 → 1.0.23

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 (89) hide show
  1. package/README copy.md +882 -0
  2. package/README.md +53 -824
  3. package/definations/category.cat.jsonschema.json +11 -13
  4. package/definations/level.lvl.jsonschema.json +48 -0
  5. package/definations/product.prd.jsonschema.json +8 -2
  6. package/dist/framework.js +42 -23
  7. package/dist/framework.js.map +1 -1
  8. package/dist/generate.js +3 -3
  9. package/dist/generate.js.map +1 -1
  10. package/dist/index.js +8 -7
  11. package/dist/index.js.map +1 -1
  12. package/openapitools.json +7 -0
  13. package/package.json +1 -1
  14. package/sampleconfig.json +3 -0
  15. package/src/framework.ts +37 -19
  16. package/src/generate.ts +3 -3
  17. package/src/index.ts +8 -7
  18. package/templates/nest/nest.env.eta +7 -0
  19. package/templates/{nest.main.eta → nest/nest.main.eta} +1 -1
  20. package/templates/nuxt/env.eta +5 -3
  21. package/backend1/.env +0 -5
  22. package/backend1/.eslintrc.js +0 -25
  23. package/backend1/.prettierrc +0 -4
  24. package/backend1/README.md +0 -73
  25. package/backend1/nest-cli.json +0 -8
  26. package/backend1/package.json +0 -75
  27. package/backend1/pnpm-lock.yaml +0 -5459
  28. package/backend1/src/app.controller.js +0 -71
  29. package/backend1/src/app.controller.js.map +0 -1
  30. package/backend1/src/app.controller.spec.js +0 -21
  31. package/backend1/src/app.controller.spec.js.map +0 -1
  32. package/backend1/src/app.controller.spec.ts +0 -22
  33. package/backend1/src/app.controller.ts +0 -12
  34. package/backend1/src/app.module.js +0 -67
  35. package/backend1/src/app.module.js.map +0 -1
  36. package/backend1/src/app.module.ts +0 -10
  37. package/backend1/src/app.service.js +0 -64
  38. package/backend1/src/app.service.js.map +0 -1
  39. package/backend1/src/app.service.ts +0 -8
  40. package/backend1/src/class/SimpleAppController.js +0 -38
  41. package/backend1/src/class/SimpleAppController.js.map +0 -1
  42. package/backend1/src/class/SimpleAppController.ts +0 -69
  43. package/backend1/src/class/SimpleAppService.js +0 -264
  44. package/backend1/src/class/SimpleAppService.js.map +0 -1
  45. package/backend1/src/class/SimpleAppService.ts +0 -213
  46. package/backend1/src/main.js +0 -22
  47. package/backend1/src/main.js.map +0 -1
  48. package/backend1/src/main.ts +0 -20
  49. package/backend1/test/app.e2e-spec.js +0 -45
  50. package/backend1/test/app.e2e-spec.js.map +0 -1
  51. package/backend1/test/app.e2e-spec.ts +0 -24
  52. package/backend1/test/jest-e2e.json +0 -9
  53. package/backend1/tsconfig.build.json +0 -4
  54. package/backend1/tsconfig.json +0 -1
  55. package/frontend1/README.md +0 -63
  56. package/frontend1/app.vue +0 -8
  57. package/frontend1/assets/css/tailwind.css +0 -28
  58. package/frontend1/components/CrudSimple.vue +0 -112
  59. package/frontend1/components/DebugDocumentData.vue +0 -20
  60. package/frontend1/components/EventMonitor.vue +0 -79
  61. package/frontend1/components/Menus.vue +0 -18
  62. package/frontend1/layouts/default.vue +0 -10
  63. package/frontend1/nuxt.config.js +0 -42
  64. package/frontend1/nuxt.config.js.map +0 -1
  65. package/frontend1/nuxt.config.ts +0 -42
  66. package/frontend1/package-lock.json +0 -11877
  67. package/frontend1/package.json +0 -38
  68. package/frontend1/pages/index.vue +0 -3
  69. package/frontend1/plugins/simpleapp.js +0 -73
  70. package/frontend1/plugins/simpleapp.js.map +0 -1
  71. package/frontend1/plugins/simpleapp.ts +0 -73
  72. package/frontend1/pnpm-lock.yaml +0 -8339
  73. package/frontend1/public/favicon.ico +0 -0
  74. package/frontend1/server/api/[...].js +0 -117
  75. package/frontend1/server/api/[...].js.map +0 -1
  76. package/frontend1/server/api/[...].ts +0 -131
  77. package/frontend1/server/tsconfig.json +0 -3
  78. package/frontend1/tailwind.config.js +0 -10
  79. package/frontend1/tailwind.config.js.map +0 -1
  80. package/frontend1/tailwind.config.ts +0 -9
  81. package/frontend1/tsconfig.json +0 -4
  82. package/src/installdependency.ts +0 -4
  83. package/templates/SimpleAppClient.eta +0 -116
  84. package/templates/app.vue.eta +0 -21
  85. package/templates/nest.env.eta +0 -5
  86. /package/src/{index2.ts → index2.ts-old} +0 -0
  87. /package/templates/{SimpleAppController.eta → nest/SimpleAppController.eta} +0 -0
  88. /package/templates/{SimpleAppService.eta → nest/SimpleAppService.eta} +0 -0
  89. /package/templates/{app.module.eta → nest/app.module.eta} +0 -0
@@ -0,0 +1,882 @@
1
+ # Quick start
2
+ 1. git clone from simpleapp-generator
3
+ ```sh
4
+ git clone https://github.com/SIMITGROUP/simpleapp-generator-template myapp
5
+ cd ~/myapp
6
+ simpleapp-generator -c config.json
7
+ ```
8
+ 2. start backend
9
+ ```sh
10
+ cd ~/myapp/backend
11
+ pnpm start:dev
12
+ ```
13
+ 3. start frontend
14
+ ```sh
15
+ cd ~/myapp/frontend
16
+ pnpm dev
17
+ ```
18
+ 4. try ui:
19
+ * frontend: (http://localhost:8080)[http://localhost:8080]
20
+ * backend: (http://localhost:8000/api)[http://localhost:8000/api]
21
+ 5. Match the json schema and the generated forms
22
+ ```sh
23
+ code ~/mydoc
24
+ ```
25
+
26
+ # Concept of Development
27
+ Development using simpleapp-generator involve below steps:
28
+ [Simple]
29
+ 1. create appropriate jsonschema
30
+ 2. generate frontend and backend architectures
31
+ 3. start backend service, obtain and save api definations into openapi.yaml
32
+ 4. regenerate codes so frontend can obtain openapi clients
33
+ 5. align frontend UI, add necessary component such as css and ui components
34
+
35
+ [Advance]
36
+ 1. complete simple task
37
+ 2. add more api/process at backend `controller`,`service`,`schema`. Such as:
38
+ a. special search
39
+ b. special workflows
40
+ c. connect external api
41
+ d. additional data processing and validation which is not supported by jsonschema (AJV)
42
+ 3. security like sso/jwt, plugins
43
+ a. keycloak integration at frontends
44
+ b. backend manage jwt
45
+ 4. allow additional field formats, validations by modifying ajv
46
+ a. allow custom jsonschema field property, and do something at backend
47
+ b. allow custom field format, and do something at backend
48
+ 5. repeat same typscript formula at frontend and backend
49
+
50
+
51
+ after generate
52
+ 1. `./backend/tsconfig.ts` add bolow into compile options
53
+ ```typescript
54
+ "resolveJsonModule": true,
55
+ "esModuleInterop": true,
56
+ ```
57
+ 2.`./backend/.env` change mongodb setting as below example:
58
+ ```bash
59
+ MONGODB_URL='mongodb://mongoadmin:secret@localhost:27017/admin?authMechanism=DEFAULT'
60
+ ```
61
+ 3. download http://localhost:8080/api into `./openapi.yaml`
62
+ 4. regenerate code (for frontend can function completely)
63
+ 5.
64
+
65
+
66
+ 1. install openapi-generator, pnpm, nest, rename openapi for new setup
67
+ 2. load backend tsconfig and add more property: **
68
+ 3. add prettier formating option for frontend
69
+ 4. error messages
70
+ 5. fix single and multi select bugs
71
+ 6. function of remain menulist
72
+ 7. security of string input, block xss
73
+
74
+
75
+ errors formating
76
+ 18.keep audit trail into db
77
+ 10.add backend find options
78
+ 10.add frontend find options
79
+ 11.retain modifications of controller, service, apiclients
80
+ 14.add permission control
81
+ 16.access right
82
+ 17.setting of tenants
83
+
84
+ authentication in nuxt
85
+ jwt in backend
86
+
87
+
88
+ 9. beautify default tailwind ui
89
+ 1. front page
90
+ 2. top bar
91
+ 3. menu bars
92
+ 4. default with of each component is it nicely fit
93
+ 5. table layout
94
+ 7. error formating
95
+ 9. write proper user guide
96
+ 13.add workflow functions
97
+
98
+
99
+
100
+ hold
101
+
102
+ 10.plugin for ajv
103
+ long string format for description
104
+
105
+ # Todo
106
+ x21.control csrf
107
+ x8. simpleapp generate currentfolder error **
108
+ x1. override app.vue *
109
+ x2. create layout
110
+ simpleapp (first time only)
111
+ /default *
112
+ x3. components/ (first time only)
113
+ x /MonitorEvent.vue *
114
+ x /CrudBasic.vue **
115
+ x /Menubar *
116
+ 4. create page/docs (everytime)
117
+ /index.ts
118
+ //create page if docs/documentname not exists ***
119
+ //override if docs/documentname/delete-me-for-avoid-override exists *
120
+ 5. login/logout sessions
121
+ x6. auto create *
122
+ x server/api to backend *
123
+
124
+
125
+
126
+
127
+
128
+ 1. define foreign key relationship in json schema2
129
+ 2. auto index and block deletion
130
+ 3. when delete identify foreign connected documents
131
+ 4. how to unique key
132
+ 5. how to multi-tenancy
133
+ 6. login/logout in nuxt
134
+ 7. jwt in nestjs
135
+ 8. format errors at server side link back client side
136
+ 9. how to auto toast
137
+ 10.server side custom validation link back client side
138
+ 11.permission controls
139
+ 12.find records
140
+ 13.audit trail
141
+ 14.data isolation by org, branch and tenant
142
+ 15.statistics, aggregations
143
+ 16.auto generate frontend page
144
+ 17.
145
+
146
+
147
+
148
+
149
+
150
+ # simpleapp-generator
151
+ ## this project still in alpha stage!
152
+
153
+ SimpleApp is an frontend and backend code generator, the ideal of this project is to allow developer build reliable and scalable application with low code methods.
154
+
155
+ It suitable for complex schema +complex calculation such as:
156
+ 1. sales invoice: having parent and childs as 1 document, it need to calculate tax, discount, exchange rate
157
+ 2. delivery order: need to calculate total quantity, unit of measurement conversion
158
+
159
+ Key Ideal:
160
+ 1. Every data store as json format, name as `document`
161
+ 2. Every document defined by jsonschema, and store in folder `definations`
162
+ 3. We store jsonschema as `<uniquedocumentname>.<uniquedocumentshortname>.jsonschema.json`. Example: `purchaseorder.po.jsonschema.json`, `student.std.jsonschema.json`
163
+ 4. `JsonSchema` used to generate:
164
+ - multiple pattern of data types for database, dto, frontend, backend. The data type match to `jsonschema`
165
+ - api controller (openapi)
166
+ - simpleapp frontend and backend objects
167
+ 5. Generated code will control data validation in both frontend and backend using `ajv`
168
+ 6. There is few important keyword need to know:
169
+ - `jsondata`: actual data like `{"document_no":"PO001",amount:300}`
170
+ - `jsonschema`: it is schema of `jsondata`, we use it to generate CRUD codes
171
+ - `frontend`: user interface framework using nuxt (vue+typescript), it doesn't store any data
172
+ - `backend`: api server using nest(typescript), it provide openapi, and store data into mongodb
173
+ - `doc service`: a typescript class use for process specific document in server. example" `po.service.ts`
174
+ - `doc controller`: it is api router for route http traffic to document service. example: `po.controller.ts`
175
+ - `doc client`: frontend client, it provide reactive data and data processing mechanism for frontend
176
+
177
+ 6. To make our app useful, we perform development at
178
+ - backend: modify `api controller` and `backend document service`
179
+ - frontend: layout user interface, bind input fields to `doc client` , and modify `doc client` required
180
+ 7. We may frequently change `jsonschema`, `doc service`, `doc controller`, `doc client`:
181
+ - the previous modified code remain when you regenerate code (with specific rules)
182
+ 8. After regenerate codes, some data processing codes in `doc service` will sync into `doc client`, to reduce repeat coding at both end
183
+
184
+ ## Benefit
185
+ - Use `jsonschema` generate most of the frontend and backend code
186
+ - Generated frontend and backend code in typescript+OOP.
187
+ - it control as tight as possible the frontend and backend data consistency
188
+ - support complex data schema, included parent and childs, nested objects
189
+ - enforce frontend and backend use same data type
190
+ - data store in mongodb, exactly same with schema, no join no headache
191
+ - flexible frontend, you can code react or vue, no problem. `simpleapp generator` only focus data, not ui
192
+ - allow developer enforce specific data processing in frontend and backend
193
+ - you can regenerate source code multiple time without worry your customization gone (there is a way!)
194
+
195
+
196
+ Init Nuxt script
197
+ 1. npm i -D @sidebase/nuxt-auth
198
+ 2. pnpm i --save next-auth@4.21.1
199
+ npm i -D @sidebase/nuxt-session
200
+
201
+
202
+
203
+ ## You shall know
204
+ This project assume you familiar with below:
205
+ 1. typescript (no typescript, not reliable frontend)
206
+ 2. mongodb
207
+ 3. vue/react kind of ecosystem
208
+
209
+ # Special Format:
210
+ There is special format value:
211
+ 1. `field-autcomplete-code`:field for document code, like `student_code,document_no`
212
+ 2. `field-autocomplete-label`: field for document name, like `student_name, product_name`
213
+
214
+ # Special properties:
215
+ ## object:
216
+ * autocomplete-src=category => autocomplete list from server-url/category/autocomplete
217
+
218
+ You need to install mongodb and openapi generator:
219
+ 1. https://www.mongodb.com/docs/manual/installation/
220
+ 2. https://openapi-generator.tech/docs/installation/
221
+
222
+ # Quick Start
223
+ This quick start create a example project developed by simpleapp-generator
224
+ 1. Install `simpleapp-generator`
225
+ ```sh
226
+ npm install -g simpleapp-generator
227
+ ```
228
+ 2. mkdir project folder for store frontend and backend codes
229
+ ```sh
230
+ mkdir ~/myapp
231
+ cd myapp
232
+ ```
233
+ 3. generate sample project
234
+ ```sh
235
+ simpleapp-generator -e person # -e mean use example schema "person". Currently only 1 example
236
+ ```
237
+
238
+ 4. run backend apiserver
239
+ ```sh
240
+ cd backend
241
+ pnpm start:dev
242
+ ```
243
+ 5. browse to `http://localhost:8000/api` for swagger ui, `http://localhost:8000/api-yaml` for openapi documents
244
+ 6. You may use vscode to see the example code in `backend/src/docs/pes`:
245
+ - pes.controller.ts //document api controller
246
+ - pes.service.ts //document service controller
247
+ - pes.type.ts, pes.apischema.ts, pes.model.ts //multiple datatype or schema
248
+
249
+
250
+
251
+
252
+
253
+
254
+
255
+
256
+ ```
257
+ mkdir definations #we put json schema here
258
+
259
+ ```
260
+ 3. create configuration file `config.json`
261
+ ```sh
262
+ echo '{"definationsFolder":"./definations","backendFolder":"./backend", "frontendFolder":"./frontend","openapi3Yaml":""}' > config.json
263
+ ```
264
+ 4. create below content and save as `~/myapp/definations/person.pes.jsonschema.json`
265
+ ```json
266
+ {
267
+ "type": "object",
268
+ "properties": {
269
+ "name": {
270
+ "type": "object",
271
+ "properties": {
272
+ "firstName": {
273
+ "type": "string",
274
+ "examples": [
275
+ "John"
276
+ ]
277
+ },
278
+ "lastName": {
279
+ "type": "string",
280
+ "examples": [
281
+ "Fox"
282
+ ]
283
+ }
284
+ }
285
+ },
286
+ "age": {
287
+ "type": "integer",
288
+ "examples": [
289
+ 20
290
+ ]
291
+ },
292
+ "email": {
293
+ "type": "string",
294
+ "examples": [
295
+ "john@example.com"
296
+ ],
297
+ "format": "email"
298
+ },
299
+ "dob": {
300
+ "type": "string",
301
+ "examples": [
302
+ "2000-01-01"
303
+ ],
304
+ "format": "date"
305
+ },
306
+ "hobbies": {
307
+ "type": "array",
308
+ "items": {
309
+ "type": "string",
310
+ "examples": [
311
+ "badminton",
312
+ "dota",
313
+ "reading"
314
+ ]
315
+ }
316
+ },
317
+ "addresses": {
318
+ "type": "array",
319
+ "items": {
320
+ "type": "object",
321
+ "required": [
322
+ "street1",
323
+ "street2",
324
+ "postcode"
325
+ ],
326
+ "properties": {
327
+ "street1": {
328
+ "type": "string",
329
+ "examples": [
330
+ "11, Fox Road"
331
+ ]
332
+ },
333
+ "street2": {
334
+ "type": "string",
335
+ "examples": [
336
+ "My Home Town"
337
+ ]
338
+ },
339
+ "postcode": {
340
+ "type": "integer",
341
+ "examples": [
342
+ 12345
343
+ ]
344
+ }
345
+ }
346
+ }
347
+ }
348
+ }
349
+ }
350
+ ```
351
+ 5. generate backend and frontend codes, and define backend/.env `mongodb connection` string:
352
+ ```sh
353
+ simpleapp-generator -c ./config.json
354
+ code backend # use vscode open backend project, edit .env
355
+ ```
356
+ 6. You can start backend server and try the generated api at `http://localhost:8000/api`
357
+ ```sh
358
+ cd ~/myapp/backend
359
+ pnpm start:dev
360
+ ```
361
+ 7. Next we need more frontend work, put content of `http://localhost:8000/api-yaml` into `~/myapp/openapi.yaml`, and edit config.json as:
362
+ ```json
363
+ {
364
+ "definationsFolder":"./definations",
365
+ "backendFolder":"./backend",
366
+ "frontendFolder":"./frontend",
367
+ "openapi3Yaml":"./openapi.yaml"
368
+ }
369
+ ```
370
+ 8. regenerate source code, and use vscode open both backend and frontend project:
371
+ ```sh
372
+ simpleapp-generator -c ./config.json
373
+ code ./frontend ;
374
+ code ./backend ;
375
+ ```
376
+
377
+
378
+ # The complete development process:
379
+ 1. Prepare documents
380
+ a. Prepare sample json data
381
+ b. Convert `json` data to `jsonschema`
382
+ c. touch up jsonschema, like define require fields, format, minLength and etc
383
+ d. place json schema into `definations` folder
384
+ 2. Generate source codes
385
+ a. generate source code into backend project
386
+ b. start backend service, obtain yaml content and save into project folder
387
+ c. re-generate source code, it create required codes for frontend
388
+ 3. Begin Frontend development:
389
+ a. use vscode open frontend project
390
+ b. create user interface with several input fields, bind to generated simpleapp object
391
+
392
+ ## 1. Prepare documents
393
+ 1. [click here](https://www.convertsimple.com/convert-javascript-to-json/) allow you create json data with lesser effort. Lets use this example:
394
+ ```json
395
+ {
396
+ "docNo": "SI001",
397
+ "customer": "My Customer Pte Ltd",
398
+ "amount": 200,
399
+ "products": [
400
+ "apple",
401
+ "orange"
402
+ ],
403
+ "details": [
404
+ {
405
+ "item": "apple",
406
+ "qty": 100,
407
+ "unitprice": 1,
408
+ "subtotal": 100
409
+ },
410
+ {
411
+ "item": "orange",
412
+ "qty": 100,
413
+ "unitprice": 1,
414
+ "subtotal": 100
415
+ }
416
+ ],
417
+ "remarks": "need fast delivery"
418
+ }
419
+ ```
420
+ b. Copy generated json data to [here](https://redocly.com/tools/json-to-json-schema) using below setting, you may define data type/format/required parameters according [jsonschema standard](https://json-schema.org/understanding-json-schema/reference/index.html)
421
+ ```
422
+ output format: json
423
+ add example to schema: true
424
+ infer require property for array items: true
425
+ disable additionalProperty: true
426
+ ```
427
+ Here is the result:
428
+ ```json
429
+ {
430
+ "type": "object",
431
+ "properties": {
432
+ "docNo": {
433
+ "type": "string",
434
+ "examples": [
435
+ "SI001"
436
+ ]
437
+ },
438
+ "customer": {
439
+ "type": "string",
440
+ "examples": [
441
+ "My Customer Pte Ltd"
442
+ ]
443
+ },
444
+ "amount": {
445
+ "type": "integer",
446
+ "examples": [
447
+ 200
448
+ ]
449
+ },
450
+ "products": {
451
+ "type": "array",
452
+ "items": {
453
+ "type": "string",
454
+ "examples": [
455
+ "apple",
456
+ "orange"
457
+ ]
458
+ }
459
+ },
460
+ "details": {
461
+ "type": "array",
462
+ "items": {
463
+ "type": "object",
464
+ "required": [
465
+ "item",
466
+ "qty",
467
+ "unitprice",
468
+ "subtotal"
469
+ ],
470
+ "properties": {
471
+ "item": {
472
+ "type": "string",
473
+ "examples": [
474
+ "apple",
475
+ "orange"
476
+ ]
477
+ },
478
+ "qty": {
479
+ "type": "integer",
480
+ "examples": [
481
+ 100,
482
+ 100
483
+ ]
484
+ },
485
+ "unitprice": {
486
+ "type": "integer",
487
+ "examples": [
488
+ 1,
489
+ 1
490
+ ]
491
+ },
492
+ "subtotal": {
493
+ "type": "integer",
494
+ "examples": [
495
+ 100,
496
+ 100
497
+ ]
498
+ }
499
+ }
500
+ }
501
+ },
502
+ "remarks": {
503
+ "type": "string",
504
+ "examples": [
505
+ "need fast delivery"
506
+ ]
507
+ }
508
+ }
509
+ }
510
+ ```
511
+ c. save the json data into `definations` folder
512
+
513
+
514
+
515
+
516
+
517
+ ## Backend NestJS project preparation
518
+ 1. install backend nest application: `npm i -g pnpm @nestjs/cli` (cli tools for pnpm and nestjs)
519
+ 2. create a folder `~/myapp`
520
+ 3. cd `~/myapp`
521
+ 4. create blank nest project `nest new backend`, pick `pnpm`
522
+ 5. enter backend folder: `cd backend`
523
+ 6. install dependency: `pnpm install --save @nestjs/swagger @nestjs/mongoose mongoose ajv ajv-formats @nestjs/config` (ignore ✕ missing peer webpack)
524
+ 7. create .env file with following settings:
525
+ ```sh
526
+ MONGODB_URL='mongodb://<user>:<pass>@<host>:<port>/<db>?authMechanism=DEFAULT'
527
+ HTTP_PORT=8000
528
+ PROJECT_NAME='SimpleApp Demo1'
529
+ PROJECT_DESCRIPTION='Try CRUD'
530
+ PROJECT_Version='1.0.0'
531
+ ```
532
+ 7. change `src/main.ts`, allow openapi document:
533
+ ```ts
534
+ import { NestFactory } from '@nestjs/core';
535
+ import { AppModule } from './app.module';
536
+ import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
537
+
538
+ async function bootstrap() {
539
+ const app = await NestFactory.create(AppModule);
540
+ app.enableCors();
541
+ const config = new DocumentBuilder()
542
+ .setTitle(process.env.PROJECT_NAME)
543
+ .setDescription(process.env.PROJECT_DESCRIPTION)
544
+ .setVersion(process.env.PROJECT_VERSION)
545
+ .build();
546
+ const document = SwaggerModule.createDocument(app, config);
547
+ SwaggerModule.setup('api', app, document, {
548
+ swaggerOptions: { showExtensions: true },
549
+ });
550
+
551
+ await app.listen(process.env.HTTP_PORT); //listen which port
552
+ }
553
+ bootstrap();
554
+ ```
555
+ 9. start backend server `pnpm start:dev`, monitor [http://localhost:3000/api](http://localhost:3000/api)
556
+
557
+
558
+ ## Frontend NuxtJS project preparation (or, any others framework if you have know how)
559
+ 1. `cd ~/myapp`
560
+ 2. create new frontend nuxt project `npx nuxi@latest init frontend`
561
+ 3. `cd frontend`
562
+ 4. install required package: `pnpm install ajv ajv-formats axios json-schema`
563
+ 5. create .env file with below content
564
+ ```sh
565
+ SIMPLEAPP_BACKEND_URL=http://localhost:8000
566
+ PORT=8800
567
+ ```
568
+ 6. run frontend: `pnpm dev -o`
569
+
570
+
571
+ ## setup Mongodb
572
+ 1. you can use mongodb, either docker or install binary
573
+ https://www.mongodb.com/docs/manual/installation/
574
+ ** remember create database, and define suitable credentials (user/password)
575
+
576
+ ## Setup openapi-generator
577
+ Refer below:
578
+ https://openapi-generator.tech/docs/installation/
579
+
580
+ I'm using mac, so i use `brew install openapi-generator`
581
+
582
+
583
+ # Job Begin!
584
+ 3 steps:
585
+ 1. Prepare json schema
586
+ 2. use json schema generate frontend and backend codes
587
+ 3. persom simple development
588
+
589
+ ## 1. Prepare sample data schema
590
+ 1. lets assume we have a sample data:
591
+ ```json
592
+ {
593
+ "name":{"firstName":"John","lastName":"Fox"},
594
+ "age":20,
595
+ "email":"john@example.com",
596
+ "dob":"2000-01-01",
597
+ "hobbies":["badminton","dota","reading"],
598
+ "addresses": [{"street1":"11, Fox Road","street2":"My Home Town","postcode":12345}]
599
+ }
600
+ ```
601
+ 2. Generate it become `jsonschema` [here](https://redocly.com/tools/json-to-json-schema), format as json. Follow below settings:
602
+ ```
603
+ add example to schema: true
604
+ infer require property for array items: true
605
+ disable additionalProperty: true
606
+ ```
607
+
608
+ Below is the sample of jsonschema:
609
+ ```json
610
+ {
611
+ "type": "object",
612
+ "properties": {
613
+ "name": {
614
+ "type": "object",
615
+ "properties": {
616
+ "firstName": {
617
+ "type": "string",
618
+ "examples": [
619
+ "John"
620
+ ]
621
+ },
622
+ "lastName": {
623
+ "type": "string",
624
+ "examples": [
625
+ "Fox"
626
+ ]
627
+ }
628
+ }
629
+ },
630
+ "age": {
631
+ "type": "integer",
632
+ "examples": [
633
+ 20
634
+ ]
635
+ },
636
+ "email": {
637
+ "type": "string",
638
+ "examples": [
639
+ "john@example.com"
640
+ ],
641
+ "format": "email"
642
+ },
643
+ "dob": {
644
+ "type": "string",
645
+ "examples": [
646
+ "2000-01-01"
647
+ ],
648
+ "format": "date"
649
+ },
650
+ "hobbies": {
651
+ "type": "array",
652
+ "items": {
653
+ "type": "string",
654
+ "examples": [
655
+ "badminton",
656
+ "dota",
657
+ "reading"
658
+ ]
659
+ }
660
+ },
661
+ "addresses": {
662
+ "type": "array",
663
+ "items": {
664
+ "type": "object",
665
+ "required": [
666
+ "street1",
667
+ "street2",
668
+ "postcode"
669
+ ],
670
+ "properties": {
671
+ "street1": {
672
+ "type": "string",
673
+ "examples": [
674
+ "11, Fox Road"
675
+ ]
676
+ },
677
+ "street2": {
678
+ "type": "string",
679
+ "examples": [
680
+ "My Home Town"
681
+ ]
682
+ },
683
+ "postcode": {
684
+ "type": "integer",
685
+ "examples": [
686
+ 12345
687
+ ]
688
+ }
689
+ }
690
+ }
691
+ }
692
+ }
693
+ }
694
+ ```
695
+
696
+ ## Generate Code
697
+ 1. install simpleapp-generetor `npm install -g simpleapp-generator`
698
+ 2. create a folder `~/myapp/definations`
699
+ 3. copy above jsonschema example as `~/myapp/definations/person.ps.jsonschema.json`.
700
+ * `person`: unique document name (small letter alphabet `[a-z]`)
701
+ * `ps`: unique document type (small letter `[a-z]`)
702
+ * `jsonschema.json`: all files ending with this extension will process
703
+ 4. create `~/myapp/config.json` with below content
704
+ ```json
705
+ {
706
+ "definationsFolder":"./definations",
707
+ "backendFolder":"./mybackend",
708
+ "backendPort":"8000",
709
+ "mongoConnectStr":"mongodb://<user>:<pass>@<host>:<port>/<db>?authMechanism=DEFAULT",
710
+ "frontendFolder":"./myfrontend",
711
+ "frontendPort":"8080",
712
+ "openapi3Yaml":"./openapi.yaml",
713
+ }
714
+ ```
715
+ 5. run `simpleapp-generator -c ./config.json`
716
+ 6. restart nestjs, the microservice is ready and you can test at `http://localhost:8000/api`. All generated api accessible via swagger-ui.
717
+ 7. Frontend need further work. Browse `http://localhost:8000/api-yaml`, save content as `openapi.yaml`
718
+ 8. Rerun `simpleapp-generator -c ./config.json`, it will help us to generate axios executable using openapi.yaml
719
+ 9. use vscode open both `~/myapp/frontend` and `~/myapp/backend`
720
+
721
+
722
+
723
+ ## perform simple development
724
+ 1. in `frontend` project, edit `app.vue`, put in below code:
725
+ ```vue
726
+ <template>
727
+ <div>
728
+ <div>
729
+ <label>Firstname</label>
730
+ <input v-model="reactivedata.name.firstName">
731
+ </div>
732
+ {{ reactivedata }}
733
+ <button @click="person.create().then((res)=>console.log(res.data))">try</button>
734
+ </div>
735
+ </template>
736
+ <script setup lang="ts">
737
+ import {PersonDoc} from './server/docs/PersonDoc'
738
+ const person = new PersonDoc()
739
+
740
+ // person.update().then((res)=>console.log("dosomething"))
741
+ // person.delete('record-id').then((res)=>console.log("dosomething"))
742
+ // person.getById('record-id').then((res)=>console.log("dosomething"))
743
+ // person.list().then((res)=>console.log(res))
744
+ const noreactivedata = person.getData() //give not reactive data, it cant apply 2 way data binding
745
+ const reactivedata = person.getReactiveData() //give vue reactive data, it can apply 2 way data binding using v-model
746
+ </script>
747
+ ```
748
+
749
+ We notice:
750
+ 1. `PersonDoc` auto generated, it come with plenty of build in crud features which you can use without knowing API:
751
+ ```typescript
752
+ person.create().then((res)=>console.log("dosomething"))
753
+ person.update().then((res)=>console.log("dosomething"))
754
+ person.delete('record-id').then((res)=>console.log("dosomething"))
755
+ person.getById('record-id').then((res)=>console.log("dosomething"))
756
+ person.list().then((res)=>console.log(res))
757
+ ```
758
+ 2. `person.getData()` gave reactive object, we can bind all properties directly to `vue` component using `v-model`
759
+ 3. you may try add more input bind to `reactivedata.name.lastName`,`reactivedata.email`, `reactivedata.age` and monitor result
760
+ 4. `button` can directly trigger `save` method from person.getData()
761
+ 5. You wont able to save the record because it not pass validation rules, check browser console it tell you what is happening
762
+ 6. There is UI component `simpleapp-uicomponent` which can integrate nicely with with `PersonDoc`. Refer the link [here](...)
763
+
764
+ # We can do more With SimpleApp
765
+ ## no time for full documentation yet
766
+ 1. Monitor variable change at frontend
767
+ step 1: add new methods for frontend's class `PesonDoc.ts`
768
+ ```
769
+ watchChanges = ()=>{
770
+ watch(this.getReactiveData(),(newdata)=>{
771
+ this.getReactiveData().age=calculateAge(newdata.dob)
772
+ //apply others changes here
773
+ })
774
+ }
775
+ ```
776
+ step 2: edit `app.vue` to on the watcher
777
+ ```typescript
778
+ //others codes
779
+ const person = new PersonDoc()
780
+ person.watchChanges() //<-- add this line to on watcher at frontend
781
+ //others codes
782
+ ```
783
+
784
+ 2. create more api to `person`, such as `post /person/:id/sendEmail {title:"title",body:"body"}`
785
+ step 1: edit backend `<backend>/src/docs/pes/pes.controller.ts`, add new source code between `<begin-controller-code>` and `<end-controller-code>`:
786
+ ```typescript
787
+ //<begin-controller-code>
788
+ //new api, wont override when regenerate code
789
+ @Get('/try/:id')
790
+ @ApiResponse({
791
+ status: 200,
792
+ description: 'success',
793
+ type: pesapischema.Person,
794
+ })
795
+ @ApiResponse({ status: 404, description: 'Document not found' })
796
+ @ApiResponse({ status: 500, description: 'Internal error' })
797
+ @ApiOperation({ operationId: 'newFindOne' }) //important, frontend access it via person.newFindOne()
798
+ async newFindOne(@Param('id') id: string) {
799
+ return this._findOne(id);
800
+ }
801
+ //<end-controller-code>
802
+ ```
803
+ step 2: try browse to `http://localhost:8000/api` to check new api appear or not.
804
+ step 3: You shall regenerate the code
805
+ ```bash
806
+ simpleapp-generator -c ./config.json
807
+ ```
808
+ step 4: go frontend project, edit `app.vue` you may try type `person.newFindOne()` see new method exists?
809
+
810
+ step 3: Regenerate code for frontend
811
+
812
+ 4. create backend only execution for `person`. It is useful cause some work only
813
+ step 1: Edit backend `backend/src/docs/pes/pes.service.ts`, add new source code between `<begin-backend-code>` and `<end-backend-code>`:
814
+ ```typescript
815
+ //<begin-backend-code>
816
+ //new method, wont override when regenerate code
817
+ logSomething = () => {
818
+ console.log('Access try api');
819
+ };
820
+ //<end-backend-code>
821
+ ```
822
+ step 2: modify `<backend>/src/docs/pes/pes.controller.ts`, call the new method
823
+ ```typescript
824
+ async newFindOne(@Param('id') id: string) {
825
+ this.service.logSomething(); //this.service is our service class
826
+ return this._findOne(id);
827
+ }
828
+ ```
829
+
830
+
831
+ 5. create frontend only code for `person`, such as:
832
+ `person.addHobbies('hobby1')`,`person.addAddress({})`,`person.delAddress(index:number)` edit `newFindOne`:
833
+ ```
834
+ ```
835
+ 6. create bothend code for `person`
836
+
837
+
838
+
839
+ foreign key
840
+ cat
841
+ category_id
842
+ category_code
843
+ category_name
844
+
845
+ product
846
+ product_id
847
+ product_code
848
+ product_name
849
+ category => category_id: category_code
850
+
851
+
852
+
853
+ invoice
854
+ invoice_id
855
+ invoice_no
856
+ invoice_date
857
+ total
858
+ details =>
859
+ product => product_id: product_code
860
+ qty
861
+ price
862
+ subtotal
863
+
864
+ order
865
+ order_id
866
+ order_no
867
+ order_date
868
+ total
869
+ details =>
870
+ product => product_id: product_code
871
+ qty
872
+ price
873
+ subtotal
874
+
875
+
876
+ cat => foreignkey: []
877
+ prd => foreignkey: category => category
878
+ invoice => foreignkey: detail.product=>product
879
+ order => foreignkey: detail.product=>product
880
+
881
+ cat =[product.category]
882
+ product=[invoice.detail.product, order.detail.product]