@ruiapp/rapid-core 0.9.5 → 0.9.7

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.
@@ -0,0 +1,12 @@
1
+ import { ActionHandlerContext } from "../actionHandler";
2
+ declare const _default: {
3
+ namespace: string;
4
+ name: string;
5
+ code: string;
6
+ type: "RESTful";
7
+ method: "GET";
8
+ endpoint: string;
9
+ handler: typeof handler;
10
+ };
11
+ export default _default;
12
+ export declare function handler(ctx: ActionHandlerContext): Promise<void>;
@@ -0,0 +1,10 @@
1
+ declare const _default: {
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "GET";
7
+ endpoint: string;
8
+ handler: typeof import("./healthz").handler;
9
+ }[];
10
+ export default _default;
package/dist/index.js CHANGED
@@ -1032,18 +1032,38 @@ async function buildRoutes(server, applicationConfig) {
1032
1032
  input,
1033
1033
  };
1034
1034
  await server.beforeRunRouteActions(handlerContext);
1035
- for (const actionConfig of routeConfig.actions) {
1036
- const actionCode = actionConfig.code;
1037
- const handler = server.getActionHandlerByCode(actionCode);
1038
- if (!handler) {
1039
- throw new Error("Unknown handler: " + actionCode);
1035
+ let handler = routeConfig.handler;
1036
+ if (handler) {
1037
+ if (lodash.isString(handler)) {
1038
+ handler = new Function(`return (${routeConfig.handler})`);
1040
1039
  }
1041
- await server.beforeRunActionHandler(handlerContext, actionConfig);
1042
- const result = handler(handlerContext, actionConfig.config);
1043
- if (result instanceof Promise) {
1044
- await result;
1040
+ if (lodash.isFunction(handler)) {
1041
+ const result = handler(handlerContext);
1042
+ if (result instanceof Promise) {
1043
+ await result;
1044
+ }
1045
+ }
1046
+ else {
1047
+ throw new Error(`Invalid handler for route ${routeConfig.code}: ${routeConfig.handler}`);
1048
+ }
1049
+ }
1050
+ else if (routeConfig.actions) {
1051
+ for (const actionConfig of routeConfig.actions) {
1052
+ const actionCode = actionConfig.code;
1053
+ const handler = server.getActionHandlerByCode(actionCode);
1054
+ if (!handler) {
1055
+ throw new Error("Unknown handler: " + actionCode);
1056
+ }
1057
+ await server.beforeRunActionHandler(handlerContext, actionConfig);
1058
+ const result = handler(handlerContext, actionConfig.config);
1059
+ if (result instanceof Promise) {
1060
+ await result;
1061
+ }
1045
1062
  }
1046
1063
  }
1064
+ else {
1065
+ throw new Error(`No handler or actions defined for route ${routeConfig.code}`);
1066
+ }
1047
1067
  if (!isNullOrUndefined(handlerContext.output)) {
1048
1068
  routerContext.json(handlerContext.output, handlerContext.status);
1049
1069
  }
@@ -3963,6 +3983,21 @@ class EntityManager {
3963
3983
  }
3964
3984
  }
3965
3985
 
3986
+ var healthz = {
3987
+ namespace: "sys",
3988
+ name: "sys.healthz",
3989
+ code: "sys.healthz",
3990
+ type: "RESTful",
3991
+ method: "GET",
3992
+ endpoint: "/healthz",
3993
+ handler: handler$x,
3994
+ };
3995
+ async function handler$x(ctx) {
3996
+ ctx.output = {};
3997
+ }
3998
+
3999
+ var coreRoutes = [healthz];
4000
+
3966
4001
  class RapidServer {
3967
4002
  #logger;
3968
4003
  #facilityFactories;
@@ -4237,7 +4272,12 @@ class RapidServer {
4237
4272
  this.#entityBeforeResponseEventEmitters.on(entityWatcher.modelSingularCode, entityWatcher.handler);
4238
4273
  }
4239
4274
  }
4275
+ this.#applicationConfig = lodash.cloneDeep(this.#bootstrapApplicationConfig);
4276
+ this.appendApplicationConfig({
4277
+ routes: coreRoutes,
4278
+ });
4240
4279
  await this.configureApplication();
4280
+ this.#buildedRoutes = await buildRoutes(this, this.#applicationConfig);
4241
4281
  if (!this.#disableCronJobs) {
4242
4282
  await pluginManager.registerCronJobs();
4243
4283
  }
@@ -4245,7 +4285,6 @@ class RapidServer {
4245
4285
  await pluginManager.onApplicationReady(this.#applicationConfig);
4246
4286
  }
4247
4287
  async configureApplication() {
4248
- this.#applicationConfig = lodash.cloneDeep(this.#bootstrapApplicationConfig);
4249
4288
  const pluginManager = this.#pluginManager;
4250
4289
  await pluginManager.onLoadingApplication(this.#applicationConfig);
4251
4290
  await pluginManager.configureModels(this.#applicationConfig);
@@ -4254,7 +4293,6 @@ class RapidServer {
4254
4293
  await pluginManager.configureRoutes(this.#applicationConfig);
4255
4294
  // TODO: check application configuration.
4256
4295
  await pluginManager.onApplicationLoaded(this.#applicationConfig);
4257
- this.#buildedRoutes = await buildRoutes(this, this.#applicationConfig);
4258
4296
  }
4259
4297
  registerFacilityFactory(factory) {
4260
4298
  this.#facilityFactories.set(factory.name, factory);
@@ -5066,7 +5104,7 @@ async function generatePasswordHash(password, salt) {
5066
5104
  * @returns
5067
5105
  */
5068
5106
  async function validatePassword(password, passwordHash) {
5069
- const isMatch = await bcrypt__default["default"].compare(password, passwordHash);
5107
+ const isMatch = await bcrypt__default["default"].compare(password || "", passwordHash || "");
5070
5108
  return isMatch;
5071
5109
  }
5072
5110
 
@@ -5174,32 +5212,32 @@ class CacheFactory {
5174
5212
  }
5175
5213
  }
5176
5214
 
5177
- const code$v = "listMetaModels";
5178
- async function handler$v(plugin, ctx, options) {
5215
+ const code$w = "listMetaModels";
5216
+ async function handler$w(plugin, ctx, options) {
5179
5217
  const { applicationConfig } = ctx;
5180
5218
  ctx.output = { list: applicationConfig.models };
5181
5219
  }
5182
5220
 
5183
5221
  var listMetaModels = /*#__PURE__*/Object.freeze({
5184
5222
  __proto__: null,
5185
- code: code$v,
5186
- handler: handler$v
5223
+ code: code$w,
5224
+ handler: handler$w
5187
5225
  });
5188
5226
 
5189
- const code$u = "listMetaRoutes";
5190
- async function handler$u(plugin, ctx, options) {
5227
+ const code$v = "listMetaRoutes";
5228
+ async function handler$v(plugin, ctx, options) {
5191
5229
  const { applicationConfig } = ctx;
5192
5230
  ctx.output = { list: applicationConfig.routes };
5193
5231
  }
5194
5232
 
5195
5233
  var listMetaRoutes = /*#__PURE__*/Object.freeze({
5196
5234
  __proto__: null,
5197
- code: code$u,
5198
- handler: handler$u
5235
+ code: code$v,
5236
+ handler: handler$v
5199
5237
  });
5200
5238
 
5201
- const code$t = "getMetaModelDetail";
5202
- async function handler$t(plugin, ctx, options) {
5239
+ const code$u = "getMetaModelDetail";
5240
+ async function handler$u(plugin, ctx, options) {
5203
5241
  const { server, input } = ctx;
5204
5242
  const model = server.getModel(input);
5205
5243
  ctx.output = model;
@@ -5207,8 +5245,8 @@ async function handler$t(plugin, ctx, options) {
5207
5245
 
5208
5246
  var getMetaModelDetail = /*#__PURE__*/Object.freeze({
5209
5247
  __proto__: null,
5210
- code: code$t,
5211
- handler: handler$t
5248
+ code: code$u,
5249
+ handler: handler$u
5212
5250
  });
5213
5251
 
5214
5252
  function removeFiltersWithNullValue(filters) {
@@ -5797,9 +5835,9 @@ async function runCollectionEntityActionHandler(ctx, options, code, autoMergeInp
5797
5835
  }
5798
5836
  }
5799
5837
 
5800
- const code$s = "findCollectionEntities";
5801
- async function handler$s(plugin, ctx, options) {
5802
- await runCollectionEntityActionHandler(ctx, options, code$s, true, false, async (entityManager, input) => {
5838
+ const code$t = "findCollectionEntities";
5839
+ async function handler$t(plugin, ctx, options) {
5840
+ await runCollectionEntityActionHandler(ctx, options, code$t, true, false, async (entityManager, input) => {
5803
5841
  const { routerContext: routeContext } = ctx;
5804
5842
  input.filters = removeFiltersWithNullValue(input.filters);
5805
5843
  input.routeContext = routeContext;
@@ -5816,13 +5854,13 @@ async function handler$s(plugin, ctx, options) {
5816
5854
 
5817
5855
  var findCollectionEntities = /*#__PURE__*/Object.freeze({
5818
5856
  __proto__: null,
5819
- code: code$s,
5820
- handler: handler$s
5857
+ code: code$t,
5858
+ handler: handler$t
5821
5859
  });
5822
5860
 
5823
- const code$r = "findCollectionEntityById";
5824
- async function handler$r(plugin, ctx, options) {
5825
- await runCollectionEntityActionHandler(ctx, options, code$r, true, true, async (entityManager, input) => {
5861
+ const code$s = "findCollectionEntityById";
5862
+ async function handler$s(plugin, ctx, options) {
5863
+ await runCollectionEntityActionHandler(ctx, options, code$s, true, true, async (entityManager, input) => {
5826
5864
  const { routerContext: routeContext } = ctx;
5827
5865
  const { id } = input;
5828
5866
  const entity = await entityManager.findById({
@@ -5844,13 +5882,13 @@ async function handler$r(plugin, ctx, options) {
5844
5882
 
5845
5883
  var findCollectionEntityById = /*#__PURE__*/Object.freeze({
5846
5884
  __proto__: null,
5847
- code: code$r,
5848
- handler: handler$r
5885
+ code: code$s,
5886
+ handler: handler$s
5849
5887
  });
5850
5888
 
5851
- const code$q = "countCollectionEntities";
5852
- async function handler$q(plugin, ctx, options) {
5853
- await runCollectionEntityActionHandler(ctx, options, code$q, true, false, async (entityManager, input) => {
5889
+ const code$r = "countCollectionEntities";
5890
+ async function handler$r(plugin, ctx, options) {
5891
+ await runCollectionEntityActionHandler(ctx, options, code$r, true, false, async (entityManager, input) => {
5854
5892
  const { routerContext: routeContext } = ctx;
5855
5893
  input.filters = removeFiltersWithNullValue(input.filters);
5856
5894
  input.routeContext = routeContext;
@@ -5861,13 +5899,13 @@ async function handler$q(plugin, ctx, options) {
5861
5899
 
5862
5900
  var countCollectionEntities = /*#__PURE__*/Object.freeze({
5863
5901
  __proto__: null,
5864
- code: code$q,
5865
- handler: handler$q
5902
+ code: code$r,
5903
+ handler: handler$r
5866
5904
  });
5867
5905
 
5868
- const code$p = "createCollectionEntity";
5869
- async function handler$p(plugin, ctx, options) {
5870
- await runCollectionEntityActionHandler(ctx, options, code$p, true, true, async (entityManager, input) => {
5906
+ const code$q = "createCollectionEntity";
5907
+ async function handler$q(plugin, ctx, options) {
5908
+ await runCollectionEntityActionHandler(ctx, options, code$q, true, true, async (entityManager, input) => {
5871
5909
  const { routerContext: routeContext } = ctx;
5872
5910
  const output = await entityManager.createEntity({
5873
5911
  entity: input,
@@ -5879,16 +5917,16 @@ async function handler$p(plugin, ctx, options) {
5879
5917
 
5880
5918
  var createCollectionEntity = /*#__PURE__*/Object.freeze({
5881
5919
  __proto__: null,
5882
- code: code$p,
5883
- handler: handler$p
5920
+ code: code$q,
5921
+ handler: handler$q
5884
5922
  });
5885
5923
 
5886
- const code$o = "createCollectionEntitiesBatch";
5887
- async function handler$o(plugin, ctx, options) {
5924
+ const code$p = "createCollectionEntitiesBatch";
5925
+ async function handler$p(plugin, ctx, options) {
5888
5926
  const { input } = ctx;
5889
5927
  const { noTransaction } = input;
5890
5928
  const { defaultInput, fixedInput } = options;
5891
- await runCollectionEntityActionHandler(ctx, options, code$o, false, !noTransaction, async (entityManager, input) => {
5929
+ await runCollectionEntityActionHandler(ctx, options, code$p, false, !noTransaction, async (entityManager, input) => {
5892
5930
  const { routerContext: routeContext } = ctx;
5893
5931
  const { entities } = input;
5894
5932
  if (!lodash.isArray(entities)) {
@@ -5926,13 +5964,13 @@ async function createEntities(options) {
5926
5964
 
5927
5965
  var createCollectionEntitiesBatch = /*#__PURE__*/Object.freeze({
5928
5966
  __proto__: null,
5929
- code: code$o,
5930
- handler: handler$o
5967
+ code: code$p,
5968
+ handler: handler$p
5931
5969
  });
5932
5970
 
5933
- const code$n = "updateCollectionEntityById";
5934
- async function handler$n(plugin, ctx, options) {
5935
- await runCollectionEntityActionHandler(ctx, options, code$n, true, true, async (entityManager, input) => {
5971
+ const code$o = "updateCollectionEntityById";
5972
+ async function handler$o(plugin, ctx, options) {
5973
+ await runCollectionEntityActionHandler(ctx, options, code$o, true, true, async (entityManager, input) => {
5936
5974
  const { routerContext: routeContext } = ctx;
5937
5975
  const operation = input.$operation;
5938
5976
  if (operation) {
@@ -5961,15 +5999,15 @@ async function handler$n(plugin, ctx, options) {
5961
5999
 
5962
6000
  var updateCollectionEntityById = /*#__PURE__*/Object.freeze({
5963
6001
  __proto__: null,
5964
- code: code$n,
5965
- handler: handler$n
6002
+ code: code$o,
6003
+ handler: handler$o
5966
6004
  });
5967
6005
 
5968
- const code$m = "deleteCollectionEntities";
5969
- async function handler$m(plugin, ctx, options) {
6006
+ const code$n = "deleteCollectionEntities";
6007
+ async function handler$n(plugin, ctx, options) {
5970
6008
  const { input } = ctx;
5971
6009
  const { noTransaction } = input;
5972
- await runCollectionEntityActionHandler(ctx, options, code$m, true, !noTransaction, async (entityManager, input) => {
6010
+ await runCollectionEntityActionHandler(ctx, options, code$n, true, !noTransaction, async (entityManager, input) => {
5973
6011
  const { routerContext: routeContext } = ctx;
5974
6012
  const { filters } = input;
5975
6013
  if (!filters || !filters.length) {
@@ -5991,13 +6029,13 @@ async function handler$m(plugin, ctx, options) {
5991
6029
 
5992
6030
  var deleteCollectionEntities = /*#__PURE__*/Object.freeze({
5993
6031
  __proto__: null,
5994
- code: code$m,
5995
- handler: handler$m
6032
+ code: code$n,
6033
+ handler: handler$n
5996
6034
  });
5997
6035
 
5998
- const code$l = "deleteCollectionEntityById";
5999
- async function handler$l(plugin, ctx, options) {
6000
- await runCollectionEntityActionHandler(ctx, options, code$l, true, true, async (entityManager, input) => {
6036
+ const code$m = "deleteCollectionEntityById";
6037
+ async function handler$m(plugin, ctx, options) {
6038
+ await runCollectionEntityActionHandler(ctx, options, code$m, true, true, async (entityManager, input) => {
6001
6039
  const { routerContext: routeContext } = ctx;
6002
6040
  await entityManager.deleteById({
6003
6041
  id: input.id,
@@ -6009,13 +6047,13 @@ async function handler$l(plugin, ctx, options) {
6009
6047
 
6010
6048
  var deleteCollectionEntityById = /*#__PURE__*/Object.freeze({
6011
6049
  __proto__: null,
6012
- code: code$l,
6013
- handler: handler$l
6050
+ code: code$m,
6051
+ handler: handler$m
6014
6052
  });
6015
6053
 
6016
- const code$k = "addEntityRelations";
6017
- async function handler$k(plugin, ctx, options) {
6018
- await runCollectionEntityActionHandler(ctx, options, code$k, true, true, async (entityManager, input) => {
6054
+ const code$l = "addEntityRelations";
6055
+ async function handler$l(plugin, ctx, options) {
6056
+ await runCollectionEntityActionHandler(ctx, options, code$l, true, true, async (entityManager, input) => {
6019
6057
  const { routerContext: routeContext } = ctx;
6020
6058
  input.routeContext = routeContext;
6021
6059
  await entityManager.addRelations(input, plugin);
@@ -6025,13 +6063,13 @@ async function handler$k(plugin, ctx, options) {
6025
6063
 
6026
6064
  var addEntityRelations = /*#__PURE__*/Object.freeze({
6027
6065
  __proto__: null,
6028
- code: code$k,
6029
- handler: handler$k
6066
+ code: code$l,
6067
+ handler: handler$l
6030
6068
  });
6031
6069
 
6032
- const code$j = "removeEntityRelations";
6033
- async function handler$j(plugin, ctx, options) {
6034
- await runCollectionEntityActionHandler(ctx, options, code$j, true, true, async (entityManager, input) => {
6070
+ const code$k = "removeEntityRelations";
6071
+ async function handler$k(plugin, ctx, options) {
6072
+ await runCollectionEntityActionHandler(ctx, options, code$k, true, true, async (entityManager, input) => {
6035
6073
  const { routerContext: routeContext } = ctx;
6036
6074
  input.routeContext = routeContext;
6037
6075
  await entityManager.removeRelations(input, plugin);
@@ -6041,16 +6079,16 @@ async function handler$j(plugin, ctx, options) {
6041
6079
 
6042
6080
  var removeEntityRelations = /*#__PURE__*/Object.freeze({
6043
6081
  __proto__: null,
6044
- code: code$j,
6045
- handler: handler$j
6082
+ code: code$k,
6083
+ handler: handler$k
6046
6084
  });
6047
6085
 
6048
- const code$i = "queryDatabase";
6049
- async function handler$i(plugin, ctx, options) {
6086
+ const code$j = "queryDatabase";
6087
+ async function handler$j(plugin, ctx, options) {
6050
6088
  const { logger, server, input } = ctx;
6051
6089
  const { sql, querySingle, defaultInput, fixedInput } = options;
6052
6090
  const mergedInput = mergeInput(defaultInput, input, fixedInput);
6053
- logger.debug(`Running ${code$i} handler...`, { defaultInput, fixedInput, mergedInput });
6091
+ logger.debug(`Running ${code$j} handler...`, { defaultInput, fixedInput, mergedInput });
6054
6092
  const result = await server.queryDatabaseObject(sql, mergedInput);
6055
6093
  if (querySingle) {
6056
6094
  ctx.output = lodash.first(result);
@@ -6062,8 +6100,8 @@ async function handler$i(plugin, ctx, options) {
6062
6100
 
6063
6101
  var queryDatabase = /*#__PURE__*/Object.freeze({
6064
6102
  __proto__: null,
6065
- code: code$i,
6066
- handler: handler$i
6103
+ code: code$j,
6104
+ handler: handler$j
6067
6105
  });
6068
6106
 
6069
6107
  /**
@@ -6241,21 +6279,21 @@ async function sendSourceResponse(proxyCtx, targetRes) {
6241
6279
  srcRes.body = targetRes.body;
6242
6280
  }
6243
6281
 
6244
- const code$h = "httpProxy";
6245
- async function handler$h(plugin, ctx, options) {
6282
+ const code$i = "httpProxy";
6283
+ async function handler$i(plugin, ctx, options) {
6246
6284
  const { logger } = ctx;
6247
- logger.debug(`Running ${code$h} handler...`);
6285
+ logger.debug(`Running ${code$i} handler...`);
6248
6286
  await doProxy(ctx.routerContext, options);
6249
6287
  }
6250
6288
 
6251
6289
  var httpProxyActionHandler = /*#__PURE__*/Object.freeze({
6252
6290
  __proto__: null,
6253
- code: code$h,
6254
- handler: handler$h
6291
+ code: code$i,
6292
+ handler: handler$i
6255
6293
  });
6256
6294
 
6257
- const code$g = "mock";
6258
- async function handler$g(plugin, ctx, options) {
6295
+ const code$h = "mock";
6296
+ async function handler$h(plugin, ctx, options) {
6259
6297
  const { logger, routerContext } = ctx;
6260
6298
  const { response } = routerContext;
6261
6299
  const { responseTime, responseStatus, responseHeaders, responseBody } = options;
@@ -6274,8 +6312,8 @@ function waitMilliseconds(ms) {
6274
6312
 
6275
6313
  var mockActionHandler = /*#__PURE__*/Object.freeze({
6276
6314
  __proto__: null,
6277
- code: code$g,
6278
- handler: handler$g
6315
+ code: code$h,
6316
+ handler: handler$h
6279
6317
  });
6280
6318
 
6281
6319
  /**
@@ -6323,8 +6361,8 @@ class RouteManager {
6323
6361
  }
6324
6362
  }
6325
6363
 
6326
- const code$f = "generateSn";
6327
- async function handler$f(plugin, ctx, options) {
6364
+ const code$g = "generateSn";
6365
+ async function handler$g(plugin, ctx, options) {
6328
6366
  const { server, routerContext: routeContext } = ctx;
6329
6367
  const input = ctx.input;
6330
6368
  if (options?.ruleCode) {
@@ -6342,8 +6380,8 @@ async function handler$f(plugin, ctx, options) {
6342
6380
 
6343
6381
  var generateSn$1 = /*#__PURE__*/Object.freeze({
6344
6382
  __proto__: null,
6345
- code: code$f,
6346
- handler: handler$f
6383
+ code: code$g,
6384
+ handler: handler$g
6347
6385
  });
6348
6386
 
6349
6387
  var pluginActionHandlers$8 = [generateSn$1];
@@ -6923,8 +6961,8 @@ class WebhooksPlugin {
6923
6961
  }
6924
6962
  }
6925
6963
 
6926
- const code$e = "changePassword";
6927
- async function handler$e(plugin, ctx, options) {
6964
+ const code$f = "changePassword";
6965
+ async function handler$f(plugin, ctx, options) {
6928
6966
  const { server, input, routerContext: routeContext } = ctx;
6929
6967
  const { id, oldPassword, newPassword } = input;
6930
6968
  const userId = routeContext.state.userId;
@@ -6966,12 +7004,12 @@ async function handler$e(plugin, ctx, options) {
6966
7004
 
6967
7005
  var changePassword$1 = /*#__PURE__*/Object.freeze({
6968
7006
  __proto__: null,
6969
- code: code$e,
6970
- handler: handler$e
7007
+ code: code$f,
7008
+ handler: handler$f
6971
7009
  });
6972
7010
 
6973
- const code$d = "createSession";
6974
- async function handler$d(plugin, ctx, options) {
7011
+ const code$e = "createSession";
7012
+ async function handler$e(plugin, ctx, options) {
6975
7013
  const { server, input, routerContext: routeContext, logger } = ctx;
6976
7014
  const { response } = routeContext;
6977
7015
  const { account, password } = input;
@@ -7021,12 +7059,12 @@ async function handler$d(plugin, ctx, options) {
7021
7059
 
7022
7060
  var createSession = /*#__PURE__*/Object.freeze({
7023
7061
  __proto__: null,
7024
- code: code$d,
7025
- handler: handler$d
7062
+ code: code$e,
7063
+ handler: handler$e
7026
7064
  });
7027
7065
 
7028
- const code$c = "deleteSession";
7029
- async function handler$c(plugin, ctx, options) {
7066
+ const code$d = "deleteSession";
7067
+ async function handler$d(plugin, ctx, options) {
7030
7068
  const { server, input, routerContext } = ctx;
7031
7069
  const { response } = routerContext;
7032
7070
  setCookie(response.headers, {
@@ -7039,12 +7077,12 @@ async function handler$c(plugin, ctx, options) {
7039
7077
 
7040
7078
  var deleteSession = /*#__PURE__*/Object.freeze({
7041
7079
  __proto__: null,
7042
- code: code$c,
7043
- handler: handler$c
7080
+ code: code$d,
7081
+ handler: handler$d
7044
7082
  });
7045
7083
 
7046
- const code$b = "getMyProfile";
7047
- async function handler$b(plugin, ctx, options) {
7084
+ const code$c = "getMyProfile";
7085
+ async function handler$c(plugin, ctx, options) {
7048
7086
  const { server, input, routerContext } = ctx;
7049
7087
  const userId = routerContext.state.userId;
7050
7088
  if (!userId) {
@@ -7076,12 +7114,12 @@ async function handler$b(plugin, ctx, options) {
7076
7114
 
7077
7115
  var getMyProfile$2 = /*#__PURE__*/Object.freeze({
7078
7116
  __proto__: null,
7079
- code: code$b,
7080
- handler: handler$b
7117
+ code: code$c,
7118
+ handler: handler$c
7081
7119
  });
7082
7120
 
7083
- const code$a = "resetPassword";
7084
- async function handler$a(plugin, ctx, options) {
7121
+ const code$b = "resetPassword";
7122
+ async function handler$b(plugin, ctx, options) {
7085
7123
  const { server, input, routerContext: routeContext } = ctx;
7086
7124
  const { userId, password } = input;
7087
7125
  const userEntitySingularCode = plugin.options?.userEntitySingularCode || "oc_user";
@@ -7109,8 +7147,8 @@ async function handler$a(plugin, ctx, options) {
7109
7147
 
7110
7148
  var resetPassword$1 = /*#__PURE__*/Object.freeze({
7111
7149
  __proto__: null,
7112
- code: code$a,
7113
- handler: handler$a
7150
+ code: code$b,
7151
+ handler: handler$b
7114
7152
  });
7115
7153
 
7116
7154
  var pluginActionHandlers$7 = [changePassword$1, createSession, deleteSession, getMyProfile$2, resetPassword$1];
@@ -7365,8 +7403,8 @@ function getFileBaseName(pathname) {
7365
7403
  return path__default["default"].basename(pathname, extName);
7366
7404
  }
7367
7405
 
7368
- const code$9 = "downloadDocument";
7369
- async function handler$9(plugin, ctx, options) {
7406
+ const code$a = "downloadDocument";
7407
+ async function handler$a(plugin, ctx, options) {
7370
7408
  const { server, applicationConfig, routerContext: routeContext, input } = ctx;
7371
7409
  const { request, response } = routeContext;
7372
7410
  const documentDataAccessor = ctx.server.getDataAccessor({
@@ -7422,12 +7460,12 @@ async function handler$9(plugin, ctx, options) {
7422
7460
 
7423
7461
  var downloadDocumentActionHandler = /*#__PURE__*/Object.freeze({
7424
7462
  __proto__: null,
7425
- code: code$9,
7426
- handler: handler$9
7463
+ code: code$a,
7464
+ handler: handler$a
7427
7465
  });
7428
7466
 
7429
- const code$8 = "downloadFile";
7430
- async function handler$8(plugin, ctx, options) {
7467
+ const code$9 = "downloadFile";
7468
+ async function handler$9(plugin, ctx, options) {
7431
7469
  const { server, applicationConfig, routerContext: routeContext } = ctx;
7432
7470
  const { request, response } = routeContext;
7433
7471
  //TODO: only public files can download by this handler
@@ -7453,12 +7491,12 @@ async function handler$8(plugin, ctx, options) {
7453
7491
 
7454
7492
  var downloadFileActionHandler = /*#__PURE__*/Object.freeze({
7455
7493
  __proto__: null,
7456
- code: code$8,
7457
- handler: handler$8
7494
+ code: code$9,
7495
+ handler: handler$9
7458
7496
  });
7459
7497
 
7460
- const code$7 = "uploadFile";
7461
- async function handler$7(plugin, ctx, options) {
7498
+ const code$8 = "uploadFile";
7499
+ async function handler$8(plugin, ctx, options) {
7462
7500
  const { server, applicationConfig, routerContext, input } = ctx;
7463
7501
  let file = input.file || input.files;
7464
7502
  if (lodash.isArray(file)) {
@@ -7479,8 +7517,8 @@ async function handler$7(plugin, ctx, options) {
7479
7517
 
7480
7518
  var uploadFileActionHandler = /*#__PURE__*/Object.freeze({
7481
7519
  __proto__: null,
7482
- code: code$7,
7483
- handler: handler$7
7520
+ code: code$8,
7521
+ handler: handler$8
7484
7522
  });
7485
7523
 
7486
7524
  var getMyProfile = {
@@ -7556,8 +7594,8 @@ class FileManager {
7556
7594
  }
7557
7595
  }
7558
7596
 
7559
- const code$6 = "getLicense";
7560
- async function handler$6(plugin, ctx, options) {
7597
+ const code$7 = "getLicense";
7598
+ async function handler$7(plugin, ctx, options) {
7561
7599
  const { server, routerContext } = ctx;
7562
7600
  const licenseService = server.getService("licenseService");
7563
7601
  const license = licenseService.getLicense();
@@ -7565,12 +7603,27 @@ async function handler$6(plugin, ctx, options) {
7565
7603
  }
7566
7604
 
7567
7605
  var getLicense$1 = /*#__PURE__*/Object.freeze({
7606
+ __proto__: null,
7607
+ code: code$7,
7608
+ handler: handler$7
7609
+ });
7610
+
7611
+ const code$6 = "updateLicense";
7612
+ async function handler$6(plugin, ctx, options) {
7613
+ const { server, routerContext } = ctx;
7614
+ const input = ctx.input;
7615
+ const licenseService = server.getService("licenseService");
7616
+ const license = await licenseService.updateLicense(input.certText);
7617
+ ctx.output = license;
7618
+ }
7619
+
7620
+ var updateLicense$1 = /*#__PURE__*/Object.freeze({
7568
7621
  __proto__: null,
7569
7622
  code: code$6,
7570
7623
  handler: handler$6
7571
7624
  });
7572
7625
 
7573
- var pluginActionHandlers$6 = [getLicense$1];
7626
+ var pluginActionHandlers$6 = [getLicense$1, updateLicense$1];
7574
7627
 
7575
7628
  var pluginModels$5 = [];
7576
7629
 
@@ -7588,7 +7641,21 @@ var getLicense = {
7588
7641
  ],
7589
7642
  };
7590
7643
 
7591
- var pluginRoutes$5 = [getLicense];
7644
+ var updateLicense = {
7645
+ namespace: "svc",
7646
+ name: "svc.updateLicense",
7647
+ code: "svc.updateLicense",
7648
+ type: "RESTful",
7649
+ method: "POST",
7650
+ endpoint: "/svc/license",
7651
+ actions: [
7652
+ {
7653
+ code: "updateLicense",
7654
+ },
7655
+ ],
7656
+ };
7657
+
7658
+ var pluginRoutes$5 = [getLicense, updateLicense];
7592
7659
 
7593
7660
  function getEncryptionIV(input) {
7594
7661
  const hash = crypto__default["default"].createHash("sha512").update(input).digest("hex");
@@ -7644,16 +7711,13 @@ class LicenseService {
7644
7711
  async loadLicense() {
7645
7712
  const settingService = this.#server.getService("settingService");
7646
7713
  const licenseSettings = await settingService.getSystemSettingValues("license");
7647
- const { deployId } = licenseSettings;
7648
- const certText = licenseSettings.cert;
7714
+ const { deployId, cert: certText } = licenseSettings;
7649
7715
  if (!deployId || !certText) {
7650
7716
  this.#server.getLogger().warn("License was not loaded properly.");
7651
7717
  return;
7652
7718
  }
7653
- const certJSON = Buffer.from(certText, "base64").toString();
7654
- const cert = JSON.parse(certJSON);
7655
7719
  try {
7656
- const license = extractCertLicense(this.#encryptionKey, deployId, cert);
7720
+ const license = this.parseLicense(deployId, certText);
7657
7721
  this.#license = license;
7658
7722
  }
7659
7723
  catch (error) {
@@ -7664,6 +7728,26 @@ class LicenseService {
7664
7728
  getLicense() {
7665
7729
  return this.#license;
7666
7730
  }
7731
+ parseLicense(deployId, certText) {
7732
+ const certJSON = Buffer.from(certText, "base64").toString();
7733
+ const cert = JSON.parse(certJSON);
7734
+ return extractCertLicense(this.#encryptionKey, deployId, cert);
7735
+ }
7736
+ async updateLicense(certText) {
7737
+ const settingService = this.#server.getService("settingService");
7738
+ const deployId = await settingService.getSystemSettingValue("license", "deployId");
7739
+ let license;
7740
+ try {
7741
+ license = this.parseLicense(deployId, certText);
7742
+ }
7743
+ catch (error) {
7744
+ this.#server.getLogger().error("Parse license failed.", error);
7745
+ throw new Error("Parse license failed.");
7746
+ }
7747
+ await settingService.setSystemSettingValue("license", "cert", certText);
7748
+ this.#license = license;
7749
+ return license;
7750
+ }
7667
7751
  isExpired() {
7668
7752
  if (!this.#license) {
7669
7753
  return true;
@@ -15,6 +15,8 @@ export default class LicenseService {
15
15
  constructor(server: IRpdServer, encryptionKey: string);
16
16
  loadLicense(): Promise<void>;
17
17
  getLicense(): RpdLicense;
18
+ parseLicense(deployId: string, certText: string): RpdLicense;
19
+ updateLicense(certText: string): Promise<RpdLicense>;
18
20
  isExpired(): boolean;
19
21
  getQuota(name: string): any;
20
22
  isOutOfQuota(name: string, currentAmount: number): boolean;
@@ -1,3 +1,4 @@
1
1
  import * as getLicense from "./getLicense";
2
- declare const _default: (typeof getLicense)[];
2
+ import * as updateLicense from "./updateLicense";
3
+ declare const _default: (typeof getLicense | typeof updateLicense)[];
3
4
  export default _default;
@@ -0,0 +1,9 @@
1
+ import { ActionHandlerContext } from "../../../core/actionHandler";
2
+ import { RapidPlugin } from "../../../core/server";
3
+ export interface UpdateLicenseOptions {
4
+ }
5
+ export interface UpdateLicenseInput {
6
+ certText: string;
7
+ }
8
+ export declare const code = "updateLicense";
9
+ export declare function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: UpdateLicenseOptions): Promise<void>;
@@ -1,4 +1,4 @@
1
- declare const _default: {
1
+ declare const _default: ({
2
2
  namespace: string;
3
3
  name: string;
4
4
  code: string;
@@ -8,5 +8,15 @@ declare const _default: {
8
8
  actions: {
9
9
  code: string;
10
10
  }[];
11
- }[];
11
+ } | {
12
+ namespace: string;
13
+ name: string;
14
+ code: string;
15
+ type: "RESTful";
16
+ method: "POST";
17
+ endpoint: string;
18
+ actions: {
19
+ code: string;
20
+ }[];
21
+ })[];
12
22
  export default _default;
@@ -0,0 +1,12 @@
1
+ declare const _default: {
2
+ namespace: string;
3
+ name: string;
4
+ code: string;
5
+ type: "RESTful";
6
+ method: "POST";
7
+ endpoint: string;
8
+ actions: {
9
+ code: string;
10
+ }[];
11
+ };
12
+ export default _default;
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ActionHandlerContext } from "./core/actionHandler";
1
2
  import { RouteContext } from "./core/routeContext";
2
3
  import { IRpdServer, RapidPlugin } from "./core/server";
3
4
  import { ColumnSelectOptions, CountRowOptions, FindRowOptions, RowFilterOptions } from "./dataAccess/dataAccessTypes";
@@ -483,6 +484,7 @@ export interface RpdRoute {
483
484
  method: RpdHttpMethod;
484
485
  endpoint: string;
485
486
  actions?: RpdRouteActionConfig[];
487
+ handler?: string | ((ctx: ActionHandlerContext) => Promise<void>);
486
488
  }
487
489
  export type RpdHttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
488
490
  export interface RpdRouteActionConfig {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,20 @@
1
+ import { RpdRoute } from "~/types";
2
+ import { ActionHandlerContext } from "../actionHandler";
3
+
4
+ export default {
5
+ namespace: "sys",
6
+ name: "sys.healthz",
7
+ code: "sys.healthz",
8
+ type: "RESTful",
9
+ method: "GET",
10
+ endpoint: "/healthz",
11
+ handler,
12
+ } satisfies RpdRoute;
13
+
14
+ export async function handler(ctx: ActionHandlerContext) {
15
+ const { server, input, routerContext: routeContext, logger } = ctx;
16
+ const { response } = routeContext;
17
+ const {} = input;
18
+
19
+ ctx.output = {};
20
+ }
@@ -0,0 +1,3 @@
1
+ import healthz from "./healthz";
2
+
3
+ export default [healthz];
@@ -5,7 +5,7 @@ import { IRpdServer } from "~/core/server";
5
5
  import { RpdApplicationConfig } from "~/types";
6
6
  import { isNullOrUndefined } from "~/utilities/typeUtility";
7
7
  import { Next, RouteContext } from "./routeContext";
8
- import { cloneDeep } from "lodash";
8
+ import { cloneDeep, isFunction, isString } from "lodash";
9
9
 
10
10
  export async function buildRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig) {
11
11
  const logger = server.getLogger();
@@ -67,19 +67,37 @@ export async function buildRoutes(server: IRpdServer, applicationConfig: RpdAppl
67
67
 
68
68
  await server.beforeRunRouteActions(handlerContext);
69
69
 
70
- for (const actionConfig of routeConfig.actions) {
71
- const actionCode = actionConfig.code;
72
- const handler = server.getActionHandlerByCode(actionCode);
73
- if (!handler) {
74
- throw new Error("Unknown handler: " + actionCode);
70
+ let handler = routeConfig.handler as any;
71
+ if (handler) {
72
+ if (isString(handler)) {
73
+ handler = new Function(`return (${routeConfig.handler})`) as any;
75
74
  }
76
75
 
77
- await server.beforeRunActionHandler(handlerContext, actionConfig);
78
-
79
- const result = handler(handlerContext, actionConfig.config);
80
- if (result instanceof Promise) {
81
- await result;
76
+ if (isFunction(handler)) {
77
+ const result = handler(handlerContext);
78
+ if (result instanceof Promise) {
79
+ await result;
80
+ }
81
+ } else {
82
+ throw new Error(`Invalid handler for route ${routeConfig.code}: ${routeConfig.handler}`);
83
+ }
84
+ } else if (routeConfig.actions) {
85
+ for (const actionConfig of routeConfig.actions) {
86
+ const actionCode = actionConfig.code;
87
+ const handler = server.getActionHandlerByCode(actionCode);
88
+ if (!handler) {
89
+ throw new Error("Unknown handler: " + actionCode);
90
+ }
91
+
92
+ await server.beforeRunActionHandler(handlerContext, actionConfig);
93
+
94
+ const result = handler(handlerContext, actionConfig.config);
95
+ if (result instanceof Promise) {
96
+ await result;
97
+ }
82
98
  }
99
+ } else {
100
+ throw new Error(`No handler or actions defined for route ${routeConfig.code}`);
83
101
  }
84
102
 
85
103
  if (!isNullOrUndefined(handlerContext.output)) {
@@ -37,19 +37,15 @@ export default class LicenseService {
37
37
  async loadLicense(): Promise<void> {
38
38
  const settingService = this.#server.getService<SettingService>("settingService");
39
39
  const licenseSettings = await settingService.getSystemSettingValues("license");
40
- const { deployId } = licenseSettings as LicenseSettings;
41
- const certText = licenseSettings.cert;
40
+ const { deployId, cert: certText } = licenseSettings as LicenseSettings;
42
41
 
43
42
  if (!deployId || !certText) {
44
43
  this.#server.getLogger().warn("License was not loaded properly.");
45
44
  return;
46
45
  }
47
46
 
48
- const certJSON = Buffer.from(certText, "base64").toString();
49
- const cert: RpdCert = JSON.parse(certJSON);
50
-
51
47
  try {
52
- const license = extractCertLicense(this.#encryptionKey, deployId, cert);
48
+ const license = this.parseLicense(deployId, certText);
53
49
  this.#license = license;
54
50
  } catch (error) {
55
51
  this.#server.getLogger().error("Loading license failed.", error);
@@ -61,6 +57,29 @@ export default class LicenseService {
61
57
  return this.#license;
62
58
  }
63
59
 
60
+ parseLicense(deployId: string, certText: string): RpdLicense {
61
+ const certJSON = Buffer.from(certText, "base64").toString();
62
+ const cert: RpdCert = JSON.parse(certJSON);
63
+ return extractCertLicense(this.#encryptionKey, deployId, cert);
64
+ }
65
+
66
+ async updateLicense(certText: string) {
67
+ const settingService = this.#server.getService<SettingService>("settingService");
68
+ const deployId: string = await settingService.getSystemSettingValue("license", "deployId");
69
+
70
+ let license: RpdLicense;
71
+ try {
72
+ license = this.parseLicense(deployId, certText);
73
+ } catch (error) {
74
+ this.#server.getLogger().error("Parse license failed.", error);
75
+ throw new Error("Parse license failed.");
76
+ }
77
+
78
+ await settingService.setSystemSettingValue("license", "cert", certText);
79
+ this.#license = license;
80
+ return license;
81
+ }
82
+
64
83
  isExpired() {
65
84
  if (!this.#license) {
66
85
  return true;
@@ -1,4 +1,5 @@
1
1
  import { IPluginActionHandler } from "~/core/actionHandler";
2
2
  import * as getLicense from "./getLicense";
3
+ import * as updateLicense from "./updateLicense";
3
4
 
4
- export default [getLicense] satisfies IPluginActionHandler[];
5
+ export default [getLicense, updateLicense] satisfies IPluginActionHandler[];
@@ -0,0 +1,24 @@
1
+ import { ActionHandlerContext } from "~/core/actionHandler";
2
+ import { RapidPlugin } from "~/core/server";
3
+ import LicenseService from "../LicenseService";
4
+
5
+ export interface UpdateLicenseOptions {}
6
+
7
+ export interface UpdateLicenseInput {
8
+ certText: string;
9
+ }
10
+
11
+ export const code = "updateLicense";
12
+
13
+ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: UpdateLicenseOptions) {
14
+ const { server, routerContext } = ctx;
15
+ const { response } = routerContext;
16
+
17
+ const input: UpdateLicenseInput = ctx.input;
18
+
19
+ const licenseService = server.getService<LicenseService>("licenseService");
20
+
21
+ const license = await licenseService.updateLicense(input.certText);
22
+
23
+ ctx.output = license;
24
+ }
@@ -1,3 +1,4 @@
1
1
  import getLicense from "./getLicense";
2
+ import updateLicense from "./updateLicense";
2
3
 
3
- export default [getLicense];
4
+ export default [getLicense, updateLicense];
@@ -0,0 +1,15 @@
1
+ import { RpdRoute } from "~/types";
2
+
3
+ export default {
4
+ namespace: "svc",
5
+ name: "svc.updateLicense",
6
+ code: "svc.updateLicense",
7
+ type: "RESTful",
8
+ method: "POST",
9
+ endpoint: "/svc/license",
10
+ actions: [
11
+ {
12
+ code: "updateLicense",
13
+ },
14
+ ],
15
+ } satisfies RpdRoute;
package/src/server.ts CHANGED
@@ -35,6 +35,7 @@ import { bind, cloneDeep, find, forEach, isString, merge, omit } from "lodash";
35
35
  import { Logger } from "./facilities/log/LogFacility";
36
36
  import { FacilityFactory } from "./core/facility";
37
37
  import { CronJobConfiguration } from "./types/cron-job-types";
38
+ import coreRoutes from "./core/routes";
38
39
 
39
40
  export interface InitServerOptions {
40
41
  logger: Logger;
@@ -367,7 +368,12 @@ export class RapidServer implements IRpdServer {
367
368
  }
368
369
  }
369
370
 
371
+ this.#applicationConfig = cloneDeep(this.#bootstrapApplicationConfig) as RpdApplicationConfig;
372
+ this.appendApplicationConfig({
373
+ routes: coreRoutes,
374
+ });
370
375
  await this.configureApplication();
376
+ this.#buildedRoutes = await buildRoutes(this, this.#applicationConfig);
371
377
 
372
378
  if (!this.#disableCronJobs) {
373
379
  await pluginManager.registerCronJobs();
@@ -378,8 +384,6 @@ export class RapidServer implements IRpdServer {
378
384
  }
379
385
 
380
386
  async configureApplication() {
381
- this.#applicationConfig = cloneDeep(this.#bootstrapApplicationConfig) as RpdApplicationConfig;
382
-
383
387
  const pluginManager = this.#pluginManager;
384
388
  await pluginManager.onLoadingApplication(this.#applicationConfig);
385
389
  await pluginManager.configureModels(this.#applicationConfig);
@@ -390,8 +394,6 @@ export class RapidServer implements IRpdServer {
390
394
  // TODO: check application configuration.
391
395
 
392
396
  await pluginManager.onApplicationLoaded(this.#applicationConfig);
393
-
394
- this.#buildedRoutes = await buildRoutes(this, this.#applicationConfig);
395
397
  }
396
398
 
397
399
  registerFacilityFactory(factory: FacilityFactory) {
package/src/types.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ActionHandlerContext } from "./core/actionHandler";
1
2
  import { RouteContext } from "./core/routeContext";
2
3
  import { IRpdServer, RapidPlugin } from "./core/server";
3
4
  import { ColumnSelectOptions, CountRowOptions, FindRowOptions, RowFilterOptions } from "./dataAccess/dataAccessTypes";
@@ -586,6 +587,7 @@ export interface RpdRoute {
586
587
  method: RpdHttpMethod;
587
588
  endpoint: string;
588
589
  actions?: RpdRouteActionConfig[];
590
+ handler?: string | ((ctx: ActionHandlerContext) => Promise<void>);
589
591
  }
590
592
 
591
593
  export type RpdHttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
@@ -21,6 +21,6 @@ export async function generatePasswordHash(password: string, salt?: number | str
21
21
  * @returns
22
22
  */
23
23
  export async function validatePassword(password: string, passwordHash: string): Promise<boolean> {
24
- const isMatch = await bcrypt.compare(password, passwordHash);
24
+ const isMatch = await bcrypt.compare(password || "", passwordHash || "");
25
25
  return isMatch;
26
26
  }