@cqrs-ddd/mikro-orm 0.2.0
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/COMMERCIAL_LICENSE.txt +34 -0
- package/LICENSE +661 -0
- package/README.md +299 -0
- package/dist/cache/cache-entry.d.ts +43 -0
- package/dist/cache/cache-entry.d.ts.map +1 -0
- package/dist/cache/cache-entry.js +92 -0
- package/dist/cache/cache-entry.js.map +1 -0
- package/dist/cache/mikro-orm.cache.d.ts +82 -0
- package/dist/cache/mikro-orm.cache.d.ts.map +1 -0
- package/dist/cache/mikro-orm.cache.js +209 -0
- package/dist/cache/mikro-orm.cache.js.map +1 -0
- package/dist/concurrency/assert-autocommit.d.ts +21 -0
- package/dist/concurrency/assert-autocommit.d.ts.map +1 -0
- package/dist/concurrency/assert-autocommit.js +27 -0
- package/dist/concurrency/assert-autocommit.js.map +1 -0
- package/dist/concurrency/conditioned-write.d.ts +23 -0
- package/dist/concurrency/conditioned-write.d.ts.map +1 -0
- package/dist/concurrency/conditioned-write.js +26 -0
- package/dist/concurrency/conditioned-write.js.map +1 -0
- package/dist/concurrency/optimistic-delete.d.ts +52 -0
- package/dist/concurrency/optimistic-delete.d.ts.map +1 -0
- package/dist/concurrency/optimistic-delete.js +67 -0
- package/dist/concurrency/optimistic-delete.js.map +1 -0
- package/dist/concurrency/optimistic-update.d.ts +51 -0
- package/dist/concurrency/optimistic-update.d.ts.map +1 -0
- package/dist/concurrency/optimistic-update.js +60 -0
- package/dist/concurrency/optimistic-update.js.map +1 -0
- package/dist/errors/mikro-orm.dialect.d.ts +32 -0
- package/dist/errors/mikro-orm.dialect.d.ts.map +1 -0
- package/dist/errors/mikro-orm.dialect.js +96 -0
- package/dist/errors/mikro-orm.dialect.js.map +1 -0
- package/dist/errors/transient-error.d.ts +51 -0
- package/dist/errors/transient-error.d.ts.map +1 -0
- package/dist/errors/transient-error.js +97 -0
- package/dist/errors/transient-error.js.map +1 -0
- package/dist/helpers/sql-identifier.d.ts +19 -0
- package/dist/helpers/sql-identifier.d.ts.map +1 -0
- package/dist/helpers/sql-identifier.js +23 -0
- package/dist/helpers/sql-identifier.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/entity-manager-source.d.ts +19 -0
- package/dist/interfaces/entity-manager-source.d.ts.map +1 -0
- package/dist/interfaces/entity-manager-source.js +4 -0
- package/dist/interfaces/entity-manager-source.js.map +1 -0
- package/dist/mapping/root-entity.properties.d.ts +63 -0
- package/dist/mapping/root-entity.properties.d.ts.map +1 -0
- package/dist/mapping/root-entity.properties.js +63 -0
- package/dist/mapping/root-entity.properties.js.map +1 -0
- package/dist/mapping/unix-timestamp.type.d.ts +17 -0
- package/dist/mapping/unix-timestamp.type.d.ts.map +1 -0
- package/dist/mapping/unix-timestamp.type.js +55 -0
- package/dist/mapping/unix-timestamp.type.js.map +1 -0
- package/dist/repository/aggregate.repository.d.ts +68 -0
- package/dist/repository/aggregate.repository.d.ts.map +1 -0
- package/dist/repository/aggregate.repository.js +103 -0
- package/dist/repository/aggregate.repository.js.map +1 -0
- package/dist/tenancy/tenant-store.d.ts +63 -0
- package/dist/tenancy/tenant-store.d.ts.map +1 -0
- package/dist/tenancy/tenant-store.js +91 -0
- package/dist/tenancy/tenant-store.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.MikroOrmDialect = void 0;
|
|
5
|
+
const core_1 = require("@mikro-orm/core");
|
|
6
|
+
const SQLITE_COLUMNS = /UNIQUE constraint failed: (.+)$/m;
|
|
7
|
+
function constraintsOf(meta, naming) {
|
|
8
|
+
const describe = (key, properties, name) => {
|
|
9
|
+
const fields = properties.flatMap((property) => meta.properties[property].fieldNames);
|
|
10
|
+
return {
|
|
11
|
+
key,
|
|
12
|
+
name: name ?? naming.indexName(meta.tableName, fields, 'unique'),
|
|
13
|
+
columns: fields.map((field) => `${meta.tableName}.${field}`).join(', '),
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
const constraints = Object.values(meta.properties)
|
|
17
|
+
.filter((property) => property.unique)
|
|
18
|
+
.map((property) => describe(property.name, [property.name], typeof property.unique === 'string' ? property.unique : undefined));
|
|
19
|
+
for (const unique of meta.uniques) {
|
|
20
|
+
const properties = [unique.properties ?? []].flat();
|
|
21
|
+
const key = properties.length === 1 ? properties[0] : unique.name;
|
|
22
|
+
if (key === undefined) {
|
|
23
|
+
throw new TypeError(`${meta.className}: a unique constraint over several properties needs a name to be mapped.`);
|
|
24
|
+
}
|
|
25
|
+
constraints.push(properties.length > 0
|
|
26
|
+
? describe(key, properties, unique.name)
|
|
27
|
+
: { key, name: key });
|
|
28
|
+
}
|
|
29
|
+
return constraints;
|
|
30
|
+
}
|
|
31
|
+
function assertDistinctColumns(meta, constraints) {
|
|
32
|
+
const seen = new Map();
|
|
33
|
+
for (const { name, columns } of constraints) {
|
|
34
|
+
if (columns === undefined)
|
|
35
|
+
continue;
|
|
36
|
+
const other = seen.get(columns);
|
|
37
|
+
if (other !== undefined) {
|
|
38
|
+
throw new TypeError(`${meta.className}: unique constraints ${other} and ${name} cover the same columns; SQLite cannot tell them apart.`);
|
|
39
|
+
}
|
|
40
|
+
seen.set(columns, name);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The MikroORM persistence dialect: it reads the violated unique constraint of a
|
|
45
|
+
* `UniqueConstraintViolationException` through the ORM's entity metadata, so a
|
|
46
|
+
* repository maps it by entity property and never names a constraint or column.
|
|
47
|
+
*
|
|
48
|
+
* - PostgreSQL reports the constraint name; it is matched against the names in
|
|
49
|
+
* the mapping (`unique: 'name'` on a property, `uniques[].name`) or, when none
|
|
50
|
+
* is declared, the naming strategy's `indexName`.
|
|
51
|
+
* - SQLite and libSQL report the `table.column` list; it is matched against the
|
|
52
|
+
* columns of each constraint.
|
|
53
|
+
*
|
|
54
|
+
* Any other error, an entity without metadata, or an unknown constraint yields
|
|
55
|
+
* `undefined`, so the decorator rethrows the original error.
|
|
56
|
+
*
|
|
57
|
+
* @throws {TypeError} On construction, when a multi-property unique constraint
|
|
58
|
+
* has no name, or two constraints of one entity cover the same columns.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* const orm = await MikroORM.init(options);
|
|
63
|
+
* setPersistenceDialect(new MikroOrmDialect(orm));
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
class MikroOrmDialect {
|
|
67
|
+
constraints = new Map();
|
|
68
|
+
metadata;
|
|
69
|
+
constructor(orm) {
|
|
70
|
+
const naming = orm.config.getNamingStrategy();
|
|
71
|
+
this.metadata = orm.getMetadata();
|
|
72
|
+
for (const meta of this.metadata.getAll().values()) {
|
|
73
|
+
if (!meta.tableName)
|
|
74
|
+
continue;
|
|
75
|
+
const constraints = constraintsOf(meta, naming);
|
|
76
|
+
assertDistinctColumns(meta, constraints);
|
|
77
|
+
this.constraints.set(meta, constraints);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
uniqueViolation(error, entity) {
|
|
81
|
+
if (!(error instanceof core_1.UniqueConstraintViolationException))
|
|
82
|
+
return undefined;
|
|
83
|
+
const meta = this.metadata.find(entity.constructor);
|
|
84
|
+
const constraints = meta ? this.constraints.get(meta) : undefined;
|
|
85
|
+
if (!constraints)
|
|
86
|
+
return undefined;
|
|
87
|
+
const { constraint } = error;
|
|
88
|
+
if (typeof constraint === 'string') {
|
|
89
|
+
return constraints.find(({ name }) => name === constraint)?.key;
|
|
90
|
+
}
|
|
91
|
+
const columns = SQLITE_COLUMNS.exec(error.message)?.[1].trim();
|
|
92
|
+
return constraints.find((unique) => unique.columns === columns)?.key;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.MikroOrmDialect = MikroOrmDialect;
|
|
96
|
+
//# sourceMappingURL=mikro-orm.dialect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mikro-orm.dialect.js","sourceRoot":"","sources":["../../src/errors/mikro-orm.dialect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistence-adapter classifier for driver/network failures that are reasonable
|
|
3
|
+
* to retry. This function is infrastructure-only; application handlers consume
|
|
4
|
+
* {@link TransientOperationError} instead of importing this classifier.
|
|
5
|
+
*
|
|
6
|
+
* An error is transient when its `code` is one of:
|
|
7
|
+
* - a retryable PostgreSQL SQLSTATE: serialization failure `40001`, deadlock
|
|
8
|
+
* `40P01`, lock not available `55P03`, shutdown `57P01`–`57P03`, or any code
|
|
9
|
+
* in the connection-exception (`08`) or insufficient-resource (`53`) class;
|
|
10
|
+
* - a Node network error: `ECONNREFUSED`, `ECONNRESET`, `EHOSTUNREACH`,
|
|
11
|
+
* `ENETUNREACH`, `EPIPE` or `ETIMEDOUT`;
|
|
12
|
+
* - `SQLITE_BUSY` or `SQLITE_LOCKED`;
|
|
13
|
+
*
|
|
14
|
+
* or when its `name` is `TaskCancelledError` or `TimeoutError`. A wrapped error
|
|
15
|
+
* is classified through its `cause` chain, which may be cyclic.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isTransientPersistenceError(error: unknown): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Translates persistence-specific transient failures into the neutral application
|
|
20
|
+
* retry signal. Non-transient failures are returned unchanged.
|
|
21
|
+
*
|
|
22
|
+
* This is the canonical `otherwise` translator for `@MapPersistenceErrors` and
|
|
23
|
+
* `@PersistedWrite` of `@cqrs-ddd/core`. Because non-transient errors keep their identity,
|
|
24
|
+
* domain errors a repository throws on purpose (`ConcurrencyConflictError`,
|
|
25
|
+
* `EntityNotFoundException`) pass through without a re-throw guard.
|
|
26
|
+
*
|
|
27
|
+
* @param error - The failure raised by the persistence operation.
|
|
28
|
+
* @param operation - What was being done, for the message, such as
|
|
29
|
+
* `` `deleting User ${user.id}` ``.
|
|
30
|
+
* @returns A {@link TransientOperationError} whose `cause` is `error`, or
|
|
31
|
+
* `error` itself when it is not transient.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* @MapPersistenceErrors<[User], User>({
|
|
36
|
+
* entity: ([user]) => user,
|
|
37
|
+
* otherwise: (error, user) =>
|
|
38
|
+
* mapPersistenceError(error, `deleting User ${user.id}`),
|
|
39
|
+
* })
|
|
40
|
+
* async save(user: User): Promise<null> { ... }
|
|
41
|
+
*
|
|
42
|
+
* // Outside the lifecycle decorators:
|
|
43
|
+
* try {
|
|
44
|
+
* return await em.findOne(Auth, { refreshTokenHash: hash }, { refresh: true });
|
|
45
|
+
* } catch (error) {
|
|
46
|
+
* throw mapPersistenceError(error, 'auth session lookup');
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function mapPersistenceError(error: unknown, operation: string): unknown;
|
|
51
|
+
//# sourceMappingURL=transient-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transient-error.d.ts","sourceRoot":"","sources":["../../src/errors/transient-error.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA6BnE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAOT"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.isTransientPersistenceError = isTransientPersistenceError;
|
|
5
|
+
exports.mapPersistenceError = mapPersistenceError;
|
|
6
|
+
const domain_1 = require("@cqrs-ddd/core/domain");
|
|
7
|
+
const TRANSIENT_CODES = new Set([
|
|
8
|
+
'40001', // PostgreSQL serialization failure
|
|
9
|
+
'40P01', // PostgreSQL deadlock
|
|
10
|
+
'55P03', // PostgreSQL lock not available
|
|
11
|
+
'57P01', // PostgreSQL admin shutdown
|
|
12
|
+
'57P02', // PostgreSQL crash shutdown
|
|
13
|
+
'57P03', // PostgreSQL cannot connect now
|
|
14
|
+
'ECONNREFUSED',
|
|
15
|
+
'ECONNRESET',
|
|
16
|
+
'EHOSTUNREACH',
|
|
17
|
+
'ENETUNREACH',
|
|
18
|
+
'EPIPE',
|
|
19
|
+
'ETIMEDOUT',
|
|
20
|
+
'SQLITE_BUSY',
|
|
21
|
+
'SQLITE_LOCKED',
|
|
22
|
+
]);
|
|
23
|
+
/**
|
|
24
|
+
* Persistence-adapter classifier for driver/network failures that are reasonable
|
|
25
|
+
* to retry. This function is infrastructure-only; application handlers consume
|
|
26
|
+
* {@link TransientOperationError} instead of importing this classifier.
|
|
27
|
+
*
|
|
28
|
+
* An error is transient when its `code` is one of:
|
|
29
|
+
* - a retryable PostgreSQL SQLSTATE: serialization failure `40001`, deadlock
|
|
30
|
+
* `40P01`, lock not available `55P03`, shutdown `57P01`–`57P03`, or any code
|
|
31
|
+
* in the connection-exception (`08`) or insufficient-resource (`53`) class;
|
|
32
|
+
* - a Node network error: `ECONNREFUSED`, `ECONNRESET`, `EHOSTUNREACH`,
|
|
33
|
+
* `ENETUNREACH`, `EPIPE` or `ETIMEDOUT`;
|
|
34
|
+
* - `SQLITE_BUSY` or `SQLITE_LOCKED`;
|
|
35
|
+
*
|
|
36
|
+
* or when its `name` is `TaskCancelledError` or `TimeoutError`. A wrapped error
|
|
37
|
+
* is classified through its `cause` chain, which may be cyclic.
|
|
38
|
+
*/
|
|
39
|
+
function isTransientPersistenceError(error) {
|
|
40
|
+
const seen = new Set();
|
|
41
|
+
let current = error;
|
|
42
|
+
while (current && typeof current === 'object' && !seen.has(current)) {
|
|
43
|
+
seen.add(current);
|
|
44
|
+
const candidate = current;
|
|
45
|
+
const code = typeof candidate.code === 'string' ? candidate.code : '';
|
|
46
|
+
if (TRANSIENT_CODES.has(code) ||
|
|
47
|
+
code.startsWith('08') || // PostgreSQL connection exception class
|
|
48
|
+
code.startsWith('53') // PostgreSQL insufficient-resource class
|
|
49
|
+
) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if (candidate.name === 'TaskCancelledError' ||
|
|
53
|
+
candidate.name === 'TimeoutError') {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
current = candidate.cause;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Translates persistence-specific transient failures into the neutral application
|
|
62
|
+
* retry signal. Non-transient failures are returned unchanged.
|
|
63
|
+
*
|
|
64
|
+
* This is the canonical `otherwise` translator for `@MapPersistenceErrors` and
|
|
65
|
+
* `@PersistedWrite` of `@cqrs-ddd/core`. Because non-transient errors keep their identity,
|
|
66
|
+
* domain errors a repository throws on purpose (`ConcurrencyConflictError`,
|
|
67
|
+
* `EntityNotFoundException`) pass through without a re-throw guard.
|
|
68
|
+
*
|
|
69
|
+
* @param error - The failure raised by the persistence operation.
|
|
70
|
+
* @param operation - What was being done, for the message, such as
|
|
71
|
+
* `` `deleting User ${user.id}` ``.
|
|
72
|
+
* @returns A {@link TransientOperationError} whose `cause` is `error`, or
|
|
73
|
+
* `error` itself when it is not transient.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* @MapPersistenceErrors<[User], User>({
|
|
78
|
+
* entity: ([user]) => user,
|
|
79
|
+
* otherwise: (error, user) =>
|
|
80
|
+
* mapPersistenceError(error, `deleting User ${user.id}`),
|
|
81
|
+
* })
|
|
82
|
+
* async save(user: User): Promise<null> { ... }
|
|
83
|
+
*
|
|
84
|
+
* // Outside the lifecycle decorators:
|
|
85
|
+
* try {
|
|
86
|
+
* return await em.findOne(Auth, { refreshTokenHash: hash }, { refresh: true });
|
|
87
|
+
* } catch (error) {
|
|
88
|
+
* throw mapPersistenceError(error, 'auth session lookup');
|
|
89
|
+
* }
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
function mapPersistenceError(error, operation) {
|
|
93
|
+
return isTransientPersistenceError(error)
|
|
94
|
+
? new domain_1.TransientOperationError(`Transient persistence failure while ${operation}.`, { cause: error })
|
|
95
|
+
: error;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=transient-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transient-error.js","sourceRoot":"","sources":["../../src/errors/transient-error.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAqCtE,kEA6BC;AAkCD,kDAUC;AA5GD,kDAAgE;AAEhE,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,OAAO,EAAE,mCAAmC;IAC5C,OAAO,EAAE,sBAAsB;IAC/B,OAAO,EAAE,gCAAgC;IACzC,OAAO,EAAE,4BAA4B;IACrC,OAAO,EAAE,4BAA4B;IACrC,OAAO,EAAE,gCAAgC;IACzC,cAAc;IACd,YAAY;IACZ,cAAc;IACd,aAAa;IACb,OAAO;IACP,WAAW;IACX,aAAa;IACb,eAAe;CAChB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,2BAA2B,CAAC,KAAc;IACxD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,OAAO,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClB,MAAM,SAAS,GAAG,OAIjB,CAAC;QACF,MAAM,IAAI,GAAG,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,IACE,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;YACzB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,wCAAwC;YACjE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,yCAAyC;UAC/D,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IACE,SAAS,CAAC,IAAI,KAAK,oBAAoB;YACvC,SAAS,CAAC,IAAI,KAAK,cAAc,EACjC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,SAAgB,mBAAmB,CACjC,KAAc,EACd,SAAiB;IAEjB,OAAO,2BAA2B,CAAC,KAAK,CAAC;QACvC,CAAC,CAAC,IAAI,gCAAuB,CACzB,uCAAuC,SAAS,GAAG,EACnD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB;QACH,CAAC,CAAC,KAAK,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Options for {@link isSqlIdentifier}. */
|
|
2
|
+
export interface SqlIdentifierOptions {
|
|
3
|
+
/** Also accept one `schema.` qualifier, as in `app.cache`. Default `false`. */
|
|
4
|
+
readonly qualified?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Whether `name` is an unquoted SQL identifier: a letter or underscore, then
|
|
8
|
+
* letters, digits or underscores. Use it before interpolating a name into SQL
|
|
9
|
+
* text, where it cannot be passed as a parameter.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* isSqlIdentifier('tenant_a'); // true
|
|
14
|
+
* isSqlIdentifier('tenant-a'); // false
|
|
15
|
+
* isSqlIdentifier('app.cache', { qualified: true }); // true
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function isSqlIdentifier(name: string, options?: SqlIdentifierOptions): boolean;
|
|
19
|
+
//# sourceMappingURL=sql-identifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-identifier.d.ts","sourceRoot":"","sources":["../../src/helpers/sql-identifier.ts"],"names":[],"mappings":"AAMA,2CAA2C;AAC3C,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAET"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.isSqlIdentifier = isSqlIdentifier;
|
|
5
|
+
const NAME = '[A-Za-z_][A-Za-z0-9_]*';
|
|
6
|
+
const UNQUALIFIED = new RegExp(`^${NAME}$`);
|
|
7
|
+
const QUALIFIED = new RegExp(`^${NAME}(\\.${NAME})?$`);
|
|
8
|
+
/**
|
|
9
|
+
* Whether `name` is an unquoted SQL identifier: a letter or underscore, then
|
|
10
|
+
* letters, digits or underscores. Use it before interpolating a name into SQL
|
|
11
|
+
* text, where it cannot be passed as a parameter.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* isSqlIdentifier('tenant_a'); // true
|
|
16
|
+
* isSqlIdentifier('tenant-a'); // false
|
|
17
|
+
* isSqlIdentifier('app.cache', { qualified: true }); // true
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
function isSqlIdentifier(name, options = {}) {
|
|
21
|
+
return (options.qualified ? QUALIFIED : UNQUALIFIED).test(name);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=sql-identifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-identifier.js","sourceRoot":"","sources":["../../src/helpers/sql-identifier.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAwBtE,0CAKC;AA3BD,MAAM,IAAI,GAAG,wBAAwB,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;AAC5C,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,CAAC,CAAC;AAQvD;;;;;;;;;;;GAWG;AACH,SAAgB,eAAe,CAC7B,IAAY,EACZ,UAAgC,EAAE;IAElC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from './cache/cache-entry';
|
|
2
|
+
export * from './cache/mikro-orm.cache';
|
|
3
|
+
export * from './concurrency/assert-autocommit';
|
|
4
|
+
export * from './concurrency/optimistic-delete';
|
|
5
|
+
export * from './concurrency/optimistic-update';
|
|
6
|
+
export * from './errors/mikro-orm.dialect';
|
|
7
|
+
export * from './errors/transient-error';
|
|
8
|
+
export * from './helpers/sql-identifier';
|
|
9
|
+
export * from './interfaces/entity-manager-source';
|
|
10
|
+
export * from './mapping/root-entity.properties';
|
|
11
|
+
export * from './mapping/unix-timestamp.type';
|
|
12
|
+
export * from './repository/aggregate.repository';
|
|
13
|
+
export * from './tenancy/tenant-store';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,wBAAwB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
__exportStar(require("./cache/cache-entry"), exports);
|
|
19
|
+
__exportStar(require("./cache/mikro-orm.cache"), exports);
|
|
20
|
+
__exportStar(require("./concurrency/assert-autocommit"), exports);
|
|
21
|
+
__exportStar(require("./concurrency/optimistic-delete"), exports);
|
|
22
|
+
__exportStar(require("./concurrency/optimistic-update"), exports);
|
|
23
|
+
__exportStar(require("./errors/mikro-orm.dialect"), exports);
|
|
24
|
+
__exportStar(require("./errors/transient-error"), exports);
|
|
25
|
+
__exportStar(require("./helpers/sql-identifier"), exports);
|
|
26
|
+
__exportStar(require("./interfaces/entity-manager-source"), exports);
|
|
27
|
+
__exportStar(require("./mapping/root-entity.properties"), exports);
|
|
28
|
+
__exportStar(require("./mapping/unix-timestamp.type"), exports);
|
|
29
|
+
__exportStar(require("./repository/aggregate.repository"), exports);
|
|
30
|
+
__exportStar(require("./tenancy/tenant-store"), exports);
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;;;;;;;;;;;;;;AAEtE,sDAAoC;AACpC,0DAAwC;AACxC,kEAAgD;AAChD,kEAAgD;AAChD,kEAAgD;AAChD,6DAA2C;AAC3C,2DAAyC;AACzC,2DAAyC;AACzC,qEAAmD;AACnD,mEAAiD;AACjD,gEAA8C;AAC9C,oEAAkD;AAClD,yDAAuC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/core';
|
|
2
|
+
/**
|
|
3
|
+
* Supplies the MikroORM `EntityManager` for the current operation.
|
|
4
|
+
*
|
|
5
|
+
* {@link AggregateRepository} and {@link MikroOrmCache} read `em` on every
|
|
6
|
+
* operation and never keep it, so a source may return a different manager each
|
|
7
|
+
* time: the current tenant's in a multi-tenant application, or the current
|
|
8
|
+
* request's. A getter over the application's own store satisfies it, and so
|
|
9
|
+
* does a plain `{ em }` object in a single-database setup or a test.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const source: IEntityManagerSource = { em: orm.em.fork() };
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export interface IEntityManagerSource {
|
|
17
|
+
readonly em: EntityManager;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=entity-manager-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-manager-source.d.ts","sourceRoot":"","sources":["../../src/interfaces/entity-manager-source.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-manager-source.js","sourceRoot":"","sources":["../../src/interfaces/entity-manager-source.ts"],"names":[],"mappings":";AAAA,sEAAsE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { UnixTimestampType } from './unix-timestamp.type';
|
|
2
|
+
/** Column names for the {@link rootEntityProperties} mapping. */
|
|
3
|
+
export interface RootEntityColumns {
|
|
4
|
+
/** Default `'id'`. */
|
|
5
|
+
readonly id?: string;
|
|
6
|
+
/** Default `'created_at'`. */
|
|
7
|
+
readonly createdAt?: string;
|
|
8
|
+
/** Default `'updated_at'`. */
|
|
9
|
+
readonly updatedAt?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Identity and timestamp columns shared by every `RootEntity` schema, mapped
|
|
13
|
+
* through the entity's private hydration setters (`accessor: true`). Timestamps
|
|
14
|
+
* are stored as epoch milliseconds through {@link UnixTimestampType}. Returns
|
|
15
|
+
* fresh property definitions for each schema.
|
|
16
|
+
*
|
|
17
|
+
* @param columns - Column names that differ from the defaults.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* export const UserSchema = new EntitySchema<User, AggregateRoot>({
|
|
22
|
+
* class: User as any,
|
|
23
|
+
* tableName: 'users',
|
|
24
|
+
* properties: {
|
|
25
|
+
* ...rootEntityProperties(),
|
|
26
|
+
* version: versionProperty(),
|
|
27
|
+
* email: { type: 'string', unique: true },
|
|
28
|
+
* },
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function rootEntityProperties(columns?: RootEntityColumns): {
|
|
33
|
+
readonly id: {
|
|
34
|
+
readonly type: "string";
|
|
35
|
+
readonly primary: true;
|
|
36
|
+
readonly fieldName: string;
|
|
37
|
+
readonly accessor: true;
|
|
38
|
+
};
|
|
39
|
+
readonly createdAt: {
|
|
40
|
+
readonly type: typeof UnixTimestampType;
|
|
41
|
+
readonly fieldName: string;
|
|
42
|
+
readonly accessor: true;
|
|
43
|
+
};
|
|
44
|
+
readonly updatedAt: {
|
|
45
|
+
readonly type: typeof UnixTimestampType;
|
|
46
|
+
readonly fieldName: string;
|
|
47
|
+
readonly accessor: true;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Optimistic-concurrency version column for aggregates written with version
|
|
52
|
+
* checks. New rows start at version 1, matching a new `RootEntity`.
|
|
53
|
+
*
|
|
54
|
+
* @param column - Column name. Default `'version'`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function versionProperty(column?: string): {
|
|
57
|
+
readonly type: "number";
|
|
58
|
+
readonly fieldName: string;
|
|
59
|
+
readonly default: 1;
|
|
60
|
+
readonly accessor: true;
|
|
61
|
+
readonly version: true;
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=root-entity.properties.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-entity.properties.d.ts","sourceRoot":"","sources":["../../src/mapping/root-entity.properties.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,sBAAsB;IACtB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,iBAAsB;;;;;;;;;;;;;;;;;EAmBnE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,SAAY;;;;;;EAQjD"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.rootEntityProperties = rootEntityProperties;
|
|
5
|
+
exports.versionProperty = versionProperty;
|
|
6
|
+
const unix_timestamp_type_1 = require("./unix-timestamp.type");
|
|
7
|
+
/**
|
|
8
|
+
* Identity and timestamp columns shared by every `RootEntity` schema, mapped
|
|
9
|
+
* through the entity's private hydration setters (`accessor: true`). Timestamps
|
|
10
|
+
* are stored as epoch milliseconds through {@link UnixTimestampType}. Returns
|
|
11
|
+
* fresh property definitions for each schema.
|
|
12
|
+
*
|
|
13
|
+
* @param columns - Column names that differ from the defaults.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* export const UserSchema = new EntitySchema<User, AggregateRoot>({
|
|
18
|
+
* class: User as any,
|
|
19
|
+
* tableName: 'users',
|
|
20
|
+
* properties: {
|
|
21
|
+
* ...rootEntityProperties(),
|
|
22
|
+
* version: versionProperty(),
|
|
23
|
+
* email: { type: 'string', unique: true },
|
|
24
|
+
* },
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
function rootEntityProperties(columns = {}) {
|
|
29
|
+
return {
|
|
30
|
+
id: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
primary: true,
|
|
33
|
+
fieldName: columns.id ?? 'id',
|
|
34
|
+
accessor: true,
|
|
35
|
+
},
|
|
36
|
+
createdAt: {
|
|
37
|
+
type: unix_timestamp_type_1.UnixTimestampType,
|
|
38
|
+
fieldName: columns.createdAt ?? 'created_at',
|
|
39
|
+
accessor: true,
|
|
40
|
+
},
|
|
41
|
+
updatedAt: {
|
|
42
|
+
type: unix_timestamp_type_1.UnixTimestampType,
|
|
43
|
+
fieldName: columns.updatedAt ?? 'updated_at',
|
|
44
|
+
accessor: true,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Optimistic-concurrency version column for aggregates written with version
|
|
50
|
+
* checks. New rows start at version 1, matching a new `RootEntity`.
|
|
51
|
+
*
|
|
52
|
+
* @param column - Column name. Default `'version'`.
|
|
53
|
+
*/
|
|
54
|
+
function versionProperty(column = 'version') {
|
|
55
|
+
return {
|
|
56
|
+
type: 'number',
|
|
57
|
+
fieldName: column,
|
|
58
|
+
default: 1,
|
|
59
|
+
accessor: true,
|
|
60
|
+
version: true,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=root-entity.properties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-entity.properties.js","sourceRoot":"","sources":["../../src/mapping/root-entity.properties.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAmCtE,oDAmBC;AAQD,0CAQC;AApED,+DAA0D;AAY1D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,oBAAoB,CAAC,UAA6B,EAAE;IAClE,OAAO;QACL,EAAE,EAAE;YACF,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,OAAO,CAAC,EAAE,IAAI,IAAI;YAC7B,QAAQ,EAAE,IAAI;SACf;QACD,SAAS,EAAE;YACT,IAAI,EAAE,uCAAiB;YACvB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,YAAY;YAC5C,QAAQ,EAAE,IAAI;SACf;QACD,SAAS,EAAE;YACT,IAAI,EAAE,uCAAiB;YACvB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,YAAY;YAC5C,QAAQ,EAAE,IAAI;SACf;KACO,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,MAAM,GAAG,SAAS;IAChD,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,MAAM;QACjB,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,IAAI;KACL,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type EntityProperty, Platform, type TransformContext, Type } from '@mikro-orm/core';
|
|
2
|
+
type Timestamp = Date | number | string | bigint;
|
|
3
|
+
/**
|
|
4
|
+
* MikroORM type that stores a `Date` as epoch milliseconds in a 64-bit `bigint`
|
|
5
|
+
* column.
|
|
6
|
+
*
|
|
7
|
+
* `null` and `undefined` pass through in both directions. A value that has no
|
|
8
|
+
* valid time throws a `TypeError` rather than being stored or returned as
|
|
9
|
+
* `NaN`.
|
|
10
|
+
*/
|
|
11
|
+
export declare class UnixTimestampType extends Type<Date | null | undefined, number | null | undefined> {
|
|
12
|
+
convertToDatabaseValue(value: Timestamp | null | undefined, _platform?: Platform, _context?: TransformContext): number | null | undefined;
|
|
13
|
+
convertToJSValue(value: Timestamp | null | undefined, _platform?: Platform, _context?: TransformContext): Date | null | undefined;
|
|
14
|
+
getColumnType(prop?: EntityProperty, platform?: Platform): string;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=unix-timestamp.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unix-timestamp.type.d.ts","sourceRoot":"","sources":["../../src/mapping/unix-timestamp.type.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,cAAc,EACnB,QAAQ,EACR,KAAK,gBAAgB,EACrB,IAAI,EACL,MAAM,iBAAiB,CAAC;AAEzB,KAAK,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AA0BjD;;;;;;;GAOG;AACH,qBAAa,iBAAkB,SAAQ,IAAI,CACzC,IAAI,GAAG,IAAI,GAAG,SAAS,EACvB,MAAM,GAAG,IAAI,GAAG,SAAS,CAC1B;IACC,sBAAsB,CACpB,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,EACnC,SAAS,CAAC,EAAE,QAAQ,EACpB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,MAAM,GAAG,IAAI,GAAG,SAAS;IAK5B,gBAAgB,CACd,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,EACnC,SAAS,CAAC,EAAE,QAAQ,EACpB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,IAAI,GAAG,IAAI,GAAG,SAAS;IAM1B,aAAa,CACX,IAAI,GAAE,cAAqC,EAC3C,QAAQ,CAAC,EAAE,QAAQ,GAClB,MAAM;CAGV"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnixTimestampType = void 0;
|
|
4
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
5
|
+
const core_1 = require("@mikro-orm/core");
|
|
6
|
+
/**
|
|
7
|
+
* Converts a timestamp value to epoch milliseconds, or throws.
|
|
8
|
+
*
|
|
9
|
+
* A number, a bigint, a numeric string, a date string and a `Date` are read. A
|
|
10
|
+
* blank string, `NaN`, an infinite number, an unparsable string, an invalid
|
|
11
|
+
* `Date` and any other value have no valid time.
|
|
12
|
+
*/
|
|
13
|
+
function toEpochMilliseconds(value) {
|
|
14
|
+
let milliseconds = Number.NaN;
|
|
15
|
+
if (value instanceof Date)
|
|
16
|
+
milliseconds = value.getTime();
|
|
17
|
+
else if (typeof value === 'number')
|
|
18
|
+
milliseconds = value;
|
|
19
|
+
else if (typeof value === 'bigint')
|
|
20
|
+
milliseconds = Number(value);
|
|
21
|
+
else if (typeof value === 'string' && value.trim() !== '') {
|
|
22
|
+
const numeric = Number(value);
|
|
23
|
+
milliseconds = Number.isNaN(numeric) ? Date.parse(value) : numeric;
|
|
24
|
+
}
|
|
25
|
+
if (!Number.isFinite(milliseconds)) {
|
|
26
|
+
throw new TypeError(`UnixTimestampType cannot read ${typeof value} value ${JSON.stringify(String(value))} as a timestamp.`);
|
|
27
|
+
}
|
|
28
|
+
return milliseconds;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* MikroORM type that stores a `Date` as epoch milliseconds in a 64-bit `bigint`
|
|
32
|
+
* column.
|
|
33
|
+
*
|
|
34
|
+
* `null` and `undefined` pass through in both directions. A value that has no
|
|
35
|
+
* valid time throws a `TypeError` rather than being stored or returned as
|
|
36
|
+
* `NaN`.
|
|
37
|
+
*/
|
|
38
|
+
class UnixTimestampType extends core_1.Type {
|
|
39
|
+
convertToDatabaseValue(value, _platform, _context) {
|
|
40
|
+
if (value == null)
|
|
41
|
+
return value;
|
|
42
|
+
return toEpochMilliseconds(value);
|
|
43
|
+
}
|
|
44
|
+
convertToJSValue(value, _platform, _context) {
|
|
45
|
+
if (value == null)
|
|
46
|
+
return value;
|
|
47
|
+
const milliseconds = toEpochMilliseconds(value);
|
|
48
|
+
return value instanceof Date ? value : new Date(milliseconds);
|
|
49
|
+
}
|
|
50
|
+
getColumnType(prop = {}, platform) {
|
|
51
|
+
return platform ? platform.getBigIntTypeDeclarationSQL(prop) : 'bigint';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.UnixTimestampType = UnixTimestampType;
|
|
55
|
+
//# sourceMappingURL=unix-timestamp.type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unix-timestamp.type.js","sourceRoot":"","sources":["../../src/mapping/unix-timestamp.type.ts"],"names":[],"mappings":";;;AAAA,sEAAsE;AACtE,0CAKyB;AAIzB;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,KAAc;IACzC,IAAI,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC;IAC9B,IAAI,KAAK,YAAY,IAAI;QAAE,YAAY,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;SACrD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,YAAY,GAAG,KAAK,CAAC;SACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;SAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACrE,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,SAAS,CACjB,iCAAiC,OAAO,KAAK,UAAU,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,kBAAkB,CACvG,CAAC;IACJ,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;;;;GAOG;AACH,MAAa,iBAAkB,SAAQ,WAGtC;IACC,sBAAsB,CACpB,KAAmC,EACnC,SAAoB,EACpB,QAA2B;QAE3B,IAAI,KAAK,IAAI,IAAI;YAAE,OAAO,KAAK,CAAC;QAChC,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,gBAAgB,CACd,KAAmC,EACnC,SAAoB,EACpB,QAA2B;QAE3B,IAAI,KAAK,IAAI,IAAI;YAAE,OAAO,KAAK,CAAC;QAChC,MAAM,YAAY,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAChD,OAAO,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC;IAChE,CAAC;IAED,aAAa,CACX,OAAuB,EAAoB,EAC3C,QAAmB;QAEnB,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC1E,CAAC;CACF;AA7BD,8CA6BC"}
|