@ruiapp/rapid-core 0.1.11 → 0.1.13

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 (30) hide show
  1. package/dist/core/eventManager.d.ts +1 -2
  2. package/dist/dataAccess/entityManager.d.ts +8 -6
  3. package/dist/index.d.ts +4 -0
  4. package/dist/index.js +403 -234
  5. package/dist/plugins/entityWatch/EntityWatchPlugin.d.ts +15 -0
  6. package/dist/plugins/entityWatch/EntityWatchPluginTypes.d.ts +15 -0
  7. package/dist/plugins/serverOperation/ServerOperationPlugin.d.ts +25 -0
  8. package/dist/plugins/serverOperation/ServerOperationPluginTypes.d.ts +11 -0
  9. package/dist/plugins/serverOperation/actionHandlers/index.d.ts +3 -0
  10. package/dist/plugins/serverOperation/actionHandlers/runServerOperation.d.ts +6 -0
  11. package/dist/types.d.ts +17 -2
  12. package/package.json +1 -1
  13. package/src/core/eventManager.ts +3 -4
  14. package/src/dataAccess/entityManager.ts +153 -10
  15. package/src/index.ts +5 -1
  16. package/src/plugins/auth/actionHandlers/createSession.ts +1 -1
  17. package/src/plugins/dataManage/actionHandlers/addEntityRelations.ts +2 -50
  18. package/src/plugins/dataManage/actionHandlers/createCollectionEntitiesBatch.ts +1 -12
  19. package/src/plugins/dataManage/actionHandlers/createCollectionEntity.ts +1 -11
  20. package/src/plugins/dataManage/actionHandlers/deleteCollectionEntityById.ts +1 -20
  21. package/src/plugins/dataManage/actionHandlers/removeEntityRelations.ts +2 -48
  22. package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +1 -25
  23. package/src/plugins/entityWatch/EntityWatchPlugin.ts +96 -0
  24. package/src/plugins/entityWatch/EntityWatchPluginTypes.ts +19 -0
  25. package/src/plugins/serverOperation/ServerOperationPlugin.ts +94 -0
  26. package/src/plugins/serverOperation/ServerOperationPluginTypes.ts +13 -0
  27. package/src/plugins/serverOperation/actionHandlers/index.ts +6 -0
  28. package/src/plugins/serverOperation/actionHandlers/runServerOperation.ts +15 -0
  29. package/src/server.ts +1 -1
  30. package/src/types.ts +13 -2
package/dist/index.js CHANGED
@@ -1692,6 +1692,27 @@ function mapPropertyNameToColumnName(model, propertyName) {
1692
1692
  return property.columnName || property.code;
1693
1693
  }
1694
1694
 
1695
+ function getEntityPartChanges(before, after) {
1696
+ if (!before) {
1697
+ throw new Error("Argument 'before' can not be null.");
1698
+ }
1699
+ if (!after) {
1700
+ throw new Error("Argument 'after' can not be null.");
1701
+ }
1702
+ let changed = null;
1703
+ for (const key in after) {
1704
+ if (after[key] != before[key]) {
1705
+ if (changed) {
1706
+ changed[key] = after[key];
1707
+ }
1708
+ else {
1709
+ changed = { [key]: after[key] };
1710
+ }
1711
+ }
1712
+ }
1713
+ return changed;
1714
+ }
1715
+
1695
1716
  function convertToDataAccessOrderBy(model, orderByList) {
1696
1717
  if (!orderByList) {
1697
1718
  return orderByList;
@@ -2079,9 +2100,20 @@ async function createEntity(server, dataAccessor, options) {
2079
2100
  }
2080
2101
  return newEntity;
2081
2102
  }
2082
- async function updateEntityById(server, dataAccessor, options) {
2103
+ async function updateEntityById(server, dataAccessor, options, plugin) {
2083
2104
  const model = dataAccessor.getModel();
2084
- const { id, entity, changes } = options;
2105
+ const { id, entityToSave } = options;
2106
+ if (!id) {
2107
+ throw new Error("Id is required when updating an entity.");
2108
+ }
2109
+ const entity = await this.findById(id);
2110
+ if (!entity) {
2111
+ throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
2112
+ }
2113
+ const changes = getEntityPartChanges(entity, entityToSave);
2114
+ if (!changes) {
2115
+ return entity;
2116
+ }
2085
2117
  const oneRelationPropertiesToUpdate = [];
2086
2118
  const manyRelationPropertiesToUpdate = [];
2087
2119
  ___namespace.keys(changes).forEach((propertyCode) => {
@@ -2187,6 +2219,13 @@ async function updateEntityById(server, dataAccessor, options) {
2187
2219
  }
2188
2220
  updatedEntity[property.code] = relatedEntities;
2189
2221
  }
2222
+ server.emitEvent("entity.update", plugin, {
2223
+ namespace: model.namespace,
2224
+ modelSingularCode: model.singularCode,
2225
+ before: entity,
2226
+ after: updatedEntity,
2227
+ changes: changes,
2228
+ });
2190
2229
  return updatedEntity;
2191
2230
  }
2192
2231
  class EntityManager {
@@ -2196,6 +2235,9 @@ class EntityManager {
2196
2235
  this.#server = server;
2197
2236
  this.#dataAccessor = dataAccessor;
2198
2237
  }
2238
+ getModel() {
2239
+ return this.#dataAccessor.getModel();
2240
+ }
2199
2241
  async findEntities(options) {
2200
2242
  return await findEntities(this.#server, this.#dataAccessor, options);
2201
2243
  }
@@ -2213,20 +2255,102 @@ class EntityManager {
2213
2255
  ]
2214
2256
  });
2215
2257
  }
2216
- async createEntity(options) {
2217
- return await createEntity(this.#server, this.#dataAccessor, options);
2258
+ async createEntity(options, plugin) {
2259
+ const model = this.getModel();
2260
+ const newEntity = await createEntity(this.#server, this.#dataAccessor, options);
2261
+ this.#server.emitEvent("entity.create", plugin, {
2262
+ namespace: model.namespace,
2263
+ modelSingularCode: model.singularCode,
2264
+ after: newEntity,
2265
+ });
2266
+ return newEntity;
2218
2267
  }
2219
- async updateEntityById(options) {
2220
- return await updateEntityById(this.#server, this.#dataAccessor, options);
2268
+ async updateEntityById(options, plugin) {
2269
+ return await updateEntityById(this.#server, this.#dataAccessor, options, plugin);
2221
2270
  }
2222
2271
  async count(options) {
2223
2272
  return await this.#dataAccessor.count(options);
2224
2273
  }
2225
- async deleteById(id) {
2226
- return await this.#dataAccessor.deleteById(id);
2274
+ async deleteById(id, plugin) {
2275
+ const model = this.getModel();
2276
+ const entity = await this.findById(id);
2277
+ if (!entity) {
2278
+ return;
2279
+ }
2280
+ await this.#dataAccessor.deleteById(id);
2281
+ this.#server.emitEvent("entity.delete", plugin, {
2282
+ namespace: model.namespace,
2283
+ modelSingularCode: model.singularCode,
2284
+ before: entity,
2285
+ });
2227
2286
  }
2228
- getModel() {
2229
- return this.#dataAccessor.getModel();
2287
+ async addRelations(options, plugin) {
2288
+ const model = this.getModel();
2289
+ const { id, property, relations } = options;
2290
+ const entity = await this.findById(id);
2291
+ if (!entity) {
2292
+ throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
2293
+ }
2294
+ const relationProperty = model.properties.find(e => e.code === property);
2295
+ if (!relationProperty) {
2296
+ throw new Error(`Property '${property}' was not found in ${model.namespace}.${model.singularCode}`);
2297
+ }
2298
+ if (!(isRelationProperty(relationProperty) && relationProperty.relation === "many")) {
2299
+ throw new Error(`Operation 'addRelations' is only supported on property of 'many' relation`);
2300
+ }
2301
+ const server = this.#server;
2302
+ const { queryBuilder } = server;
2303
+ if (relationProperty.linkTableName) {
2304
+ for (const relation of relations) {
2305
+ const command = `INSERT INTO ${queryBuilder.quoteTable({ schema: relationProperty.linkSchema, tableName: relationProperty.linkTableName })} (${queryBuilder.quoteObject(relationProperty.selfIdColumnName)}, ${queryBuilder.quoteObject(relationProperty.targetIdColumnName)})
2306
+ SELECT $1, $2 WHERE NOT EXISTS (
2307
+ SELECT ${queryBuilder.quoteObject(relationProperty.selfIdColumnName)}, ${queryBuilder.quoteObject(relationProperty.targetIdColumnName)}
2308
+ FROM ${queryBuilder.quoteTable({ schema: relationProperty.linkSchema, tableName: relationProperty.linkTableName })}
2309
+ WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName)}=$2
2310
+ )`;
2311
+ const params = [id, relation.id];
2312
+ await server.queryDatabaseObject(command, params);
2313
+ }
2314
+ }
2315
+ server.emitEvent("entity.addRelations", plugin, {
2316
+ namespace: model.namespace,
2317
+ modelSingularCode: model.singularCode,
2318
+ entity,
2319
+ property,
2320
+ relations,
2321
+ });
2322
+ }
2323
+ async removeRelations(options, plugin) {
2324
+ const model = this.getModel();
2325
+ const { id, property, relations } = options;
2326
+ const entity = await this.findById(id);
2327
+ if (!entity) {
2328
+ throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
2329
+ }
2330
+ const relationProperty = model.properties.find(e => e.code === property);
2331
+ if (!relationProperty) {
2332
+ throw new Error(`Property '${property}' was not found in ${model.namespace}.${model.singularCode}`);
2333
+ }
2334
+ if (!(isRelationProperty(relationProperty) && relationProperty.relation === "many")) {
2335
+ throw new Error(`Operation 'removeRelations' is only supported on property of 'many' relation`);
2336
+ }
2337
+ const server = this.#server;
2338
+ const { queryBuilder } = server;
2339
+ if (relationProperty.linkTableName) {
2340
+ for (const relation of relations) {
2341
+ const command = `DELETE FROM ${queryBuilder.quoteTable({ schema: relationProperty.linkSchema, tableName: relationProperty.linkTableName })}
2342
+ WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName)}=$2;`;
2343
+ const params = [id, relation.id];
2344
+ await server.queryDatabaseObject(command, params);
2345
+ }
2346
+ }
2347
+ server.emitEvent("entity.removeRelations", plugin, {
2348
+ namespace: model.namespace,
2349
+ modelSingularCode: model.singularCode,
2350
+ entity,
2351
+ property,
2352
+ relations,
2353
+ });
2230
2354
  }
2231
2355
  }
2232
2356
 
@@ -2557,32 +2681,32 @@ async function generateJwtSecretKey() {
2557
2681
  return encode(exportedKey);
2558
2682
  }
2559
2683
 
2560
- const code$j = "listMetaModels";
2561
- async function handler$j(plugin, ctx, options) {
2684
+ const code$k = "listMetaModels";
2685
+ async function handler$k(plugin, ctx, options) {
2562
2686
  const { applicationConfig } = ctx;
2563
2687
  ctx.output = { list: applicationConfig.models };
2564
2688
  }
2565
2689
 
2566
2690
  var listMetaModels = /*#__PURE__*/Object.freeze({
2567
2691
  __proto__: null,
2568
- code: code$j,
2569
- handler: handler$j
2692
+ code: code$k,
2693
+ handler: handler$k
2570
2694
  });
2571
2695
 
2572
- const code$i = "listMetaRoutes";
2573
- async function handler$i(plugin, ctx, options) {
2696
+ const code$j = "listMetaRoutes";
2697
+ async function handler$j(plugin, ctx, options) {
2574
2698
  const { applicationConfig } = ctx;
2575
2699
  ctx.output = { list: applicationConfig.routes };
2576
2700
  }
2577
2701
 
2578
2702
  var listMetaRoutes = /*#__PURE__*/Object.freeze({
2579
2703
  __proto__: null,
2580
- code: code$i,
2581
- handler: handler$i
2704
+ code: code$j,
2705
+ handler: handler$j
2582
2706
  });
2583
2707
 
2584
- const code$h = "getMetaModelDetail";
2585
- async function handler$h(plugin, ctx, options) {
2708
+ const code$i = "getMetaModelDetail";
2709
+ async function handler$i(plugin, ctx, options) {
2586
2710
  const { server, input } = ctx;
2587
2711
  const model = server.getModel(input);
2588
2712
  ctx.output = model;
@@ -2590,8 +2714,8 @@ async function handler$h(plugin, ctx, options) {
2590
2714
 
2591
2715
  var getMetaModelDetail = /*#__PURE__*/Object.freeze({
2592
2716
  __proto__: null,
2593
- code: code$h,
2594
- handler: handler$h
2717
+ code: code$i,
2718
+ handler: handler$i
2595
2719
  });
2596
2720
 
2597
2721
  /**
@@ -2961,9 +3085,9 @@ function transformFilterWithSubFilters(filter) {
2961
3085
  return filter;
2962
3086
  }
2963
3087
 
2964
- const code$g = "findCollectionEntities";
2965
- async function handler$g(plugin, ctx, options) {
2966
- await runCollectionEntityActionHandler(ctx, options, code$g, async (entityManager, input) => {
3088
+ const code$h = "findCollectionEntities";
3089
+ async function handler$h(plugin, ctx, options) {
3090
+ await runCollectionEntityActionHandler(ctx, options, code$h, async (entityManager, input) => {
2967
3091
  input.filters = removeFiltersWithNullValue(input.filters);
2968
3092
  const entities = await entityManager.findEntities(input);
2969
3093
  const result = { list: entities };
@@ -2978,13 +3102,13 @@ async function handler$g(plugin, ctx, options) {
2978
3102
 
2979
3103
  var findCollectionEntities = /*#__PURE__*/Object.freeze({
2980
3104
  __proto__: null,
2981
- code: code$g,
2982
- handler: handler$g
3105
+ code: code$h,
3106
+ handler: handler$h
2983
3107
  });
2984
3108
 
2985
- const code$f = "findCollectionEntityById";
2986
- async function handler$f(plugin, ctx, options) {
2987
- console.debug(`Running ${code$f} handler...`);
3109
+ const code$g = "findCollectionEntityById";
3110
+ async function handler$g(plugin, ctx, options) {
3111
+ console.debug(`Running ${code$g} handler...`);
2988
3112
  const { server, input } = ctx;
2989
3113
  const { id } = input;
2990
3114
  const entityManager = server.getEntityManager(options.singularCode);
@@ -2997,13 +3121,13 @@ async function handler$f(plugin, ctx, options) {
2997
3121
 
2998
3122
  var findCollectionEntityById = /*#__PURE__*/Object.freeze({
2999
3123
  __proto__: null,
3000
- code: code$f,
3001
- handler: handler$f
3124
+ code: code$g,
3125
+ handler: handler$g
3002
3126
  });
3003
3127
 
3004
- const code$e = "countCollectionEntities";
3005
- async function handler$e(plugin, ctx, options) {
3006
- await runCollectionEntityActionHandler(ctx, options, code$e, (entityManager, input) => {
3128
+ const code$f = "countCollectionEntities";
3129
+ async function handler$f(plugin, ctx, options) {
3130
+ await runCollectionEntityActionHandler(ctx, options, code$f, (entityManager, input) => {
3007
3131
  input.filters = removeFiltersWithNullValue(input.filters);
3008
3132
  return entityManager.count(input);
3009
3133
  });
@@ -3011,15 +3135,15 @@ async function handler$e(plugin, ctx, options) {
3011
3135
 
3012
3136
  var countCollectionEntities = /*#__PURE__*/Object.freeze({
3013
3137
  __proto__: null,
3014
- code: code$e,
3015
- handler: handler$e
3138
+ code: code$f,
3139
+ handler: handler$f
3016
3140
  });
3017
3141
 
3018
- const code$d = "createCollectionEntity";
3019
- async function handler$d(plugin, ctx, options) {
3142
+ const code$e = "createCollectionEntity";
3143
+ async function handler$e(plugin, ctx, options) {
3020
3144
  const { server, input } = ctx;
3021
3145
  const { defaultInput, fixedInput } = options;
3022
- console.debug(`Running ${code$d} handler...`);
3146
+ console.debug(`Running ${code$e} handler...`);
3023
3147
  console.debug(`defaultInput: ${JSON.stringify(defaultInput)}`);
3024
3148
  const mergedInput = mergeInput(defaultInput, input, fixedInput);
3025
3149
  console.debug(`fixedInput: ${JSON.stringify(fixedInput)}`);
@@ -3031,26 +3155,21 @@ async function handler$d(plugin, ctx, options) {
3031
3155
  const entityManager = server.getEntityManager(options.singularCode);
3032
3156
  const output = await entityManager.createEntity({
3033
3157
  entity: input,
3034
- });
3158
+ }, plugin);
3035
3159
  ctx.output = output;
3036
- server.emitEvent("entity.create", plugin, {
3037
- namespace: options.namespace,
3038
- modelSingularCode: options.singularCode,
3039
- after: output,
3040
- });
3041
3160
  }
3042
3161
 
3043
3162
  var createCollectionEntity = /*#__PURE__*/Object.freeze({
3044
3163
  __proto__: null,
3045
- code: code$d,
3046
- handler: handler$d
3164
+ code: code$e,
3165
+ handler: handler$e
3047
3166
  });
3048
3167
 
3049
- const code$c = "createCollectionEntitiesBatch";
3050
- async function handler$c(plugin, ctx, options) {
3168
+ const code$d = "createCollectionEntitiesBatch";
3169
+ async function handler$d(plugin, ctx, options) {
3051
3170
  const { server, input } = ctx;
3052
3171
  const { defaultInput, fixedInput } = options;
3053
- console.debug(`Running ${code$c} handler...`);
3172
+ console.debug(`Running ${code$d} handler...`);
3054
3173
  const { entities } = input;
3055
3174
  if (!_.isArray(entities)) {
3056
3175
  throw new Error("input.entities should be an array.");
@@ -3068,12 +3187,7 @@ async function handler$c(plugin, ctx, options) {
3068
3187
  const entityManager = server.getEntityManager(options.singularCode);
3069
3188
  const newEntity = await entityManager.createEntity({
3070
3189
  entity: mergedEntity,
3071
- });
3072
- server.emitEvent("entity.create", plugin, {
3073
- namespace: options.namespace,
3074
- modelSingularCode: options.singularCode,
3075
- after: newEntity,
3076
- });
3190
+ }, plugin);
3077
3191
  output.push(newEntity);
3078
3192
  }
3079
3193
  ctx.output = output;
@@ -3081,202 +3195,90 @@ async function handler$c(plugin, ctx, options) {
3081
3195
 
3082
3196
  var createCollectionEntitiesBatch = /*#__PURE__*/Object.freeze({
3083
3197
  __proto__: null,
3084
- code: code$c,
3085
- handler: handler$c
3198
+ code: code$d,
3199
+ handler: handler$d
3086
3200
  });
3087
3201
 
3088
- function getEntityPartChanges(before, after) {
3089
- if (!before) {
3090
- throw new Error("Argument 'before' can not be null.");
3091
- }
3092
- if (!after) {
3093
- throw new Error("Argument 'after' can not be null.");
3094
- }
3095
- let changed = null;
3096
- for (const key in after) {
3097
- if (after[key] != before[key]) {
3098
- if (changed) {
3099
- changed[key] = after[key];
3100
- }
3101
- else {
3102
- changed = { [key]: after[key] };
3103
- }
3104
- }
3105
- }
3106
- return changed;
3107
- }
3108
-
3109
- const code$b = "updateCollectionEntityById";
3110
- async function handler$b(plugin, ctx, options) {
3202
+ const code$c = "updateCollectionEntityById";
3203
+ async function handler$c(plugin, ctx, options) {
3111
3204
  const { server, input } = ctx;
3112
3205
  const { defaultInput, fixedInput } = options;
3113
- console.debug(`Running ${code$b} handler...`);
3206
+ console.debug(`Running ${code$c} handler...`);
3114
3207
  console.debug(`defaultInput: ${JSON.stringify(defaultInput)}`);
3115
3208
  const mergedInput = mergeInput(defaultInput, input, fixedInput);
3116
3209
  console.debug(`fixedInput: ${JSON.stringify(fixedInput)}`);
3117
3210
  console.debug(`mergedInput: ${JSON.stringify(mergedInput)}`);
3118
3211
  const entityManager = server.getEntityManager(options.singularCode);
3119
- const id = mergedInput.id;
3120
- const row = await entityManager.findById(id);
3121
- if (!row) {
3122
- throw new Error(`${options.namespace}.${options.singularCode} with id "${id}" was not found.`);
3123
- }
3124
- const entity = mapDbRowToEntity(entityManager.getModel(), row);
3125
- const changes = getEntityPartChanges(entity, mergedInput);
3126
- if (!changes) {
3127
- ctx.output = entity;
3128
- return;
3129
- }
3130
- const output = await entityManager.updateEntityById({ id, entity, changes });
3212
+ const output = await entityManager.updateEntityById({ id: mergedInput.id, entityToSave: mergedInput }, plugin);
3131
3213
  ctx.output = output;
3132
- server.emitEvent("entity.update", plugin, {
3133
- namespace: options.namespace,
3134
- modelSingularCode: options.singularCode,
3135
- before: entity,
3136
- after: output,
3137
- changes: changes,
3138
- });
3139
3214
  }
3140
3215
 
3141
3216
  var updateCollectionEntityById = /*#__PURE__*/Object.freeze({
3142
3217
  __proto__: null,
3143
- code: code$b,
3144
- handler: handler$b
3218
+ code: code$c,
3219
+ handler: handler$c
3145
3220
  });
3146
3221
 
3147
- const code$a = "deleteCollectionEntityById";
3148
- async function handler$a(plugin, ctx, options) {
3149
- console.debug(`Running ${code$a} handler...`);
3222
+ const code$b = "deleteCollectionEntityById";
3223
+ async function handler$b(plugin, ctx, options) {
3224
+ console.debug(`Running ${code$b} handler...`);
3150
3225
  const { server, input } = ctx;
3151
3226
  const entityManager = server.getEntityManager(options.singularCode);
3152
- const id = input.id;
3153
- const row = await entityManager.findById(id);
3154
- if (!row) {
3155
- ctx.status = 200;
3156
- return;
3157
- }
3158
- await entityManager.deleteById(id);
3159
- const entity = mapDbRowToEntity(entityManager.getModel(), row);
3160
- server.emitEvent("entity.delete", plugin, {
3161
- namespace: options.namespace,
3162
- modelSingularCode: options.singularCode,
3163
- before: entity,
3164
- });
3227
+ await entityManager.deleteById(input.id, plugin);
3165
3228
  ctx.status = 200;
3166
3229
  }
3167
3230
 
3168
3231
  var deleteCollectionEntityById = /*#__PURE__*/Object.freeze({
3169
3232
  __proto__: null,
3170
- code: code$a,
3171
- handler: handler$a
3233
+ code: code$b,
3234
+ handler: handler$b
3172
3235
  });
3173
3236
 
3174
- const code$9 = "addEntityRelations";
3175
- async function handler$9(plugin, ctx, options) {
3237
+ const code$a = "addEntityRelations";
3238
+ async function handler$a(plugin, ctx, options) {
3176
3239
  const { server, input } = ctx;
3177
- const { queryBuilder } = server;
3178
3240
  const { defaultInput, fixedInput } = options;
3179
- console.debug(`Running ${code$9} handler...`);
3241
+ console.debug(`Running ${code$a} handler...`);
3180
3242
  console.debug(`defaultInput: ${JSON.stringify(defaultInput)}`);
3181
3243
  const mergedInput = mergeInput(defaultInput, input, fixedInput);
3182
3244
  console.debug(`fixedInput: ${JSON.stringify(fixedInput)}`);
3183
3245
  console.debug(`mergedInput: ${JSON.stringify(mergedInput)}`);
3184
- const dataAccessor = server.getDataAccessor(options);
3185
- const model = dataAccessor.getModel();
3186
- const { id, property, relations } = mergedInput;
3187
- const row = await dataAccessor.findById(id);
3188
- if (!row) {
3189
- throw new Error(`${options.namespace}.${options.singularCode} with id "${id}" was not found.`);
3190
- }
3191
- const relationProperty = model.properties.find(e => e.code === property);
3192
- if (!relationProperty) {
3193
- throw new Error(`Property '${property}' was not found in ${options.namespace}.${options.singularCode}`);
3194
- }
3195
- if (!(isRelationProperty(relationProperty) && relationProperty.relation === "many")) {
3196
- throw new Error(`Operation 'createEntityRelations' is only supported on property of 'many' relation`);
3197
- }
3198
- if (relationProperty.linkTableName) {
3199
- for (const relation of relations) {
3200
- const command = `INSERT INTO ${queryBuilder.quoteTable({ schema: relationProperty.linkSchema, tableName: relationProperty.linkTableName })} (${queryBuilder.quoteObject(relationProperty.selfIdColumnName)}, ${queryBuilder.quoteObject(relationProperty.targetIdColumnName)})
3201
- SELECT $1, $2 WHERE NOT EXISTS (
3202
- SELECT ${queryBuilder.quoteObject(relationProperty.selfIdColumnName)}, ${queryBuilder.quoteObject(relationProperty.targetIdColumnName)}
3203
- FROM ${queryBuilder.quoteTable({ schema: relationProperty.linkSchema, tableName: relationProperty.linkTableName })}
3204
- WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName)}=$2
3205
- )`;
3206
- const params = [id, relation.id];
3207
- await server.queryDatabaseObject(command, params);
3208
- }
3209
- }
3246
+ const entityManager = server.getEntityManager(options.singularCode);
3247
+ await entityManager.addRelations(mergedInput, plugin);
3210
3248
  ctx.output = {};
3211
- server.emitEvent("entity.addRelations", plugin, {
3212
- namespace: options.namespace,
3213
- modelSingularCode: options.singularCode,
3214
- entity: row,
3215
- property,
3216
- relations: relations,
3217
- });
3218
3249
  }
3219
3250
 
3220
3251
  var addEntityRelations = /*#__PURE__*/Object.freeze({
3221
3252
  __proto__: null,
3222
- code: code$9,
3223
- handler: handler$9
3253
+ code: code$a,
3254
+ handler: handler$a
3224
3255
  });
3225
3256
 
3226
- const code$8 = "removeEntityRelations";
3227
- async function handler$8(plugin, ctx, options) {
3257
+ const code$9 = "removeEntityRelations";
3258
+ async function handler$9(plugin, ctx, options) {
3228
3259
  const { server, input } = ctx;
3229
- const { queryBuilder } = server;
3230
3260
  const { defaultInput, fixedInput } = options;
3231
- console.debug(`Running ${code$8} handler...`);
3261
+ console.debug(`Running ${code$9} handler...`);
3232
3262
  console.debug(`defaultInput: ${JSON.stringify(defaultInput)}`);
3233
3263
  const mergedInput = mergeInput(defaultInput, input, fixedInput);
3234
3264
  console.debug(`fixedInput: ${JSON.stringify(fixedInput)}`);
3235
3265
  console.debug(`mergedInput: ${JSON.stringify(mergedInput)}`);
3236
- const dataAccessor = server.getDataAccessor(options);
3237
- const model = dataAccessor.getModel();
3238
- const { id, property, relations } = mergedInput;
3239
- const row = await dataAccessor.findById(id);
3240
- if (!row) {
3241
- throw new Error(`${options.namespace}.${options.singularCode} with id "${id}" was not found.`);
3242
- }
3243
- console.log(mergedInput);
3244
- const relationProperty = model.properties.find(e => e.code === property);
3245
- if (!relationProperty) {
3246
- throw new Error(`Property '${property}' was not found in ${options.namespace}.${options.singularCode}`);
3247
- }
3248
- if (!(isRelationProperty(relationProperty) && relationProperty.relation === "many")) {
3249
- throw new Error(`Operation 'createEntityRelations' is only supported on property of 'many' relation`);
3250
- }
3251
- if (relationProperty.linkTableName) {
3252
- for (const relation of relations) {
3253
- const command = `DELETE FROM ${queryBuilder.quoteTable({ schema: relationProperty.linkSchema, tableName: relationProperty.linkTableName })}
3254
- WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName)}=$2;`;
3255
- const params = [id, relation.id];
3256
- await server.queryDatabaseObject(command, params);
3257
- }
3258
- }
3266
+ const entityManager = server.getEntityManager(options.singularCode);
3267
+ await entityManager.removeRelations(mergedInput, plugin);
3259
3268
  ctx.output = {};
3260
- server.emitEvent("entity.removeRelations", plugin, {
3261
- namespace: options.namespace,
3262
- modelSingularCode: options.singularCode,
3263
- entity: row,
3264
- property,
3265
- relations: relations,
3266
- });
3267
3269
  }
3268
3270
 
3269
3271
  var removeEntityRelations = /*#__PURE__*/Object.freeze({
3270
3272
  __proto__: null,
3271
- code: code$8,
3272
- handler: handler$8
3273
+ code: code$9,
3274
+ handler: handler$9
3273
3275
  });
3274
3276
 
3275
- const code$7 = "queryDatabase";
3276
- async function handler$7(plugin, ctx, options) {
3277
+ const code$8 = "queryDatabase";
3278
+ async function handler$8(plugin, ctx, options) {
3277
3279
  const { server, input } = ctx;
3278
3280
  const { sql, querySingle, defaultInput, fixedInput } = options;
3279
- console.debug(`Running ${code$7} handler...`);
3281
+ console.debug(`Running ${code$8} handler...`);
3280
3282
  console.debug(`defaultInput: ${JSON.stringify(defaultInput)}`);
3281
3283
  const mergedInput = mergeInput(defaultInput, input, fixedInput);
3282
3284
  console.debug(`fixedInput: ${JSON.stringify(fixedInput)}`);
@@ -3292,8 +3294,8 @@ async function handler$7(plugin, ctx, options) {
3292
3294
 
3293
3295
  var queryDatabase = /*#__PURE__*/Object.freeze({
3294
3296
  __proto__: null,
3295
- code: code$7,
3296
- handler: handler$7
3297
+ code: code$8,
3298
+ handler: handler$8
3297
3299
  });
3298
3300
 
3299
3301
  /**
@@ -3485,16 +3487,16 @@ async function sendSourceResponse(proxyCtx, targetRes) {
3485
3487
  srcRes.body = targetRes.body;
3486
3488
  }
3487
3489
 
3488
- const code$6 = "httpProxy";
3489
- async function handler$6(plugin, ctx, options) {
3490
- console.debug(`Running ${code$6} handler...`);
3490
+ const code$7 = "httpProxy";
3491
+ async function handler$7(plugin, ctx, options) {
3492
+ console.debug(`Running ${code$7} handler...`);
3491
3493
  await doProxy(ctx.routerContext, options);
3492
3494
  }
3493
3495
 
3494
3496
  var httpProxy = /*#__PURE__*/Object.freeze({
3495
3497
  __proto__: null,
3496
- code: code$6,
3497
- handler: handler$6
3498
+ code: code$7,
3499
+ handler: handler$7
3498
3500
  });
3499
3501
 
3500
3502
  /**
@@ -3745,8 +3747,8 @@ class WebhooksPlugin {
3745
3747
  }
3746
3748
  }
3747
3749
 
3748
- const code$5 = "createSession";
3749
- async function handler$5(plugin, ctx, options) {
3750
+ const code$6 = "createSession";
3751
+ async function handler$6(plugin, ctx, options) {
3750
3752
  const { server, input, routerContext } = ctx;
3751
3753
  const { response } = routerContext;
3752
3754
  const { account, password } = input;
@@ -3770,7 +3772,7 @@ async function handler$5(plugin, ctx, options) {
3770
3772
  iss: "authManager",
3771
3773
  sub: "userAccessToken",
3772
3774
  aud: "" + user.id,
3773
- iat: new Date,
3775
+ iat: Math.floor(Date.now() / 1000),
3774
3776
  act: user.login,
3775
3777
  }, secretKey);
3776
3778
  setCookie(response.headers, {
@@ -3785,12 +3787,12 @@ async function handler$5(plugin, ctx, options) {
3785
3787
 
3786
3788
  var createSession = /*#__PURE__*/Object.freeze({
3787
3789
  __proto__: null,
3788
- code: code$5,
3789
- handler: handler$5
3790
+ code: code$6,
3791
+ handler: handler$6
3790
3792
  });
3791
3793
 
3792
- const code$4 = "deleteSession";
3793
- async function handler$4(plugin, ctx, options) {
3794
+ const code$5 = "deleteSession";
3795
+ async function handler$5(plugin, ctx, options) {
3794
3796
  const { server, input, routerContext } = ctx;
3795
3797
  const { response } = routerContext;
3796
3798
  setCookie(response.headers, {
@@ -3803,12 +3805,12 @@ async function handler$4(plugin, ctx, options) {
3803
3805
 
3804
3806
  var deleteSession = /*#__PURE__*/Object.freeze({
3805
3807
  __proto__: null,
3806
- code: code$4,
3807
- handler: handler$4
3808
+ code: code$5,
3809
+ handler: handler$5
3808
3810
  });
3809
3811
 
3810
- const code$3 = "getMyProfile";
3811
- async function handler$3(plugin, ctx, options) {
3812
+ const code$4 = "getMyProfile";
3813
+ async function handler$4(plugin, ctx, options) {
3812
3814
  const { server, input, routerContext } = ctx;
3813
3815
  const userId = routerContext.state.userId;
3814
3816
  if (!userId) {
@@ -3838,11 +3840,11 @@ async function handler$3(plugin, ctx, options) {
3838
3840
 
3839
3841
  var getMyProfile$2 = /*#__PURE__*/Object.freeze({
3840
3842
  __proto__: null,
3841
- code: code$3,
3842
- handler: handler$3
3843
+ code: code$4,
3844
+ handler: handler$4
3843
3845
  });
3844
3846
 
3845
- var pluginActionHandlers = [
3847
+ var pluginActionHandlers$1 = [
3846
3848
  createSession,
3847
3849
  deleteSession,
3848
3850
  getMyProfile$2,
@@ -3979,7 +3981,7 @@ class AuthPlugin {
3979
3981
  async registerMiddlewares(server) {
3980
3982
  }
3981
3983
  async registerActionHandlers(server) {
3982
- for (const actionHandler of pluginActionHandlers) {
3984
+ for (const actionHandler of pluginActionHandlers$1) {
3983
3985
  server.registerActionHandler(this, actionHandler);
3984
3986
  }
3985
3987
  }
@@ -4057,8 +4059,8 @@ async function appendFile(path, data) {
4057
4059
  });
4058
4060
  }
4059
4061
 
4060
- const code$2 = "downloadDocument";
4061
- async function handler$2(plugin, ctx, options) {
4062
+ const code$3 = "downloadDocument";
4063
+ async function handler$3(plugin, ctx, options) {
4062
4064
  const { server, applicationConfig, routerContext, input } = ctx;
4063
4065
  const { request, response } = routerContext;
4064
4066
  const documentDataAccessor = ctx.server.getDataAccessor({
@@ -4086,12 +4088,12 @@ async function handler$2(plugin, ctx, options) {
4086
4088
 
4087
4089
  var downloadDocumentActionHandler = /*#__PURE__*/Object.freeze({
4088
4090
  __proto__: null,
4089
- code: code$2,
4090
- handler: handler$2
4091
+ code: code$3,
4092
+ handler: handler$3
4091
4093
  });
4092
4094
 
4093
- const code$1 = "downloadFile";
4094
- async function handler$1(plugin, ctx, options) {
4095
+ const code$2 = "downloadFile";
4096
+ async function handler$2(plugin, ctx, options) {
4095
4097
  const { server, applicationConfig, routerContext, input } = ctx;
4096
4098
  const { request, response } = routerContext;
4097
4099
  const dataAccessor = ctx.server.getDataAccessor({
@@ -4111,12 +4113,12 @@ async function handler$1(plugin, ctx, options) {
4111
4113
 
4112
4114
  var downloadFileActionHandler = /*#__PURE__*/Object.freeze({
4113
4115
  __proto__: null,
4114
- code: code$1,
4115
- handler: handler$1
4116
+ code: code$2,
4117
+ handler: handler$2
4116
4118
  });
4117
4119
 
4118
- const code = "uploadFile";
4119
- async function handler(plugin, ctx, options) {
4120
+ const code$1 = "uploadFile";
4121
+ async function handler$1(plugin, ctx, options) {
4120
4122
  const { server, applicationConfig, routerContext, input } = ctx;
4121
4123
  let file = input.file || input.files;
4122
4124
  if (_.isArray(file)) {
@@ -4137,8 +4139,8 @@ async function handler(plugin, ctx, options) {
4137
4139
 
4138
4140
  var uploadFileActionHandler = /*#__PURE__*/Object.freeze({
4139
4141
  __proto__: null,
4140
- code: code,
4141
- handler: handler
4142
+ code: code$1,
4143
+ handler: handler$1
4142
4144
  });
4143
4145
 
4144
4146
  var getMyProfile = {
@@ -4239,10 +4241,176 @@ class FileManager {
4239
4241
  }
4240
4242
  }
4241
4243
 
4244
+ const code = "runServerOperation";
4245
+ async function handler(plugin, ctx, options) {
4246
+ const { operation } = options;
4247
+ await operation(ctx);
4248
+ }
4249
+
4250
+ var runServerOperation = /*#__PURE__*/Object.freeze({
4251
+ __proto__: null,
4252
+ code: code,
4253
+ handler: handler
4254
+ });
4255
+
4256
+ var pluginActionHandlers = [
4257
+ runServerOperation,
4258
+ ];
4259
+
4260
+ class ServerOperationPlugin {
4261
+ #operations;
4262
+ constructor(options) {
4263
+ this.#operations = options.operations || [];
4264
+ }
4265
+ get code() {
4266
+ return "serverOperation";
4267
+ }
4268
+ get description() {
4269
+ return "";
4270
+ }
4271
+ get extendingAbilities() {
4272
+ return [];
4273
+ }
4274
+ get configurableTargets() {
4275
+ return [];
4276
+ }
4277
+ get configurations() {
4278
+ return [];
4279
+ }
4280
+ async initPlugin(server) {
4281
+ }
4282
+ async registerMiddlewares(server) {
4283
+ }
4284
+ async registerActionHandlers(server) {
4285
+ for (const actionHandler of pluginActionHandlers) {
4286
+ server.registerActionHandler(this, actionHandler);
4287
+ }
4288
+ }
4289
+ async registerEventHandlers(server) {
4290
+ }
4291
+ async registerMessageHandlers(server) {
4292
+ }
4293
+ async registerTaskProcessors(server) {
4294
+ }
4295
+ async onLoadingApplication(server, applicationConfig) {
4296
+ }
4297
+ async configureModels(server, applicationConfig) {
4298
+ }
4299
+ async configureModelProperties(server, applicationConfig) {
4300
+ }
4301
+ async configureRoutes(server, applicationConfig) {
4302
+ const routes = [];
4303
+ for (const operation of this.#operations) {
4304
+ routes.push({
4305
+ namespace: "app",
4306
+ name: `app.operations.${operation.code}`,
4307
+ code: `app.operations.${operation.code}`,
4308
+ type: "RESTful",
4309
+ method: operation.method,
4310
+ endpoint: `/app/${operation.code}`,
4311
+ actions: [
4312
+ {
4313
+ code: "runServerOperation",
4314
+ config: {
4315
+ operation: operation.handler,
4316
+ }
4317
+ },
4318
+ ],
4319
+ });
4320
+ }
4321
+ server.appendApplicationConfig({ routes });
4322
+ }
4323
+ async onApplicationLoaded(server, applicationConfig) {
4324
+ }
4325
+ async onApplicationReady(server, applicationConfig) {
4326
+ }
4327
+ }
4328
+
4329
+ class EntityWatchPlugin {
4330
+ #createEventEmitters;
4331
+ #updateEventEmitters;
4332
+ #deleteEventEmitters;
4333
+ #addRelationsEventEmitters;
4334
+ #removeRelationsEventEmitters;
4335
+ constructor(options) {
4336
+ const { watchers } = options;
4337
+ this.#createEventEmitters = new EventManager();
4338
+ this.#updateEventEmitters = new EventManager();
4339
+ this.#deleteEventEmitters = new EventManager();
4340
+ this.#addRelationsEventEmitters = new EventManager();
4341
+ this.#removeRelationsEventEmitters = new EventManager();
4342
+ for (const watcher of watchers) {
4343
+ if (watcher.eventName === "entity.create") {
4344
+ this.#createEventEmitters.on(watcher.modelSingularCode, watcher.handler);
4345
+ }
4346
+ else if (watcher.eventName === "entity.update") {
4347
+ this.#updateEventEmitters.on(watcher.modelSingularCode, watcher.handler);
4348
+ }
4349
+ else if (watcher.eventName === "entity.delete") {
4350
+ this.#deleteEventEmitters.on(watcher.modelSingularCode, watcher.handler);
4351
+ }
4352
+ else if (watcher.eventName === "entity.addRelations") {
4353
+ this.#addRelationsEventEmitters.on(watcher.modelSingularCode, watcher.handler);
4354
+ }
4355
+ else if (watcher.eventName === "entity.removeRelations") {
4356
+ this.#removeRelationsEventEmitters.on(watcher.modelSingularCode, watcher.handler);
4357
+ }
4358
+ }
4359
+ }
4360
+ get code() {
4361
+ return "entityWatch";
4362
+ }
4363
+ get description() {
4364
+ return "";
4365
+ }
4366
+ get extendingAbilities() {
4367
+ return [];
4368
+ }
4369
+ get configurableTargets() {
4370
+ return [];
4371
+ }
4372
+ get configurations() {
4373
+ return [];
4374
+ }
4375
+ async registerEventHandlers(server) {
4376
+ server.registerEventHandler("entity.create", this.handleEntityEvent.bind(this, server, "entity.create"));
4377
+ server.registerEventHandler("entity.update", this.handleEntityEvent.bind(this, server, "entity.update"));
4378
+ server.registerEventHandler("entity.delete", this.handleEntityEvent.bind(this, server, "entity.delete"));
4379
+ server.registerEventHandler("entity.addRelations", this.handleEntityEvent.bind(this, server, "entity.addRelations"));
4380
+ server.registerEventHandler("entity.removeRelations", this.handleEntityEvent.bind(this, server, "entity.removeRelations"));
4381
+ }
4382
+ handleEntityEvent(server, eventName, sender, payload) {
4383
+ if (sender === this) {
4384
+ return;
4385
+ }
4386
+ const { modelSingularCode } = payload;
4387
+ const entityWatchHandlerContext = {
4388
+ server,
4389
+ payload,
4390
+ };
4391
+ if (eventName === "entity.create") {
4392
+ this.#createEventEmitters.emit(modelSingularCode, entityWatchHandlerContext);
4393
+ }
4394
+ else if (eventName === "entity.update") {
4395
+ this.#updateEventEmitters.emit(modelSingularCode, entityWatchHandlerContext);
4396
+ }
4397
+ else if (eventName === "entity.delete") {
4398
+ this.#deleteEventEmitters.emit(modelSingularCode, entityWatchHandlerContext);
4399
+ }
4400
+ else if (eventName === "entity.addRelations") {
4401
+ this.#addRelationsEventEmitters.emit(modelSingularCode, entityWatchHandlerContext);
4402
+ }
4403
+ else if (eventName === "entity.removeRelations") {
4404
+ this.#removeRelationsEventEmitters.emit(modelSingularCode, entityWatchHandlerContext);
4405
+ }
4406
+ }
4407
+ }
4408
+
4242
4409
  fixBigIntJSONSerialize();
4243
4410
 
4244
4411
  exports.AuthPlugin = AuthPlugin;
4245
4412
  exports.DataManagePlugin = DataManager;
4413
+ exports.EntityWatchPlugin = EntityWatchPlugin;
4246
4414
  exports.FileManagePlugin = FileManager;
4247
4415
  exports.GlobalRequest = GlobalRequest;
4248
4416
  exports.MetaManagePlugin = MetaManager;
@@ -4250,6 +4418,7 @@ exports.RapidRequest = RapidRequest;
4250
4418
  exports.RapidServer = RapidServer;
4251
4419
  exports.RouteContext = RouteContext;
4252
4420
  exports.RouteManagePlugin = RouteManager;
4421
+ exports.ServerOperationPlugin = ServerOperationPlugin;
4253
4422
  exports.WebhooksPlugin = WebhooksPlugin;
4254
4423
  exports.bootstrapApplicationConfig = bootstrapApplicationConfig$1;
4255
4424
  exports.createJwt = createJwt;