@simitgroup/simpleapp-generator 1.6.7-m-alpha → 1.6.7-o-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/ReleaseNote.md CHANGED
@@ -1,3 +1,6 @@
1
+ [1.6.7o-alpha]
2
+ 1. exclude findIdThenPatch to execute beforeUpdate and afterUpdate
3
+
1
4
  [1.6.7m-alpha]
2
5
  1. insert many bug fix
3
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simitgroup/simpleapp-generator",
3
- "version": "1.6.7m-alpha",
3
+ "version": "1.6.7o-alpha",
4
4
  "description": "frontend nuxtjs and backend nests code generator using jsonschema",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -10,6 +10,7 @@ import { MongooseModule,MongooseModuleOptions } from '@nestjs/mongoose';
10
10
  import { GraphQLModule } from '@nestjs/graphql';
11
11
  import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
12
12
  import {GenerateModule} from './simpleapp/simpleapp.module'
13
+ import {EnvironmentMongoSchema} from './simpleapp/maintenance/models/environment.model'
13
14
  <% const nestmodules = it.configs.additionalNestModules%>
14
15
  <% for(let i=0; i<nestmodules.length;i++){ %>
15
16
  <% const modulename = capitalizeFirstLetter(nestmodules[i]) %>
@@ -91,6 +92,7 @@ import { WebhookMongoSchema } from './simpleapp/generate/models/webhook.model';
91
92
  { name: 'Permission', schema: PermissionMongoSchema },
92
93
  { name: 'ApiEvent', schema: ApiEventMongoSchema },
93
94
  { name: 'Webhook', schema: WebhookMongoSchema },
95
+ { name: 'Environment', schema: EnvironmentMongoSchema },
94
96
  ]),
95
97
  ],
96
98
  controllers: [AppController],
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * This file was automatically generated by simpleapp generator. Every
3
3
  * MODIFICATION OVERRIDE BY GENERATEOR
4
- * last change 2024-03-17
4
+ * last change 2025-08-27
5
5
  * Author: Ks Tan
6
6
  */
7
7
 
8
8
  import Base64URL from '@darkwolf/base64url';
9
- import { BadRequestException, Injectable, Logger, NestMiddleware } from '@nestjs/common';
9
+ import { BadRequestException, Injectable, Logger, NestMiddleware, ServiceUnavailableException } from '@nestjs/common';
10
10
  import { InjectModel } from '@nestjs/mongoose';
11
11
  import { NextFunction, Request, Response } from 'express';
12
12
  import { Model } from 'mongoose';
@@ -17,7 +17,7 @@ import { Miniappinstallation, Webhook } from '../../types';
17
17
  import { UserContext } from '../user.context';
18
18
  import { ApiKeyService } from './api-key/api-key.service';
19
19
  import { HEADER_X_API_KEY, HEADER_X_API_SECRET } from '../constants/header';
20
-
20
+ import {Environment} from '../../../maintenance/apischemas/environment'
21
21
  @Injectable()
22
22
  export class TenantMiddleware implements NestMiddleware {
23
23
  protected defaultXOrg = Base64URL.encodeText('0-0-0');
@@ -32,6 +32,7 @@ export class TenantMiddleware implements NestMiddleware {
32
32
  @InjectModel('Appintegration') private readonly appModel: Model<Appintegration>,
33
33
  @InjectModel('Webhook') private readonly webhookModel: Model<Webhook>,
34
34
  @InjectModel('Miniappinstallation') private readonly miniAppInstallationModel: Model<Miniappinstallation>,
35
+ @InjectModel('Environment') private envModel:Model<Environment>,
35
36
  private readonly apiKeyService: ApiKeyService,
36
37
  ) {}
37
38
 
@@ -51,6 +52,13 @@ export class TenantMiddleware implements NestMiddleware {
51
52
  return;
52
53
  }
53
54
 
55
+ const envs = await this.envModel.find()
56
+ let maintenanceMode = false
57
+ if(envs){
58
+ maintenanceMode = !envs[0].systemEnable
59
+ }
60
+
61
+
54
62
  let tokenStr: string = req.get('authorization') ?? '';
55
63
  tokenStr = tokenStr.replace('Bearer ', '');
56
64
  const xOrg = req.get('x-org') ?? this.defaultXOrg;
@@ -61,6 +69,11 @@ export class TenantMiddleware implements NestMiddleware {
61
69
  if (tokenStr) {
62
70
  await user.setCurrentUserInfo(tokenStr, xOrg, this.webhookModel);
63
71
  }
72
+
73
+ if(maintenanceMode && !user.isRealmAdmin()){
74
+ throw new ServiceUnavailableException("System in maintenance mode")
75
+ }
76
+
64
77
  req['sessionuser'] = user;
65
78
  next();
66
79
  return;
@@ -74,6 +87,9 @@ export class TenantMiddleware implements NestMiddleware {
74
87
  await this.apiKeyService.validate(req, user);
75
88
 
76
89
  req['sessionuser'] = user;
90
+ if(maintenanceMode){
91
+ throw new ServiceUnavailableException("System in maintenance mode")
92
+ }
77
93
  next();
78
94
  return;
79
95
  } catch (e) {
@@ -110,6 +126,12 @@ export class TenantMiddleware implements NestMiddleware {
110
126
 
111
127
  try {
112
128
  await user.setCurrentUserInfo(tokenStr, xOrg, this.webhookModel);
129
+
130
+ if(maintenanceMode && !user.isRealmAdmin()){
131
+ throw new ServiceUnavailableException("System in maintenance mode")
132
+ }
133
+
134
+
113
135
  user.detectMiniAppSdkRequest(req);
114
136
  if (user.getId() == '' && this.requireXOrg(req.baseUrl)) {
115
137
  this.logger.log('Access deny for user:', req.baseUrl);
@@ -836,7 +836,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
836
836
  }
837
837
  };
838
838
 
839
- findIdThenPatch = async (appuser: UserContext, id: string, data: T, session: mongo.ClientSession = undefined,skipLog:boolean=false) => {
839
+ findIdThenPatch = async (appuser: UserContext, id: string, data: Partial<T>, session: mongo.ClientSession = undefined, skipLog: boolean = false) => {
840
840
  const existingdata = await this.findById(appuser, id);
841
841
  if (!existingdata) {
842
842
  throw new NotFoundException(`${id} not found`, 'not found');
@@ -849,7 +849,8 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
849
849
 
850
850
  await this.identifyForeignKeys(appuser, data);
851
851
 
852
- if (this.hooks.beforeUpdate) await this.hooks.beforeUpdate(appuser, id, existingdata, data);
852
+ //patch not suitable trigger afterupdate
853
+ // if (this.hooks.beforeUpdate) await this.hooks.beforeUpdate(appuser, id, existingdata, data);
853
854
 
854
855
  const dbsession = appuser.getDBSession();
855
856
  if (dbsession && !dbsession.inTransaction()) {
@@ -860,7 +861,8 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
860
861
  // Object.assign(existingdata, data);
861
862
  delete data['_id'];
862
863
 
863
- this.reCalculateValue(data);
864
+ //patch not suitable trigger afterupdate
865
+ // this.reCalculateValue(data);
864
866
 
865
867
  // existingdata['_id']=''
866
868
  // console.log("newdata",data)
@@ -879,13 +881,14 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
879
881
  new: true,
880
882
  });
881
883
  //skip audit trail, useful when want to patch x-foreignkey code,label
882
- if(!skipLog) {
884
+ if (!skipLog) {
883
885
  await this.audittrail.addEvent(appuser, this.documentName, id, 'patch', data);
884
886
  }
885
887
  appuser.addUpdatedRecordId(this.documentName, data._id);
886
888
 
887
- if (this.hooks.afterUpdate) await this.hooks.afterUpdate(appuser, id, existingdata, result);
888
- await this.callWebhook(appuser, 'update', result);
889
+ //patch not suitable trigger afterupdate
890
+ // if (this.hooks.afterUpdate) await this.hooks.afterUpdate(appuser, id, existingdata, result);
891
+ // await this.callWebhook(appuser, 'update', result);
889
892
  return result; //await this.findById(appuser, id);
890
893
  } catch (err) {
891
894
  throw new InternalServerErrorException(err.message);
@@ -1036,7 +1039,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
1036
1039
  async runDefault(appuser: UserContext): Promise<unknown> {
1037
1040
  return 'Hello this is ' + this.getDocumentType() + ': ' + this.getDocumentName();
1038
1041
  }
1039
- async identifyForeignKeys(appuser: UserContext, data: T) {
1042
+ async identifyForeignKeys(appuser: UserContext, data: Partial<T>) {
1040
1043
  /**
1041
1044
  * 1. looping schemas identify what foreign key exists
1042
1045
  * 2. loop through record obtain all foreign key value
@@ -47,8 +47,8 @@ export type DefaultHooks<T> = {
47
47
  beforeUpdate?: (
48
48
  appuser: UserContext,
49
49
  id: string,
50
- data: T,
51
50
  existingdata: T,
51
+ data: T,
52
52
  ) => Promise<void>;
53
53
  afterUpdate?: (appuser: UserContext, id: string, prevdata: T,newdata:T) => Promise<void>;
54
54
  beforeDelete?: (
@@ -0,0 +1,17 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * MODIFICATION OVERRIDE BY GENERATEOR
4
+ * last change 2025-08-27
5
+ * Author: Ks Tan
6
+ */
7
+
8
+ import { ApiProperty } from '@nestjs/swagger';
9
+
10
+ export class UpgradeScript {
11
+ @ApiProperty({ type: String})
12
+ id: String
13
+ @ApiProperty({ type: String})
14
+ subject:String
15
+ @ApiProperty({ type: String})
16
+ description:String
17
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * MODIFICATION OVERRIDE BY GENERATEOR
4
+ * last change 2025-08-27
5
+ * Author: Ks Tan
6
+ */
7
+ export class Environment {
8
+ systemEnable: boolean
9
+ stopUntil: string
10
+ maintenanceMessage: string
11
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * MODIFICATION OVERRIDE BY GENERATEOR
4
+ * last change 2025-08-27
5
+ * Author: Ks Tan
6
+ */
7
+ export * from './dbupdate'
8
+ export * from './environment'
@@ -0,0 +1,39 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * --remove-this-line-to-prevent-override--
4
+ * last change 2025-08-27
5
+ * Author: Ks Tan
6
+ */
7
+
8
+ import { InternalServerErrorException } from "@nestjs/common"
9
+ import { exec } from "child_process"
10
+ import mongoose, { ClientSession } from "mongoose"
11
+
12
+
13
+ const readEnvironment = async () =>{
14
+ try {
15
+ await mongoose.connection.db.collection('environment').aggregate([
16
+
17
+ ],).toArray() // `toArray` forces execution
18
+ return "read environment";
19
+ } catch (err) {
20
+ throw err
21
+ }
22
+ }
23
+
24
+
25
+ export const v1_00_00 = ()=>{
26
+ const subject = 'Just a sample'
27
+ const description = `do nothing, only read enironment
28
+ `;
29
+ const execute = async () =>{
30
+ try{
31
+ const res1 = await readEnvironment()
32
+
33
+ return `${res1}`
34
+ }catch(e){
35
+ throw e
36
+ }
37
+ }
38
+ return {execute,subject,description}
39
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * --remove-this-line-to-prevent-override--
4
+ * last change 2025-08-27
5
+ * Author: Ks Tan
6
+ */
7
+ export { v1_00_00 } from './1.00.00'
8
+
@@ -0,0 +1,72 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * MODIFICATION OVERRIDE BY GENERATEOR
4
+ * last change 2025-08-27
5
+ * Author: Ks Tan
6
+ */
7
+ import { Controller, Get, Post, Param,Logger,HttpCode } from '@nestjs/common';
8
+ import { MaintenanceService } from './maintenance.service';
9
+ import { ApiTags, ApiBody, ApiResponse, ApiOperation, ApiQuery } from '@nestjs/swagger';
10
+ import { Roles } from 'src/simpleapp/generate/commons/roles/roles.decorator';
11
+ import { Role } from 'src/simpleapp/generate/commons/roles/roles.enum';
12
+ import * as schemas from './apischemas'
13
+
14
+ @ApiTags('maintenance')
15
+ @Controller('maintenance')
16
+ @Roles(Role.SuperAdmin)
17
+ export class MaintenanceController {
18
+ private logger = new Logger();
19
+ constructor(private readonly maintenanceSvc: MaintenanceService) {}
20
+
21
+ @Get('/get-updates')
22
+ @Roles(Role.SuperAdmin)
23
+ @ApiResponse({
24
+ status: 200,
25
+ description: 'Sample 200 response',
26
+ type: [schemas.UpgradeScript],
27
+ })
28
+ async getUpdate() {
29
+ const result = await this.maintenanceSvc.getUpdates();
30
+ return result
31
+ }
32
+
33
+ @Post('/run-updates/:id')
34
+ @HttpCode(200)
35
+ @Roles(Role.SuperAdmin)
36
+ @ApiResponse({
37
+ status: 200,
38
+ description: 'Sample 200 response',
39
+ type: [String],
40
+ })
41
+ async runUpdate(@Param('id') id:string) {
42
+ const result:string = await this.maintenanceSvc.runUpdates(id);
43
+ return result
44
+ }
45
+
46
+ @Post('/stop-service')
47
+ @HttpCode(200)
48
+ @Roles(Role.SuperAdmin)
49
+ @ApiResponse({
50
+ status: 200,
51
+ description: 'Sample 200 response',
52
+ type: [String],
53
+ })
54
+ async runStopService() {
55
+ const result:string = await this.maintenanceSvc.runStopService();
56
+ return result
57
+ }
58
+
59
+ @Post('/start-service')
60
+ @HttpCode(200)
61
+ @Roles(Role.SuperAdmin)
62
+ @ApiResponse({
63
+ status: 200,
64
+ description: 'Sample 200 response',
65
+ type: [String],
66
+ })
67
+ async runStartService() {
68
+ const result:string = await this.maintenanceSvc.runStartService();
69
+ return result
70
+ }
71
+
72
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * MODIFICATION OVERRIDE BY GENERATEOR
4
+ * last change 2025-08-27
5
+ * Author: Ks Tan
6
+ */
7
+
8
+ import { BadRequestException, Injectable, InternalServerErrorException } from '@nestjs/common';
9
+ import { Model } from 'mongoose';
10
+ import { InjectModel } from '@nestjs/mongoose';
11
+ import * as dbupdate from './dbupdate'
12
+ import * as schemas from './apischemas'
13
+ @Injectable()
14
+ export class MaintenanceService {
15
+
16
+
17
+ constructor(@InjectModel('Environment') private sysEnvdoc: Model<schemas.Environment>) {
18
+
19
+ this.initEnv()
20
+ }
21
+
22
+ async initEnv(){
23
+ const res = await this.sysEnvdoc.find()
24
+ if(res.length==0){
25
+ const newdoc = new this.sysEnvdoc({
26
+ systemEnable:true
27
+ });
28
+ await newdoc.save()
29
+ }
30
+
31
+ }
32
+
33
+
34
+ async getUpdates() {
35
+ const keys = Object.keys(dbupdate)
36
+ const updatescripts:schemas.UpgradeScript[] = []
37
+ const key =keys[0]
38
+ // console.log(dbupdate[key]())
39
+
40
+
41
+ keys.forEach((k)=>{
42
+ const item = dbupdate[k]()
43
+ if(item.execute && item.subject){
44
+ updatescripts.push({
45
+ id: k,
46
+ subject:item.subject,
47
+ description: item.description
48
+ })
49
+ }
50
+ })
51
+
52
+ return Promise.resolve(updatescripts);
53
+ }
54
+
55
+ async runUpdates(versionId:string) {
56
+ try{
57
+ if(dbupdate[versionId]){
58
+ const result = await dbupdate[versionId]().execute()
59
+ return Promise.resolve(result);
60
+ }else{
61
+
62
+ throw new BadRequestException(`invalid update script ${versionId}`)
63
+ }
64
+
65
+ }catch(e){
66
+ throw new InternalServerErrorException(`Error db update (${versionId}): ${e.message}`)
67
+ }
68
+
69
+
70
+ }
71
+
72
+ async runStopService(){
73
+ const res = await this.sysEnvdoc.find()
74
+ if(res.length>0){
75
+ res[0].systemEnable=false
76
+ res[0].save()
77
+ }
78
+ return Promise.resolve(`status: ${res[0].systemEnable}`)
79
+ }
80
+ async runStartService(){
81
+ const res = await this.sysEnvdoc.find()
82
+ if(res.length>0){
83
+ res[0].systemEnable=true
84
+ res[0].save()
85
+ }
86
+ return Promise.resolve(`status: ${res[0].systemEnable}`)
87
+ }
88
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * MODIFICATION OVERRIDE BY GENERATEOR
4
+ * last change 2025-08-27
5
+ * Author: Ks Tan
6
+ */
7
+ import { Schema } from 'mongoose';
8
+ // import { TenantClientSetting, TenantOwner, TenantOutstandingReminder, Tenant } from '../types/tenant.type';
9
+ const schemasetting = {
10
+ systemEnable: { type: Boolean},
11
+ stopUntil: { type: String },
12
+ maintenanceMessage: { type: String},
13
+ };
14
+
15
+ export const EnvironmentMongoSchema = new Schema(schemasetting, { collection: 'environment' })
16
+
@@ -10,6 +10,10 @@ import {DocNumberFormatGenerator} from './generate/commons/docnogenerator.servic
10
10
  import { AuditTrail } from './generate/commons/audittrail.service';
11
11
  import { RunWebhookService } from '../simpleapp/generate/commons/runwebhook.service'
12
12
  import { UserResolverService } from './services/userresolver.service';
13
+ import {MaintenanceService} from './maintenance/maintenance.service'
14
+ import {MaintenanceController} from './maintenance/maintenance.controller'
15
+ import {EnvironmentMongoSchema} from './maintenance/models/environment.model'
16
+
13
17
  // auto import modules
14
18
  <% for(let i=0;i<it.modules.length; i++){ %>
15
19
  <% let obj = it.modules[i]%>
@@ -42,6 +46,7 @@ import additionalModule from './additional.module';
42
46
  ...additionalModule.imports,
43
47
 
44
48
  MongooseModule.forFeature([
49
+ { name: 'Environment', schema: EnvironmentMongoSchema },
45
50
  <% for(let i=0;i<it.modules.length; i++){ %>
46
51
  <% let obj = it.modules[i]%>
47
52
  { name: '<%= obj.docname %>', schema: <%= obj.docname %>MongoSchema },