@monorise/core 3.1.0 → 4.0.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.
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ import { DynamoDB, TransactWriteItemsInput, AttributeValue, TransactWriteItem, U
5
5
  import * as hono_utils_http_status from 'hono/utils/http-status';
6
6
  import * as hono_utils_types from 'hono/utils/types';
7
7
  import { createFactory } from 'hono/factory';
8
- import httpStatus4 from 'http-status';
8
+ import httpStatus8 from 'http-status';
9
9
  import { unmarshall, marshall } from '@aws-sdk/util-dynamodb';
10
10
  import { EventBridgeClient } from '@aws-sdk/client-eventbridge';
11
11
  import * as hono_aws_lambda from 'hono/aws-lambda';
@@ -465,10 +465,10 @@ factory.createMiddleware((c, next) => __async(null, null, function* () {
465
465
  return yield next();
466
466
  }
467
467
  if (!xApiKey || Array.isArray(xApiKey) || !API_KEYS.includes(xApiKey)) {
468
- c.status(httpStatus4.UNAUTHORIZED);
468
+ c.status(httpStatus8.UNAUTHORIZED);
469
469
  return c.json({
470
- status: httpStatus4.UNAUTHORIZED,
471
- message: httpStatus4["401_MESSAGE"]
470
+ status: httpStatus8.UNAUTHORIZED,
471
+ message: httpStatus8["401_MESSAGE"]
472
472
  });
473
473
  }
474
474
  return yield next();
@@ -4446,6 +4446,26 @@ external_exports.object({
4446
4446
  lastKey: external_exports.string().optional()
4447
4447
  });
4448
4448
 
4449
+ type WhereOperator = {
4450
+ $eq: string | number | boolean;
4451
+ } | {
4452
+ $ne: string | number | boolean;
4453
+ } | {
4454
+ $gt: number;
4455
+ } | {
4456
+ $lt: number;
4457
+ } | {
4458
+ $gte: number;
4459
+ } | {
4460
+ $lte: number;
4461
+ } | {
4462
+ $exists: boolean;
4463
+ } | {
4464
+ $beginsWith: string;
4465
+ };
4466
+ type WhereClause = WhereOperator | string | number | boolean;
4467
+ type WhereConditions = Record<string, WhereClause>;
4468
+
4449
4469
  declare class EntityServiceLifeCycle {
4450
4470
  private EntityConfig;
4451
4471
  private publishEvent;
@@ -4477,11 +4497,12 @@ declare class EntityService {
4477
4497
  adjustments: Record<string, number>;
4478
4498
  accountId?: string;
4479
4499
  }) => Promise<Entity<T>>;
4480
- updateEntity: <T extends Entity$2>({ entityType, entityId, entityPayload, accountId, }: {
4500
+ updateEntity: <T extends Entity$2>({ entityType, entityId, entityPayload, accountId, where, }: {
4481
4501
  entityType: T;
4482
4502
  entityId: string;
4483
4503
  entityPayload: Partial<EntitySchemaMap[T]>;
4484
4504
  accountId?: string | string[];
4505
+ where?: WhereConditions;
4485
4506
  }) => Promise<Entity<T>>;
4486
4507
  deleteEntity: <T extends Entity$2>({ entityType, entityId, accountId, }: {
4487
4508
  entityType: T;
package/dist/index.js CHANGED
@@ -17,6 +17,18 @@ var __spreadValues = (a, b) => {
17
17
  return a;
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
20
32
  var __export = (target, all) => {
21
33
  for (var name in all)
22
34
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -762,6 +774,22 @@ var EntityRepository = class extends Repository {
762
774
  } catch (err) {
763
775
  if (err instanceof TransactionCanceledException) {
764
776
  const [updateErr, ...uniqueFieldErr] = err.CancellationReasons || [];
777
+ if ((updateErr == null ? void 0 : updateErr.Code) === BatchStatementErrorCodeEnum.ConditionalCheckFailed) {
778
+ if (opts == null ? void 0 : opts.ConditionExpression) {
779
+ throw new StandardError(
780
+ StandardErrorCode.CONDITIONAL_CHECK_FAILED,
781
+ "Conditional check failed",
782
+ err,
783
+ { entityId, toUpdate }
784
+ );
785
+ }
786
+ throw new StandardError(
787
+ StandardErrorCode.ENTITY_NOT_FOUND,
788
+ "Entity not found",
789
+ err,
790
+ { entityId, toUpdate }
791
+ );
792
+ }
765
793
  for (let i = 0; i < uniqueFieldErr.length; i++) {
766
794
  if (i % 2 === 1 && uniqueFieldErr[i].Code === BatchStatementErrorCodeEnum.ConditionalCheckFailed) {
767
795
  const field = updatedUniqueFields[Math.floor(i / 2)];
@@ -782,6 +810,14 @@ var EntityRepository = class extends Repository {
782
810
  return updatedEntity;
783
811
  } catch (err) {
784
812
  if (err instanceof ConditionalCheckFailedException) {
813
+ if (opts == null ? void 0 : opts.ConditionExpression) {
814
+ throw new StandardError(
815
+ StandardErrorCode.CONDITIONAL_CHECK_FAILED,
816
+ "Conditional check failed",
817
+ err,
818
+ { entityId, toUpdate }
819
+ );
820
+ }
785
821
  throw new StandardError(
786
822
  StandardErrorCode.ENTITY_NOT_FOUND,
787
823
  "Entity not found",
@@ -7051,10 +7087,11 @@ var UpdateEntityController = class {
7051
7087
  constructor(entityService) {
7052
7088
  this.entityService = entityService;
7053
7089
  this.controller = createMiddleware8((c) => __async(this, null, function* () {
7054
- var _a;
7090
+ var _b;
7055
7091
  const accountId = c.req.header("account-id");
7056
7092
  const { entityType, entityId } = c.req.param();
7057
7093
  const body = yield c.req.json();
7094
+ const _a = body, { $where: where } = _a, entityPayload = __objRest(_a, ["$where"]);
7058
7095
  const errorContext = {
7059
7096
  accountId,
7060
7097
  "req.params": c.req.param(),
@@ -7064,14 +7101,15 @@ var UpdateEntityController = class {
7064
7101
  const entity = yield this.entityService.updateEntity({
7065
7102
  entityType,
7066
7103
  entityId,
7067
- entityPayload: body,
7068
- accountId
7104
+ entityPayload,
7105
+ accountId,
7106
+ where
7069
7107
  });
7070
7108
  errorContext.entity = entity;
7071
7109
  c.status(httpStatus8.OK);
7072
7110
  return c.json(entity);
7073
7111
  } catch (err) {
7074
- if (((_a = err.constructor) == null ? void 0 : _a.name) === "ZodError") {
7112
+ if (((_b = err.constructor) == null ? void 0 : _b.name) === "ZodError") {
7075
7113
  c.status(httpStatus8.BAD_REQUEST);
7076
7114
  return c.json({
7077
7115
  code: "API_VALIDATION_ERROR",
@@ -7087,6 +7125,10 @@ var UpdateEntityController = class {
7087
7125
  c.status(httpStatus8.BAD_REQUEST);
7088
7126
  return c.json(__spreadValues({}, err.toJSON()));
7089
7127
  }
7128
+ if (err instanceof StandardError && err.code === StandardErrorCode.CONDITIONAL_CHECK_FAILED) {
7129
+ c.status(httpStatus8.CONFLICT);
7130
+ return c.json(__spreadValues({}, err.toJSON()));
7131
+ }
7090
7132
  console.log(
7091
7133
  "====UPDATE_ENTITY_CONTROLLER_ERROR",
7092
7134
  err,
@@ -7437,6 +7479,67 @@ var UpdateMutualController = class {
7437
7479
  }
7438
7480
  };
7439
7481
 
7482
+ // data/utils/build-condition-expression.ts
7483
+ import { marshall as marshall5 } from "@aws-sdk/util-dynamodb";
7484
+ function buildConditionExpression(where) {
7485
+ const conditions = ["attribute_exists(PK)"];
7486
+ const expressionAttributeNames = { "#data": "data" };
7487
+ const expressionAttributeValues = {};
7488
+ for (const [field, clause] of Object.entries(where)) {
7489
+ const namePlaceholder = `#where_${field}`;
7490
+ expressionAttributeNames[namePlaceholder] = field;
7491
+ const fieldRef = `#data.${namePlaceholder}`;
7492
+ if (clause === null || clause === void 0) continue;
7493
+ if (typeof clause !== "object") {
7494
+ const valPlaceholder = `:where_${field}`;
7495
+ expressionAttributeValues[valPlaceholder] = clause;
7496
+ conditions.push(`${fieldRef} = ${valPlaceholder}`);
7497
+ continue;
7498
+ }
7499
+ const op = clause;
7500
+ if ("$eq" in op) {
7501
+ const valPlaceholder = `:where_${field}_eq`;
7502
+ expressionAttributeValues[valPlaceholder] = op.$eq;
7503
+ conditions.push(`${fieldRef} = ${valPlaceholder}`);
7504
+ } else if ("$ne" in op) {
7505
+ const valPlaceholder = `:where_${field}_ne`;
7506
+ expressionAttributeValues[valPlaceholder] = op.$ne;
7507
+ conditions.push(`${fieldRef} <> ${valPlaceholder}`);
7508
+ } else if ("$gt" in op) {
7509
+ const valPlaceholder = `:where_${field}_gt`;
7510
+ expressionAttributeValues[valPlaceholder] = op.$gt;
7511
+ conditions.push(`${fieldRef} > ${valPlaceholder}`);
7512
+ } else if ("$lt" in op) {
7513
+ const valPlaceholder = `:where_${field}_lt`;
7514
+ expressionAttributeValues[valPlaceholder] = op.$lt;
7515
+ conditions.push(`${fieldRef} < ${valPlaceholder}`);
7516
+ } else if ("$gte" in op) {
7517
+ const valPlaceholder = `:where_${field}_gte`;
7518
+ expressionAttributeValues[valPlaceholder] = op.$gte;
7519
+ conditions.push(`${fieldRef} >= ${valPlaceholder}`);
7520
+ } else if ("$lte" in op) {
7521
+ const valPlaceholder = `:where_${field}_lte`;
7522
+ expressionAttributeValues[valPlaceholder] = op.$lte;
7523
+ conditions.push(`${fieldRef} <= ${valPlaceholder}`);
7524
+ } else if ("$exists" in op) {
7525
+ if (op.$exists) {
7526
+ conditions.push(`attribute_exists(${fieldRef})`);
7527
+ } else {
7528
+ conditions.push(`attribute_not_exists(${fieldRef})`);
7529
+ }
7530
+ } else if ("$beginsWith" in op) {
7531
+ const valPlaceholder = `:where_${field}_beginsWith`;
7532
+ expressionAttributeValues[valPlaceholder] = op.$beginsWith;
7533
+ conditions.push(`begins_with(${fieldRef}, ${valPlaceholder})`);
7534
+ }
7535
+ }
7536
+ return {
7537
+ ConditionExpression: conditions.join(" AND "),
7538
+ ExpressionAttributeNames: expressionAttributeNames,
7539
+ ExpressionAttributeValues: marshall5(expressionAttributeValues)
7540
+ };
7541
+ }
7542
+
7440
7543
  // services/entity.service.ts
7441
7544
  var EntityService = class {
7442
7545
  constructor(EntityConfig, EmailAuthEnabledEntities, entityRepository, publishEvent2, entityServiceLifeCycle) {
@@ -7537,7 +7640,8 @@ var EntityService = class {
7537
7640
  entityType,
7538
7641
  entityId,
7539
7642
  entityPayload,
7540
- accountId
7643
+ accountId,
7644
+ where
7541
7645
  }) {
7542
7646
  var _a, _b;
7543
7647
  const errorContext = {};
@@ -7553,10 +7657,12 @@ var EntityService = class {
7553
7657
  const parsedEntityPayload = entitySchema.parse(entityPayload);
7554
7658
  const parsedMutualPayload = mutualSchema == null ? void 0 : mutualSchema.parse(entityPayload);
7555
7659
  errorContext.parsedMutualPayload = parsedMutualPayload;
7660
+ const opts = where && Object.keys(where).length > 0 ? buildConditionExpression(where) : void 0;
7556
7661
  const entity = yield this.entityRepository.updateEntity(
7557
7662
  entityType,
7558
7663
  entityId,
7559
- { data: parsedEntityPayload }
7664
+ { data: parsedEntityPayload },
7665
+ opts
7560
7666
  );
7561
7667
  errorContext.entity = entity;
7562
7668
  if (parsedMutualPayload) {