edinburgh 0.4.1 → 0.4.4
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/LICENSE +1 -1
- package/README.md +515 -82
- package/build/src/datapack.d.ts +17 -1
- package/build/src/datapack.js +44 -5
- package/build/src/datapack.js.map +1 -1
- package/build/src/edinburgh.d.ts +1 -1
- package/build/src/edinburgh.js +4 -3
- package/build/src/edinburgh.js.map +1 -1
- package/build/src/indexes.d.ts +34 -17
- package/build/src/indexes.js +126 -55
- package/build/src/indexes.js.map +1 -1
- package/build/src/migrate.js +21 -5
- package/build/src/migrate.js.map +1 -1
- package/build/src/models.js +18 -5
- package/build/src/models.js.map +1 -1
- package/build/src/types.d.ts +13 -1
- package/build/src/types.js +89 -1
- package/build/src/types.js.map +1 -1
- package/build/src/utils.d.ts +2 -0
- package/build/src/utils.js +12 -0
- package/build/src/utils.js.map +1 -1
- package/package.json +9 -7
- package/skill/SKILL.md +1473 -0
- package/src/datapack.ts +49 -7
- package/src/edinburgh.ts +5 -3
- package/src/indexes.ts +143 -71
- package/src/migrate.ts +19 -5
- package/src/models.ts +17 -5
- package/src/types.ts +97 -1
- package/src/utils.ts +12 -0
package/README.md
CHANGED
|
@@ -70,7 +70,9 @@ await E.transact(() => {
|
|
|
70
70
|
});
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
##
|
|
73
|
+
## Tutorial
|
|
74
|
+
|
|
75
|
+
### TypeScript Configuration
|
|
74
76
|
|
|
75
77
|
When using TypeScript to transpile to JavaScript, make sure to enable the following options in your `tsconfig.json`:
|
|
76
78
|
|
|
@@ -83,15 +85,385 @@ When using TypeScript to transpile to JavaScript, make sure to enable the follow
|
|
|
83
85
|
}
|
|
84
86
|
```
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
### Defining Models
|
|
89
|
+
|
|
90
|
+
Models are classes that extend `E.Model<Self>` and use the `@E.registerModel` decorator:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import * as E from "edinburgh";
|
|
94
|
+
|
|
95
|
+
@E.registerModel
|
|
96
|
+
class User extends E.Model<User> {
|
|
97
|
+
static pk = E.primary(User, "id");
|
|
98
|
+
|
|
99
|
+
id = E.field(E.identifier);
|
|
100
|
+
name = E.field(E.string);
|
|
101
|
+
email = E.field(E.string);
|
|
102
|
+
age = E.field(E.number);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Instance fields are declared with `E.field(type, options?)`. Available types:
|
|
107
|
+
|
|
108
|
+
| Type | TypeScript type | Notes |
|
|
109
|
+
|------|----------------|-------|
|
|
110
|
+
| `E.string` | `string` | |
|
|
111
|
+
| `E.orderedString` | `string` | Lexicographic sort in indexes; no null bytes |
|
|
112
|
+
| `E.number` | `number` | |
|
|
113
|
+
| `E.boolean` | `boolean` | |
|
|
114
|
+
| `E.dateTime` | `Date` | Defaults to `new Date()` |
|
|
115
|
+
| `E.identifier` | `string` | Auto-generated 8-char unique ID |
|
|
116
|
+
| `E.opt(T)` | `T \| undefined` | Makes any type optional |
|
|
117
|
+
| `E.or(A, B, ...)` | `A \| B \| ...` | Union type; args can be types or literal values |
|
|
118
|
+
| `E.literal(v)` | literal type | Constant value; defaults to that value |
|
|
119
|
+
| `E.array(T)` | `T[]` | Optional `{min, max}` constraints |
|
|
120
|
+
| `E.set(T)` | `Set<T>` | Optional `{min, max}` constraints |
|
|
121
|
+
| `E.record(T)` | `Record<string \| number, T>` | Key-value object with string/number keys |
|
|
122
|
+
| `E.link(Model)` | `Model` | Foreign key, lazy-loaded on access |
|
|
123
|
+
|
|
124
|
+
#### Defaults
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
@E.registerModel
|
|
128
|
+
class Post extends E.Model<Post> {
|
|
129
|
+
static pk = E.primary(Post, "id");
|
|
130
|
+
|
|
131
|
+
id = E.field(E.identifier); // auto-generated
|
|
132
|
+
title = E.field(E.string);
|
|
133
|
+
status = E.field(E.or("draft", "published"), {default: "draft"});
|
|
134
|
+
tags = E.field(E.array(E.string), {default: () => []}); // use function for mutable defaults
|
|
135
|
+
createdAt = E.field(E.dateTime); // dateTime defaults to new Date()
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Transactions
|
|
140
|
+
|
|
141
|
+
All database operations must run inside `E.transact()`:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// Initialize (optional — defaults to ".edinburgh" directory)
|
|
145
|
+
E.init("./my-database");
|
|
146
|
+
|
|
147
|
+
// Create
|
|
148
|
+
await E.transact(() => {
|
|
149
|
+
const user = new User({name: "Alice", email: "alice@example.com", age: 30});
|
|
150
|
+
// user.id is auto-generated
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Read + Update
|
|
154
|
+
await E.transact(() => {
|
|
155
|
+
const user = User.byEmail.get("alice@example.com");
|
|
156
|
+
if (user) user.age++;
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Return values from transactions
|
|
160
|
+
const name = await E.transact(() => {
|
|
161
|
+
const user = User.byEmail.get("alice@example.com");
|
|
162
|
+
return user?.name;
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Transactions auto-retry on conflict (up to 6 times by default). Keep transaction functions idempotent.
|
|
167
|
+
|
|
168
|
+
### Indexes
|
|
169
|
+
|
|
170
|
+
Edinburgh supports three index types:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
@E.registerModel
|
|
174
|
+
class Product extends E.Model<Product> {
|
|
175
|
+
static pk = E.primary(Product, "sku"); // primary: one per model, stores data
|
|
176
|
+
static byName = E.unique(Product, "name"); // unique: enforces uniqueness + fast lookup
|
|
177
|
+
static byCategory = E.index(Product, "category");// secondary: non-unique, for queries
|
|
178
|
+
|
|
179
|
+
sku = E.field(E.string);
|
|
180
|
+
name = E.field(E.string);
|
|
181
|
+
category = E.field(E.string);
|
|
182
|
+
price = E.field(E.number);
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
If no `E.primary()` is declared, Edinburgh auto-creates one on an `id` field (adding `E.identifier` if missing).
|
|
187
|
+
|
|
188
|
+
#### Lookups
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
await E.transact(() => {
|
|
192
|
+
// Primary key lookup
|
|
193
|
+
const p = Product.pk.get("SKU-001");
|
|
194
|
+
|
|
195
|
+
// Unique index lookup
|
|
196
|
+
const p2 = Product.byName.get("Widget");
|
|
197
|
+
|
|
198
|
+
// All return undefined if not found
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### Range Queries
|
|
203
|
+
|
|
204
|
+
All index types support `.find()` for range iteration:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
await E.transact(() => {
|
|
208
|
+
// Exact match
|
|
209
|
+
for (const p of Product.byCategory.find({is: "electronics"})) {
|
|
210
|
+
console.log(p.name);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Range (inclusive)
|
|
214
|
+
for (const p of Product.pk.find({from: "A", to: "M"})) {
|
|
215
|
+
console.log(p.sku);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Exclusive bounds
|
|
219
|
+
for (const p of Product.pk.find({after: "A", before: "M"})) { ... }
|
|
220
|
+
|
|
221
|
+
// Open-ended
|
|
222
|
+
for (const p of Product.pk.find({from: "M"})) { ... }
|
|
223
|
+
|
|
224
|
+
// Reverse
|
|
225
|
+
for (const p of Product.pk.find({reverse: true})) { ... }
|
|
226
|
+
|
|
227
|
+
// Count and fetch helpers
|
|
228
|
+
const count = Product.byCategory.find({is: "electronics"}).count();
|
|
229
|
+
const first = Product.byCategory.find({is: "electronics"}).fetch(); // first match or undefined
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Composite Indexes
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
@E.registerModel
|
|
237
|
+
class Event extends E.Model<Event> {
|
|
238
|
+
static pk = E.primary(Event, ["year", "month", "id"]);
|
|
239
|
+
|
|
240
|
+
year = E.field(E.number);
|
|
241
|
+
month = E.field(E.number);
|
|
242
|
+
id = E.field(E.identifier);
|
|
243
|
+
title = E.field(E.string);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
await E.transact(() => {
|
|
247
|
+
// Prefix matching — find all events in 2025
|
|
248
|
+
for (const e of Event.pk.find({is: [2025]})) { ... }
|
|
249
|
+
|
|
250
|
+
// Find events in March 2025
|
|
251
|
+
for (const e of Event.pk.find({is: [2025, 3]})) { ... }
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### Non-Persistent Properties
|
|
256
|
+
|
|
257
|
+
You can freely add regular methods, getters, and other non-persistent properties to model classes. These work normally in JavaScript but are **not stored in the database** and **not synchronized** across transactions or processes.
|
|
87
258
|
|
|
88
|
-
|
|
259
|
+
```typescript
|
|
260
|
+
@E.registerModel
|
|
261
|
+
class User extends E.Model<User> {
|
|
262
|
+
static pk = E.primary(User, "id");
|
|
263
|
+
id = E.field(E.identifier);
|
|
264
|
+
firstName = E.field(E.string);
|
|
265
|
+
lastName = E.field(E.string);
|
|
266
|
+
|
|
267
|
+
// Non-persisted property
|
|
268
|
+
cachedFullName?: string;
|
|
269
|
+
|
|
270
|
+
get fullName(): string {
|
|
271
|
+
this.cachedFullName ??= `${this.firstName} ${this.lastName}`;
|
|
272
|
+
return this.cachedFullName;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
greet(): string {
|
|
276
|
+
return `Hello, ${this.fullName}!`;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
#### Computed Indexes
|
|
282
|
+
|
|
283
|
+
Instead of naming fields, you can pass a **function** to `E.unique()` or `E.index()`. The function receives a model instance and returns an **array** of index key values. Each element creates a separate index entry, enabling multi-value indexes. Return `[]` to skip indexing for that instance (partial index).
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
@E.registerModel
|
|
287
|
+
class Article extends E.Model<Article> {
|
|
288
|
+
static pk = E.primary(Article, "id");
|
|
289
|
+
static byFullName = E.unique(Article, (a: Article) => [`${a.firstName} ${a.lastName}`]);
|
|
290
|
+
static byWord = E.index(Article, (a: Article) => a.title.toLowerCase().split(" "));
|
|
291
|
+
static byDomain = E.index(Article, (a: Article) => a.email ? [a.email.split("@")[1]] : []);
|
|
292
|
+
|
|
293
|
+
id = E.field(E.identifier);
|
|
294
|
+
firstName = E.field(E.string);
|
|
295
|
+
lastName = E.field(E.string);
|
|
296
|
+
title = E.field(E.string);
|
|
297
|
+
email = E.field(E.opt(E.string));
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
await E.transact(() => {
|
|
301
|
+
new Article({ firstName: "Jane", lastName: "Doe", title: "Hello World", email: "jane@acme.com" });
|
|
302
|
+
|
|
303
|
+
// Lookup via computed unique index
|
|
304
|
+
const jane = Article.byFullName.get("Jane Doe");
|
|
305
|
+
|
|
306
|
+
// Multi-value: each word in the title is indexed separately
|
|
307
|
+
for (const a of Article.byWord.find({is: "hello"})) { ... }
|
|
308
|
+
|
|
309
|
+
// Partial index: articles without email are skipped
|
|
310
|
+
for (const a of Article.byDomain.find({is: "acme.com"})) { ... }
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Computed indexes also support `find()` range queries and `batchProcess()`, just like field-based indexes.
|
|
315
|
+
|
|
316
|
+
### Relationships (Links)
|
|
317
|
+
|
|
318
|
+
Use `E.link(Model)` for foreign keys:
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
@E.registerModel
|
|
322
|
+
class Author extends E.Model<Author> {
|
|
323
|
+
static pk = E.primary(Author, "id");
|
|
324
|
+
id = E.field(E.identifier);
|
|
325
|
+
name = E.field(E.string);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
@E.registerModel
|
|
329
|
+
class Book extends E.Model<Book> {
|
|
330
|
+
static pk = E.primary(Book, "id");
|
|
331
|
+
id = E.field(E.identifier);
|
|
332
|
+
title = E.field(E.string);
|
|
333
|
+
author = E.field(E.link(Author));
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
await E.transact(() => {
|
|
337
|
+
const author = new Author({name: "Tolkien"});
|
|
338
|
+
const book = new Book({title: "The Hobbit", author});
|
|
339
|
+
|
|
340
|
+
// Later: linked models are lazy-loaded on property access
|
|
341
|
+
const b = Book.pk.get(book.id)!;
|
|
342
|
+
console.log(b.author.name); // loads Author automatically (~1µs)
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Deleting
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
await E.transact(() => {
|
|
350
|
+
const user = User.pk.get(someId);
|
|
351
|
+
if (user) user.delete();
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Model Utilities
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
await E.transact(() => {
|
|
359
|
+
const user = new User({name: "Bob", email: "bob@example.com", age: 25});
|
|
360
|
+
|
|
361
|
+
user.validate(); // returns Error[]
|
|
362
|
+
user.isValid(); // returns boolean
|
|
363
|
+
user.getState(); // "created" | "loaded" | "lazy" | "deleted"
|
|
364
|
+
user.getPrimaryKey(); // Uint8Array
|
|
365
|
+
user.preventPersist(); // exclude from commit
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// findAll iterates all instances
|
|
369
|
+
await E.transact(() => {
|
|
370
|
+
for (const user of User.findAll()) { ... }
|
|
371
|
+
for (const user of User.findAll({reverse: true})) { ... }
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// replaceInto: upsert by primary key
|
|
375
|
+
await E.transact(() => {
|
|
376
|
+
User.replaceInto({id: existingId, name: "Updated Name", email: "new@example.com", age: 30});
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Batch Processing
|
|
381
|
+
|
|
382
|
+
For large datasets, `batchProcess` auto-commits in batches:
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
await Product.byCategory.batchProcess({is: "old"}, (product) => {
|
|
386
|
+
product.category = "archived";
|
|
387
|
+
});
|
|
388
|
+
// Commits every ~1 second or 4096 rows (configurable via limitSeconds, limitRows)
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Schema Evolution
|
|
392
|
+
|
|
393
|
+
Edinburgh handles schema changes automatically:
|
|
394
|
+
|
|
395
|
+
- **Adding/removing fields**: Old rows are lazily migrated on read. New fields use their default value.
|
|
396
|
+
- **Changing field types**: Requires a `static migrate()` function.
|
|
397
|
+
- **Adding/removing indexes**: Requires running `npx migrate-edinburgh`.
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
@E.registerModel
|
|
401
|
+
class User extends E.Model<User> {
|
|
402
|
+
static pk = E.primary(User, "id");
|
|
403
|
+
id = E.field(E.identifier);
|
|
404
|
+
name = E.field(E.string);
|
|
405
|
+
role = E.field(E.string, {default: "user"}); // new field
|
|
406
|
+
|
|
407
|
+
static migrate(record: Record<string, any>) {
|
|
408
|
+
record.role ??= "user"; // provide value for old rows
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Run `npx migrate-edinburgh` (or call `E.runMigration()`) after adding/removing indexes, changing index field types, or when a `migrate()` function affects indexed fields.
|
|
414
|
+
|
|
415
|
+
### preCommit Hook
|
|
416
|
+
|
|
417
|
+
Compute derived fields before data is written:
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
@E.registerModel
|
|
421
|
+
class Article extends E.Model<Article> {
|
|
422
|
+
static pk = E.primary(Article, "id");
|
|
423
|
+
id = E.field(E.identifier);
|
|
424
|
+
title = E.field(E.string);
|
|
425
|
+
slug = E.field(E.string);
|
|
426
|
+
|
|
427
|
+
preCommit() {
|
|
428
|
+
this.slug = this.title.toLowerCase().replace(/\s+/g, "-");
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Change Tracking
|
|
434
|
+
|
|
435
|
+
Monitor commits with `setOnSaveCallback`:
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
E.setOnSaveCallback((commitId, items) => {
|
|
439
|
+
for (const [instance, change] of items) {
|
|
440
|
+
if (change === "created") { /* new record */ }
|
|
441
|
+
else if (change === "deleted") { /* removed */ }
|
|
442
|
+
else { /* change is an object with old values of modified fields */ }
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Logging
|
|
448
|
+
|
|
449
|
+
Enable debug logging by setting the `EDINBURGH_LOG_LEVEL` environment variable (0–3). Higher numbers produce more verbose logs.
|
|
89
450
|
|
|
90
451
|
- 0: no logging (default)
|
|
91
452
|
- 1: model-level logs
|
|
92
453
|
- 2: + update logs
|
|
93
454
|
- 3: + read logs
|
|
94
455
|
|
|
456
|
+
### AI Integration
|
|
457
|
+
|
|
458
|
+
If you use Claude Code, GitHub Copilot or another AI agent that supports Skills, Edinburgh includes a `skill/` directory in its npm package that provides specialized knowledge to the AI about how to use the library effectively.
|
|
459
|
+
|
|
460
|
+
Symlink the skill into your project's `.claude/skills` directory:
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
mkdir -p .claude/skills
|
|
464
|
+
ln -s ../../node_modules/edinburgh/skill .claude/skills/edinburgh
|
|
465
|
+
```
|
|
466
|
+
|
|
95
467
|
## API Reference
|
|
96
468
|
|
|
97
469
|
The following is auto-generated from `src/edinburgh.ts`:
|
|
@@ -100,7 +472,7 @@ The following is auto-generated from `src/edinburgh.ts`:
|
|
|
100
472
|
|
|
101
473
|
**Signature:** `() => void`
|
|
102
474
|
|
|
103
|
-
### init · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
475
|
+
### init · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L67)
|
|
104
476
|
|
|
105
477
|
Initialize the database with the specified directory path.
|
|
106
478
|
This function may be called multiple times with the same parameters. If it is not called before the first transact(),
|
|
@@ -118,7 +490,7 @@ the database will be automatically initialized with the default directory.
|
|
|
118
490
|
init("./my-database");
|
|
119
491
|
```
|
|
120
492
|
|
|
121
|
-
### transact · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
493
|
+
### transact · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L118)
|
|
122
494
|
|
|
123
495
|
Executes a function within a database transaction context.
|
|
124
496
|
|
|
@@ -168,7 +540,7 @@ await E.transact(() => {
|
|
|
168
540
|
});
|
|
169
541
|
```
|
|
170
542
|
|
|
171
|
-
### setMaxRetryCount · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
543
|
+
### setMaxRetryCount · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L208)
|
|
172
544
|
|
|
173
545
|
Set the maximum number of retries for a transaction in case of conflicts.
|
|
174
546
|
The default value is 6. Setting it to 0 will disable retries and cause transactions to fail immediately on conflict.
|
|
@@ -179,7 +551,7 @@ The default value is 6. Setting it to 0 will disable retries and cause transacti
|
|
|
179
551
|
|
|
180
552
|
- `count: number` - The maximum number of retries for a transaction.
|
|
181
553
|
|
|
182
|
-
### setOnSaveCallback · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
554
|
+
### setOnSaveCallback · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L222)
|
|
183
555
|
|
|
184
556
|
Set a callback function to be called after a model is saved and committed.
|
|
185
557
|
|
|
@@ -192,11 +564,11 @@ Set a callback function to be called after a model is saved and committed.
|
|
|
192
564
|
- A sequential number. Higher numbers have been committed after lower numbers.
|
|
193
565
|
- A map of model instances to their changes. The change can be "created", "deleted", or an object containing the old values.
|
|
194
566
|
|
|
195
|
-
### deleteEverything · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
567
|
+
### deleteEverything · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L227)
|
|
196
568
|
|
|
197
569
|
**Signature:** `() => Promise<void>`
|
|
198
570
|
|
|
199
|
-
### Model · [abstract class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
571
|
+
### Model · [abstract class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L220)
|
|
200
572
|
|
|
201
573
|
[object Object],[object Object],[object Object],[object Object],[object Object]
|
|
202
574
|
|
|
@@ -219,25 +591,25 @@ class User extends E.Model<User> {
|
|
|
219
591
|
}
|
|
220
592
|
```
|
|
221
593
|
|
|
222
|
-
#### Model.tableName · [static property](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
594
|
+
#### Model.tableName · [static property](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L227)
|
|
223
595
|
|
|
224
596
|
The database table name (defaults to class name).
|
|
225
597
|
|
|
226
598
|
**Type:** `string`
|
|
227
599
|
|
|
228
|
-
#### Model.override · [static property](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
600
|
+
#### Model.override · [static property](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L231)
|
|
229
601
|
|
|
230
602
|
When true, registerModel replaces an existing model with the same tableName.
|
|
231
603
|
|
|
232
604
|
**Type:** `boolean`
|
|
233
605
|
|
|
234
|
-
#### Model.fields · [static property](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
606
|
+
#### Model.fields · [static property](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L232)
|
|
235
607
|
|
|
236
608
|
Field configuration metadata.
|
|
237
609
|
|
|
238
610
|
**Type:** `Record<string | number | symbol, FieldConfig<unknown>>`
|
|
239
611
|
|
|
240
|
-
#### Model.migrate · [static method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
612
|
+
#### Model.migrate · [static method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
241
613
|
|
|
242
614
|
Optional migration function called when deserializing rows written with an older schema version.
|
|
243
615
|
Receives a plain record with all fields (primary key fields + value fields) and should mutate it
|
|
@@ -272,7 +644,7 @@ class User extends E.Model<User> {
|
|
|
272
644
|
}
|
|
273
645
|
```
|
|
274
646
|
|
|
275
|
-
#### Model.findAll · [static method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
647
|
+
#### Model.findAll · [static method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
276
648
|
|
|
277
649
|
Find all instances of this model in the database, ordered by primary key.
|
|
278
650
|
|
|
@@ -285,7 +657,7 @@ Find all instances of this model in the database, ordered by primary key.
|
|
|
285
657
|
|
|
286
658
|
**Returns:** An iterator.
|
|
287
659
|
|
|
288
|
-
#### Model.replaceInto · [static method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
660
|
+
#### Model.replaceInto · [static method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
289
661
|
|
|
290
662
|
Load an existing instance by primary key and update it, or create a new one.
|
|
291
663
|
|
|
@@ -302,7 +674,7 @@ new instance is created with `obj` as its initial properties.
|
|
|
302
674
|
|
|
303
675
|
**Returns:** The loaded-and-updated or newly created instance.
|
|
304
676
|
|
|
305
|
-
#### model.preCommit · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
677
|
+
#### model.preCommit · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
306
678
|
|
|
307
679
|
Optional hook called on each modified instance right before the transaction commits.
|
|
308
680
|
Runs before data is written to disk, so changes made here are included in the commit.
|
|
@@ -334,7 +706,7 @@ class Post extends E.Model<Post> {
|
|
|
334
706
|
}
|
|
335
707
|
```
|
|
336
708
|
|
|
337
|
-
#### model.getPrimaryKey · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
709
|
+
#### model.getPrimaryKey · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
338
710
|
|
|
339
711
|
**Signature:** `() => Uint8Array<ArrayBufferLike>`
|
|
340
712
|
|
|
@@ -343,7 +715,7 @@ class Post extends E.Model<Post> {
|
|
|
343
715
|
|
|
344
716
|
**Returns:** The primary key for this instance.
|
|
345
717
|
|
|
346
|
-
#### model.getPrimaryKeyHash · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
718
|
+
#### model.getPrimaryKeyHash · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
347
719
|
|
|
348
720
|
**Signature:** `() => number`
|
|
349
721
|
|
|
@@ -352,7 +724,7 @@ class Post extends E.Model<Post> {
|
|
|
352
724
|
|
|
353
725
|
**Returns:** A 53-bit positive integer non-cryptographic hash of the primary key, or undefined if not yet saved.
|
|
354
726
|
|
|
355
|
-
#### model.isLazyField · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
727
|
+
#### model.isLazyField · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
356
728
|
|
|
357
729
|
**Signature:** `(field: keyof this) => boolean`
|
|
358
730
|
|
|
@@ -360,7 +732,7 @@ class Post extends E.Model<Post> {
|
|
|
360
732
|
|
|
361
733
|
- `field: keyof this`
|
|
362
734
|
|
|
363
|
-
#### model.preventPersist · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
735
|
+
#### model.preventPersist · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
364
736
|
|
|
365
737
|
Prevent this instance from being persisted to the database.
|
|
366
738
|
|
|
@@ -379,7 +751,7 @@ user.name = "New Name";
|
|
|
379
751
|
user.preventPersist(); // Changes won't be saved
|
|
380
752
|
```
|
|
381
753
|
|
|
382
|
-
#### model.delete · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
754
|
+
#### model.delete · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
383
755
|
|
|
384
756
|
Delete this model instance from the database.
|
|
385
757
|
|
|
@@ -397,7 +769,7 @@ const user = User.load("user123");
|
|
|
397
769
|
user.delete(); // Removes from database
|
|
398
770
|
```
|
|
399
771
|
|
|
400
|
-
#### model.validate · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
772
|
+
#### model.validate · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
401
773
|
|
|
402
774
|
Validate all fields in this model instance.
|
|
403
775
|
|
|
@@ -419,7 +791,7 @@ if (errors.length > 0) {
|
|
|
419
791
|
}
|
|
420
792
|
```
|
|
421
793
|
|
|
422
|
-
#### model.isValid · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
794
|
+
#### model.isValid · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
423
795
|
|
|
424
796
|
Check if this model instance is valid.
|
|
425
797
|
|
|
@@ -437,28 +809,28 @@ const user = new User({name: "John"});
|
|
|
437
809
|
if (!user.isValid()) shoutAtTheUser();
|
|
438
810
|
```
|
|
439
811
|
|
|
440
|
-
#### model.getState · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
812
|
+
#### model.getState · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
441
813
|
|
|
442
814
|
**Signature:** `() => "created" | "deleted" | "loaded" | "lazy"`
|
|
443
815
|
|
|
444
816
|
**Parameters:**
|
|
445
817
|
|
|
446
818
|
|
|
447
|
-
#### model.toString · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
819
|
+
#### model.toString · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
448
820
|
|
|
449
821
|
**Signature:** `() => string`
|
|
450
822
|
|
|
451
823
|
**Parameters:**
|
|
452
824
|
|
|
453
825
|
|
|
454
|
-
#### model.[Symbol.for('nodejs.util.inspect.custom')] · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
826
|
+
#### model.[Symbol.for('nodejs.util.inspect.custom')] · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
455
827
|
|
|
456
828
|
**Signature:** `() => string`
|
|
457
829
|
|
|
458
830
|
**Parameters:**
|
|
459
831
|
|
|
460
832
|
|
|
461
|
-
### registerModel · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
833
|
+
### registerModel · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L113)
|
|
462
834
|
|
|
463
835
|
Register a model class with the Edinburgh ORM system.
|
|
464
836
|
|
|
@@ -485,7 +857,7 @@ class User extends E.Model<User> {
|
|
|
485
857
|
}
|
|
486
858
|
```
|
|
487
859
|
|
|
488
|
-
### field · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
860
|
+
### field · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L89)
|
|
489
861
|
|
|
490
862
|
Create a field definition for a model property.
|
|
491
863
|
|
|
@@ -515,13 +887,13 @@ class User extends E.Model<User> {
|
|
|
515
887
|
}
|
|
516
888
|
```
|
|
517
889
|
|
|
518
|
-
### string · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
890
|
+
### string · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
519
891
|
|
|
520
892
|
Type wrapper instance for the string type.
|
|
521
893
|
|
|
522
894
|
**Value:** `TypeWrapper<string>`
|
|
523
895
|
|
|
524
|
-
### orderedString · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
896
|
+
### orderedString · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
525
897
|
|
|
526
898
|
Type wrapper instance for the ordered string type, which is just like a string
|
|
527
899
|
except that it sorts lexicographically in the database (instead of by incrementing
|
|
@@ -531,37 +903,37 @@ may not contain null characters.
|
|
|
531
903
|
|
|
532
904
|
**Value:** `TypeWrapper<string>`
|
|
533
905
|
|
|
534
|
-
### number · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
906
|
+
### number · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
535
907
|
|
|
536
908
|
Type wrapper instance for the number type.
|
|
537
909
|
|
|
538
910
|
**Value:** `TypeWrapper<number>`
|
|
539
911
|
|
|
540
|
-
### dateTime · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
912
|
+
### dateTime · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
541
913
|
|
|
542
|
-
Type wrapper instance for the date/time type.
|
|
914
|
+
Type wrapper instance for the date/time type. Stored without timezone info, rounded to whole seconds.
|
|
543
915
|
|
|
544
916
|
**Value:** `TypeWrapper<Date>`
|
|
545
917
|
|
|
546
|
-
### boolean · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
918
|
+
### boolean · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
547
919
|
|
|
548
920
|
Type wrapper instance for the boolean type.
|
|
549
921
|
|
|
550
922
|
**Value:** `TypeWrapper<boolean>`
|
|
551
923
|
|
|
552
|
-
### identifier · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
924
|
+
### identifier · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
553
925
|
|
|
554
926
|
Type wrapper instance for the identifier type.
|
|
555
927
|
|
|
556
928
|
**Value:** `TypeWrapper<string>`
|
|
557
929
|
|
|
558
|
-
### undef · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
930
|
+
### undef · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
559
931
|
|
|
560
932
|
Type wrapper instance for the 'undefined' type.
|
|
561
933
|
|
|
562
934
|
**Value:** `TypeWrapper<undefined>`
|
|
563
935
|
|
|
564
|
-
### opt · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
936
|
+
### opt · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
565
937
|
|
|
566
938
|
Create an optional type wrapper (allows undefined).
|
|
567
939
|
|
|
@@ -584,7 +956,7 @@ const optionalString = E.opt(E.string);
|
|
|
584
956
|
const optionalNumber = E.opt(E.number);
|
|
585
957
|
```
|
|
586
958
|
|
|
587
|
-
### or · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
959
|
+
### or · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
588
960
|
|
|
589
961
|
Create a union type wrapper from multiple type choices.
|
|
590
962
|
|
|
@@ -607,7 +979,7 @@ const stringOrNumber = E.or(E.string, E.number);
|
|
|
607
979
|
const status = E.or("active", "inactive", "pending");
|
|
608
980
|
```
|
|
609
981
|
|
|
610
|
-
### array · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
982
|
+
### array · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
611
983
|
|
|
612
984
|
Create an array type wrapper with optional length constraints.
|
|
613
985
|
|
|
@@ -631,7 +1003,53 @@ const stringArray = E.array(E.string);
|
|
|
631
1003
|
const boundedArray = E.array(E.number, {min: 1, max: 10});
|
|
632
1004
|
```
|
|
633
1005
|
|
|
634
|
-
###
|
|
1006
|
+
### set · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
1007
|
+
|
|
1008
|
+
Create a Set type wrapper with optional length constraints.
|
|
1009
|
+
|
|
1010
|
+
**Signature:** `<const T>(inner: TypeWrapper<T>, opts?: { min?: number; max?: number; }) => TypeWrapper<Set<T>>`
|
|
1011
|
+
|
|
1012
|
+
**Type Parameters:**
|
|
1013
|
+
|
|
1014
|
+
- `T` - The element type.
|
|
1015
|
+
|
|
1016
|
+
**Parameters:**
|
|
1017
|
+
|
|
1018
|
+
- `inner: TypeWrapper<T>` - - Type wrapper for set elements.
|
|
1019
|
+
- `opts: {min?: number, max?: number}` (optional) - - Optional constraints (min/max length).
|
|
1020
|
+
|
|
1021
|
+
**Returns:** A set type instance.
|
|
1022
|
+
|
|
1023
|
+
**Examples:**
|
|
1024
|
+
|
|
1025
|
+
```typescript
|
|
1026
|
+
const stringSet = E.set(E.string);
|
|
1027
|
+
const boundedSet = E.set(E.number, {min: 1, max: 10});
|
|
1028
|
+
```
|
|
1029
|
+
|
|
1030
|
+
### record · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
1031
|
+
|
|
1032
|
+
Create a Record type wrapper for key-value objects with string or number keys.
|
|
1033
|
+
|
|
1034
|
+
**Signature:** `<const T>(inner: TypeWrapper<T>) => TypeWrapper<Record<string | number, T>>`
|
|
1035
|
+
|
|
1036
|
+
**Type Parameters:**
|
|
1037
|
+
|
|
1038
|
+
- `T` - The value type.
|
|
1039
|
+
|
|
1040
|
+
**Parameters:**
|
|
1041
|
+
|
|
1042
|
+
- `inner: TypeWrapper<T>` - - Type wrapper for record values.
|
|
1043
|
+
|
|
1044
|
+
**Returns:** A record type instance.
|
|
1045
|
+
|
|
1046
|
+
**Examples:**
|
|
1047
|
+
|
|
1048
|
+
```typescript
|
|
1049
|
+
const scores = E.record(E.number); // Record<string | number, number>
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
### literal · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
635
1053
|
|
|
636
1054
|
Create a literal type wrapper for a constant value.
|
|
637
1055
|
|
|
@@ -654,7 +1072,7 @@ const statusType = E.literal("active");
|
|
|
654
1072
|
const countType = E.literal(42);
|
|
655
1073
|
```
|
|
656
1074
|
|
|
657
|
-
### link · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1075
|
+
### link · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
658
1076
|
|
|
659
1077
|
Create a link type wrapper for model relationships.
|
|
660
1078
|
|
|
@@ -682,21 +1100,26 @@ class Post extends E.Model<Post> {
|
|
|
682
1100
|
}
|
|
683
1101
|
```
|
|
684
1102
|
|
|
685
|
-
### index · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1103
|
+
### index · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
686
1104
|
|
|
687
|
-
Create a secondary index on model fields.
|
|
1105
|
+
Create a secondary index on model fields, or a computed secondary index using a function.
|
|
688
1106
|
|
|
689
|
-
|
|
1107
|
+
For field-based indexes, pass a field name or array of field names.
|
|
1108
|
+
For computed indexes, pass a function that takes a model instance and returns an array of
|
|
1109
|
+
index keys. Return `[]` to skip indexing for that instance. Each array element creates a
|
|
1110
|
+
separate index entry, enabling multi-value indexes (e.g., indexing by each word in a name).
|
|
1111
|
+
|
|
1112
|
+
**Signature:** `{ <M extends typeof Model, V>(MyModel: M, fn: (instance: InstanceType<M>) => V[]): SecondaryIndex<M, [], [V]>; <M extends typeof Model, const F extends (keyof InstanceType<M> & string)>(MyModel: M, field: F): SecondaryIndex<...>; <M extends typeof Model, const FS extends readonly (keyof InstanceType<M> & string)[]>(...`
|
|
690
1113
|
|
|
691
1114
|
**Type Parameters:**
|
|
692
1115
|
|
|
693
1116
|
- `M extends typeof Model` - The model class.
|
|
694
|
-
- `
|
|
1117
|
+
- `V` - The computed index value type (for function-based indexes).
|
|
695
1118
|
|
|
696
1119
|
**Parameters:**
|
|
697
1120
|
|
|
698
1121
|
- `MyModel: M` - - The model class to create the index for.
|
|
699
|
-
- `
|
|
1122
|
+
- `fn: (instance: InstanceType<M>) => V[]`
|
|
700
1123
|
|
|
701
1124
|
**Returns:** A new SecondaryIndex instance.
|
|
702
1125
|
|
|
@@ -706,10 +1129,11 @@ Create a secondary index on model fields.
|
|
|
706
1129
|
class User extends E.Model<User> {
|
|
707
1130
|
static byAge = E.index(User, "age");
|
|
708
1131
|
static byTagsDate = E.index(User, ["tags", "createdAt"]);
|
|
1132
|
+
static byWord = E.index(User, (u: User) => u.name.split(" "));
|
|
709
1133
|
}
|
|
710
1134
|
```
|
|
711
1135
|
|
|
712
|
-
### primary · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1136
|
+
### primary · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
713
1137
|
|
|
714
1138
|
Create a primary index on model fields.
|
|
715
1139
|
|
|
@@ -736,21 +1160,26 @@ class User extends E.Model<User> {
|
|
|
736
1160
|
}
|
|
737
1161
|
```
|
|
738
1162
|
|
|
739
|
-
### unique · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1163
|
+
### unique · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
1164
|
+
|
|
1165
|
+
Create a unique index on model fields, or a computed unique index using a function.
|
|
740
1166
|
|
|
741
|
-
|
|
1167
|
+
For field-based indexes, pass a field name or array of field names.
|
|
1168
|
+
For computed indexes, pass a function that takes a model instance and returns an array of
|
|
1169
|
+
index keys. Return `[]` to skip indexing for that instance. Each array element creates a
|
|
1170
|
+
separate index entry, enabling multi-value indexes (e.g., indexing by each word in a name).
|
|
742
1171
|
|
|
743
|
-
**Signature:** `{ <M extends typeof Model, const F extends (keyof InstanceType<M> & string)>(MyModel: M, field: F): UniqueIndex
|
|
1172
|
+
**Signature:** `{ <M extends typeof Model, V>(MyModel: M, fn: (instance: InstanceType<M>) => V[]): UniqueIndex<M, [], [V]>; <M extends typeof Model, const F extends (keyof InstanceType<M> & string)>(MyModel: M, field: F): UniqueIndex<...>; <M extends typeof Model, const FS extends readonly (keyof InstanceType<M> & string)[]>(MyMode...`
|
|
744
1173
|
|
|
745
1174
|
**Type Parameters:**
|
|
746
1175
|
|
|
747
1176
|
- `M extends typeof Model` - The model class.
|
|
748
|
-
- `
|
|
1177
|
+
- `V` - The computed index value type (for function-based indexes).
|
|
749
1178
|
|
|
750
1179
|
**Parameters:**
|
|
751
1180
|
|
|
752
1181
|
- `MyModel: M` - - The model class to create the index for.
|
|
753
|
-
- `
|
|
1182
|
+
- `fn: (instance: InstanceType<M>) => V[]`
|
|
754
1183
|
|
|
755
1184
|
**Returns:** A new UniqueIndex instance.
|
|
756
1185
|
|
|
@@ -760,10 +1189,11 @@ Create a unique index on model fields.
|
|
|
760
1189
|
class User extends E.Model<User> {
|
|
761
1190
|
static byEmail = E.unique(User, "email");
|
|
762
1191
|
static byNameAge = E.unique(User, ["name", "age"]);
|
|
1192
|
+
static byFullName = E.unique(User, (u: User) => [`${u.firstName} ${u.lastName}`]);
|
|
763
1193
|
}
|
|
764
1194
|
```
|
|
765
1195
|
|
|
766
|
-
### dump · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1196
|
+
### dump · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
767
1197
|
|
|
768
1198
|
Dump database contents for debugging.
|
|
769
1199
|
|
|
@@ -772,7 +1202,7 @@ This is primarily useful for development and debugging purposes.
|
|
|
772
1202
|
|
|
773
1203
|
**Signature:** `() => void`
|
|
774
1204
|
|
|
775
|
-
### BaseIndex · [abstract class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1205
|
+
### BaseIndex · [abstract class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L125)
|
|
776
1206
|
|
|
777
1207
|
Base class for database indexes for efficient lookups on model fields.
|
|
778
1208
|
|
|
@@ -782,39 +1212,40 @@ Indexes enable fast queries on specific field combinations and enforce uniquenes
|
|
|
782
1212
|
|
|
783
1213
|
- `M extends typeof Model` - The model class this index belongs to.
|
|
784
1214
|
- `F extends readonly (keyof InstanceType<M> & string)[]` - The field names that make up this index.
|
|
1215
|
+
- `ARGS extends readonly any[] = IndexArgTypes<M, F>`
|
|
785
1216
|
|
|
786
1217
|
**Constructor Parameters:**
|
|
787
1218
|
|
|
788
1219
|
- `MyModel`: - The model class this index belongs to.
|
|
789
1220
|
- `_fieldNames`: - Array of field names that make up this index.
|
|
790
1221
|
|
|
791
|
-
#### baseIndex.find · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1222
|
+
#### baseIndex.find · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
792
1223
|
|
|
793
|
-
**Signature:** `(opts?: FindOptions<
|
|
1224
|
+
**Signature:** `(opts?: FindOptions<ARGS>) => IndexRangeIterator<M>`
|
|
794
1225
|
|
|
795
1226
|
**Parameters:**
|
|
796
1227
|
|
|
797
|
-
- `opts: FindOptions<
|
|
1228
|
+
- `opts: FindOptions<ARGS>` (optional)
|
|
798
1229
|
|
|
799
|
-
#### baseIndex.batchProcess · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1230
|
+
#### baseIndex.batchProcess · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
800
1231
|
|
|
801
1232
|
[object Object],[object Object],[object Object]
|
|
802
1233
|
|
|
803
|
-
**Signature:** `(opts: FindOptions<
|
|
1234
|
+
**Signature:** `(opts: FindOptions<ARGS> & { limitSeconds?: number; limitRows?: number; }, callback: (row: InstanceType<M>) => void | Promise<void>) => Promise<...>`
|
|
804
1235
|
|
|
805
1236
|
**Parameters:**
|
|
806
1237
|
|
|
807
|
-
- `opts: FindOptions<
|
|
1238
|
+
- `opts: FindOptions<ARGS> & { limitSeconds?: number; limitRows?: number }` (optional) - - Query options (same as `find()`), plus:
|
|
808
1239
|
- `callback: (row: InstanceType<M>) => void | Promise<void>` - - Called for each matching row within a transaction
|
|
809
1240
|
|
|
810
|
-
#### baseIndex.toString · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1241
|
+
#### baseIndex.toString · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
811
1242
|
|
|
812
1243
|
**Signature:** `() => string`
|
|
813
1244
|
|
|
814
1245
|
**Parameters:**
|
|
815
1246
|
|
|
816
1247
|
|
|
817
|
-
### UniqueIndex · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1248
|
+
### UniqueIndex · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
818
1249
|
|
|
819
1250
|
Unique index that stores references to the primary key.
|
|
820
1251
|
|
|
@@ -822,16 +1253,17 @@ Unique index that stores references to the primary key.
|
|
|
822
1253
|
|
|
823
1254
|
- `M extends typeof Model` - The model class this index belongs to.
|
|
824
1255
|
- `F extends readonly (keyof InstanceType<M> & string)[]` - The field names that make up this index.
|
|
1256
|
+
- `ARGS extends readonly any[] = IndexArgTypes<M, F>`
|
|
825
1257
|
|
|
826
|
-
#### uniqueIndex.get · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1258
|
+
#### uniqueIndex.get · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
827
1259
|
|
|
828
1260
|
Get a model instance by unique index key values.
|
|
829
1261
|
|
|
830
|
-
**Signature:** `(...args:
|
|
1262
|
+
**Signature:** `(...args: ARGS) => InstanceType<M>`
|
|
831
1263
|
|
|
832
1264
|
**Parameters:**
|
|
833
1265
|
|
|
834
|
-
- `args:
|
|
1266
|
+
- `args: ARGS` - - The unique index key values.
|
|
835
1267
|
|
|
836
1268
|
**Returns:** The model instance if found, undefined otherwise.
|
|
837
1269
|
|
|
@@ -841,7 +1273,7 @@ Get a model instance by unique index key values.
|
|
|
841
1273
|
const userByEmail = User.byEmail.get("john@example.com");
|
|
842
1274
|
```
|
|
843
1275
|
|
|
844
|
-
### PrimaryIndex · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1276
|
+
### PrimaryIndex · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
845
1277
|
|
|
846
1278
|
Primary index that stores the actual model data.
|
|
847
1279
|
|
|
@@ -850,7 +1282,7 @@ Primary index that stores the actual model data.
|
|
|
850
1282
|
- `M extends typeof Model` - The model class this index belongs to.
|
|
851
1283
|
- `F extends readonly (keyof InstanceType<M> & string)[]` - The field names that make up this index.
|
|
852
1284
|
|
|
853
|
-
#### primaryIndex.get · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1285
|
+
#### primaryIndex.get · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
854
1286
|
|
|
855
1287
|
Get a model instance by primary key values.
|
|
856
1288
|
|
|
@@ -868,7 +1300,7 @@ Get a model instance by primary key values.
|
|
|
868
1300
|
const user = User.pk.get("john_doe");
|
|
869
1301
|
```
|
|
870
1302
|
|
|
871
|
-
#### primaryIndex.getLazy · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1303
|
+
#### primaryIndex.getLazy · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
872
1304
|
|
|
873
1305
|
Does the same as as `get()`, but will delay loading the instance from disk until the first
|
|
874
1306
|
property access. In case it turns out the instance doesn't exist, an error will be thrown
|
|
@@ -882,7 +1314,7 @@ at that time.
|
|
|
882
1314
|
|
|
883
1315
|
**Returns:** The (lazily loaded) model instance.
|
|
884
1316
|
|
|
885
|
-
### SecondaryIndex · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1317
|
+
### SecondaryIndex · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
886
1318
|
|
|
887
1319
|
Secondary index for non-unique lookups.
|
|
888
1320
|
|
|
@@ -890,8 +1322,9 @@ Secondary index for non-unique lookups.
|
|
|
890
1322
|
|
|
891
1323
|
- `M extends typeof Model` - The model class this index belongs to.
|
|
892
1324
|
- `F extends readonly (keyof InstanceType<M> & string)[]` - The field names that make up this index.
|
|
1325
|
+
- `ARGS extends readonly any[] = IndexArgTypes<M, F>`
|
|
893
1326
|
|
|
894
|
-
### Change · [type](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1327
|
+
### Change · [type](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L95)
|
|
895
1328
|
|
|
896
1329
|
**Type:** `Record<any, any> | "created" | "deleted"`
|
|
897
1330
|
|
|
@@ -905,11 +1338,11 @@ Secondary index for non-unique lookups.
|
|
|
905
1338
|
|
|
906
1339
|
**Type:** `Set<Model<unknown>>`
|
|
907
1340
|
|
|
908
|
-
#### transaction.instancesByPk · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1341
|
+
#### transaction.instancesByPk · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L46)
|
|
909
1342
|
|
|
910
1343
|
**Type:** `Map<number, Model<unknown>>`
|
|
911
1344
|
|
|
912
|
-
### DatabaseError · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1345
|
+
### DatabaseError · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L157)
|
|
913
1346
|
|
|
914
1347
|
The DatabaseError class is used to represent errors that occur during database operations.
|
|
915
1348
|
It extends the built-in Error class and has a machine readable error code string property.
|
|
@@ -919,7 +1352,7 @@ Invalid function arguments will throw TypeError.
|
|
|
919
1352
|
|
|
920
1353
|
**Value:** `DatabaseErrorConstructor`
|
|
921
1354
|
|
|
922
|
-
### runMigration · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1355
|
+
### runMigration · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L118)
|
|
923
1356
|
|
|
924
1357
|
Run database migration: upgrade all rows to the latest schema version,
|
|
925
1358
|
convert old primary indices, and clean up orphaned secondary indices.
|
|
@@ -938,51 +1371,51 @@ Limit migration to specific table names.
|
|
|
938
1371
|
|
|
939
1372
|
**Type:** `string[]`
|
|
940
1373
|
|
|
941
|
-
#### migrationOptions.convertOldPrimaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1374
|
+
#### migrationOptions.convertOldPrimaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L23)
|
|
942
1375
|
|
|
943
1376
|
Whether to convert old primary indices for known tables (default: true).
|
|
944
1377
|
|
|
945
1378
|
**Type:** `boolean`
|
|
946
1379
|
|
|
947
|
-
#### migrationOptions.deleteOrphanedIndexes · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1380
|
+
#### migrationOptions.deleteOrphanedIndexes · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L31)
|
|
948
1381
|
|
|
949
1382
|
Whether to delete orphaned secondary/unique indices (default: true).
|
|
950
1383
|
|
|
951
1384
|
**Type:** `boolean`
|
|
952
1385
|
|
|
953
|
-
#### migrationOptions.upgradeVersions · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1386
|
+
#### migrationOptions.upgradeVersions · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L39)
|
|
954
1387
|
|
|
955
1388
|
Whether to upgrade rows to the latest version (default: true).
|
|
956
1389
|
|
|
957
1390
|
**Type:** `boolean`
|
|
958
1391
|
|
|
959
|
-
#### migrationOptions.onProgress · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1392
|
+
#### migrationOptions.onProgress · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L44)
|
|
960
1393
|
|
|
961
1394
|
Progress callback.
|
|
962
1395
|
|
|
963
1396
|
**Type:** `(info: ProgressInfo) => void`
|
|
964
1397
|
|
|
965
|
-
### MigrationResult · [interface](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1398
|
+
### MigrationResult · [interface](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L49)
|
|
966
1399
|
|
|
967
|
-
#### migrationResult.secondaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1400
|
+
#### migrationResult.secondaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L51)
|
|
968
1401
|
|
|
969
1402
|
Per-table stats for row upgrades.
|
|
970
1403
|
|
|
971
1404
|
**Type:** `Record<string, number>`
|
|
972
1405
|
|
|
973
|
-
#### migrationResult.primaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1406
|
+
#### migrationResult.primaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L52)
|
|
974
1407
|
|
|
975
1408
|
Per-table stats for old primary conversions.
|
|
976
1409
|
|
|
977
1410
|
**Type:** `Record<string, number>`
|
|
978
1411
|
|
|
979
|
-
#### migrationResult.conversionFailures · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1412
|
+
#### migrationResult.conversionFailures · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L58)
|
|
980
1413
|
|
|
981
1414
|
Per-table conversion failure counts by reason.
|
|
982
1415
|
|
|
983
1416
|
**Type:** `Record<string, Record<string, number>>`
|
|
984
1417
|
|
|
985
|
-
#### migrationResult.orphaned · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1418
|
+
#### migrationResult.orphaned · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L59)
|
|
986
1419
|
|
|
987
1420
|
Number of orphaned index entries deleted.
|
|
988
1421
|
|