@t4h.framework/orm 0.11.4 → 0.11.7

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.
@@ -1,351 +1,133 @@
1
1
  ---
2
2
  name: framework-orm
3
3
  description: >-
4
- Guides correct use of @t4h.framework/orm in T4H Framework workflows: entity
5
- decorators (@Entity, @Property, @Index), the ORM model (create, upsert, find, findOne,
6
- exists, delete), 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
- workflows with TestWorkflowEnvironment, or working in packages/orm.
4
+ Guides the use of @t4h.framework/orm in T4H Framework workflows: entity
5
+ decorators (@Entity, @Property, @Index, @ManyToOne, @OneToMany), the ORM
6
+ class (create, upsert, find, findOne, exists, delete), Ref, RefCollection and
7
+ MapCollection, getSnapshot with populate, where operators ($in, $like, $or,
8
+ ...), ConstraintError, and ORMClaim. Use when you define database entities,
9
+ read or write rows in a workflow, model relations between tables, give or
10
+ mock ORMClaim in a test with TestWorkflowEnvironment, or write an ORMClaim
11
+ implementation.
10
12
  ---
11
13
 
12
14
  # @t4h.framework/orm
13
15
 
14
- ORM activities, claim, and models for database operations within workflows. Package path: `framework/packages/orm`. Peer dependency: `@t4h.framework/core`.
16
+ Each `ORM`, `Ref` and `RefCollection` call is an activity recorded in the
17
+ workflow history. The runtime gives the database through `ORMClaim`.
15
18
 
16
- Import from the package entry `@t4h.framework/orm`. Its `exports` map has only `.`, so `tsc` rejects a deep import.
19
+ ## Define an entity
17
20
 
18
- ```typescript
19
- import {
20
- Entity, Property, Index, ORM, Ref, RefCollection,
21
- ORMClaim, ConstraintError,
22
- ORMCreateActivity, ORMFindActivity, ORMFindOneActivity,
23
- ORMGetSnapshotActivity, ORMUpdateActivity, ORMRemoveActivity,
24
- ORMDeleteActivity,
25
- getEntityMetadata, getEntityTableName, getEntityProperties,
26
- type EntityInsertData, type EntityPartialData, type FindWhere,
27
- type SerializableCreateInput, type SerializableFindInput,
28
- type SerializableGetSnapshotInput, type SerializableUpdateInput,
29
- type SerializableRemoveInput, type SerializableDeleteInput,
30
- } from '@t4h.framework/orm'
31
- ```
32
-
33
- Node `>=22`. See [README.md](../../../README.md).
34
-
35
- ---
36
-
37
- ## Architecture
38
-
39
- `Workflow` → `ORM` / `Ref` methods (`History.bind` on ORM activities) → `ORMClaim` (runtime database adapter).
40
-
41
- | Layer | Role |
42
- |-------|------|
43
- | **ORM** | High-level API; applies defaults + constraints before activities |
44
- | **Ref** / **RefCollection** | Row handles returned by create/find |
45
- | **Activities** | Shipped, replay-safe activities the `ORM`/`Ref` APIs drive; delegate to `ORMClaim` |
46
- | **ORMClaim** | Abstract claim; runtime provides concrete DB implementation |
47
-
48
- ---
49
-
50
- ## Defining entities
51
-
52
- Set `experimentalDecorators` and `emitDecoratorMetadata` to `true` in the `compilerOptions` of the project `tsconfig.json`.
53
-
54
- Import `reflect-metadata` where decorators are evaluated (Property decorator imports it).
55
-
56
- ### @Entity
21
+ 1. Enable `experimentalDecorators` and `emitDecoratorMetadata` in
22
+ `tsconfig.json`.
23
+ 2. Decorate the class with `@Entity({ tableName })` (required option) and each
24
+ column with `@Property`.
25
+ 3. Declare `id` and each property with a `default` as optional. Also set
26
+ `nullable: true` on `id`: the store sets it.
57
27
 
58
28
  ```typescript
59
29
  @Entity({ tableName: 'users' })
60
30
  class User {
61
- @Property({ type: 'string' })
62
- public name!: string
31
+ @Property({ type: 'uuid', nullable: true })
32
+ public id?: string
63
33
 
64
- @Property({ type: 'string' })
34
+ @Property({ type: 'string', index: true })
65
35
  public email!: string
66
36
 
67
37
  @Property({ type: 'boolean', default: true })
68
- public active!: boolean
38
+ public active?: boolean
69
39
  }
70
40
  ```
71
41
 
72
- - `tableName` is optional; defaults to the class name (`User` → `"User"`).
73
- - Use `getEntityTableName(User)` or rely on ORM to resolve the table name.
42
+ ## Create the ORM once
74
43
 
75
- ### @Property
76
-
77
- Options: `type?`, `nullable?` (default required), `default?`, `index?` (adds index metadata).
78
-
79
- 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.
80
-
81
- ### @Index
82
-
83
- Class-level composite indexes:
84
-
85
- ```typescript
86
- @Index({ properties: ['tenantId', 'email'], name: 'accounts_tenant_email_idx' })
87
- class Account { /* ... */ }
88
- ```
89
-
90
- An empty `properties` throws (`decorators/Index.ts`). Per-property `@Property({ index: true })` also registers `{ properties: [propertyKey] }`.
91
-
92
- ---
93
-
94
- ## ORM configuration
95
-
96
- `ORM` extends `SerializableClass` — instances can be serialized for workflow persistence. `connectionString` is typed `Secret` (a string is a `tsc` error): pass the `EnvDesign` entry declared `type: Secret`. The host reads the value where each query runs.
44
+ Declare `DATABASE_URL: { type: Secret }` with `EnvDesign` in
45
+ `src/constants/environments.ts`, and create the `ORM` at module level, not in
46
+ the workflow function:
97
47
 
98
48
  ```typescript
99
49
  import { environments } from '../constants/environments.js'
100
50
 
101
- const orm = new ORM({
102
- connectionString: environments.DATABASE_URL, // Secret
103
- entities: [User, Product],
104
- })
105
- ```
106
-
107
- - `entities`: array of entity **constructors** (decorated classes).
108
- - `config.entities` stores resolved `EntityMetadata` (table name, properties map, indexes).
109
-
110
- Restore from serialized state:
111
-
112
- ```typescript
113
- const orm = await ORM.fromSerializable(serialized, v => v)
114
- ```
115
-
116
- ---
117
-
118
- ## CRUD in workflows
119
-
120
- ORM methods bind activities via `History.bind` — calls inside a workflow are **reconciler-driven** (replay-safe).
121
-
122
- ### Create
123
-
124
- ```typescript
125
- // Single row → Ref<T>
126
- const userRef = await orm.create(User, {
127
- name: 'John',
128
- email: 'john@example.com',
129
- active: true,
130
- })
131
-
132
- // Batch → RefCollection<T>
133
- const usersRef = await orm.create(User, [
134
- { name: 'Alice', email: 'alice@example.com', active: true },
135
- { name: 'Bob', email: 'bob@example.com', active: true },
136
- ])
137
- ```
138
-
139
- Defaults are applied before persistence (`applyDefaultProperties`). Omitted fields with `@Property({ default })` are filled in.
140
-
141
- ### Upsert
142
-
143
- ```typescript
144
- // Single row → Ref<T>; array → RefCollection<T>
145
- const userRef = await orm.upsert(
146
- User,
147
- { email: 'john@example.com', name: 'John', active: true },
148
- { conflictOn: ['email'] },
149
- )
150
- ```
151
-
152
- Rows are validated like `create`. If a row matching `conflictOn` (equality on every listed property) exists, only the passed fields are written; defaults apply on insert only. An empty `conflictOn`, or a row with no value for a `conflictOn` property, throws (`ConstraintError` for a missing key, `Error` for an empty `conflictOn`). The call is a single `ORMUpsertActivity` backed by `ORMClaim.upsert`, which has a default (`find`, then `create` or `update`) — mock `upsert` in tests, or `find`/`create`/`update` if the mock extends `ORMClaim`. A retry after a crash updates instead of duplicating, but it is not atomic across workflows: concurrent writes of the same key may both insert.
153
-
154
- ### Find
155
-
156
- ```typescript
157
- const userRef = await orm.findOne(User, {
158
- where: { email: 'john@example.com' },
159
- orderBy: { name: 'asc' },
160
- }) // Ref<User> | null
161
-
162
- const usersRef = await orm.find(User, {
163
- where: { active: true },
164
- orderBy: { name: 'asc' },
165
- limit: 10,
166
- offset: 0,
167
- }) // RefCollection<User>
168
-
169
- const exists = await orm.exists(User, {
170
- where: { email: 'john@example.com' },
171
- }) // boolean (delegates to findOne)
172
-
173
- const deleted = await orm.delete(User, {
174
- where: { active: false },
175
- }) // number — deletes every match; `{}` empties the table
176
- ```
177
-
178
- `findOne` activity internally calls `claim.find` with `limit: 1`.
179
-
180
- ### Ref operations
181
-
182
- ```typescript
183
- const snapshot = await userRef.getSnapshot() // T | null — entity instance
184
- await userRef.update({ name: 'Jane' }) // partial patch only
185
- await userRef.remove()
186
- ```
187
-
188
- `getSnapshot` returns `null` when the row no longer exists. `update` validates only keys present in the patch.
189
-
190
- **RefCollection:** `toArray()`, `length`, `at(i)`, async `forEach`/`map`/`filter`, `Symbol.iterator`.
191
-
192
- ---
193
-
194
- ## Query operators
195
-
196
- `where` uses `FindWhere<T>` — implicit equality or operator objects:
197
-
198
- ```typescript
199
- await orm.find(User, {
200
- where: {
201
- name: 'John', // $eq (implicit)
202
- active: { $ne: false },
203
- email: { $like: '%@example%' },
204
- age: { $gte: 18, $lt: 65 },
205
- status: { $in: ['active', 'pending'] },
206
- $or: [{ name: 'Alice' }, { name: 'Bob' }],
207
- $and: [{ active: true }, { age: { $gte: 18 } }],
208
- },
51
+ export const orm = new ORM({
52
+ connectionString: environments.DATABASE_URL,
53
+ entities: [User, Post],
209
54
  })
210
55
  ```
211
56
 
212
- Available operators: `$eq`, `$ne`, `$in`, `$nin`, `$not`, `$gt`, `$gte`, `$lt`, `$lte`, `$like`, `$ilike`, `$and`, `$or`.
213
-
214
- ---
215
-
216
- ## Constraint validation
217
-
218
- Validation runs in the ORM library (`ORM.create`, `ORM.upsert` and `Ref.update`), **not** in `ORMClaim` implementations. Failures throw `ConstraintError`.
219
-
220
- ### Create pipeline
221
-
222
- 1. `applyDefaultProperties` — fills `default` for `undefined` fields
223
- 2. `assertPropertyTypeConstraint` — validates declared types
224
- 3. `assertNonNullablePropertyConstraint` — required fields must be present
225
-
226
- ### Update pipeline
227
-
228
- 1. Defaults only for keys present in the patch
229
- 2. Same asserts, scoped to patch keys via `{ keys: Object.keys(data) }`
230
-
231
- ### Handling errors
57
+ ## Read and write
232
58
 
233
59
  ```typescript
234
- import { ConstraintError, ORM } from '@t4h.framework/orm'
60
+ const userRef = await orm.create(User, { email: input.email }) // Ref<User>
61
+ const found = await orm.findOne(User, { where: { email: input.email } }) // Ref<User> | null
62
+ const active = await orm.find(User, { where: { active: true }, limit: 10 }) // RefCollection<User>
235
63
 
236
- try {
237
- await orm.create(User, { email: 'bad' } as EntityInsertData<User>)
238
- } catch (error) {
239
- if (error instanceof ConstraintError) {
240
- // e.g. 'Property "name" is required'
241
- // e.g. 'Property "name" must be of type string'
242
- }
243
- }
64
+ const user = await userRef.getSnapshot() // User | null
65
+ await userRef.update({ active: false }) // partial patch
66
+ const snapshots = await active.getSnapshots() // one activity for all refs
244
67
  ```
245
68
 
246
- Constraint checks run **before** activities are invoked — failed creates/updates never reach `ORMClaim`.
69
+ ## Relations
247
70
 
248
- ---
249
-
250
- ## ORMClaim (runtime dependency)
251
-
252
- Runtime must register a concrete implementation:
71
+ The `@ManyToOne` side owns the column and is a `Ref<T>`. The `@OneToMany` side
72
+ is a lazy `MapCollection<T>`. Read related rows in the same activity with
73
+ `populate`:
253
74
 
254
75
  ```typescript
255
- { provide: ORMClaim, value: new MyORMClaimImpl() }
256
- ```
76
+ @OneToMany(() => Post, post => post.author)
77
+ public posts!: MapCollection<Post>
257
78
 
258
- Contract:
79
+ @ManyToOne(() => User)
80
+ public author!: Ref<User>
259
81
 
260
- ```typescript
261
- abstract class ORMClaim<R extends SerializableRowRef> {
262
- abstract find(input: SerializableFindInput): R[] | Promise<R[]>
263
- abstract create(input: SerializableCreateInput): R[] | Promise<R[]>
264
- abstract getSnapshot(input: SerializableGetSnapshotInput<R>): SerializedRow | null | Promise<SerializedRow | null>
265
- abstract update(input: SerializableUpdateInput<R>): void | Promise<void>
266
- abstract remove(input: SerializableRemoveInput<R>): void | Promise<void>
267
- upsert(input: SerializableUpsertInput): Promise<R[]> // default: find, then create/update; override for a native upsert
268
- abstract delete(input: SerializableDeleteInput): number | Promise<number>
269
- }
82
+ const user = await userRef.getSnapshot({ populate: ['posts.comments'] })
83
+ const titles = await user?.posts.map(post => post.title)
270
84
  ```
271
85
 
272
- Activity inputs always include `orm` + `table`; create adds `data[]`, find and delete add `where` (find also takes optional `orderBy`/`limit`/`offset`), snapshot/update/remove add `ref` (opaque `Serializable` row handle). Update also includes partial `data`. Upsert adds `conflictOn` and `data: { insert, update }[]` — `insert` is the full row with defaults, `update` only the caller's fields; return refs in input order.
273
-
274
- ---
275
-
276
- ## Activities
277
-
278
- These are the **shipped, replay-safe activities** the `ORM`/`Ref` APIs drive for you (you can also pass them to `History.reconciler` directly). `@t4h.framework/core/no-framework-activity-in-app` rejects `new` and `extends` on them:
279
-
280
- | Activity | Input | Output |
281
- |----------|-------|--------|
282
- | `ORMCreateActivity` | `SerializableCreateInput` | `SerializableRowRef[]` |
283
- | `ORMFindActivity` | `SerializableFindInput` | `SerializableRowRef[]` |
284
- | `ORMFindOneActivity` | `SerializableFindInput` | `SerializableRowRef \| null` |
285
- | `ORMGetSnapshotActivity` | `SerializableGetSnapshotInput` | `SerializedRow \| null` |
286
- | `ORMUpdateActivity` | `SerializableUpdateInput` | `void` |
287
- | `ORMRemoveActivity` | `SerializableRemoveInput` | `void` |
288
- | `ORMDeleteActivity` | `SerializableDeleteInput` | `number` |
289
-
290
- Prefer **`ORM` / `Ref` APIs** in workflow code — they apply constraints and return typed handles. Use activities directly only for advanced/testing scenarios.
291
-
292
- ---
293
-
294
- ## Workflow example
295
-
296
- Define entities, instantiate `ORM` with `connectionString` + `entities`, and use it inside a `Workflow`:
297
-
298
- ```typescript
299
- export const orm = new ORM({ connectionString: environments.DATABASE_URL, entities: [User] })
300
-
301
- export const ormWorkflow = new Workflow({ id: 'orm' }, async () => {
302
- await orm.create(User, { name: 'John', email: 'john@example.com', age: 20 })
303
- const user = await orm.findOne(User, { where: { email: 'john@example.com' } })
304
- await user?.update({ name: 'John Updated' })
305
- await user?.remove()
306
- return { user }
307
- })
308
- ```
309
-
310
- Ensure the runtime provides `ORMClaim`.
311
-
312
- ---
313
-
314
- ## Testing
315
-
316
- Test the **workflow** with `TestWorkflowEnvironment` from
317
- `@t4h.framework/core/testing`, mocking `ORMClaim` — the single claim the ORM
318
- activities resolve. Provide the methods your workflow triggers (`create`, `upsert`, `find`,
319
- `findOne`, `getSnapshot`, `update`, `remove`). See the **framework-workflow-testing**
320
- skill for the harness API.
86
+ ## Traps
87
+
88
+ - `getSnapshot()` returns `null` when the row no longer exists. A populated
89
+ `@ManyToOne` can also be `null`, also when the relation is not nullable.
90
+ - A snapshot is a copy. Write through the `Ref` (`ref.update`), and use
91
+ `ref.load('author')` to get the `Ref` of a related row.
92
+ - `MapCollection` is not a promise. Call a method (`toArray()`, `map()`,
93
+ `count()`); do not `await user.posts`.
94
+ - `refs.map(ref => ref.getSnapshot())` runs one activity per ref. Use
95
+ `refs.getSnapshots()` or `populate`.
96
+ - A populate is the output of one activity and goes into the history. Keep it
97
+ narrow on large relations; filter with `where` and `limit`.
98
+ - `orm.delete(User, { where: {} })` deletes every row of the table.
99
+ - `upsert` needs a non-empty `conflictOn` and a value for each listed property.
100
+ It is not atomic across workflows: two workflows can both insert.
101
+ - A bad row throws `ConstraintError` before an activity runs.
102
+ - Do not construct or extend the `ORM*Activity` classes. The lint rule
103
+ `@t4h.framework/core/no-framework-activity-in-app` rejects it. Use `ORM` and
104
+ `Ref`.
105
+ - To write a relation, give a `Ref` (or the data of a new row in `create`).
106
+ You cannot write the `@OneToMany` side of an existing row.
107
+
108
+ ## Test
109
+
110
+ Give `ORMClaim` with `mockClaim` and mock only what the workflow calls.
111
+ `ORMClaim` has no `findOne` (it calls `find` with `limit: 1`), and
112
+ `getSnapshot` on a `Ref` calls `getSnapshots`:
321
113
 
322
114
  ```typescript
323
115
  import { TestWorkflowEnvironment, mockClaim } from '@t4h.framework/core/testing'
324
116
  import { ORMClaim } from '@t4h.framework/orm'
325
117
 
326
- const mockCreate = vi.fn().mockImplementation(async () => [{ id: 1 }])
327
- const mockFindOne = vi.fn().mockImplementation(async () => ({ id: 1, name: 'John' }))
328
-
329
- const env = TestWorkflowEnvironment.create({ now: 0 })
118
+ const create = vi.fn(async () => [{ id: 1 }])
119
+ const getSnapshots = vi.fn(async () => [{ id: 1, email: 'john@example.com' }])
330
120
 
331
- await env.execute(workflow, input, {
332
- claims: [mockClaim(ORMClaim, { create: mockCreate, findOne: mockFindOne })],
121
+ await TestWorkflowEnvironment.create().execute(onboard, input, {
122
+ claims: [mockClaim(ORMClaim, { create, getSnapshots })],
333
123
  })
334
124
  ```
335
125
 
336
- Constraint/validation errors are applied by the `ORM`/`Ref` layer before the
337
- activity runs, so you can assert an invalid input rejects without the claim being
338
- called: `expect(mockCreate).not.toHaveBeenCalled()`.
339
-
340
- ---
341
-
342
- ## Checklist for agents
343
-
344
- 1. **`@Entity` + `@Property`** on each entity class.
345
- 2. Register entities in **`ORM({ entities: [...] })`**; runtime provides **`ORMClaim`**.
346
- 3. Use **`orm` / `Ref` APIs** in workflows — not raw SQL or direct claim calls.
347
- 4. Handle **`ConstraintError`**; validation runs before activities.
348
- 5. **`Ref.update`** is partial; **`getSnapshot`** returns entity instances.
349
- 6. Test workflows with **`TestWorkflowEnvironment`** + **`mockClaim(ORMClaim, ...)`**.
126
+ ## Reference
350
127
 
351
- See also: `packages/orm/README.md`; **framework-workflow-testing** for the test harness.
128
+ - Overview, runtime and tests: https://tech4humans-brasil.github.io/framework/orm/
129
+ - Entities and validation: https://tech4humans-brasil.github.io/framework/orm/entities
130
+ - Queries, upsert, delete, operators: https://tech4humans-brasil.github.io/framework/orm/queries
131
+ - `Ref` and `RefCollection`: https://tech4humans-brasil.github.io/framework/orm/records
132
+ - Relations, populate, `MapCollection`: https://tech4humans-brasil.github.io/framework/orm/relations
133
+ - Types: `node_modules/@t4h.framework/orm/dist/orm.d.ts`
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @t4h.framework/orm
2
2
 
3
+ ## 0.11.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [#276](https://github.com/tech4humans-brasil/framework/pull/276) [`7b38934`](https://github.com/tech4humans-brasil/framework/commit/7b38934e8f9207c98c33afcd76e3a7a4da7e8b14) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - The samples compile against the declared model. The docs give the peer, the `tsconfig` setting, and what a claim must do: `getSnapshot`, and `find` with `$in`, `limit`, `offset` and `orderBy`.
8
+
9
+ ## 0.11.6
10
+
11
+ ### Patch Changes
12
+
13
+ - [#271](https://github.com/tech4humans-brasil/framework/pull/271) [`a2763a2`](https://github.com/tech4humans-brasil/framework/commit/a2763a26fbc466009293389c76036af75070a945) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Replaces the double casts, `as never` and the conditional spreads in the source with real types and type guards. The behavior and the public API do not change.
14
+
15
+ ## 0.11.5
16
+
17
+ ### Patch Changes
18
+
19
+ - [#257](https://github.com/tech4humans-brasil/framework/pull/257) [`586bfb4`](https://github.com/tech4humans-brasil/framework/commit/586bfb4663f4a478527ee0c8db360603f034d615) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - The orm README is short and points to the docs site. The docs and the skill now match the source: the entity examples declare `id` as optional, and a test mocks `find` and `getSnapshots` of `ORMClaim`, not `findOne`.
20
+
3
21
  ## 0.11.4
4
22
 
5
23
  ### Patch Changes
package/README.md CHANGED
@@ -1,308 +1,50 @@
1
1
  # @t4h.framework/orm
2
2
 
3
- ORM activities, claim, and models for database operations within workflows.
3
+ Durable, replay-safe database access for workflows. You describe tables as
4
+ decorated classes and read and write them through `ORM`, `Ref` and
5
+ `RefCollection`. The runtime gives the database through `ORMClaim`.
4
6
 
5
- ## Claim
7
+ ## Installation
6
8
 
7
- ### ORMClaim
8
-
9
- Abstract dependency for database operations. The runtime must provide a concrete implementation (e.g. PostgreSQL, SQLite).
10
-
11
- ```typescript
12
- import { ORMClaim } from '@t4h.framework/orm'
13
- ```
14
-
15
- ### Interface
16
-
17
- ```typescript
18
- abstract class ORMClaim<R extends SerializableRowRef> {
19
- public abstract find(input: SerializableFindInput): R[] | Promise<R[]>
20
- public abstract create(input: SerializableCreateInput): R[] | Promise<R[]>
21
- public abstract getSnapshot(input: SerializableGetSnapshotInput<R>): SerializedRow | Promise<SerializedRow>
22
- public abstract update(input: SerializableUpdateInput<R>): void | Promise<void>
23
- public abstract remove(input: SerializableRemoveInput<R>): void | Promise<void>
24
- public abstract getSnapshots(input: SerializableGetSnapshotsInput<R>): (SerializedRow | null)[] | Promise<(SerializedRow | null)[]>
25
- public abstract delete(input: SerializableDeleteInput): number | Promise<number>
26
-
27
- // Default: find, then create or update. Override for a native upsert.
28
- public upsert(input: SerializableUpsertInput): Promise<R[]>
29
- }
9
+ ```bash
10
+ npm install @t4h.framework/orm
30
11
  ```
31
12
 
32
- ## Defining Entities
13
+ Peer dependency: `@t4h.framework/core`. Enable `experimentalDecorators` and
14
+ `emitDecoratorMetadata` in `tsconfig.json`.
33
15
 
34
- Use the `@Entity` and `@Property` decorators to define database entities:
16
+ ## Usage
35
17
 
36
18
  ```typescript
37
- import { Entity, Property } from '@t4h.framework/orm'
19
+ import { Workflow } from '@t4h.framework/core'
20
+ import { Entity, ORM, Property } from '@t4h.framework/orm'
21
+
22
+ import { environments } from './constants/environments.js'
38
23
 
39
24
  @Entity({ tableName: 'users' })
40
25
  class User {
41
26
  @Property({ type: 'uuid', nullable: true })
42
27
  public id?: string
43
28
 
44
- @Property({ type: 'string' })
45
- public name!: string
46
-
47
29
  @Property({ type: 'string' })
48
30
  public email!: string
49
-
50
- @Property({ type: 'boolean', default: true })
51
- public active?: boolean
52
31
  }
53
- ```
54
-
55
- `id` is assigned by the store on create, so declare it optional and `nullable`
56
- — a non-nullable property missing from the data fails
57
- `assertNonNullablePropertyConstraint`, and `EntityInsertData` would require you
58
- to pass it yourself. The same goes for any property carrying a `default`.
59
-
60
- ### @Entity options
61
-
62
- ```typescript
63
- @Entity({ tableName?: string })
64
- ```
65
-
66
- ### @Property options
67
-
68
- ```typescript
69
- @Property({
70
- type?: string,
71
- nullable?: boolean,
72
- default?: any,
73
- index?: boolean,
74
- })
75
- ```
76
-
77
- 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.
78
-
79
- If `nullable` is omitted, the property is required at runtime validation.
80
-
81
- ### TypeScript configuration for entity classes
82
-
83
- Projects that define entities with `@Property()` should enable:
84
-
85
- ```json
86
- {
87
- "compilerOptions": {
88
- "experimentalDecorators": true,
89
- "emitDecoratorMetadata": true
90
- }
91
- }
92
- ```
93
-
94
- ## Constraints
95
-
96
- Row validation runs in the ORM library (`ORM.create`, `ORM.upsert` and `Ref.update`), not in `ORMClaim` implementations. Failed checks throw `ConstraintError`.
97
-
98
- ### Pipeline
99
-
100
- **Create** (full row, after defaults):
101
-
102
- 1. `applyDefaultProperties` — fills `default` for `undefined` fields
103
- 2. `assertPropertyTypeConstraint` — validates declared types
104
- 3. `assertNonNullablePropertyConstraint` — required fields must be present
105
-
106
- **Update** (partial patch only):
107
-
108
- 1. Defaults only for keys present in the patch
109
- 2. Same asserts, scoped to patch keys
110
-
111
- ### Supported property types
112
-
113
- `string`, `uuid`, `number`, `boolean`, `array`, `date`, `object`. Properties without `type` skip type validation.
114
-
115
- ### Example
116
-
117
- ```typescript
118
- import { ConstraintError, ORM } from '@t4h.framework/orm'
119
-
120
- try {
121
- await orm.create(User, { email: 'taken@example.com' })
122
- } catch (error) {
123
- if (error instanceof ConstraintError) {
124
- // handle validation failure
125
- }
126
- }
127
- ```
128
-
129
- ## ORM Model
130
-
131
- The `ORM` class provides a high-level API for database operations. It wraps the underlying activities (`ORMCreateActivity`, `ORMFindActivity`, `ORMFindOneActivity`).
132
-
133
- ### Creating records
134
-
135
- The connection string is a `Secret`, so `tsc` rejects a string. Declare it with `type: Secret` in the `EnvDesign` in `src/constants/environments.ts`:
136
-
137
- ```typescript
138
- // src/constants/environments.ts
139
- import { EnvDesign, Secret } from '@t4h.framework/core'
140
-
141
- export const environments = EnvDesign({
142
- DATABASE_URL: { type: Secret },
143
- })
144
- ```
145
-
146
- ```typescript
147
- import { ORM } from '@t4h.framework/orm'
148
-
149
- import { environments } from './constants/environments.js'
150
32
 
151
33
  const orm = new ORM({
152
34
  connectionString: environments.DATABASE_URL,
153
35
  entities: [User],
154
36
  })
155
37
 
156
- const userRef = await orm.create(User, {
157
- name: 'John',
158
- email: 'john@example.com',
159
- active: true,
160
- })
161
- ```
162
-
163
- ### Batch create
164
-
165
- ```typescript
166
- const usersRef = await orm.create(User, [
167
- { name: 'Alice', email: 'alice@example.com', active: true },
168
- { name: 'Bob', email: 'bob@example.com', active: true },
169
- ])
170
- ```
171
-
172
- ### Upsert
173
-
174
- ```typescript
175
- // Inserts, or updates the row with the same email
176
- const userRef = await orm.upsert(
177
- User,
178
- { email: 'john@example.com', name: 'John', active: true },
179
- { conflictOn: ['email'] },
180
- )
181
- ```
182
-
183
- Pass an array for a batch (returns a `RefCollection`). On update only the fields you passed are written; defaults apply on insert only. The call runs as a single `ORMUpsertActivity`, so a retry after a crash updates instead of duplicating; it is not atomic across workflows, so concurrent writes of the same key may both insert.
184
-
185
- ### Finding records
186
-
187
- ```typescript
188
- const userRef = await orm.findOne(User, {
189
- where: { email: 'john@example.com' },
190
- })
38
+ export const onboard = new Workflow({ id: 'onboard' }, async () => {
39
+ const userRef = await orm.create(User, { email: 'john@example.com' })
191
40
 
192
- const usersRef = await orm.find(User, {
193
- where: { active: true },
194
- orderBy: { name: 'asc' },
195
- limit: 10,
196
- offset: 0,
41
+ return await userRef.getSnapshot()
197
42
  })
198
43
  ```
199
44
 
200
- ### Checking existence
201
-
202
- ```typescript
203
- const exists = await orm.exists(User, {
204
- where: { email: 'john@example.com' },
205
- })
206
- ```
207
-
208
- ### Deleting records
209
-
210
- ```typescript
211
- const deleted = await orm.delete(User, {
212
- where: { active: false },
213
- }) // number of deleted rows
214
- ```
215
-
216
- `where` is required; an empty `{}` deletes every row.
217
-
218
- ## Ref
219
-
220
- A `Ref<T>` is a reference to a single entity row. It supports `getSnapshot`, `update`, and `remove`:
221
-
222
- ```typescript
223
- const userRef = await orm.findOne(User, { where: { id: '...' } })
224
-
225
- const user = await userRef.getSnapshot() // returns the full entity
226
- await userRef.update({ name: 'Jane' }) // partial update
227
- await userRef.remove() // delete
228
- ```
229
-
230
- ## RefCollection
231
-
232
- A `RefCollection<T>` is a collection of entity references returned by `find` or batch `create`:
233
-
234
- ```typescript
235
- const usersRef = await orm.find(User, { where: { active: true } })
236
-
237
- const users = usersRef.toArray() // Ref<User>[]
238
- usersRef.forEach(ref => { /* ... */ })
239
- await usersRef.getSnapshots() // (User | null)[] in one activity
240
- usersRef.filter(ref => { /* ... */ })
241
- usersRef.at(0) // Ref<User> | undefined
242
- ```
243
-
244
- ## Relations
245
-
246
- `@ManyToOne` owns the relation and stores the related row in a column; `@OneToMany` reads it back from the other table. The to-one side is a `Ref<T>`, the many side a lazy `MapCollection<T>`:
247
-
248
- ```typescript
249
- @Entity({ tableName: 'users' })
250
- class User {
251
- @OneToMany(() => Post, post => post.author)
252
- public posts!: MapCollection<Post>
253
- }
254
-
255
- @Entity({ tableName: 'posts' })
256
- class Post {
257
- @ManyToOne(() => User)
258
- public author!: Ref<User>
259
- }
260
-
261
- await orm.create(Post, { title: 'Hello', author: userRef })
262
-
263
- const aliceRef = await orm.findOne(User, { where: { name: 'Alice' } })
264
-
265
- const user = await aliceRef!.getSnapshot({
266
- populate: ['posts'], // read in the same activity
267
- })
268
-
269
- await user!.posts.map(post => post.title)
270
-
271
- const posts = await aliceRef!.load('posts') // MapCollection<Post>, read when used
272
- ```
273
-
274
- See [docs/relations.md](./docs/relations.md).
275
-
276
- ## Query Operators
277
-
278
- The `where` clause supports the following operators:
279
-
280
- ```typescript
281
- await orm.find(User, {
282
- where: {
283
- name: 'John', // $eq (implicit)
284
- active: { $ne: false }, // not equal
285
- email: { $like: '%@example%' }, // LIKE
286
- age: { $gte: 18, $lt: 65 }, // range
287
- },
288
- })
289
- ```
290
-
291
- Available operators: `$eq`, `$ne`, `$in`, `$nin`, `$not`, `$gt`, `$gte`, `$lt`, `$lte`, `$like`, `$ilike`, `$and`, `$or`.
292
-
293
- ## Activities
294
-
295
- The package includes the following activities (used internally by `ORM` and `Ref`):
45
+ `environments` comes from `EnvDesign` in `src/constants/environments.ts`, with
46
+ `DATABASE_URL` declared as `{ type: Secret }`.
296
47
 
297
- - `ORMCreateActivity` -- creates one or more rows
298
- - `ORMFindActivity` -- finds multiple rows
299
- - `ORMFindOneActivity` -- finds a single row
300
- - `ORMGetSnapshotActivity` -- retrieves full entity data from a ref (no longer used by `Ref.getSnapshot`)
301
- - `ORMLoadActivity` -- backs `getSnapshot` / `getSnapshots`: retrieves rows with their relations and `populate` in one activity
302
- - `ORMLoadRelationActivity` -- follows a to-one relation from one or more refs, returning refs
303
- - `ORMUpdateActivity` -- updates a row
304
- - `ORMUpsertActivity` -- inserts or updates rows by `conflictOn` (via `ORMClaim.upsert`)
305
- - `ORMRemoveActivity` -- removes a row
306
- - `ORMDeleteActivity` -- deletes every row matching a `where`
48
+ ## Documentation
307
49
 
308
- All activities extend `SyncActivity` and use `ORMClaim` internally.
50
+ https://tech4humans-brasil.github.io/framework/orm/
@@ -1 +1 @@
1
- {"version":3,"file":"Entity.d.ts","sourceRoot":"","sources":["../../src/decorators/Entity.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,CAQ7D"}
1
+ {"version":3,"file":"Entity.d.ts","sourceRoot":"","sources":["../../src/decorators/Entity.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,CAW7D"}
@@ -1,6 +1,9 @@
1
1
  import { getEntityMetadata, registerEntity } from './metadata.js';
2
+ import { isEntityConstructor } from '../helpers/isEntityConstructor.js';
2
3
  export function Entity(options) {
3
4
  return target => {
5
+ if (!isEntityConstructor(target))
6
+ throw new TypeError(`@Entity decorates a class, not "${target.name}"`);
4
7
  const metadata = getEntityMetadata(target);
5
8
  metadata.tableName = options.tableName;
6
9
  registerEntity(target);
@@ -1 +1 @@
1
- {"version":3,"file":"Entity.js","sourceRoot":"","sources":["../../src/decorators/Entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAOjE,MAAM,UAAU,MAAM,CAAC,OAAsB;IAC3C,OAAO,MAAM,CAAC,EAAE;QACd,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAsC,CAAC,CAAA;QAE1E,QAAQ,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;QAEtC,cAAc,CAAC,MAAsC,CAAC,CAAA;IACxD,CAAC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"Entity.js","sourceRoot":"","sources":["../../src/decorators/Entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AAMvE,MAAM,UAAU,MAAM,CAAC,OAAsB;IAC3C,OAAO,MAAM,CAAC,EAAE;QACd,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC;YAC9B,MAAM,IAAI,SAAS,CAAC,mCAAmC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAA;QAExE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAA;QAE1C,QAAQ,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;QAEtC,cAAc,CAAC,MAAM,CAAC,CAAA;IACxB,CAAC,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Index.d.ts","sourceRoot":"","sources":["../../src/decorators/Index.ts"],"names":[],"mappings":"AAGA,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"}
1
+ {"version":3,"file":"Index.d.ts","sourceRoot":"","sources":["../../src/decorators/Index.ts"],"names":[],"mappings":"AAGA,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,CAY5D"}
@@ -1,8 +1,11 @@
1
1
  import { getEntityMetadata } from './metadata.js';
2
+ import { isEntityConstructor } from '../helpers/isEntityConstructor.js';
2
3
  export function Index(options) {
3
4
  return target => {
4
5
  if (!options.properties.length)
5
6
  throw new Error('Index properties cannot be empty');
7
+ if (!isEntityConstructor(target))
8
+ throw new TypeError(`@Index decorates a class, not "${target.name}"`);
6
9
  const metadata = getEntityMetadata(target);
7
10
  metadata.indexes.push(options);
8
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Index.js","sourceRoot":"","sources":["../../src/decorators/Index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAQjD,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,MAAsC,CAAC,CAAA;QAE1E,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAChC,CAAC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"Index.js","sourceRoot":"","sources":["../../src/decorators/Index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AAOvE,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,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC;YAC9B,MAAM,IAAI,SAAS,CAAC,kCAAkC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAA;QAEvE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAA;QAE1C,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAChC,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { EntityConstructor } from '../typings/ORM.js';
2
+ export declare const isEntityConstructor: (value: unknown) => value is EntityConstructor;
3
+ //# sourceMappingURL=isEntityConstructor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isEntityConstructor.d.ts","sourceRoot":"","sources":["../../src/helpers/isEntityConstructor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,eAAO,MAAM,mBAAmB,GAC9B,OAAO,OAAO,KACb,KAAK,IAAI,iBAMX,CAAA"}
@@ -0,0 +1,7 @@
1
+ export const isEntityConstructor = (value) => {
2
+ if (typeof value !== 'function')
3
+ return false;
4
+ const prototype = value.prototype;
5
+ return typeof prototype === 'object' && prototype !== null;
6
+ };
7
+ //# sourceMappingURL=isEntityConstructor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isEntityConstructor.js","sourceRoot":"","sources":["../../src/helpers/isEntityConstructor.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,KAAc,EACc,EAAE;IAC9B,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,OAAO,KAAK,CAAA;IAE7C,MAAM,SAAS,GAAY,KAAK,CAAC,SAAS,CAAA;IAE1C,OAAO,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,IAAI,CAAA;AAC5D,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ORM.d.ts","sourceRoot":"","sources":["../../src/typings/ORM.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ORM.d.ts","sourceRoot":"","sources":["../../src/typings/ORM.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t4h.framework/orm",
3
- "version": "0.11.4",
3
+ "version": "0.11.7",
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",
@@ -36,7 +36,7 @@
36
36
  "reflect-metadata": "^0.2.2"
37
37
  },
38
38
  "devDependencies": {
39
- "@t4h.framework/core": "^0.20.0",
39
+ "@t4h.framework/core": "^0.21.2",
40
40
  "typescript": "^5.9.3",
41
41
  "vitest": "^4.0.18"
42
42
  },