orchid-orm 1.17.36 → 1.17.37
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/dist/index.d.ts +147 -142
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -337,7 +337,10 @@ type MapRelations<T extends Table> = T extends {
|
|
|
337
337
|
[K in keyof T['relations']]: MapRelation<T, T['relations'], K>;
|
|
338
338
|
} : EmptyObject;
|
|
339
339
|
|
|
340
|
-
type TableClass<T extends Table = Table> =
|
|
340
|
+
type TableClass<T extends Table = Table> = {
|
|
341
|
+
new (): T;
|
|
342
|
+
instance(): T;
|
|
343
|
+
};
|
|
341
344
|
type TableClasses = Record<string, TableClass>;
|
|
342
345
|
type TableToDb<T extends Table, RelationQueries extends Record<string, RelationQueryBase>> = Db<T['table'], T['columns'], RelationQueries, T['types'], T['computed'] extends ComputedColumnsBase<never> ? T['columns'] & {
|
|
343
346
|
[K in keyof T['computed']]: ReturnType<T['computed'][K]>['_type'];
|
|
@@ -370,151 +373,153 @@ type BeforeHookMethod = <T extends Table>(cb: QueryBeforeHook) => T;
|
|
|
370
373
|
type AfterHookMethod = <T extends Table>(cb: QueryAfterHook) => T;
|
|
371
374
|
type AfterSelectableHookMethod = <T extends Table, S extends (keyof T['columns'])[]>(this: T, select: S, cb: AfterHook<S, T['columns']>) => T;
|
|
372
375
|
type SchemaProviderBase = any;
|
|
376
|
+
interface BaseTableInstance<ColumnTypes> {
|
|
377
|
+
table: string;
|
|
378
|
+
columns: ColumnsShapeBase;
|
|
379
|
+
schema?: string;
|
|
380
|
+
noPrimaryKey?: boolean;
|
|
381
|
+
snakeCase?: boolean;
|
|
382
|
+
types: ColumnTypes;
|
|
383
|
+
q: QueryData;
|
|
384
|
+
language?: string;
|
|
385
|
+
filePath: string;
|
|
386
|
+
result: ColumnsShapeBase;
|
|
387
|
+
clone<T extends QueryBase>(this: T): T;
|
|
388
|
+
getFilePath(): string;
|
|
389
|
+
setColumns<T extends ColumnsShapeBase>(fn: (t: ColumnTypes) => T): T;
|
|
390
|
+
/**
|
|
391
|
+
* You can add a generated column in the migration (see [generated](/guide/migration-column-methods.html#generated-column)),
|
|
392
|
+
* such column will persist in the database, it can be indexed.
|
|
393
|
+
*
|
|
394
|
+
* Or you can add a computed column on the ORM level, without adding it to the database, in such a way:
|
|
395
|
+
*
|
|
396
|
+
* ```ts
|
|
397
|
+
* import { BaseTable } from './baseTable';
|
|
398
|
+
*
|
|
399
|
+
* export class UserTable extends BaseTable {
|
|
400
|
+
* readonly table = 'user';
|
|
401
|
+
* columns = this.setColumns((t) => ({
|
|
402
|
+
* id: t.identity().primaryKey(),
|
|
403
|
+
* firstName: t.string(),
|
|
404
|
+
* lastName: t.string(),
|
|
405
|
+
* }));
|
|
406
|
+
*
|
|
407
|
+
* computed = this.setComputed({
|
|
408
|
+
* fullName: (q) =>
|
|
409
|
+
* q.sql`${q.column('firstName')} || ' ' || ${q.column('lastName')}`.type(
|
|
410
|
+
* (t) => t.string(),
|
|
411
|
+
* ),
|
|
412
|
+
* });
|
|
413
|
+
* }
|
|
414
|
+
* ```
|
|
415
|
+
*
|
|
416
|
+
* `setComputed` takes an object where keys are computed column names, and values are functions returning raw SQL.
|
|
417
|
+
*
|
|
418
|
+
* Use `q.column` as shown above to reference a table column, it will be prefixed with a correct table name even if the table is joined under a different name.
|
|
419
|
+
*
|
|
420
|
+
* Computed columns are not selected by default, only on demand:
|
|
421
|
+
*
|
|
422
|
+
* ```ts
|
|
423
|
+
* const a = await db.user.take();
|
|
424
|
+
* a.fullName; // not selected
|
|
425
|
+
*
|
|
426
|
+
* const b = await db.user.select('*', 'fullName');
|
|
427
|
+
* b.fullName; // selected
|
|
428
|
+
*
|
|
429
|
+
* // Table post belongs to user as an author.
|
|
430
|
+
* // it's possible to select joined computed column:
|
|
431
|
+
* const posts = await db.post
|
|
432
|
+
* .join('author')
|
|
433
|
+
* .select('post.title', 'author.fullName');
|
|
434
|
+
* ```
|
|
435
|
+
*
|
|
436
|
+
* SQL query can be generated dynamically based on the current request context.
|
|
437
|
+
*
|
|
438
|
+
* Imagine we are using [AsyncLocalStorage](https://nodejs.org/api/async_context.html#asynchronous-context-tracking)
|
|
439
|
+
* to keep track of current user's language.
|
|
440
|
+
*
|
|
441
|
+
* And we have articles translated to different languages, each article has `title_en`, `title_uk`, `title_be` and so on.
|
|
442
|
+
*
|
|
443
|
+
* We can define a computed `title` by passing a function into `sql` method:
|
|
444
|
+
*
|
|
445
|
+
* ```ts
|
|
446
|
+
* type Locale = 'en' | 'uk' | 'be';
|
|
447
|
+
* const asyncLanguageStorage = new AsyncLocalStorage<Locale>();
|
|
448
|
+
* const defaultLocale: Locale = 'en';
|
|
449
|
+
*
|
|
450
|
+
* export class ArticleTable extends BaseTable {
|
|
451
|
+
* readonly table = 'article';
|
|
452
|
+
* columns = this.setColumns((t) => ({
|
|
453
|
+
* id: t.identity().primaryKey(),
|
|
454
|
+
* title_en: t.text(),
|
|
455
|
+
* title_uk: t.text().nullable(),
|
|
456
|
+
* title_be: t.text().nullable(),
|
|
457
|
+
* }));
|
|
458
|
+
*
|
|
459
|
+
* computed = this.setComputed({
|
|
460
|
+
* title: (q) =>
|
|
461
|
+
* q
|
|
462
|
+
* // .sql can take a function that accepts `sql` argument and must return SQL
|
|
463
|
+
* .sql((sql) => {
|
|
464
|
+
* // get locale dynamically based on current storage value
|
|
465
|
+
* const locale = asyncLanguageStorage.getStore() || defaultLocale;
|
|
466
|
+
*
|
|
467
|
+
* // use COALESCE in case when localized title is NULL, use title_en
|
|
468
|
+
* return sql`COALESCE(
|
|
469
|
+
* ${q.column(`title_${locale}`)},
|
|
470
|
+
* ${q.column(`title_${defaultLocale}`)}
|
|
471
|
+
* )`;
|
|
472
|
+
* })
|
|
473
|
+
* .type((t) => t.text()),
|
|
474
|
+
* });
|
|
475
|
+
* }
|
|
476
|
+
* ```
|
|
477
|
+
*
|
|
478
|
+
* @param computed - object where keys are column names and values are functions returning raw SQL
|
|
479
|
+
*/
|
|
480
|
+
setComputed<Table extends string, Shape extends ColumnsShapeBase, Computed extends ComputedColumnsBase<Db<Table, Shape, EmptyObject, ColumnTypes>>>(computed: Computed): Computed;
|
|
481
|
+
belongsTo<Self extends Table, Related extends TableClass, Scope extends Query, Options extends BelongsToOptions<Self, Related, Scope>>(this: Self, fn: () => Related, options: Options): {
|
|
482
|
+
type: 'belongsTo';
|
|
483
|
+
fn: () => Related;
|
|
484
|
+
options: Options;
|
|
485
|
+
};
|
|
486
|
+
hasOne<Self extends Table, Related extends TableClass, Scope extends Query, Through extends string, Source extends string, Options extends HasOneOptions<Self, Related, Scope, Through, Source>>(this: Self, fn: () => Related, options: Options): {
|
|
487
|
+
type: 'hasOne';
|
|
488
|
+
fn: () => Related;
|
|
489
|
+
options: Options;
|
|
490
|
+
};
|
|
491
|
+
hasMany<Self extends Table, Related extends TableClass, Scope extends Query, Through extends string, Source extends string, Options extends HasManyOptions<Self, Related, Scope, Through, Source>>(this: Self, fn: () => Related, options: Options): {
|
|
492
|
+
type: 'hasMany';
|
|
493
|
+
fn: () => Related;
|
|
494
|
+
options: Options;
|
|
495
|
+
};
|
|
496
|
+
hasAndBelongsToMany<Self extends Table, Related extends TableClass, Scope extends Query, Options extends HasAndBelongsToManyOptions<Self, Related, Scope>>(this: Self, fn: () => Related, options: Options): {
|
|
497
|
+
type: 'hasAndBelongsToMany';
|
|
498
|
+
fn: () => Related;
|
|
499
|
+
options: Options;
|
|
500
|
+
};
|
|
501
|
+
beforeQuery: BeforeHookMethod;
|
|
502
|
+
afterQuery: AfterHookMethod;
|
|
503
|
+
beforeCreate: BeforeHookMethod;
|
|
504
|
+
afterCreate: AfterSelectableHookMethod;
|
|
505
|
+
afterCreateCommit: AfterSelectableHookMethod;
|
|
506
|
+
beforeUpdate: BeforeHookMethod;
|
|
507
|
+
afterUpdate: AfterSelectableHookMethod;
|
|
508
|
+
afterUpdateCommit: AfterSelectableHookMethod;
|
|
509
|
+
beforeSave: BeforeHookMethod;
|
|
510
|
+
afterSave: AfterSelectableHookMethod;
|
|
511
|
+
afterSaveCommit: AfterSelectableHookMethod;
|
|
512
|
+
beforeDelete: BeforeHookMethod;
|
|
513
|
+
afterDelete: AfterSelectableHookMethod;
|
|
514
|
+
afterDeleteCommit: AfterSelectableHookMethod;
|
|
515
|
+
}
|
|
373
516
|
interface BaseTableClass<ColumnTypes, SchemaProvider extends SchemaProviderBase> {
|
|
374
517
|
nowSQL: string | undefined;
|
|
375
518
|
exportAs: string;
|
|
376
519
|
schema: SchemaProvider;
|
|
377
520
|
getFilePath(): string;
|
|
378
|
-
new ():
|
|
379
|
-
|
|
380
|
-
columns: ColumnsShapeBase;
|
|
381
|
-
schema?: string;
|
|
382
|
-
noPrimaryKey?: boolean;
|
|
383
|
-
snakeCase?: boolean;
|
|
384
|
-
types: ColumnTypes;
|
|
385
|
-
q: QueryData;
|
|
386
|
-
language?: string;
|
|
387
|
-
filePath: string;
|
|
388
|
-
result: ColumnsShapeBase;
|
|
389
|
-
clone<T extends QueryBase>(this: T): T;
|
|
390
|
-
getFilePath(): string;
|
|
391
|
-
setColumns<T extends ColumnsShapeBase>(fn: (t: ColumnTypes) => T): T;
|
|
392
|
-
/**
|
|
393
|
-
* You can add a generated column in the migration (see [generated](/guide/migration-column-methods.html#generated-column)),
|
|
394
|
-
* such column will persist in the database, it can be indexed.
|
|
395
|
-
*
|
|
396
|
-
* Or you can add a computed column on the ORM level, without adding it to the database, in such a way:
|
|
397
|
-
*
|
|
398
|
-
* ```ts
|
|
399
|
-
* import { BaseTable } from './baseTable';
|
|
400
|
-
*
|
|
401
|
-
* export class UserTable extends BaseTable {
|
|
402
|
-
* readonly table = 'user';
|
|
403
|
-
* columns = this.setColumns((t) => ({
|
|
404
|
-
* id: t.identity().primaryKey(),
|
|
405
|
-
* firstName: t.string(),
|
|
406
|
-
* lastName: t.string(),
|
|
407
|
-
* }));
|
|
408
|
-
*
|
|
409
|
-
* computed = this.setComputed({
|
|
410
|
-
* fullName: (q) =>
|
|
411
|
-
* q.sql`${q.column('firstName')} || ' ' || ${q.column('lastName')}`.type(
|
|
412
|
-
* (t) => t.string(),
|
|
413
|
-
* ),
|
|
414
|
-
* });
|
|
415
|
-
* }
|
|
416
|
-
* ```
|
|
417
|
-
*
|
|
418
|
-
* `setComputed` takes an object where keys are computed column names, and values are functions returning raw SQL.
|
|
419
|
-
*
|
|
420
|
-
* Use `q.column` as shown above to reference a table column, it will be prefixed with a correct table name even if the table is joined under a different name.
|
|
421
|
-
*
|
|
422
|
-
* Computed columns are not selected by default, only on demand:
|
|
423
|
-
*
|
|
424
|
-
* ```ts
|
|
425
|
-
* const a = await db.user.take();
|
|
426
|
-
* a.fullName; // not selected
|
|
427
|
-
*
|
|
428
|
-
* const b = await db.user.select('*', 'fullName');
|
|
429
|
-
* b.fullName; // selected
|
|
430
|
-
*
|
|
431
|
-
* // Table post belongs to user as an author.
|
|
432
|
-
* // it's possible to select joined computed column:
|
|
433
|
-
* const posts = await db.post
|
|
434
|
-
* .join('author')
|
|
435
|
-
* .select('post.title', 'author.fullName');
|
|
436
|
-
* ```
|
|
437
|
-
*
|
|
438
|
-
* SQL query can be generated dynamically based on the current request context.
|
|
439
|
-
*
|
|
440
|
-
* Imagine we are using [AsyncLocalStorage](https://nodejs.org/api/async_context.html#asynchronous-context-tracking)
|
|
441
|
-
* to keep track of current user's language.
|
|
442
|
-
*
|
|
443
|
-
* And we have articles translated to different languages, each article has `title_en`, `title_uk`, `title_be` and so on.
|
|
444
|
-
*
|
|
445
|
-
* We can define a computed `title` by passing a function into `sql` method:
|
|
446
|
-
*
|
|
447
|
-
* ```ts
|
|
448
|
-
* type Locale = 'en' | 'uk' | 'be';
|
|
449
|
-
* const asyncLanguageStorage = new AsyncLocalStorage<Locale>();
|
|
450
|
-
* const defaultLocale: Locale = 'en';
|
|
451
|
-
*
|
|
452
|
-
* export class ArticleTable extends BaseTable {
|
|
453
|
-
* readonly table = 'article';
|
|
454
|
-
* columns = this.setColumns((t) => ({
|
|
455
|
-
* id: t.identity().primaryKey(),
|
|
456
|
-
* title_en: t.text(),
|
|
457
|
-
* title_uk: t.text().nullable(),
|
|
458
|
-
* title_be: t.text().nullable(),
|
|
459
|
-
* }));
|
|
460
|
-
*
|
|
461
|
-
* computed = this.setComputed({
|
|
462
|
-
* title: (q) =>
|
|
463
|
-
* q
|
|
464
|
-
* // .sql can take a function that accepts `sql` argument and must return SQL
|
|
465
|
-
* .sql((sql) => {
|
|
466
|
-
* // get locale dynamically based on current storage value
|
|
467
|
-
* const locale = asyncLanguageStorage.getStore() || defaultLocale;
|
|
468
|
-
*
|
|
469
|
-
* // use COALESCE in case when localized title is NULL, use title_en
|
|
470
|
-
* return sql`COALESCE(
|
|
471
|
-
* ${q.column(`title_${locale}`)},
|
|
472
|
-
* ${q.column(`title_${defaultLocale}`)}
|
|
473
|
-
* )`;
|
|
474
|
-
* })
|
|
475
|
-
* .type((t) => t.text()),
|
|
476
|
-
* });
|
|
477
|
-
* }
|
|
478
|
-
* ```
|
|
479
|
-
*
|
|
480
|
-
* @param computed - object where keys are column names and values are functions returning raw SQL
|
|
481
|
-
*/
|
|
482
|
-
setComputed<Table extends string, Shape extends ColumnsShapeBase, Computed extends ComputedColumnsBase<Db<Table, Shape, EmptyObject, ColumnTypes>>>(computed: Computed): Computed;
|
|
483
|
-
belongsTo<Self extends Table, Related extends TableClass, Scope extends Query, Options extends BelongsToOptions<Self, Related, Scope>>(this: Self, fn: () => Related, options: Options): {
|
|
484
|
-
type: 'belongsTo';
|
|
485
|
-
fn: () => Related;
|
|
486
|
-
options: Options;
|
|
487
|
-
};
|
|
488
|
-
hasOne<Self extends Table, Related extends TableClass, Scope extends Query, Through extends string, Source extends string, Options extends HasOneOptions<Self, Related, Scope, Through, Source>>(this: Self, fn: () => Related, options: Options): {
|
|
489
|
-
type: 'hasOne';
|
|
490
|
-
fn: () => Related;
|
|
491
|
-
options: Options;
|
|
492
|
-
};
|
|
493
|
-
hasMany<Self extends Table, Related extends TableClass, Scope extends Query, Through extends string, Source extends string, Options extends HasManyOptions<Self, Related, Scope, Through, Source>>(this: Self, fn: () => Related, options: Options): {
|
|
494
|
-
type: 'hasMany';
|
|
495
|
-
fn: () => Related;
|
|
496
|
-
options: Options;
|
|
497
|
-
};
|
|
498
|
-
hasAndBelongsToMany<Self extends Table, Related extends TableClass, Scope extends Query, Options extends HasAndBelongsToManyOptions<Self, Related, Scope>>(this: Self, fn: () => Related, options: Options): {
|
|
499
|
-
type: 'hasAndBelongsToMany';
|
|
500
|
-
fn: () => Related;
|
|
501
|
-
options: Options;
|
|
502
|
-
};
|
|
503
|
-
beforeQuery: BeforeHookMethod;
|
|
504
|
-
afterQuery: AfterHookMethod;
|
|
505
|
-
beforeCreate: BeforeHookMethod;
|
|
506
|
-
afterCreate: AfterSelectableHookMethod;
|
|
507
|
-
afterCreateCommit: AfterSelectableHookMethod;
|
|
508
|
-
beforeUpdate: BeforeHookMethod;
|
|
509
|
-
afterUpdate: AfterSelectableHookMethod;
|
|
510
|
-
afterUpdateCommit: AfterSelectableHookMethod;
|
|
511
|
-
beforeSave: BeforeHookMethod;
|
|
512
|
-
afterSave: AfterSelectableHookMethod;
|
|
513
|
-
afterSaveCommit: AfterSelectableHookMethod;
|
|
514
|
-
beforeDelete: BeforeHookMethod;
|
|
515
|
-
afterDelete: AfterSelectableHookMethod;
|
|
516
|
-
afterDeleteCommit: AfterSelectableHookMethod;
|
|
517
|
-
};
|
|
521
|
+
new (): BaseTableInstance<ColumnTypes>;
|
|
522
|
+
instance(): BaseTableInstance<ColumnTypes>;
|
|
518
523
|
}
|
|
519
524
|
declare function createBaseTable<SchemaProvider extends SchemaProviderBase, ColumnTypes = DefaultColumnTypes>({ columnTypes: columnTypesArg, snakeCase, filePath: filePathArg, nowSQL, exportAs, language, schemaProvider: schemaProviderArg, }?: {
|
|
520
525
|
columnTypes?: ColumnTypes | ((t: DefaultColumnTypes) => ColumnTypes);
|
|
@@ -545,4 +550,4 @@ type Repo<T extends Query, Methods extends MethodsBase<T>, Mapped = MapMethods<T
|
|
|
545
550
|
}>(q: Q) => Q & Mapped) & T & Mapped;
|
|
546
551
|
declare const createRepo: <T extends Query, Methods extends MethodsBase<T>>(table: T, methods: Methods) => Repo<T, Methods, MapMethods<T, Methods>>;
|
|
547
552
|
|
|
548
|
-
export { BaseTableClass, DbTable, Insertable, MapMethods, MapQueryMethods, MethodsBase, OrchidORM, QueryMethods, Queryable, Repo, ScopeFn, Selectable, Table, TableClass, TableClasses, TableToDb, Updateable, createBaseTable, createRepo, orchidORM };
|
|
553
|
+
export { BaseTableClass, BaseTableInstance, DbTable, Insertable, MapMethods, MapQueryMethods, MethodsBase, OrchidORM, QueryMethods, Queryable, Repo, ScopeFn, Selectable, Table, TableClass, TableClasses, TableToDb, Updateable, createBaseTable, createRepo, orchidORM };
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,10 @@ function createBaseTable({
|
|
|
44
44
|
`Failed to determine file path of a base table. Please set the \`filePath\` option of \`createBaseTable\` manually.`
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
|
+
static instance() {
|
|
48
|
+
var _a2;
|
|
49
|
+
return (_a2 = this._instance) != null ? _a2 : this._instance = new this();
|
|
50
|
+
}
|
|
47
51
|
clone() {
|
|
48
52
|
return this;
|
|
49
53
|
}
|
|
@@ -73,7 +77,7 @@ function createBaseTable({
|
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
|
-
return
|
|
80
|
+
return shape;
|
|
77
81
|
}
|
|
78
82
|
setComputed(computed) {
|
|
79
83
|
return computed;
|
|
@@ -1696,7 +1700,7 @@ const orchidORM = (_a, tables) => {
|
|
|
1696
1700
|
if (key[0] === "$") {
|
|
1697
1701
|
throw new Error(`Table class name must not start with $`);
|
|
1698
1702
|
}
|
|
1699
|
-
const table =
|
|
1703
|
+
const table = tables[key].instance();
|
|
1700
1704
|
tableInstances[key] = table;
|
|
1701
1705
|
const options2 = __spreadProps(__spreadValues$1({}, commonOptions), {
|
|
1702
1706
|
schema: table.schema,
|