@simitgroup/simpleapp-generator 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +6 -0
- package/LICENSE +201 -0
- package/README.md +668 -0
- package/definations/person.pes.jsonschema.json +84 -0
- package/definations/salesinvoice.si.jsonschema.json +84 -0
- package/dist/app.module.ts +14 -0
- package/dist/constant.js +6 -0
- package/dist/constant.js.map +1 -0
- package/dist/createproject.js +123 -0
- package/dist/createproject.js.map +1 -0
- package/dist/generate.js +225 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/libs.js +15 -0
- package/dist/libs.js.map +1 -0
- package/dist/processors/jsonschemabuilder.js +116 -0
- package/dist/processors/jsonschemabuilder.js.map +1 -0
- package/dist/type.js +13 -0
- package/dist/type.js.map +1 -0
- package/package.json +44 -0
- package/sampleconfig.json +6 -0
- package/src/constant.ts +2 -0
- package/src/createproject.ts +96 -0
- package/src/generate.ts +254 -0
- package/src/index.ts +73 -0
- package/src/libs.ts +14 -0
- package/src/processors/jsonschemabuilder.ts +137 -0
- package/src/type.ts +42 -0
- package/templates/SimpleAppClient.eta +111 -0
- package/templates/SimpleAppController.eta +66 -0
- package/templates/SimpleAppService.eta +134 -0
- package/templates/app.module.eta +15 -0
- package/templates/app.vue.eta +21 -0
- package/templates/basic/apiclient.eta +56 -0
- package/templates/basic/apischema.eta +29 -0
- package/templates/basic/backend.config.eta +1 -0
- package/templates/basic/beforesave.eta +7 -0
- package/templates/basic/controller.eta +103 -0
- package/templates/basic/controller2.eta +86 -0
- package/templates/basic/frontend.config.eta +1 -0
- package/templates/basic/jsonschema.eta +6 -0
- package/templates/basic/model-converter.etabackup +21 -0
- package/templates/basic/model.eta +35 -0
- package/templates/basic/module.eta +20 -0
- package/templates/basic/readme.eta +3 -0
- package/templates/basic/service.eta +32 -0
- package/templates/basic/service.etabackupe +106 -0
- package/templates/basic/type.eta +27 -0
- package/templates/basic/type.etabackup +23 -0
- package/templates/basic/uischema.eta +13 -0
- package/templates/nest.env.eta +5 -0
- package/templates/nest.main.eta +20 -0
- package/templates/nuxt.env.eta +2 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// import { ExceptionsHandler } from '@nestjs/core/exceptions/exceptions-handler';
|
|
2
|
+
import { JSONSchema7, JSONSchema7Definition,JSONSchema7Array,JSONSchema7TypeName } from 'json-schema';
|
|
3
|
+
import * as js7 from 'json-schema';
|
|
4
|
+
import { capitalizeFirstLetter } from '../libs';
|
|
5
|
+
import {JsonSchemaProperties} from "../type"
|
|
6
|
+
// import { ConflictException } from '@nestjs/common';
|
|
7
|
+
import {
|
|
8
|
+
FieldModel,
|
|
9
|
+
Fieldtypes,
|
|
10
|
+
ChildModels,
|
|
11
|
+
SchemaModel,
|
|
12
|
+
} from '../type';
|
|
13
|
+
import { json } from 'stream/consumers';
|
|
14
|
+
|
|
15
|
+
let allmodels: ChildModels = {};
|
|
16
|
+
export const readJsonSchemaBuilder = (
|
|
17
|
+
doctype: string,
|
|
18
|
+
docname: string,
|
|
19
|
+
jsondata:JSONSchema7,
|
|
20
|
+
): ChildModels => {
|
|
21
|
+
allmodels = {};
|
|
22
|
+
const validateddata: JSONSchema7 = { ...jsondata };
|
|
23
|
+
let schema: SchemaModel | SchemaModel[];
|
|
24
|
+
|
|
25
|
+
if (jsondata && jsondata.type == 'object') {
|
|
26
|
+
//no _id then need add
|
|
27
|
+
// console.log(jsondata)
|
|
28
|
+
schema = processObject(doctype,docname, jsondata)
|
|
29
|
+
// console.log("schema",schema)
|
|
30
|
+
} else if (jsondata.type == 'array') {
|
|
31
|
+
throw(`unsupport array type for ${docname}.${doctype}`)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return allmodels;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const processObject = (doctype: string,
|
|
39
|
+
docname: string,
|
|
40
|
+
jsondata:JSONSchema7,) : SchemaModel =>{
|
|
41
|
+
if(!jsondata['properties']){
|
|
42
|
+
throw ("Invalid json schema {doctype}.{docname}, no 'properties' defined")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//ensure some field exists, also override it
|
|
46
|
+
jsondata.properties['_id'] = {type: 'string',description: 'Control value, dont edit it',};
|
|
47
|
+
jsondata.properties['doctype'] = {type: 'string', default:doctype, examples: [doctype],description: 'Control value, dont edit it',};
|
|
48
|
+
return genSchema(
|
|
49
|
+
capitalizeFirstLetter(docname),
|
|
50
|
+
'object',
|
|
51
|
+
jsondata.properties,
|
|
52
|
+
jsondata['required'] ? jsondata['required'] : [],
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const genSchema = (
|
|
57
|
+
docname: string,
|
|
58
|
+
schematype: string,
|
|
59
|
+
jsondata: JsonSchemaProperties|undefined,//JSONSchema7,//|JsonSchemaProperties|JSONSchema7Definition,
|
|
60
|
+
requiredlist: string[] | undefined,
|
|
61
|
+
): SchemaModel => {
|
|
62
|
+
const newmodel: SchemaModel = {};
|
|
63
|
+
const props = Object.getOwnPropertyNames(jsondata);
|
|
64
|
+
// console.log('==== requirelist', requiredlist);
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < props.length; i++) {
|
|
67
|
+
const key = props[i];
|
|
68
|
+
|
|
69
|
+
//below is Object.assign use for force datatype compatibility
|
|
70
|
+
const obj:JSONSchema7={}
|
|
71
|
+
Object.assign(obj,jsondata[key]);
|
|
72
|
+
const objectitem:JSONSchema7= {} as JSONSchema7
|
|
73
|
+
Object.assign(objectitem,obj.items);
|
|
74
|
+
|
|
75
|
+
// Object.assign(objtmp,jsondata?[key]:{});
|
|
76
|
+
const isrequired = requiredlist && requiredlist.includes(key);
|
|
77
|
+
// console.log('----', key, isrequired, obj);
|
|
78
|
+
const newName: string = docname + capitalizeFirstLetter(key);
|
|
79
|
+
// console.log(key);
|
|
80
|
+
//need create sub model
|
|
81
|
+
// console.log("----",key,obj.type,objectitem.type)
|
|
82
|
+
if (obj.type == 'object') {
|
|
83
|
+
genSchema(newName, obj.type, obj.properties, obj.required);
|
|
84
|
+
newmodel[key] = newName;
|
|
85
|
+
} else if (obj.type == 'array' && obj.items && objectitem?.type == 'object') {
|
|
86
|
+
//array need submodel
|
|
87
|
+
// console.log("======",newName,key)
|
|
88
|
+
genSchema(newName, obj.type, objectitem?.properties, obj.required);
|
|
89
|
+
newmodel[key] = [newName];
|
|
90
|
+
} else if (obj.type == 'array' && objectitem?.type != 'object') {
|
|
91
|
+
//array need submodel
|
|
92
|
+
// genSchema(newName, obj.type, obj.items.properties);
|
|
93
|
+
const objecttype:string = objectitem.type?.toString() ?? 'string'
|
|
94
|
+
newmodel[key] = [objecttype];
|
|
95
|
+
} else {
|
|
96
|
+
newmodel[key] = getField(key, obj, isrequired);
|
|
97
|
+
// console.log('--------newmodel', newmodel[key]);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
allmodels[docname] = { type: schematype, model: newmodel };
|
|
101
|
+
return newmodel;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const getField = (
|
|
105
|
+
fieldname: string,
|
|
106
|
+
obj: any,
|
|
107
|
+
isrequired: boolean | undefined,
|
|
108
|
+
): FieldModel => {
|
|
109
|
+
let datatype: Fieldtypes = Fieldtypes.string;
|
|
110
|
+
let format = obj.format;
|
|
111
|
+
if (obj.type == 'integer') {
|
|
112
|
+
datatype = Fieldtypes.number;
|
|
113
|
+
format = 'integer';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const f: FieldModel = {
|
|
117
|
+
type: datatype,
|
|
118
|
+
// oritype: obj.type,
|
|
119
|
+
required: isrequired,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
if (obj.title) f.title = obj.title;
|
|
123
|
+
if (obj.description) f.description = obj.description;
|
|
124
|
+
if (obj.format) f.format = obj.format;
|
|
125
|
+
if (obj.example) f.example = obj.example;
|
|
126
|
+
if (obj.examples) f.examples = obj.examples;
|
|
127
|
+
if (obj.default) {
|
|
128
|
+
f.default = obj.default;
|
|
129
|
+
} else {
|
|
130
|
+
if (f.type == 'string') f.default = '';
|
|
131
|
+
else if (f.type == 'number' || f.type == 'integer') f.default = 0;
|
|
132
|
+
else if (f.type == 'boolean') f.default = false;
|
|
133
|
+
else if (f.type == 'array') f.default = [];
|
|
134
|
+
else f.default = {};
|
|
135
|
+
}
|
|
136
|
+
return f;
|
|
137
|
+
};
|
package/src/type.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { JSONSchema7, JSONSchema7Definition } from 'json-schema';
|
|
2
|
+
export type ChildModels = {
|
|
3
|
+
[key: string]: { type: string; model: SchemaModel };
|
|
4
|
+
};
|
|
5
|
+
export enum Fieldtypes {
|
|
6
|
+
'string' = 'string',
|
|
7
|
+
'object' = 'object',
|
|
8
|
+
'array' = 'array',
|
|
9
|
+
'boolean' = 'boolean',
|
|
10
|
+
'integer' = 'integer',
|
|
11
|
+
'number' = 'number',
|
|
12
|
+
}
|
|
13
|
+
export type FieldModel = {
|
|
14
|
+
title?: string; //display name
|
|
15
|
+
description?: string; //small text for explain at inputs
|
|
16
|
+
default?: any;
|
|
17
|
+
type: Fieldtypes;
|
|
18
|
+
// oritype: string;
|
|
19
|
+
format?: string;
|
|
20
|
+
required?: boolean;
|
|
21
|
+
example?: any;
|
|
22
|
+
examples?: any;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// export type SchemaCategoryModel = {
|
|
26
|
+
// [key: string]: FieldModel;
|
|
27
|
+
// };
|
|
28
|
+
|
|
29
|
+
export type SchemaModel = {
|
|
30
|
+
[key: string]: string | string[] | FieldModel | SchemaModel | SchemaModel[];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type JsonSchemaProperties= {
|
|
34
|
+
[key: string]: JSONSchema7Definition
|
|
35
|
+
// JSONSchema7Definition ,JSONSchema7
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
export type ModuleObject = {
|
|
40
|
+
doctype:string
|
|
41
|
+
docname:string
|
|
42
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import Ajv from 'ajv';
|
|
2
|
+
import addFormats from 'ajv-formats';
|
|
3
|
+
import { ref, Ref } from 'vue';
|
|
4
|
+
import { AxiosResponse } from 'axios';
|
|
5
|
+
import { JSONSchema7 } from 'json-schema';
|
|
6
|
+
import { Configuration } from '../openapi';
|
|
7
|
+
type crudType = {
|
|
8
|
+
runFindOne: Function;
|
|
9
|
+
runCreate: Function;
|
|
10
|
+
runUpdate: Function;
|
|
11
|
+
runList: Function;
|
|
12
|
+
runDelete: Function;
|
|
13
|
+
};
|
|
14
|
+
export class SimpleAppClient<
|
|
15
|
+
TData extends { _id?: string },
|
|
16
|
+
TApi extends crudType,
|
|
17
|
+
> {
|
|
18
|
+
protected docapi;
|
|
19
|
+
protected data = <Ref<TData>>ref({} as TData);
|
|
20
|
+
public schema = {}; //cant define data type, cause it make autocomplete gone.
|
|
21
|
+
protected doctype = '';
|
|
22
|
+
protected errorlist = ref({});
|
|
23
|
+
constructor(apiobj: TApi) {
|
|
24
|
+
this.docapi = apiobj;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setDocType = (doctype: string) => (this.doctype = doctype);
|
|
28
|
+
setSchema = (schema: any) => (this.schema = schema);
|
|
29
|
+
getSchema = () => this.schema;
|
|
30
|
+
getErrors = () => this.errorlist;
|
|
31
|
+
getData = () => this.data.value;
|
|
32
|
+
getReactiveData = () => this.data;
|
|
33
|
+
setData = (data: any) => {
|
|
34
|
+
// this.data.value = data;
|
|
35
|
+
Object.assign(this.data.value, data);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
async getById(id: string) {
|
|
39
|
+
return await this.docapi.runFindOne(id).then((res: AxiosResponse) => {
|
|
40
|
+
// this.data.value = { ...res.data };
|
|
41
|
+
Object.assign(this.data.value, res.data);
|
|
42
|
+
return res;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async create() {
|
|
46
|
+
const errors = this.validateFailed();
|
|
47
|
+
if (errors) {
|
|
48
|
+
return await Promise.reject(errors);
|
|
49
|
+
} else {
|
|
50
|
+
return await this.docapi
|
|
51
|
+
.runCreate(this.data.value)
|
|
52
|
+
.then((res: AxiosResponse) => {
|
|
53
|
+
this.data.value = { ...res.data };
|
|
54
|
+
return res;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async update() {
|
|
59
|
+
const recordid: string = this.data.value._id ?? '';
|
|
60
|
+
const errors = this.validateFailed();
|
|
61
|
+
if (errors) {
|
|
62
|
+
return await Promise.reject(errors);
|
|
63
|
+
} else {
|
|
64
|
+
return await this.docapi
|
|
65
|
+
.runUpdate(recordid, this.data.value)
|
|
66
|
+
.then((res: AxiosResponse) => {
|
|
67
|
+
return res;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async delete(id: string) {
|
|
72
|
+
return await this.docapi.runDelete(id);
|
|
73
|
+
}
|
|
74
|
+
async list() {
|
|
75
|
+
return await this.docapi.runList();
|
|
76
|
+
}
|
|
77
|
+
find() {}
|
|
78
|
+
hook(type: string, data: TData) {
|
|
79
|
+
console.log('internal save hook');
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
validateFailed() {
|
|
83
|
+
const ajv = new Ajv({ allErrors: true });
|
|
84
|
+
addFormats(ajv);
|
|
85
|
+
this.errorlist.value = {};
|
|
86
|
+
this.hook('pre-validation', this.data.value);
|
|
87
|
+
const validate = ajv.compile(this.schema);
|
|
88
|
+
const valid = validate(this.data.value);
|
|
89
|
+
if (!valid) {
|
|
90
|
+
const errors = validate.errors;
|
|
91
|
+
const tmp: { [key: string]: any } = {};
|
|
92
|
+
if (errors) {
|
|
93
|
+
for (let i = 0; i < errors?.length; i++) {
|
|
94
|
+
const key: string = errors[i]['instancePath'];
|
|
95
|
+
if (!tmp[key]) {
|
|
96
|
+
tmp[key] = [];
|
|
97
|
+
}
|
|
98
|
+
tmp[key].push(errors[i]);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// console.error(tmp);
|
|
102
|
+
this.errorlist.value = tmp;
|
|
103
|
+
// console.error(this.errorlist);
|
|
104
|
+
|
|
105
|
+
return validate.errors;
|
|
106
|
+
} else {
|
|
107
|
+
this.hook('post-validation', this.data.value);
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Controller,
|
|
3
|
+
Get,
|
|
4
|
+
Put,
|
|
5
|
+
Post,
|
|
6
|
+
Delete,
|
|
7
|
+
Body,
|
|
8
|
+
Param,
|
|
9
|
+
Type,
|
|
10
|
+
} from '@nestjs/common';
|
|
11
|
+
import { ApiTags, ApiBody, ApiResponse, ApiOperation } from '@nestjs/swagger';
|
|
12
|
+
|
|
13
|
+
const doctype = 'person'.toUpperCase();
|
|
14
|
+
type ServiceType = {
|
|
15
|
+
list: Function;
|
|
16
|
+
create: Function;
|
|
17
|
+
update: Function;
|
|
18
|
+
delete: Function;
|
|
19
|
+
findById: Function;
|
|
20
|
+
findIdThenDelete: Function;
|
|
21
|
+
findIdThenUpdate: Function;
|
|
22
|
+
setData: Function;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// @ApiTags(doctype)
|
|
26
|
+
// @Controller(doctype.toLowerCase())
|
|
27
|
+
export class SimpleAppController<TService extends ServiceType, TApiSchema, T> {
|
|
28
|
+
protected service: TService;
|
|
29
|
+
protected tryno: number;
|
|
30
|
+
// protected apiSchemaClass=
|
|
31
|
+
|
|
32
|
+
constructor(service: TService) {
|
|
33
|
+
this.service = service;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async _list() {
|
|
38
|
+
return this.service.list();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async _findOne(id: string) {
|
|
42
|
+
const result = (await this.service.findById(id)) as TApiSchema;
|
|
43
|
+
|
|
44
|
+
return result as Type<TApiSchema>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async _create(data: TApiSchema) {
|
|
49
|
+
//const newdata: persontype.Person = { ...data };
|
|
50
|
+
const newdata: T = {} as T; //= { ...data };
|
|
51
|
+
Object.assign(newdata, data); //
|
|
52
|
+
return this.service.setData(newdata).create() as TApiSchema;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
async _update( id: string,data: TApiSchema) {
|
|
57
|
+
const newdata: T = {} as T; //= { ...data };
|
|
58
|
+
Object.assign(newdata, data); //
|
|
59
|
+
return this.service.findIdThenUpdate(id, newdata) as TApiSchema;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
async _delete(id: string) {
|
|
64
|
+
return this.service.findIdThenDelete(id);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { InjectModel } from '@nestjs/mongoose';
|
|
3
|
+
import { Model } from 'mongoose';
|
|
4
|
+
import Ajv from 'ajv';
|
|
5
|
+
import addFormats from 'ajv-formats';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
NotFoundException,
|
|
9
|
+
InternalServerErrorException,
|
|
10
|
+
} from '@nestjs/common/exceptions';
|
|
11
|
+
@Injectable()
|
|
12
|
+
export class SimpleAppService<T extends { _id?: string }> {
|
|
13
|
+
protected jsonschema = { type: 'object', properties: {}, required: [] };
|
|
14
|
+
protected data: T = { _id: '' } as T;
|
|
15
|
+
protected doc: Model<T>;
|
|
16
|
+
protected errorlist = [];
|
|
17
|
+
constructor(newdoc: Model<T>) {
|
|
18
|
+
this.doc = newdoc;
|
|
19
|
+
}
|
|
20
|
+
getRecordId = (): string => this.data._id;
|
|
21
|
+
setSchema = (newschema) => (this.jsonschema = newschema);
|
|
22
|
+
getSchema = () => this.doc.schema.obj;
|
|
23
|
+
getData = () => {
|
|
24
|
+
console.log('thisdata', this.data);
|
|
25
|
+
return this.data;
|
|
26
|
+
};
|
|
27
|
+
setData = (newdata: T) => {
|
|
28
|
+
delete newdata._id;
|
|
29
|
+
this.data = { ...newdata };
|
|
30
|
+
return this;
|
|
31
|
+
};
|
|
32
|
+
async list() {
|
|
33
|
+
try {
|
|
34
|
+
const products = await this.doc.find();
|
|
35
|
+
const productlist = products.map((p: T) => {
|
|
36
|
+
return p;
|
|
37
|
+
});
|
|
38
|
+
// console.log(products);
|
|
39
|
+
return productlist;
|
|
40
|
+
} catch (err) {
|
|
41
|
+
throw new InternalServerErrorException(err.message);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async findById(id: string) {
|
|
45
|
+
try {
|
|
46
|
+
console.log('findById', id);
|
|
47
|
+
this.data = await this.doc.findById(id);
|
|
48
|
+
console.log('findById done', this.data);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
//error
|
|
51
|
+
throw new InternalServerErrorException(err.message);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!this.data) {
|
|
55
|
+
//data not found
|
|
56
|
+
throw new NotFoundException('Document Not found:');
|
|
57
|
+
}
|
|
58
|
+
console.log('this.data', this.data);
|
|
59
|
+
return this.data;
|
|
60
|
+
// return this;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async create() {
|
|
64
|
+
let result;
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
delete this.data._id;
|
|
68
|
+
this.validateData(this.data);
|
|
69
|
+
const newdoc = new this.doc(this.data);
|
|
70
|
+
result = await newdoc.save();
|
|
71
|
+
} catch (err) {
|
|
72
|
+
throw new InternalServerErrorException(err.message);
|
|
73
|
+
}
|
|
74
|
+
return result as T;
|
|
75
|
+
}
|
|
76
|
+
async update() {
|
|
77
|
+
const id: string = this.getRecordId();
|
|
78
|
+
this.findIdThenUpdate(id, this.data);
|
|
79
|
+
}
|
|
80
|
+
async delete() {
|
|
81
|
+
const id: string = this.getRecordId();
|
|
82
|
+
this.findIdThenDelete(id);
|
|
83
|
+
}
|
|
84
|
+
hook(type: string, data: T) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
validateData(data: T) {
|
|
88
|
+
const ajv = new Ajv({ allErrors: true });
|
|
89
|
+
addFormats(ajv);
|
|
90
|
+
|
|
91
|
+
if (!this.hook('pre-validation', data)) {
|
|
92
|
+
const erromsg: string[] = [];
|
|
93
|
+
for (let i = 0; i < this.errorlist.length; i++) {
|
|
94
|
+
erromsg.push(this.errorlist[i].message);
|
|
95
|
+
}
|
|
96
|
+
throw new InternalServerErrorException(erromsg.join('\n'));
|
|
97
|
+
}
|
|
98
|
+
const validate = ajv.compile(this.jsonschema);
|
|
99
|
+
const valid = validate(data);
|
|
100
|
+
if (!valid) {
|
|
101
|
+
console.log(validate.errors);
|
|
102
|
+
const erromsg: string[] = [];
|
|
103
|
+
for (let i = 0; i < validate.errors.length; i++) {
|
|
104
|
+
erromsg.push(validate.errors[i].message);
|
|
105
|
+
}
|
|
106
|
+
throw new InternalServerErrorException(erromsg.join('\n'));
|
|
107
|
+
}
|
|
108
|
+
this.hook('post-validation', data);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async findIdThenDelete(id: string) {
|
|
112
|
+
// const data = await this.findById(id);
|
|
113
|
+
try {
|
|
114
|
+
const deleteresult = await this.doc.findByIdAndDelete(id);
|
|
115
|
+
return deleteresult;
|
|
116
|
+
} catch (err) {
|
|
117
|
+
throw new InternalServerErrorException(err.message);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async findIdThenUpdate(id: string, data: T) {
|
|
122
|
+
// const existingdata = await this.findById(id);
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
console.log('findIdThenUpdate', id);
|
|
126
|
+
this.validateData(data);
|
|
127
|
+
// const result = await existingdata.doc.updateOne(data);
|
|
128
|
+
const result = await this.doc.findByIdAndUpdate(id, data);
|
|
129
|
+
return result;
|
|
130
|
+
} catch (err) {
|
|
131
|
+
throw new InternalServerErrorException(err.message);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { MongooseModule } from '@nestjs/mongoose';
|
|
3
|
+
import { ConfigModule } from '@nestjs/config';
|
|
4
|
+
|
|
5
|
+
<% for(let i=0;i<it.length; i++){ %>
|
|
6
|
+
import {<%= it[i].docname %>Module} from './docs/<%= it[i].doctype %>/<%= it[i].doctype %>.module'
|
|
7
|
+
<%}%>
|
|
8
|
+
|
|
9
|
+
@Module({
|
|
10
|
+
//define environment variables: MONGODB_URL='mongodb://<user>:<pass>@<host>:<port>/<db>?authMechanism=DEFAULT'
|
|
11
|
+
imports: [ConfigModule.forRoot(),MongooseModule.forRoot(process.env.MONGODB_URL),<% for(let i=0;i<it.length; i++){ %><%= it[i].docname %>Module,<%}%>],
|
|
12
|
+
controllers: [],
|
|
13
|
+
providers: [],
|
|
14
|
+
})
|
|
15
|
+
export class AppModule {}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div>
|
|
4
|
+
<label>Firstname</label>
|
|
5
|
+
<input v-model="reactivedata.name.firstName">{{ reactivedata }}
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<button @click="person.create().then((res)=>console.log(res.data))">try</button>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
<script setup lang="ts">
|
|
12
|
+
import {PersonDoc} from './server/docs/PersonDoc'
|
|
13
|
+
const person = new PersonDoc()
|
|
14
|
+
|
|
15
|
+
// person.update().then((res)=>console.log("dosomething"))
|
|
16
|
+
// person.delete('record-id').then((res)=>console.log("dosomething"))
|
|
17
|
+
// person.getById('record-id').then((res)=>console.log("dosomething"))
|
|
18
|
+
// person.list().then((res)=>console.log(res))
|
|
19
|
+
const noreactivedata = person.getData()
|
|
20
|
+
const reactivedata = person.getReactiveData()
|
|
21
|
+
</script>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by simpleapp generator.
|
|
3
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
4
|
+
* and regenerate this file.
|
|
5
|
+
*/
|
|
6
|
+
import { SimpleAppClient } from '../class/SimpleAppClient';
|
|
7
|
+
// import { JSONSchema7 } from 'json-schema';
|
|
8
|
+
import { Configuration,
|
|
9
|
+
<%= it.doctype.toUpperCase()%>Api,
|
|
10
|
+
<%= it.typename%> ,
|
|
11
|
+
<%Object.keys(it.schema).forEach(function(key){%>
|
|
12
|
+
<% if(typeof it.schema[key]=='string'){%><%= it.schema[key] %>,<%}%>
|
|
13
|
+
<%})%>
|
|
14
|
+
|
|
15
|
+
} from '../openapi';
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
export class <%= it.typename%>Doc extends SimpleAppClient<<%= it.typename%>,<%= it.doctype.toUpperCase()%>Api>{
|
|
20
|
+
public readonly schema= <%~ JSON.stringify(it.jsonschema) %>;
|
|
21
|
+
|
|
22
|
+
constructor() {
|
|
23
|
+
const apiconfig = new Configuration({ basePath: useRuntimeConfig().public.SIMPLEAPP_BACKEND_URL });
|
|
24
|
+
const apiobj = new <%= it.doctype.toUpperCase()%>Api(apiconfig)
|
|
25
|
+
super(apiobj)
|
|
26
|
+
|
|
27
|
+
this.setNew();
|
|
28
|
+
}
|
|
29
|
+
setNew = ()=>{
|
|
30
|
+
const newdata = {
|
|
31
|
+
|
|
32
|
+
<%Object.keys(it.schema).forEach(function(key){%>
|
|
33
|
+
<%let field=it.schema[key]%>
|
|
34
|
+
<% if(typeof field=='string'){%>
|
|
35
|
+
<%=key%> : <<%= field %>>{},
|
|
36
|
+
<%} else if(field.type=='string'){%>
|
|
37
|
+
<%=key%> : '<%= field.default %>',
|
|
38
|
+
<%} else if(Array.isArray(field)) {%>
|
|
39
|
+
<%=key%> : [], //typeof field == array
|
|
40
|
+
<%} else {%>
|
|
41
|
+
<%=key%> : <%=field.default%>, //else <%= typeof field %>
|
|
42
|
+
<%}%>
|
|
43
|
+
<%})%>
|
|
44
|
+
}
|
|
45
|
+
this.setData(newdata)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/*****************************customized frontend + backend code*****************************************/
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
<%~ it.bothEndCode %>
|
|
52
|
+
|
|
53
|
+
/*****************************customized frontend only code*****************************************/
|
|
54
|
+
|
|
55
|
+
<%~ it.frontEndCode %>
|
|
56
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by simpleapp generator.
|
|
3
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
4
|
+
* and regenerate this file.
|
|
5
|
+
*/
|
|
6
|
+
import { ApiProperty } from '@nestjs/swagger';
|
|
7
|
+
|
|
8
|
+
<%Object.keys(it.models).forEach(function(name) { %>
|
|
9
|
+
<% let schema = it.models[name].model %>
|
|
10
|
+
export class <%= name %>{
|
|
11
|
+
|
|
12
|
+
<% Object.keys(schema).forEach(function(key){%>
|
|
13
|
+
<% let obj = schema[key] %>
|
|
14
|
+
<% if(typeof obj == 'string') {%>
|
|
15
|
+
@ApiProperty({type: ()=><%=obj%>})
|
|
16
|
+
<%= key %>: <%= obj %>;
|
|
17
|
+
<% }else if( Array.isArray( obj)){%>
|
|
18
|
+
@ApiProperty({type: ()=>[<%=initType(obj[0]) %>] })
|
|
19
|
+
<%= key %>: <%= obj[0] %>[];
|
|
20
|
+
|
|
21
|
+
<% }else{%>
|
|
22
|
+
@ApiProperty(<%~ JSON.stringify(obj)%> )
|
|
23
|
+
<%= key %>: <%= obj.type %>;
|
|
24
|
+
<% } %>
|
|
25
|
+
<% }) %>
|
|
26
|
+
}
|
|
27
|
+
<%}) %>
|
|
28
|
+
|
|
29
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const API_BASE_URL = 'http://localhost:3000';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by simpleapp generator.
|
|
3
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
4
|
+
* and regenerate this file.
|
|
5
|
+
*/
|
|
6
|
+
import { <%= it.typename %> } from './<%= it.doctype %>.type';
|
|
7
|
+
export const beforeSave = (doc: <%= it.typename %>) => {}
|