@tstdl/base 0.93.14 → 0.93.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/document-management/api/document-management.api.d.ts +4 -0
- package/document-management/service-models/document.service-model.d.ts +2 -0
- package/injector/injector.js +9 -8
- package/mail/drizzle/0001_flimsy_bloodscream.sql +5 -0
- package/mail/drizzle/meta/0001_snapshot.json +69 -0
- package/mail/drizzle/meta/_journal.json +7 -0
- package/mail/mail.service.js +4 -4
- package/mail/models/mail-log.model.d.ts +2 -2
- package/mail/models/mail-log.model.js +2 -2
- package/message-bus/local/local-message-bus-provider.d.ts +2 -1
- package/message-bus/local/local-message-bus-provider.js +5 -4
- package/message-bus/local/local-message-bus.js +1 -3
- package/message-bus/message-bus-base.js +2 -2
- package/orm/data-types/index.d.ts +1 -0
- package/orm/data-types/index.js +1 -0
- package/orm/data-types/tsvector.d.ts +16 -0
- package/orm/data-types/tsvector.js +13 -0
- package/orm/decorators.d.ts +44 -32
- package/orm/decorators.js +3 -6
- package/orm/entity.d.ts +20 -13
- package/orm/entity.js +18 -18
- package/orm/repository.types.d.ts +13 -13
- package/orm/server/drizzle/schema-converter.js +115 -63
- package/orm/server/types.d.ts +2 -3
- package/package.json +4 -4
- package/test/drizzle/0002_nice_squadron_supreme.sql +1 -0
- package/test/drizzle/0003_serious_mockingbird.sql +1 -0
- package/test/drizzle/0004_complete_pixie.sql +1 -0
- package/test/drizzle/0005_bumpy_sabra.sql +1 -0
- package/test/drizzle/0006_overrated_post.sql +6 -0
- package/test/drizzle/meta/0002_snapshot.json +63 -0
- package/test/drizzle/meta/0003_snapshot.json +73 -0
- package/test/drizzle/meta/0004_snapshot.json +89 -0
- package/test/drizzle/meta/0005_snapshot.json +104 -0
- package/test/drizzle/meta/0006_snapshot.json +104 -0
- package/test/drizzle/meta/_journal.json +35 -0
- package/test/test.model.d.ts +2 -2
- package/test/test.model.js +6 -4
- package/utils/value-or-provider.d.ts +7 -4
- package/utils/value-or-provider.js +9 -12
|
@@ -7,7 +7,7 @@ import type { Paths, Record, SimplifyObject, TypedOmit } from '../types/index.js
|
|
|
7
7
|
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
|
-
import type { Entity, EntityMetadata
|
|
10
|
+
import type { BaseEntity, Entity, EntityMetadata } from './entity.js';
|
|
11
11
|
import type { FullTextSearchQuery, Query } from './query.js';
|
|
12
12
|
import type { TsHeadlineOptions } from './sqls.js';
|
|
13
13
|
type WithSql<T> = {
|
|
@@ -18,13 +18,13 @@ type WithSql<T> = {
|
|
|
18
18
|
* or a raw Drizzle SQLWrapper for a complex target.
|
|
19
19
|
* @template T - The entity type.
|
|
20
20
|
*/
|
|
21
|
-
export type TargetColumnPaths<T extends
|
|
21
|
+
export type TargetColumnPaths<T extends BaseEntity> = Paths<UntaggedDeep<T>>;
|
|
22
22
|
/**
|
|
23
23
|
* Specifies the target column (e.g. for ordering, distinct on), which can be a property path within the entity
|
|
24
24
|
* or a raw Drizzle SQLWrapper for a complex target.
|
|
25
25
|
* @template T - The entity type.
|
|
26
26
|
*/
|
|
27
|
-
export type TargetColumn<T extends
|
|
27
|
+
export type TargetColumn<T extends BaseEntity> = TargetColumnPaths<T> | SQLWrapper;
|
|
28
28
|
/** Specifies the direction for ordering results ('asc' or 'desc'). */
|
|
29
29
|
export type OrderDirection = 'asc' | 'desc';
|
|
30
30
|
/**
|
|
@@ -32,26 +32,26 @@ export type OrderDirection = 'asc' | 'desc';
|
|
|
32
32
|
* (optionally with direction), or an object mapping property paths to directions.
|
|
33
33
|
* @template T - The entity type.
|
|
34
34
|
*/
|
|
35
|
-
export type Order<T extends
|
|
35
|
+
export type Order<T extends BaseEntity> = TargetColumn<T> | (TargetColumn<T> | [TargetColumn<T>, OrderDirection])[] | Partial<Record<Exclude<TargetColumn<T>, SQLWrapper>, OrderDirection>>;
|
|
36
36
|
/**
|
|
37
37
|
* Options object containing ordering configuration.
|
|
38
38
|
* @template T - The entity type.
|
|
39
39
|
*/
|
|
40
|
-
export type OrderOptions<T extends
|
|
40
|
+
export type OrderOptions<T extends BaseEntity> = {
|
|
41
41
|
order?: Order<T>;
|
|
42
42
|
};
|
|
43
43
|
/**
|
|
44
44
|
* Options for loading a single entity, including ordering and offset.
|
|
45
45
|
* @template T - The entity type.
|
|
46
46
|
*/
|
|
47
|
-
export type LoadOptions<T extends
|
|
47
|
+
export type LoadOptions<T extends BaseEntity> = OrderOptions<T> & {
|
|
48
48
|
offset?: number;
|
|
49
49
|
};
|
|
50
50
|
/**
|
|
51
51
|
* Options for loading multiple entities, including ordering, offset, and limit.
|
|
52
52
|
* @template T - The entity type.
|
|
53
53
|
*/
|
|
54
|
-
export type LoadManyOptions<T extends
|
|
54
|
+
export type LoadManyOptions<T extends BaseEntity> = LoadOptions<T> & {
|
|
55
55
|
limit?: number;
|
|
56
56
|
distinct?: boolean | TargetColumn<T>[];
|
|
57
57
|
};
|
|
@@ -74,7 +74,7 @@ export type RankOptions = {
|
|
|
74
74
|
/**
|
|
75
75
|
* Options for highlighting search results.
|
|
76
76
|
*/
|
|
77
|
-
export type HighlightOptions<T extends
|
|
77
|
+
export type HighlightOptions<T extends BaseEntity> = {
|
|
78
78
|
/**
|
|
79
79
|
* The source to generate the highlight from. Can be one or more property paths or a raw SQL expression.
|
|
80
80
|
*/
|
|
@@ -84,7 +84,7 @@ export type HighlightOptions<T extends EntityWithoutMetadata> = {
|
|
|
84
84
|
* Options for the `search` method.
|
|
85
85
|
* @template T - The entity type.
|
|
86
86
|
*/
|
|
87
|
-
export type SearchOptions<T extends
|
|
87
|
+
export type SearchOptions<T extends BaseEntity> = SimplifyObject<FullTextSearchQuery<T>['$fts'] & TypedOmit<LoadManyOptions<T>, 'order'> & {
|
|
88
88
|
/**
|
|
89
89
|
* An additional filter to apply to the search query.
|
|
90
90
|
*/
|
|
@@ -119,7 +119,7 @@ export type SearchOptions<T extends EntityWithoutMetadata> = SimplifyObject<Full
|
|
|
119
119
|
* Represents a single result from a full-text search operation.
|
|
120
120
|
* @template T - The entity type.
|
|
121
121
|
*/
|
|
122
|
-
export type SearchResult<T extends
|
|
122
|
+
export type SearchResult<T extends BaseEntity> = {
|
|
123
123
|
entity: T;
|
|
124
124
|
score?: number;
|
|
125
125
|
highlight?: string;
|
|
@@ -128,7 +128,7 @@ export type SearchResult<T extends EntityWithoutMetadata> = {
|
|
|
128
128
|
* Options for update operations (currently inherits from LoadOptions, primarily for ordering).
|
|
129
129
|
* @template T - The entity type.
|
|
130
130
|
*/
|
|
131
|
-
export type UpdateOptions<T extends
|
|
131
|
+
export type UpdateOptions<T extends BaseEntity> = LoadOptions<T>;
|
|
132
132
|
/** Type definition for updating entity metadata attributes, allowing partial updates and SQL expressions. */
|
|
133
133
|
export type EntityMetadataUpdate = WithSql<Partial<UntaggedDeep<Pick<EntityMetadata, 'attributes'>>>>;
|
|
134
134
|
export type EntityMetadataInsert = Partial<Pick<EntityMetadata, 'attributes'>>;
|
|
@@ -138,7 +138,7 @@ export type EntityMetadataInsert = Partial<Pick<EntityMetadata, 'attributes'>>;
|
|
|
138
138
|
* Allows SQL expressions for values.
|
|
139
139
|
* @template T - The entity type.
|
|
140
140
|
*/
|
|
141
|
-
export type NewEntity<T extends Entity |
|
|
141
|
+
export type NewEntity<T extends Entity | BaseEntity> = T extends Entity ? WithSql<UntaggedDeep<TypedOmit<T, 'id' | 'metadata'> & {
|
|
142
142
|
id?: string;
|
|
143
143
|
metadata?: EntityMetadataInsert;
|
|
144
144
|
}>> : WithSql<UntaggedDeep<TypedOmit<T, 'id'> & {
|
|
@@ -150,7 +150,7 @@ export type NewEntity<T extends Entity | EntityWithoutMetadata> = T extends Enti
|
|
|
150
150
|
* Allows SQL expressions for values.
|
|
151
151
|
* @template T - The entity type.
|
|
152
152
|
*/
|
|
153
|
-
export type EntityUpdate<T extends
|
|
153
|
+
export type EntityUpdate<T extends BaseEntity> = T extends Entity ? WithSql<PartialDeep<UntaggedDeep<TypedOmit<T, 'metadata'>>>> & {
|
|
154
154
|
metadata?: EntityMetadataUpdate;
|
|
155
155
|
} : WithSql<PartialDeep<UntaggedDeep<T>>>;
|
|
156
156
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SQL, sql } from 'drizzle-orm';
|
|
2
2
|
import { toCamelCase, toSnakeCase } from 'drizzle-orm/casing';
|
|
3
3
|
import { boolean, check, doublePrecision, foreignKey, index, integer, jsonb, pgSchema, primaryKey, text, unique, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
|
|
4
|
+
import { match, P } from 'ts-pattern';
|
|
4
5
|
import { MultiKeyMap } from '../../../data-structures/multi-key-map.js';
|
|
5
6
|
import { tryGetEnumName } from '../../../enumeration/enumeration.js';
|
|
6
7
|
import { NotSupportedError } from '../../../errors/not-supported.error.js';
|
|
@@ -12,10 +13,12 @@ import { compareByValueSelectionToOrder, orderRest } from '../../../utils/compar
|
|
|
12
13
|
import { decodeText, encodeUtf8 } from '../../../utils/encoding.js';
|
|
13
14
|
import { enumValues } from '../../../utils/enum.js';
|
|
14
15
|
import { memoize, memoizeSingle } from '../../../utils/function/memoize.js';
|
|
16
|
+
import { iif } from '../../../utils/helpers.js';
|
|
15
17
|
import { compileDereferencer } from '../../../utils/object/dereference.js';
|
|
16
18
|
import { fromEntries, objectEntries } from '../../../utils/object/object.js';
|
|
17
19
|
import { assertDefined, assertDefinedPass, isArray, isDefined, isNotNullOrUndefined, isNull, isString, isUndefined } from '../../../utils/type-guards.js';
|
|
18
|
-
import {
|
|
20
|
+
import { resolveValueOrProvider } from '../../../utils/value-or-provider.js';
|
|
21
|
+
import { bytea, numericDate, timestamp, tsvector } from '../../data-types/index.js';
|
|
19
22
|
import { JsonSchema } from '../../schemas/json.js';
|
|
20
23
|
import { NumericDateSchema } from '../../schemas/numeric-date.js';
|
|
21
24
|
import { TimestampSchema } from '../../schemas/timestamp.js';
|
|
@@ -55,12 +58,9 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
55
58
|
function buildIndex(table, data, columnName) {
|
|
56
59
|
const columns = (data.columns ?? [columnName]).map((columnValue) => {
|
|
57
60
|
assertDefined(columnValue, 'Missing column name for index.');
|
|
58
|
-
if (columnValue instanceof SQL) {
|
|
59
|
-
return columnValue;
|
|
60
|
-
}
|
|
61
61
|
const [columnName, columnOrder] = isString(columnValue) ? [columnValue] : columnValue;
|
|
62
|
-
let column = getColumn(table, columnName);
|
|
63
62
|
const order = columnOrder ?? data.order ?? 'asc';
|
|
63
|
+
let column = getColumn(table, columnName);
|
|
64
64
|
column = column[order]();
|
|
65
65
|
if (data.options?.nulls == 'first') {
|
|
66
66
|
column = column.nullsFirst();
|
|
@@ -71,37 +71,13 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
71
71
|
return column;
|
|
72
72
|
});
|
|
73
73
|
const indexFn = (data.options?.unique == true) ? uniqueIndex : index;
|
|
74
|
-
|
|
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);
|
|
74
|
+
let builder = indexFn(data.options?.name ?? getIndexName(tableName, columns, { naming: data.options?.naming })).using(data.options?.using ?? 'btree', ...columns);
|
|
82
75
|
if (isDefined(data.options?.where)) {
|
|
83
76
|
const query = convertQuery(data.options.where(table), table, columnDefinitionsMap);
|
|
84
77
|
builder = builder.where(query.inlineParams());
|
|
85
78
|
}
|
|
86
79
|
return builder;
|
|
87
80
|
}
|
|
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
|
-
}
|
|
105
81
|
function buildPrimaryKey(table) {
|
|
106
82
|
const columns = primaryKeyColumnDefinitions.map((columnDefinition) => getColumn(table, columnDefinition.name));
|
|
107
83
|
return primaryKey({
|
|
@@ -112,42 +88,118 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
112
88
|
const primaryKeyColumnDefinitions = columnDefinitions.filter((columnDefinition) => columnDefinition.reflectionData?.primaryKey == true);
|
|
113
89
|
const skipPrimaryKey = primaryKeyColumnDefinitions.length > 1;
|
|
114
90
|
const columnEntries = columnDefinitions.map((entry) => [entry.name, entry.buildType({ skipPrimaryKey })]);
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
...
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
91
|
+
const fullTextSearchColumnEntries = tableReflectionDatas
|
|
92
|
+
.flatMap((tableReflectionData) => tableReflectionData.fullTextSearch ?? [])
|
|
93
|
+
.flatMap((ftsData) => getFullTextSearchColumns(ftsData, () => drizzleSchema, (property) => getColumn(drizzleSchema, property)));
|
|
94
|
+
const drizzleSchema = dbSchema.table(tableName, fromEntries([
|
|
95
|
+
...columnEntries,
|
|
96
|
+
...fullTextSearchColumnEntries,
|
|
97
|
+
]), (drizzleTable) => {
|
|
98
|
+
const table = drizzleTable;
|
|
99
|
+
const indexes = tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.index).filter(isDefined).map((data) => buildIndex(drizzleTable, data));
|
|
100
|
+
const fullTextIndexes = tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.fullTextSearch ?? []).flatMap((ftsData) => getFullTextSearchIndexes(ftsData, table, (property) => getColumn(drizzleTable, property)));
|
|
101
|
+
const checks = tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.checks).filter(isDefined).map((data) => check(data.name, data.builder(table)));
|
|
102
|
+
return [
|
|
103
|
+
...((primaryKeyColumnDefinitions.length > 1)
|
|
104
|
+
? [buildPrimaryKey(drizzleTable)]
|
|
105
|
+
: []),
|
|
106
|
+
...(columnDefinitions.map((columnDefinition) => {
|
|
107
|
+
const indexData = columnDefinition.reflectionData?.index;
|
|
108
|
+
if (isUndefined(indexData)) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
return buildIndex(drizzleTable, indexData, columnDefinition.name);
|
|
112
|
+
}).filter(isDefined)),
|
|
113
|
+
...tableReflectionDatas.flatMap((tableReflectionData) => {
|
|
114
|
+
return tableReflectionData.foreignKeys?.map((foreignKeyData) => {
|
|
115
|
+
const foreignTable = getDrizzleTableFromType(foreignKeyData.target(), dbSchema.schemaName);
|
|
116
|
+
return foreignKey({
|
|
117
|
+
name: foreignKeyData.options?.name ?? getForeignKeyName(tableName, foreignKeyData.columns, { naming: foreignKeyData.options?.naming }),
|
|
118
|
+
columns: foreignKeyData.columns.map((column) => getColumn(drizzleTable, column)),
|
|
119
|
+
foreignColumns: foreignKeyData.foreignColumns.map((column) => getColumn(foreignTable, column)),
|
|
120
|
+
});
|
|
121
|
+
}) ?? [];
|
|
122
|
+
}),
|
|
123
|
+
...tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.unique).filter(isDefined).map((data) => {
|
|
124
|
+
const columns = data.columns?.map((column) => getColumn(drizzleTable, column));
|
|
125
|
+
let constraint = unique(data.options?.name ?? getUniqueName(tableName, columns, { naming: data.options?.naming })).on(...columns);
|
|
126
|
+
if (data.options?.nulls == 'not distinct') {
|
|
127
|
+
constraint = constraint.nullsNotDistinct();
|
|
128
|
+
}
|
|
129
|
+
return constraint;
|
|
130
|
+
}),
|
|
131
|
+
...indexes,
|
|
132
|
+
...fullTextIndexes,
|
|
133
|
+
...checks,
|
|
134
|
+
];
|
|
135
|
+
});
|
|
147
136
|
drizzleSchema[columnDefinitionsSymbol] = columnDefinitions;
|
|
148
137
|
drizzleSchema[columnDefinitionsMapSymbol] = columnDefinitionsMap;
|
|
149
138
|
return drizzleSchema;
|
|
150
139
|
}
|
|
140
|
+
function getFullTextSearchColumns(data, tableProvider, columnProvider) {
|
|
141
|
+
if (isDefined(data.vector)) {
|
|
142
|
+
const name = `fts_v_${data.name}`;
|
|
143
|
+
const generationSource = () => {
|
|
144
|
+
const table = tableProvider();
|
|
145
|
+
const source = assertDefinedPass(resolveValueOrProvider(data.source ?? data.vector?.rawVectorSource, table), 'Either "source" or "vector.rawVectorSource" must be provided for full-text search vector generation.');
|
|
146
|
+
const language = resolveValueOrProvider(data.vector?.language ?? 'simple', table);
|
|
147
|
+
return match(source)
|
|
148
|
+
.with(P.instanceOf(SQL), (sqlExpression) => sqlExpression)
|
|
149
|
+
.otherwise((paths) => {
|
|
150
|
+
const vectors = paths.map((property) => {
|
|
151
|
+
const column = columnProvider(property);
|
|
152
|
+
const tsVector = toTsVector(language, column);
|
|
153
|
+
const weight = data.vector?.weights?.[property];
|
|
154
|
+
if (isDefined(weight)) {
|
|
155
|
+
return setweight(tsVector, weight);
|
|
156
|
+
}
|
|
157
|
+
return tsVector;
|
|
158
|
+
});
|
|
159
|
+
return sql `(${sql.join(vectors, sql ` || `)})`;
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
const column = tsvector(name).generatedAlwaysAs(generationSource);
|
|
163
|
+
return [[name, column]];
|
|
164
|
+
}
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
function getFullTextSearchIndexes(data, table, columnProvider) {
|
|
168
|
+
return [
|
|
169
|
+
...iif(isDefined(data.vector), () => {
|
|
170
|
+
const indexName = `fts_${data.name}_bm25`;
|
|
171
|
+
const textSource = assertDefinedPass(data.source, 'Either "source" or "vector.rawVectorSource" must be provided for full-text search vector generation.');
|
|
172
|
+
const source = resolveValueOrProvider(textSource, table);
|
|
173
|
+
const indexExpression = match(source)
|
|
174
|
+
.with(P.instanceOf(SQL), (sqlExpression) => sqlExpression)
|
|
175
|
+
.otherwise((paths) => {
|
|
176
|
+
const columns = paths.map((property) => columnProvider(property));
|
|
177
|
+
return sql `(${sql.join(columns, sql ` || `)})`;
|
|
178
|
+
});
|
|
179
|
+
const bm25Index = index(indexName).using('bm25', indexExpression).with({ key_field: 'id' });
|
|
180
|
+
return [bm25Index];
|
|
181
|
+
}, () => []),
|
|
182
|
+
...iif(isDefined(data.vector), () => {
|
|
183
|
+
const columnName = `fts_v_${data.name}`;
|
|
184
|
+
const indexName = `${columnName}_gin`;
|
|
185
|
+
const ginIndex = index(indexName).using('gin', columnProvider(columnName)).with({ fastupdate: 'off' });
|
|
186
|
+
return [ginIndex];
|
|
187
|
+
}, () => []),
|
|
188
|
+
...iif(isDefined(data.trigram), () => {
|
|
189
|
+
const indexName = `fts_t_${data.name}_gist`;
|
|
190
|
+
const textSource = assertDefinedPass(data.source, 'Either "source" or "vector.rawVectorSource" must be provided for full-text search vector generation.');
|
|
191
|
+
const source = resolveValueOrProvider(textSource, table);
|
|
192
|
+
const indexExpression = match(source)
|
|
193
|
+
.with(P.instanceOf(SQL), (sqlExpression) => sqlExpression)
|
|
194
|
+
.otherwise((paths) => {
|
|
195
|
+
const columns = paths.map((property) => columnProvider(property));
|
|
196
|
+
return sql `(${sql.join(columns, sql ` || `)})`;
|
|
197
|
+
});
|
|
198
|
+
const gistIndex = index(indexName).using('gist', indexExpression).with({ fastupdate: 'off' });
|
|
199
|
+
return [gistIndex];
|
|
200
|
+
}, () => []),
|
|
201
|
+
];
|
|
202
|
+
}
|
|
151
203
|
function getPostgresColumnEntries(type, dbSchema, tableName, path = new JsonPath({ dollar: false }), prefix = '') {
|
|
152
204
|
const metadata = reflectionRegistry.getMetadata(type);
|
|
153
205
|
assertDefined(metadata, `Type ${type.name} does not have reflection metadata (path: ${path.toString()}).`);
|
package/orm/server/types.d.ts
CHANGED
|
@@ -3,8 +3,7 @@ import type { PgColumnBuilder, PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
|
3
3
|
import type { CamelCase, ConditionalPick, SnakeCase } from 'type-fest';
|
|
4
4
|
import type { JsonPath } from '../../json-path/json-path.js';
|
|
5
5
|
import type { Record } from '../../schema/index.js';
|
|
6
|
-
import type { UnionToIntersection } from '../../types/index.js';
|
|
7
|
-
import type { Tagged } from '../../types/index.js';
|
|
6
|
+
import type { Tagged, UnionToIntersection } from '../../types/index.js';
|
|
8
7
|
import type { OrmColumnReflectionData } from '../decorators.js';
|
|
9
8
|
import type { EntityType } from '../entity.js';
|
|
10
9
|
import type { ColumnBuilder, EmbeddedConfigTag } from '../types.js';
|
|
@@ -32,7 +31,7 @@ export type PgTableFromType<T extends EntityType = EntityType, S extends string
|
|
|
32
31
|
name: TableName;
|
|
33
32
|
schema: S;
|
|
34
33
|
columns: BuildColumns<TableName, {
|
|
35
|
-
[P in Exclude<keyof InstanceType<T>, keyof EmbeddedProperties<InstanceType<T>>>]: Column<CamelCase<Extract<P, string>>, InstanceType<T>[P]>;
|
|
34
|
+
[P in Exclude<Exclude<keyof InstanceType<T>, '__entityMeta__'>, keyof EmbeddedProperties<InstanceType<T>>>]: Column<CamelCase<Extract<P, string>>, InstanceType<T>[P]>;
|
|
36
35
|
} & UnionToIntersection<{
|
|
37
36
|
[P in keyof EmbeddedProperties<InstanceType<T>>]: EmbeddedColumns<InstanceType<T>[P], ColumnPrefix<InstanceType<T>[P]>>;
|
|
38
37
|
}[keyof EmbeddedProperties<InstanceType<T>>]>, 'pg'>;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tstdl/base",
|
|
3
|
-
"version": "0.93.
|
|
3
|
+
"version": "0.93.16",
|
|
4
4
|
"author": "Patrick Hein",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
9
|
"scripts": {
|
|
10
|
-
"build": "tsc && tsc-alias",
|
|
10
|
+
"build": "tsc && tsc-alias && npm run copy:orm",
|
|
11
11
|
"build:watch": "concurrently --raw --kill-others npm:tsc:watch npm:tsc-alias:watch",
|
|
12
12
|
"build:production": "rm -rf dist && npm run build && npm run build:production:copy-files",
|
|
13
13
|
"build:production:copy-files": "cp package.json eslint.config.js tsconfig.server.json dist/ && cp tsconfig.base.json dist/tsconfig.json && npm run copy:orm",
|
|
@@ -131,12 +131,12 @@
|
|
|
131
131
|
"luxon": "^3.7",
|
|
132
132
|
"reflect-metadata": "^0.2",
|
|
133
133
|
"rxjs": "^7.8",
|
|
134
|
-
"ts-pattern": "^5.
|
|
134
|
+
"ts-pattern": "^5.9",
|
|
135
135
|
"type-fest": "^5.1"
|
|
136
136
|
},
|
|
137
137
|
"peerDependencies": {
|
|
138
138
|
"@google-cloud/storage": "^7.17",
|
|
139
|
-
"@google/genai": "^1.
|
|
139
|
+
"@google/genai": "^1.27",
|
|
140
140
|
"@tstdl/angular": "^0.93",
|
|
141
141
|
"@zxcvbn-ts/core": "^3.0",
|
|
142
142
|
"@zxcvbn-ts/language-common": "^3.0",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DROP INDEX "test"."test_title_content_tags_idx";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE "test"."test" ADD COLUMN "ftsv_asd" "tsvector" GENERATED ALWAYS AS ((setweight(to_tsvector('simple', "test"."test"."title"), 'A') || setweight(to_tsvector('simple', "test"."test"."content"), 'B') || setweight(to_tsvector('simple', "test"."test"."tags"), 'C'))) STORED;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CREATE INDEX "ftsv_asd_gin" ON "test"."test" USING gin ("ftsv_asd");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CREATE INDEX "ftst_asd_gist" ON "test"."test" USING gist (("title" || "content" || "tags"));
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
DROP INDEX "test"."ftsv_asd_gin";--> statement-breakpoint
|
|
2
|
+
DROP INDEX "test"."ftst_asd_gist";--> statement-breakpoint
|
|
3
|
+
ALTER TABLE "test"."test" ADD COLUMN "fts_v_asd" "tsvector" GENERATED ALWAYS AS ((setweight(to_tsvector('simple', "test"."test"."title"), 'A') || setweight(to_tsvector('simple', "test"."test"."content"), 'B') || setweight(to_tsvector('simple', "test"."test"."tags"), 'C'))) STORED;--> statement-breakpoint
|
|
4
|
+
CREATE INDEX "fts_v_asd_gin" ON "test"."test" USING gin ("fts_v_asd");--> statement-breakpoint
|
|
5
|
+
CREATE INDEX "fts_t_asd_gist" ON "test"."test" USING gist (("title" || "content" || "tags"));--> statement-breakpoint
|
|
6
|
+
ALTER TABLE "test"."test" DROP COLUMN "ftsv_asd";
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "c8eced2f-44d3-46b3-aafa-e8a775549cd0",
|
|
3
|
+
"prevId": "3949ca77-11a4-4ca4-a404-1529e02d058c",
|
|
4
|
+
"version": "7",
|
|
5
|
+
"dialect": "postgresql",
|
|
6
|
+
"tables": {
|
|
7
|
+
"test.test": {
|
|
8
|
+
"name": "test",
|
|
9
|
+
"schema": "test",
|
|
10
|
+
"columns": {
|
|
11
|
+
"id": {
|
|
12
|
+
"name": "id",
|
|
13
|
+
"type": "uuid",
|
|
14
|
+
"primaryKey": true,
|
|
15
|
+
"notNull": true,
|
|
16
|
+
"default": "gen_random_uuid()"
|
|
17
|
+
},
|
|
18
|
+
"title": {
|
|
19
|
+
"name": "title",
|
|
20
|
+
"type": "text",
|
|
21
|
+
"primaryKey": false,
|
|
22
|
+
"notNull": true
|
|
23
|
+
},
|
|
24
|
+
"content": {
|
|
25
|
+
"name": "content",
|
|
26
|
+
"type": "text",
|
|
27
|
+
"primaryKey": false,
|
|
28
|
+
"notNull": true
|
|
29
|
+
},
|
|
30
|
+
"tags": {
|
|
31
|
+
"name": "tags",
|
|
32
|
+
"type": "text",
|
|
33
|
+
"primaryKey": false,
|
|
34
|
+
"notNull": true
|
|
35
|
+
},
|
|
36
|
+
"language": {
|
|
37
|
+
"name": "language",
|
|
38
|
+
"type": "text",
|
|
39
|
+
"primaryKey": false,
|
|
40
|
+
"notNull": true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"indexes": {},
|
|
44
|
+
"foreignKeys": {},
|
|
45
|
+
"compositePrimaryKeys": {},
|
|
46
|
+
"uniqueConstraints": {},
|
|
47
|
+
"policies": {},
|
|
48
|
+
"checkConstraints": {},
|
|
49
|
+
"isRLSEnabled": false
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"enums": {},
|
|
53
|
+
"schemas": {},
|
|
54
|
+
"sequences": {},
|
|
55
|
+
"roles": {},
|
|
56
|
+
"policies": {},
|
|
57
|
+
"views": {},
|
|
58
|
+
"_meta": {
|
|
59
|
+
"columns": {},
|
|
60
|
+
"schemas": {},
|
|
61
|
+
"tables": {}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "febb0102-cd99-43ee-8458-f25dc50e5264",
|
|
3
|
+
"prevId": "c8eced2f-44d3-46b3-aafa-e8a775549cd0",
|
|
4
|
+
"version": "7",
|
|
5
|
+
"dialect": "postgresql",
|
|
6
|
+
"tables": {
|
|
7
|
+
"test.test": {
|
|
8
|
+
"name": "test",
|
|
9
|
+
"schema": "test",
|
|
10
|
+
"columns": {
|
|
11
|
+
"id": {
|
|
12
|
+
"name": "id",
|
|
13
|
+
"type": "uuid",
|
|
14
|
+
"primaryKey": true,
|
|
15
|
+
"notNull": true,
|
|
16
|
+
"default": "gen_random_uuid()"
|
|
17
|
+
},
|
|
18
|
+
"title": {
|
|
19
|
+
"name": "title",
|
|
20
|
+
"type": "text",
|
|
21
|
+
"primaryKey": false,
|
|
22
|
+
"notNull": true
|
|
23
|
+
},
|
|
24
|
+
"content": {
|
|
25
|
+
"name": "content",
|
|
26
|
+
"type": "text",
|
|
27
|
+
"primaryKey": false,
|
|
28
|
+
"notNull": true
|
|
29
|
+
},
|
|
30
|
+
"tags": {
|
|
31
|
+
"name": "tags",
|
|
32
|
+
"type": "text",
|
|
33
|
+
"primaryKey": false,
|
|
34
|
+
"notNull": true
|
|
35
|
+
},
|
|
36
|
+
"language": {
|
|
37
|
+
"name": "language",
|
|
38
|
+
"type": "text",
|
|
39
|
+
"primaryKey": false,
|
|
40
|
+
"notNull": true
|
|
41
|
+
},
|
|
42
|
+
"ftsv_asd": {
|
|
43
|
+
"name": "ftsv_asd",
|
|
44
|
+
"type": "tsvector",
|
|
45
|
+
"primaryKey": false,
|
|
46
|
+
"notNull": false,
|
|
47
|
+
"generated": {
|
|
48
|
+
"as": "(setweight(to_tsvector('simple', \"test\".\"test\".\"title\"), 'A') || setweight(to_tsvector('simple', \"test\".\"test\".\"content\"), 'B') || setweight(to_tsvector('simple', \"test\".\"test\".\"tags\"), 'C'))",
|
|
49
|
+
"type": "stored"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"indexes": {},
|
|
54
|
+
"foreignKeys": {},
|
|
55
|
+
"compositePrimaryKeys": {},
|
|
56
|
+
"uniqueConstraints": {},
|
|
57
|
+
"policies": {},
|
|
58
|
+
"checkConstraints": {},
|
|
59
|
+
"isRLSEnabled": false
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"enums": {},
|
|
63
|
+
"schemas": {},
|
|
64
|
+
"sequences": {},
|
|
65
|
+
"roles": {},
|
|
66
|
+
"policies": {},
|
|
67
|
+
"views": {},
|
|
68
|
+
"_meta": {
|
|
69
|
+
"columns": {},
|
|
70
|
+
"schemas": {},
|
|
71
|
+
"tables": {}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "40cebc5a-7b84-40ff-ba11-c878018e6488",
|
|
3
|
+
"prevId": "febb0102-cd99-43ee-8458-f25dc50e5264",
|
|
4
|
+
"version": "7",
|
|
5
|
+
"dialect": "postgresql",
|
|
6
|
+
"tables": {
|
|
7
|
+
"test.test": {
|
|
8
|
+
"name": "test",
|
|
9
|
+
"schema": "test",
|
|
10
|
+
"columns": {
|
|
11
|
+
"id": {
|
|
12
|
+
"name": "id",
|
|
13
|
+
"type": "uuid",
|
|
14
|
+
"primaryKey": true,
|
|
15
|
+
"notNull": true,
|
|
16
|
+
"default": "gen_random_uuid()"
|
|
17
|
+
},
|
|
18
|
+
"title": {
|
|
19
|
+
"name": "title",
|
|
20
|
+
"type": "text",
|
|
21
|
+
"primaryKey": false,
|
|
22
|
+
"notNull": true
|
|
23
|
+
},
|
|
24
|
+
"content": {
|
|
25
|
+
"name": "content",
|
|
26
|
+
"type": "text",
|
|
27
|
+
"primaryKey": false,
|
|
28
|
+
"notNull": true
|
|
29
|
+
},
|
|
30
|
+
"tags": {
|
|
31
|
+
"name": "tags",
|
|
32
|
+
"type": "text",
|
|
33
|
+
"primaryKey": false,
|
|
34
|
+
"notNull": true
|
|
35
|
+
},
|
|
36
|
+
"language": {
|
|
37
|
+
"name": "language",
|
|
38
|
+
"type": "text",
|
|
39
|
+
"primaryKey": false,
|
|
40
|
+
"notNull": true
|
|
41
|
+
},
|
|
42
|
+
"ftsv_asd": {
|
|
43
|
+
"name": "ftsv_asd",
|
|
44
|
+
"type": "tsvector",
|
|
45
|
+
"primaryKey": false,
|
|
46
|
+
"notNull": false,
|
|
47
|
+
"generated": {
|
|
48
|
+
"as": "(setweight(to_tsvector('simple', \"test\".\"test\".\"title\"), 'A') || setweight(to_tsvector('simple', \"test\".\"test\".\"content\"), 'B') || setweight(to_tsvector('simple', \"test\".\"test\".\"tags\"), 'C'))",
|
|
49
|
+
"type": "stored"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"indexes": {
|
|
54
|
+
"ftsv_asd_gin": {
|
|
55
|
+
"name": "ftsv_asd_gin",
|
|
56
|
+
"columns": [
|
|
57
|
+
{
|
|
58
|
+
"expression": "ftsv_asd",
|
|
59
|
+
"isExpression": false,
|
|
60
|
+
"asc": true,
|
|
61
|
+
"nulls": "last"
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
"isUnique": false,
|
|
65
|
+
"concurrently": false,
|
|
66
|
+
"method": "gin",
|
|
67
|
+
"with": {}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"foreignKeys": {},
|
|
71
|
+
"compositePrimaryKeys": {},
|
|
72
|
+
"uniqueConstraints": {},
|
|
73
|
+
"policies": {},
|
|
74
|
+
"checkConstraints": {},
|
|
75
|
+
"isRLSEnabled": false
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"enums": {},
|
|
79
|
+
"schemas": {},
|
|
80
|
+
"sequences": {},
|
|
81
|
+
"roles": {},
|
|
82
|
+
"policies": {},
|
|
83
|
+
"views": {},
|
|
84
|
+
"_meta": {
|
|
85
|
+
"columns": {},
|
|
86
|
+
"schemas": {},
|
|
87
|
+
"tables": {}
|
|
88
|
+
}
|
|
89
|
+
}
|