@antelopejs/interface-database-decorators 0.1.6 → 0.1.8
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/README.md +0 -2
- package/dist/antelope.test.js +4 -3
- package/dist/antelope.test.js.map +1 -1
- package/dist/common.d.ts +7 -1
- package/dist/common.js +10 -2
- package/dist/common.js.map +1 -1
- package/dist/database.d.ts +2 -1
- package/dist/database.js +20 -9
- package/dist/database.js.map +1 -1
- package/dist/model.d.ts +7 -2
- package/dist/model.js +25 -13
- package/dist/model.js.map +1 -1
- package/dist/modifiers/autodate.js.map +1 -1
- package/dist/modifiers/common.js +2 -2
- package/dist/modifiers/common.js.map +1 -1
- package/dist/modifiers/encryption.js +1 -1
- package/dist/modifiers/encryption.js.map +1 -1
- package/dist/modifiers/hash.js +1 -1
- package/dist/modifiers/hash.js.map +1 -1
- package/dist/modifiers/localization.js.map +1 -1
- package/dist/relation.js +1 -1
- package/dist/relation.js.map +1 -1
- package/dist/schema.js +2 -0
- package/dist/schema.js.map +1 -1
- package/dist/table.d.ts +39 -5
- package/dist/table.js +35 -8
- package/dist/table.js.map +1 -1
- package/dist/tests/common.test.js +1 -1
- package/dist/tests/common.test.js.map +1 -1
- package/dist/tests/cross_instance.test.d.ts +1 -0
- package/dist/tests/cross_instance.test.js +120 -0
- package/dist/tests/cross_instance.test.js.map +1 -0
- package/dist/tests/database.test.js +98 -2
- package/dist/tests/database.test.js.map +1 -1
- package/dist/tests/helpers/other-instance.d.ts +13 -0
- package/dist/tests/helpers/other-instance.js +46 -0
- package/dist/tests/helpers/other-instance.js.map +1 -0
- package/dist/tests/integration.test.js +4 -4
- package/dist/tests/integration.test.js.map +1 -1
- package/dist/tests/model.test.js +4 -4
- package/dist/tests/model.test.js.map +1 -1
- package/dist/tests/modifiers/autodate.test.js +3 -3
- package/dist/tests/modifiers/autodate.test.js.map +1 -1
- package/dist/tests/modifiers/common.test.js +2 -2
- package/dist/tests/modifiers/common.test.js.map +1 -1
- package/dist/tests/modifiers/encryption.test.js +2 -2
- package/dist/tests/modifiers/encryption.test.js.map +1 -1
- package/dist/tests/modifiers/hash.test.js +2 -2
- package/dist/tests/modifiers/hash.test.js.map +1 -1
- package/dist/tests/modifiers/localization.test.js +2 -2
- package/dist/tests/modifiers/localization.test.js.map +1 -1
- package/dist/tests/relation.test.js +2 -2
- package/dist/tests/relation.test.js.map +1 -1
- package/dist/tests/schema.test.js +2 -2
- package/dist/tests/schema.test.js.map +1 -1
- package/dist/tests/table.test.js +11 -11
- package/dist/tests/table.test.js.map +1 -1
- package/docs/2.table-definitions.md +90 -18
- package/docs/3.table-modifiers.md +77 -23
- package/docs/4.data-models.md +5 -5
- package/docs/5.parameter-decoration.md +14 -3
- package/package.json +66 -57
- package/skills/database-decorators-interface/SKILL.md +61 -16
|
@@ -23,7 +23,12 @@ class User extends Table {
|
|
|
23
23
|
The `Table.with()` static method incorporates modifier mixins into the table class, adding capabilities like encryption, hashing, or localization:
|
|
24
24
|
|
|
25
25
|
```typescript
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
Table,
|
|
28
|
+
Field,
|
|
29
|
+
EncryptionModifier,
|
|
30
|
+
Encrypted,
|
|
31
|
+
} from "@antelopejs/interface-database-decorators";
|
|
27
32
|
|
|
28
33
|
class SensitiveData extends Table.with(EncryptionModifier) {
|
|
29
34
|
@Field("string")
|
|
@@ -56,16 +61,38 @@ class User extends Table {
|
|
|
56
61
|
|
|
57
62
|
### Options
|
|
58
63
|
|
|
59
|
-
| Option
|
|
60
|
-
|
|
|
61
|
-
| `group`
|
|
64
|
+
| Option | Type | Description |
|
|
65
|
+
| --------------- | --------- | ------------------------------------------------------------------- |
|
|
66
|
+
| `group` | `string` | Assign the field to a named compound index group. |
|
|
67
|
+
| `crossInstance` | `boolean` | Also keep the index fast for queries that run across all instances. |
|
|
68
|
+
|
|
69
|
+
### Cross-Instance Indexes
|
|
70
|
+
|
|
71
|
+
Every index is scoped to the schema instance, so queries on a single instance always use it. Set `crossInstance: true` when the index is also queried across all instances (queries on the `CROSS_INSTANCE` instance), so the database driver maintains an additional index for those queries.
|
|
72
|
+
|
|
73
|
+
The option never changes query results. Without it, cross-instance queries that name the index still return the same rows but run slower, and the driver logs a warning once per index. Leave it unset for indexes that are only queried within one instance, since each extra index costs storage and write time.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
class User extends Table {
|
|
77
|
+
@Index({ crossInstance: true })
|
|
78
|
+
@Field("string")
|
|
79
|
+
declare email: string;
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
For a compound index, setting `crossInstance: true` on any field of the group applies it to the whole group.
|
|
62
84
|
|
|
63
85
|
### Compound Indexes
|
|
64
86
|
|
|
65
87
|
Assign multiple fields to the same index group to create a compound index:
|
|
66
88
|
|
|
67
89
|
```typescript
|
|
68
|
-
import {
|
|
90
|
+
import {
|
|
91
|
+
Table,
|
|
92
|
+
Field,
|
|
93
|
+
Index,
|
|
94
|
+
Relation,
|
|
95
|
+
} from "@antelopejs/interface-database-decorators";
|
|
69
96
|
|
|
70
97
|
class User extends Table {
|
|
71
98
|
@Field("string")
|
|
@@ -93,7 +120,12 @@ class UserActivity extends Table {
|
|
|
93
120
|
|
|
94
121
|
```typescript
|
|
95
122
|
import * as t from "io-ts";
|
|
96
|
-
import {
|
|
123
|
+
import {
|
|
124
|
+
Table,
|
|
125
|
+
Field,
|
|
126
|
+
Index,
|
|
127
|
+
RegisterTable,
|
|
128
|
+
} from "@antelopejs/interface-database-decorators";
|
|
97
129
|
|
|
98
130
|
@RegisterTable("orders", "shop")
|
|
99
131
|
class Order extends Table {
|
|
@@ -116,7 +148,12 @@ Properties without `@Field` are omitted from `fields`. `@Field` stacks freely wi
|
|
|
116
148
|
The `Relation` decorator declares a link from a field to another table. It is **declarative metadata only**: database implementations do not enforce it (no foreign key constraint, no referential validation). Introspection tooling consumes it to expose the links between tables — for example to render schema diagrams or navigate related records.
|
|
117
149
|
|
|
118
150
|
```typescript
|
|
119
|
-
import {
|
|
151
|
+
import {
|
|
152
|
+
Table,
|
|
153
|
+
Field,
|
|
154
|
+
Index,
|
|
155
|
+
Relation,
|
|
156
|
+
} from "@antelopejs/interface-database-decorators";
|
|
120
157
|
|
|
121
158
|
class Comment extends Table {
|
|
122
159
|
@Index()
|
|
@@ -132,11 +169,11 @@ class Comment extends Table {
|
|
|
132
169
|
|
|
133
170
|
### Options
|
|
134
171
|
|
|
135
|
-
| Option | Type
|
|
136
|
-
| --------- |
|
|
137
|
-
| `to` | `() => typeof Table` | Thunk returning the target table class (lazy to allow forward references).
|
|
138
|
-
| `toField` | `string`
|
|
139
|
-
| `many` | `boolean`
|
|
172
|
+
| Option | Type | Description |
|
|
173
|
+
| --------- | -------------------- | -------------------------------------------------------------------------------- |
|
|
174
|
+
| `to` | `() => typeof Table` | Thunk returning the target table class (lazy to allow forward references). |
|
|
175
|
+
| `toField` | `string` | Target field name. Defaults to the target table's primary key. |
|
|
176
|
+
| `many` | `boolean` | The decorated field holds multiple target keys (many targets per source record). |
|
|
140
177
|
|
|
141
178
|
`@Relation` stacks freely with `@Field` and `@Index`.
|
|
142
179
|
|
|
@@ -145,7 +182,12 @@ class Comment extends Table {
|
|
|
145
182
|
The `RegisterTable` class decorator associates a table class with a specific table name and schema. This registration is used by `RegisterSchema` to build the schema definition automatically.
|
|
146
183
|
|
|
147
184
|
```typescript
|
|
148
|
-
import {
|
|
185
|
+
import {
|
|
186
|
+
Table,
|
|
187
|
+
Field,
|
|
188
|
+
Index,
|
|
189
|
+
RegisterTable,
|
|
190
|
+
} from "@antelopejs/interface-database-decorators";
|
|
149
191
|
|
|
150
192
|
@RegisterTable("users", "myapp")
|
|
151
193
|
class User extends Table {
|
|
@@ -165,7 +207,11 @@ The first argument is the table name in the database, and the second is the sche
|
|
|
165
207
|
The `Fixture` decorator defines default data to insert when a table is first created. It receives a generator function that produces initial records.
|
|
166
208
|
|
|
167
209
|
```typescript
|
|
168
|
-
import {
|
|
210
|
+
import {
|
|
211
|
+
Table,
|
|
212
|
+
Field,
|
|
213
|
+
Fixture,
|
|
214
|
+
} from "@antelopejs/interface-database-decorators";
|
|
169
215
|
|
|
170
216
|
@Fixture(() => [
|
|
171
217
|
{ _id: "admin", name: "Administrator" },
|
|
@@ -205,7 +251,12 @@ class SystemConfig extends Table {
|
|
|
205
251
|
Tables support standard class inheritance. Define a base table with common fields and extend it for specific use cases:
|
|
206
252
|
|
|
207
253
|
```typescript
|
|
208
|
-
import {
|
|
254
|
+
import {
|
|
255
|
+
Table,
|
|
256
|
+
Field,
|
|
257
|
+
Index,
|
|
258
|
+
Relation,
|
|
259
|
+
} from "@antelopejs/interface-database-decorators";
|
|
209
260
|
|
|
210
261
|
class BaseEntity extends Table {
|
|
211
262
|
@Field("date")
|
|
@@ -243,7 +294,9 @@ class Post extends BaseEntity {
|
|
|
243
294
|
|
|
244
295
|
## Register a Schema
|
|
245
296
|
|
|
246
|
-
The `RegisterSchema` function builds a `SchemaDefinition` from all tables registered for the given schema id (via `@RegisterTable`), constructs the `Schema` (which the adapter provisions), then inserts any fixture data for tables that are empty.
|
|
297
|
+
The `RegisterSchema` function builds a `SchemaDefinition` from all tables registered for the given schema id (via `@RegisterTable`), constructs the `Schema` (which the adapter provisions), binds each table class to that `Schema` (see [Open a Table from its Class](#open-a-table-from-its-class)), then inserts any fixture data for tables that are empty.
|
|
298
|
+
|
|
299
|
+
Call it in the module that declares the tables: the binding then follows that module's database, whichever module later uses the classes.
|
|
247
300
|
|
|
248
301
|
```typescript
|
|
249
302
|
import { RegisterSchema } from "@antelopejs/interface-database-decorators";
|
|
@@ -253,8 +306,27 @@ await RegisterSchema("myapp");
|
|
|
253
306
|
|
|
254
307
|
### Parameters
|
|
255
308
|
|
|
256
|
-
| Parameter | Type | Description
|
|
257
|
-
| ---------- | -------- |
|
|
309
|
+
| Parameter | Type | Description |
|
|
310
|
+
| ---------- | -------- | ------------------------------------------------------------------ |
|
|
258
311
|
| `schemaId` | `string` | Schema id matching the `@RegisterTable(_, schemaId)` declarations. |
|
|
259
312
|
|
|
260
313
|
`RegisterSchema` returns `Promise<void>`.
|
|
314
|
+
|
|
315
|
+
## Open a Table from its Class
|
|
316
|
+
|
|
317
|
+
`Table.table()` returns the AQL table a class describes, in the schema `RegisterSchema` bound it to:
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
@RegisterTable("users", "myapp")
|
|
321
|
+
class User extends Table {
|
|
322
|
+
declare name: string;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
await RegisterSchema("myapp");
|
|
326
|
+
|
|
327
|
+
User.table(); // default instance of "myapp"
|
|
328
|
+
User.table("tenant-1"); // instance "tenant-1" (CROSS_INSTANCE is accepted too)
|
|
329
|
+
User.table(db); // db.table("users") on a SchemaInstance you already hold
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
When given a `SchemaInstance`, `table()` takes the table from it as is: pass an instance of the class's own schema. A class that no `RegisterSchema` call bound throws, naming the class.
|
|
@@ -9,7 +9,12 @@ Table modifiers transform field values as they are stored in and retrieved from
|
|
|
9
9
|
The `EncryptionModifier` encrypts field values before storing them and decrypts them on retrieval. Both operations happen transparently.
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
Table,
|
|
14
|
+
Field,
|
|
15
|
+
EncryptionModifier,
|
|
16
|
+
Encrypted,
|
|
17
|
+
} from "@antelopejs/interface-database-decorators";
|
|
13
18
|
|
|
14
19
|
class UserCredentials extends Table.with(EncryptionModifier) {
|
|
15
20
|
@Encrypted({
|
|
@@ -39,18 +44,23 @@ class UserCredentials extends Table.with(EncryptionModifier) {
|
|
|
39
44
|
|
|
40
45
|
#### Options
|
|
41
46
|
|
|
42
|
-
| Option | Type | Default
|
|
43
|
-
| ----------- | -------- |
|
|
44
|
-
| `secretKey` | `string` | (required)
|
|
45
|
-
| `algorithm` | `string` | `"aes-256-gcm"`
|
|
46
|
-
| `ivSize` | `number` | `16`
|
|
47
|
+
| Option | Type | Default | Description |
|
|
48
|
+
| ----------- | -------- | --------------- | ------------------------------------ |
|
|
49
|
+
| `secretKey` | `string` | (required) | The encryption key. |
|
|
50
|
+
| `algorithm` | `string` | `"aes-256-gcm"` | Encryption algorithm. |
|
|
51
|
+
| `ivSize` | `number` | `16` | Initialization vector size in bytes. |
|
|
47
52
|
|
|
48
53
|
### HashModifier
|
|
49
54
|
|
|
50
55
|
The `HashModifier` stores a one-way hash of field values. Unlike encryption, hashing is irreversible -- you cannot retrieve the original value. Use this for passwords and other sensitive data that only needs equality verification.
|
|
51
56
|
|
|
52
57
|
```typescript
|
|
53
|
-
import {
|
|
58
|
+
import {
|
|
59
|
+
Table,
|
|
60
|
+
Field,
|
|
61
|
+
HashModifier,
|
|
62
|
+
Hashed,
|
|
63
|
+
} from "@antelopejs/interface-database-decorators";
|
|
54
64
|
|
|
55
65
|
class User extends Table.with(HashModifier) {
|
|
56
66
|
@Field("string")
|
|
@@ -93,7 +103,12 @@ Returns `true` if `value`, when hashed, matches the stored hash for the given fi
|
|
|
93
103
|
The `LocalizationModifier` stores multiple language versions of a field value. Access a specific locale by calling `localize()` on the table instance.
|
|
94
104
|
|
|
95
105
|
```typescript
|
|
96
|
-
import {
|
|
106
|
+
import {
|
|
107
|
+
Table,
|
|
108
|
+
Field,
|
|
109
|
+
LocalizationModifier,
|
|
110
|
+
Localized,
|
|
111
|
+
} from "@antelopejs/interface-database-decorators";
|
|
97
112
|
|
|
98
113
|
class Product extends Table.with(LocalizationModifier) {
|
|
99
114
|
@Field("number")
|
|
@@ -150,8 +165,8 @@ product.localize("*").name = {
|
|
|
150
165
|
|
|
151
166
|
#### Options
|
|
152
167
|
|
|
153
|
-
| Option | Type | Description
|
|
154
|
-
| ---------------- | -------- |
|
|
168
|
+
| Option | Type | Description |
|
|
169
|
+
| ---------------- | -------- | ------------------------------------------------------- |
|
|
155
170
|
| `fallbackLocale` | `string` | Locale to use when the requested locale is unavailable. |
|
|
156
171
|
|
|
157
172
|
#### Mixin Method
|
|
@@ -169,7 +184,11 @@ Sets the active locale for accessing localized fields. If `fields` is provided,
|
|
|
169
184
|
The `AutoDateModifier` automatically populates timestamp fields during insert and update operations. Use the `CreationTime` and `UpdateTime` decorators to mark fields.
|
|
170
185
|
|
|
171
186
|
```typescript
|
|
172
|
-
import {
|
|
187
|
+
import {
|
|
188
|
+
Table,
|
|
189
|
+
CreationTime,
|
|
190
|
+
UpdateTime,
|
|
191
|
+
} from "@antelopejs/interface-database-decorators";
|
|
173
192
|
|
|
174
193
|
class Article extends Table {
|
|
175
194
|
declare title: string;
|
|
@@ -204,7 +223,11 @@ import {
|
|
|
204
223
|
Localized,
|
|
205
224
|
} from "@antelopejs/interface-database-decorators";
|
|
206
225
|
|
|
207
|
-
class UserProfile extends Table.with(
|
|
226
|
+
class UserProfile extends Table.with(
|
|
227
|
+
EncryptionModifier,
|
|
228
|
+
HashModifier,
|
|
229
|
+
LocalizationModifier,
|
|
230
|
+
) {
|
|
208
231
|
@Encrypted({ secretKey: process.env.SECRET_KEY || "default-key" })
|
|
209
232
|
@Field("any")
|
|
210
233
|
declare privateInfo: {
|
|
@@ -229,11 +252,20 @@ class UserProfile extends Table.with(EncryptionModifier, HashModifier, Localizat
|
|
|
229
252
|
A `OneWayModifier` transforms data in one direction (when writing to the database). Use it for irreversible transformations like hashing.
|
|
230
253
|
|
|
231
254
|
```typescript
|
|
232
|
-
import {
|
|
255
|
+
import {
|
|
256
|
+
OneWayModifier,
|
|
257
|
+
MixinSymbol,
|
|
258
|
+
attachModifier,
|
|
259
|
+
} from "@antelopejs/interface-database-decorators";
|
|
233
260
|
import { MakePropertyDecorator } from "@antelopejs/interface-core/decorators";
|
|
234
261
|
import { createHash } from "crypto";
|
|
235
262
|
|
|
236
|
-
class PrefixHashModifier extends OneWayModifier<
|
|
263
|
+
class PrefixHashModifier extends OneWayModifier<
|
|
264
|
+
string | undefined,
|
|
265
|
+
[],
|
|
266
|
+
{},
|
|
267
|
+
{ algorithm?: string }
|
|
268
|
+
> {
|
|
237
269
|
public readonly autolock = true;
|
|
238
270
|
|
|
239
271
|
public override lock(_locked: string | undefined, value: unknown) {
|
|
@@ -248,15 +280,20 @@ class PrefixHashModifier extends OneWayModifier<string | undefined, [], {}, { al
|
|
|
248
280
|
|
|
249
281
|
const PrefixHashed = MakePropertyDecorator(
|
|
250
282
|
(target, propertyKey, options?: { algorithm?: string }) => {
|
|
251
|
-
attachModifier(
|
|
283
|
+
attachModifier(
|
|
284
|
+
target.constructor,
|
|
285
|
+
PrefixHashModifier,
|
|
286
|
+
propertyKey,
|
|
287
|
+
options || {},
|
|
288
|
+
);
|
|
252
289
|
},
|
|
253
290
|
);
|
|
254
291
|
```
|
|
255
292
|
|
|
256
293
|
The generic parameters for `OneWayModifier<LockedType, Args, Meta, Options>` are:
|
|
257
294
|
|
|
258
|
-
| Parameter | Description
|
|
259
|
-
| ------------ |
|
|
295
|
+
| Parameter | Description |
|
|
296
|
+
| ------------ | ---------------------------------------------------- |
|
|
260
297
|
| `LockedType` | The type stored in the database after transformation |
|
|
261
298
|
| `Args` | Additional arguments for `lock` and `test` |
|
|
262
299
|
| `Meta` | Per-field metadata stored alongside the value |
|
|
@@ -267,10 +304,19 @@ The generic parameters for `OneWayModifier<LockedType, Args, Meta, Options>` are
|
|
|
267
304
|
A `TwoWayModifier` extends `OneWayModifier` with an `unlock` method for reversible transformations like encryption:
|
|
268
305
|
|
|
269
306
|
```typescript
|
|
270
|
-
import {
|
|
307
|
+
import {
|
|
308
|
+
TwoWayModifier,
|
|
309
|
+
MixinSymbol,
|
|
310
|
+
attachModifier,
|
|
311
|
+
} from "@antelopejs/interface-database-decorators";
|
|
271
312
|
import { MakePropertyDecorator } from "@antelopejs/interface-core/decorators";
|
|
272
313
|
|
|
273
|
-
class Base64Modifier extends TwoWayModifier<
|
|
314
|
+
class Base64Modifier extends TwoWayModifier<
|
|
315
|
+
string,
|
|
316
|
+
[],
|
|
317
|
+
{},
|
|
318
|
+
{ prefix?: string }
|
|
319
|
+
> {
|
|
274
320
|
public readonly autolock = true;
|
|
275
321
|
public readonly autounlock = true;
|
|
276
322
|
|
|
@@ -295,7 +341,12 @@ class Base64Modifier extends TwoWayModifier<string, [], {}, { prefix?: string }>
|
|
|
295
341
|
|
|
296
342
|
const Base64Encoded = MakePropertyDecorator(
|
|
297
343
|
(target, propertyKey, options?: { prefix?: string }) => {
|
|
298
|
-
attachModifier(
|
|
344
|
+
attachModifier(
|
|
345
|
+
target.constructor,
|
|
346
|
+
Base64Modifier,
|
|
347
|
+
propertyKey,
|
|
348
|
+
options || {},
|
|
349
|
+
);
|
|
299
350
|
},
|
|
300
351
|
);
|
|
301
352
|
```
|
|
@@ -317,8 +368,8 @@ class MyContainerModifier extends ContainerModifier<{}, { fallback?: string }> {
|
|
|
317
368
|
|
|
318
369
|
Modifiers can hook into the data lifecycle by implementing event handler methods. These methods are called during data conversion and database operations:
|
|
319
370
|
|
|
320
|
-
| Event | Triggered When
|
|
321
|
-
| --------------- |
|
|
371
|
+
| Event | Triggered When |
|
|
372
|
+
| --------------- | ------------------------------------------ |
|
|
322
373
|
| `fromPlainData` | After converting plain data to an instance |
|
|
323
374
|
| `toPlainData` | After converting an instance to plain data |
|
|
324
375
|
| `fromDatabase` | After reading from the database |
|
|
@@ -327,7 +378,10 @@ Modifiers can hook into the data lifecycle by implementing event handler methods
|
|
|
327
378
|
| `update` | Before updating an existing record |
|
|
328
379
|
|
|
329
380
|
```typescript
|
|
330
|
-
import {
|
|
381
|
+
import {
|
|
382
|
+
Modifier,
|
|
383
|
+
MixinSymbol,
|
|
384
|
+
} from "@antelopejs/interface-database-decorators";
|
|
331
385
|
|
|
332
386
|
class TimestampModifier extends Modifier {
|
|
333
387
|
public insert(instance: any, field: string) {
|
package/docs/4.data-models.md
CHANGED
|
@@ -15,10 +15,10 @@ const UserModel = BasicDataModel(User, "users");
|
|
|
15
15
|
|
|
16
16
|
### Parameters
|
|
17
17
|
|
|
18
|
-
| Parameter | Type
|
|
19
|
-
| ----------- |
|
|
20
|
-
| `dataType` | `Constructible<T
|
|
21
|
-
| `tableName` | `string`
|
|
18
|
+
| Parameter | Type | Description |
|
|
19
|
+
| ----------- | ------------------ | --------------------------------------------------------------------- |
|
|
20
|
+
| `dataType` | `Constructible<T>` | The Table class representing your table |
|
|
21
|
+
| `tableName` | `string` | The table name in the database (optional if `@RegisterTable` is used) |
|
|
22
22
|
|
|
23
23
|
When the table class has been decorated with `@RegisterTable`, the `tableName` parameter can be omitted.
|
|
24
24
|
|
|
@@ -170,7 +170,7 @@ import { GetModel } from "@antelopejs/interface-database-decorators";
|
|
|
170
170
|
const userModel = GetModel(UserModel, "instance-id");
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
-
Model instances are cached by class and instance ID, so repeated calls with the same arguments return the same instance.
|
|
173
|
+
Model instances are cached by class and instance ID, so repeated calls with the same arguments return the same instance. A model built by `BasicDataModel` uses the schema its table class was bound to by `RegisterSchema`, so it stays on the declaring module's database even when another module calls `GetModel`; an unbound table class throws. A custom model class without a `tableClass` is resolved from its `schemaName` with `Schema.get`.
|
|
174
174
|
|
|
175
175
|
## Modifier Integration
|
|
176
176
|
|
|
@@ -17,7 +17,9 @@ import { UserModel } from "./user.model";
|
|
|
17
17
|
|
|
18
18
|
class UsersController extends Controller("/users") {
|
|
19
19
|
@Get()
|
|
20
|
-
async listUsers(
|
|
20
|
+
async listUsers(
|
|
21
|
+
@Model(UserModel, "main") userModel: InstanceType<typeof UserModel>,
|
|
22
|
+
) {
|
|
21
23
|
return await userModel.getAll();
|
|
22
24
|
}
|
|
23
25
|
}
|
|
@@ -36,7 +38,8 @@ class MultitenantController extends Controller("/tenants") {
|
|
|
36
38
|
@Get("/:tenantId/users")
|
|
37
39
|
async getTenantUsers(
|
|
38
40
|
@Parameter("tenantId") tenantId: string,
|
|
39
|
-
@Model(UserModel, (ctx) => `tenant-${ctx.params.tenantId}`)
|
|
41
|
+
@Model(UserModel, (ctx) => `tenant-${ctx.params.tenantId}`)
|
|
42
|
+
userModel: InstanceType<typeof UserModel>,
|
|
40
43
|
) {
|
|
41
44
|
return await userModel.getAll();
|
|
42
45
|
}
|
|
@@ -88,7 +91,15 @@ const model3 = GetModel(UserModel, "other");
|
|
|
88
91
|
Model decorators compose naturally with other API decorators for building complete CRUD controllers:
|
|
89
92
|
|
|
90
93
|
```typescript
|
|
91
|
-
import {
|
|
94
|
+
import {
|
|
95
|
+
Controller,
|
|
96
|
+
Get,
|
|
97
|
+
Post,
|
|
98
|
+
Put,
|
|
99
|
+
Delete,
|
|
100
|
+
RawBody,
|
|
101
|
+
Parameter,
|
|
102
|
+
} from "@antelopejs/interface-api";
|
|
92
103
|
import { Model } from "@antelopejs/interface-database-decorators";
|
|
93
104
|
import { UserModel } from "./user.model";
|
|
94
105
|
|
package/package.json
CHANGED
|
@@ -1,27 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antelopejs/interface-database-decorators",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "AntelopeJS interface for database schema decorators and model definitions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antelopejs",
|
|
7
|
-
"interface",
|
|
8
7
|
"database",
|
|
9
8
|
"decorators",
|
|
9
|
+
"interface",
|
|
10
10
|
"orm"
|
|
11
11
|
],
|
|
12
|
+
"license": "Apache-2.0",
|
|
12
13
|
"repository": {
|
|
13
14
|
"type": "git",
|
|
14
15
|
"url": "git+https://github.com/AntelopeJS/interface-database-decorators.git"
|
|
15
16
|
},
|
|
16
|
-
"license": "Apache-2.0",
|
|
17
|
-
"packageManager": "pnpm@10.6.5",
|
|
18
|
-
"main": "dist/index.js",
|
|
19
|
-
"types": "dist/index.d.ts",
|
|
20
17
|
"files": [
|
|
21
18
|
"dist",
|
|
22
19
|
"docs",
|
|
23
20
|
"skills"
|
|
24
21
|
],
|
|
22
|
+
"main": "dist/index.js",
|
|
23
|
+
"types": "dist/index.d.ts",
|
|
24
|
+
"typesVersions": {
|
|
25
|
+
"*": {
|
|
26
|
+
"common": [
|
|
27
|
+
"dist/common.d.ts"
|
|
28
|
+
],
|
|
29
|
+
"database": [
|
|
30
|
+
"dist/database.d.ts"
|
|
31
|
+
],
|
|
32
|
+
"model": [
|
|
33
|
+
"dist/model.d.ts"
|
|
34
|
+
],
|
|
35
|
+
"relation": [
|
|
36
|
+
"dist/relation.d.ts"
|
|
37
|
+
],
|
|
38
|
+
"schema": [
|
|
39
|
+
"dist/schema.d.ts"
|
|
40
|
+
],
|
|
41
|
+
"table": [
|
|
42
|
+
"dist/table.d.ts"
|
|
43
|
+
],
|
|
44
|
+
"modifiers/autodate": [
|
|
45
|
+
"dist/modifiers/autodate.d.ts"
|
|
46
|
+
],
|
|
47
|
+
"modifiers/common": [
|
|
48
|
+
"dist/modifiers/common.d.ts"
|
|
49
|
+
],
|
|
50
|
+
"modifiers/encryption": [
|
|
51
|
+
"dist/modifiers/encryption.d.ts"
|
|
52
|
+
],
|
|
53
|
+
"modifiers/hash": [
|
|
54
|
+
"dist/modifiers/hash.d.ts"
|
|
55
|
+
],
|
|
56
|
+
"modifiers/localization": [
|
|
57
|
+
"dist/modifiers/localization.d.ts"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
},
|
|
25
61
|
"exports": {
|
|
26
62
|
".": {
|
|
27
63
|
"types": "./dist/index.d.ts",
|
|
@@ -73,81 +109,54 @@
|
|
|
73
109
|
},
|
|
74
110
|
"./package.json": "./package.json"
|
|
75
111
|
},
|
|
112
|
+
"publishConfig": {
|
|
113
|
+
"access": "public",
|
|
114
|
+
"provenance": true
|
|
115
|
+
},
|
|
76
116
|
"scripts": {
|
|
77
117
|
"build": "rimraf dist && tsc",
|
|
78
|
-
"format": "
|
|
79
|
-
"lint:fix": "
|
|
80
|
-
"lint": "
|
|
118
|
+
"format": "oxfmt .",
|
|
119
|
+
"lint:fix": "oxlint --fix",
|
|
120
|
+
"lint": "oxlint",
|
|
81
121
|
"prepack": "pnpm run build",
|
|
82
122
|
"release": "pnpm run lint && pnpm run prepack && release-it",
|
|
83
|
-
"test": "pnpm run build && ajs module test ."
|
|
123
|
+
"test": "pnpm run build && ajs module test .",
|
|
124
|
+
"format:check": "oxfmt --check .",
|
|
125
|
+
"knip": "knip"
|
|
84
126
|
},
|
|
85
127
|
"dependencies": {
|
|
86
128
|
"randomstring": "^1.3.1",
|
|
87
129
|
"reflect-metadata": "^0.2.2"
|
|
88
130
|
},
|
|
89
131
|
"devDependencies": {
|
|
90
|
-
"@antelopejs/
|
|
91
|
-
"@antelopejs/interface-
|
|
92
|
-
"@antelopejs/interface-
|
|
93
|
-
"@
|
|
132
|
+
"@antelopejs/core": "^1.13.4",
|
|
133
|
+
"@antelopejs/interface-api": "^0.0.13",
|
|
134
|
+
"@antelopejs/interface-core": "^0.1.1",
|
|
135
|
+
"@antelopejs/interface-database": "^0.1.8",
|
|
136
|
+
"@antelopejs/tooling-configs": "^0.0.6",
|
|
94
137
|
"@types/chai": "^4.3.20",
|
|
95
138
|
"@types/mocha": "^10.0.10",
|
|
96
139
|
"@types/node": "^22.19.15",
|
|
97
140
|
"@types/randomstring": "^1.3.0",
|
|
98
141
|
"@types/semver": "^7.7.1",
|
|
99
142
|
"chai": "^4.5.0",
|
|
143
|
+
"eslint-plugin-perfectionist": "^5.11.0",
|
|
144
|
+
"knip": "^6.34.0",
|
|
100
145
|
"mongodb-memory-server-core": "^10.4.3",
|
|
146
|
+
"oxfmt": "^0.66.0",
|
|
147
|
+
"oxlint": "1.81.0",
|
|
148
|
+
"oxlint-tsgolint": "^7.0.2001",
|
|
101
149
|
"release-it": "^19.2.4",
|
|
102
150
|
"release-it-changelogen": "^0.1.0",
|
|
103
151
|
"rimraf": "^6.1.3",
|
|
104
152
|
"typescript": "^5.9.3"
|
|
105
153
|
},
|
|
106
154
|
"peerDependencies": {
|
|
107
|
-
"@antelopejs/interface-api": ">=0.0.
|
|
108
|
-
"@antelopejs/interface-core": ">=0.
|
|
109
|
-
"@antelopejs/interface-database": ">=0.1.
|
|
110
|
-
},
|
|
111
|
-
"publishConfig": {
|
|
112
|
-
"access": "public"
|
|
113
|
-
},
|
|
114
|
-
"typesVersions": {
|
|
115
|
-
"*": {
|
|
116
|
-
"common": [
|
|
117
|
-
"dist/common.d.ts"
|
|
118
|
-
],
|
|
119
|
-
"database": [
|
|
120
|
-
"dist/database.d.ts"
|
|
121
|
-
],
|
|
122
|
-
"model": [
|
|
123
|
-
"dist/model.d.ts"
|
|
124
|
-
],
|
|
125
|
-
"relation": [
|
|
126
|
-
"dist/relation.d.ts"
|
|
127
|
-
],
|
|
128
|
-
"schema": [
|
|
129
|
-
"dist/schema.d.ts"
|
|
130
|
-
],
|
|
131
|
-
"table": [
|
|
132
|
-
"dist/table.d.ts"
|
|
133
|
-
],
|
|
134
|
-
"modifiers/autodate": [
|
|
135
|
-
"dist/modifiers/autodate.d.ts"
|
|
136
|
-
],
|
|
137
|
-
"modifiers/common": [
|
|
138
|
-
"dist/modifiers/common.d.ts"
|
|
139
|
-
],
|
|
140
|
-
"modifiers/encryption": [
|
|
141
|
-
"dist/modifiers/encryption.d.ts"
|
|
142
|
-
],
|
|
143
|
-
"modifiers/hash": [
|
|
144
|
-
"dist/modifiers/hash.d.ts"
|
|
145
|
-
],
|
|
146
|
-
"modifiers/localization": [
|
|
147
|
-
"dist/modifiers/localization.d.ts"
|
|
148
|
-
]
|
|
149
|
-
}
|
|
155
|
+
"@antelopejs/interface-api": ">=0.0.13 <1.0.0",
|
|
156
|
+
"@antelopejs/interface-core": ">=0.1.1 <1.0.0",
|
|
157
|
+
"@antelopejs/interface-database": ">=0.1.8 <1.0.0"
|
|
150
158
|
},
|
|
159
|
+
"packageManager": "pnpm@10.6.5",
|
|
151
160
|
"antelopeJs": {
|
|
152
161
|
"standalone": true,
|
|
153
162
|
"test": "src/antelope.test.ts",
|