orchid-orm 1.17.14 → 1.17.16
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 +234 -4
- package/dist/index.js +102 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +103 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as pqb from 'pqb';
|
|
2
|
-
import { Query, QueryWithTable, SetQueryTableAlias, WhereArg, UpdateData, CreateData, Db, IsolationLevel, TransactionOptions, Adapter, FromArgs, FromResult, AdapterOptions, QueryLogOptions, NoPrimaryKeyOption, RelationConfigBase, RelationQuery, SetQueryReturnsOne, SetQueryReturnsOneOptional, SetQueryReturnsAll, RelationQueryBase, ColumnsShape, DefaultColumnTypes, QueryData, QueryBase, QueryBeforeHook, QueryAfterHook, AfterHook, WhereResult, MergeQuery, SetQueryReturns, QueryReturnType } from 'pqb';
|
|
2
|
+
import { Query, QueryWithTable, SetQueryTableAlias, WhereArg, UpdateData, CreateData, Db, IsolationLevel, TransactionOptions, Adapter, FromArgs, FromResult, AdapterOptions, QueryLogOptions, NoPrimaryKeyOption, RelationConfigBase, RelationQuery, SetQueryReturnsOne, SetQueryReturnsOneOptional, SetQueryReturnsAll, RelationQueryBase, ComputedColumnsBase, QueryDefaultReturnData, ColumnsShape, DefaultColumnTypes, QueryData, QueryBase, QueryBeforeHook, QueryAfterHook, AfterHook, WhereResult, MergeQuery, SetQueryReturns, QueryReturnType } from 'pqb';
|
|
3
3
|
export { OrchidOrmError, OrchidOrmInternalError, columnTypes, raw, testTransaction } from 'pqb';
|
|
4
4
|
import * as orchid_core from 'orchid-core';
|
|
5
5
|
import { EmptyObject, MaybeArray, StringKey, ColumnTypesBase, ColumnShapeQueryType, ColumnShapeOutput, ColumnShapeInput, ColumnsShapeBase } from 'orchid-core';
|
|
@@ -349,7 +349,9 @@ type MapRelations<T extends Table> = T extends {
|
|
|
349
349
|
|
|
350
350
|
type TableClass<T extends Table = Table> = new () => T;
|
|
351
351
|
type TableClasses = Record<string, TableClass>;
|
|
352
|
-
type TableToDb<T extends Table, RelationQueries extends Record<string, RelationQueryBase>> = Db<T['table'], T['
|
|
352
|
+
type TableToDb<T extends Table, RelationQueries extends Record<string, RelationQueryBase>> = Db<T['table'], T['computed'] extends ComputedColumnsBase<never> ? T['columns'] & {
|
|
353
|
+
[K in keyof T['computed']]: ReturnType<T['computed'][K]>['_type'];
|
|
354
|
+
} : T['columns'], RelationQueries, T['types'], QueryDefaultReturnData<T['columns']>> & {
|
|
353
355
|
definedAs: string;
|
|
354
356
|
db: OrchidORM;
|
|
355
357
|
getFilePath(): string;
|
|
@@ -361,10 +363,14 @@ type Table = {
|
|
|
361
363
|
table: string;
|
|
362
364
|
columns: ColumnsShape;
|
|
363
365
|
schema?: string;
|
|
364
|
-
|
|
366
|
+
types: ColumnTypesBase;
|
|
365
367
|
noPrimaryKey?: boolean;
|
|
366
368
|
filePath: string;
|
|
367
369
|
language?: string;
|
|
370
|
+
/**
|
|
371
|
+
* collect computed columns returned by {@link BaseTable.setColumns}
|
|
372
|
+
*/
|
|
373
|
+
computed?: ComputedColumnsBase<never>;
|
|
368
374
|
};
|
|
369
375
|
type Queryable<T extends Table> = Partial<ColumnShapeQueryType<T['columns']>>;
|
|
370
376
|
type Selectable<T extends Table> = ColumnShapeOutput<T['columns']>;
|
|
@@ -388,7 +394,7 @@ declare const createBaseTable: <ColumnTypes extends Record<string, orchid_core.A
|
|
|
388
394
|
schema?: string | undefined;
|
|
389
395
|
noPrimaryKey?: boolean | undefined;
|
|
390
396
|
snakeCase: boolean | undefined;
|
|
391
|
-
|
|
397
|
+
types: Record<string, orchid_core.AnyColumnTypeCreator> extends ColumnTypes ? {
|
|
392
398
|
timestamps<T extends orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>>(this: {
|
|
393
399
|
name(name: string): {
|
|
394
400
|
timestamp(): T;
|
|
@@ -662,6 +668,230 @@ declare const createBaseTable: <ColumnTypes extends Record<string, orchid_core.A
|
|
|
662
668
|
}) | undefined): {};
|
|
663
669
|
check(check: orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>): {};
|
|
664
670
|
} : ColumnTypes) => T_15): T_15;
|
|
671
|
+
/**
|
|
672
|
+
* You can add a generated column in the migration (see [generated](/guide/migration-column-methods.html#generated-column)),
|
|
673
|
+
* such column will persist in the database, it can be indexed.
|
|
674
|
+
*
|
|
675
|
+
* Or you can add a computed column on the ORM level, without adding it to the database, in such a way:
|
|
676
|
+
*
|
|
677
|
+
* ```ts
|
|
678
|
+
* import { BaseTable } from './baseTable';
|
|
679
|
+
*
|
|
680
|
+
* export class UserTable extends BaseTable {
|
|
681
|
+
* readonly table = 'user';
|
|
682
|
+
* columns = this.setColumns((t) => ({
|
|
683
|
+
* id: t.identity().primaryKey(),
|
|
684
|
+
* firstName: t.string(),
|
|
685
|
+
* lastName: t.string(),
|
|
686
|
+
* }));
|
|
687
|
+
*
|
|
688
|
+
* computed = this.setComputed({
|
|
689
|
+
* fullName: (q) =>
|
|
690
|
+
* q.sql`${q.column('firstName')} || ' ' || ${q.column('lastName')}`.type(
|
|
691
|
+
* (t) => t.string(),
|
|
692
|
+
* ),
|
|
693
|
+
* });
|
|
694
|
+
* }
|
|
695
|
+
* ```
|
|
696
|
+
*
|
|
697
|
+
* `setComputed` takes an object where keys are computed column names, and values are functions returning raw SQL.
|
|
698
|
+
*
|
|
699
|
+
* 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.
|
|
700
|
+
*
|
|
701
|
+
* Computed columns are not selected by default, only on demand:
|
|
702
|
+
*
|
|
703
|
+
* ```ts
|
|
704
|
+
* const a = await db.user.take();
|
|
705
|
+
* a.fullName; // not selected
|
|
706
|
+
*
|
|
707
|
+
* const b = await db.user.select('*', 'fullName');
|
|
708
|
+
* b.fullName; // selected
|
|
709
|
+
*
|
|
710
|
+
* // Table post belongs to user as an author.
|
|
711
|
+
* // it's possible to select joined computed column:
|
|
712
|
+
* const posts = await db.post
|
|
713
|
+
* .join('author')
|
|
714
|
+
* .select('post.title', 'author.fullName');
|
|
715
|
+
* ```
|
|
716
|
+
*
|
|
717
|
+
* SQL query can be generated dynamically based on the current request context.
|
|
718
|
+
*
|
|
719
|
+
* Imagine we are using [AsyncLocalStorage](https://nodejs.org/api/async_context.html#asynchronous-context-tracking)
|
|
720
|
+
* to keep track of current user's language.
|
|
721
|
+
*
|
|
722
|
+
* And we have articles translated to different languages, each article has `title_en`, `title_uk`, `title_be` and so on.
|
|
723
|
+
*
|
|
724
|
+
* We can define a computed `title` by passing a function into `sql` method:
|
|
725
|
+
*
|
|
726
|
+
* ```ts
|
|
727
|
+
* type Locale = 'en' | 'uk' | 'be';
|
|
728
|
+
* const asyncLanguageStorage = new AsyncLocalStorage<Locale>();
|
|
729
|
+
* const defaultLocale: Locale = 'en';
|
|
730
|
+
*
|
|
731
|
+
* export class ArticleTable extends BaseTable {
|
|
732
|
+
* readonly table = 'article';
|
|
733
|
+
* columns = this.setColumns((t) => ({
|
|
734
|
+
* id: t.identity().primaryKey(),
|
|
735
|
+
* title_en: t.text(),
|
|
736
|
+
* title_uk: t.text().nullable(),
|
|
737
|
+
* title_be: t.text().nullable(),
|
|
738
|
+
* }));
|
|
739
|
+
*
|
|
740
|
+
* computed = this.setComputed({
|
|
741
|
+
* title: (q) =>
|
|
742
|
+
* q
|
|
743
|
+
* // .sql can take a function that accepts `sql` argument and must return SQL
|
|
744
|
+
* .sql((sql) => {
|
|
745
|
+
* // get locale dynamically based on current storage value
|
|
746
|
+
* const locale = asyncLanguageStorage.getStore() || defaultLocale;
|
|
747
|
+
*
|
|
748
|
+
* // use COALESCE in case when localized title is NULL, use title_en
|
|
749
|
+
* return sql`COALESCE(
|
|
750
|
+
* ${q.column(`title_${locale}`)},
|
|
751
|
+
* ${q.column(`title_${defaultLocale}`)}
|
|
752
|
+
* )`;
|
|
753
|
+
* })
|
|
754
|
+
* .type((t) => t.text()),
|
|
755
|
+
* });
|
|
756
|
+
* }
|
|
757
|
+
* ```
|
|
758
|
+
*
|
|
759
|
+
* @param computed - object where keys are column names and values are functions returning raw SQL
|
|
760
|
+
*/
|
|
761
|
+
setComputed<Table_3 extends string, Shape_1 extends ColumnsShape, Computed extends ComputedColumnsBase<Db<Table_3, Shape_1, {}, Record<string, orchid_core.AnyColumnTypeCreator> extends ColumnTypes ? {
|
|
762
|
+
timestamps<T extends orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>>(this: {
|
|
763
|
+
name(name: string): {
|
|
764
|
+
timestamp(): T;
|
|
765
|
+
};
|
|
766
|
+
timestamp(): T;
|
|
767
|
+
timestampsSnakeCase(): {
|
|
768
|
+
createdAt: orchid_core.ColumnWithDefault<T, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
769
|
+
updatedAt: orchid_core.ColumnWithDefault<T, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
770
|
+
};
|
|
771
|
+
}): {
|
|
772
|
+
createdAt: orchid_core.ColumnWithDefault<T, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
773
|
+
updatedAt: orchid_core.ColumnWithDefault<T, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
774
|
+
};
|
|
775
|
+
timestampsSnakeCase<T_1 extends orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>>(this: {
|
|
776
|
+
name(name: string): {
|
|
777
|
+
timestamp(): T_1;
|
|
778
|
+
};
|
|
779
|
+
timestamp(): T_1;
|
|
780
|
+
}): {
|
|
781
|
+
createdAt: orchid_core.ColumnWithDefault<T_1, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
782
|
+
updatedAt: orchid_core.ColumnWithDefault<T_1, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
783
|
+
};
|
|
784
|
+
timestampsNoTZ<T_2 extends orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>>(this: {
|
|
785
|
+
name(name: string): {
|
|
786
|
+
timestampNoTZ(): T_2;
|
|
787
|
+
};
|
|
788
|
+
timestampNoTZ(): T_2;
|
|
789
|
+
timestampsNoTZSnakeCase(): {
|
|
790
|
+
createdAt: orchid_core.ColumnWithDefault<T_2, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
791
|
+
updatedAt: orchid_core.ColumnWithDefault<T_2, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
792
|
+
};
|
|
793
|
+
}): {
|
|
794
|
+
createdAt: orchid_core.ColumnWithDefault<T_2, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
795
|
+
updatedAt: orchid_core.ColumnWithDefault<T_2, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
796
|
+
};
|
|
797
|
+
timestampsNoTZSnakeCase<T_3 extends orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>>(this: {
|
|
798
|
+
name(name: string): {
|
|
799
|
+
timestampNoTZ(): T_3;
|
|
800
|
+
};
|
|
801
|
+
timestampNoTZ(): T_3;
|
|
802
|
+
}): {
|
|
803
|
+
createdAt: orchid_core.ColumnWithDefault<T_3, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
804
|
+
updatedAt: orchid_core.ColumnWithDefault<T_3, orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>>;
|
|
805
|
+
};
|
|
806
|
+
name: typeof orchid_core.name;
|
|
807
|
+
sql: {
|
|
808
|
+
(sql: TemplateStringsArray, ...values: unknown[]): orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>;
|
|
809
|
+
(sql: string): orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>;
|
|
810
|
+
(values: Record<string, unknown>, sql: string): orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>;
|
|
811
|
+
(values: Record<string, unknown>): (strings: TemplateStringsArray, ...values: unknown[]) => orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>;
|
|
812
|
+
};
|
|
813
|
+
smallint(): pqb.SmallIntColumn;
|
|
814
|
+
integer(): pqb.IntegerColumn;
|
|
815
|
+
bigint(): pqb.BigIntColumn;
|
|
816
|
+
numeric<Precision extends number | undefined = undefined, Scale extends number | undefined = undefined>(precision?: Precision | undefined, scale?: Scale | undefined): pqb.DecimalColumn<Precision, Scale>;
|
|
817
|
+
decimal<Precision_1 extends number | undefined = undefined, Scale_1 extends number | undefined = undefined>(precision?: Precision_1 | undefined, scale?: Scale_1 | undefined): pqb.DecimalColumn<Precision_1, Scale_1>;
|
|
818
|
+
real(): pqb.RealColumn;
|
|
819
|
+
doublePrecision(): pqb.DoublePrecisionColumn;
|
|
820
|
+
identity(options?: pqb.TableData.Identity | undefined): orchid_core.ColumnWithDefault<pqb.IntegerColumn, orchid_core.Expression<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>>>;
|
|
821
|
+
smallSerial(): pqb.SmallSerialColumn;
|
|
822
|
+
serial(): pqb.SerialColumn;
|
|
823
|
+
bigSerial(): pqb.BigSerialColumn;
|
|
824
|
+
money(): pqb.MoneyColumn;
|
|
825
|
+
varchar<Limit extends number | undefined = undefined>(limit?: Limit | undefined): pqb.VarCharColumn<Limit>;
|
|
826
|
+
char<Limit_1 extends number | undefined = undefined>(limit?: Limit_1 | undefined): pqb.CharColumn<Limit_1>;
|
|
827
|
+
text(min: number, max: number): pqb.TextColumn;
|
|
828
|
+
string<Limit_2 extends number = 255>(limit?: Limit_2): pqb.VarCharColumn<Limit_2>;
|
|
829
|
+
citext(min: number, max: number): pqb.CitextColumn;
|
|
830
|
+
bytea(): pqb.ByteaColumn;
|
|
831
|
+
date(): pqb.DateColumn;
|
|
832
|
+
timestampNoTZ<Precision_2 extends number>(precision?: Precision_2 | undefined): pqb.TimestampColumn<Precision_2>;
|
|
833
|
+
timestamp<Precision_3 extends number | undefined = undefined>(precision?: Precision_3 | undefined): pqb.TimestampTZColumn<number>;
|
|
834
|
+
time<Precision_4 extends number | undefined = undefined>(precision?: Precision_4 | undefined): pqb.TimeColumn<Precision_4>;
|
|
835
|
+
interval<Fields extends string | undefined = undefined, Precision_5 extends number | undefined = undefined>(fields?: Fields | undefined, precision?: Precision_5 | undefined): pqb.IntervalColumn<Fields, Precision_5>;
|
|
836
|
+
boolean(): pqb.BooleanColumn;
|
|
837
|
+
enum<U extends string, T_4 extends [U, ...U[]]>(dataType: string, type: T_4): pqb.EnumColumn<U, T_4>;
|
|
838
|
+
point(): pqb.PointColumn;
|
|
839
|
+
line(): pqb.LineColumn;
|
|
840
|
+
lseg(): pqb.LsegColumn;
|
|
841
|
+
box(): pqb.BoxColumn;
|
|
842
|
+
path(): pqb.PathColumn;
|
|
843
|
+
polygon(): pqb.PolygonColumn;
|
|
844
|
+
circle(): pqb.CircleColumn;
|
|
845
|
+
cidr(): pqb.CidrColumn;
|
|
846
|
+
inet(): pqb.InetColumn;
|
|
847
|
+
macaddr(): pqb.MacAddrColumn;
|
|
848
|
+
macaddr8(): pqb.MacAddr8Column;
|
|
849
|
+
bit<Length extends number>(length: Length): pqb.BitColumn<Length>;
|
|
850
|
+
bitVarying<Length_1 extends number | undefined = undefined>(length?: Length_1 | undefined): pqb.BitVaryingColumn<Length_1>;
|
|
851
|
+
tsvector(): pqb.TsVectorColumn;
|
|
852
|
+
tsquery(): pqb.TsQueryColumn;
|
|
853
|
+
uuid(): pqb.UUIDColumn;
|
|
854
|
+
xml(): pqb.XMLColumn;
|
|
855
|
+
json<Type extends orchid_core.JSONType<unknown, {}> = orchid_core.JSONUnknown>(schemaOrFn?: Type | ((j: {
|
|
856
|
+
unknown: () => orchid_core.JSONUnknown;
|
|
857
|
+
boolean: () => orchid_core.JSONBoolean;
|
|
858
|
+
null: () => orchid_core.JSONNull;
|
|
859
|
+
number: <T_5 extends number = number>() => orchid_core.JSONNumber<T_5>;
|
|
860
|
+
string: <T_6 extends string = string>() => orchid_core.JSONString<T_6>;
|
|
861
|
+
array: <T_7 extends orchid_core.JSONType<unknown, {}>>(item: T_7) => orchid_core.JSONArray<T_7, "many">;
|
|
862
|
+
object: <Shape extends orchid_core.JSONObjectShape>(shape: Shape) => orchid_core.JSONObject<Shape, "strip", orchid_core.JSONType<unknown, {}>>;
|
|
863
|
+
literal: <T_8 extends orchid_core.JSONPrimitive>(value: T_8) => orchid_core.JSONLiteral<T_8>;
|
|
864
|
+
discriminatedUnion: <Discriminator extends string, Types extends orchid_core.JSONDiscriminatedUnionArg<Discriminator>>(discriminator: Discriminator, types: Types) => orchid_core.JSONDiscriminatedUnion<Discriminator, Types>;
|
|
865
|
+
enum: <U_1 extends string, T_9 extends [U_1, ...U_1[]]>(options: T_9) => orchid_core.JSONEnum<string, T_9>;
|
|
866
|
+
intersection: <Left extends orchid_core.JSONType<unknown, {}>, Right extends orchid_core.JSONType<unknown, {}>>(left: Left, right: Right) => orchid_core.JSONIntersection<Left, Right>;
|
|
867
|
+
lazy: <T_10 extends orchid_core.JSONType<unknown, {}>>(fn: () => T_10) => orchid_core.JSONLazy<T_10>;
|
|
868
|
+
nativeEnum: <T_11 extends orchid_core.EnumLike>(type: T_11) => orchid_core.JSONNativeEnum<T_11>;
|
|
869
|
+
record: <Key extends orchid_core.JSONString<string> | orchid_core.JSONNumber<number>, Value extends orchid_core.JSONType<unknown, {}>>(...args: [value: Value] | [key: Key, value: Value]) => orchid_core.JSONRecord<Key, Value>;
|
|
870
|
+
tuple: <T_12 extends orchid_core.JSONTupleItems, Rest extends orchid_core.JSONType<unknown, {}> | undefined = undefined>(items: T_12, rest?: Rest | undefined) => orchid_core.JSONTuple<T_12, Rest>;
|
|
871
|
+
union: <T_13 extends orchid_core.JSONUnionArgs>(...types: T_13) => orchid_core.JSONUnion<T_13>;
|
|
872
|
+
}) => Type) | undefined): pqb.JSONColumn<Type>;
|
|
873
|
+
jsonText(): pqb.JSONTextColumn;
|
|
874
|
+
array<Item extends pqb.ColumnType<unknown, pqb.BaseOperators, unknown, unknown, unknown>>(item: Item): pqb.ArrayColumn<Item>;
|
|
875
|
+
type(dataType: string): pqb.CustomTypeColumn;
|
|
876
|
+
domain(dataType: string): pqb.DomainColumn;
|
|
877
|
+
primaryKey(columns: string[], options?: {
|
|
878
|
+
name?: string | undefined;
|
|
879
|
+
} | undefined): {};
|
|
880
|
+
index(columns: orchid_core.MaybeArray<string | pqb.IndexColumnOptions>, options?: pqb.IndexOptions): {};
|
|
881
|
+
unique(columns: orchid_core.MaybeArray<string | pqb.IndexColumnOptions>, options?: pqb.IndexOptions | undefined): {};
|
|
882
|
+
searchIndex(columns: orchid_core.MaybeArray<string | pqb.IndexColumnOptions>, options?: pqb.IndexOptions | undefined): {};
|
|
883
|
+
constraint<Table_1 extends string | (() => orchid_core.ForeignKeyTable), Columns extends Table_1 extends () => orchid_core.ForeignKeyTable ? [orchid_core.ColumnNameOfTable<ReturnType<Table_1>>, ...orchid_core.ColumnNameOfTable<ReturnType<Table_1>>[]] : [string, ...string[]]>({ name, references, check, dropMode, }: {
|
|
884
|
+
name?: string | undefined;
|
|
885
|
+
references?: [columns: string[], fnOrTable: Table_1, foreignColumns: Columns, options?: pqb.ForeignKeyOptions | undefined] | undefined;
|
|
886
|
+
check?: orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}> | undefined;
|
|
887
|
+
dropMode?: pqb.DropMode | undefined;
|
|
888
|
+
}): {};
|
|
889
|
+
foreignKey<Table_2 extends string | (() => orchid_core.ForeignKeyTable), Columns_1 extends Table_2 extends () => orchid_core.ForeignKeyTable ? [orchid_core.ColumnNameOfTable<ReturnType<Table_2>>, ...orchid_core.ColumnNameOfTable<ReturnType<Table_2>>[]] : [string, ...string[]]>(columns: string[], fnOrTable: Table_2, foreignColumns: Columns_1, options?: (pqb.ForeignKeyOptions & {
|
|
890
|
+
name?: string | undefined;
|
|
891
|
+
dropMode?: pqb.DropMode | undefined;
|
|
892
|
+
}) | undefined): {};
|
|
893
|
+
check(check: orchid_core.RawSQLBase<orchid_core.ColumnTypeBase<unknown, orchid_core.BaseOperators, unknown, unknown, unknown, orchid_core.ColumnDataBase>, {}>): {};
|
|
894
|
+
} : ColumnTypes, QueryDefaultReturnData<Shape_1>>>>(computed: Computed): Computed;
|
|
665
895
|
belongsTo<Self extends any, Related extends TableClass<Table>, Scope extends Query, Options extends BelongsToOptions<Self, Related, Scope>>(this: Self, fn: () => Related, options: Options): {
|
|
666
896
|
type: "belongsTo";
|
|
667
897
|
fn: () => Related;
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ const createBaseTable = ({
|
|
|
25
25
|
const base = (_a = class {
|
|
26
26
|
constructor() {
|
|
27
27
|
this.snakeCase = snakeCase;
|
|
28
|
-
this.
|
|
28
|
+
this.types = columnTypes;
|
|
29
29
|
this.q = {};
|
|
30
30
|
this.language = language;
|
|
31
31
|
}
|
|
@@ -73,6 +73,99 @@ const createBaseTable = ({
|
|
|
73
73
|
}
|
|
74
74
|
return this.constructor.prototype.columns = shape;
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* You can add a generated column in the migration (see [generated](/guide/migration-column-methods.html#generated-column)),
|
|
78
|
+
* such column will persist in the database, it can be indexed.
|
|
79
|
+
*
|
|
80
|
+
* Or you can add a computed column on the ORM level, without adding it to the database, in such a way:
|
|
81
|
+
*
|
|
82
|
+
* ```ts
|
|
83
|
+
* import { BaseTable } from './baseTable';
|
|
84
|
+
*
|
|
85
|
+
* export class UserTable extends BaseTable {
|
|
86
|
+
* readonly table = 'user';
|
|
87
|
+
* columns = this.setColumns((t) => ({
|
|
88
|
+
* id: t.identity().primaryKey(),
|
|
89
|
+
* firstName: t.string(),
|
|
90
|
+
* lastName: t.string(),
|
|
91
|
+
* }));
|
|
92
|
+
*
|
|
93
|
+
* computed = this.setComputed({
|
|
94
|
+
* fullName: (q) =>
|
|
95
|
+
* q.sql`${q.column('firstName')} || ' ' || ${q.column('lastName')}`.type(
|
|
96
|
+
* (t) => t.string(),
|
|
97
|
+
* ),
|
|
98
|
+
* });
|
|
99
|
+
* }
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* `setComputed` takes an object where keys are computed column names, and values are functions returning raw SQL.
|
|
103
|
+
*
|
|
104
|
+
* 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.
|
|
105
|
+
*
|
|
106
|
+
* Computed columns are not selected by default, only on demand:
|
|
107
|
+
*
|
|
108
|
+
* ```ts
|
|
109
|
+
* const a = await db.user.take();
|
|
110
|
+
* a.fullName; // not selected
|
|
111
|
+
*
|
|
112
|
+
* const b = await db.user.select('*', 'fullName');
|
|
113
|
+
* b.fullName; // selected
|
|
114
|
+
*
|
|
115
|
+
* // Table post belongs to user as an author.
|
|
116
|
+
* // it's possible to select joined computed column:
|
|
117
|
+
* const posts = await db.post
|
|
118
|
+
* .join('author')
|
|
119
|
+
* .select('post.title', 'author.fullName');
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* SQL query can be generated dynamically based on the current request context.
|
|
123
|
+
*
|
|
124
|
+
* Imagine we are using [AsyncLocalStorage](https://nodejs.org/api/async_context.html#asynchronous-context-tracking)
|
|
125
|
+
* to keep track of current user's language.
|
|
126
|
+
*
|
|
127
|
+
* And we have articles translated to different languages, each article has `title_en`, `title_uk`, `title_be` and so on.
|
|
128
|
+
*
|
|
129
|
+
* We can define a computed `title` by passing a function into `sql` method:
|
|
130
|
+
*
|
|
131
|
+
* ```ts
|
|
132
|
+
* type Locale = 'en' | 'uk' | 'be';
|
|
133
|
+
* const asyncLanguageStorage = new AsyncLocalStorage<Locale>();
|
|
134
|
+
* const defaultLocale: Locale = 'en';
|
|
135
|
+
*
|
|
136
|
+
* export class ArticleTable extends BaseTable {
|
|
137
|
+
* readonly table = 'article';
|
|
138
|
+
* columns = this.setColumns((t) => ({
|
|
139
|
+
* id: t.identity().primaryKey(),
|
|
140
|
+
* title_en: t.text(),
|
|
141
|
+
* title_uk: t.text().nullable(),
|
|
142
|
+
* title_be: t.text().nullable(),
|
|
143
|
+
* }));
|
|
144
|
+
*
|
|
145
|
+
* computed = this.setComputed({
|
|
146
|
+
* title: (q) =>
|
|
147
|
+
* q
|
|
148
|
+
* // .sql can take a function that accepts `sql` argument and must return SQL
|
|
149
|
+
* .sql((sql) => {
|
|
150
|
+
* // get locale dynamically based on current storage value
|
|
151
|
+
* const locale = asyncLanguageStorage.getStore() || defaultLocale;
|
|
152
|
+
*
|
|
153
|
+
* // use COALESCE in case when localized title is NULL, use title_en
|
|
154
|
+
* return sql`COALESCE(
|
|
155
|
+
* ${q.column(`title_${locale}`)},
|
|
156
|
+
* ${q.column(`title_${defaultLocale}`)}
|
|
157
|
+
* )`;
|
|
158
|
+
* })
|
|
159
|
+
* .type((t) => t.text()),
|
|
160
|
+
* });
|
|
161
|
+
* }
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* @param computed - object where keys are column names and values are functions returning raw SQL
|
|
165
|
+
*/
|
|
166
|
+
setComputed(computed) {
|
|
167
|
+
return computed;
|
|
168
|
+
}
|
|
76
169
|
belongsTo(fn, options) {
|
|
77
170
|
return {
|
|
78
171
|
type: "belongsTo",
|
|
@@ -103,7 +196,7 @@ const createBaseTable = ({
|
|
|
103
196
|
}
|
|
104
197
|
}, _a.nowSQL = nowSQL, _a.exportAs = exportAs, _a.schema = schemaProvider, _a);
|
|
105
198
|
orchidCore.applyMixins(base, [pqb.QueryHooks]);
|
|
106
|
-
base.prototype.
|
|
199
|
+
base.prototype.types = columnTypes;
|
|
107
200
|
return base;
|
|
108
201
|
};
|
|
109
202
|
|
|
@@ -1705,7 +1798,7 @@ const orchidORM = (_a, tables) => {
|
|
|
1705
1798
|
qb,
|
|
1706
1799
|
table.table,
|
|
1707
1800
|
table.columns,
|
|
1708
|
-
table.
|
|
1801
|
+
table.types,
|
|
1709
1802
|
transactionStorage,
|
|
1710
1803
|
options2
|
|
1711
1804
|
);
|
|
@@ -1713,6 +1806,12 @@ const orchidORM = (_a, tables) => {
|
|
|
1713
1806
|
dbTable.db = result;
|
|
1714
1807
|
dbTable.filePath = table.filePath;
|
|
1715
1808
|
dbTable.name = table.constructor.name;
|
|
1809
|
+
if (table.computed) {
|
|
1810
|
+
pqb.addComputedColumns(
|
|
1811
|
+
dbTable,
|
|
1812
|
+
table.computed
|
|
1813
|
+
);
|
|
1814
|
+
}
|
|
1716
1815
|
result[key] = dbTable;
|
|
1717
1816
|
}
|
|
1718
1817
|
applyRelations(qb, tableInstances, result);
|