@t4h.framework/orm 0.3.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.
- package/.ai/skills/framework-orm/SKILL.md +325 -0
- package/README.md +54 -0
- package/dist/activities/ORMGetSnapshotActivity.d.ts +3 -3
- package/dist/activities/ORMGetSnapshotActivity.d.ts.map +1 -1
- package/dist/activities/ORMGetSnapshotActivity.js.map +1 -1
- package/dist/claims/ORMClaim.d.ts +1 -1
- package/dist/claims/ORMClaim.d.ts.map +1 -1
- package/dist/constraints/__tests__/create-entity-metadata.d.ts +3 -0
- package/dist/constraints/__tests__/create-entity-metadata.d.ts.map +1 -0
- package/dist/constraints/__tests__/create-entity-metadata.js +10 -0
- package/dist/constraints/__tests__/create-entity-metadata.js.map +1 -0
- package/dist/constraints/apply-default-properties.d.ts +7 -0
- package/dist/constraints/apply-default-properties.d.ts.map +1 -0
- package/dist/constraints/apply-default-properties.js +16 -0
- package/dist/constraints/apply-default-properties.js.map +1 -0
- package/dist/constraints/assert-constraints.d.ts +7 -0
- package/dist/constraints/assert-constraints.d.ts.map +1 -0
- package/dist/constraints/assert-constraints.js +13 -0
- package/dist/constraints/assert-constraints.js.map +1 -0
- package/dist/constraints/assert-non-nullable-property-constraint.d.ts +7 -0
- package/dist/constraints/assert-non-nullable-property-constraint.d.ts.map +1 -0
- package/dist/constraints/assert-non-nullable-property-constraint.js +14 -0
- package/dist/constraints/assert-non-nullable-property-constraint.js.map +1 -0
- package/dist/constraints/assert-property-type-constraint.d.ts +7 -0
- package/dist/constraints/assert-property-type-constraint.d.ts.map +1 -0
- package/dist/constraints/assert-property-type-constraint.js +30 -0
- package/dist/constraints/assert-property-type-constraint.js.map +1 -0
- package/dist/constraints/assert-unique-constraint.d.ts +11 -0
- package/dist/constraints/assert-unique-constraint.d.ts.map +1 -0
- package/dist/constraints/assert-unique-constraint.js +41 -0
- package/dist/constraints/assert-unique-constraint.js.map +1 -0
- package/dist/decorators/Index.d.ts +6 -0
- package/dist/decorators/Index.d.ts.map +1 -0
- package/dist/decorators/Index.js +10 -0
- package/dist/decorators/Index.js.map +1 -0
- package/dist/decorators/Property.d.ts +1 -0
- package/dist/decorators/Property.d.ts.map +1 -1
- package/dist/decorators/Property.js +17 -1
- package/dist/decorators/Property.js.map +1 -1
- package/dist/decorators/metadata.d.ts +5 -2
- package/dist/decorators/metadata.d.ts.map +1 -1
- package/dist/decorators/metadata.js +1 -1
- package/dist/decorators/metadata.js.map +1 -1
- package/dist/errors/ConstraintError.d.ts +4 -0
- package/dist/errors/ConstraintError.d.ts.map +1 -0
- package/dist/errors/ConstraintError.js +7 -0
- package/dist/errors/ConstraintError.js.map +1 -0
- package/dist/models/ORM.d.ts +25 -5
- package/dist/models/ORM.d.ts.map +1 -1
- package/dist/models/ORM.js +42 -7
- package/dist/models/ORM.js.map +1 -1
- package/dist/models/Ref.d.ts +1 -1
- package/dist/models/Ref.d.ts.map +1 -1
- package/dist/models/Ref.js +11 -2
- package/dist/models/Ref.js.map +1 -1
- package/dist/orm.d.ts +3 -0
- package/dist/orm.d.ts.map +1 -1
- package/dist/orm.js +3 -0
- package/dist/orm.js.map +1 -1
- 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,
|
|
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,
|
|
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;
|
|
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 @@
|
|
|
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 @@
|
|
|
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 +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;
|
|
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
|
-
...
|
|
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,
|
|
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
|
-
|
|
10
|
-
|
|
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;
|
|
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":"
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|
package/dist/models/ORM.d.ts
CHANGED
|
@@ -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:
|
|
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():
|
|
23
|
-
|
|
24
|
-
|
|
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>;
|
package/dist/models/ORM.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ORM.d.ts","sourceRoot":"","sources":["../../src/models/ORM.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
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"}
|
package/dist/models/ORM.js
CHANGED
|
@@ -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 {
|
|
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
|
|
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(
|
|
17
|
-
Object.assign(this, {
|
|
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
|
-
|
|
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),
|
package/dist/models/ORM.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ORM.js","sourceRoot":"","sources":["../../src/models/ORM.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ORM.js","sourceRoot":"","sources":["../../src/models/ORM.ts"],"names":[],"mappings":"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"}
|
package/dist/models/Ref.d.ts
CHANGED
|
@@ -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
|
}
|
package/dist/models/Ref.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/models/Ref.js
CHANGED
|
@@ -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 {
|
|
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:
|
|
42
|
+
data: row,
|
|
34
43
|
});
|
|
35
44
|
}
|
|
36
45
|
async remove() {
|
package/dist/models/Ref.js.map
CHANGED
|
@@ -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,
|
|
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.
|
|
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
|
-
"
|
|
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.
|
|
43
|
+
"@t4h.framework/core": "^0.6.0"
|
|
42
44
|
},
|
|
43
45
|
"packageManager": "yarn@4.12.0",
|
|
44
46
|
"engines": {
|