@tstdl/base 0.91.28 → 0.91.31
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/.eslintrc.json +5 -1
- package/authentication/models/authentication-credentials.model.js +10 -10
- package/authentication/models/authentication-session.model.d.ts +2 -2
- package/authentication/models/authentication-session.model.js +16 -16
- package/authentication/models/init-secret-reset-data.model.js +3 -3
- package/authentication/models/token-payload-base.model.d.ts +4 -4
- package/authentication/models/token-payload-base.model.js +12 -12
- package/{reflection/reflection-data-map.d.ts → data-structures/context-data-map.d.ts} +3 -2
- package/{reflection/reflection-data-map.js → data-structures/context-data-map.js} +13 -6
- package/data-structures/index.d.ts +1 -0
- package/data-structures/index.js +1 -0
- package/examples/api/basic-overview.js +2 -2
- package/examples/api/custom-authentication.js +3 -3
- package/examples/orm/drizzle.config.d.ts +2 -0
- package/examples/orm/drizzle.config.js +5 -0
- package/examples/orm/schemas.d.ts +3 -0
- package/examples/orm/schemas.js +4 -0
- package/examples/orm/test.js +10 -0
- package/examples/orm/user.model.d.ts +9 -0
- package/examples/orm/user.model.js +39 -0
- package/key-value-store/index.d.ts +0 -1
- package/key-value-store/index.js +0 -1
- package/key-value-store/key-value.store.d.ts +9 -10
- package/key-value-store/mongo/mongo-key-value.store.js +2 -1
- package/mail/mail.client.js +5 -6
- package/orm/database-schema.d.ts +8 -0
- package/orm/database-schema.js +13 -0
- package/orm/decorators.d.ts +26 -0
- package/orm/decorators.js +21 -2
- package/orm/drizzle/schema-converter.d.ts +19 -0
- package/orm/drizzle/schema-converter.js +116 -0
- package/orm/entity.d.ts +6 -2
- package/orm/entity.js +9 -9
- package/orm/index.d.ts +1 -2
- package/orm/index.js +1 -2
- package/orm/repository.d.ts +27 -24
- package/orm/repository.js +124 -7
- package/orm/schemas/index.d.ts +1 -0
- package/orm/schemas/index.js +1 -0
- package/orm/schemas/uuid.d.ts +11 -0
- package/orm/schemas/uuid.js +16 -0
- package/orm/types.d.ts +20 -7
- package/orm/types.js +3 -5
- package/package.json +7 -4
- package/reflection/registry.d.ts +9 -6
- package/reflection/registry.js +25 -14
- package/schema/decorators/property.d.ts +2 -2
- package/schema/decorators/types.d.ts +1 -0
- package/schema/schema.d.ts +1 -1
- package/schema/schemas/array.d.ts +6 -3
- package/schema/schemas/array.js +9 -4
- package/schema/schemas/deferred.d.ts +12 -0
- package/schema/schemas/deferred.js +23 -0
- package/schema/schemas/index.d.ts +1 -0
- package/schema/schemas/index.js +1 -0
- package/schema/schemas/number.d.ts +5 -0
- package/schema/schemas/number.js +8 -1
- package/schema/schemas/string.d.ts +4 -1
- package/schema/schemas/string.js +8 -2
- package/schema/schemas/uint8-array.d.ts +3 -2
- package/schema/schemas/uint8-array.js +8 -5
- package/templates/resolvers/file.template-resolver.d.ts +1 -2
- package/templates/resolvers/file.template-resolver.js +2 -2
- package/templates/resolvers/jsx.template-resolver.d.ts +1 -3
- package/templates/resolvers/jsx.template-resolver.js +3 -7
- package/templates/template.model.d.ts +1 -1
- package/templates/template.model.js +5 -5
- package/utils/math.d.ts +11 -1
- package/utils/math.js +28 -0
- package/utils/string/index.d.ts +1 -0
- package/utils/string/index.js +1 -0
- package/utils/string/snake-case.d.ts +1 -0
- package/utils/string/snake-case.js +4 -0
- package/orm/schema-converter.d.ts +0 -99
- package/orm/schema-converter.js +0 -74
- package/orm/schema.d.ts +0 -3
- /package/{orm/schema.js → examples/orm/test.d.ts} +0 -0
package/orm/decorators.js
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
|
-
import { createPropertyDecorator } from '../reflection/utils.js';
|
|
1
|
+
import { createClassDecorator, createDecorator, createPropertyDecorator } from '../reflection/utils.js';
|
|
2
|
+
import { isArray } from '../utils/type-guards.js';
|
|
3
|
+
export function createTableDecorator(data) {
|
|
4
|
+
return createClassDecorator({ data: { orm: data }, mergeData: true });
|
|
5
|
+
}
|
|
6
|
+
export function createColumnDecorator(data) {
|
|
7
|
+
return createPropertyDecorator({ data: { orm: data }, mergeData: true });
|
|
8
|
+
}
|
|
9
|
+
export function createTableAndColumnDecorator(data) {
|
|
10
|
+
return createDecorator({ class: true, property: true, data: { orm: data }, mergeData: true });
|
|
11
|
+
}
|
|
12
|
+
export function Column(options) {
|
|
13
|
+
return createColumnDecorator({ ...options });
|
|
14
|
+
}
|
|
2
15
|
export function PrimaryKey() {
|
|
3
|
-
return
|
|
16
|
+
return createColumnDecorator({ primaryKey: true });
|
|
17
|
+
}
|
|
18
|
+
export function Unique(name, columnsOrOptions, options) {
|
|
19
|
+
if (isArray(columnsOrOptions)) {
|
|
20
|
+
return createTableDecorator({ unique: [{ name, columns: columnsOrOptions, options }] });
|
|
21
|
+
}
|
|
22
|
+
return createColumnDecorator({ unique: { name, options: columnsOrOptions ?? options } });
|
|
4
23
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BuildColumns, NotNull } from 'drizzle-orm';
|
|
2
|
+
import { type PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
3
|
+
import type { SnakeCase } from 'type-fest';
|
|
4
|
+
import type { Enumeration, Type } from '../../types.js';
|
|
5
|
+
import type { EntityType } from '../entity.js';
|
|
6
|
+
import type { ColumnBuilder } from '../types.js';
|
|
7
|
+
type Column<Name extends string, T> = null extends T ? ColumnBuilder<T, Name> : NotNull<ColumnBuilder<T, Name>>;
|
|
8
|
+
export declare const getDrizzleTableFromType: typeof _getDrizzleTableFromType;
|
|
9
|
+
export type PgTableFromType<S extends string, T extends Type, TableName extends string = T extends EntityType ? SnakeCase<T['entityName']> : string> = PgTableWithColumns<{
|
|
10
|
+
name: TableName;
|
|
11
|
+
schema: S;
|
|
12
|
+
columns: BuildColumns<TableName, {
|
|
13
|
+
[P in keyof InstanceType<T>]: Column<Extract<P, string>, InstanceType<T>[P]>;
|
|
14
|
+
}, 'pg'>;
|
|
15
|
+
dialect: 'pg';
|
|
16
|
+
}>;
|
|
17
|
+
export declare function _getDrizzleTableFromType<S extends string, T extends Type>(schemaName: S, type: T, tableName?: string): PgTableFromType<S, T>;
|
|
18
|
+
export declare function registerEnum(enumeration: Enumeration, name: string): void;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { toSnakeCase } from 'drizzle-orm/casing';
|
|
2
|
+
import { boolean, doublePrecision, integer, pgSchema, text, unique, uuid } from 'drizzle-orm/pg-core';
|
|
3
|
+
import { NotSupportedError } from '../../errors/not-supported.error.js';
|
|
4
|
+
import { reflectionRegistry } from '../../reflection/registry.js';
|
|
5
|
+
import { ArraySchema, BooleanSchema, EnumerationSchema, getObjectSchema, NullableSchema, NumberSchema, OptionalSchema, StringSchema } from '../../schema/index.js';
|
|
6
|
+
import { enumValues } from '../../utils/enum.js';
|
|
7
|
+
import { memoize, memoizeSingle } from '../../utils/function/memoize.js';
|
|
8
|
+
import { fromEntries, objectEntries } from '../../utils/object/object.js';
|
|
9
|
+
import { assertDefinedPass, assertStringPass, isArray, isDefined, isString, isUndefined } from '../../utils/type-guards.js';
|
|
10
|
+
import { UuidSchema } from '../schemas/uuid.js';
|
|
11
|
+
const getDbSchema = memoizeSingle(pgSchema);
|
|
12
|
+
export const getDrizzleTableFromType = memoize(_getDrizzleTableFromType);
|
|
13
|
+
export function _getDrizzleTableFromType(schemaName, type, tableName = getDefaultTableName(type)) {
|
|
14
|
+
const metadata = reflectionRegistry.getMetadata(type);
|
|
15
|
+
if (isUndefined(metadata)) {
|
|
16
|
+
throw new Error('Type does not have reflection metadata.');
|
|
17
|
+
}
|
|
18
|
+
const dbSchema = getDbSchema(schemaName);
|
|
19
|
+
const tableReflectionData = metadata.data.tryGet('orm');
|
|
20
|
+
const objectSchema = getObjectSchema(type);
|
|
21
|
+
const entries = objectEntries(objectSchema.properties).map(([property, schema]) => {
|
|
22
|
+
const columnReflectionData = metadata.properties.get(property)?.data.tryGet('orm');
|
|
23
|
+
const propertyName = columnReflectionData?.name ?? assertStringPass(toSnakeCase(property));
|
|
24
|
+
return [
|
|
25
|
+
property,
|
|
26
|
+
getPostgresColumn(tableName, propertyName, dbSchema, schema, columnReflectionData ?? {})
|
|
27
|
+
];
|
|
28
|
+
});
|
|
29
|
+
function getColumn(table, propertyName) {
|
|
30
|
+
return assertDefinedPass(table[propertyName], `Property "${propertyName}" does not exist on ${type.name}`);
|
|
31
|
+
}
|
|
32
|
+
const drizzleSchema = dbSchema.table(tableName, fromEntries(entries), (table) => {
|
|
33
|
+
const uniqueEntries = tableReflectionData?.unique?.map((data, index) => {
|
|
34
|
+
const columns = data.columns?.map((column) => getColumn(table, column));
|
|
35
|
+
let constraint = unique(isDefined(data.name) ? toSnakeCase(data.name) : undefined).on(...columns);
|
|
36
|
+
if (data.options?.nulls == 'not distinct') {
|
|
37
|
+
constraint = constraint.nullsNotDistinct();
|
|
38
|
+
}
|
|
39
|
+
return [`unique_${index}`, constraint];
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
...isDefined(uniqueEntries) ? fromEntries(uniqueEntries) : undefined
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
return drizzleSchema; // eslint-disable-line @typescript-eslint/no-unsafe-return
|
|
46
|
+
}
|
|
47
|
+
function getPostgresColumn(tableName, columnName, dbSchema, propertySchema, reflectionData) {
|
|
48
|
+
let nullable = false;
|
|
49
|
+
let array = false;
|
|
50
|
+
let baseSchema = propertySchema;
|
|
51
|
+
while (true) {
|
|
52
|
+
if ((baseSchema instanceof NullableSchema) || (baseSchema instanceof OptionalSchema)) {
|
|
53
|
+
nullable = true;
|
|
54
|
+
baseSchema = baseSchema.schema;
|
|
55
|
+
}
|
|
56
|
+
else if (baseSchema instanceof ArraySchema) {
|
|
57
|
+
array = true;
|
|
58
|
+
baseSchema = baseSchema.itemSchema;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let column = getPostgresBaseColumn(tableName, columnName, dbSchema, baseSchema);
|
|
65
|
+
if (array) {
|
|
66
|
+
column = column.array();
|
|
67
|
+
}
|
|
68
|
+
if (!nullable) {
|
|
69
|
+
column = column.notNull();
|
|
70
|
+
}
|
|
71
|
+
if (isDefined(reflectionData.unique)) {
|
|
72
|
+
column = column.unique(reflectionData.unique.name, isString(reflectionData.unique.options?.nulls) ? { nulls: reflectionData.unique.options.nulls } : undefined);
|
|
73
|
+
}
|
|
74
|
+
if (reflectionData.primaryKey == true) {
|
|
75
|
+
column = column.primaryKey();
|
|
76
|
+
}
|
|
77
|
+
return column;
|
|
78
|
+
}
|
|
79
|
+
function getPostgresBaseColumn(tableName, columnName, dbSchema, schema) {
|
|
80
|
+
if (schema instanceof NumberSchema) {
|
|
81
|
+
return schema.integer
|
|
82
|
+
? integer(columnName)
|
|
83
|
+
: doublePrecision(columnName);
|
|
84
|
+
}
|
|
85
|
+
if (schema instanceof UuidSchema) {
|
|
86
|
+
let column = uuid(columnName);
|
|
87
|
+
if (schema.defaultRandom) {
|
|
88
|
+
column = column.defaultRandom();
|
|
89
|
+
}
|
|
90
|
+
return column;
|
|
91
|
+
}
|
|
92
|
+
if (schema instanceof StringSchema) {
|
|
93
|
+
return text(columnName);
|
|
94
|
+
}
|
|
95
|
+
if (schema instanceof BooleanSchema) {
|
|
96
|
+
return boolean(columnName);
|
|
97
|
+
}
|
|
98
|
+
if (schema instanceof EnumerationSchema) {
|
|
99
|
+
const pgEnum = getPgEnum(tableName, columnName, dbSchema, schema.enumeration);
|
|
100
|
+
return pgEnum(columnName);
|
|
101
|
+
}
|
|
102
|
+
throw new NotSupportedError(`Schema ${schema.constructor.name} not supported`);
|
|
103
|
+
}
|
|
104
|
+
const enums = new Map();
|
|
105
|
+
export function registerEnum(enumeration, name) {
|
|
106
|
+
enums.set(enumeration, name);
|
|
107
|
+
}
|
|
108
|
+
function getPgEnum(tableName, columnName, dbSchema, enumeration) {
|
|
109
|
+
const values = (isArray(enumeration) ? enumeration : enumValues(enumeration))
|
|
110
|
+
.map((value) => value.toString());
|
|
111
|
+
const enumName = enums.get(enumeration) ?? `${tableName}_${columnName}_enum`;
|
|
112
|
+
return dbSchema.enum(enumName, values);
|
|
113
|
+
}
|
|
114
|
+
function getDefaultTableName(type) {
|
|
115
|
+
return toSnakeCase(isString(type.entityName) ? type.entityName : type.name);
|
|
116
|
+
}
|
package/orm/entity.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type { Record, TypedOmit } from '../types.js';
|
|
1
|
+
import type { Record, Type, TypedOmit } from '../types.js';
|
|
2
|
+
import { type HasDefault, type IsPrimaryKey, Uuid } from './types.js';
|
|
3
|
+
export interface EntityType<T extends Entity = Entity> extends Type<T> {
|
|
4
|
+
readonly entityName: string;
|
|
5
|
+
}
|
|
2
6
|
export declare abstract class EntityMetadata {
|
|
3
7
|
revision: number;
|
|
4
8
|
revisionTimestamp: number;
|
|
@@ -7,7 +11,7 @@ export declare abstract class EntityMetadata {
|
|
|
7
11
|
attributes: Record;
|
|
8
12
|
}
|
|
9
13
|
export declare abstract class Entity {
|
|
10
|
-
id:
|
|
14
|
+
id: IsPrimaryKey<HasDefault<Uuid>>;
|
|
11
15
|
metadata: EntityMetadata;
|
|
12
16
|
}
|
|
13
17
|
export type NewEntity<T extends Entity> = TypedOmit<T, 'id' | 'metadata'> & {
|
package/orm/entity.js
CHANGED
|
@@ -8,6 +8,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
10
|
import { NumberProperty, Property, any, record } from '../schema/index.js';
|
|
11
|
+
import { PrimaryKey } from './decorators.js';
|
|
12
|
+
import { Uuid } from './types.js';
|
|
11
13
|
export class EntityMetadata {
|
|
12
14
|
revision;
|
|
13
15
|
revisionTimestamp;
|
|
@@ -16,15 +18,15 @@ export class EntityMetadata {
|
|
|
16
18
|
attributes;
|
|
17
19
|
}
|
|
18
20
|
__decorate([
|
|
19
|
-
|
|
21
|
+
NumberProperty(),
|
|
20
22
|
__metadata("design:type", Number)
|
|
21
23
|
], EntityMetadata.prototype, "revision", void 0);
|
|
22
24
|
__decorate([
|
|
23
|
-
|
|
25
|
+
NumberProperty(),
|
|
24
26
|
__metadata("design:type", Number)
|
|
25
27
|
], EntityMetadata.prototype, "revisionTimestamp", void 0);
|
|
26
28
|
__decorate([
|
|
27
|
-
|
|
29
|
+
NumberProperty(),
|
|
28
30
|
__metadata("design:type", Number)
|
|
29
31
|
], EntityMetadata.prototype, "createTimestamp", void 0);
|
|
30
32
|
__decorate([
|
|
@@ -37,13 +39,11 @@ __decorate([
|
|
|
37
39
|
], EntityMetadata.prototype, "attributes", void 0);
|
|
38
40
|
export class Entity {
|
|
39
41
|
id;
|
|
42
|
+
// @Property(EntityMetadata)
|
|
40
43
|
metadata;
|
|
41
44
|
}
|
|
42
45
|
__decorate([
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
PrimaryKey(),
|
|
47
|
+
Uuid({ defaultRandom: true }),
|
|
48
|
+
__metadata("design:type", Object)
|
|
45
49
|
], Entity.prototype, "id", void 0);
|
|
46
|
-
__decorate([
|
|
47
|
-
Property(EntityMetadata),
|
|
48
|
-
__metadata("design:type", EntityMetadata)
|
|
49
|
-
], Entity.prototype, "metadata", void 0);
|
package/orm/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from './decorators.js';
|
|
2
|
+
export * from './drizzle/schema-converter.js';
|
|
2
3
|
export * from './entity.js';
|
|
3
4
|
export * from './query.js';
|
|
4
5
|
export * from './repository.js';
|
|
5
|
-
export * from './schema-converter.js';
|
|
6
|
-
export * from './schema.js';
|
|
7
6
|
export * from './types.js';
|
package/orm/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from './decorators.js';
|
|
2
|
+
export * from './drizzle/schema-converter.js';
|
|
2
3
|
export * from './entity.js';
|
|
3
4
|
export * from './query.js';
|
|
4
5
|
export * from './repository.js';
|
|
5
|
-
export * from './schema-converter.js';
|
|
6
|
-
export * from './schema.js';
|
|
7
6
|
export * from './types.js';
|
package/orm/repository.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { Paths,
|
|
2
|
-
import
|
|
1
|
+
import type { Paths, TypedOmit } from '../types.js';
|
|
2
|
+
import { SQL } from 'drizzle-orm';
|
|
3
|
+
import type { Entity, EntityMetadata, EntityType, NewEntity } from './entity.js';
|
|
3
4
|
import type { Query } from './query.js';
|
|
4
5
|
export declare const repositoryType: unique symbol;
|
|
5
6
|
export type OrderOptions<T extends Entity> = {
|
|
@@ -17,34 +18,36 @@ export type EntityMetadataUpdate = {
|
|
|
17
18
|
metadata?: Partial<EntityMetadata>;
|
|
18
19
|
};
|
|
19
20
|
export type EntityUpdate<T extends Entity> = Partial<TypedOmit<T, 'metadata'>> & EntityMetadataUpdate;
|
|
21
|
+
export declare const entityType: import("../injector/token.js").InjectionToken<EntityType<any>, never>;
|
|
20
22
|
export declare abstract class EntityRepository<T extends Entity = Entity> {
|
|
21
|
-
readonly type:
|
|
23
|
+
readonly type: EntityType<T>;
|
|
24
|
+
readonly schema: import("./drizzle/schema-converter.js").PgTableFromType<"", EntityType<Entity>, string>;
|
|
22
25
|
readonly database: import("drizzle-orm/node-postgres").NodePgDatabase<Record<string, never>> & {
|
|
23
|
-
$client:
|
|
26
|
+
$client: import("drizzle-orm/node-postgres").NodePgClient;
|
|
24
27
|
};
|
|
25
|
-
load(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
load(id: string): Promise<T>;
|
|
29
|
+
tryLoad(id: string): Promise<T | undefined>;
|
|
30
|
+
loadByQuery(query: Query<T> | SQL | undefined, options?: LoadOptions<T>): Promise<T>;
|
|
31
|
+
tryLoadByQuery(query: Query<T> | SQL | undefined, options?: LoadOptions<T>): Promise<T | undefined>;
|
|
32
|
+
loadMany(ids: string[], options?: LoadManyOptions<T>): Promise<T[]>;
|
|
33
|
+
loadManyCursor(ids: string[], options?: LoadManyOptions<T>): AsyncIterableIterator<T>;
|
|
34
|
+
loadManyByQuery(query: Query<T> | SQL | undefined, options?: LoadManyOptions<T>): Promise<T[]>;
|
|
35
|
+
loadManyByQueryCursor(query: Query<T> | SQL | undefined, options?: LoadManyOptions<T>): AsyncIterableIterator<T>;
|
|
36
|
+
loadAll(options?: LoadManyOptions<T>): Promise<T[]>;
|
|
37
|
+
loadAllCursor(options?: LoadManyOptions<T>): AsyncIterableIterator<T>;
|
|
38
|
+
count(): Promise<number>;
|
|
39
|
+
countByQuery(query: Query<T> | SQL): Promise<number>;
|
|
40
|
+
has(id: string): Promise<boolean>;
|
|
41
|
+
hasByQuery(query: Query<T> | SQL): Promise<boolean>;
|
|
42
|
+
hasAll(ids: string[]): Promise<boolean>;
|
|
43
|
+
insert(_entity: NewEntity<T>): Promise<T>;
|
|
41
44
|
abstract insertMany(entities: NewEntity<T>[]): Promise<T[]>;
|
|
42
45
|
abstract update(id: string, update: EntityUpdate<T>): Promise<void>;
|
|
43
|
-
abstract
|
|
46
|
+
abstract updateByQuery(query: Query<T>, update: EntityUpdate<T>): Promise<void>;
|
|
44
47
|
abstract updateMany(ids: string[], update: EntityUpdate<T>): Promise<void>;
|
|
45
|
-
abstract
|
|
48
|
+
abstract updateManyByQuery(filter: Query<T>, update: EntityUpdate<T>): Promise<void>;
|
|
46
49
|
abstract delete(id: string): Promise<boolean>;
|
|
47
50
|
abstract deleteMany(ids: string[]): Promise<number>;
|
|
48
|
-
abstract
|
|
49
|
-
abstract
|
|
51
|
+
abstract deleteByQuery(query: Query<T>): Promise<boolean>;
|
|
52
|
+
abstract deleteManyByQuery(query: Query<T>): Promise<number>;
|
|
50
53
|
}
|
package/orm/repository.js
CHANGED
|
@@ -1,11 +1,128 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
2
8
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
9
|
+
import { NotFoundError } from '../errors/not-found.error.js';
|
|
10
|
+
import { NotImplementedError } from '../errors/not-implemented.error.js';
|
|
11
|
+
import { NotSupportedError } from '../errors/not-supported.error.js';
|
|
12
|
+
import { Singleton } from '../injector/decorators.js';
|
|
13
|
+
import { inject } from '../injector/inject.js';
|
|
14
|
+
import { injectionToken } from '../injector/token.js';
|
|
15
|
+
import { assertDefinedPass, isUndefined } from '../utils/type-guards.js';
|
|
16
|
+
import { count, eq, inArray, sql, SQL } from 'drizzle-orm';
|
|
17
|
+
import { getDrizzleTableFromType } from './drizzle/schema-converter.js';
|
|
3
18
|
export const repositoryType = Symbol('repositoryType');
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
19
|
+
export const entityType = injectionToken('Entity type');
|
|
20
|
+
let EntityRepository = class EntityRepository {
|
|
21
|
+
type = inject(entityType);
|
|
22
|
+
schema = getDrizzleTableFromType('', this.type);
|
|
23
|
+
database = drizzle('');
|
|
24
|
+
async load(id) {
|
|
25
|
+
const entity = await this.tryLoad(id);
|
|
26
|
+
if (isUndefined(entity)) {
|
|
27
|
+
throw new NotFoundError(`${this.type.entityName} ${id} not found.`);
|
|
28
|
+
}
|
|
29
|
+
return entity;
|
|
30
|
+
}
|
|
31
|
+
async tryLoad(id) {
|
|
32
|
+
return this.tryLoadByQuery(eq(this.schema.id, id));
|
|
33
|
+
}
|
|
34
|
+
async loadByQuery(query, options) {
|
|
35
|
+
const entity = await this.tryLoadByQuery(query, options);
|
|
36
|
+
if (isUndefined(entity)) {
|
|
37
|
+
throw new NotFoundError(`${this.type.entityName} not found.`);
|
|
38
|
+
}
|
|
39
|
+
return entity;
|
|
40
|
+
}
|
|
41
|
+
async tryLoadByQuery(query, options) {
|
|
42
|
+
if (!(query instanceof SQL)) {
|
|
43
|
+
throw new NotSupportedError();
|
|
44
|
+
}
|
|
45
|
+
const dbQuery = this.database.select()
|
|
46
|
+
.from(this.schema)
|
|
47
|
+
.where(query)
|
|
48
|
+
.offset(options?.offset);
|
|
49
|
+
const [entity] = (await dbQuery);
|
|
50
|
+
return entity;
|
|
51
|
+
}
|
|
52
|
+
async loadMany(ids, options) {
|
|
53
|
+
return this.loadManyByQuery(inArray(this.schema.id, ids), options);
|
|
54
|
+
}
|
|
55
|
+
async *loadManyCursor(ids, options) {
|
|
56
|
+
const entities = await this.loadMany(ids, options);
|
|
57
|
+
yield* entities;
|
|
58
|
+
}
|
|
59
|
+
async loadManyByQuery(query, options) {
|
|
60
|
+
if (!(query instanceof SQL)) {
|
|
61
|
+
throw new NotSupportedError();
|
|
62
|
+
}
|
|
63
|
+
const dbQuery = this.database.select()
|
|
64
|
+
.from(this.schema)
|
|
65
|
+
.where(query)
|
|
66
|
+
.offset(options?.offset)
|
|
67
|
+
.limit(options?.limit);
|
|
68
|
+
return dbQuery;
|
|
69
|
+
}
|
|
70
|
+
async *loadManyByQueryCursor(query, options) {
|
|
71
|
+
const entities = await this.loadManyByQuery(query, options);
|
|
72
|
+
yield* entities;
|
|
73
|
+
}
|
|
74
|
+
async loadAll(options) {
|
|
75
|
+
return this.loadManyByQuery(undefined, options);
|
|
76
|
+
}
|
|
77
|
+
async *loadAllCursor(options) {
|
|
78
|
+
const entities = await this.loadAll(options);
|
|
79
|
+
yield* entities;
|
|
80
|
+
}
|
|
81
|
+
async count() {
|
|
82
|
+
const dbQuery = this.database
|
|
83
|
+
.select({ count: count() })
|
|
84
|
+
.from(this.schema);
|
|
85
|
+
const [result] = await dbQuery;
|
|
86
|
+
return assertDefinedPass(result).count;
|
|
87
|
+
}
|
|
88
|
+
async countByQuery(query) {
|
|
89
|
+
if (!(query instanceof SQL)) {
|
|
90
|
+
throw new NotSupportedError();
|
|
91
|
+
}
|
|
92
|
+
const dbQuery = this.database
|
|
93
|
+
.select({ count: count() })
|
|
94
|
+
.from(this.schema)
|
|
95
|
+
.where(query);
|
|
96
|
+
const [result] = await dbQuery;
|
|
97
|
+
return assertDefinedPass(result).count;
|
|
98
|
+
}
|
|
99
|
+
async has(id) {
|
|
100
|
+
return this.hasByQuery(eq(this.schema.id, id));
|
|
101
|
+
}
|
|
102
|
+
async hasByQuery(query) {
|
|
103
|
+
// SELECT EXISTS(SELECT 1 FROM contact WHERE id=12) as exists
|
|
104
|
+
if (!(query instanceof SQL)) {
|
|
105
|
+
throw new NotSupportedError();
|
|
106
|
+
}
|
|
107
|
+
const dbQuery = this.database
|
|
108
|
+
.select({
|
|
109
|
+
exists: sql `SELECT EXISTS(SELECT 1 FROM ${this.schema} WHERE ${query})`
|
|
110
|
+
})
|
|
111
|
+
.from(this.schema)
|
|
112
|
+
.where(query);
|
|
113
|
+
const [result] = await dbQuery;
|
|
114
|
+
return assertDefinedPass(result).exists;
|
|
115
|
+
}
|
|
116
|
+
async hasAll(ids) {
|
|
117
|
+
const result = await this.database.execute(sql `SELECT array_agg(id) @> ${ids} AS contains FROM ${this.schema};`);
|
|
118
|
+
return assertDefinedPass(result.rows[0]).contains;
|
|
119
|
+
}
|
|
120
|
+
async insert(_entity) {
|
|
121
|
+
// await this.database.insert(this.schema).values([entity as T]);
|
|
9
122
|
throw new NotImplementedError();
|
|
10
123
|
}
|
|
11
|
-
}
|
|
124
|
+
};
|
|
125
|
+
EntityRepository = __decorate([
|
|
126
|
+
Singleton()
|
|
127
|
+
], EntityRepository);
|
|
128
|
+
export { EntityRepository };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './uuid.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './uuid.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StringSchema, type SchemaPropertyDecorator, type SchemaPropertyDecoratorOptions } from '../../schema/index.js';
|
|
2
|
+
export type UuidSchemaOptions = {
|
|
3
|
+
defaultRandom?: boolean;
|
|
4
|
+
};
|
|
5
|
+
export declare class UuidSchema extends StringSchema {
|
|
6
|
+
readonly name = "uuid";
|
|
7
|
+
readonly defaultRandom: boolean;
|
|
8
|
+
constructor(options?: UuidSchemaOptions);
|
|
9
|
+
}
|
|
10
|
+
export declare function uuid(options?: UuidSchemaOptions): UuidSchema;
|
|
11
|
+
export declare function Uuid(options?: UuidSchemaOptions & SchemaPropertyDecoratorOptions): SchemaPropertyDecorator;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Property, StringSchema } from '../../schema/index.js';
|
|
2
|
+
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u;
|
|
3
|
+
export class UuidSchema extends StringSchema {
|
|
4
|
+
name = 'uuid';
|
|
5
|
+
defaultRandom;
|
|
6
|
+
constructor(options) {
|
|
7
|
+
super({ pattern: uuidPattern });
|
|
8
|
+
this.defaultRandom = options?.defaultRandom ?? false;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function uuid(options) {
|
|
12
|
+
return new UuidSchema(options);
|
|
13
|
+
}
|
|
14
|
+
export function Uuid(options) {
|
|
15
|
+
return Property(uuid(options), options);
|
|
16
|
+
}
|
package/orm/types.d.ts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
|
+
import type { HasDefault as DrizzleHasDefault, IsPrimaryKey as DrizzleIsPrimaryKey } from 'drizzle-orm';
|
|
2
|
+
import type { boolean, doublePrecision, integer, PgColumnBuilderBase, text, uuid } from 'drizzle-orm/pg-core';
|
|
3
|
+
import type { GetTagMetadata, Tagged, UnwrapTagged } from 'type-fest';
|
|
1
4
|
import { Integer } from '../schema/index.js';
|
|
2
|
-
import type {
|
|
3
|
-
import
|
|
4
|
-
export
|
|
5
|
-
export type
|
|
6
|
-
export type
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import type { Record } from '../types.js';
|
|
6
|
+
import { Uuid } from './schemas/index.js';
|
|
7
|
+
export type IsPrimaryKey<T> = T extends Tagged<unknown, 'column', PgColumnBuilderBase> ? Tagged<UnwrapTagged<T>, 'column', DrizzleIsPrimaryKey<GetTagMetadata<T, 'column'>>> : Tagged<T, 'column', ColumnBuilder<T>>;
|
|
8
|
+
export type HasDefault<T> = T extends Tagged<unknown, 'column', PgColumnBuilderBase> ? Tagged<UnwrapTagged<T>, 'column', DrizzleHasDefault<GetTagMetadata<T, 'column'>>> : Tagged<T, 'column', ColumnBuilder<T>>;
|
|
9
|
+
export type Nested<T extends Record> = Tagged<T, 'column', {
|
|
10
|
+
nested: T;
|
|
11
|
+
}>;
|
|
12
|
+
export type ColumnBuilder<T, ColumnName extends string = never> = T extends Tagged<T, 'column', any> ? GetTagMetadata<T, 'column'> : T extends string ? string extends ColumnName ? ReturnType<typeof text<ColumnName, string, [string, ...string[]]>> : ReturnType<typeof text<string, [string, ...string[]]>> : T extends number ? string extends ColumnName ? ReturnType<typeof doublePrecision<ColumnName>> : ReturnType<typeof doublePrecision> : T extends boolean ? string extends ColumnName ? ReturnType<typeof boolean<ColumnName>> : ReturnType<typeof boolean> : never;
|
|
13
|
+
export type TypeBuilder<T, ColumnName extends string = never> = [
|
|
14
|
+
ColumnName
|
|
15
|
+
] extends [never] ? T extends Tagged<any, 'column', PgColumnBuilderBase> ? T : T extends infer U ? Tagged<U, 'column', ColumnBuilder<U>> : never : never;
|
|
16
|
+
export type Text = Tagged<string, 'column', ReturnType<typeof text<string, [string, ...string[]]>>>;
|
|
17
|
+
export type Uuid = Tagged<string, 'column', ReturnType<typeof uuid>>;
|
|
18
|
+
export type Integer = Tagged<number, 'column', ReturnType<typeof integer>>;
|
|
19
|
+
export type DoublePrecision = Tagged<number, 'column', ReturnType<typeof doublePrecision>>;
|
|
20
|
+
export type Boolean = Tagged<number, 'column', ReturnType<typeof boolean>>;
|
|
21
|
+
export { Integer, Uuid };
|
package/orm/types.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-redeclare, @typescript-eslint/naming-convention */
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
export { Integer };
|
|
2
|
+
import { Integer } from '../schema/index.js';
|
|
3
|
+
import { Uuid } from './schemas/index.js';
|
|
4
|
+
export { Integer, Uuid };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tstdl/base",
|
|
3
|
-
"version": "0.91.
|
|
3
|
+
"version": "0.91.31",
|
|
4
4
|
"author": "Patrick Hein",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"./json-path": "./json-path/index.js",
|
|
57
57
|
"./jsx": "./jsx/index.js",
|
|
58
58
|
"./key-value-store": "./key-value-store/index.js",
|
|
59
|
+
"./key-value-store/mongo": "./key-value-store/mongo/index.js",
|
|
59
60
|
"./lock": "./lock/index.js",
|
|
60
61
|
"./lock/mongo": "./lock/mongo/index.js",
|
|
61
62
|
"./lock/web": "./lock/web/index.js",
|
|
@@ -125,8 +126,10 @@
|
|
|
125
126
|
"@types/mjml": "4.7",
|
|
126
127
|
"@types/node": "22",
|
|
127
128
|
"@types/nodemailer": "6.4",
|
|
129
|
+
"@types/pg": "8.11",
|
|
128
130
|
"@typescript-eslint/eslint-plugin": "7.17",
|
|
129
131
|
"concurrently": "9.0",
|
|
132
|
+
"drizzle-kit": "0.26",
|
|
130
133
|
"eslint": "8.57",
|
|
131
134
|
"eslint-import-resolver-typescript": "3.6",
|
|
132
135
|
"eslint-plugin-import": "2.31",
|
|
@@ -144,14 +147,14 @@
|
|
|
144
147
|
"@zxcvbn-ts/language-de": "^3.0",
|
|
145
148
|
"@zxcvbn-ts/language-en": "^3.0",
|
|
146
149
|
"chroma-js": "^2.6",
|
|
147
|
-
"drizzle-orm": "^0.
|
|
150
|
+
"drizzle-orm": "^0.35",
|
|
148
151
|
"handlebars": "^4.7",
|
|
149
152
|
"koa": "^2.15",
|
|
150
153
|
"minio": "^8.0",
|
|
151
154
|
"mjml": "^4.15",
|
|
152
|
-
"mongodb": "^6.
|
|
155
|
+
"mongodb": "^6.10",
|
|
153
156
|
"nodemailer": "^6.9",
|
|
154
|
-
"pg": "
|
|
157
|
+
"pg": "8.13",
|
|
155
158
|
"playwright": "^1.48",
|
|
156
159
|
"preact": "^10.24",
|
|
157
160
|
"preact-render-to-string": "^6.5",
|
package/reflection/registry.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AbstractConstructor } from '../types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { ContextDataMap } from '../data-structures/context-data-map.js';
|
|
3
3
|
import type { DecoratorData } from './types.js';
|
|
4
4
|
export type ReflectionMetadata = TypeMetadata | PropertyMetadata | MethodMetadata | ConstructorParameterMetadata | MethodParameterMetadata;
|
|
5
5
|
export type MetadataType = 'type' | 'property' | 'method' | 'method-parameter' | 'constructor-parameter';
|
|
@@ -15,31 +15,34 @@ export type TypeMetadata = MetadataBase<'type'> & {
|
|
|
15
15
|
readonly staticProperties: ReadonlyMap<string | symbol, PropertyMetadata>;
|
|
16
16
|
readonly methods: ReadonlyMap<string | symbol, MethodMetadata>;
|
|
17
17
|
readonly staticMethods: ReadonlyMap<string | symbol, MethodMetadata>;
|
|
18
|
-
readonly data:
|
|
18
|
+
readonly data: ContextDataMap;
|
|
19
19
|
};
|
|
20
20
|
export type PropertyMetadata = MetadataBase<'property'> & {
|
|
21
21
|
key: string | symbol;
|
|
22
22
|
type: AbstractConstructor;
|
|
23
23
|
isAccessor: boolean;
|
|
24
|
-
data:
|
|
24
|
+
data: ContextDataMap;
|
|
25
|
+
inherited: boolean;
|
|
25
26
|
};
|
|
26
27
|
export type MethodMetadata = MetadataBase<'method'> & {
|
|
27
28
|
parameters: MethodParameterMetadata[];
|
|
28
29
|
returnType: AbstractConstructor | undefined;
|
|
29
|
-
data:
|
|
30
|
+
data: ContextDataMap;
|
|
31
|
+
inherited: boolean;
|
|
30
32
|
};
|
|
31
33
|
export type ConstructorParameterMetadata = MetadataBase<'constructor-parameter'> & {
|
|
32
34
|
type: AbstractConstructor | undefined;
|
|
33
35
|
index: number;
|
|
34
|
-
data:
|
|
36
|
+
data: ContextDataMap;
|
|
35
37
|
};
|
|
36
38
|
export type MethodParameterMetadata = MetadataBase<'method-parameter'> & {
|
|
37
39
|
type: AbstractConstructor;
|
|
38
40
|
index: number;
|
|
39
|
-
data:
|
|
41
|
+
data: ContextDataMap;
|
|
40
42
|
};
|
|
41
43
|
export type ParameterMetadata = ConstructorParameterMetadata | MethodParameterMetadata;
|
|
42
44
|
export declare class ReflectionRegistry {
|
|
45
|
+
#private;
|
|
43
46
|
private readonly metadataMap;
|
|
44
47
|
private readonly finalizedTypesSet;
|
|
45
48
|
constructor();
|