@t4h.framework/orm 0.2.0 → 0.4.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.
Files changed (60) hide show
  1. package/.ai/skills/framework-orm/SKILL.md +325 -0
  2. package/README.md +54 -0
  3. package/dist/activities/ORMGetSnapshotActivity.d.ts +3 -3
  4. package/dist/activities/ORMGetSnapshotActivity.d.ts.map +1 -1
  5. package/dist/activities/ORMGetSnapshotActivity.js.map +1 -1
  6. package/dist/claims/ORMClaim.d.ts +1 -1
  7. package/dist/claims/ORMClaim.d.ts.map +1 -1
  8. package/dist/constraints/__tests__/create-entity-metadata.d.ts +3 -0
  9. package/dist/constraints/__tests__/create-entity-metadata.d.ts.map +1 -0
  10. package/dist/constraints/__tests__/create-entity-metadata.js +10 -0
  11. package/dist/constraints/__tests__/create-entity-metadata.js.map +1 -0
  12. package/dist/constraints/apply-default-properties.d.ts +7 -0
  13. package/dist/constraints/apply-default-properties.d.ts.map +1 -0
  14. package/dist/constraints/apply-default-properties.js +16 -0
  15. package/dist/constraints/apply-default-properties.js.map +1 -0
  16. package/dist/constraints/assert-constraints.d.ts +7 -0
  17. package/dist/constraints/assert-constraints.d.ts.map +1 -0
  18. package/dist/constraints/assert-constraints.js +13 -0
  19. package/dist/constraints/assert-constraints.js.map +1 -0
  20. package/dist/constraints/assert-non-nullable-property-constraint.d.ts +7 -0
  21. package/dist/constraints/assert-non-nullable-property-constraint.d.ts.map +1 -0
  22. package/dist/constraints/assert-non-nullable-property-constraint.js +14 -0
  23. package/dist/constraints/assert-non-nullable-property-constraint.js.map +1 -0
  24. package/dist/constraints/assert-property-type-constraint.d.ts +7 -0
  25. package/dist/constraints/assert-property-type-constraint.d.ts.map +1 -0
  26. package/dist/constraints/assert-property-type-constraint.js +30 -0
  27. package/dist/constraints/assert-property-type-constraint.js.map +1 -0
  28. package/dist/constraints/assert-unique-constraint.d.ts +11 -0
  29. package/dist/constraints/assert-unique-constraint.d.ts.map +1 -0
  30. package/dist/constraints/assert-unique-constraint.js +41 -0
  31. package/dist/constraints/assert-unique-constraint.js.map +1 -0
  32. package/dist/decorators/Index.d.ts +6 -0
  33. package/dist/decorators/Index.d.ts.map +1 -0
  34. package/dist/decorators/Index.js +10 -0
  35. package/dist/decorators/Index.js.map +1 -0
  36. package/dist/decorators/Property.d.ts +1 -0
  37. package/dist/decorators/Property.d.ts.map +1 -1
  38. package/dist/decorators/Property.js +17 -1
  39. package/dist/decorators/Property.js.map +1 -1
  40. package/dist/decorators/metadata.d.ts +5 -2
  41. package/dist/decorators/metadata.d.ts.map +1 -1
  42. package/dist/decorators/metadata.js +1 -1
  43. package/dist/decorators/metadata.js.map +1 -1
  44. package/dist/errors/ConstraintError.d.ts +4 -0
  45. package/dist/errors/ConstraintError.d.ts.map +1 -0
  46. package/dist/errors/ConstraintError.js +7 -0
  47. package/dist/errors/ConstraintError.js.map +1 -0
  48. package/dist/models/ORM.d.ts +25 -5
  49. package/dist/models/ORM.d.ts.map +1 -1
  50. package/dist/models/ORM.js +42 -7
  51. package/dist/models/ORM.js.map +1 -1
  52. package/dist/models/Ref.d.ts +1 -1
  53. package/dist/models/Ref.d.ts.map +1 -1
  54. package/dist/models/Ref.js +11 -2
  55. package/dist/models/Ref.js.map +1 -1
  56. package/dist/orm.d.ts +3 -0
  57. package/dist/orm.d.ts.map +1 -1
  58. package/dist/orm.js +3 -0
  59. package/dist/orm.js.map +1 -1
  60. package/package.json +6 -4
@@ -0,0 +1,325 @@
1
+ ---
2
+ name: framework-orm
3
+ description: >-
4
+ Guides correct use of @t4h.framework/orm in T4H Framework workflows: entity
5
+ decorators (@Entity, @Property, @Index), the ORM model (create, find, findOne,
6
+ exists), Ref and RefCollection, query operators, constraint validation, ORM
7
+ activities, and ORMClaim wiring. Use when defining database entities, persisting
8
+ or querying rows in workflows, implementing ORMClaim providers, testing ORM
9
+ activities with Claim.run, or working in packages/orm.
10
+ ---
11
+
12
+ # @t4h.framework/orm
13
+
14
+ ORM activities, claim, and models for database operations within workflows. Package path: `framework/packages/orm`. Peer dependency: `@t4h.framework/core`.
15
+
16
+ Import from `src/orm.ts` only — do not reference unexported modules:
17
+
18
+ ```typescript
19
+ import {
20
+ Entity, Property, Index, ORM, Ref, RefCollection,
21
+ ORMClaim, ConstraintError,
22
+ ORMCreateActivity, ORMFindActivity, ORMFindOneActivity,
23
+ ORMGetSnapshotActivity, ORMUpdateActivity, ORMRemoveActivity,
24
+ getEntityMetadata, getEntityTableName, getEntityProperties,
25
+ type EntityInsertData, type EntityPartialData, type FindWhere,
26
+ type SerializableCreateInput, type SerializableFindInput,
27
+ type SerializableGetSnapshotInput, type SerializableUpdateInput,
28
+ type SerializableRemoveInput,
29
+ } from '@t4h.framework/orm'
30
+ ```
31
+
32
+ Node `>=22`. See [README.md](../../../README.md).
33
+
34
+ ---
35
+
36
+ ## Architecture
37
+
38
+ `Workflow` → `ORM` / `Ref` methods (`History.bind` on ORM activities) → `ORMClaim` (runtime database adapter).
39
+
40
+ | Layer | Role |
41
+ |-------|------|
42
+ | **ORM** | High-level API; applies defaults + constraints before activities |
43
+ | **Ref** / **RefCollection** | Row handles returned by create/find |
44
+ | **Activities** | `SyncActivity` classes delegating to `ORMClaim` |
45
+ | **ORMClaim** | Abstract claim; runtime provides concrete DB implementation |
46
+
47
+ All ORM activities use `new Claim({ orm: ORMClaim })` and delegate in `run()`.
48
+
49
+ ---
50
+
51
+ ## Defining entities
52
+
53
+ Enable decorator metadata in the project `tsconfig.json`:
54
+
55
+ ```json
56
+ {
57
+ "compilerOptions": {
58
+ "experimentalDecorators": true,
59
+ "emitDecoratorMetadata": true
60
+ }
61
+ }
62
+ ```
63
+
64
+ Import `reflect-metadata` where decorators are evaluated (Property decorator imports it).
65
+
66
+ ### @Entity
67
+
68
+ ```typescript
69
+ @Entity({ tableName: 'users' })
70
+ class User {
71
+ @Property({ type: 'string' })
72
+ public name!: string
73
+
74
+ @Property({ type: 'string' })
75
+ public email!: string
76
+
77
+ @Property({ type: 'boolean', default: true })
78
+ public active!: boolean
79
+ }
80
+ ```
81
+
82
+ - `tableName` is optional; defaults to the class name (`User` → `"User"`).
83
+ - Use `getEntityTableName(User)` or rely on ORM to resolve the table name.
84
+
85
+ ### @Property
86
+
87
+ Options: `type?`, `nullable?` (default required), `default?`, `index?` (adds index metadata).
88
+
89
+ Omit `type` to infer from design metadata (`String`→`string`, `Number`→`number`, etc.). Declare domain types (`uuid`) explicitly. Validated types: `string`, `uuid`, `number`, `boolean`, `array`, `date`, `object`. No `type` → skip type validation.
90
+
91
+ ### @Index
92
+
93
+ Class-level composite indexes:
94
+
95
+ ```typescript
96
+ @Index({ properties: ['tenantId', 'email'], name: 'accounts_tenant_email_idx' })
97
+ class Account { /* ... */ }
98
+ ```
99
+
100
+ `properties` must be non-empty or the decorator throws. Per-property `@Property({ index: true })` also registers `{ properties: [propertyKey] }`.
101
+
102
+ ---
103
+
104
+ ## ORM configuration
105
+
106
+ `ORM` extends `SerializableClass` — instances can be serialized for workflow persistence.
107
+
108
+ ```typescript
109
+ const orm = new ORM({
110
+ connectionString: 'postgresql://localhost:5432/mydb',
111
+ entities: [User, Product],
112
+ })
113
+ ```
114
+
115
+ - `entities`: array of entity **constructors** (decorated classes).
116
+ - `config.entities` stores resolved `EntityMetadata` (table name, properties map, indexes).
117
+
118
+ Restore from serialized state:
119
+
120
+ ```typescript
121
+ const orm = await ORM.fromSerializable(serialized, v => v)
122
+ ```
123
+
124
+ ---
125
+
126
+ ## CRUD in workflows
127
+
128
+ ORM methods bind activities via `History.bind` — calls inside a workflow are **reconciler-driven** (replay-safe).
129
+
130
+ ### Create
131
+
132
+ ```typescript
133
+ // Single row → Ref<T>
134
+ const userRef = await orm.create(User, {
135
+ name: 'John',
136
+ email: 'john@example.com',
137
+ active: true,
138
+ })
139
+
140
+ // Batch → RefCollection<T>
141
+ const usersRef = await orm.create(User, [
142
+ { name: 'Alice', email: 'alice@example.com', active: true },
143
+ { name: 'Bob', email: 'bob@example.com', active: true },
144
+ ])
145
+ ```
146
+
147
+ Defaults are applied before persistence (`applyDefaultProperties`). Omitted fields with `@Property({ default })` are filled in.
148
+
149
+ ### Find
150
+
151
+ ```typescript
152
+ const userRef = await orm.findOne(User, {
153
+ where: { email: 'john@example.com' },
154
+ orderBy: { name: 'asc' },
155
+ }) // Ref<User> | null
156
+
157
+ const usersRef = await orm.find(User, {
158
+ where: { active: true },
159
+ orderBy: { name: 'asc' },
160
+ limit: 10,
161
+ offset: 0,
162
+ }) // RefCollection<User>
163
+
164
+ const exists = await orm.exists(User, {
165
+ where: { email: 'john@example.com' },
166
+ }) // boolean (delegates to findOne)
167
+ ```
168
+
169
+ `findOne` activity internally calls `claim.find` with `limit: 1`.
170
+
171
+ ### Ref operations
172
+
173
+ ```typescript
174
+ const snapshot = await userRef.getSnapshot() // T | null — entity instance via Reflect.construct
175
+ await userRef.update({ name: 'Jane' }) // partial patch only
176
+ await userRef.remove()
177
+ ```
178
+
179
+ `getSnapshot` returns `null` when the row no longer exists. `update` validates only keys present in the patch.
180
+
181
+ **RefCollection:** `toArray()`, `length`, `at(i)`, async `forEach`/`map`/`filter`, `Symbol.iterator`.
182
+
183
+ ---
184
+
185
+ ## Query operators
186
+
187
+ `where` uses `FindWhere<T>` — implicit equality or operator objects:
188
+
189
+ ```typescript
190
+ await orm.find(User, {
191
+ where: {
192
+ name: 'John', // $eq (implicit)
193
+ active: { $ne: false },
194
+ email: { $like: '%@example%' },
195
+ age: { $gte: 18, $lt: 65 },
196
+ status: { $in: ['active', 'pending'] },
197
+ $or: [{ name: 'Alice' }, { name: 'Bob' }],
198
+ $and: [{ active: true }, { age: { $gte: 18 } }],
199
+ },
200
+ })
201
+ ```
202
+
203
+ Available operators: `$eq`, `$ne`, `$in`, `$nin`, `$not`, `$gt`, `$gte`, `$lt`, `$lte`, `$like`, `$ilike`, `$and`, `$or`.
204
+
205
+ ---
206
+
207
+ ## Constraint validation
208
+
209
+ Validation runs in the ORM library (`ORM.create` and `Ref.update`), **not** in `ORMClaim` implementations. Failures throw `ConstraintError`.
210
+
211
+ ### Create pipeline
212
+
213
+ 1. `applyDefaultProperties` — fills `default` for `undefined` fields
214
+ 2. `assertPropertyTypeConstraint` — validates declared types
215
+ 3. `assertNonNullablePropertyConstraint` — required fields must be present
216
+
217
+ ### Update pipeline
218
+
219
+ 1. Defaults only for keys present in the patch
220
+ 2. Same asserts, scoped to patch keys via `{ keys: Object.keys(data) }`
221
+
222
+ ### Handling errors
223
+
224
+ ```typescript
225
+ import { ConstraintError, ORM } from '@t4h.framework/orm'
226
+
227
+ try {
228
+ await orm.create(User, { email: 'bad' } as EntityInsertData<User>)
229
+ } catch (error) {
230
+ if (error instanceof ConstraintError) {
231
+ // e.g. 'Property "name" is required'
232
+ // e.g. 'Property "name" must be of type string'
233
+ }
234
+ }
235
+ ```
236
+
237
+ Constraint checks run **before** activities are invoked — failed creates/updates never reach `ORMClaim`.
238
+
239
+ ---
240
+
241
+ ## ORMClaim (runtime dependency)
242
+
243
+ Runtime must register a concrete implementation:
244
+
245
+ ```typescript
246
+ { provide: ORMClaim, value: new MyORMClaimImpl() }
247
+ ```
248
+
249
+ Contract:
250
+
251
+ ```typescript
252
+ abstract class ORMClaim<R extends SerializableRowRef> {
253
+ abstract find(input: SerializableFindInput): R[] | Promise<R[]>
254
+ abstract create(input: SerializableCreateInput): R[] | Promise<R[]>
255
+ abstract getSnapshot(input: SerializableGetSnapshotInput<R>): SerializedRow | null | Promise<SerializedRow | null>
256
+ abstract update(input: SerializableUpdateInput<R>): void | Promise<void>
257
+ abstract remove(input: SerializableRemoveInput<R>): void | Promise<void>
258
+ }
259
+ ```
260
+
261
+ Activity inputs always include `orm` + `table`; create adds `data[]`, find adds `where` (+ optional `orderBy`/`limit`/`offset`), snapshot/update/remove add `ref` (opaque `Serializable` row handle). Update also includes partial `data`.
262
+
263
+ Access claim-backed activity logic only inside `Claim.run` or workflow `History.run` context.
264
+
265
+ ---
266
+
267
+ ## Activities
268
+
269
+ All extend `SyncActivity` and delegate to `ORMClaim`:
270
+
271
+ | Activity | Input | Output |
272
+ |----------|-------|--------|
273
+ | `ORMCreateActivity` | `SerializableCreateInput` | `SerializableRowRef[]` |
274
+ | `ORMFindActivity` | `SerializableFindInput` | `SerializableRowRef[]` |
275
+ | `ORMFindOneActivity` | `SerializableFindInput` | `SerializableRowRef \| null` |
276
+ | `ORMGetSnapshotActivity` | `SerializableGetSnapshotInput` | `SerializedRow \| null` |
277
+ | `ORMUpdateActivity` | `SerializableUpdateInput` | `void` |
278
+ | `ORMRemoveActivity` | `SerializableRemoveInput` | `void` |
279
+
280
+ Prefer **`ORM` / `Ref` APIs** in workflow code — they apply constraints and return typed handles. Use activities directly only for advanced/testing scenarios.
281
+
282
+ ---
283
+
284
+ ## Workflow example
285
+
286
+ From `examples/basic/src/workflows/orm.ts` — define entities, instantiate `ORM` with `connectionString` + `entities`, use inside `Workflow`:
287
+
288
+ ```typescript
289
+ export const orm = new ORM({ connectionString: '...', entities: [User] })
290
+
291
+ export const ormWorkflow = new Workflow({ id: 'orm' }, async () => {
292
+ await orm.create(User, { name: 'John', email: 'john@example.com', age: 20 })
293
+ const user = await orm.findOne(User, { where: { email: 'john@example.com' } })
294
+ await user?.update({ name: 'John Updated' })
295
+ await user?.remove()
296
+ return { user }
297
+ })
298
+ ```
299
+
300
+ Ensure the runtime provides `ORMClaim`.
301
+
302
+ ---
303
+
304
+ ## Testing
305
+
306
+ Run: `yarn test` in `packages/orm`.
307
+
308
+ **ORM / Ref unit tests** — mock `History.bind` by activity name (`ORMCreateActivity`, `ORMFindOneActivity`, etc.) per `src/models/__tests__/ORM.spec.ts`. Assert `ConstraintError` before activities run: `expect(mockCreate).not.toHaveBeenCalled()`.
309
+
310
+ **Activity unit tests** — wrap `activity.run(input)` in `Claim.run([{ provide: ORMClaim, value: mockClaim }], fn)` per `src/activities/__tests__/ORMCreateActivity.spec.ts`.
311
+
312
+ **Workflow integration** — `WorkflowTesting.run` with a mocked `ORMClaim` provider (see **framework-core** skill).
313
+
314
+ ---
315
+
316
+ ## Checklist for agents
317
+
318
+ 1. **`@Entity` + `@Property`** with `experimentalDecorators` + `emitDecoratorMetadata`.
319
+ 2. Register entities in **`ORM({ entities: [...] })`**; runtime provides **`ORMClaim`**.
320
+ 3. Use **`orm` / `Ref` APIs** in workflows — not raw SQL or direct claim calls.
321
+ 4. Handle **`ConstraintError`**; validation runs before activities.
322
+ 5. **`Ref.update`** is partial; **`getSnapshot`** returns entity instances.
323
+ 6. Test with **`History.bind` mocks** or **`Claim.run` + ORMClaim mock**; only use exported APIs.
324
+
325
+ See also: `packages/orm/README.md`, `examples/basic/src/workflows/orm.ts`.
package/README.md CHANGED
@@ -64,6 +64,60 @@ class User {
64
64
  })
65
65
  ```
66
66
 
67
+ When `type` is omitted, it is inferred from the TypeScript property type if the project enables `emitDecoratorMetadata` (and imports `reflect-metadata`). Domain types such as `uuid` must be declared explicitly.
68
+
69
+ If `nullable` is omitted, the property is required at runtime validation.
70
+
71
+ ### TypeScript configuration for entity classes
72
+
73
+ Projects that define entities with `@Property()` should enable:
74
+
75
+ ```json
76
+ {
77
+ "compilerOptions": {
78
+ "experimentalDecorators": true,
79
+ "emitDecoratorMetadata": true
80
+ }
81
+ }
82
+ ```
83
+
84
+ ## Constraints
85
+
86
+ Row validation runs in the ORM library (`ORM.create` and `Ref.update`), not in `ORMClaim` implementations. Failed checks throw `ConstraintError`.
87
+
88
+ ### Pipeline
89
+
90
+ **Create** (full row, after defaults):
91
+
92
+ 1. `applyDefaultProperties` — fills `default` for `undefined` fields
93
+ 2. `assertPropertyTypeConstraint` — validates declared types
94
+ 3. `assertNonNullablePropertyConstraint` — required fields must be present
95
+ 4. `assertUniqueConstraint` — no duplicates in the batch, then no conflicting row in storage via `orm.exists`
96
+
97
+ **Update** (partial patch only):
98
+
99
+ 1. Defaults only for keys present in the patch
100
+ 2. Same asserts, scoped to patch keys
101
+ 3. Unique checks skip values unchanged vs `getSnapshot()` (same row keeps its current unique value)
102
+
103
+ ### Supported property types
104
+
105
+ `string`, `uuid`, `number`, `boolean`, `array`, `date`, `object`. Properties without `type` skip type validation.
106
+
107
+ ### Example
108
+
109
+ ```typescript
110
+ import { ConstraintError, ORM } from '@t4h.framework/orm'
111
+
112
+ try {
113
+ await orm.create(User, { email: 'taken@example.com' })
114
+ } catch (error) {
115
+ if (error instanceof ConstraintError) {
116
+ // handle validation failure
117
+ }
118
+ }
119
+ ```
120
+
67
121
  ## ORM Model
68
122
 
69
123
  The `ORM` class provides a high-level API for database operations. It wraps the underlying activities (`ORMCreateActivity`, `ORMFindActivity`, `ORMFindOneActivity`).
@@ -3,11 +3,11 @@ import type { SerializableGetSnapshotInput, SerializableRowRef, SerializedRow }
3
3
  declare const CLAIMS_KEY: unique symbol;
4
4
  export declare class ORMGetSnapshotActivity extends SyncActivity<[
5
5
  input: SerializableGetSnapshotInput<SerializableRowRef>
6
- ], SerializableGetSnapshotInput<SerializableRowRef>, SerializedRow, SerializedRow> {
6
+ ], SerializableGetSnapshotInput<SerializableRowRef>, SerializedRow | null, SerializedRow | null> {
7
7
  private readonly [CLAIMS_KEY];
8
8
  toInput(input: SerializableGetSnapshotInput<SerializableRowRef>): SerializableGetSnapshotInput<SerializableRowRef>;
9
- run(input: SerializableGetSnapshotInput<SerializableRowRef>): SerializedRow | Promise<SerializedRow>;
10
- toOutput(output: SerializedRow): SerializedRow;
9
+ run(input: SerializableGetSnapshotInput<SerializableRowRef>): SerializedRow | Promise<SerializedRow | null> | null;
10
+ toOutput(output: SerializedRow | null): SerializedRow | null;
11
11
  }
12
12
  export {};
13
13
  //# sourceMappingURL=ORMGetSnapshotActivity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ORMGetSnapshotActivity.d.ts","sourceRoot":"","sources":["../../src/activities/ORMGetSnapshotActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAS,MAAM,qBAAqB,CAAA;AAGzD,OAAO,KAAK,EACV,4BAA4B,EAC5B,kBAAkB,EAClB,aAAa,EACd,MAAM,mBAAmB,CAAA;AAE1B,QAAA,MAAM,UAAU,eAA6C,CAAA;AAE7D,qBAAa,sBAAuB,SAAQ,YAAY,CACtD;IAAC,KAAK,EAAE,4BAA4B,CAAC,kBAAkB,CAAC;CAAC,EACzD,4BAA4B,CAAC,kBAAkB,CAAC,EAChD,aAAa,EACb,aAAa,CACd;IACC,OAAO,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAE3B;IAEK,OAAO,CACZ,KAAK,EAAE,4BAA4B,CAAC,kBAAkB,CAAC,GACtD,4BAA4B,CAAC,kBAAkB,CAAC;IAI5C,GAAG,CAAC,KAAK,EAAE,4BAA4B,CAAC,kBAAkB,CAAC;IAI3D,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa;CAGtD"}
1
+ {"version":3,"file":"ORMGetSnapshotActivity.d.ts","sourceRoot":"","sources":["../../src/activities/ORMGetSnapshotActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAS,MAAM,qBAAqB,CAAA;AAGzD,OAAO,KAAK,EACV,4BAA4B,EAC5B,kBAAkB,EAClB,aAAa,EACd,MAAM,mBAAmB,CAAA;AAE1B,QAAA,MAAM,UAAU,eAA6C,CAAA;AAE7D,qBAAa,sBAAuB,SAAQ,YAAY,CACtD;IAAC,KAAK,EAAE,4BAA4B,CAAC,kBAAkB,CAAC;CAAC,EACzD,4BAA4B,CAAC,kBAAkB,CAAC,EAChD,aAAa,GAAG,IAAI,EACpB,aAAa,GAAG,IAAI,CACrB;IACC,OAAO,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAE3B;IAEK,OAAO,CACZ,KAAK,EAAE,4BAA4B,CAAC,kBAAkB,CAAC,GACtD,4BAA4B,CAAC,kBAAkB,CAAC;IAI5C,GAAG,CAAC,KAAK,EAAE,4BAA4B,CAAC,kBAAkB,CAAC;IAI3D,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,GAAG,aAAa,GAAG,IAAI;CAGpE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ORMGetSnapshotActivity.js","sourceRoot":"","sources":["../../src/activities/ORMGetSnapshotActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAEzD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAOhD,MAAM,UAAU,GAAG,MAAM,CAAC,kCAAkC,CAAC,CAAA;AAE7D,MAAM,OAAO,sBAAuB,SAAQ,YAK3C;IACkB,CAAC,UAAU,CAAC,GAAG,IAAI,KAAK,CAAC;QACxC,GAAG,EAAE,QAAQ;KACd,CAAC,CAAA;IAEK,OAAO,CACZ,KAAuD;QAEvD,OAAO,KAAK,CAAA;IACd,CAAC;IAEM,GAAG,CAAC,KAAuD;QAChE,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IAChD,CAAC;IAEM,QAAQ,CAAC,MAAqB;QACnC,OAAO,MAAM,CAAA;IACf,CAAC;CACF"}
1
+ {"version":3,"file":"ORMGetSnapshotActivity.js","sourceRoot":"","sources":["../../src/activities/ORMGetSnapshotActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAEzD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAOhD,MAAM,UAAU,GAAG,MAAM,CAAC,kCAAkC,CAAC,CAAA;AAE7D,MAAM,OAAO,sBAAuB,SAAQ,YAK3C;IACkB,CAAC,UAAU,CAAC,GAAG,IAAI,KAAK,CAAC;QACxC,GAAG,EAAE,QAAQ;KACd,CAAC,CAAA;IAEK,OAAO,CACZ,KAAuD;QAEvD,OAAO,KAAK,CAAA;IACd,CAAC;IAEM,GAAG,CAAC,KAAuD;QAChE,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IAChD,CAAC;IAEM,QAAQ,CAAC,MAA4B;QAC1C,OAAO,MAAM,CAAA;IACf,CAAC;CACF"}
@@ -2,7 +2,7 @@ import type { SerializableCreateInput, SerializableFindInput, SerializableGetSna
2
2
  export declare abstract class ORMClaim<R extends SerializableRowRef> {
3
3
  abstract find(input: SerializableFindInput): R[] | Promise<R[]>;
4
4
  abstract create(input: SerializableCreateInput): R[] | Promise<R[]>;
5
- abstract getSnapshot(input: SerializableGetSnapshotInput<R>): SerializedRow | Promise<SerializedRow>;
5
+ abstract getSnapshot(input: SerializableGetSnapshotInput<R>): SerializedRow | null | Promise<SerializedRow | null>;
6
6
  abstract update(input: SerializableUpdateInput<R>): void | Promise<void>;
7
7
  abstract remove(input: SerializableRemoveInput<R>): void | Promise<void>;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ORMClaim.d.ts","sourceRoot":"","sources":["../../src/claims/ORMClaim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,aAAa,EACd,MAAM,mBAAmB,CAAA;AAE1B,8BAAsB,QAAQ,CAAC,CAAC,SAAS,kBAAkB;aACzC,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAEtD,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAE1D,WAAW,CACzB,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,GACrC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;aAEzB,MAAM,CACpB,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAChC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;aAEP,MAAM,CACpB,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAChC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CACxB"}
1
+ {"version":3,"file":"ORMClaim.d.ts","sourceRoot":"","sources":["../../src/claims/ORMClaim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,aAAa,EACd,MAAM,mBAAmB,CAAA;AAE1B,8BAAsB,QAAQ,CAAC,CAAC,SAAS,kBAAkB;aACzC,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAEtD,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAE1D,WAAW,CACzB,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,GACrC,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;aAEvC,MAAM,CACpB,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAChC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;aAEP,MAAM,CACpB,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAChC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CACxB"}
@@ -0,0 +1,3 @@
1
+ import type { EntityMetadata, PropertyMetadata } from '../../decorators/metadata.js';
2
+ export declare function createEntityMetadata(properties: Record<string, Omit<PropertyMetadata, 'name'>>): EntityMetadata;
3
+ //# sourceMappingURL=create-entity-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-entity-metadata.d.ts","sourceRoot":"","sources":["../../../src/constraints/__tests__/create-entity-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EACjB,MAAM,8BAA8B,CAAA;AAErC,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,GACzD,cAAc,CAUhB"}
@@ -0,0 +1,10 @@
1
+ export function createEntityMetadata(properties) {
2
+ return {
3
+ indexes: [],
4
+ properties: new Map(Object.entries(properties).map(([name, meta]) => [
5
+ name,
6
+ { name, indexes: [], ...meta },
7
+ ])),
8
+ };
9
+ }
10
+ //# sourceMappingURL=create-entity-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-entity-metadata.js","sourceRoot":"","sources":["../../../src/constraints/__tests__/create-entity-metadata.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,oBAAoB,CAClC,UAA0D;IAE1D,OAAO;QACL,OAAO,EAAE,EAAE;QACX,UAAU,EAAE,IAAI,GAAG,CACjB,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;YAC/C,IAAI;YACJ,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE;SAC/B,CAAC,CACH;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { EntityMetadata, SerializedRow } from '../orm.js';
2
+ export declare function applyDefaultProperties(rows: SerializedRow[] | SerializedRow, entity: EntityMetadata, keys?: string[]): {
3
+ [x: string]: import("@t4h.framework/core").Serializable;
4
+ } | {
5
+ [x: string]: import("@t4h.framework/core").Serializable;
6
+ }[];
7
+ //# sourceMappingURL=apply-default-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-default-properties.d.ts","sourceRoot":"","sources":["../../src/constraints/apply-default-properties.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAmB9D,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,aAAa,EAAE,GAAG,aAAa,EACrC,MAAM,EAAE,cAAc,EACtB,IAAI,CAAC,EAAE,MAAM,EAAE;;;;IAMhB"}
@@ -0,0 +1,16 @@
1
+ function applyDefaultPropertiesToRow(raw, entity, keys) {
2
+ const row = { ...raw };
3
+ for (const [name, meta] of entity.properties.entries()) {
4
+ if (keys && !keys.includes(name))
5
+ continue;
6
+ if (row[name] === undefined && meta.default !== undefined)
7
+ row[name] = meta.default;
8
+ }
9
+ return row;
10
+ }
11
+ export function applyDefaultProperties(rows, entity, keys) {
12
+ if (Array.isArray(rows))
13
+ return rows.map(raw => applyDefaultPropertiesToRow(raw, entity, keys));
14
+ return applyDefaultPropertiesToRow(rows, entity, keys);
15
+ }
16
+ //# sourceMappingURL=apply-default-properties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-default-properties.js","sourceRoot":"","sources":["../../src/constraints/apply-default-properties.ts"],"names":[],"mappings":"AAEA,SAAS,2BAA2B,CAClC,GAAkB,EAClB,MAAsB,EACtB,IAAe;IAEf,MAAM,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,CAAA;IAEtB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAQ;QAE1C,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YACvD,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAA;IAC5B,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,IAAqC,EACrC,MAAsB,EACtB,IAAe;IAEf,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QACrB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA;IAExE,OAAO,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;AACxD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type EntityConstructor, type SerializedRow } from '../orm.js';
2
+ interface AssertConstraintsOptions {
3
+ keys?: string[];
4
+ }
5
+ export declare function assertConstraints<T>(entity: EntityConstructor<T>, rows: SerializedRow[], options?: AssertConstraintsOptions): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=assert-constraints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-constraints.d.ts","sourceRoot":"","sources":["../../src/constraints/assert-constraints.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EACnB,MAAM,WAAW,CAAA;AAIlB,UAAU,wBAAwB;IAChC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,IAAI,EAAE,aAAa,EAAE,EACrB,OAAO,CAAC,EAAE,wBAAwB,iBAWnC"}
@@ -0,0 +1,13 @@
1
+ import { getEntityMetadata, } from '../orm.js';
2
+ import { assertNonNullablePropertyConstraint } from './assert-non-nullable-property-constraint.js';
3
+ import { assertPropertyTypeConstraint } from './assert-property-type-constraint.js';
4
+ export async function assertConstraints(entity, rows, options) {
5
+ const entityMetadata = getEntityMetadata(entity);
6
+ assertPropertyTypeConstraint(rows, entityMetadata, {
7
+ keys: options?.keys,
8
+ });
9
+ assertNonNullablePropertyConstraint(rows, entityMetadata, {
10
+ keys: options?.keys,
11
+ });
12
+ }
13
+ //# sourceMappingURL=assert-constraints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-constraints.js","sourceRoot":"","sources":["../../src/constraints/assert-constraints.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,GAGlB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,mCAAmC,EAAE,MAAM,8CAA8C,CAAA;AAClG,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAA;AAMnF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAA4B,EAC5B,IAAqB,EACrB,OAAkC;IAElC,MAAM,cAAc,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAEhD,4BAA4B,CAAC,IAAI,EAAE,cAAc,EAAE;QACjD,IAAI,EAAE,OAAO,EAAE,IAAI;KACpB,CAAC,CAAA;IAEF,mCAAmC,CAAC,IAAI,EAAE,cAAc,EAAE;QACxD,IAAI,EAAE,OAAO,EAAE,IAAI;KACpB,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { EntityMetadata, SerializedRow } from '../orm.js';
2
+ interface AssertNonNullablePropertyConstraintOptions {
3
+ keys?: string[];
4
+ }
5
+ export declare function assertNonNullablePropertyConstraint(rows: SerializedRow[], entity: EntityMetadata, options?: AssertNonNullablePropertyConstraintOptions): void;
6
+ export {};
7
+ //# sourceMappingURL=assert-non-nullable-property-constraint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-non-nullable-property-constraint.d.ts","sourceRoot":"","sources":["../../src/constraints/assert-non-nullable-property-constraint.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAE9D,UAAU,0CAA0C;IAClD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,aAAa,EAAE,EACrB,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,0CAA0C,QAYrD"}
@@ -0,0 +1,14 @@
1
+ import { ConstraintError } from '../errors/ConstraintError.js';
2
+ export function assertNonNullablePropertyConstraint(rows, entity, options) {
3
+ rows.forEach(row => {
4
+ for (const [name, meta] of entity.properties.entries()) {
5
+ if (options?.keys && !options.keys.includes(name))
6
+ continue;
7
+ if (meta.nullable)
8
+ continue;
9
+ if (row[name] === null || row[name] === undefined)
10
+ throw new ConstraintError(`Property "${name}" is required`);
11
+ }
12
+ });
13
+ }
14
+ //# sourceMappingURL=assert-non-nullable-property-constraint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-non-nullable-property-constraint.js","sourceRoot":"","sources":["../../src/constraints/assert-non-nullable-property-constraint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAO9D,MAAM,UAAU,mCAAmC,CACjD,IAAqB,EACrB,MAAsB,EACtB,OAAoD;IAEpD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QACjB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,OAAO,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAQ;YAE3D,IAAI,IAAI,CAAC,QAAQ;gBAAE,SAAQ;YAE3B,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,SAAS;gBAC/C,MAAM,IAAI,eAAe,CAAC,aAAa,IAAI,eAAe,CAAC,CAAA;QAC/D,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { EntityMetadata, SerializedRow } from '../orm.js';
2
+ interface AssertPropertyTypeConstraintOptions {
3
+ keys?: string[];
4
+ }
5
+ export declare function assertPropertyTypeConstraint(rows: SerializedRow[], entity: EntityMetadata, options?: AssertPropertyTypeConstraintOptions): void;
6
+ export {};
7
+ //# sourceMappingURL=assert-property-type-constraint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-property-type-constraint.d.ts","sourceRoot":"","sources":["../../src/constraints/assert-property-type-constraint.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAgB9D,UAAU,mCAAmC;IAC3C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,aAAa,EAAE,EACrB,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,mCAAmC,QAyB9C"}
@@ -0,0 +1,30 @@
1
+ import { ConstraintError } from '../errors/ConstraintError.js';
2
+ const UUID_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
3
+ const PROPERTY_TYPE = {
4
+ string: (value) => typeof value === 'string',
5
+ uuid: (value) => typeof value === 'string' && UUID_REGEX.test(value),
6
+ number: (value) => typeof value === 'number' && !Number.isNaN(value),
7
+ boolean: (value) => typeof value === 'boolean',
8
+ array: (value) => Array.isArray(value),
9
+ date: (value) => value instanceof Date || typeof value === 'string',
10
+ object: (value) => typeof value === 'object' && value !== null && !Array.isArray(value),
11
+ };
12
+ export function assertPropertyTypeConstraint(rows, entity, options) {
13
+ rows.forEach(row => {
14
+ for (const [name, meta] of entity.properties.entries()) {
15
+ if (options?.keys && !options.keys.includes(name))
16
+ continue;
17
+ const value = row[name];
18
+ if (!meta.type)
19
+ continue;
20
+ if (value === undefined || value === null)
21
+ continue;
22
+ const validator = PROPERTY_TYPE[meta.type];
23
+ if (!validator)
24
+ throw new ConstraintError(`Property "${name}" has unsupported type "${meta.type}"`);
25
+ if (!validator(value))
26
+ throw new ConstraintError(`Property "${name}" must be of type ${meta.type}`);
27
+ }
28
+ });
29
+ }
30
+ //# sourceMappingURL=assert-property-type-constraint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-property-type-constraint.js","sourceRoot":"","sources":["../../src/constraints/assert-property-type-constraint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAG9D,MAAM,UAAU,GACd,+EAA+E,CAAA;AAEjF,MAAM,aAAa,GAAG;IACpB,MAAM,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ;IACrD,IAAI,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;IAC7E,MAAM,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;IAC7E,OAAO,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,SAAS;IACvD,KAAK,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;IAC/C,IAAI,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,KAAK,YAAY,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;IAC5E,MAAM,EAAE,CAAC,KAAc,EAAE,EAAE,CACzB,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;CACvE,CAAA;AAMD,MAAM,UAAU,4BAA4B,CAC1C,IAAqB,EACrB,MAAsB,EACtB,OAA6C;IAE7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QACjB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,OAAO,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAQ;YAE3D,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAA;YAEvB,IAAI,CAAC,IAAI,CAAC,IAAI;gBAAE,SAAQ;YAExB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;gBAAE,SAAQ;YAEnD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,IAAkC,CAAC,CAAA;YAExE,IAAI,CAAC,SAAS;gBACZ,MAAM,IAAI,eAAe,CACvB,aAAa,IAAI,2BAA2B,IAAI,CAAC,IAAI,GAAG,CACzD,CAAA;YAEH,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;gBACnB,MAAM,IAAI,eAAe,CACvB,aAAa,IAAI,qBAAqB,IAAI,CAAC,IAAI,EAAE,CAClD,CAAA;QACL,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Serializable } from '@t4h.framework/core';
2
+ import type { EntityMetadata, SerializedRow } from '../orm.js';
3
+ import type { FindWhere } from '../typings/FindWhere.js';
4
+ interface AssertUniqueConstraintOptions<T> {
5
+ keys?: string[];
6
+ validator: (where: FindWhere<T>) => Promise<unknown>;
7
+ isUnchanged?: (name: string, value: Serializable) => boolean;
8
+ }
9
+ export declare function assertUniqueConstraint<T>(rows: SerializedRow[], entity: EntityMetadata, options: AssertUniqueConstraintOptions<T>): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=assert-unique-constraint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-unique-constraint.d.ts","sourceRoot":"","sources":["../../src/constraints/assert-unique-constraint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAGvD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,UAAU,6BAA6B,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACpD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAA;CAC7D;AA6BD,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,IAAI,EAAE,aAAa,EAAE,EACrB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,6BAA6B,CAAC,CAAC,CAAC,iBA6B1C"}
@@ -0,0 +1,41 @@
1
+ import { ConstraintError } from '../errors/ConstraintError.js';
2
+ function assertUniqueWithinBatch(rows, entity, keys) {
3
+ entity.properties.entries().forEach(([name, meta]) => {
4
+ if (keys && !keys.includes(name))
5
+ return;
6
+ if (!meta.unique)
7
+ return;
8
+ const seen = new Set();
9
+ rows.forEach(row => {
10
+ const value = row[name];
11
+ if (value === undefined || value === null)
12
+ return;
13
+ if (seen.has(value))
14
+ throw new ConstraintError(`Unique constraint violation for property "${name}" with value "${value}" (duplicate in batch)`);
15
+ seen.add(value);
16
+ });
17
+ });
18
+ }
19
+ export async function assertUniqueConstraint(rows, entity, options) {
20
+ assertUniqueWithinBatch(rows, entity, options?.keys);
21
+ await Promise.all(rows.map(async (row) => {
22
+ for (const [name, meta] of entity.properties.entries()) {
23
+ if (options?.keys && !options.keys.includes(name))
24
+ continue;
25
+ if (!meta.unique)
26
+ continue;
27
+ const value = row[name];
28
+ if (value === undefined || value === null)
29
+ continue;
30
+ if (options.isUnchanged?.(name, value))
31
+ continue;
32
+ const result = await options.validator({
33
+ [name]: value,
34
+ });
35
+ if (result === undefined || result === null)
36
+ continue;
37
+ throw new ConstraintError(`Unique constraint violation for property "${name}" with value "${value}"`);
38
+ }
39
+ }));
40
+ }
41
+ //# sourceMappingURL=assert-unique-constraint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-unique-constraint.js","sourceRoot":"","sources":["../../src/constraints/assert-unique-constraint.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAU9D,SAAS,uBAAuB,CAC9B,IAAqB,EACrB,MAAsB,EACtB,IAAe;IAEf,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACnD,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAM;QAExC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAM;QAExB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAgB,CAAA;QAEpC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACjB,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAA;YAEvB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAM;YAEjD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;gBACjB,MAAM,IAAI,eAAe,CACvB,6CAA6C,IAAI,iBAAiB,KAAK,wBAAwB,CAChG,CAAA;YAEH,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACjB,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAqB,EACrB,MAAsB,EACtB,OAAyC;IAEzC,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;IAEpD,MAAM,OAAO,CAAC,GAAG,CACf,IAAI,CAAC,GAAG,CAAC,KAAK,EAAC,GAAG,EAAC,EAAE;QACnB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,OAAO,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAQ;YAE3D,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,SAAQ;YAE1B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAA;YAEvB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;gBAAE,SAAQ;YAEnD,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;gBAAE,SAAQ;YAEhD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC;gBACrC,CAAC,IAAI,CAAC,EAAE,KAAK;aACE,CAAC,CAAA;YAElB,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI;gBAAE,SAAQ;YAErD,MAAM,IAAI,eAAe,CACvB,6CAA6C,IAAI,iBAAiB,KAAK,GAAG,CAC3E,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CACH,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface IndexMetadata {
2
+ properties: string[];
3
+ name?: string;
4
+ }
5
+ export declare function Index(options: IndexMetadata): ClassDecorator;
6
+ //# sourceMappingURL=Index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Index.d.ts","sourceRoot":"","sources":["../../src/decorators/Index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,CAS5D"}
@@ -0,0 +1,10 @@
1
+ import { getEntityMetadata } from './metadata.js';
2
+ export function Index(options) {
3
+ return target => {
4
+ if (!options.properties.length)
5
+ throw new Error('Index properties cannot be empty');
6
+ const metadata = getEntityMetadata(target);
7
+ metadata.indexes.push(options);
8
+ };
9
+ }
10
+ //# sourceMappingURL=Index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Index.js","sourceRoot":"","sources":["../../src/decorators/Index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAOjD,MAAM,UAAU,KAAK,CAAC,OAAsB;IAC1C,OAAO,MAAM,CAAC,EAAE;QACd,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM;YAC5B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;QAErD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAkC,CAAC,CAAA;QAEtE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAChC,CAAC,CAAA;AACH,CAAC"}
@@ -1,3 +1,4 @@
1
+ import 'reflect-metadata';
1
2
  import { type PropertyMetadata } from './metadata.js';
2
3
  export type PropertyOptions = Omit<PropertyMetadata, 'name'>;
3
4
  export declare function Property(options?: PropertyOptions): PropertyDecorator;
@@ -1 +1 @@
1
- {"version":3,"file":"Property.d.ts","sourceRoot":"","sources":["../../src/decorators/Property.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAExE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAA;AAE5D,wBAAgB,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,iBAAiB,CASrE"}
1
+ {"version":3,"file":"Property.d.ts","sourceRoot":"","sources":["../../src/decorators/Property.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAA;AAEzB,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAExE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAA;AAW5D,wBAAgB,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,iBAAiB,CAoBrE"}
@@ -1,10 +1,26 @@
1
+ import 'reflect-metadata';
1
2
  import { getEntityMetadata } from './metadata.js';
3
+ const DESIGN_TYPE = new Map([
4
+ [String, 'string'],
5
+ [Number, 'number'],
6
+ [Boolean, 'boolean'],
7
+ [Array, 'array'],
8
+ [Date, 'date'],
9
+ [Object, 'object'],
10
+ ]);
2
11
  export function Property(options) {
3
12
  return (target, propertyKey) => {
4
13
  const metadata = getEntityMetadata(target.constructor);
14
+ const resolved = { ...options };
15
+ if (!resolved.type) {
16
+ const designType = Reflect.getMetadata('design:type', target, propertyKey);
17
+ resolved.type = DESIGN_TYPE.get(designType);
18
+ }
19
+ if (resolved.index)
20
+ metadata.indexes.push({ properties: [propertyKey] });
5
21
  metadata.properties.set(propertyKey, {
6
22
  name: propertyKey,
7
- ...options,
23
+ ...resolved,
8
24
  });
9
25
  };
10
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Property.js","sourceRoot":"","sources":["../../src/decorators/Property.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAyB,MAAM,eAAe,CAAA;AAIxE,MAAM,UAAU,QAAQ,CAAC,OAAyB;IAChD,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAA4B,CAAC,CAAA;QAEvE,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,WAAqB,EAAE;YAC7C,IAAI,EAAE,WAAqB;YAC3B,GAAG,OAAO;SACX,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"Property.js","sourceRoot":"","sources":["../../src/decorators/Property.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAA;AAEzB,OAAO,EAAE,iBAAiB,EAAyB,MAAM,eAAe,CAAA;AAIxE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAkB;IAC3C,CAAC,MAAM,EAAE,QAAQ,CAAC;IAClB,CAAC,MAAM,EAAE,QAAQ,CAAC;IAClB,CAAC,OAAO,EAAE,SAAS,CAAC;IACpB,CAAC,KAAK,EAAE,OAAO,CAAC;IAChB,CAAC,IAAI,EAAE,MAAM,CAAC;IACd,CAAC,MAAM,EAAE,QAAQ,CAAC;CACnB,CAAC,CAAA;AAEF,MAAM,UAAU,QAAQ,CAAC,OAAyB;IAChD,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAA4B,CAAC,CAAA;QAEvE,MAAM,QAAQ,GAAoB,EAAE,GAAG,OAAO,EAAE,CAAA;QAEhD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,CAAC,CAAA;YAE1E,QAAQ,CAAC,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAC7C,CAAC;QAED,IAAI,QAAQ,CAAC,KAAK;YAChB,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,WAAqB,CAAC,EAAE,CAAC,CAAA;QAEhE,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,WAAqB,EAAE;YAC7C,IAAI,EAAE,WAAqB;YAC3B,GAAG,QAAQ;SACZ,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC"}
@@ -1,13 +1,16 @@
1
+ import type { Serializable } from '@t4h.framework/core';
2
+ import type { IndexMetadata } from './Index.js';
1
3
  export interface EntityMetadata {
2
4
  tableName?: string;
3
5
  properties: Map<string, PropertyMetadata>;
6
+ indexes: Array<IndexMetadata>;
4
7
  }
5
8
  export interface PropertyMetadata {
6
9
  name: string;
7
10
  type?: string;
8
11
  nullable?: boolean;
9
- unique?: boolean;
10
- default?: unknown;
12
+ default?: Serializable;
13
+ index?: boolean;
11
14
  }
12
15
  export declare function getEntityMetadata(target: new (...args: any[]) => any): EntityMetadata;
13
16
  export declare function getEntityTableName(target: new (...args: any[]) => any): string;
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/decorators/metadata.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CAC1C;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAID,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,cAAc,CAShB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,MAAM,CAIR;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAE/B"}
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/decorators/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACzC,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAID,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,cAAc,CAShB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,MAAM,CAIR;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAE/B"}
@@ -2,7 +2,7 @@ const entityMetadataMap = new WeakMap();
2
2
  export function getEntityMetadata(target) {
3
3
  let metadata = entityMetadataMap.get(target.prototype);
4
4
  if (!metadata) {
5
- metadata = { properties: new Map() };
5
+ metadata = { properties: new Map(), indexes: [] };
6
6
  entityMetadataMap.set(target.prototype, metadata);
7
7
  }
8
8
  return metadata;
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/decorators/metadata.ts"],"names":[],"mappings":"AAaA,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAA0B,CAAA;AAE/D,MAAM,UAAU,iBAAiB,CAC/B,MAAmC;IAEnC,IAAI,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAEtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,EAAE,UAAU,EAAE,IAAI,GAAG,EAAE,EAAE,CAAA;QACpC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IACnD,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,MAAmC;IAEnC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAE1C,OAAO,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI,CAAA;AAC1C,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,MAAmC;IAEnC,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,UAAU,CAAA;AAC7C,CAAC"}
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/decorators/metadata.ts"],"names":[],"mappings":"AAkBA,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAA0B,CAAA;AAE/D,MAAM,UAAU,iBAAiB,CAC/B,MAAmC;IAEnC,IAAI,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAEtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,EAAE,UAAU,EAAE,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;QACjD,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IACnD,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,MAAmC;IAEnC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAE1C,OAAO,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI,CAAA;AAC1C,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,MAAmC;IAEnC,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,UAAU,CAAA;AAC7C,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare class ConstraintError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ //# sourceMappingURL=ConstraintError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConstraintError.d.ts","sourceRoot":"","sources":["../../src/errors/ConstraintError.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAgB,SAAQ,KAAK;gBACrB,OAAO,EAAE,MAAM;CAInC"}
@@ -0,0 +1,7 @@
1
+ export class ConstraintError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = 'ConstraintError';
5
+ }
6
+ }
7
+ //# sourceMappingURL=ConstraintError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConstraintError.js","sourceRoot":"","sources":["../../src/errors/ConstraintError.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAmB,OAAe;QAChC,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC/B,CAAC;CACF"}
@@ -1,11 +1,12 @@
1
- import { SerializableClass } from '@t4h.framework/core';
1
+ import { SerializableClass, type PromiseLikeType } from '@t4h.framework/core';
2
2
  import { Ref } from './Ref.js';
3
3
  import { RefCollection } from './RefCollection.js';
4
+ import { type EntityMetadata } from '../decorators/metadata.js';
4
5
  import type { FindWhere } from '../typings/FindWhere.js';
5
6
  import type { EntityConstructor, EntityData, EntityInsertData } from '../typings/ORM.js';
6
7
  export interface ORMConfig {
7
8
  connectionString: string;
8
- entities: EntityConstructor[];
9
+ entities: EntityMetadata[];
9
10
  }
10
11
  export interface FindOneOptions<T> {
11
12
  where: FindWhere<T>;
@@ -19,9 +20,28 @@ export interface FindOptions<T> extends FindOneOptions<T> {
19
20
  }
20
21
  export declare class ORM extends SerializableClass {
21
22
  readonly config: ORMConfig;
22
- toSerializable(): string;
23
- protected fromSerializable(connectionString: string): void;
24
- constructor(config: ORMConfig);
23
+ toSerializable(): {
24
+ connectionString: string;
25
+ entities: {
26
+ tableName: string | undefined;
27
+ indexes: {
28
+ properties: string[];
29
+ name: string | undefined;
30
+ }[];
31
+ properties: {
32
+ name: string;
33
+ type: string | undefined;
34
+ nullable: boolean | undefined;
35
+ default: import("@t4h.framework/core").Serializable;
36
+ index: boolean | undefined;
37
+ }[];
38
+ }[];
39
+ };
40
+ protected fromSerializable(serializable: PromiseLikeType<ReturnType<this['toSerializable']>>): void;
41
+ constructor(config: {
42
+ connectionString: string;
43
+ entities: EntityConstructor[];
44
+ });
25
45
  create<T>(entity: EntityConstructor<T>, data: EntityInsertData<T>): Promise<Ref<T>>;
26
46
  create<T>(entity: EntityConstructor<T>, data: EntityInsertData<T>[]): Promise<RefCollection<T>>;
27
47
  findOne<T>(entity: EntityConstructor<T>, options: FindOneOptions<T>): Promise<Ref<T> | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"ORM.d.ts","sourceRoot":"","sources":["../../src/models/ORM.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEhE,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAKlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAGjB,MAAM,mBAAmB,CAAA;AAM1B,MAAM,WAAW,SAAS;IACxB,gBAAgB,EAAE,MAAM,CAAA;IACxB,QAAQ,EAAE,iBAAiB,EAAE,CAAA;CAC9B;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IACnB,OAAO,CAAC,EAAE;SAAG,CAAC,IAAI,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM;KAAE,CAAA;CAC1D;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,qBAAa,GAAI,SAAQ,iBAAiB;aASZ,MAAM,EAAE,SAAS;IARtC,cAAc;IAIrB,SAAS,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI;gBAI9B,MAAM,EAAE,SAAS;IAIhC,MAAM,CAAC,CAAC,EACnB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAEL,MAAM,CAAC,CAAC,EACnB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,GAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAoBf,OAAO,CAAC,CAAC,EACpB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAaZ,IAAI,CAAC,CAAC,EACjB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAaf,MAAM,CAAC,CAAC,EACnB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,OAAO,CAAC;CAGpB"}
1
+ {"version":3,"file":"ORM.d.ts","sourceRoot":"","sources":["../../src/models/ORM.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EACjB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAMlD,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAA;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAGjB,MAAM,mBAAmB,CAAA;AAM1B,MAAM,WAAW,SAAS;IACxB,gBAAgB,EAAE,MAAM,CAAA;IACxB,QAAQ,EAAE,cAAc,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IACnB,OAAO,CAAC,EAAE;SAAG,CAAC,IAAI,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM;KAAE,CAAA;CAC1D;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,qBAAa,GAAI,SAAQ,iBAAiB;IACxC,SAAgB,MAAM,EAAG,SAAS,CAAA;IAE3B,cAAc;;;;;;;;;;;;;;;;;IAsBrB,SAAS,CAAC,gBAAgB,CACxB,YAAY,EAAE,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAChE,IAAI;gBAeK,MAAM,EAAE;QAClB,gBAAgB,EAAE,MAAM,CAAA;QACxB,QAAQ,EAAE,iBAAiB,EAAE,CAAA;KAC9B;IAaY,MAAM,CAAC,CAAC,EACnB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAEL,MAAM,CAAC,CAAC,EACnB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,GAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IA0Bf,OAAO,CAAC,CAAC,EACpB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAaZ,IAAI,CAAC,CAAC,EACjB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAaf,MAAM,CAAC,CAAC,EACnB,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,OAAO,CAAC;CAGpB"}
@@ -1,28 +1,63 @@
1
- import { History, SerializableClass } from '@t4h.framework/core';
1
+ import { History, SerializableClass, } from '@t4h.framework/core';
2
2
  import { Ref } from './Ref.js';
3
3
  import { RefCollection } from './RefCollection.js';
4
4
  import { ORMCreateActivity } from '../activities/ORMCreateActivity.js';
5
5
  import { ORMFindActivity } from '../activities/ORMFindActivity.js';
6
6
  import { ORMFindOneActivity } from '../activities/ORMFindOneActivity.js';
7
- import { getEntityTableName } from '../decorators/metadata.js';
7
+ import { applyDefaultProperties } from '../constraints/apply-default-properties.js';
8
+ import { assertConstraints } from '../constraints/assert-constraints.js';
9
+ import { getEntityMetadata, getEntityTableName, } from '../decorators/metadata.js';
8
10
  const create = History.bind(ORMCreateActivity);
9
11
  const find = History.bind(ORMFindActivity);
10
12
  const findOne = History.bind(ORMFindOneActivity);
11
13
  export class ORM extends SerializableClass {
12
14
  config;
13
15
  toSerializable() {
14
- return this.config.connectionString;
16
+ return {
17
+ connectionString: this.config.connectionString,
18
+ entities: this.config.entities.map(entity => ({
19
+ tableName: entity.tableName,
20
+ indexes: entity.indexes.map(index => ({
21
+ properties: index.properties,
22
+ name: index.name,
23
+ })),
24
+ properties: Array.from(entity.properties.entries()).map(([name, property]) => ({
25
+ name,
26
+ type: property.type,
27
+ nullable: property.nullable,
28
+ default: property.default,
29
+ index: property.index,
30
+ })),
31
+ })),
32
+ };
15
33
  }
16
- fromSerializable(connectionString) {
17
- Object.assign(this, { config: { connectionString } });
34
+ fromSerializable(serializable) {
35
+ Object.assign(this, {
36
+ config: {
37
+ connectionString: serializable.connectionString,
38
+ entities: serializable.entities.map(entity => ({
39
+ tableName: entity.tableName,
40
+ indexes: entity.indexes,
41
+ properties: new Map(entity.properties.map(property => [property.name, property])),
42
+ })),
43
+ },
44
+ });
18
45
  }
19
46
  constructor(config) {
20
47
  super();
21
- this.config = config;
48
+ if (!config)
49
+ return;
50
+ Object.assign(this, {
51
+ config: {
52
+ connectionString: config.connectionString,
53
+ entities: config.entities.map(entity => getEntityMetadata(entity)),
54
+ },
55
+ });
22
56
  }
23
57
  async create(entity, data) {
24
58
  const isBatch = Array.isArray(data);
25
- const rows = isBatch ? data : [data];
59
+ const rows = applyDefaultProperties(isBatch ? data : [data], getEntityMetadata(entity));
60
+ await assertConstraints(entity, rows);
26
61
  const result = await create({
27
62
  orm: this,
28
63
  table: getEntityTableName(entity),
@@ -1 +1 @@
1
- {"version":3,"file":"ORM.js","sourceRoot":"","sources":["../../src/models/ORM.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ORM.js","sourceRoot":"","sources":["../../src/models/ORM.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ export declare class Ref<T> {
5
5
  private readonly entity;
6
6
  private readonly ref;
7
7
  constructor(orm: ORM, entity: EntityConstructor<T>, ref: SerializableRowRef);
8
- getSnapshot(): Promise<T>;
8
+ getSnapshot(): Promise<T | null>;
9
9
  update(data: EntityPartialData<T>): Promise<void>;
10
10
  remove(): Promise<void>;
11
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Ref.d.ts","sourceRoot":"","sources":["../../src/models/Ref.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAKnC,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAEnB,MAAM,mBAAmB,CAAA;AAM1B,qBAAa,GAAG,CAAC,CAAC;IAEd,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAFH,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,GAAG,EAAE,kBAAkB;IAG7B,WAAW,IAAI,OAAO,CAAC,CAAC,CAAC;IAczB,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IASjD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAOrC"}
1
+ {"version":3,"file":"Ref.d.ts","sourceRoot":"","sources":["../../src/models/Ref.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAUnC,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAEnB,MAAM,mBAAmB,CAAA;AAM1B,qBAAa,GAAG,CAAC,CAAC;IAEd,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAFH,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,GAAG,EAAE,kBAAkB;IAG7B,WAAW,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAgBhC,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBjD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAOrC"}
@@ -2,7 +2,9 @@ import { History } from '@t4h.framework/core';
2
2
  import { ORMGetSnapshotActivity } from '../activities/ORMGetSnapshotActivity.js';
3
3
  import { ORMRemoveActivity } from '../activities/ORMRemoveActivity.js';
4
4
  import { ORMUpdateActivity } from '../activities/ORMUpdateActivity.js';
5
- import { getEntityTableName } from '../decorators/metadata.js';
5
+ import { applyDefaultProperties } from '../constraints/apply-default-properties.js';
6
+ import { assertConstraints } from '../constraints/assert-constraints.js';
7
+ import { getEntityMetadata, getEntityTableName, } from '../decorators/metadata.js';
6
8
  const getSnapshotOp = History.bind(ORMGetSnapshotActivity);
7
9
  const update = History.bind(ORMUpdateActivity);
8
10
  const remove = History.bind(ORMRemoveActivity);
@@ -21,16 +23,23 @@ export class Ref {
21
23
  table: getEntityTableName(this.entity),
22
24
  ref: this.ref,
23
25
  });
26
+ if (result === null)
27
+ return null;
24
28
  const entity = Reflect.construct(this.entity, []);
25
29
  Object.assign(entity, result);
26
30
  return entity;
27
31
  }
28
32
  async update(data) {
33
+ const keys = Object.keys(data);
34
+ const row = applyDefaultProperties(data, getEntityMetadata(this.entity), keys);
35
+ await assertConstraints(this.entity, [row], {
36
+ keys,
37
+ });
29
38
  await update({
30
39
  orm: this.orm,
31
40
  table: getEntityTableName(this.entity),
32
41
  ref: this.ref,
33
- data: data,
42
+ data: row,
34
43
  });
35
44
  }
36
45
  async remove() {
@@ -1 +1 @@
1
- {"version":3,"file":"Ref.js","sourceRoot":"","sources":["../../src/models/Ref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAG7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAA;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAA;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAQ9D,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;AAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;AAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;AAE9C,MAAM,OAAO,GAAG;IAEK;IACA;IACA;IAHnB,YACmB,GAAQ,EACR,MAA4B,EAC5B,GAAuB;QAFvB,QAAG,GAAH,GAAG,CAAK;QACR,WAAM,GAAN,MAAM,CAAsB;QAC5B,QAAG,GAAH,GAAG,CAAoB;IACvC,CAAC;IAEG,KAAK,CAAC,WAAW;QACtB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACjC,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;YACtC,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAW,CAAA;QAE3D,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAE7B,OAAO,MAAW,CAAA;IACpB,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,IAA0B;QAC5C,MAAM,MAAM,CAAC;YACX,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;YACtC,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,IAAqB;SAC5B,CAAC,CAAA;IACJ,CAAC;IAEM,KAAK,CAAC,MAAM;QACjB,MAAM,MAAM,CAAC;YACX,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;YACtC,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAA;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"Ref.js","sourceRoot":"","sources":["../../src/models/Ref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAG7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAA;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAA;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAA;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAA;AACxE,OAAO,EACL,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,2BAA2B,CAAA;AAQlC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;AAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;AAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;AAE9C,MAAM,OAAO,GAAG;IAEK;IACA;IACA;IAHnB,YACmB,GAAQ,EACR,MAA4B,EAC5B,GAAuB;QAFvB,QAAG,GAAH,GAAG,CAAK;QACR,WAAM,GAAN,MAAM,CAAsB;QAC5B,QAAG,GAAH,GAAG,CAAoB;IACvC,CAAC;IAEG,KAAK,CAAC,WAAW;QACtB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACjC,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;YACtC,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAA;QAEF,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAA;QAEhC,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAW,CAAA;QAE3D,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAE7B,OAAO,MAAW,CAAA;IACpB,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,IAA0B;QAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAE9B,MAAM,GAAG,GAAG,sBAAsB,CAChC,IAAqB,EACrB,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,EAC9B,IAAI,CACY,CAAA;QAElB,MAAM,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE;YAC1C,IAAI;SACL,CAAC,CAAA;QAEF,MAAM,MAAM,CAAC;YACX,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;YACtC,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,GAAG;SACV,CAAC,CAAA;IACJ,CAAC;IAEM,KAAK,CAAC,MAAM;QACjB,MAAM,MAAM,CAAC;YACX,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;YACtC,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAA;IACJ,CAAC;CACF"}
package/dist/orm.d.ts CHANGED
@@ -1,11 +1,14 @@
1
1
  export * from './claims/ORMClaim.js';
2
+ export * from './errors/ConstraintError.js';
2
3
  export * from './decorators/Entity.js';
4
+ export * from './decorators/Index.js';
3
5
  export * from './decorators/Property.js';
4
6
  export * from './decorators/metadata.js';
5
7
  export * from './models/ORM.js';
6
8
  export * from './models/Ref.js';
7
9
  export * from './models/RefCollection.js';
8
10
  export * from './activities/ORMCreateActivity.js';
11
+ export * from './activities/ORMFindOneActivity.js';
9
12
  export * from './activities/ORMRemoveActivity.js';
10
13
  export * from './activities/ORMFindActivity.js';
11
14
  export * from './activities/ORMGetSnapshotActivity.js';
package/dist/orm.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"orm.d.ts","sourceRoot":"","sources":["../src/orm.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA;AAEpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2BAA2B,CAAA;AAEzC,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,wCAAwC,CAAA;AACtD,cAAc,mCAAmC,CAAA;AAEjD,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"orm.d.ts","sourceRoot":"","sources":["../src/orm.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA;AAEpC,cAAc,6BAA6B,CAAA;AAE3C,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2BAA2B,CAAA;AAEzC,cAAc,mCAAmC,CAAA;AACjD,cAAc,oCAAoC,CAAA;AAClD,cAAc,mCAAmC,CAAA;AACjD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,wCAAwC,CAAA;AACtD,cAAc,mCAAmC,CAAA;AAEjD,cAAc,kBAAkB,CAAA"}
package/dist/orm.js CHANGED
@@ -1,11 +1,14 @@
1
1
  export * from './claims/ORMClaim.js';
2
+ export * from './errors/ConstraintError.js';
2
3
  export * from './decorators/Entity.js';
4
+ export * from './decorators/Index.js';
3
5
  export * from './decorators/Property.js';
4
6
  export * from './decorators/metadata.js';
5
7
  export * from './models/ORM.js';
6
8
  export * from './models/Ref.js';
7
9
  export * from './models/RefCollection.js';
8
10
  export * from './activities/ORMCreateActivity.js';
11
+ export * from './activities/ORMFindOneActivity.js';
9
12
  export * from './activities/ORMRemoveActivity.js';
10
13
  export * from './activities/ORMFindActivity.js';
11
14
  export * from './activities/ORMGetSnapshotActivity.js';
package/dist/orm.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"orm.js","sourceRoot":"","sources":["../src/orm.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA;AAEpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2BAA2B,CAAA;AAEzC,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,wCAAwC,CAAA;AACtD,cAAc,mCAAmC,CAAA;AAEjD,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"orm.js","sourceRoot":"","sources":["../src/orm.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA;AAEpC,cAAc,6BAA6B,CAAA;AAE3C,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2BAA2B,CAAA;AAEzC,cAAc,mCAAmC,CAAA;AACjD,cAAc,oCAAoC,CAAA;AAClD,cAAc,mCAAmC,CAAA;AACjD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,wCAAwC,CAAA;AACtD,cAAc,mCAAmC,CAAA;AAEjD,cAAc,kBAAkB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t4h.framework/orm",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "ORM module for the T4H Framework",
5
5
  "homepage": "https://github.com/tech4humans-brasil/framework/tree/main/packages/orm",
6
6
  "bugs": "https://github.com/tech4humans-brasil/framework/issues",
@@ -20,7 +20,8 @@
20
20
  "types": "./dist/orm.d.ts",
21
21
  "files": [
22
22
  "dist",
23
- "LICENSE"
23
+ "LICENSE",
24
+ ".ai"
24
25
  ],
25
26
  "scripts": {
26
27
  "build": "tsc --project tsconfig.build.json",
@@ -31,14 +32,15 @@
31
32
  "test:watch": "vitest"
32
33
  },
33
34
  "dependencies": {
34
- "@t4h.framework/core": "^0.2.0"
35
+ "reflect-metadata": "^0.2.2"
35
36
  },
36
37
  "devDependencies": {
38
+ "@t4h.framework/core": "^0.6.0",
37
39
  "typescript": "^5.9.3",
38
40
  "vitest": "^4.0.18"
39
41
  },
40
42
  "peerDependencies": {
41
- "@t4h.framework/core": "^0.2.0"
43
+ "@t4h.framework/core": "^0.6.0"
42
44
  },
43
45
  "packageManager": "yarn@4.12.0",
44
46
  "engines": {