@tstdl/base 0.93.8 → 0.93.10
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/audit/module.d.ts +3 -3
- package/audit/module.js +3 -3
- package/document-management/api/document-management.api.d.ts +6 -6
- package/document-management/service-models/document.service-model.d.ts +3 -3
- package/orm/decorators.d.ts +35 -3
- package/orm/decorators.js +6 -0
- package/orm/query.d.ts +49 -30
- package/orm/query.js +2 -6
- package/orm/repository.types.d.ts +58 -0
- package/orm/server/database.js +2 -1
- package/orm/server/drizzle/schema-converter.js +31 -2
- package/orm/server/query-converter.d.ts +5 -7
- package/orm/server/query-converter.js +69 -15
- package/orm/server/repository.d.ts +13 -5
- package/orm/server/repository.js +106 -4
- package/orm/sqls.d.ts +143 -8
- package/orm/sqls.js +143 -8
- package/package.json +3 -3
- package/schema/schemas/object.js +1 -1
- package/test/drizzle/0000_sudden_sphinx.sql +9 -0
- package/test/drizzle/meta/0000_snapshot.json +79 -0
- package/test/drizzle/meta/_journal.json +13 -0
- package/test/drizzle.config.d.ts +2 -0
- package/test/drizzle.config.js +11 -0
- package/test/index.d.ts +3 -0
- package/test/index.js +3 -0
- package/test/module.d.ts +6 -0
- package/test/module.js +17 -0
- package/test/schemas.d.ts +3 -0
- package/test/schemas.js +4 -0
- package/test/test.model.d.ts +8 -0
- package/test/test.model.js +345 -0
- package/test1.d.ts +1 -0
- package/test1.js +56 -0
- package/test3.d.ts +1 -0
- package/test3.js +47 -0
- package/test4.d.ts +23 -0
- package/test4.js +168 -0
- package/test5.d.ts +1 -0
- package/test5.js +22 -0
- package/test6.d.ts +1 -0
- package/test6.js +53 -0
package/audit/module.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DatabaseConfig } from '../orm/server/index.js';
|
|
2
2
|
/**
|
|
3
|
-
* Configuration for {@link
|
|
3
|
+
* Configuration for {@link configureAudit}.
|
|
4
4
|
*/
|
|
5
5
|
export declare class AuditModuleConfig {
|
|
6
6
|
/**
|
|
@@ -13,10 +13,10 @@ export declare class AuditModuleConfig {
|
|
|
13
13
|
* Configures audit server services.
|
|
14
14
|
* @param config Configuration.
|
|
15
15
|
*/
|
|
16
|
-
export declare function
|
|
16
|
+
export declare function configureAudit(config: AuditModuleConfig): void;
|
|
17
17
|
/**
|
|
18
18
|
* Migrates the audit database schema to the latest version.
|
|
19
|
-
* It uses the database connection provided with {@link
|
|
19
|
+
* It uses the database connection provided with {@link configureAudit},
|
|
20
20
|
* or falls back to the globally configured database if no specific configuration is provided.
|
|
21
21
|
*/
|
|
22
22
|
export declare function migrateAuditSchema(): Promise<void>;
|
package/audit/module.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { inject, Injector } from '../injector/index.js';
|
|
2
2
|
import { Database, migrate } from '../orm/server/index.js';
|
|
3
3
|
/**
|
|
4
|
-
* Configuration for {@link
|
|
4
|
+
* Configuration for {@link configureAudit}.
|
|
5
5
|
*/
|
|
6
6
|
export class AuditModuleConfig {
|
|
7
7
|
/**
|
|
@@ -14,12 +14,12 @@ export class AuditModuleConfig {
|
|
|
14
14
|
* Configures audit server services.
|
|
15
15
|
* @param config Configuration.
|
|
16
16
|
*/
|
|
17
|
-
export function
|
|
17
|
+
export function configureAudit(config) {
|
|
18
18
|
Injector.register(AuditModuleConfig, { useValue: config });
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Migrates the audit database schema to the latest version.
|
|
22
|
-
* It uses the database connection provided with {@link
|
|
22
|
+
* It uses the database connection provided with {@link configureAudit},
|
|
23
23
|
* or falls back to the globally configured database if no specific configuration is provided.
|
|
24
24
|
*/
|
|
25
25
|
export async function migrateAuditSchema() {
|
|
@@ -127,8 +127,8 @@ export declare const documentManagementApiDefinition: {
|
|
|
127
127
|
method: "POST";
|
|
128
128
|
parameters: import("../../schema/index.js").ObjectSchema<{
|
|
129
129
|
date?: import("../../orm/types.js").NumericDate | null | undefined;
|
|
130
|
-
typeId?: import("../../orm/types.js").Uuid | null | undefined;
|
|
131
130
|
title?: string | null | undefined;
|
|
131
|
+
typeId?: import("../../orm/types.js").Uuid | null | undefined;
|
|
132
132
|
subtitle?: string | null | undefined;
|
|
133
133
|
summary?: string | null | undefined;
|
|
134
134
|
comment?: string | null | undefined;
|
|
@@ -326,8 +326,8 @@ export declare const documentManagementApiDefinition: {
|
|
|
326
326
|
parameters: import("../../schema/index.js").ObjectSchema<{
|
|
327
327
|
id: import("../../orm/types.js").IsPrimaryKey<import("../../orm/types.js").HasDefault<import("../../orm/types.js").Uuid>>;
|
|
328
328
|
date?: import("../../orm/types.js").NumericDate | null | undefined;
|
|
329
|
-
typeId?: import("../../orm/types.js").Uuid | null | undefined;
|
|
330
329
|
title?: string | null | undefined;
|
|
330
|
+
typeId?: import("../../orm/types.js").Uuid | null | undefined;
|
|
331
331
|
subtitle?: string | null | undefined;
|
|
332
332
|
comment?: string | null | undefined;
|
|
333
333
|
properties?: {
|
|
@@ -337,11 +337,11 @@ export declare const documentManagementApiDefinition: {
|
|
|
337
337
|
attributes: import("../../orm/types.js").HasDefault<import("../../orm/types.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
|
|
338
338
|
}> | undefined;
|
|
339
339
|
}[] | undefined;
|
|
340
|
+
tags?: string[] | undefined;
|
|
340
341
|
collections?: {
|
|
341
342
|
assign?: string[] | undefined;
|
|
342
343
|
archive?: string[] | undefined;
|
|
343
344
|
} | undefined;
|
|
344
|
-
tags?: string[] | undefined;
|
|
345
345
|
metadata?: Partial<{
|
|
346
346
|
attributes: import("../../orm/types.js").HasDefault<import("../../orm/types.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
|
|
347
347
|
}> | undefined;
|
|
@@ -527,8 +527,8 @@ declare const _DocumentManagementApi: import("../../api/client/index.js").ApiCli
|
|
|
527
527
|
method: "POST";
|
|
528
528
|
parameters: import("../../schema/index.js").ObjectSchema<{
|
|
529
529
|
date?: import("../../orm/types.js").NumericDate | null | undefined;
|
|
530
|
-
typeId?: import("../../orm/types.js").Uuid | null | undefined;
|
|
531
530
|
title?: string | null | undefined;
|
|
531
|
+
typeId?: import("../../orm/types.js").Uuid | null | undefined;
|
|
532
532
|
subtitle?: string | null | undefined;
|
|
533
533
|
summary?: string | null | undefined;
|
|
534
534
|
comment?: string | null | undefined;
|
|
@@ -726,8 +726,8 @@ declare const _DocumentManagementApi: import("../../api/client/index.js").ApiCli
|
|
|
726
726
|
parameters: import("../../schema/index.js").ObjectSchema<{
|
|
727
727
|
id: import("../../orm/types.js").IsPrimaryKey<import("../../orm/types.js").HasDefault<import("../../orm/types.js").Uuid>>;
|
|
728
728
|
date?: import("../../orm/types.js").NumericDate | null | undefined;
|
|
729
|
-
typeId?: import("../../orm/types.js").Uuid | null | undefined;
|
|
730
729
|
title?: string | null | undefined;
|
|
730
|
+
typeId?: import("../../orm/types.js").Uuid | null | undefined;
|
|
731
731
|
subtitle?: string | null | undefined;
|
|
732
732
|
comment?: string | null | undefined;
|
|
733
733
|
properties?: {
|
|
@@ -737,11 +737,11 @@ declare const _DocumentManagementApi: import("../../api/client/index.js").ApiCli
|
|
|
737
737
|
attributes: import("../../orm/types.js").HasDefault<import("../../orm/types.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
|
|
738
738
|
}> | undefined;
|
|
739
739
|
}[] | undefined;
|
|
740
|
+
tags?: string[] | undefined;
|
|
740
741
|
collections?: {
|
|
741
742
|
assign?: string[] | undefined;
|
|
742
743
|
archive?: string[] | undefined;
|
|
743
744
|
} | undefined;
|
|
744
|
-
tags?: string[] | undefined;
|
|
745
745
|
metadata?: Partial<{
|
|
746
746
|
attributes: import("../../orm/types.js").HasDefault<import("../../orm/types.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
|
|
747
747
|
}> | undefined;
|
|
@@ -20,8 +20,8 @@ export declare const updateDocumentCollectionsParametersSchema: import("../../sc
|
|
|
20
20
|
}>;
|
|
21
21
|
export declare const createDocumentParametersSchema: import("../../schema/index.js").ObjectSchema<{
|
|
22
22
|
date?: import("../../orm/index.js").NumericDate | null | undefined;
|
|
23
|
-
typeId?: import("../../orm/index.js").Uuid | null | undefined;
|
|
24
23
|
title?: string | null | undefined;
|
|
24
|
+
typeId?: import("../../orm/index.js").Uuid | null | undefined;
|
|
25
25
|
subtitle?: string | null | undefined;
|
|
26
26
|
summary?: string | null | undefined;
|
|
27
27
|
comment?: string | null | undefined;
|
|
@@ -53,8 +53,8 @@ export declare const createDocumentParametersSchema: import("../../schema/index.
|
|
|
53
53
|
export declare const updateDocumentParametersSchema: import("../../schema/index.js").ObjectSchema<{
|
|
54
54
|
id: import("../../orm/index.js").IsPrimaryKey<import("../../orm/index.js").HasDefault<import("../../orm/index.js").Uuid>>;
|
|
55
55
|
date?: import("../../orm/index.js").NumericDate | null | undefined;
|
|
56
|
-
typeId?: import("../../orm/index.js").Uuid | null | undefined;
|
|
57
56
|
title?: string | null | undefined;
|
|
57
|
+
typeId?: import("../../orm/index.js").Uuid | null | undefined;
|
|
58
58
|
subtitle?: string | null | undefined;
|
|
59
59
|
comment?: string | null | undefined;
|
|
60
60
|
properties?: {
|
|
@@ -64,11 +64,11 @@ export declare const updateDocumentParametersSchema: import("../../schema/index.
|
|
|
64
64
|
attributes: import("../../orm/index.js").HasDefault<import("../../orm/index.js").Json<import("../../orm/index.js").EntityMetadataAttributes>>;
|
|
65
65
|
}> | undefined;
|
|
66
66
|
}[] | undefined;
|
|
67
|
+
tags?: string[] | undefined;
|
|
67
68
|
collections?: {
|
|
68
69
|
assign?: string[] | undefined;
|
|
69
70
|
archive?: string[] | undefined;
|
|
70
71
|
} | undefined;
|
|
71
|
-
tags?: string[] | undefined;
|
|
72
72
|
metadata?: Partial<{
|
|
73
73
|
attributes: import("../../orm/index.js").HasDefault<import("../../orm/index.js").Json<import("../../orm/index.js").EntityMetadataAttributes>>;
|
|
74
74
|
}> | undefined;
|
package/orm/decorators.d.ts
CHANGED
|
@@ -5,14 +5,15 @@
|
|
|
5
5
|
import type { SQL } from 'drizzle-orm';
|
|
6
6
|
import type { LiteralUnion } from 'type-fest';
|
|
7
7
|
import { type SpecificCreateDecoratorOptions } from '../reflection/index.js';
|
|
8
|
-
import type { AbstractConstructor, TypedOmit } from '../types/index.js';
|
|
8
|
+
import type { AbstractConstructor, Record, TypedOmit } from '../types/index.js';
|
|
9
9
|
import type { AnyEntity, Entity, EntityType, EntityWithoutMetadata } from './entity.js';
|
|
10
10
|
import type { Query } from './query.js';
|
|
11
11
|
import type { TargetColumnPaths } from './repository.types.js';
|
|
12
12
|
import type { PgTableFromType } from './server/types.js';
|
|
13
13
|
type IndexMethod = LiteralUnion<'hash' | 'btree' | 'gist' | 'spgist' | 'gin' | 'brin' | 'hnsw' | 'ivfflat', string>;
|
|
14
14
|
type NamingStrategy = 'abbreviated-table';
|
|
15
|
-
type
|
|
15
|
+
type Column<T> = Extract<keyof T, string>;
|
|
16
|
+
type Columns<T> = [Column<T>, ...Column<T>[]];
|
|
16
17
|
/**
|
|
17
18
|
* Builder function type for creating SQL check constraints.
|
|
18
19
|
* @param table The Drizzle table object.
|
|
@@ -77,7 +78,7 @@ export type UniqueReflectionData = {
|
|
|
77
78
|
* @template T The entity type.
|
|
78
79
|
*/
|
|
79
80
|
export type IndexReflectionData<T extends Entity | EntityWithoutMetadata = any> = {
|
|
80
|
-
columns?: (string | [string, 'asc' | 'desc'])[];
|
|
81
|
+
columns?: (string | [string, 'asc' | 'desc'] | SQL)[];
|
|
81
82
|
order?: 'asc' | 'desc';
|
|
82
83
|
options?: {
|
|
83
84
|
name?: string;
|
|
@@ -86,6 +87,22 @@ export type IndexReflectionData<T extends Entity | EntityWithoutMetadata = any>
|
|
|
86
87
|
unique?: boolean;
|
|
87
88
|
where?: WhereBuilder<T>;
|
|
88
89
|
nulls?: 'first' | 'last';
|
|
90
|
+
/**
|
|
91
|
+
* For full-text search indexes (e.g., GIN), specifies the text search configuration language (e.g., 'english').
|
|
92
|
+
* Can also be a SQL object for dynamic configuration.
|
|
93
|
+
*/
|
|
94
|
+
language?: string | SQL;
|
|
95
|
+
/**
|
|
96
|
+
* For multi-column full-text search indexes, specifies how to create the tsvector.
|
|
97
|
+
* - 'concat': (Default) Concatenate columns into a single tsvector.
|
|
98
|
+
* - 'separate': Create a separate tsvector for each column, useful for indexing columns with different languages or weights.
|
|
99
|
+
*/
|
|
100
|
+
vectors?: 'concat' | 'separate';
|
|
101
|
+
/**
|
|
102
|
+
* For multi-column full-text search indexes, specifies weights for columns.
|
|
103
|
+
* Keys are column names, values are 'A', 'B', 'C', or 'D'.
|
|
104
|
+
*/
|
|
105
|
+
weights?: Partial<Record<TargetColumnPaths<any>, 'A' | 'B' | 'C' | 'D'>>;
|
|
89
106
|
};
|
|
90
107
|
};
|
|
91
108
|
type CheckReflectionData = {
|
|
@@ -104,6 +121,10 @@ export type ForeignKeyReflectionData = {
|
|
|
104
121
|
naming?: NamingStrategy;
|
|
105
122
|
};
|
|
106
123
|
};
|
|
124
|
+
export type GinIndexOptions<T extends Entity | EntityWithoutMetadata = any> = TypedOmit<NonNullable<IndexReflectionData<T>['options']>, 'using' | 'weights'> & {
|
|
125
|
+
weights?: Partial<Record<TargetColumnPaths<any>, 'A' | 'B' | 'C' | 'D'>>;
|
|
126
|
+
language?: string | SQL;
|
|
127
|
+
};
|
|
107
128
|
/**
|
|
108
129
|
* Factory function to create a class decorator for ORM table configuration.
|
|
109
130
|
* Merges provided data with existing ORM reflection data on the class metadata.
|
|
@@ -204,6 +225,17 @@ export declare function Index<T extends Entity | EntityWithoutMetadata = any>(op
|
|
|
204
225
|
* @param options Additional index options.
|
|
205
226
|
*/
|
|
206
227
|
export declare function Index<T extends Entity | EntityWithoutMetadata = any>(columns: Columns<T>, options?: IndexReflectionData<T>['options']): ClassDecorator;
|
|
228
|
+
/**
|
|
229
|
+
* Defines a GIN index on a single column, often for full-text search.
|
|
230
|
+
* @param options GIN index options. For full-text search, `language` is required.
|
|
231
|
+
*/
|
|
232
|
+
export declare function GinIndex<T extends Entity | EntityWithoutMetadata = any>(options: GinIndexOptions<T>): PropertyDecorator;
|
|
233
|
+
/**
|
|
234
|
+
* Defines a composite GIN index on multiple columns, often for full-text search.
|
|
235
|
+
* @param columnsOrSql The columns to include in the index.
|
|
236
|
+
* @param options GIN index options. For full-text search, providing a `language` is highly recommended.
|
|
237
|
+
*/
|
|
238
|
+
export declare function GinIndex<T extends Entity | EntityWithoutMetadata = any>(columnsOrSql: (Column<T> | SQL)[], options?: GinIndexOptions<T>): ClassDecorator;
|
|
207
239
|
/**
|
|
208
240
|
* Automatically expire records after a certain time to live (TTL) based on the createTimestamp metadata. Requires extension of {@link Entity} instead of {@link EntityWithoutMetadata}.
|
|
209
241
|
* @param ttl Time To Live in milliseconds.
|
package/orm/decorators.js
CHANGED
|
@@ -137,6 +137,12 @@ export function Index(columnsOrOptions, options) {
|
|
|
137
137
|
}
|
|
138
138
|
return createColumnDecorator({ index: { options: columnsOrOptions } });
|
|
139
139
|
}
|
|
140
|
+
export function GinIndex(columnsOrSqlOrOptions, options) {
|
|
141
|
+
if (isArray(columnsOrSqlOrOptions)) {
|
|
142
|
+
return createTableDecorator({ index: [{ columns: columnsOrSqlOrOptions, options: { ...options, using: 'gin' } }] });
|
|
143
|
+
}
|
|
144
|
+
return createColumnDecorator({ index: { options: { ...columnsOrSqlOrOptions, using: 'gin' } } });
|
|
145
|
+
}
|
|
140
146
|
/**
|
|
141
147
|
* Automatically expire records after a certain time to live (TTL) based on the createTimestamp metadata. Requires extension of {@link Entity} instead of {@link EntityWithoutMetadata}.
|
|
142
148
|
* @param ttl Time To Live in milliseconds.
|
package/orm/query.d.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
* @module
|
|
3
|
-
* Defines types for constructing database queries using a MongoDB-like syntax.
|
|
4
|
-
* Supports logical operators, comparison operators, and specialized queries like text search and geospatial queries.
|
|
5
|
-
*/
|
|
6
|
-
import type { SQLWrapper } from 'drizzle-orm';
|
|
7
|
-
import type { Flatten, Record } from '../types/index.js';
|
|
1
|
+
import type { SQL, SQLWrapper } from 'drizzle-orm';
|
|
8
2
|
import type { Geometry } from '../types/geo-json.js';
|
|
3
|
+
import type { Flatten, Record } from '../types/index.js';
|
|
9
4
|
import type { UntaggedDeep } from '../types/tagged.js';
|
|
10
5
|
/** Represents a logical query combining multiple sub-queries (e.g., $and, $or, $nor). */
|
|
11
6
|
export type LogicalQuery<T = any> = LogicalAndQuery<T> | LogicalOrQuery<T> | LogicalNorQuery<T>;
|
|
@@ -20,13 +15,14 @@ export type ComparisonQueryBody<T = any> = {
|
|
|
20
15
|
/** Represents either a full comparison query object or a direct value for equality comparison. */
|
|
21
16
|
export type ComparisonQueryOrValue<T = any> = ComparisonQuery<T> | ComparisonValue<T>;
|
|
22
17
|
/** Represents a comparison query using various operators like $eq, $ne, $gt, $in, etc. */
|
|
23
|
-
export type ComparisonQuery<T = any> = Partial<ComparisonAndQuery<T> & ComparisonOrQuery<T> & ComparisonNotQuery<T> & ComparisonEqualsQuery<T> & ComparisonNotEqualsQuery<T> & ComparisonExistsQuery & ComparisonItemQuery<T> & ComparisonInQuery<T> & ComparisonNotInQuery<T> & ComparisonAllQuery<T> & ComparisonGreaterThanQuery<T> & ComparisonGreaterThanOrEqualsQuery<T> & ComparisonLessThanQuery<T> & ComparisonLessThanOrEqualsQuery<T> & ComparisonRegexQuery &
|
|
18
|
+
export type ComparisonQuery<T = any> = Partial<ComparisonAndQuery<T> & ComparisonOrQuery<T> & ComparisonNotQuery<T> & ComparisonEqualsQuery<T> & ComparisonNotEqualsQuery<T> & ComparisonExistsQuery & ComparisonItemQuery<T> & ComparisonInQuery<T> & ComparisonNotInQuery<T> & ComparisonAllQuery<T> & ComparisonGreaterThanQuery<T> & ComparisonGreaterThanOrEqualsQuery<T> & ComparisonLessThanQuery<T> & ComparisonLessThanOrEqualsQuery<T> & ComparisonRegexQuery & ComparisonFtsQuery & ComparisonGeoShapeQuery & ComparisonGeoDistanceQuery>;
|
|
19
|
+
export type FtsParser = 'raw' | 'plain' | 'phrase' | 'websearch';
|
|
24
20
|
/** Union of keys representing comparison query operators. */
|
|
25
21
|
export type ComparisonQueryTypes = keyof ComparisonQuery;
|
|
26
22
|
/** Array containing all valid comparison query operator keys. */
|
|
27
23
|
export declare const allComparisonQueryTypes: ComparisonQueryTypes[];
|
|
28
|
-
/** Represents specialized query types beyond simple comparisons
|
|
29
|
-
export type SpecialQuery<T = any> = Partial<
|
|
24
|
+
/** Represents specialized query types beyond simple comparisons. */
|
|
25
|
+
export type SpecialQuery<T = any> = Partial<FullTextSearchQuery<T>>;
|
|
30
26
|
/** Union of keys representing special query operators. */
|
|
31
27
|
export type SpecialQueryTypes = keyof SpecialQuery;
|
|
32
28
|
/** Array containing all valid special query operator keys. */
|
|
@@ -42,11 +38,7 @@ export type QueryObject<T> = LogicalQuery<T> | (ComparisonQueryBody<T> & Special
|
|
|
42
38
|
/** Union of all possible query operator keys (logical, comparison, special). */
|
|
43
39
|
export type QueryTypes = LogicalQueryTypes | ComparisonQueryTypes | SpecialQueryTypes;
|
|
44
40
|
/** Array containing all valid query operator keys. */
|
|
45
|
-
export declare const allQueryTypes: ("$and" | "$or" | "$nor" | "$not" | "$eq" | "$neq" | "$exists" | "$item" | "$in" | "$nin" | "$all" | "$gt" | "$gte" | "$lt" | "$lte" | "$regex" | "$
|
|
46
|
-
/** Logical operators used within certain query types like $text. */
|
|
47
|
-
export type Operator = 'and' | 'or';
|
|
48
|
-
/** Array containing all valid logical operators ('and', 'or'). */
|
|
49
|
-
export declare const allOperators: Operator[];
|
|
41
|
+
export declare const allQueryTypes: ("$and" | "$or" | "$nor" | "$not" | "$eq" | "$neq" | "$exists" | "$item" | "$in" | "$nin" | "$all" | "$gt" | "$gte" | "$lt" | "$lte" | "$regex" | "$fts" | "$geoShape" | "$geoDistance")[];
|
|
50
42
|
/** Represents an AND logical query. All sub-queries must be true. */
|
|
51
43
|
export type LogicalAndQuery<T = any> = {
|
|
52
44
|
$and: readonly Query<T>[];
|
|
@@ -126,11 +118,24 @@ export type ComparisonRegexQuery = {
|
|
|
126
118
|
flags: string;
|
|
127
119
|
};
|
|
128
120
|
};
|
|
129
|
-
/** Represents a full-text search query
|
|
130
|
-
export type
|
|
131
|
-
$
|
|
132
|
-
|
|
133
|
-
|
|
121
|
+
/** Represents a full-text search query. */
|
|
122
|
+
export type ComparisonFtsQuery = {
|
|
123
|
+
$fts: string | {
|
|
124
|
+
query: string;
|
|
125
|
+
/**
|
|
126
|
+
* The search method to use.
|
|
127
|
+
* - 'vector': (Default) Standard full-text search using tsvector and tsquery.
|
|
128
|
+
* - 'similarity': Trigram-based similarity search using the pg_trgm extension.
|
|
129
|
+
*/
|
|
130
|
+
method?: 'vector' | 'similarity';
|
|
131
|
+
/**
|
|
132
|
+
* The parser to use for the query. Only applicable for 'vector' method.
|
|
133
|
+
*/
|
|
134
|
+
parser?: FtsParser;
|
|
135
|
+
/**
|
|
136
|
+
* The text search configuration (e.g., 'english', 'simple'). Can also be a SQL object for dynamic configuration. Only applicable for 'vector' method.
|
|
137
|
+
*/
|
|
138
|
+
language?: string | SQL;
|
|
134
139
|
};
|
|
135
140
|
};
|
|
136
141
|
/** Defines the possible spatial relationships for geospatial shape queries. */
|
|
@@ -157,16 +162,30 @@ export type ComparisonGeoDistanceQuery = {
|
|
|
157
162
|
minDistance?: number;
|
|
158
163
|
};
|
|
159
164
|
};
|
|
160
|
-
/**
|
|
161
|
-
export type
|
|
162
|
-
|
|
163
|
-
export declare const allTextSpanQueryModes: TextSpanQueryMode[];
|
|
164
|
-
/** Represents a text span query ($textSpan), searching for text across multiple fields. */
|
|
165
|
-
export type TextSpanQuery<T = any> = {
|
|
166
|
-
$textSpan: {
|
|
165
|
+
/** Represents a full-text search query across one or more fields. Used by the `search` repository method. */
|
|
166
|
+
export type FullTextSearchQuery<T = any> = {
|
|
167
|
+
$fts: {
|
|
167
168
|
fields: readonly (Extract<keyof T, string>)[];
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
query: string | SQL<string>;
|
|
170
|
+
/**
|
|
171
|
+
* The search method to use.
|
|
172
|
+
* - 'vector': (Default) Standard full-text search using tsvector and tsquery.
|
|
173
|
+
* - 'similarity': Trigram-based similarity search using the pg_trgm extension.
|
|
174
|
+
*/
|
|
175
|
+
method?: 'vector' | 'similarity';
|
|
176
|
+
/**
|
|
177
|
+
* The parser to use for the query. Only applicable for 'vector' method.
|
|
178
|
+
*/
|
|
179
|
+
parser?: FtsParser;
|
|
180
|
+
/**
|
|
181
|
+
* The text search configuration (e.g., 'english', 'simple'). Can also be a SQL object for dynamic configuration. Only applicable for 'vector' method.
|
|
182
|
+
*/
|
|
183
|
+
language?: string | SQL<string>;
|
|
184
|
+
/**
|
|
185
|
+
* Assigns weights to fields for ranking.
|
|
186
|
+
* Keys are field names from `fields`, values are 'A', 'B', 'C', or 'D'.
|
|
187
|
+
* Fields without a specified weight will use the default. Only applicable for 'vector' method.
|
|
188
|
+
*/
|
|
189
|
+
weights?: Partial<Record<Extract<keyof T, string>, 'A' | 'B' | 'C' | 'D'>>;
|
|
171
190
|
};
|
|
172
191
|
};
|
package/orm/query.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
/** Array containing all valid logical query operator keys. */
|
|
2
2
|
export const allLogicalQueryTypes = ['$and', '$or', '$nor'];
|
|
3
3
|
/** Array containing all valid comparison query operator keys. */
|
|
4
|
-
export const allComparisonQueryTypes = ['$all', '$not', '$eq', '$exists', '$gt', '$gte', '$in', '$item', '$lt', '$lte', '$neq', '$nin', '$regex', '$
|
|
4
|
+
export const allComparisonQueryTypes = ['$all', '$not', '$eq', '$exists', '$gt', '$gte', '$in', '$item', '$lt', '$lte', '$neq', '$nin', '$regex', '$fts', '$geoDistance', '$geoShape'];
|
|
5
5
|
/** Array containing all valid special query operator keys. */
|
|
6
|
-
export const allSpecialQueryTypes = ['$
|
|
6
|
+
export const allSpecialQueryTypes = ['$fts'];
|
|
7
7
|
/** Array containing all valid query operator keys. */
|
|
8
8
|
export const allQueryTypes = [...allLogicalQueryTypes, ...allComparisonQueryTypes, ...allSpecialQueryTypes];
|
|
9
|
-
/** Array containing all valid logical operators ('and', 'or'). */
|
|
10
|
-
export const allOperators = ['and', 'or'];
|
|
11
|
-
/** Array containing all valid text span query modes. */
|
|
12
|
-
export const allTextSpanQueryModes = ['best', 'most', 'cross'];
|
|
@@ -8,6 +8,8 @@ import type { UntaggedDeep } from '../types/tagged.js';
|
|
|
8
8
|
import type { SQL, SQLWrapper } from 'drizzle-orm';
|
|
9
9
|
import type { PartialDeep } from 'type-fest';
|
|
10
10
|
import type { Entity, EntityMetadata, EntityWithoutMetadata } from './entity.js';
|
|
11
|
+
import type { Query } from './query.js';
|
|
12
|
+
import type { TsHeadlineOptions } from './sqls.js';
|
|
11
13
|
type WithSql<T> = {
|
|
12
14
|
[P in keyof T]: T[P] extends Record ? WithSql<T[P]> : (T[P] | SQL);
|
|
13
15
|
};
|
|
@@ -53,6 +55,62 @@ export type LoadManyOptions<T extends EntityWithoutMetadata> = LoadOptions<T> &
|
|
|
53
55
|
limit?: number;
|
|
54
56
|
distinct?: boolean | TargetColumn<T>[];
|
|
55
57
|
};
|
|
58
|
+
/**
|
|
59
|
+
* Options for ranking search results.
|
|
60
|
+
*/
|
|
61
|
+
export type RankOptions = {
|
|
62
|
+
/**
|
|
63
|
+
* Array of four numbers to weight D, C, B, and A labels respectively.
|
|
64
|
+
* Defaults to PostgreSQL's default {0.1, 0.2, 0.4, 1.0}.
|
|
65
|
+
*/
|
|
66
|
+
weights?: [number, number, number, number];
|
|
67
|
+
/**
|
|
68
|
+
* Specifies how a document's length should impact its rank.
|
|
69
|
+
* It's a bitmask, e.g., 0 (default) ignores length, 2 divides by document length.
|
|
70
|
+
* See PostgreSQL documentation for `ts_rank_cd` for more details.
|
|
71
|
+
*/
|
|
72
|
+
normalization?: number;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Options for highlighting search results.
|
|
76
|
+
*/
|
|
77
|
+
export type HighlightOptions<T extends EntityWithoutMetadata> = {
|
|
78
|
+
/**
|
|
79
|
+
* The source to generate the highlight from. Can be one or more property paths or a raw SQL expression.
|
|
80
|
+
*/
|
|
81
|
+
source: TargetColumnPaths<T> | SQL<string>;
|
|
82
|
+
} & TsHeadlineOptions;
|
|
83
|
+
/**
|
|
84
|
+
* Options for the `search` method.
|
|
85
|
+
* @template T - The entity type.
|
|
86
|
+
*/
|
|
87
|
+
export type SearchOptions<T extends EntityWithoutMetadata> = Omit<LoadManyOptions<T>, 'order'> & {
|
|
88
|
+
/**
|
|
89
|
+
* An additional filter to apply to the search query.
|
|
90
|
+
*/
|
|
91
|
+
filter?: Query<T>;
|
|
92
|
+
/**
|
|
93
|
+
* Enable and configure ranking of search results.
|
|
94
|
+
* - If `true` (default), results are ordered by score descending using default ranking options.
|
|
95
|
+
* - If an `RankOptions` object is provided, ranking is customized.
|
|
96
|
+
* - If an `SQL` object is provided, it's used as a custom scoring expression.
|
|
97
|
+
* @default true
|
|
98
|
+
*/
|
|
99
|
+
rank?: boolean | RankOptions | SQL;
|
|
100
|
+
/**
|
|
101
|
+
* Enable and configure highlighting of search results.
|
|
102
|
+
*/
|
|
103
|
+
highlight?: TargetColumnPaths<T> | SQL<string> | HighlightOptions<T>;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Represents a single result from a full-text search operation.
|
|
107
|
+
* @template T - The entity type.
|
|
108
|
+
*/
|
|
109
|
+
export type SearchResult<T extends EntityWithoutMetadata> = {
|
|
110
|
+
entity: T;
|
|
111
|
+
score: number;
|
|
112
|
+
highlight?: string;
|
|
113
|
+
};
|
|
56
114
|
/**
|
|
57
115
|
* Options for update operations (currently inherits from LoadOptions, primarily for ordering).
|
|
58
116
|
* @template T - The entity type.
|
package/orm/server/database.js
CHANGED
|
@@ -14,6 +14,7 @@ import { migrate } from 'drizzle-orm/node-postgres/migrator';
|
|
|
14
14
|
import { Pool } from 'pg';
|
|
15
15
|
import { inject, Injector, ReplaceClass } from '../../injector/index.js';
|
|
16
16
|
import { isUndefined } from '../../utils/type-guards.js';
|
|
17
|
+
import { millisecondsPerMinute } from '../../utils/units.js';
|
|
17
18
|
import { DatabaseConfig } from './module.js';
|
|
18
19
|
/**
|
|
19
20
|
* Represents the application's database connection.
|
|
@@ -33,7 +34,7 @@ Injector.registerSingleton(Database, {
|
|
|
33
34
|
throw new Error('Missing postgres connection. Provide it either via injection argument or a provider for DatabaseConfig.');
|
|
34
35
|
}
|
|
35
36
|
const pool = new Pool({
|
|
36
|
-
idle_in_transaction_session_timeout:
|
|
37
|
+
idle_in_transaction_session_timeout: 10 * millisecondsPerMinute,
|
|
37
38
|
...connection,
|
|
38
39
|
});
|
|
39
40
|
context.addDisposeHandler(async () => await pool.end());
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { sql, SQL } from 'drizzle-orm';
|
|
1
2
|
import { toCamelCase, toSnakeCase } from 'drizzle-orm/casing';
|
|
2
3
|
import { boolean, check, doublePrecision, foreignKey, index, integer, jsonb, pgSchema, primaryKey, text, unique, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
|
|
3
4
|
import { MultiKeyMap } from '../../../data-structures/multi-key-map.js';
|
|
4
5
|
import { tryGetEnumName } from '../../../enumeration/enumeration.js';
|
|
5
6
|
import { NotSupportedError } from '../../../errors/not-supported.error.js';
|
|
6
7
|
import { JsonPath } from '../../../json-path/json-path.js';
|
|
8
|
+
import { setweight, toTsVector } from '../../../orm/sqls.js';
|
|
7
9
|
import { reflectionRegistry } from '../../../reflection/registry.js';
|
|
8
10
|
import { ArraySchema, BooleanSchema, DefaultSchema, EnumerationSchema, getObjectSchema, NullableSchema, NumberSchema, ObjectSchema, OptionalSchema, StringSchema, Uint8ArraySchema } from '../../../schema/index.js';
|
|
9
11
|
import { compareByValueSelectionToOrder, orderRest } from '../../../utils/comparison.js';
|
|
@@ -53,9 +55,12 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
53
55
|
function buildIndex(table, data, columnName) {
|
|
54
56
|
const columns = (data.columns ?? [columnName]).map((columnValue) => {
|
|
55
57
|
assertDefined(columnValue, 'Missing column name for index.');
|
|
58
|
+
if (columnValue instanceof SQL) {
|
|
59
|
+
return columnValue;
|
|
60
|
+
}
|
|
56
61
|
const [columnName, columnOrder] = isString(columnValue) ? [columnValue] : columnValue;
|
|
57
|
-
const order = columnOrder ?? data.order ?? 'asc';
|
|
58
62
|
let column = getColumn(table, columnName);
|
|
63
|
+
const order = columnOrder ?? data.order ?? 'asc';
|
|
59
64
|
column = column[order]();
|
|
60
65
|
if (data.options?.nulls == 'first') {
|
|
61
66
|
column = column.nullsFirst();
|
|
@@ -66,13 +71,37 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
66
71
|
return column;
|
|
67
72
|
});
|
|
68
73
|
const indexFn = (data.options?.unique == true) ? uniqueIndex : index;
|
|
69
|
-
|
|
74
|
+
const containsSql = columns.some((column) => column instanceof SQL);
|
|
75
|
+
const indexName = data.options?.name ?? (containsSql
|
|
76
|
+
? assertDefinedPass(data.options?.name, 'Index with SQL expressions must have a name.')
|
|
77
|
+
: getIndexName(tableName, columns, { naming: data.options?.naming }));
|
|
78
|
+
const indexColumns = (data.options?.using == 'gin'
|
|
79
|
+
? buildGinIndexColumns(columns, data.options)
|
|
80
|
+
: columns);
|
|
81
|
+
let builder = indexFn(indexName).using(data.options?.using ?? 'btree', ...indexColumns);
|
|
70
82
|
if (isDefined(data.options?.where)) {
|
|
71
83
|
const query = convertQuery(data.options.where(table), table, columnDefinitionsMap);
|
|
72
84
|
builder = builder.where(query.inlineParams());
|
|
73
85
|
}
|
|
74
86
|
return builder;
|
|
75
87
|
}
|
|
88
|
+
function buildGinIndexColumns(columns, options) {
|
|
89
|
+
const vectors = columns.map((column) => {
|
|
90
|
+
if (column instanceof SQL) {
|
|
91
|
+
return column;
|
|
92
|
+
}
|
|
93
|
+
const tsVector = toTsVector(options.language ?? 'simple', column);
|
|
94
|
+
const weight = options.weights?.[column.name];
|
|
95
|
+
if (isDefined(weight)) {
|
|
96
|
+
return setweight(tsVector, weight);
|
|
97
|
+
}
|
|
98
|
+
return tsVector;
|
|
99
|
+
});
|
|
100
|
+
if (options.vectors == 'separate') {
|
|
101
|
+
return vectors;
|
|
102
|
+
}
|
|
103
|
+
return [sql `(${sql.join(vectors, sql ` || `)})`];
|
|
104
|
+
}
|
|
76
105
|
function buildPrimaryKey(table) {
|
|
77
106
|
const columns = primaryKeyColumnDefinitions.map((columnDefinition) => getColumn(table, columnDefinition.name));
|
|
78
107
|
return primaryKey({
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module
|
|
3
|
-
* Converts a generic query object structure into a Drizzle ORM SQL condition.
|
|
4
|
-
* Supports logical operators ($and, $or, $nor) and various comparison operators
|
|
5
|
-
* ($eq, $neq, $in, $nin, $lt, $lte, $gt, $gte, $regex).
|
|
6
|
-
*/
|
|
7
1
|
import { SQL } from 'drizzle-orm';
|
|
8
|
-
import type {
|
|
2
|
+
import type { Record } from '../../types/index.js';
|
|
3
|
+
import type { FtsParser, Query } from '../query.js';
|
|
9
4
|
import type { ColumnDefinition, PgTableFromType } from './types.js';
|
|
10
5
|
/**
|
|
11
6
|
* Converts a query object into a Drizzle SQL condition.
|
|
@@ -20,3 +15,6 @@ import type { ColumnDefinition, PgTableFromType } from './types.js';
|
|
|
20
15
|
* @throws {Error} If an unsupported query type is encountered.
|
|
21
16
|
*/
|
|
22
17
|
export declare function convertQuery(query: Query, table: PgTableFromType, columnDefinitionsMap: Map<string, ColumnDefinition>): SQL;
|
|
18
|
+
export declare function getTsQuery(text: string | SQL, language: string | SQL, parser: FtsParser): SQL;
|
|
19
|
+
export declare function getTsVector(fields: readonly string[], language: string | SQL, table: PgTableFromType, columnDefinitionsMap: Map<string, ColumnDefinition>, weights?: Partial<Record<string, 'A' | 'B' | 'C' | 'D'>>): SQL;
|
|
20
|
+
export declare function getSimilaritySearchExpression(fields: readonly string[], table: PgTableFromType, columnDefinitionsMap: Map<string, ColumnDefinition>): SQL;
|