monorise 1.1.0-dev.2 → 1.1.0-dev.3

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 (77) hide show
  1. package/dist/base/index.d.ts +53 -1
  2. package/dist/base/index.js +49 -1
  3. package/dist/base/index.js.map +1 -1
  4. package/dist/core/index.d.ts +3 -53
  5. package/dist/core/index.js +1 -1
  6. package/dist/core/index.js.map +1 -1
  7. package/dist/react/{chunk-DTRWUIDH.js → chunk-BIXAYYE4.js} +35 -5
  8. package/dist/react/{chunk-DTRWUIDH.js.map → chunk-BIXAYYE4.js.map} +1 -1
  9. package/dist/react/index.d.ts +1 -1
  10. package/dist/react/index.js +143 -10403
  11. package/dist/react/index.js.map +1 -1
  12. package/dist/react/websocket-7MZ3ENOC.js +9 -0
  13. package/package.json +2 -2
  14. package/dist/react/chunk-2QOYO3GF.js +0 -182
  15. package/dist/react/chunk-2QOYO3GF.js.map +0 -1
  16. package/dist/react/chunk-4WSYM746.js +0 -383
  17. package/dist/react/chunk-4WSYM746.js.map +0 -1
  18. package/dist/react/chunk-5XIRNUBL.js +0 -43
  19. package/dist/react/chunk-5XIRNUBL.js.map +0 -1
  20. package/dist/react/chunk-7JDOKZGQ.js +0 -172
  21. package/dist/react/chunk-7JDOKZGQ.js.map +0 -1
  22. package/dist/react/chunk-A5TI2FW3.js +0 -13
  23. package/dist/react/chunk-A5TI2FW3.js.map +0 -1
  24. package/dist/react/chunk-BJXCFDMF.js +0 -15
  25. package/dist/react/chunk-BJXCFDMF.js.map +0 -1
  26. package/dist/react/chunk-BUTF5RJU.js +0 -29
  27. package/dist/react/chunk-BUTF5RJU.js.map +0 -1
  28. package/dist/react/chunk-GFVCNWVT.js +0 -54
  29. package/dist/react/chunk-GFVCNWVT.js.map +0 -1
  30. package/dist/react/chunk-JT5EZZSL.js +0 -489
  31. package/dist/react/chunk-JT5EZZSL.js.map +0 -1
  32. package/dist/react/chunk-KJX5LOMN.js +0 -43
  33. package/dist/react/chunk-KJX5LOMN.js.map +0 -1
  34. package/dist/react/chunk-KLXK4V6G.js +0 -65
  35. package/dist/react/chunk-KLXK4V6G.js.map +0 -1
  36. package/dist/react/chunk-LJLMKEKI.js +0 -245
  37. package/dist/react/chunk-LJLMKEKI.js.map +0 -1
  38. package/dist/react/chunk-MIXAYX55.js +0 -147
  39. package/dist/react/chunk-RPNCWADG.js +0 -248
  40. package/dist/react/chunk-RPNCWADG.js.map +0 -1
  41. package/dist/react/chunk-S6RDMHHH.js +0 -47
  42. package/dist/react/chunk-S6RDMHHH.js.map +0 -1
  43. package/dist/react/chunk-U6RIOMF4.js +0 -893
  44. package/dist/react/chunk-U6RIOMF4.js.map +0 -1
  45. package/dist/react/chunk-WCRLJFBW.js +0 -5568
  46. package/dist/react/chunk-WCRLJFBW.js.map +0 -1
  47. package/dist/react/chunk-YF6S7S36.js +0 -588
  48. package/dist/react/chunk-YF6S7S36.js.map +0 -1
  49. package/dist/react/dist-es-5WYA7CWK.js +0 -379
  50. package/dist/react/dist-es-5WYA7CWK.js.map +0 -1
  51. package/dist/react/dist-es-CR5AOOCO.js +0 -333
  52. package/dist/react/dist-es-CR5AOOCO.js.map +0 -1
  53. package/dist/react/dist-es-KZ3GLAJI.js +0 -494
  54. package/dist/react/dist-es-KZ3GLAJI.js.map +0 -1
  55. package/dist/react/dist-es-R4TRTT45.js +0 -22
  56. package/dist/react/dist-es-R4TRTT45.js.map +0 -1
  57. package/dist/react/dist-es-SKDPAJEW.js +0 -169
  58. package/dist/react/dist-es-SKDPAJEW.js.map +0 -1
  59. package/dist/react/dist-es-TOHBZNTZ.js +0 -71
  60. package/dist/react/dist-es-TOHBZNTZ.js.map +0 -1
  61. package/dist/react/dist-es-XNAC47MK.js +0 -90
  62. package/dist/react/dist-es-XNAC47MK.js.map +0 -1
  63. package/dist/react/event-streams-WAZW4P3K.js +0 -277
  64. package/dist/react/event-streams-WAZW4P3K.js.map +0 -1
  65. package/dist/react/loadSso-KXVD6CBM.js +0 -556
  66. package/dist/react/loadSso-KXVD6CBM.js.map +0 -1
  67. package/dist/react/service.config-I7RKP6FE.js +0 -14
  68. package/dist/react/service.config-I7RKP6FE.js.map +0 -1
  69. package/dist/react/signin-SEY3FDQ5.js +0 -653
  70. package/dist/react/signin-SEY3FDQ5.js.map +0 -1
  71. package/dist/react/sso-oidc-REODVHH5.js +0 -786
  72. package/dist/react/sso-oidc-REODVHH5.js.map +0 -1
  73. package/dist/react/sts-I3M4QP37.js +0 -3948
  74. package/dist/react/sts-I3M4QP37.js.map +0 -1
  75. package/dist/react/websocket-OSLLJSNO.js +0 -10
  76. package/dist/react/websocket-OSLLJSNO.js.map +0 -1
  77. /package/dist/react/{chunk-MIXAYX55.js.map → websocket-7MZ3ENOC.js.map} +0 -0
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { Entity as Entity$1, EntitySchemaMap as EntitySchemaMap$1 } from '@monorise/base';
2
3
 
3
4
  type WhereOperator = {
4
5
  $eq: string | number | boolean;
@@ -421,4 +422,55 @@ declare const createEntityConfig: <T extends Entity, B extends z.ZodRawShape, C
421
422
  };
422
423
  declare const createMutualConfig: <MD extends z.ZodRawShape>(config: MutualConfig<MD>) => MutualConfig<MD>;
423
424
 
424
- export { type AdjustmentCondition, type AdjustmentConditionFn, type CreatedEntity, type DraftEntity, Entity, type EntitySchemaMap, type MonoriseEntityConfig, type MutualConfig, type NumericFields, type UpdateCondition, type UpdateConditionFn, type WhereClause, type WhereConditions, type WhereOperator, createEntityConfig, createMutualConfig };
425
+ type TransactionCreateEntity<T extends Entity$1 = Entity$1> = {
426
+ operation: 'createEntity';
427
+ entityType: T;
428
+ entityId?: string;
429
+ payload: EntitySchemaMap$1[T];
430
+ };
431
+ type TransactionUpdateEntity<T extends Entity$1 = Entity$1> = {
432
+ operation: 'updateEntity';
433
+ entityType: T;
434
+ entityId: string;
435
+ payload: Partial<EntitySchemaMap$1[T]>;
436
+ accountId?: string;
437
+ condition?: string;
438
+ };
439
+ type TransactionAdjustEntity<T extends Entity$1 = Entity$1> = {
440
+ operation: 'adjustEntity';
441
+ entityType: T;
442
+ entityId: string;
443
+ adjustments: Record<string, number>;
444
+ accountId?: string;
445
+ condition?: string;
446
+ };
447
+ type TransactionDeleteEntity<T extends Entity$1 = Entity$1> = {
448
+ operation: 'deleteEntity';
449
+ entityType: T;
450
+ entityId: string;
451
+ };
452
+ type TransactionOperation = TransactionCreateEntity | TransactionUpdateEntity | TransactionAdjustEntity | TransactionDeleteEntity;
453
+ type TransactionResultEntry = {
454
+ operation: string;
455
+ entityType: Entity$1;
456
+ entityId: string;
457
+ data?: Record<string, unknown>;
458
+ };
459
+ type TransactionResult = {
460
+ results: TransactionResultEntry[];
461
+ };
462
+
463
+ declare const transactional: {
464
+ createEntity: <T extends Entity$1>(entityType: T, payload: EntitySchemaMap$1[T] & {
465
+ entityId?: string;
466
+ }) => TransactionCreateEntity<T>;
467
+ updateEntity: <T extends Entity$1>(entityType: T, entityId: string, payload: Partial<EntitySchemaMap$1[T]> & {
468
+ $condition?: string;
469
+ }) => TransactionUpdateEntity<T>;
470
+ adjustEntity: <T extends Entity$1>(entityType: T, entityId: string, adjustments: Record<string, number> & {
471
+ $condition?: string;
472
+ }) => TransactionAdjustEntity<T>;
473
+ deleteEntity: <T extends Entity$1>(entityType: T, entityId: string) => TransactionDeleteEntity<T>;
474
+ };
475
+
476
+ export { type AdjustmentCondition, type AdjustmentConditionFn, type CreatedEntity, type DraftEntity, Entity, type EntitySchemaMap, type MonoriseEntityConfig, type MutualConfig, type NumericFields, type TransactionAdjustEntity, type TransactionCreateEntity, type TransactionDeleteEntity, type TransactionOperation, type TransactionResult, type TransactionResultEntry, type TransactionUpdateEntity, type UpdateCondition, type UpdateConditionFn, type WhereClause, type WhereConditions, type WhereOperator, createEntityConfig, createMutualConfig, transactional };
@@ -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
 
21
33
  // types/monorise.type.ts
22
34
  var Entity = /* @__PURE__ */ ((Entity2) => {
@@ -38,9 +50,45 @@ var createEntityConfig = (config) => __spreadProps(__spreadValues({}, config), {
38
50
  finalSchema: makeSchema(config)
39
51
  });
40
52
  var createMutualConfig = (config) => config;
53
+
54
+ // transactional.ts
55
+ var transactional = {
56
+ createEntity: (entityType, payload) => {
57
+ const _a = payload, { entityId } = _a, rest = __objRest(_a, ["entityId"]);
58
+ return __spreadValues({
59
+ operation: "createEntity",
60
+ entityType,
61
+ payload: rest
62
+ }, entityId && { entityId });
63
+ },
64
+ updateEntity: (entityType, entityId, payload) => {
65
+ const _a = payload, { $condition } = _a, rest = __objRest(_a, ["$condition"]);
66
+ return __spreadValues({
67
+ operation: "updateEntity",
68
+ entityType,
69
+ entityId,
70
+ payload: rest
71
+ }, $condition && { condition: $condition });
72
+ },
73
+ adjustEntity: (entityType, entityId, adjustments) => {
74
+ const _a = adjustments, { $condition } = _a, rest = __objRest(_a, ["$condition"]);
75
+ return __spreadValues({
76
+ operation: "adjustEntity",
77
+ entityType,
78
+ entityId,
79
+ adjustments: rest
80
+ }, $condition && { condition: $condition });
81
+ },
82
+ deleteEntity: (entityType, entityId) => ({
83
+ operation: "deleteEntity",
84
+ entityType,
85
+ entityId
86
+ })
87
+ };
41
88
  export {
42
89
  Entity,
43
90
  createEntityConfig,
44
- createMutualConfig
91
+ createMutualConfig,
92
+ transactional
45
93
  };
46
94
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../types/monorise.type.ts","../utils/index.ts"],"sourcesContent":["import type { z } from 'zod';\nimport type { WhereConditions } from './conditions.type';\n\nexport enum Entity {}\n\nexport interface EntitySchemaMap {\n [key: string]: Record<string, any>;\n}\n\n/**\n * @description Configuration for a mutual relationship between two entities.\n * Defines the schema for mutualData validation. Define once, reference from both entity configs.\n *\n * @example\n * ```ts\n * const enrollmentMutual = createMutualConfig({\n * entities: [Entity.STUDENT, Entity.COURSE],\n * mutualDataSchema: z.object({\n * role: z.enum(['student', 'auditor']),\n * enrolledAt: z.string().datetime(),\n * }),\n * });\n * ```\n */\nexport interface MutualConfig<\n MD extends z.ZodRawShape = z.ZodRawShape,\n> {\n entities: [Entity, Entity];\n mutualDataSchema: z.ZodObject<MD>;\n}\n\nexport type DraftEntity<T extends Entity = Entity> =\n T extends keyof EntitySchemaMap ? EntitySchemaMap[T] : never;\n\nexport type NumericFields<T> = {\n [K in keyof T as T[K] extends number ? K : never]?: number;\n};\n\nexport type CreatedEntity<T extends Entity = Entity> = {\n entityId: string;\n entityType: string;\n data: T extends keyof EntitySchemaMap ? EntitySchemaMap[T] : never;\n createdAt: string;\n updatedAt: string;\n};\n\n/**\n * @description Configuration for a monorise entity, a shared configuration that is used across frontend and backend.\n * This can be served as a single source of truth for the entity configuration.\n * It is used to define the schema, and mutual relationships between this entity and other entities.\n *\n * @example\n * ```ts\n * const baseSchema = z.object({\n * title: z.string(),\n * }).partial();\n *\n * const createSchema = baseSchema.extend({\n * title: z.string(),\n * })\n *\n * const config = createEntityConfig({\n * name: 'learner',\n * displayName: 'Learner',\n * baseSchema,\n * createSchema,\n * });\n * ```\n */\nexport interface MonoriseEntityConfig<\n T extends Entity = Entity,\n B extends z.ZodRawShape = z.ZodRawShape,\n C extends z.ZodRawShape = z.ZodRawShape,\n M extends z.ZodRawShape = z.ZodRawShape,\n CO extends z.ZodObject<C> | undefined = undefined,\n MO extends z.ZodObject<M> | undefined = undefined,\n> {\n /**\n * @description Name of the entity. Must be in **lower-kebab-case** and **unique** across all entities\n *\n * @example `learner`, `learning-activity`\n */\n name: string | T;\n\n /**\n * @description Display name of the entity. It is not required to be unique\n */\n displayName: string;\n\n /**\n * @description (DEPRECATED) Use `uniqueFields` instead, Monorise should not handle auth mechanism\n * @description (Optional) Specify the authentication method to be used for the entity\n */\n authMethod?: {\n /**\n * @description Authentication method using email\n *\n * Note: The email used for authentication is unique per entity.\n * For example, if `johndoe@mail.com` is used for `learner` entity,\n * it can be reused again on `admin` entity. However, the same email\n * address cannot be repeated for the same entity.\n */\n email: {\n /**\n * @description Number of milliseconds before the token expires\n */\n tokenExpiresIn: number;\n };\n };\n\n /**\n * @description Base schema for the entity\n */\n baseSchema: z.ZodObject<B>;\n\n /**\n * @description Minimal schema required to create an entity\n */\n createSchema?: CO;\n searchableFields?: (keyof B)[];\n uniqueFields?: (keyof B)[];\n\n /**\n * @description Define mutual relationship of this entity with other entities\n */\n mutual?: {\n /**\n * @description Subscribes to update events from specified entities in the array.\n * These events will be used to run prejoin processor.\n */\n subscribes?: { entityType: Entity }[];\n /**\n * @description Virtual schema for mutual relationship. The schema is only used for validation purpose, but these fields are not stored in the database\n */\n mutualSchema: MO;\n\n /**\n * @description Keys of `mutualFields` are fields defined in `mutualSchema`.\n * Each field is a mutual relationship between this entity and another entity.\n */\n mutualFields: {\n [key: string]: {\n entityType: Entity;\n toMutualIds?: (context: any) => string[];\n /**\n * @description (Optional) Custom function to process `mutualData`. If not provided, `mutualData` will be empty.\n *\n * @returns the final state of `mutualData` to be stored in the mutual record. Must be an object.\n */\n mutualDataProcessor?: (\n mutualIds: string[],\n currentMutual: any,\n customContext?: Record<string, any>,\n ) => Record<string, any>;\n /**\n * @description (Optional) Reference to a mutual config created by `createMutualConfig`.\n * Provides mutualData schema validation for create/update operations on this mutual relationship.\n */\n mutual?: MutualConfig;\n };\n };\n\n /**\n * @description (Optional) Better known as tree processor\n * This is used to prejoin entities that are not directly related as mutual.\n * For example, if `learner` entity is related to `course` entity, and `course` entity is related to `module` entity,\n * prejoins can be used to join `learner` and `module` entities.\n * With this, the `learner` entity can access the `module` entity without having to go through the `course` entity,\n * hence reducing the number of queries.\n *\n * DynamoDB best practices: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-general-normalization.html\n *\n */\n prejoins?: {\n mutualField: string;\n targetEntityType: Entity;\n entityPaths: {\n skipCache?: boolean;\n entityType: Entity;\n processor?: (items: any[], context: Record<string, any>) => any;\n }[];\n }[];\n };\n /**\n * Use this function to perform side effects on the final schema for example refine/superRefine the schema\n *\n * @param schema The final schema of the entity (the combination of `baseSchema`/`createSchema` and `mutualSchema` if specified)\n * @returns void\n *\n * @example\n * ```ts\n * effect: (schema) => {\n * schema.refine(\n * // refinement logic here\n * )\n * }\n */\n effect?: (\n schema: z.ZodObject<z.ZodRawShape>,\n ) => z.ZodEffects<z.ZodObject<z.ZodRawShape>>;\n\n /**\n * @description (Optional) Use tags to create additional access patterns for the entity.\n * Time complexity for retrieving tagged entities is O(1).\n *\n * The following configuration will create a tag named `region` for the `organization` entity grouped by `region`.\n * You would then be able to retrieve all organizations in a specific region by:\n * GET `/core/tag/organization/region?group={region_name}`\n *\n * @example\n *\n * ```ts\n * {\n * name: 'organization',\n * tags: [\n * {\n * name: 'region',\n * processor: (entity) => {\n * return [\n * {\n * group: entity.data.region\n * }\n * ]\n * },\n * }\n * ]\n * }\n * ```\n *\n * @description\n *\n * The following configuration will create a tag named `dob` for the `user` entity sorted by `dob`.\n * You would then be able to retrieve all users sorted by `dob` by:\n * GET `/core/tag/user/dob?start=2000-01-01&end=2020-12-31`\n *\n * @example\n * ```ts\n * {\n * name: 'user',\n * tags: [\n * {\n * name: 'dob',\n * processor: (entity) => {\n * return [\n * {\n * sortValue: entity.data.dob\n * }\n * ]\n * },\n * }\n * ]\n * }\n * ```\n */\n tags?: {\n name: string;\n processor: (entity: { entityId: string; entityType: string; data: Record<string, any>; createdAt: string; updatedAt: string }) => {\n group?: string;\n sortValue?: string;\n }[];\n }[];\n\n /**\n * @description (Optional) Constraints for `adjustEntity` operations.\n * When adjusting numeric fields, these constraints are enforced at the database level.\n * If an adjustment would violate a constraint, the operation is rejected.\n *\n * @deprecated Use `conditions` instead. Will be removed in a future version.\n *\n * @example\n * ```ts\n * {\n * adjustmentConstraints: {\n * // Static: same for all entities of this type\n * balance: { min: 0 },\n * credits: { min: 0, max: 10000 },\n *\n * // Dynamic: reads constraint value from entity's own data\n * balance: { minField: 'minBalance' },\n * credits: { min: 0, maxField: 'creditLimit' },\n * }\n * }\n * ```\n */\n adjustmentConstraints?: {\n [fieldName: string]: {\n /** Static minimum value */\n min?: number;\n /** Static maximum value */\n max?: number;\n /** Field name on the entity whose value is used as the minimum (must be a numeric field) */\n minField?: keyof {\n [K in keyof B as B[K] extends z.ZodNumber | z.ZodOptional<z.ZodNumber> ? K : never]: K;\n } extends never ? string : keyof {\n [K in keyof B as B[K] extends z.ZodNumber | z.ZodOptional<z.ZodNumber> ? K : never]: K;\n };\n /** Field name on the entity whose value is used as the maximum (must be a numeric field) */\n maxField?: keyof {\n [K in keyof B as B[K] extends z.ZodNumber | z.ZodOptional<z.ZodNumber> ? K : never]: K;\n } extends never ? string : keyof {\n [K in keyof B as B[K] extends z.ZodNumber | z.ZodOptional<z.ZodNumber> ? K : never]: K;\n };\n };\n };\n\n /**\n * @description Named conditions for adjustEntity operations.\n * Each condition is either a static `WhereConditions` object or a function\n * `(data, adjustments) => WhereConditions` that receives the entity's current data\n * and the adjustment deltas.\n *\n * When defined, `$condition` is **required** in the adjustEntity request body.\n * The client sends a condition name (string), the server resolves it to a\n * DynamoDB ConditionExpression.\n *\n * @example\n * ```ts\n * {\n * adjustmentConditions: {\n * withdraw: (data, adjustments) => ({\n * balance: { $gte: (data.minBalance ?? 0) + Math.abs(adjustments?.balance ?? 0) },\n * }),\n * deposit: (data, adjustments) => ({\n * balance: { $lte: 1000000 - (adjustments.balance ?? 0) },\n * }),\n * }\n * }\n * ```\n */\n adjustmentConditions?: {\n [conditionName: string]:\n | WhereConditions\n | ((\n data: Partial<z.infer<z.ZodObject<B>>>,\n adjustments: Record<string, number>,\n ) => WhereConditions);\n };\n\n /**\n * @description Named conditions for updateEntity operations.\n * Each condition is either a static `WhereConditions` object or a function\n * `(data) => WhereConditions` that receives the entity's current data.\n *\n * `$condition` is always **optional** for updateEntity.\n * The client sends a condition name (string), the server resolves it to a\n * DynamoDB ConditionExpression. Replaces raw `$where` (deprecated).\n *\n * @example\n * ```ts\n * {\n * updateConditions: {\n * publish: { status: { $eq: 'draft' } },\n * archive: (data) => ({ status: { $ne: 'archived' } }),\n * }\n * }\n * ```\n */\n updateConditions?: {\n [conditionName: string]:\n | WhereConditions\n | ((data: Partial<z.infer<z.ZodObject<B>>>) => WhereConditions);\n };\n}\n","import type { Entity, MonoriseEntityConfig, MutualConfig } from '../types/monorise.type';\nimport { z } from 'zod';\n\nfunction makeSchema<\n T extends Entity,\n B extends z.ZodRawShape,\n C extends z.ZodRawShape,\n M extends z.ZodRawShape,\n CO extends z.ZodObject<C> | undefined = undefined,\n MO extends z.ZodObject<M> | undefined = undefined,\n>(config: MonoriseEntityConfig<T, B, C, M, CO, MO>) {\n const { baseSchema, createSchema, mutual, effect } = config;\n const { mutualSchema } = mutual || {};\n\n type FinalSchemaType = CO extends z.AnyZodObject\n ? MO extends z.AnyZodObject\n ? z.ZodObject<B & CO['shape'] & MO['shape']>\n : z.ZodObject<B & CO['shape']>\n : MO extends z.AnyZodObject\n ? z.ZodObject<B & MO['shape']>\n : z.ZodObject<B>;\n\n const finalSchema = z.object({\n ...baseSchema.shape,\n ...createSchema?.shape,\n ...mutualSchema?.shape,\n }) as FinalSchemaType;\n\n if (effect) {\n return effect(finalSchema) as z.ZodEffects<FinalSchemaType>;\n }\n\n return finalSchema;\n}\n\nconst createEntityConfig = <\n T extends Entity,\n B extends z.ZodRawShape,\n C extends z.ZodRawShape,\n M extends z.ZodRawShape,\n CO extends z.ZodObject<C> | undefined = undefined,\n MO extends z.ZodObject<M> | undefined = undefined,\n>(\n config: MonoriseEntityConfig<T, B, C, M, CO, MO>,\n) => ({\n ...config,\n finalSchema: makeSchema(config),\n});\n\nconst createMutualConfig = <MD extends z.ZodRawShape>(\n config: MutualConfig<MD>,\n) => config;\n\nexport { createEntityConfig, createMutualConfig };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAGO,IAAK,SAAL,kBAAKA,YAAL;AAAK,SAAAA;AAAA,GAAA;;;ACFZ,SAAS,SAAS;AAElB,SAAS,WAOP,QAAkD;AAClD,QAAM,EAAE,YAAY,cAAc,QAAQ,OAAO,IAAI;AACrD,QAAM,EAAE,aAAa,IAAI,UAAU,CAAC;AAUpC,QAAM,cAAc,EAAE,OAAO,iDACxB,WAAW,QACX,6CAAc,QACd,6CAAc,MAClB;AAED,MAAI,QAAQ;AACV,WAAO,OAAO,WAAW;AAAA,EAC3B;AAEA,SAAO;AACT;AAEA,IAAM,qBAAqB,CAQzB,WACI,iCACD,SADC;AAAA,EAEJ,aAAa,WAAW,MAAM;AAChC;AAEA,IAAM,qBAAqB,CACzB,WACG;","names":["Entity"]}
1
+ {"version":3,"sources":["../types/monorise.type.ts","../utils/index.ts","../transactional.ts"],"sourcesContent":["import type { z } from 'zod';\nimport type { WhereConditions } from './conditions.type';\n\nexport enum Entity {}\n\nexport interface EntitySchemaMap {\n [key: string]: Record<string, any>;\n}\n\n/**\n * @description Configuration for a mutual relationship between two entities.\n * Defines the schema for mutualData validation. Define once, reference from both entity configs.\n *\n * @example\n * ```ts\n * const enrollmentMutual = createMutualConfig({\n * entities: [Entity.STUDENT, Entity.COURSE],\n * mutualDataSchema: z.object({\n * role: z.enum(['student', 'auditor']),\n * enrolledAt: z.string().datetime(),\n * }),\n * });\n * ```\n */\nexport interface MutualConfig<\n MD extends z.ZodRawShape = z.ZodRawShape,\n> {\n entities: [Entity, Entity];\n mutualDataSchema: z.ZodObject<MD>;\n}\n\nexport type DraftEntity<T extends Entity = Entity> =\n T extends keyof EntitySchemaMap ? EntitySchemaMap[T] : never;\n\nexport type NumericFields<T> = {\n [K in keyof T as T[K] extends number ? K : never]?: number;\n};\n\nexport type CreatedEntity<T extends Entity = Entity> = {\n entityId: string;\n entityType: string;\n data: T extends keyof EntitySchemaMap ? EntitySchemaMap[T] : never;\n createdAt: string;\n updatedAt: string;\n};\n\n/**\n * @description Configuration for a monorise entity, a shared configuration that is used across frontend and backend.\n * This can be served as a single source of truth for the entity configuration.\n * It is used to define the schema, and mutual relationships between this entity and other entities.\n *\n * @example\n * ```ts\n * const baseSchema = z.object({\n * title: z.string(),\n * }).partial();\n *\n * const createSchema = baseSchema.extend({\n * title: z.string(),\n * })\n *\n * const config = createEntityConfig({\n * name: 'learner',\n * displayName: 'Learner',\n * baseSchema,\n * createSchema,\n * });\n * ```\n */\nexport interface MonoriseEntityConfig<\n T extends Entity = Entity,\n B extends z.ZodRawShape = z.ZodRawShape,\n C extends z.ZodRawShape = z.ZodRawShape,\n M extends z.ZodRawShape = z.ZodRawShape,\n CO extends z.ZodObject<C> | undefined = undefined,\n MO extends z.ZodObject<M> | undefined = undefined,\n> {\n /**\n * @description Name of the entity. Must be in **lower-kebab-case** and **unique** across all entities\n *\n * @example `learner`, `learning-activity`\n */\n name: string | T;\n\n /**\n * @description Display name of the entity. It is not required to be unique\n */\n displayName: string;\n\n /**\n * @description (DEPRECATED) Use `uniqueFields` instead, Monorise should not handle auth mechanism\n * @description (Optional) Specify the authentication method to be used for the entity\n */\n authMethod?: {\n /**\n * @description Authentication method using email\n *\n * Note: The email used for authentication is unique per entity.\n * For example, if `johndoe@mail.com` is used for `learner` entity,\n * it can be reused again on `admin` entity. However, the same email\n * address cannot be repeated for the same entity.\n */\n email: {\n /**\n * @description Number of milliseconds before the token expires\n */\n tokenExpiresIn: number;\n };\n };\n\n /**\n * @description Base schema for the entity\n */\n baseSchema: z.ZodObject<B>;\n\n /**\n * @description Minimal schema required to create an entity\n */\n createSchema?: CO;\n searchableFields?: (keyof B)[];\n uniqueFields?: (keyof B)[];\n\n /**\n * @description Define mutual relationship of this entity with other entities\n */\n mutual?: {\n /**\n * @description Subscribes to update events from specified entities in the array.\n * These events will be used to run prejoin processor.\n */\n subscribes?: { entityType: Entity }[];\n /**\n * @description Virtual schema for mutual relationship. The schema is only used for validation purpose, but these fields are not stored in the database\n */\n mutualSchema: MO;\n\n /**\n * @description Keys of `mutualFields` are fields defined in `mutualSchema`.\n * Each field is a mutual relationship between this entity and another entity.\n */\n mutualFields: {\n [key: string]: {\n entityType: Entity;\n toMutualIds?: (context: any) => string[];\n /**\n * @description (Optional) Custom function to process `mutualData`. If not provided, `mutualData` will be empty.\n *\n * @returns the final state of `mutualData` to be stored in the mutual record. Must be an object.\n */\n mutualDataProcessor?: (\n mutualIds: string[],\n currentMutual: any,\n customContext?: Record<string, any>,\n ) => Record<string, any>;\n /**\n * @description (Optional) Reference to a mutual config created by `createMutualConfig`.\n * Provides mutualData schema validation for create/update operations on this mutual relationship.\n */\n mutual?: MutualConfig;\n };\n };\n\n /**\n * @description (Optional) Better known as tree processor\n * This is used to prejoin entities that are not directly related as mutual.\n * For example, if `learner` entity is related to `course` entity, and `course` entity is related to `module` entity,\n * prejoins can be used to join `learner` and `module` entities.\n * With this, the `learner` entity can access the `module` entity without having to go through the `course` entity,\n * hence reducing the number of queries.\n *\n * DynamoDB best practices: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-general-normalization.html\n *\n */\n prejoins?: {\n mutualField: string;\n targetEntityType: Entity;\n entityPaths: {\n skipCache?: boolean;\n entityType: Entity;\n processor?: (items: any[], context: Record<string, any>) => any;\n }[];\n }[];\n };\n /**\n * Use this function to perform side effects on the final schema for example refine/superRefine the schema\n *\n * @param schema The final schema of the entity (the combination of `baseSchema`/`createSchema` and `mutualSchema` if specified)\n * @returns void\n *\n * @example\n * ```ts\n * effect: (schema) => {\n * schema.refine(\n * // refinement logic here\n * )\n * }\n */\n effect?: (\n schema: z.ZodObject<z.ZodRawShape>,\n ) => z.ZodEffects<z.ZodObject<z.ZodRawShape>>;\n\n /**\n * @description (Optional) Use tags to create additional access patterns for the entity.\n * Time complexity for retrieving tagged entities is O(1).\n *\n * The following configuration will create a tag named `region` for the `organization` entity grouped by `region`.\n * You would then be able to retrieve all organizations in a specific region by:\n * GET `/core/tag/organization/region?group={region_name}`\n *\n * @example\n *\n * ```ts\n * {\n * name: 'organization',\n * tags: [\n * {\n * name: 'region',\n * processor: (entity) => {\n * return [\n * {\n * group: entity.data.region\n * }\n * ]\n * },\n * }\n * ]\n * }\n * ```\n *\n * @description\n *\n * The following configuration will create a tag named `dob` for the `user` entity sorted by `dob`.\n * You would then be able to retrieve all users sorted by `dob` by:\n * GET `/core/tag/user/dob?start=2000-01-01&end=2020-12-31`\n *\n * @example\n * ```ts\n * {\n * name: 'user',\n * tags: [\n * {\n * name: 'dob',\n * processor: (entity) => {\n * return [\n * {\n * sortValue: entity.data.dob\n * }\n * ]\n * },\n * }\n * ]\n * }\n * ```\n */\n tags?: {\n name: string;\n processor: (entity: { entityId: string; entityType: string; data: Record<string, any>; createdAt: string; updatedAt: string }) => {\n group?: string;\n sortValue?: string;\n }[];\n }[];\n\n /**\n * @description (Optional) Constraints for `adjustEntity` operations.\n * When adjusting numeric fields, these constraints are enforced at the database level.\n * If an adjustment would violate a constraint, the operation is rejected.\n *\n * @deprecated Use `conditions` instead. Will be removed in a future version.\n *\n * @example\n * ```ts\n * {\n * adjustmentConstraints: {\n * // Static: same for all entities of this type\n * balance: { min: 0 },\n * credits: { min: 0, max: 10000 },\n *\n * // Dynamic: reads constraint value from entity's own data\n * balance: { minField: 'minBalance' },\n * credits: { min: 0, maxField: 'creditLimit' },\n * }\n * }\n * ```\n */\n adjustmentConstraints?: {\n [fieldName: string]: {\n /** Static minimum value */\n min?: number;\n /** Static maximum value */\n max?: number;\n /** Field name on the entity whose value is used as the minimum (must be a numeric field) */\n minField?: keyof {\n [K in keyof B as B[K] extends z.ZodNumber | z.ZodOptional<z.ZodNumber> ? K : never]: K;\n } extends never ? string : keyof {\n [K in keyof B as B[K] extends z.ZodNumber | z.ZodOptional<z.ZodNumber> ? K : never]: K;\n };\n /** Field name on the entity whose value is used as the maximum (must be a numeric field) */\n maxField?: keyof {\n [K in keyof B as B[K] extends z.ZodNumber | z.ZodOptional<z.ZodNumber> ? K : never]: K;\n } extends never ? string : keyof {\n [K in keyof B as B[K] extends z.ZodNumber | z.ZodOptional<z.ZodNumber> ? K : never]: K;\n };\n };\n };\n\n /**\n * @description Named conditions for adjustEntity operations.\n * Each condition is either a static `WhereConditions` object or a function\n * `(data, adjustments) => WhereConditions` that receives the entity's current data\n * and the adjustment deltas.\n *\n * When defined, `$condition` is **required** in the adjustEntity request body.\n * The client sends a condition name (string), the server resolves it to a\n * DynamoDB ConditionExpression.\n *\n * @example\n * ```ts\n * {\n * adjustmentConditions: {\n * withdraw: (data, adjustments) => ({\n * balance: { $gte: (data.minBalance ?? 0) + Math.abs(adjustments?.balance ?? 0) },\n * }),\n * deposit: (data, adjustments) => ({\n * balance: { $lte: 1000000 - (adjustments.balance ?? 0) },\n * }),\n * }\n * }\n * ```\n */\n adjustmentConditions?: {\n [conditionName: string]:\n | WhereConditions\n | ((\n data: Partial<z.infer<z.ZodObject<B>>>,\n adjustments: Record<string, number>,\n ) => WhereConditions);\n };\n\n /**\n * @description Named conditions for updateEntity operations.\n * Each condition is either a static `WhereConditions` object or a function\n * `(data) => WhereConditions` that receives the entity's current data.\n *\n * `$condition` is always **optional** for updateEntity.\n * The client sends a condition name (string), the server resolves it to a\n * DynamoDB ConditionExpression. Replaces raw `$where` (deprecated).\n *\n * @example\n * ```ts\n * {\n * updateConditions: {\n * publish: { status: { $eq: 'draft' } },\n * archive: (data) => ({ status: { $ne: 'archived' } }),\n * }\n * }\n * ```\n */\n updateConditions?: {\n [conditionName: string]:\n | WhereConditions\n | ((data: Partial<z.infer<z.ZodObject<B>>>) => WhereConditions);\n };\n}\n","import type { Entity, MonoriseEntityConfig, MutualConfig } from '../types/monorise.type';\nimport { z } from 'zod';\n\nfunction makeSchema<\n T extends Entity,\n B extends z.ZodRawShape,\n C extends z.ZodRawShape,\n M extends z.ZodRawShape,\n CO extends z.ZodObject<C> | undefined = undefined,\n MO extends z.ZodObject<M> | undefined = undefined,\n>(config: MonoriseEntityConfig<T, B, C, M, CO, MO>) {\n const { baseSchema, createSchema, mutual, effect } = config;\n const { mutualSchema } = mutual || {};\n\n type FinalSchemaType = CO extends z.AnyZodObject\n ? MO extends z.AnyZodObject\n ? z.ZodObject<B & CO['shape'] & MO['shape']>\n : z.ZodObject<B & CO['shape']>\n : MO extends z.AnyZodObject\n ? z.ZodObject<B & MO['shape']>\n : z.ZodObject<B>;\n\n const finalSchema = z.object({\n ...baseSchema.shape,\n ...createSchema?.shape,\n ...mutualSchema?.shape,\n }) as FinalSchemaType;\n\n if (effect) {\n return effect(finalSchema) as z.ZodEffects<FinalSchemaType>;\n }\n\n return finalSchema;\n}\n\nconst createEntityConfig = <\n T extends Entity,\n B extends z.ZodRawShape,\n C extends z.ZodRawShape,\n M extends z.ZodRawShape,\n CO extends z.ZodObject<C> | undefined = undefined,\n MO extends z.ZodObject<M> | undefined = undefined,\n>(\n config: MonoriseEntityConfig<T, B, C, M, CO, MO>,\n) => ({\n ...config,\n finalSchema: makeSchema(config),\n});\n\nconst createMutualConfig = <MD extends z.ZodRawShape>(\n config: MutualConfig<MD>,\n) => config;\n\nexport { createEntityConfig, createMutualConfig };\n","import type { Entity as EntityType, EntitySchemaMap } from '@monorise/base';\nimport type {\n TransactionAdjustEntity,\n TransactionCreateEntity,\n TransactionDeleteEntity,\n TransactionOperation,\n TransactionUpdateEntity,\n} from './types/transaction.type';\n\nexport const transactional = {\n createEntity: <T extends EntityType>(\n entityType: T,\n payload: EntitySchemaMap[T] & { entityId?: string },\n ): TransactionCreateEntity<T> => {\n const { entityId, ...rest } = payload as EntitySchemaMap[T] & {\n entityId?: string;\n };\n return {\n operation: 'createEntity',\n entityType,\n payload: rest as EntitySchemaMap[T],\n ...(entityId && { entityId }),\n };\n },\n\n updateEntity: <T extends EntityType>(\n entityType: T,\n entityId: string,\n payload: Partial<EntitySchemaMap[T]> & { $condition?: string },\n ): TransactionUpdateEntity<T> => {\n const { $condition, ...rest } = payload as Partial<EntitySchemaMap[T]> & {\n $condition?: string;\n };\n return {\n operation: 'updateEntity',\n entityType,\n entityId,\n payload: rest as Partial<EntitySchemaMap[T]>,\n ...($condition && { condition: $condition }),\n };\n },\n\n adjustEntity: <T extends EntityType>(\n entityType: T,\n entityId: string,\n adjustments: Record<string, number> & { $condition?: string },\n ): TransactionAdjustEntity<T> => {\n const { $condition, ...rest } = adjustments;\n return {\n operation: 'adjustEntity',\n entityType,\n entityId,\n adjustments: rest,\n ...($condition && { condition: $condition }),\n };\n },\n\n deleteEntity: <T extends EntityType>(\n entityType: T,\n entityId: string,\n ): TransactionDeleteEntity<T> => ({\n operation: 'deleteEntity',\n entityType,\n entityId,\n }),\n};\n\nexport type { TransactionOperation };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGO,IAAK,SAAL,kBAAKA,YAAL;AAAK,SAAAA;AAAA,GAAA;;;ACFZ,SAAS,SAAS;AAElB,SAAS,WAOP,QAAkD;AAClD,QAAM,EAAE,YAAY,cAAc,QAAQ,OAAO,IAAI;AACrD,QAAM,EAAE,aAAa,IAAI,UAAU,CAAC;AAUpC,QAAM,cAAc,EAAE,OAAO,iDACxB,WAAW,QACX,6CAAc,QACd,6CAAc,MAClB;AAED,MAAI,QAAQ;AACV,WAAO,OAAO,WAAW;AAAA,EAC3B;AAEA,SAAO;AACT;AAEA,IAAM,qBAAqB,CAQzB,WACI,iCACD,SADC;AAAA,EAEJ,aAAa,WAAW,MAAM;AAChC;AAEA,IAAM,qBAAqB,CACzB,WACG;;;AC1CE,IAAM,gBAAgB;AAAA,EAC3B,cAAc,CACZ,YACA,YAC+B;AAC/B,UAA8B,cAAtB,WAdZ,IAckC,IAAT,iBAAS,IAAT,CAAb;AAGR,WAAO;AAAA,MACL,WAAW;AAAA,MACX;AAAA,MACA,SAAS;AAAA,OACL,YAAY,EAAE,SAAS;AAAA,EAE/B;AAAA,EAEA,cAAc,CACZ,YACA,UACA,YAC+B;AAC/B,UAAgC,cAAxB,aA9BZ,IA8BoC,IAAT,iBAAS,IAAT,CAAf;AAGR,WAAO;AAAA,MACL,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,SAAS;AAAA,OACL,cAAc,EAAE,WAAW,WAAW;AAAA,EAE9C;AAAA,EAEA,cAAc,CACZ,YACA,UACA,gBAC+B;AAC/B,UAAgC,kBAAxB,aA/CZ,IA+CoC,IAAT,iBAAS,IAAT,CAAf;AACR,WAAO;AAAA,MACL,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,aAAa;AAAA,OACT,cAAc,EAAE,WAAW,WAAW;AAAA,EAE9C;AAAA,EAEA,cAAc,CACZ,YACA,cACgC;AAAA,IAChC,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF;AACF;","names":["Entity"]}
@@ -1,4 +1,5 @@
1
- import { Entity as Entity$2, EntitySchemaMap, createEntityConfig, WhereConditions } from '../base/index';
1
+ import { Entity as Entity$2, EntitySchemaMap, createEntityConfig, WhereConditions, TransactionOperation, TransactionResult } from '../base/index';
2
+ export { transactional } from '../base/index';
2
3
  import * as hono from 'hono';
3
4
  import { Hono } from 'hono';
4
5
  import { DynamoDB, TransactWriteItemsInput, AttributeValue, TransactWriteItem, UpdateItemCommandInput } from '@aws-sdk/client-dynamodb';
@@ -4724,44 +4725,6 @@ declare class ListTagsController {
4724
4725
  }, hono_utils_http_status.ContentfulStatusCode, "json">>;
4725
4726
  }
4726
4727
 
4727
- type TransactionCreateEntity<T extends Entity$2 = Entity$2> = {
4728
- operation: 'createEntity';
4729
- entityType: T;
4730
- entityId?: string;
4731
- payload: EntitySchemaMap[T];
4732
- };
4733
- type TransactionUpdateEntity<T extends Entity$2 = Entity$2> = {
4734
- operation: 'updateEntity';
4735
- entityType: T;
4736
- entityId: string;
4737
- payload: Partial<EntitySchemaMap[T]>;
4738
- accountId?: string;
4739
- condition?: string;
4740
- };
4741
- type TransactionAdjustEntity<T extends Entity$2 = Entity$2> = {
4742
- operation: 'adjustEntity';
4743
- entityType: T;
4744
- entityId: string;
4745
- adjustments: Record<string, number>;
4746
- accountId?: string;
4747
- condition?: string;
4748
- };
4749
- type TransactionDeleteEntity<T extends Entity$2 = Entity$2> = {
4750
- operation: 'deleteEntity';
4751
- entityType: T;
4752
- entityId: string;
4753
- };
4754
- type TransactionOperation = TransactionCreateEntity | TransactionUpdateEntity | TransactionAdjustEntity | TransactionDeleteEntity;
4755
- type TransactionResultEntry = {
4756
- operation: string;
4757
- entityType: Entity$2;
4758
- entityId: string;
4759
- data?: Record<string, unknown>;
4760
- };
4761
- type TransactionResult = {
4762
- results: TransactionResultEntry[];
4763
- };
4764
-
4765
4728
  declare class TransactionService {
4766
4729
  private EntityConfig;
4767
4730
  private EmailAuthEnabledEntities;
@@ -4943,19 +4906,6 @@ declare const $default: (container: DependencyContainer) => (event: APIGatewayPr
4943
4906
  */
4944
4907
  declare const broadcast: (container: DependencyContainer) => (event: DynamoDBStreamEvent) => Promise<void>;
4945
4908
 
4946
- declare const transactional: {
4947
- createEntity: <T extends Entity$2>(entityType: T, payload: EntitySchemaMap[T] & {
4948
- entityId?: string;
4949
- }) => TransactionCreateEntity<T>;
4950
- updateEntity: <T extends Entity$2>(entityType: T, entityId: string, payload: Partial<EntitySchemaMap[T]> & {
4951
- $condition?: string;
4952
- }) => TransactionUpdateEntity<T>;
4953
- adjustEntity: <T extends Entity$2>(entityType: T, entityId: string, adjustments: Record<string, number> & {
4954
- $condition?: string;
4955
- }) => TransactionAdjustEntity<T>;
4956
- deleteEntity: <T extends Entity$2>(entityType: T, entityId: string) => TransactionDeleteEntity<T>;
4957
- };
4958
-
4959
4909
  declare class CoreFactory {
4960
4910
  private config;
4961
4911
  setupCommonRoutes: ReturnType<typeof setupCommonRoutes>;
@@ -4977,4 +4927,4 @@ declare class CoreFactory {
4977
4927
  });
4978
4928
  }
4979
4929
 
4980
- export { DependencyContainer, Entity$1 as Entity, EntityRepository, EntityService, Mutual, MutualRepository, MutualService, PROJECTION_EXPRESSION, StandardError, StandardErrorCode, TagRepository, TransactionService, WebSocketRepository, appHandler, handler$4 as createEntityProcessor, CoreFactory as default, handler$3 as mutualProcessor, handler$2 as prejoinProcessor, handler$1 as replicationProcessor, setupCommonRoutes, handler as tagProcessor, transactional, broadcast as wsBroadcast, connect as wsConnect, $default as wsDefault, disconnect as wsDisconnect };
4930
+ export { DependencyContainer, Entity$1 as Entity, EntityRepository, EntityService, Mutual, MutualRepository, MutualService, PROJECTION_EXPRESSION, StandardError, StandardErrorCode, TagRepository, TransactionService, WebSocketRepository, appHandler, handler$4 as createEntityProcessor, CoreFactory as default, handler$3 as mutualProcessor, handler$2 as prejoinProcessor, handler$1 as replicationProcessor, setupCommonRoutes, handler as tagProcessor, broadcast as wsBroadcast, connect as wsConnect, $default as wsDefault, disconnect as wsDisconnect };
@@ -9547,7 +9547,7 @@ var DependencyContainer = class {
9547
9547
  }
9548
9548
  };
9549
9549
 
9550
- // helpers/transactional.ts
9550
+ // ../base/transactional.ts
9551
9551
  var transactional = {
9552
9552
  createEntity: (entityType, payload) => {
9553
9553
  const _a = payload, { entityId } = _a, rest = __objRest(_a, ["entityId"]);