@simitgroup/simpleapp-generator 1.4.1-alpha → 1.5.0-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.
- package/dist/buildinschemas/autoincreament.d.ts.map +1 -1
- package/dist/buildinschemas/autoincreament.js +1 -0
- package/dist/buildinschemas/autoincreament.js.map +1 -1
- package/dist/buildinschemas/docnoformat.d.ts.map +1 -1
- package/dist/buildinschemas/docnoformat.js +1 -0
- package/dist/buildinschemas/docnoformat.js.map +1 -1
- package/dist/buildinschemas/permission.d.ts.map +1 -1
- package/dist/buildinschemas/permission.js +1 -8
- package/dist/buildinschemas/permission.js.map +1 -1
- package/dist/framework.d.ts.map +1 -1
- package/dist/framework.js +4 -2
- package/dist/framework.js.map +1 -1
- package/dist/generate.js +8 -10
- package/dist/generate.js.map +1 -1
- package/dist/processors/bpmnbuilder.d.ts.map +1 -1
- package/dist/processors/bpmnbuilder.js +10 -4
- package/dist/processors/bpmnbuilder.js.map +1 -1
- package/dist/processors/jsonschemabuilder.d.ts.map +1 -1
- package/dist/processors/jsonschemabuilder.js +9 -0
- package/dist/processors/jsonschemabuilder.js.map +1 -1
- package/package.json +1 -1
- package/src/buildinschemas/autoincreament.ts +1 -0
- package/src/buildinschemas/docnoformat.ts +1 -0
- package/src/buildinschemas/permission.ts +1 -8
- package/src/framework.ts +5 -4
- package/src/generate.ts +11 -11
- package/src/processors/bpmnbuilder.ts +10 -5
- package/src/processors/jsonschemabuilder.ts +10 -0
- package/templates/basic/nest/apischema.ts.eta +5 -0
- package/templates/basic/nest/controller.ts.eta +28 -10
- package/templates/basic/nest/resolver.ts.eta +124 -0
- package/templates/basic/nest/service.ts.eta +0 -6
- package/templates/basic/nuxt/pages.landing.vue.eta +4 -2
- package/templates/basic/nuxt/pages.mobile.landing.vue.eta +3 -3
- package/templates/nest/.env._eta +7 -7
- package/templates/nest/src/app.module.ts.eta +22 -21
- package/templates/nest/src/app.resolver.ts.eta +9 -0
- package/templates/nest/src/simpleapp/generate/commons/decorators/appuser.decorator.ts.eta +11 -5
- package/templates/nest/src/simpleapp/generate/commons/interceptors/response.interceptor.ts.eta +44 -39
- package/templates/nest/src/simpleapp/generate/commons/middlewares/tenant.middleware.ts.eta +16 -4
- package/templates/nest/src/simpleapp/generate/commons/roles/roles.guard.ts.eta +24 -12
- package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +26 -18
- package/templates/nest/src/simpleapp/generate/types/index.ts.eta +1 -0
- package/templates/nest/src/simpleapp/generate/types/workflow.type.ts.eta +15 -0
- package/templates/nest/src/simpleapp/generate/workflow/workflow.config.ts.eta +2 -2
- package/templates/nest/src/simpleapp/generate/workflow/workflow.controller.ts.eta +8 -6
- package/templates/nest/src/simpleapp/generate/workflow/workflow.service.ts.eta +41 -22
- package/templates/nest/src/simpleapp/resolvers/readme.md.eta +1 -0
- package/templates/nest/src/simpleapp/simpleapp.module.ts.eta +9 -2
- package/templates/nuxt/app.vue._eta +9 -2
- package/templates/nuxt/components/calendar/CalendarByResource.vue.eta +1 -1
- package/templates/nuxt/components/mobile/MobileToolbar.vue.eta +11 -11
- package/templates/nuxt/components/overlay/OverlayHoldscreen.vue._eta +26 -0
- package/templates/nuxt/components/renderer/RendererDate.vue.eta +1 -1
- package/templates/nuxt/components/renderer/RendererDateTime.vue.eta +1 -1
- package/templates/nuxt/components/renderer/RendererForeignKey.vue.eta +7 -7
- package/templates/nuxt/components/renderer/RendererMoney.vue.eta +21 -12
- package/templates/nuxt/components/renderer/RendererTime.vue.eta +13 -0
- package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +11 -10
- package/templates/nuxt/composables/date.generate.ts.eta +10 -3
- package/templates/nuxt/composables/getDocument.generate.ts.eta +4 -4
- package/templates/nuxt/composables/graphquery.generate.ts.eta +26 -0
- package/templates/nuxt/composables/holdscreen.generate.ts.eta +9 -0
- package/templates/nuxt/composables/refreshDocumentList.generate.ts.eta +7 -6
- package/templates/nuxt/layouts/mobile.vue._eta +3 -3
- package/templates/nuxt/nuxt.config.ts._eta +8 -0
- package/templates/nuxt/pages/[xorg]/index.vue._eta +9 -0
- package/templates/nuxt/pages/[xorg]/mobile/index.vue._eta +2 -15
- package/templates/nuxt/pages/picktenant.vue._eta +3 -1
- package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +17 -3
- package/templates/nuxt/types/calendar.ts.eta +8 -3
- package/templates/nuxt/types/documentlist.ts.eta +13 -1
- package/templates/nuxt/types/events.ts.eta +5 -3
- package/templates/nuxt/types/others.ts.eta +3 -5
- package/templates/project/workflows/bpmn/{suspendcustomer.bpmn._eta → sayhello.bpmn._eta} +6 -36
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -5,21 +5,26 @@
|
|
|
5
5
|
* Author: Ks Tan
|
|
6
6
|
*/
|
|
7
7
|
import { ApiProperty } from '@nestjs/swagger';
|
|
8
|
+
import { Field, ObjectType } from '@nestjs/graphql';
|
|
8
9
|
|
|
9
10
|
<%Object.keys(it.models).forEach(function(name) { %>
|
|
10
11
|
<% let schema = it.models[name].model %>
|
|
12
|
+
@ObjectType()
|
|
11
13
|
export class <%= name %>{
|
|
12
14
|
|
|
13
15
|
<% Object.keys(schema).forEach(function(key){%>
|
|
14
16
|
<% let obj = schema[key] %>
|
|
15
17
|
<% if(typeof obj == 'string') {%>
|
|
18
|
+
@Field()
|
|
16
19
|
@ApiProperty({type: ()=><%=obj%>})
|
|
17
20
|
<%= key %>: <%= obj %>;
|
|
18
21
|
<% }else if( Array.isArray( obj)){%>
|
|
22
|
+
@Field(type=>[<%=initType(obj[0]) %>])
|
|
19
23
|
@ApiProperty({type: ()=>[<%=initType(obj[0]) %>] })
|
|
20
24
|
<%= key %>: <%= obj[0] %>[];
|
|
21
25
|
|
|
22
26
|
<% }else{%>
|
|
27
|
+
@Field()
|
|
23
28
|
@ApiProperty(<%~ JSON.stringify(obj)%> )
|
|
24
29
|
<%= key %>: <%= obj.type %>;
|
|
25
30
|
<% } %>
|
|
@@ -34,6 +34,25 @@ import { Response } from 'express';
|
|
|
34
34
|
import {AppUser} from '../commons/decorators/appuser.decorator'
|
|
35
35
|
import {UserContext} from '../commons/user.context'
|
|
36
36
|
|
|
37
|
+
<% const getFieldType =(proptype, typename)=>{
|
|
38
|
+
const systemtypes = ['Boolean','boolean','string','String','number','Number','object','Object','integer','Integer']
|
|
39
|
+
let tmptypename = typename.replace('[','').replace(']','')
|
|
40
|
+
|
|
41
|
+
if(systemtypes.includes(tmptypename)){
|
|
42
|
+
|
|
43
|
+
}else if(proptype=='schema'){
|
|
44
|
+
tmptypename= 'schemas.'+tmptypename
|
|
45
|
+
}else{ //type
|
|
46
|
+
tmptypename= 'types.'+tmptypename
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if(typename.includes('[')){
|
|
50
|
+
return proptype=='schema' ? `[${tmptypename}]` : `${tmptypename}[]`
|
|
51
|
+
}else{
|
|
52
|
+
return tmptypename
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
%>
|
|
37
56
|
<% let superadmindoctype = ['tenant','globaluser'] %>
|
|
38
57
|
const doctype = '<%= it.doctype %>'.toUpperCase();
|
|
39
58
|
@ApiTags(doctype)
|
|
@@ -149,19 +168,21 @@ export class <%= it.typename %>Controller extends SimpleAppAbstractController<
|
|
|
149
168
|
<%}%>
|
|
150
169
|
<% if(['post','put','patch'].includes(api.method)){ %>
|
|
151
170
|
@ApiBody({ description: 'Request Body',
|
|
152
|
-
type:
|
|
171
|
+
type:
|
|
172
|
+
<%= api.schema
|
|
153
173
|
? (api.schema.includes('[') ? '[schemas.'+api.schema.replace('[','').replace(']','') + ']' : 'schemas.'+api.schema )
|
|
154
|
-
: 'Object'
|
|
174
|
+
: 'Object'
|
|
175
|
+
%>
|
|
176
|
+
})
|
|
155
177
|
<%}%>
|
|
156
178
|
@ApiResponse({status: 200,description: '<%=api.description%>'
|
|
157
|
-
,type: <%= api.responseType
|
|
158
|
-
|
|
159
|
-
: 'Object'%> })
|
|
179
|
+
,type: <%= getFieldType('schema',api.responseType)%>
|
|
180
|
+
})
|
|
160
181
|
@ApiOperation({ operationId: 'run<%=capitalizeFirstLetter(api.action)%>' })
|
|
161
182
|
<% if(api.queryPara && api.queryPara.length>0) {%>
|
|
162
183
|
<%for(let q=0;q<api.queryPara.length; q++){%>
|
|
163
184
|
@ApiQuery({name: "<%=api['queryPara'][q]%>",required: false,type: String})
|
|
164
|
-
<%}%>
|
|
185
|
+
<%}%>
|
|
165
186
|
<%}%>
|
|
166
187
|
async <%=capitalizeFirstLetter(api.action) %>(
|
|
167
188
|
@AppUser() appuser: UserContext,
|
|
@@ -303,8 +324,5 @@ export class <%= it.typename %>Controller extends SimpleAppAbstractController<
|
|
|
303
324
|
async delete(@AppUser() appuser: UserContext,@Param('id') id: string) {
|
|
304
325
|
return this._delete(appuser,id);
|
|
305
326
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
327
|
+
|
|
310
328
|
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by simpleapp generator. It is changable
|
|
3
|
+
* --remove-this-line-to-prevent-override--
|
|
4
|
+
* last change 2024-04-17
|
|
5
|
+
* Author: Ks Tan
|
|
6
|
+
*/
|
|
7
|
+
import { Resolver, Query, Mutation, Args, ID,Context } from '@nestjs/graphql';
|
|
8
|
+
import * as schemas from '../apischemas';
|
|
9
|
+
import { AppUser } from '../commons/decorators/appuser.decorator';
|
|
10
|
+
import { UserContext } from '../commons/user.context';
|
|
11
|
+
import { <%= it.typename %>, <%= it.typename %>Service } from '../../services/<%= it.doctype.toLowerCase() %>.service';
|
|
12
|
+
import { Roles } from '../commons/roles/roles.decorator';
|
|
13
|
+
import { Role } from '../commons/roles/roles.enum';
|
|
14
|
+
|
|
15
|
+
import { Request } from '@nestjs/common';
|
|
16
|
+
|
|
17
|
+
<% const getFieldType =(proptype, typename)=>{
|
|
18
|
+
const systemtypes = ['Boolean','boolean','string','String','number','Number','object','Object','integer','Integer']
|
|
19
|
+
let tmptypename = typename.replace('[','').replace(']','')
|
|
20
|
+
|
|
21
|
+
if(systemtypes.includes(tmptypename)){
|
|
22
|
+
|
|
23
|
+
}else if(proptype=='schema'){
|
|
24
|
+
tmptypename= 'schemas.'+tmptypename
|
|
25
|
+
}else{ //type
|
|
26
|
+
tmptypename= 'types.'+tmptypename
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if(typename.includes('[')){
|
|
30
|
+
return proptype=='schema' ? `[${tmptypename}]` : `${tmptypename}[]`
|
|
31
|
+
}else{
|
|
32
|
+
return tmptypename
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
%>
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
<% let superadmindoctype = ['tenant','globaluser'] %>
|
|
39
|
+
@Resolver(() => schemas.<%= it.typename %>)
|
|
40
|
+
export class <%= it.typename %>Resolver {
|
|
41
|
+
constructor(private readonly service: <%= it.typename %>Service) { }
|
|
42
|
+
|
|
43
|
+
<%if(superadmindoctype.includes(it.doctype)){%>
|
|
44
|
+
@Roles(Role.SuperAdmin,Role.<%= `${it.typename}_search`%>)
|
|
45
|
+
<%}else{%>
|
|
46
|
+
@Roles(Role.SuperAdmin,Role.SuperUser,Role.<%= `${it.typename}_search`%>)
|
|
47
|
+
<%}%>
|
|
48
|
+
@Query(() => [schemas.<%= it.typename %>])
|
|
49
|
+
async <%= it.name %>s(@AppUser() appuser: UserContext): Promise<<%= it.typename %>[]> {
|
|
50
|
+
|
|
51
|
+
return await this.service.search(appuser,undefined,undefined,undefined)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
<%if(superadmindoctype.includes(it.doctype)){%>
|
|
56
|
+
@Roles(Role.SuperAdmin,Role.<%= `${it.typename}_search`%>)
|
|
57
|
+
<%}else{%>
|
|
58
|
+
@Roles(Role.SuperAdmin,Role.SuperUser,Role.<%= `${it.typename}_search`%>)
|
|
59
|
+
<%}%>
|
|
60
|
+
@Query(() => schemas.<%= it.typename %>)
|
|
61
|
+
async <%= it.name %>(@AppUser() appuser: UserContext,@Args('id', { type: () => ID } ) id: string): Promise<<%= it.typename %>> {
|
|
62
|
+
|
|
63
|
+
return await this.service.findById(appuser,id)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
/***************************** begin additionalAPI definations *****************************************/
|
|
75
|
+
|
|
76
|
+
<% for(let i=0;i<it.apiSettings.length;i++){%>
|
|
77
|
+
<% let api = it.apiSettings[i] %>
|
|
78
|
+
<% if(api.method!='get') continue %>
|
|
79
|
+
<%if(superadmindoctype.includes(it.doctype)){%>
|
|
80
|
+
@Roles(Role.SuperAdmin,Role.<%= `${it.typename}_${api.action}`%>,
|
|
81
|
+
<%if(api.requiredRole && api.requiredRole.length>0) { %>
|
|
82
|
+
<% for(let r=0;r<api.requiredRole.length;r++){%>Role.<%=api.requiredRole[r]%>,<%}%>
|
|
83
|
+
<%}%>
|
|
84
|
+
)
|
|
85
|
+
<%}else{%>
|
|
86
|
+
@Roles(Role.SuperAdmin,Role.SuperUser,Role.<%= `${it.typename}_${api.action}`%>,
|
|
87
|
+
<%if(api.requiredRole && api.requiredRole.length>0) { %>
|
|
88
|
+
<% for(let r=0;r<api.requiredRole.length;r++){%>Role.<%=api.requiredRole[r]%>,<%}%>
|
|
89
|
+
<%}%>
|
|
90
|
+
)
|
|
91
|
+
<%}%>
|
|
92
|
+
@Query(()=> <%= getFieldType('schema',api.responseType)%>)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
async <%= it.name %><%=capitalizeFirstLetter(api.action) %>(
|
|
97
|
+
@AppUser() appuser: UserContext,
|
|
98
|
+
<% if(api.entryPoint && api.entryPoint.includes(':')) {%>
|
|
99
|
+
<%let subpath = api.entryPoint.split('/')%>
|
|
100
|
+
<% for(let a=0;a<subpath.length;a++){%>
|
|
101
|
+
<%const partstr = subpath[a]%>
|
|
102
|
+
<%if(partstr.includes(':')){%>
|
|
103
|
+
<% const paraname = partstr.replace(':','') %>
|
|
104
|
+
@Args('<%=paraname%>') <%=paraname%>: string,
|
|
105
|
+
<%}%>
|
|
106
|
+
<%}%>
|
|
107
|
+
<%}%>
|
|
108
|
+
){
|
|
109
|
+
|
|
110
|
+
return await this.service.run<%=capitalizeFirstLetter(api.action)%>(appuser,<% if(api.entryPoint && api.entryPoint.includes(':')) {%>
|
|
111
|
+
<%let subpath = api.entryPoint.split('/')%>
|
|
112
|
+
<% for(let a=0;a<subpath.length;a++){%>
|
|
113
|
+
<%const partstr = subpath[a]%>
|
|
114
|
+
<%if(partstr.includes(':')){%>
|
|
115
|
+
<% const paraname = partstr.replace(':','') %>
|
|
116
|
+
<%=paraname%>,
|
|
117
|
+
<%}%>
|
|
118
|
+
<%}%>
|
|
119
|
+
<%}%>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
<%}%>
|
|
123
|
+
/***************************** end additionalAPI definitions *****************************************/
|
|
124
|
+
}
|
|
@@ -5,12 +5,6 @@
|
|
|
5
5
|
* Author: Ks Tan
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* This file was automatically generated by simpleapp generator.
|
|
10
|
-
|
|
11
|
-
* last change 2023-09-23
|
|
12
|
-
* Author: Ks Tan
|
|
13
|
-
*/
|
|
14
8
|
import { InjectModel } from '@nestjs/mongoose';
|
|
15
9
|
import { Model } from 'mongoose';
|
|
16
10
|
import { Injectable } from '@nestjs/common';
|
|
@@ -35,17 +35,19 @@
|
|
|
35
35
|
* last change 2023-09-09
|
|
36
36
|
* author: Ks Tan
|
|
37
37
|
*/
|
|
38
|
+
import { <%= it.typename %> } from '~/simpleapp/generate/openapi';
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
const {$<%= it.typename %>Doc,$listen } = useNuxtApp();
|
|
41
42
|
const doc = $<%= it.typename %>Doc()
|
|
42
43
|
const docdata = doc.getReactiveData();
|
|
43
|
-
|
|
44
|
+
type <%= it.typename %>Key = keyof <%= it.typename %>
|
|
45
|
+
|
|
44
46
|
definePageMeta({
|
|
45
47
|
menuPath:'nocategory/<%= it.name %>'
|
|
46
48
|
});
|
|
47
49
|
|
|
48
|
-
const columns= [<%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
|
|
50
|
+
const columns:<%= it.typename %>Key[] = [<%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
|
|
49
51
|
<%let obj=it.jsonschema.properties[key] %>
|
|
50
52
|
<%let config=it.jsonschema['x-simpleapp-config'] %>
|
|
51
53
|
<%if(skipcolumns.indexOf(key)>=0){%>
|
|
@@ -35,17 +35,17 @@
|
|
|
35
35
|
* last change 2023-09-09
|
|
36
36
|
* author: Ks Tan
|
|
37
37
|
*/
|
|
38
|
-
|
|
38
|
+
import { <%= it.typename %> } from '~/simpleapp/generate/openapi';
|
|
39
39
|
|
|
40
40
|
const {$<%= it.typename %>Doc,$listen } = useNuxtApp();
|
|
41
41
|
const doc = $<%= it.typename %>Doc()
|
|
42
42
|
const docdata = doc.getReactiveData();
|
|
43
|
-
|
|
43
|
+
type <%= it.typename %>Key = keyof <%= it.typename %>
|
|
44
44
|
definePageMeta({
|
|
45
45
|
menuPath:'nocategory/<%= it.name %>'
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
const columns= [<%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
|
|
48
|
+
const columns: <%= it.typename %>Key[] = [<%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
|
|
49
49
|
<%let obj=it.jsonschema.properties[key] %>
|
|
50
50
|
<%let config=it.jsonschema['x-simpleapp-config'] %>
|
|
51
51
|
<%if(skipcolumns.indexOf(key)>=0){%>
|
package/templates/nest/.env._eta
CHANGED
|
@@ -14,19 +14,19 @@ HTTP_PORT=<%=it.configs.backendPort%>
|
|
|
14
14
|
BPMN_PATH=./src/simpleapp/workflows/bpmn/
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
OAUTH2_BASEURL=<%=it.configs.oauthSetting.oauthBaseUrl%>
|
|
17
|
+
OAUTH2_BASEURL=<%=it.configs.oauthSetting ? it.configs.oauthSetting.oauthBaseUrl : ''%>
|
|
18
18
|
|
|
19
|
-
OAUTH2_REALM=<%=it.configs.oauthSetting.oauthRealm%>
|
|
19
|
+
OAUTH2_REALM=<%=it.configs.oauthSetting ? it.configs.oauthSetting.oauthRealm : ''%>
|
|
20
20
|
|
|
21
|
-
OAUTH2_CONFIGURL=<%=it.configs.oauthSetting.oauthRealmUrl%>
|
|
21
|
+
OAUTH2_CONFIGURL=<%=it.configs.oauthSetting ? it.configs.oauthSetting.oauthRealmUrl : ''%>
|
|
22
22
|
|
|
23
|
-
OAUTH2_CLIENTID=<%=it.configs.oauthSetting.oauthClient%>
|
|
23
|
+
OAUTH2_CLIENTID=<%=it.configs.oauthSetting ? it.configs.oauthSetting.oauthClient : ''%>
|
|
24
24
|
|
|
25
|
-
OAUTH2_CLIENTSECRET=<%=it.configs.oauthSetting.oauthClientSecret%>
|
|
25
|
+
OAUTH2_CLIENTSECRET=<%=it.configs.oauthSetting ? it.configs.oauthSetting.oauthClientSecret : ''%>
|
|
26
26
|
|
|
27
|
-
OAUTH2_ADMINROLE = <%=it.configs.oauthSetting.adminRole%>
|
|
27
|
+
OAUTH2_ADMINROLE = <%=it.configs.oauthSetting ? it.configs.oauthSetting.adminRole : ''%>
|
|
28
28
|
|
|
29
|
-
AUTH_SECRET_KEY=<%=it.configs.oauthSetting.oauthAuthSecretKey%>
|
|
29
|
+
AUTH_SECRET_KEY=<%=it.configs.oauthSetting ? it.configs.oauthSetting.oauthAuthSecretKey : 'any'%>
|
|
30
30
|
|
|
31
31
|
BACKEND_URL=http://localhost:<%=it.configs.backendPort%>
|
|
32
32
|
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* This file was automatically generated by simpleapp generator. Every
|
|
3
3
|
* MODIFICATION OVERRIDE BY GENERATEOR
|
|
4
|
-
* last change
|
|
4
|
+
* last change 2024-03-17
|
|
5
5
|
* Author: Ks Tan
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';
|
|
8
|
+
import { Module, MiddlewareConsumer, NestModule, Provider } from '@nestjs/common';
|
|
9
9
|
import { MongooseModule,MongooseModuleOptions } from '@nestjs/mongoose';
|
|
10
|
+
import { GraphQLModule } from '@nestjs/graphql';
|
|
11
|
+
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
|
|
12
|
+
|
|
10
13
|
import { APP_GUARD,APP_INTERCEPTOR,APP_FILTER } from '@nestjs/core';
|
|
11
14
|
import { ResponseInterceptor } from './simpleapp/generate/commons/interceptors/response.interceptor'
|
|
12
15
|
import {
|
|
@@ -21,6 +24,7 @@ import {RolesGuard} from './simpleapp/generate/commons/roles/roles.guard'
|
|
|
21
24
|
import { ConfigModule } from '@nestjs/config';
|
|
22
25
|
import { ServeStaticModule } from '@nestjs/serve-static';
|
|
23
26
|
import { join } from 'path';
|
|
27
|
+
import { AppResolver } from './app.resolver';
|
|
24
28
|
import { TenantMiddleware } from './simpleapp/generate/commons/middlewares/tenant.middleware';
|
|
25
29
|
import { AppController } from './app.controller';
|
|
26
30
|
import { AppService } from './app.service';
|
|
@@ -30,9 +34,16 @@ import { PermissionMongoSchema } from './simpleapp/generate/models/perm.model';
|
|
|
30
34
|
import { ApiEventMongoSchema } from './simpleapp/generate/models/apievent.model';
|
|
31
35
|
import { EventEmitterModule } from '@nestjs/event-emitter';
|
|
32
36
|
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
33
40
|
@Module({
|
|
34
41
|
|
|
35
42
|
imports: [
|
|
43
|
+
GraphQLModule.forRoot<ApolloDriverConfig>({
|
|
44
|
+
driver: ApolloDriver,
|
|
45
|
+
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
|
|
46
|
+
}),
|
|
36
47
|
ConfigModule.forRoot(),
|
|
37
48
|
EventEmitterModule.forRoot({
|
|
38
49
|
// set this to `true` to use wildcards
|
|
@@ -71,30 +82,20 @@ import { EventEmitterModule } from '@nestjs/event-emitter';
|
|
|
71
82
|
]),
|
|
72
83
|
],
|
|
73
84
|
controllers: [AppController],
|
|
74
|
-
providers: [
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
|
|
82
|
-
useClass: ResourceGuard,
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
provide: APP_GUARD,
|
|
86
|
-
useClass: RolesGuard, //use simpleapp own roleguard
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
provide: APP_INTERCEPTOR,
|
|
90
|
-
useClass: ResponseInterceptor,
|
|
91
|
-
},
|
|
92
|
-
],
|
|
85
|
+
providers: [AppService,AppResolver, {
|
|
86
|
+
provide: APP_INTERCEPTOR,
|
|
87
|
+
useClass: ResponseInterceptor,
|
|
88
|
+
},
|
|
89
|
+
{provide: APP_GUARD,useClass: AuthGuard,},
|
|
90
|
+
{provide: APP_GUARD,useClass: ResourceGuard,},
|
|
91
|
+
{provide: APP_GUARD,useClass: RolesGuard,}
|
|
92
|
+
],
|
|
93
93
|
})
|
|
94
94
|
export class AppModule implements NestModule {
|
|
95
95
|
configure(consumer: MiddlewareConsumer) {
|
|
96
96
|
consumer
|
|
97
97
|
.apply(TenantMiddleware)
|
|
98
|
+
// .exclude('/graphql')
|
|
98
99
|
.exclude('/api-yaml')
|
|
99
100
|
.exclude('/api-json')
|
|
100
101
|
.exclude('/api')
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* This file was automatically generated by simpleapp generator. Every
|
|
3
3
|
* MODIFICATION OVERRIDE BY GENERATEOR
|
|
4
|
-
* last change
|
|
4
|
+
* last change 2024-04-17
|
|
5
5
|
* Author: Ks Tan
|
|
6
6
|
*/
|
|
7
7
|
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
|
8
8
|
|
|
9
9
|
export const AppUser = createParamDecorator(
|
|
10
|
-
(data: unknown, ctx: ExecutionContext) => {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
(data: unknown, ctx: ExecutionContext) => {
|
|
11
|
+
if (ctx.getType() == 'http') {
|
|
12
|
+
const request = ctx.switchToHttp().getRequest();
|
|
13
|
+
return request['sessionuser'];
|
|
14
|
+
} else if (ctx.getArgs()[2]) {
|
|
15
|
+
const req = ctx.getArgs()[2].req;
|
|
16
|
+
return req['sessionuser'];
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
13
19
|
},
|
|
14
|
-
);
|
|
20
|
+
);
|
package/templates/nest/src/simpleapp/generate/commons/interceptors/response.interceptor.ts.eta
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* This file was automatically generated by simpleapp generator. Every
|
|
3
3
|
* MODIFICATION OVERRIDE BY GENERATEOR
|
|
4
|
-
* last change 2023-
|
|
4
|
+
* last change 2023-03-17
|
|
5
5
|
* Author: Ks Tan
|
|
6
6
|
*/
|
|
7
7
|
import {
|
|
@@ -25,31 +25,41 @@ export class ResponseInterceptor implements NestInterceptor {
|
|
|
25
25
|
@InjectModel('ApiEvent') private apieventmodel: Model<ApiEvent>,
|
|
26
26
|
) {}
|
|
27
27
|
|
|
28
|
-
|
|
29
28
|
async intercept(
|
|
30
29
|
context: ExecutionContext,
|
|
31
30
|
next: CallHandler,
|
|
32
31
|
): Promise<Observable<any>> {
|
|
32
|
+
|
|
33
|
+
//not http request then exclude such as graphql
|
|
34
|
+
if(context.getType()!='http'){
|
|
35
|
+
// obtain usersession here
|
|
36
|
+
return next.handle().pipe(tap(async () => {
|
|
37
|
+
//console.log("none http, do nothing at interceptor")
|
|
38
|
+
}))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
33
42
|
const req = context.switchToHttp().getRequest();
|
|
34
43
|
const resp = context.switchToHttp().getResponse();
|
|
44
|
+
//console.log("want to get user session:", Object.keys(req))
|
|
35
45
|
const usersession: UserContext = req['sessionuser'];
|
|
36
|
-
|
|
46
|
+
//console.log("after read user session:",usersession)
|
|
37
47
|
const method = req['method'];
|
|
38
48
|
const headers = { ...req['headers'] };
|
|
39
49
|
const ip = req['ip'];
|
|
40
50
|
const url = req['url'];
|
|
41
51
|
// let { url, method, headers, body }
|
|
42
52
|
const session = await this.connection.startSession();
|
|
43
|
-
if(!session['runCount']){
|
|
44
|
-
session['runCount']=0
|
|
45
|
-
}else{
|
|
46
|
-
session['runCount']=session['runCount']+1
|
|
47
|
-
}
|
|
48
|
-
usersession.setDBSession(session)
|
|
53
|
+
if (!session['runCount']) {
|
|
54
|
+
session['runCount'] = 0;
|
|
55
|
+
} else {
|
|
56
|
+
session['runCount'] = session['runCount'] + 1;
|
|
57
|
+
}
|
|
58
|
+
usersession.setDBSession(session);
|
|
49
59
|
// const session: ClientSession = usersession.getDBSession();
|
|
50
60
|
const logid: string = crypto.randomUUID();
|
|
51
61
|
const starttime = new Date();
|
|
52
|
-
let canCommit = true
|
|
62
|
+
let canCommit = true;
|
|
53
63
|
//authorization no need
|
|
54
64
|
delete headers['authorization']; //='--removed--'
|
|
55
65
|
const eventdata: ApiEvent = {
|
|
@@ -71,37 +81,33 @@ export class ResponseInterceptor implements NestInterceptor {
|
|
|
71
81
|
|
|
72
82
|
// req['eventObj'] = eventObj;
|
|
73
83
|
return next.handle().pipe(
|
|
74
|
-
|
|
75
|
-
catchError( async(err,caught)=>{
|
|
76
|
-
|
|
84
|
+
catchError(async (err, caught) => {
|
|
77
85
|
// console.log('**************catchError at interceptor ',method,url)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const responseBody = {
|
|
86
|
+
if (session.inTransaction()) {
|
|
87
|
+
await session.abortTransaction();
|
|
88
|
+
canCommit = false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const responseBody = {
|
|
85
92
|
message: err.message,
|
|
86
93
|
timestamp: new Date().toISOString(),
|
|
87
94
|
path: url,
|
|
88
95
|
error: err.options,
|
|
89
96
|
};
|
|
90
|
-
|
|
91
|
-
// eventObj.statusCode = err.status;
|
|
92
|
-
// eventObj.errMsg = responseBody.message;
|
|
93
|
-
// const endtime = new Date();
|
|
94
|
-
// eventObj.updated = endtime.toISOString();
|
|
95
|
-
// eventObj.data = req.body;
|
|
96
|
-
// eventObj.errData = responseBody.error;
|
|
97
|
-
// eventObj.status = 'NG';
|
|
98
|
-
// eventObj.duration =
|
|
99
|
-
// endtime.getTime() - new Date(eventObj.created).getTime();
|
|
100
|
-
// eventObj.save();
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
// eventObj.statusCode = err.status;
|
|
99
|
+
// eventObj.errMsg = responseBody.message;
|
|
100
|
+
// const endtime = new Date();
|
|
101
|
+
// eventObj.updated = endtime.toISOString();
|
|
102
|
+
// eventObj.data = req.body;
|
|
103
|
+
// eventObj.errData = responseBody.error;
|
|
104
|
+
// eventObj.status = 'NG';
|
|
105
|
+
// eventObj.duration =
|
|
106
|
+
// endtime.getTime() - new Date(eventObj.created).getTime();
|
|
107
|
+
// eventObj.save();
|
|
104
108
|
|
|
109
|
+
resp.status(err.status);
|
|
110
|
+
return responseBody;
|
|
105
111
|
}),
|
|
106
112
|
tap(async () => {
|
|
107
113
|
// console.log("============interceptor tap",method,url)
|
|
@@ -111,17 +117,16 @@ export class ResponseInterceptor implements NestInterceptor {
|
|
|
111
117
|
eventObj.updated = endtime.toISOString();
|
|
112
118
|
eventObj.status = 'OK';
|
|
113
119
|
eventObj.duration = endtime.getTime() - starttime.getTime();
|
|
114
|
-
await eventObj.save();
|
|
115
|
-
|
|
120
|
+
await eventObj.save();
|
|
116
121
|
|
|
117
122
|
if (process.env.DRYRUN == 'true') {
|
|
118
123
|
console.warn('--------dryrun! roll back everything-----------');
|
|
119
|
-
if (session.inTransaction() && canCommit
|
|
120
|
-
await session.abortTransaction()
|
|
124
|
+
if (session.inTransaction() && canCommit) {
|
|
125
|
+
await session.abortTransaction();
|
|
121
126
|
}
|
|
122
127
|
} else {
|
|
123
|
-
if (session.inTransaction() && canCommit
|
|
124
|
-
await session.commitTransaction()//.then(()=>session.endSession());
|
|
128
|
+
if (session.inTransaction() && canCommit) {
|
|
129
|
+
await session.commitTransaction(); //.then(()=>session.endSession());
|
|
125
130
|
}
|
|
126
131
|
}
|
|
127
132
|
// session.endSession()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* This file was automatically generated by simpleapp generator. Every
|
|
3
3
|
* MODIFICATION OVERRIDE BY GENERATEOR
|
|
4
|
-
* last change
|
|
4
|
+
* last change 2024-03-17
|
|
5
5
|
* Author: Ks Tan
|
|
6
6
|
*/
|
|
7
7
|
import {
|
|
@@ -52,6 +52,19 @@ export class TenantMiddleware implements NestMiddleware {
|
|
|
52
52
|
next();
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
|
+
const u = new UserContext(this.usermodel, this.permmodel);
|
|
56
|
+
|
|
57
|
+
if (req.baseUrl == '/graphql') {
|
|
58
|
+
let tokenstr: string = req.headers['authorization'] ?? '';
|
|
59
|
+
tokenstr = tokenstr.replace('Bearer ', '');
|
|
60
|
+
const xorg = req.headers['x-org'] ?? this.defaultxorg;
|
|
61
|
+
if (tokenstr) {
|
|
62
|
+
await u.setCurrentUserInfo(tokenstr, xorg);
|
|
63
|
+
}
|
|
64
|
+
req['sessionuser'] = u;
|
|
65
|
+
next();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
55
68
|
this.logger.debug(`running TenantMiddleware for ${req.baseUrl}`);
|
|
56
69
|
if (!req.headers['authorization']) {
|
|
57
70
|
this.logger.log('undefine bearer token');
|
|
@@ -62,11 +75,10 @@ export class TenantMiddleware implements NestMiddleware {
|
|
|
62
75
|
'undefine x-org and require that at ' + req.baseUrl,
|
|
63
76
|
'TenantMiddleware',
|
|
64
77
|
);
|
|
65
|
-
throw new BadRequestException('undefine header string x-org')
|
|
78
|
+
throw new BadRequestException('undefine header string x-org');
|
|
66
79
|
// return res.status(401).send('undefine header string x-org');
|
|
67
80
|
}
|
|
68
81
|
// const session = await this.connection.startSession();
|
|
69
|
-
const u = new UserContext(this.usermodel, this.permmodel);
|
|
70
82
|
// console.log("line 43")
|
|
71
83
|
try {
|
|
72
84
|
let tokenstr: string = req.headers['authorization'];
|
|
@@ -95,7 +107,7 @@ export class TenantMiddleware implements NestMiddleware {
|
|
|
95
107
|
}
|
|
96
108
|
} catch (err) {
|
|
97
109
|
this.logger.error(err);
|
|
98
|
-
throw new BadRequestException(err
|
|
110
|
+
throw new BadRequestException(err);
|
|
99
111
|
}
|
|
100
112
|
}
|
|
101
113
|
}
|