@monorise/base 1.0.0 → 1.0.2

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
@@ -1,4 +1,4 @@
1
- import { CreatedEntity, DraftEntity, Entity, EntitySchemaMap, MonoriseConfig } from './types/monorise.type';
1
+ import { CreatedEntity, DraftEntity, Entity, EntitySchemaMap, MonoriseEntityConfig } from './types/monorise.type';
2
2
  import { Mutual, MutualData, MutualDataMapping, MutualDataWithIndex } from './types/mutual.type';
3
- export { Entity, EntitySchemaMap, DraftEntity, CreatedEntity, MonoriseConfig, MutualDataWithIndex, MutualDataMapping, MutualData, Mutual, };
3
+ export { Entity, EntitySchemaMap, DraftEntity, CreatedEntity, MonoriseEntityConfig, MutualDataWithIndex, MutualDataMapping, MutualData, Mutual, };
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,WAAW,EACX,MAAM,EACN,eAAe,EACf,cAAc,EACf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,MAAM,EACN,eAAe,EACf,WAAW,EACX,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,MAAM,GACP,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,WAAW,EACX,MAAM,EACN,eAAe,EACf,oBAAoB,EACrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,MAAM,EACN,eAAe,EACf,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,MAAM,GACP,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { z } from 'zod';
1
2
  export declare enum Entity {
2
3
  }
3
4
  export interface EntitySchemaMap {
@@ -11,7 +12,194 @@ export type CreatedEntity<T extends Entity = Entity> = {
11
12
  createdAt: string;
12
13
  updatedAt: string;
13
14
  };
14
- export interface MonoriseConfig {
15
- configPath: string;
15
+ /**
16
+ * @description Configuration for a monorise entity, a shared configuration that is used across frontend and backend.
17
+ * This can be served as a single source of truth for the entity configuration.
18
+ * It is used to define the schema, and mutual relationships between this entity and other entities.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const baseSchema = z.object({
23
+ * title: z.string(),
24
+ * }).partial();
25
+ *
26
+ * const createSchema = baseSchema.extend({
27
+ * title: z.string(),
28
+ * })
29
+ *
30
+ * const config = createEntityConfig({
31
+ * name: 'learner',
32
+ * displayName: 'Learner',
33
+ * baseSchema,
34
+ * createSchema,
35
+ * });
36
+ * ```
37
+ */
38
+ export interface MonoriseEntityConfig<T extends Entity = Entity, B extends z.ZodRawShape = z.ZodRawShape, C extends z.ZodRawShape = z.ZodRawShape, M extends z.ZodRawShape = z.ZodRawShape, CO extends z.ZodObject<C> | undefined = undefined, MO extends z.ZodObject<M> | undefined = undefined> {
39
+ /**
40
+ * @description Name of the entity. Must be in **lower-kebab-case** and **unique** across all entities
41
+ *
42
+ * @example `learner`, `learning-activity`
43
+ */
44
+ name: string | T;
45
+ /**
46
+ * @description Display name of the entity. It is not required to be unique
47
+ */
48
+ displayName: string;
49
+ /**
50
+ * @description (Optional) Specify the authentication method to be used for the entity
51
+ */
52
+ authMethod?: {
53
+ /**
54
+ * @description Authentication method using email
55
+ *
56
+ * Note: The email used for authentication is unique per entity.
57
+ * For example, if `johndoe@mail.com` is used for `learner` entity,
58
+ * it can be reused again on `admin` entity. However, the same email
59
+ * address cannot be repeated for the same entity.
60
+ */
61
+ email: {
62
+ /**
63
+ * @description Number of milliseconds before the token expires
64
+ */
65
+ tokenExpiresIn: number;
66
+ };
67
+ };
68
+ /**
69
+ * @description Base schema for the entity
70
+ */
71
+ baseSchema: z.ZodObject<B>;
72
+ /**
73
+ * @description Minimal schema required to create an entity
74
+ */
75
+ createSchema?: CO;
76
+ searchableFields?: (keyof B)[];
77
+ /**
78
+ * @description Define mutual relationship of this entity with other entities
79
+ */
80
+ mutual?: {
81
+ /**
82
+ * @description Subscribes to update events from specified entities in the array.
83
+ * These events will be used to run prejoin processor.
84
+ */
85
+ subscribes?: {
86
+ entityType: Entity;
87
+ }[];
88
+ /**
89
+ * @description Virtual schema for mutual relationship. The schema is only used for validation purpose, but these fields are not stored in the database
90
+ */
91
+ mutualSchema: MO;
92
+ /**
93
+ * @description Keys of `mutualFields` are fields defined in `mutualSchema`.
94
+ * Each field is a mutual relationship between this entity and another entity.
95
+ */
96
+ mutualFields: {
97
+ [key: string]: {
98
+ entityType: Entity;
99
+ toMutualIds?: (context: any) => string[];
100
+ /**
101
+ * @description (Optional) Custom function to process `mutualData`. If not provided, `mutualData` will be empty.
102
+ *
103
+ * @returns the final state of `mutualData` to be stored in the mutual record. Must be an object.
104
+ */
105
+ mutualDataProcessor?: (mutualIds: string[], currentMutual: any, customContext?: Record<string, any>) => Record<string, any>;
106
+ };
107
+ };
108
+ /**
109
+ * @description (Optional) Better known as tree processor
110
+ * This is used to prejoin entities that are not directly related as mutual.
111
+ * For example, if `learner` entity is related to `course` entity, and `course` entity is related to `module` entity,
112
+ * prejoins can be used to join `learner` and `module` entities.
113
+ * With this, the `learner` entity can access the `module` entity without having to go through the `course` entity,
114
+ * hence reducing the number of queries.
115
+ *
116
+ * DynamoDB best practices: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-general-normalization.html
117
+ *
118
+ */
119
+ prejoins?: {
120
+ mutualField: string;
121
+ targetEntityType: Entity;
122
+ entityPaths: {
123
+ skipCache?: boolean;
124
+ entityType: Entity;
125
+ processor?: (items: any[], context: Record<string, any>) => any;
126
+ }[];
127
+ }[];
128
+ };
129
+ /**
130
+ * Use this function to perform side effects on the final schema for example refine/superRefine the schema
131
+ *
132
+ * @param schema The final schema of the entity (the combination of `baseSchema`/`createSchema` and `mutualSchema` if specified)
133
+ * @returns void
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * effect: (schema) => {
138
+ * schema.refine(
139
+ * // refinement logic here
140
+ * )
141
+ * }
142
+ */
143
+ effect?: (schema: CO extends z.AnyZodObject ? MO extends z.AnyZodObject ? z.ZodObject<MO['shape'] & CO['shape']> : CO : MO extends z.AnyZodObject ? z.ZodObject<MO['shape'] & B> : z.ZodObject<B>) => z.ZodEffects<CO extends z.AnyZodObject ? MO extends z.AnyZodObject ? z.ZodObject<MO['shape'] & CO['shape']> : CO : MO extends z.AnyZodObject ? z.ZodObject<MO['shape'] & B> : z.ZodObject<B>>;
144
+ /**
145
+ * @description (Optional) Use tags to create additional access patterns for the entity.
146
+ * Time complexity for retrieving tagged entities is O(1).
147
+ *
148
+ * The following configuration will create a tag named `region` for the `organization` entity grouped by `region`.
149
+ * You would then be able to retrieve all organizations in a specific region by:
150
+ * GET `/core/tag/organization/region?group={region_name}`
151
+ *
152
+ * @example
153
+ *
154
+ * ```ts
155
+ * {
156
+ * name: 'organization',
157
+ * tags: [
158
+ * {
159
+ * name: 'region',
160
+ * processor: (entity) => {
161
+ * return [
162
+ * {
163
+ * group: entity.data.region
164
+ * }
165
+ * ]
166
+ * },
167
+ * }
168
+ * ]
169
+ * }
170
+ * ```
171
+ *
172
+ * @description
173
+ *
174
+ * The following configuration will create a tag named `dob` for the `user` entity sorted by `dob`.
175
+ * You would then be able to retrieve all users sorted by `dob` by:
176
+ * GET `/core/tag/user/dob?start=2000-01-01&end=2020-12-31`
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * {
181
+ * name: 'user',
182
+ * tags: [
183
+ * {
184
+ * name: 'dob',
185
+ * processor: (entity) => {
186
+ * return [
187
+ * {
188
+ * sortValue: entity.data.dob
189
+ * }
190
+ * ]
191
+ * },
192
+ * }
193
+ * ]
194
+ * }
195
+ * ```
196
+ */
197
+ tags?: {
198
+ name: string;
199
+ processor: (entity: CreatedEntity<T>) => {
200
+ group?: string;
201
+ sortValue?: string;
202
+ }[];
203
+ }[];
16
204
  }
17
205
  //# sourceMappingURL=monorise.type.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"monorise.type.d.ts","sourceRoot":"","sources":["../../types/monorise.type.ts"],"names":[],"mappings":"AAAA,oBAAY,MAAM;CAAG;AAErB,MAAM,WAAW,eAAe;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACpC;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAC/C,CAAC,SAAS,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;AAE/D,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,CAAC,SAAS,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB"}
1
+ {"version":3,"file":"monorise.type.d.ts","sourceRoot":"","sources":["../../types/monorise.type.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"monorise.type.js","sourceRoot":"","sources":["../../types/monorise.type.ts"],"names":[],"mappings":";;;AAAA,IAAY,MAAS;AAArB,WAAY,MAAM;AAAE,CAAC,EAAT,MAAM,sBAAN,MAAM,QAAG"}
1
+ {"version":3,"file":"monorise.type.js","sourceRoot":"","sources":["../../types/monorise.type.ts"],"names":[],"mappings":";;;AAEA,IAAY,MAAS;AAArB,WAAY,MAAM;AAAE,CAAC,EAAT,MAAM,sBAAN,MAAM,QAAG"}
@@ -1,4 +1,4 @@
1
- import { Entity, type EntitySchemaMap } from './monorise.type';
1
+ import type { Entity, EntitySchemaMap } from './monorise.type';
2
2
  type MutualDataWithIndex = {
3
3
  index: number;
4
4
  };
@@ -1 +1 @@
1
- {"version":3,"file":"mutual.type.d.ts","sourceRoot":"","sources":["../../types/mutual.type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE/D,KAAK,mBAAmB,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,UAAU,iBAAiB;CAC1B;AAED,KAAK,UAAU,CACb,CAAC,SAAS,MAAM,EAChB,CAAC,SAAS,MAAM,IACd,CAAC,SAAS,MAAM,iBAAiB,GACjC,CAAC,SAAS,MAAM,iBAAiB,CAAC,CAAC,CAAC,GAClC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACvB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACrB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAExB,KAAK,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,CAAC,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,CAAC,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,CAAC,SAAS,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IACnE,UAAU,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"mutual.type.d.ts","sourceRoot":"","sources":["../../types/mutual.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE/D,KAAK,mBAAmB,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAGF,UAAU,iBAAiB;CAAG;AAE9B,KAAK,UAAU,CACb,CAAC,SAAS,MAAM,EAChB,CAAC,SAAS,MAAM,IACd,CAAC,SAAS,MAAM,iBAAiB,GACjC,CAAC,SAAS,MAAM,iBAAiB,CAAC,CAAC,CAAC,GAClC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACvB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACrB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAExB,KAAK,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,CAAC,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,CAAC,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,CAAC,SAAS,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IACnE,UAAU,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC"}
@@ -1,4 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- ;
4
3
  //# sourceMappingURL=mutual.type.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mutual.type.js","sourceRoot":"","sources":["../../types/mutual.type.ts"],"names":[],"mappings":";;AAOC,CAAC"}
1
+ {"version":3,"file":"mutual.type.js","sourceRoot":"","sources":["../../types/mutual.type.ts"],"names":[],"mappings":""}
package/index.ts CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  DraftEntity,
4
4
  Entity,
5
5
  EntitySchemaMap,
6
- MonoriseConfig,
6
+ MonoriseEntityConfig,
7
7
  } from './types/monorise.type';
8
8
 
9
9
  import {
@@ -18,7 +18,7 @@ export {
18
18
  EntitySchemaMap,
19
19
  DraftEntity,
20
20
  CreatedEntity,
21
- MonoriseConfig,
21
+ MonoriseEntityConfig,
22
22
  MutualDataWithIndex,
23
23
  MutualDataMapping,
24
24
  MutualData,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monorise/base",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,5 +12,8 @@
12
12
  },
13
13
  "keywords": [],
14
14
  "author": "",
15
- "license": "ISC"
15
+ "license": "ISC",
16
+ "dependencies": {
17
+ "zod": "^3.24.2"
18
+ }
16
19
  }
@@ -1,3 +1,5 @@
1
+ import type { z } from 'zod';
2
+
1
3
  export enum Entity {}
2
4
 
3
5
  export interface EntitySchemaMap {
@@ -15,6 +17,226 @@ export type CreatedEntity<T extends Entity = Entity> = {
15
17
  updatedAt: string;
16
18
  };
17
19
 
18
- export interface MonoriseConfig {
19
- configPath: string;
20
- }
20
+ /**
21
+ * @description Configuration for a monorise entity, a shared configuration that is used across frontend and backend.
22
+ * This can be served as a single source of truth for the entity configuration.
23
+ * It is used to define the schema, and mutual relationships between this entity and other entities.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const baseSchema = z.object({
28
+ * title: z.string(),
29
+ * }).partial();
30
+ *
31
+ * const createSchema = baseSchema.extend({
32
+ * title: z.string(),
33
+ * })
34
+ *
35
+ * const config = createEntityConfig({
36
+ * name: 'learner',
37
+ * displayName: 'Learner',
38
+ * baseSchema,
39
+ * createSchema,
40
+ * });
41
+ * ```
42
+ */
43
+ export interface MonoriseEntityConfig<
44
+ T extends Entity = Entity,
45
+ B extends z.ZodRawShape = z.ZodRawShape,
46
+ C extends z.ZodRawShape = z.ZodRawShape,
47
+ M extends z.ZodRawShape = z.ZodRawShape,
48
+ CO extends z.ZodObject<C> | undefined = undefined,
49
+ MO extends z.ZodObject<M> | undefined = undefined,
50
+ > {
51
+ /**
52
+ * @description Name of the entity. Must be in **lower-kebab-case** and **unique** across all entities
53
+ *
54
+ * @example `learner`, `learning-activity`
55
+ */
56
+ name: string | T;
57
+
58
+ /**
59
+ * @description Display name of the entity. It is not required to be unique
60
+ */
61
+ displayName: string;
62
+
63
+ /**
64
+ * @description (Optional) Specify the authentication method to be used for the entity
65
+ */
66
+ authMethod?: {
67
+ /**
68
+ * @description Authentication method using email
69
+ *
70
+ * Note: The email used for authentication is unique per entity.
71
+ * For example, if `johndoe@mail.com` is used for `learner` entity,
72
+ * it can be reused again on `admin` entity. However, the same email
73
+ * address cannot be repeated for the same entity.
74
+ */
75
+ email: {
76
+ /**
77
+ * @description Number of milliseconds before the token expires
78
+ */
79
+ tokenExpiresIn: number;
80
+ };
81
+ };
82
+
83
+ /**
84
+ * @description Base schema for the entity
85
+ */
86
+ baseSchema: z.ZodObject<B>;
87
+
88
+ /**
89
+ * @description Minimal schema required to create an entity
90
+ */
91
+ createSchema?: CO;
92
+ searchableFields?: (keyof B)[];
93
+
94
+ /**
95
+ * @description Define mutual relationship of this entity with other entities
96
+ */
97
+ mutual?: {
98
+ /**
99
+ * @description Subscribes to update events from specified entities in the array.
100
+ * These events will be used to run prejoin processor.
101
+ */
102
+ subscribes?: { entityType: Entity }[];
103
+ /**
104
+ * @description Virtual schema for mutual relationship. The schema is only used for validation purpose, but these fields are not stored in the database
105
+ */
106
+ mutualSchema: MO;
107
+
108
+ /**
109
+ * @description Keys of `mutualFields` are fields defined in `mutualSchema`.
110
+ * Each field is a mutual relationship between this entity and another entity.
111
+ */
112
+ mutualFields: {
113
+ [key: string]: {
114
+ entityType: Entity;
115
+ toMutualIds?: (context: any) => string[];
116
+ /**
117
+ * @description (Optional) Custom function to process `mutualData`. If not provided, `mutualData` will be empty.
118
+ *
119
+ * @returns the final state of `mutualData` to be stored in the mutual record. Must be an object.
120
+ */
121
+ mutualDataProcessor?: (
122
+ mutualIds: string[],
123
+ currentMutual: any,
124
+ customContext?: Record<string, any>,
125
+ ) => Record<string, any>;
126
+ };
127
+ };
128
+
129
+ /**
130
+ * @description (Optional) Better known as tree processor
131
+ * This is used to prejoin entities that are not directly related as mutual.
132
+ * For example, if `learner` entity is related to `course` entity, and `course` entity is related to `module` entity,
133
+ * prejoins can be used to join `learner` and `module` entities.
134
+ * With this, the `learner` entity can access the `module` entity without having to go through the `course` entity,
135
+ * hence reducing the number of queries.
136
+ *
137
+ * DynamoDB best practices: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-general-normalization.html
138
+ *
139
+ */
140
+ prejoins?: {
141
+ mutualField: string;
142
+ targetEntityType: Entity;
143
+ entityPaths: {
144
+ skipCache?: boolean;
145
+ entityType: Entity;
146
+ processor?: (items: any[], context: Record<string, any>) => any;
147
+ }[];
148
+ }[];
149
+ };
150
+ /**
151
+ * Use this function to perform side effects on the final schema for example refine/superRefine the schema
152
+ *
153
+ * @param schema The final schema of the entity (the combination of `baseSchema`/`createSchema` and `mutualSchema` if specified)
154
+ * @returns void
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * effect: (schema) => {
159
+ * schema.refine(
160
+ * // refinement logic here
161
+ * )
162
+ * }
163
+ */
164
+ effect?: (
165
+ schema: CO extends z.AnyZodObject
166
+ ? MO extends z.AnyZodObject
167
+ ? z.ZodObject<MO['shape'] & CO['shape']>
168
+ : CO
169
+ : MO extends z.AnyZodObject
170
+ ? z.ZodObject<MO['shape'] & B>
171
+ : z.ZodObject<B>,
172
+ ) => z.ZodEffects<
173
+ CO extends z.AnyZodObject
174
+ ? MO extends z.AnyZodObject
175
+ ? z.ZodObject<MO['shape'] & CO['shape']>
176
+ : CO
177
+ : MO extends z.AnyZodObject
178
+ ? z.ZodObject<MO['shape'] & B>
179
+ : z.ZodObject<B>
180
+ >;
181
+
182
+ /**
183
+ * @description (Optional) Use tags to create additional access patterns for the entity.
184
+ * Time complexity for retrieving tagged entities is O(1).
185
+ *
186
+ * The following configuration will create a tag named `region` for the `organization` entity grouped by `region`.
187
+ * You would then be able to retrieve all organizations in a specific region by:
188
+ * GET `/core/tag/organization/region?group={region_name}`
189
+ *
190
+ * @example
191
+ *
192
+ * ```ts
193
+ * {
194
+ * name: 'organization',
195
+ * tags: [
196
+ * {
197
+ * name: 'region',
198
+ * processor: (entity) => {
199
+ * return [
200
+ * {
201
+ * group: entity.data.region
202
+ * }
203
+ * ]
204
+ * },
205
+ * }
206
+ * ]
207
+ * }
208
+ * ```
209
+ *
210
+ * @description
211
+ *
212
+ * The following configuration will create a tag named `dob` for the `user` entity sorted by `dob`.
213
+ * You would then be able to retrieve all users sorted by `dob` by:
214
+ * GET `/core/tag/user/dob?start=2000-01-01&end=2020-12-31`
215
+ *
216
+ * @example
217
+ * ```ts
218
+ * {
219
+ * name: 'user',
220
+ * tags: [
221
+ * {
222
+ * name: 'dob',
223
+ * processor: (entity) => {
224
+ * return [
225
+ * {
226
+ * sortValue: entity.data.dob
227
+ * }
228
+ * ]
229
+ * },
230
+ * }
231
+ * ]
232
+ * }
233
+ * ```
234
+ */
235
+ tags?: {
236
+ name: string;
237
+ processor: (entity: CreatedEntity<T>) => {
238
+ group?: string;
239
+ sortValue?: string;
240
+ }[];
241
+ }[];
242
+ }
@@ -1,11 +1,11 @@
1
- import { Entity, type EntitySchemaMap } from './monorise.type';
1
+ import type { Entity, EntitySchemaMap } from './monorise.type';
2
2
 
3
3
  type MutualDataWithIndex = {
4
4
  index: number;
5
5
  };
6
6
 
7
- interface MutualDataMapping {
8
- };
7
+ // biome-ignore lint/suspicious/noEmptyInterface: To be extended via declare module
8
+ interface MutualDataMapping {}
9
9
 
10
10
  type MutualData<
11
11
  B extends Entity,