monorise 0.0.4 → 0.1.0

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.
@@ -53,6 +53,19 @@ declare abstract class Repository {
53
53
  ExpressionAttributeNames: Record<string, string>;
54
54
  ExpressionAttributeValues: Record<string, AttributeValue>;
55
55
  };
56
+ toAdjustUpdate(adjustments: Record<string, number>, constraints?: {
57
+ [field: string]: {
58
+ min?: number;
59
+ max?: number;
60
+ minField?: string;
61
+ maxField?: string;
62
+ };
63
+ }, prefix?: string): {
64
+ UpdateExpression: string;
65
+ ConditionExpression?: string;
66
+ ExpressionAttributeNames: Record<string, string>;
67
+ ExpressionAttributeValues: Record<string, AttributeValue>;
68
+ };
56
69
  }
57
70
 
58
71
  declare class Entity$1<T extends Entity$2> extends Item$1 {
@@ -119,6 +132,12 @@ declare class EntityRepository extends Repository {
119
132
  ExpressionAttributeNames?: Record<string, string>;
120
133
  ExpressionAttributeValues?: Record<string, AttributeValue>;
121
134
  }): Promise<Entity$1<T>>;
135
+ adjustEntity<T extends Entity$2>(entityType: T, entityId: string, adjustments: Record<string, number>, constraints?: {
136
+ [field: string]: {
137
+ min?: number;
138
+ max?: number;
139
+ };
140
+ }): Promise<Entity$1<T>>;
122
141
  deleteEntity<T extends Entity$2>(entityType: T, entityId: string): Promise<void>;
123
142
  queryEntities<T extends Entity$2>(entityType: T, query: string): Promise<{
124
143
  items: Entity$1<T>[];
@@ -4452,6 +4471,12 @@ declare class EntityService {
4452
4471
  mutualId?: string;
4453
4472
  };
4454
4473
  }) => Promise<Entity<T>>;
4474
+ adjustEntity: <T extends Entity$2>({ entityType, entityId, adjustments, accountId, }: {
4475
+ entityType: T;
4476
+ entityId: string;
4477
+ adjustments: Record<string, number>;
4478
+ accountId?: string;
4479
+ }) => Promise<Entity<T>>;
4455
4480
  updateEntity: <T extends Entity$2>({ entityType, entityId, entityPayload, accountId, }: {
4456
4481
  entityType: T;
4457
4482
  entityId: string;
@@ -4518,6 +4543,14 @@ declare class UpdateEntityController {
4518
4543
  }, hono_utils_http_status.ContentfulStatusCode, "json">>;
4519
4544
  }
4520
4545
 
4546
+ declare class AdjustEntityController {
4547
+ private entityService;
4548
+ constructor(entityService: EntityService);
4549
+ controller: hono.MiddlewareHandler<any, string, {}, Response & hono.TypedResponse<{
4550
+ [x: string]: hono_utils_types.JSONValue;
4551
+ }, hono_utils_http_status.ContentfulStatusCode, "json">>;
4552
+ }
4553
+
4521
4554
  declare class UpsertEntityController {
4522
4555
  private EntityConfig;
4523
4556
  private entityRepository;
@@ -4673,6 +4706,7 @@ declare class DependencyContainer {
4673
4706
  get createEntityController(): CreateEntityController;
4674
4707
  get upsertEntityController(): UpsertEntityController;
4675
4708
  get updateEntityController(): UpdateEntityController;
4709
+ get adjustEntityController(): AdjustEntityController;
4676
4710
  get deleteEntityController(): DeleteEntityController;
4677
4711
  get listEntitiesByEntityController(): ListEntitiesByEntityController;
4678
4712
  get getMutualController(): GetMutualController;
@@ -107,6 +107,10 @@ var setupCommonRoutes = (container) => {
107
107
  "/entity/:entityType/unique/:uniqueField/:uniqueFieldValue",
108
108
  container.getEntityByUniqueFieldController.controller
109
109
  );
110
+ app.post(
111
+ "/entity/:entityType/:entityId/adjust",
112
+ container.adjustEntityController.controller
113
+ );
110
114
  app.get(
111
115
  "/entity/:entityType/:entityId",
112
116
  container.getEntityController.controller
@@ -250,6 +254,47 @@ var Repository = class {
250
254
  };
251
255
  return updateAttributes;
252
256
  }
257
+ toAdjustUpdate(adjustments, constraints, prefix = "data") {
258
+ const parts = [];
259
+ const conditionParts = [];
260
+ const expressionAttributeNames = {};
261
+ const expressionAttributeValues = {};
262
+ expressionAttributeNames[`#${prefix}`] = prefix;
263
+ for (const field of Object.keys(adjustments)) {
264
+ const namePlaceholder = `#${field}`;
265
+ const valuePlaceholder = `:${field}`;
266
+ const fieldExpr = `if_not_exists(#${prefix}.${namePlaceholder}, :zero)`;
267
+ parts.push(
268
+ `#${prefix}.${namePlaceholder} = ${fieldExpr} + ${valuePlaceholder}`
269
+ );
270
+ expressionAttributeNames[namePlaceholder] = field;
271
+ expressionAttributeValues[valuePlaceholder] = adjustments[field];
272
+ if (constraints == null ? void 0 : constraints[field]) {
273
+ const constraint = constraints[field];
274
+ const delta = adjustments[field];
275
+ const currentFieldRef = `#${prefix}.${namePlaceholder}`;
276
+ if (constraint.min !== void 0 && delta < 0) {
277
+ const thresholdPlaceholder = `:${field}_min_threshold`;
278
+ conditionParts.push(`${currentFieldRef} >= ${thresholdPlaceholder}`);
279
+ expressionAttributeValues[thresholdPlaceholder] = constraint.min - delta;
280
+ }
281
+ if (constraint.max !== void 0 && delta > 0) {
282
+ const thresholdPlaceholder = `:${field}_max_threshold`;
283
+ conditionParts.push(`${currentFieldRef} <= ${thresholdPlaceholder}`);
284
+ expressionAttributeValues[thresholdPlaceholder] = constraint.max - delta;
285
+ }
286
+ }
287
+ }
288
+ expressionAttributeValues[":zero"] = 0;
289
+ return __spreadProps(__spreadValues({
290
+ UpdateExpression: `SET ${parts.join(", ")}`
291
+ }, conditionParts.length > 0 && {
292
+ ConditionExpression: conditionParts.join(" AND ")
293
+ }), {
294
+ ExpressionAttributeNames: expressionAttributeNames,
295
+ ExpressionAttributeValues: marshall(expressionAttributeValues)
296
+ });
297
+ }
253
298
  };
254
299
 
255
300
  // data/Entity.ts
@@ -751,6 +796,25 @@ var EntityRepository = class extends Repository {
751
796
  }
752
797
  });
753
798
  }
799
+ adjustEntity(entityType, entityId, adjustments, constraints) {
800
+ return __async(this, null, function* () {
801
+ const entity = new Entity(entityType, entityId);
802
+ const { UpdateExpression, ConditionExpression, ExpressionAttributeNames, ExpressionAttributeValues } = this.toAdjustUpdate(adjustments, constraints);
803
+ const updatedAtExpression = ", #updatedAt = :updatedAt";
804
+ ExpressionAttributeNames["#updatedAt"] = "updatedAt";
805
+ ExpressionAttributeValues[":updatedAt"] = { S: (/* @__PURE__ */ new Date()).toISOString() };
806
+ const resp = yield this.dynamodbClient.updateItem(__spreadProps(__spreadValues({
807
+ TableName: this.TABLE_NAME,
808
+ Key: entity.keys(),
809
+ UpdateExpression: UpdateExpression + updatedAtExpression
810
+ }, ConditionExpression && { ConditionExpression }), {
811
+ ExpressionAttributeNames,
812
+ ExpressionAttributeValues,
813
+ ReturnValues: "ALL_NEW"
814
+ }));
815
+ return Entity.fromItem(resp.Attributes);
816
+ });
817
+ }
754
818
  deleteEntity(entityType, entityId) {
755
819
  return __async(this, null, function* () {
756
820
  try {
@@ -2850,6 +2914,7 @@ var CreateEntityController = class {
2850
2914
  const entity = yield this.entityService.createEntity({
2851
2915
  entityType,
2852
2916
  entityPayload: body,
2917
+ entityId: body.entityId,
2853
2918
  accountId,
2854
2919
  options: {
2855
2920
  createAndUpdateDatetime: body.createdAt
@@ -7033,15 +7098,63 @@ var UpdateEntityController = class {
7033
7098
  }
7034
7099
  };
7035
7100
 
7036
- // controllers/entity/upsert-entity.controller.ts
7101
+ // controllers/entity/adjust-entity.controller.ts
7037
7102
  import { createMiddleware as createMiddleware9 } from "hono/factory";
7038
7103
  import httpStatus9 from "http-status";
7104
+ var AdjustEntityController = class {
7105
+ constructor(entityService) {
7106
+ this.entityService = entityService;
7107
+ this.controller = createMiddleware9((c) => __async(this, null, function* () {
7108
+ var _a;
7109
+ const accountId = c.req.header("account-id") || "";
7110
+ const { entityType, entityId } = c.req.param();
7111
+ const body = yield c.req.json();
7112
+ for (const [key, value] of Object.entries(body)) {
7113
+ if (typeof value !== "number") {
7114
+ c.status(httpStatus9.BAD_REQUEST);
7115
+ return c.json({
7116
+ code: "API_VALIDATION_ERROR",
7117
+ message: `Field "${key}" must be a number, got ${typeof value}`
7118
+ });
7119
+ }
7120
+ }
7121
+ try {
7122
+ const entity = yield this.entityService.adjustEntity({
7123
+ entityType,
7124
+ entityId,
7125
+ adjustments: body,
7126
+ accountId
7127
+ });
7128
+ c.status(httpStatus9.OK);
7129
+ return c.json(entity.toJSON());
7130
+ } catch (err) {
7131
+ if (err instanceof StandardError && err.code === StandardErrorCode.ENTITY_IS_UNDEFINED) {
7132
+ c.status(httpStatus9.NOT_FOUND);
7133
+ return c.json(__spreadValues({}, err.toJSON()));
7134
+ }
7135
+ if ((err == null ? void 0 : err.name) === "ConditionalCheckFailedException" || ((_a = err == null ? void 0 : err.__type) == null ? void 0 : _a.includes("ConditionalCheckFailed"))) {
7136
+ c.status(httpStatus9.CONFLICT);
7137
+ return c.json({
7138
+ code: "ADJUSTMENT_CONSTRAINT_VIOLATED",
7139
+ message: "Adjustment would violate entity constraints"
7140
+ });
7141
+ }
7142
+ console.log("====ADJUST_ENTITY_CONTROLLER_ERROR", err);
7143
+ throw err;
7144
+ }
7145
+ }));
7146
+ }
7147
+ };
7148
+
7149
+ // controllers/entity/upsert-entity.controller.ts
7150
+ import { createMiddleware as createMiddleware10 } from "hono/factory";
7151
+ import httpStatus10 from "http-status";
7039
7152
  var UpsertEntityController = class {
7040
7153
  constructor(EntityConfig, entityRepository, publishEvent2) {
7041
7154
  this.EntityConfig = EntityConfig;
7042
7155
  this.entityRepository = entityRepository;
7043
7156
  this.publishEvent = publishEvent2;
7044
- this.controller = createMiddleware9((c) => __async(this, null, function* () {
7157
+ this.controller = createMiddleware10((c) => __async(this, null, function* () {
7045
7158
  var _a, _b;
7046
7159
  const accountId = c.req.header("account-id");
7047
7160
  const { entityType, entityId } = c.req.param();
@@ -7097,7 +7210,7 @@ var UpsertEntityController = class {
7097
7210
  return c.json(entity);
7098
7211
  } catch (err) {
7099
7212
  if (err instanceof ZodError) {
7100
- c.status(httpStatus9.BAD_REQUEST);
7213
+ c.status(httpStatus10.BAD_REQUEST);
7101
7214
  return c.json({
7102
7215
  code: "API_VALIDATION_ERROR",
7103
7216
  message: "API validation failed",
@@ -7105,7 +7218,7 @@ var UpsertEntityController = class {
7105
7218
  });
7106
7219
  }
7107
7220
  if (err instanceof StandardError && err.code === StandardErrorCode.EMAIL_EXISTS) {
7108
- c.status(httpStatus9.BAD_REQUEST);
7221
+ c.status(httpStatus10.BAD_REQUEST);
7109
7222
  return c.json(__spreadValues({}, err.toJSON()));
7110
7223
  }
7111
7224
  throw err;
@@ -7115,12 +7228,12 @@ var UpsertEntityController = class {
7115
7228
  };
7116
7229
 
7117
7230
  // controllers/mutual/create-mutual.controller.ts
7118
- import { createMiddleware as createMiddleware10 } from "hono/factory";
7119
- import httpStatus10 from "http-status";
7231
+ import { createMiddleware as createMiddleware11 } from "hono/factory";
7232
+ import httpStatus11 from "http-status";
7120
7233
  var CreateMutualController = class {
7121
7234
  constructor(mutualService) {
7122
7235
  this.mutualService = mutualService;
7123
- this.controller = createMiddleware10((c) => __async(this, null, function* () {
7236
+ this.controller = createMiddleware11((c) => __async(this, null, function* () {
7124
7237
  const accountId = c.req.header("account-id");
7125
7238
  const { byEntityType, byEntityId, entityType, entityId } = c.req.param();
7126
7239
  const asEntity = c.req.query("asEntity");
@@ -7140,7 +7253,7 @@ var CreateMutualController = class {
7140
7253
  return c.json(mutual);
7141
7254
  } catch (err) {
7142
7255
  if (err instanceof ZodError) {
7143
- c.status(httpStatus10.BAD_REQUEST);
7256
+ c.status(httpStatus11.BAD_REQUEST);
7144
7257
  return c.json({
7145
7258
  code: "API_VALIDATION_ERROR",
7146
7259
  message: "API validation failed",
@@ -7148,11 +7261,11 @@ var CreateMutualController = class {
7148
7261
  });
7149
7262
  }
7150
7263
  if (err instanceof StandardError && err.code === StandardErrorCode.MUTUAL_EXISTS) {
7151
- c.status(httpStatus10.BAD_REQUEST);
7264
+ c.status(httpStatus11.BAD_REQUEST);
7152
7265
  return c.json(__spreadValues({}, err.toJSON()));
7153
7266
  }
7154
7267
  if (err instanceof StandardError && err.code === StandardErrorCode.ENTITY_IS_UNDEFINED) {
7155
- c.status(httpStatus10.BAD_REQUEST);
7268
+ c.status(httpStatus11.BAD_REQUEST);
7156
7269
  return c.json(__spreadValues({}, err.toJSON()));
7157
7270
  }
7158
7271
  throw err;
@@ -7162,12 +7275,12 @@ var CreateMutualController = class {
7162
7275
  };
7163
7276
 
7164
7277
  // controllers/mutual/delete-mutual.controller.ts
7165
- import { createMiddleware as createMiddleware11 } from "hono/factory";
7166
- import httpStatus11 from "http-status";
7278
+ import { createMiddleware as createMiddleware12 } from "hono/factory";
7279
+ import httpStatus12 from "http-status";
7167
7280
  var DeleteMutualController = class {
7168
7281
  constructor(mutualService) {
7169
7282
  this.mutualService = mutualService;
7170
- this.controller = createMiddleware11((c) => __async(this, null, function* () {
7283
+ this.controller = createMiddleware12((c) => __async(this, null, function* () {
7171
7284
  const accountId = c.req.header("account-id");
7172
7285
  const { byEntityType, byEntityId, entityType, entityId } = c.req.param();
7173
7286
  try {
@@ -7181,7 +7294,7 @@ var DeleteMutualController = class {
7181
7294
  return c.json(mutual);
7182
7295
  } catch (err) {
7183
7296
  if (err instanceof StandardError && err.code === StandardErrorCode.MUTUAL_NOT_FOUND) {
7184
- c.status(httpStatus11.BAD_REQUEST);
7297
+ c.status(httpStatus12.BAD_REQUEST);
7185
7298
  return c.json(__spreadValues({}, err.toJSON()));
7186
7299
  }
7187
7300
  throw err;
@@ -7191,12 +7304,12 @@ var DeleteMutualController = class {
7191
7304
  };
7192
7305
 
7193
7306
  // controllers/mutual/get-mutual.controller.ts
7194
- import { createMiddleware as createMiddleware12 } from "hono/factory";
7195
- import httpStatus12 from "http-status";
7307
+ import { createMiddleware as createMiddleware13 } from "hono/factory";
7308
+ import httpStatus13 from "http-status";
7196
7309
  var GetMutualController = class {
7197
7310
  constructor(associateRepository) {
7198
7311
  this.associateRepository = associateRepository;
7199
- this.controller = createMiddleware12((c) => __async(this, null, function* () {
7312
+ this.controller = createMiddleware13((c) => __async(this, null, function* () {
7200
7313
  const { byEntityType, byEntityId, entityType, entityId } = c.req.param();
7201
7314
  try {
7202
7315
  const associate = yield this.associateRepository.getMutual(
@@ -7208,7 +7321,7 @@ var GetMutualController = class {
7208
7321
  return c.json(associate);
7209
7322
  } catch (err) {
7210
7323
  if (err instanceof StandardError && err.code === StandardErrorCode.MUTUAL_IS_UNDEFINED) {
7211
- c.status(httpStatus12.NOT_FOUND);
7324
+ c.status(httpStatus13.NOT_FOUND);
7212
7325
  return c.json({
7213
7326
  code: "MUTUAL_NOT_FOUND",
7214
7327
  message: "Mutual not found"
@@ -7221,11 +7334,11 @@ var GetMutualController = class {
7221
7334
  };
7222
7335
 
7223
7336
  // controllers/mutual/list-entities-by-entity.controller.ts
7224
- import { createMiddleware as createMiddleware13 } from "hono/factory";
7337
+ import { createMiddleware as createMiddleware14 } from "hono/factory";
7225
7338
  var ListEntitiesByEntityController = class {
7226
7339
  constructor(associateRepository) {
7227
7340
  this.associateRepository = associateRepository;
7228
- this.controller = createMiddleware13((c) => __async(this, null, function* () {
7341
+ this.controller = createMiddleware14((c) => __async(this, null, function* () {
7229
7342
  const { byEntityType, byEntityId, entityType } = c.req.param();
7230
7343
  const querySchema3 = external_exports.object({
7231
7344
  chainEntityQuery: external_exports.string().optional(),
@@ -7283,12 +7396,12 @@ var ListEntitiesByEntityController = class {
7283
7396
  };
7284
7397
 
7285
7398
  // controllers/mutual/update-mutual.controller.ts
7286
- import { createMiddleware as createMiddleware14 } from "hono/factory";
7287
- import httpStatus13 from "http-status";
7399
+ import { createMiddleware as createMiddleware15 } from "hono/factory";
7400
+ import httpStatus14 from "http-status";
7288
7401
  var UpdateMutualController = class {
7289
7402
  constructor(mutualService) {
7290
7403
  this.mutualService = mutualService;
7291
- this.controller = createMiddleware14((c) => __async(this, null, function* () {
7404
+ this.controller = createMiddleware15((c) => __async(this, null, function* () {
7292
7405
  const accountId = c.req.header("account-id");
7293
7406
  const { byEntityType, byEntityId, entityType, entityId } = c.req.param();
7294
7407
  const body = yield c.req.json();
@@ -7307,7 +7420,7 @@ var UpdateMutualController = class {
7307
7420
  return c.json(mutual);
7308
7421
  } catch (err) {
7309
7422
  if (err instanceof ZodError) {
7310
- c.status(httpStatus13.BAD_REQUEST);
7423
+ c.status(httpStatus14.BAD_REQUEST);
7311
7424
  return c.json({
7312
7425
  code: "API_VALIDATION_ERROR",
7313
7426
  message: "API validation failed",
@@ -7315,7 +7428,7 @@ var UpdateMutualController = class {
7315
7428
  });
7316
7429
  }
7317
7430
  if (err instanceof StandardError && err.code === StandardErrorCode.MUTUAL_NOT_FOUND) {
7318
- c.status(httpStatus13.BAD_REQUEST);
7431
+ c.status(httpStatus14.BAD_REQUEST);
7319
7432
  return c.json(__spreadValues({}, err.toJSON()));
7320
7433
  }
7321
7434
  throw err;
@@ -7375,6 +7488,51 @@ var EntityService = class {
7375
7488
  );
7376
7489
  return entity;
7377
7490
  });
7491
+ this.adjustEntity = (_0) => __async(this, [_0], function* ({
7492
+ entityType,
7493
+ entityId,
7494
+ adjustments,
7495
+ accountId
7496
+ }) {
7497
+ var _a, _b, _c, _d;
7498
+ const rawConstraints = (_a = this.EntityConfig[entityType]) == null ? void 0 : _a.adjustmentConstraints;
7499
+ let resolvedConstraints = rawConstraints;
7500
+ if (rawConstraints) {
7501
+ const hasDynamicFields = Object.values(rawConstraints).some(
7502
+ (c) => c.minField || c.maxField
7503
+ );
7504
+ if (hasDynamicFields) {
7505
+ const currentEntity = yield this.entityRepository.getEntity(entityType, entityId);
7506
+ const data = (_b = currentEntity == null ? void 0 : currentEntity.data) != null ? _b : {};
7507
+ resolvedConstraints = {};
7508
+ for (const [field, constraint] of Object.entries(rawConstraints)) {
7509
+ const resolved = {};
7510
+ if (constraint.min !== void 0) resolved.min = constraint.min;
7511
+ if (constraint.max !== void 0) resolved.max = constraint.max;
7512
+ if (constraint.minField) resolved.min = (_c = data[constraint.minField]) != null ? _c : 0;
7513
+ if (constraint.maxField) resolved.max = (_d = data[constraint.maxField]) != null ? _d : Number.MAX_SAFE_INTEGER;
7514
+ resolvedConstraints[field] = resolved;
7515
+ }
7516
+ }
7517
+ }
7518
+ const entity = yield this.entityRepository.adjustEntity(
7519
+ entityType,
7520
+ entityId,
7521
+ adjustments,
7522
+ resolvedConstraints
7523
+ );
7524
+ yield this.publishEvent({
7525
+ event: EVENT.CORE.ENTITY_UPDATED,
7526
+ payload: {
7527
+ entityType,
7528
+ entityId,
7529
+ data: entity.data,
7530
+ updatedByAccountId: accountId,
7531
+ publishedAt: entity.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
7532
+ }
7533
+ });
7534
+ return entity;
7535
+ });
7378
7536
  this.updateEntity = (_0) => __async(this, [_0], function* ({
7379
7537
  entityType,
7380
7538
  entityId,
@@ -7657,7 +7815,7 @@ var MutualService = class {
7657
7815
  };
7658
7816
 
7659
7817
  // controllers/tag/list-tags.controller.ts
7660
- import { createMiddleware as createMiddleware15 } from "hono/factory";
7818
+ import { createMiddleware as createMiddleware16 } from "hono/factory";
7661
7819
  var querySchema2 = external_exports.object({
7662
7820
  group: external_exports.string().optional(),
7663
7821
  query: external_exports.string().optional(),
@@ -7669,7 +7827,7 @@ var querySchema2 = external_exports.object({
7669
7827
  var ListTagsController = class {
7670
7828
  constructor(tagRepository) {
7671
7829
  this.tagRepository = tagRepository;
7672
- this.controller = createMiddleware15((c) => __async(this, null, function* () {
7830
+ this.controller = createMiddleware16((c) => __async(this, null, function* () {
7673
7831
  const errorContext = {};
7674
7832
  try {
7675
7833
  errorContext.params = c.req.param();
@@ -7865,6 +8023,12 @@ var DependencyContainer = class {
7865
8023
  this.entityService
7866
8024
  );
7867
8025
  }
8026
+ get adjustEntityController() {
8027
+ return this.createCachedInstance(
8028
+ AdjustEntityController,
8029
+ this.entityService
8030
+ );
8031
+ }
7868
8032
  get deleteEntityController() {
7869
8033
  return this.createCachedInstance(
7870
8034
  DeleteEntityController,