ts-prorm-orm 1.1.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/CHANGELOG.md +1111 -0
- package/LICENSE +21 -0
- package/README.md +573 -0
- package/dist/audit/history-query.js +180 -0
- package/dist/audit/index.js +23 -0
- package/dist/audit/logger.js +236 -0
- package/dist/cache/cache-manager.js +84 -0
- package/dist/cache/index.js +16 -0
- package/dist/cache/redis-cluster-cache.js +557 -0
- package/dist/cli.js +2200 -0
- package/dist/compliance/audit-trail.js +68 -0
- package/dist/compliance/backup-verification.js +685 -0
- package/dist/compliance/breach-detector.js +505 -0
- package/dist/compliance/consent-record.js +227 -0
- package/dist/compliance/consent-versioning.js +331 -0
- package/dist/compliance/cross-border-log.js +530 -0
- package/dist/compliance/data-classifier.js +258 -0
- package/dist/compliance/data-lineage.js +565 -0
- package/dist/compliance/data-masker.js +303 -0
- package/dist/compliance/data-portability.js +265 -0
- package/dist/compliance/data-retention.js +195 -0
- package/dist/compliance/dsar-workflow.js +342 -0
- package/dist/compliance/field-encryption.js +223 -0
- package/dist/compliance/immutable-record.js +148 -0
- package/dist/compliance/index.js +260 -0
- package/dist/compliance/privacy-impact-assessment.js +364 -0
- package/dist/compliance/pseudonymization.js +269 -0
- package/dist/compliance/query-firewall.js +1182 -0
- package/dist/compliance/rate-limiter.js +580 -0
- package/dist/compliance/right-to-erasure.js +117 -0
- package/dist/compliance/row-level-security.js +246 -0
- package/dist/compliance/security-decorator.js +574 -0
- package/dist/compliance/security-monitor.js +525 -0
- package/dist/compliance/sensitive-data-discovery.js +476 -0
- package/dist/compliance/session-isolation.js +472 -0
- package/dist/compliance/tls-enforcer.js +108 -0
- package/dist/compliance/worm-storage.js +712 -0
- package/dist/connection-manager.js +198 -0
- package/dist/connection-pool.js +519 -0
- package/dist/decorators/audit.js +136 -0
- package/dist/decorators/belongs-to-many.js +115 -0
- package/dist/decorators/belongs-to.js +115 -0
- package/dist/decorators/check.js +435 -0
- package/dist/decorators/collate.js +329 -0
- package/dist/decorators/comment.js +205 -0
- package/dist/decorators/database-settings.js +236 -0
- package/dist/decorators/default.js +244 -0
- package/dist/decorators/encryption.js +235 -0
- package/dist/decorators/engine.js +97 -0
- package/dist/decorators/fk-constraints.js +594 -0
- package/dist/decorators/foreign-table.js +136 -0
- package/dist/decorators/generated.js +274 -0
- package/dist/decorators/has-many.js +127 -0
- package/dist/decorators/has-one.js +116 -0
- package/dist/decorators/hstore.js +129 -0
- package/dist/decorators/index.js +355 -0
- package/dist/decorators/json-column.js +83 -0
- package/dist/decorators/jsonb.js +101 -0
- package/dist/decorators/orm-decorators.js +425 -0
- package/dist/decorators/permissions.js +294 -0
- package/dist/decorators/procedure.js +210 -0
- package/dist/decorators/query-options.js +556 -0
- package/dist/decorators/range.js +167 -0
- package/dist/decorators/set-column.js +83 -0
- package/dist/decorators/spatial.js +114 -0
- package/dist/decorators/storage.js +580 -0
- package/dist/decorators/timezone.js +512 -0
- package/dist/decorators/trigger.js +90 -0
- package/dist/decorators/uuid.js +135 -0
- package/dist/decorators/view.js +258 -0
- package/dist/diagrams/chen-diagram.js +354 -0
- package/dist/diagrams/class-diagram.js +384 -0
- package/dist/diagrams/dependency-diagram.js +432 -0
- package/dist/diagrams/er-diagram.js +605 -0
- package/dist/diagrams/flow-diagram.js +394 -0
- package/dist/diagrams/gantt-diagram.js +411 -0
- package/dist/diagrams/index-diagram.js +353 -0
- package/dist/diagrams/index.js +184 -0
- package/dist/diagrams/migration-diagram.js +316 -0
- package/dist/diagrams/model-diagram.js +616 -0
- package/dist/diagrams/package-diagram.js +376 -0
- package/dist/diagrams/palette.js +85 -0
- package/dist/diagrams/relational-diagram.js +455 -0
- package/dist/diagrams/schemadoc-diagram.js +309 -0
- package/dist/diagrams/sequence-diagram.js +307 -0
- package/dist/diagrams/state-diagram.js +344 -0
- package/dist/diagrams/svg-dom.js +111 -0
- package/dist/diagrams/tree-diagram.js +250 -0
- package/dist/dialects/clickhouse/index.js +1742 -0
- package/dist/dialects/cockroachdb/index.js +4677 -0
- package/dist/dialects/cratedb/index.js +441 -0
- package/dist/dialects/databricks/index.js +517 -0
- package/dist/dialects/db2/index.js +2225 -0
- package/dist/dialects/dialect.js +720 -0
- package/dist/dialects/duckdb/index.js +2014 -0
- package/dist/dialects/exasol/index.js +357 -0
- package/dist/dialects/firebird/index.js +495 -0
- package/dist/dialects/greenplum/index.js +457 -0
- package/dist/dialects/hana/index.js +1741 -0
- package/dist/dialects/mariadb/index.js +3590 -0
- package/dist/dialects/mssql/index.js +2296 -0
- package/dist/dialects/mysql/index.js +4058 -0
- package/dist/dialects/oracle/index.js +2999 -0
- package/dist/dialects/postgres/index.js +5319 -0
- package/dist/dialects/query-stream-helper.js +152 -0
- package/dist/dialects/questdb/index.js +433 -0
- package/dist/dialects/redshift/index.js +2277 -0
- package/dist/dialects/singlestore/index.js +354 -0
- package/dist/dialects/snowflake/index.js +2082 -0
- package/dist/dialects/spanner/index.js +1768 -0
- package/dist/dialects/sqlite/index.js +3382 -0
- package/dist/dialects/tidb/index.js +377 -0
- package/dist/dialects/timescaledb/index.js +164 -0
- package/dist/dialects/trino/index.js +420 -0
- package/dist/dialects/turso/index.js +227 -0
- package/dist/dialects/vertica/index.js +317 -0
- package/dist/dialects/yugabytedb/index.js +424 -0
- package/dist/errors/index.js +472 -0
- package/dist/errors/utils.js +340 -0
- package/dist/errors.js +21 -0
- package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
- package/dist/extensions/catalog/mssql-features.js +147 -0
- package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
- package/dist/extensions/catalog/oracle-db2-features.js +196 -0
- package/dist/extensions/catalog/postgres-extensions.js +516 -0
- package/dist/extensions/index.js +71 -0
- package/dist/extensions/types.js +13 -0
- package/dist/foreign-data.js +173 -0
- package/dist/hooks/hooks-manager.js +350 -0
- package/dist/hooks/index.js +37 -0
- package/dist/index.js +463 -0
- package/dist/logging.js +335 -0
- package/dist/migrations/index.js +40 -0
- package/dist/migrations/migration.js +196 -0
- package/dist/migrations/migrator.js +411 -0
- package/dist/migrations/prormmigration.js +275 -0
- package/dist/migrations/query-interface.js +435 -0
- package/dist/migrations/seeder.js +353 -0
- package/dist/models/associations.js +852 -0
- package/dist/models/constraints.js +288 -0
- package/dist/models/data-types.js +2518 -0
- package/dist/models/decorators.js +445 -0
- package/dist/models/index.js +33 -0
- package/dist/models/indexes.js +531 -0
- package/dist/models/methods.js +382 -0
- package/dist/models/model-manager.js +103 -0
- package/dist/models/model.js +5349 -0
- package/dist/models/operators.js +67 -0
- package/dist/models/scopes.js +189 -0
- package/dist/models/typescript-types.js +26 -0
- package/dist/nosql/aerospike/index.js +205 -0
- package/dist/nosql/allegrograph/index.js +169 -0
- package/dist/nosql/arangodb/index.js +364 -0
- package/dist/nosql/azure-blob/index.js +206 -0
- package/dist/nosql/beanstalkd/index.js +231 -0
- package/dist/nosql/beequeue/index.js +210 -0
- package/dist/nosql/bigchaindb/index.js +195 -0
- package/dist/nosql/bigtable/index.js +224 -0
- package/dist/nosql/blazegraph/index.js +173 -0
- package/dist/nosql/bullmq/index.js +191 -0
- package/dist/nosql/cassandra/index.js +174 -0
- package/dist/nosql/chroma/index.js +190 -0
- package/dist/nosql/cloudflare-kv/index.js +220 -0
- package/dist/nosql/coherence/index.js +200 -0
- package/dist/nosql/cosmosdb/index.js +157 -0
- package/dist/nosql/couchbase/index.js +213 -0
- package/dist/nosql/dax/index.js +212 -0
- package/dist/nosql/deno-kv/index.js +206 -0
- package/dist/nosql/dgraph/index.js +171 -0
- package/dist/nosql/doris/index.js +169 -0
- package/dist/nosql/druid/index.js +162 -0
- package/dist/nosql/dynamodb/index.js +937 -0
- package/dist/nosql/elasticsearch/index.js +377 -0
- package/dist/nosql/etcd/index.js +502 -0
- package/dist/nosql/eventhubs/index.js +213 -0
- package/dist/nosql/eventstore/index.js +254 -0
- package/dist/nosql/faunadb/index.js +188 -0
- package/dist/nosql/firestore/index.js +177 -0
- package/dist/nosql/fluree/index.js +148 -0
- package/dist/nosql/fuseki/index.js +170 -0
- package/dist/nosql/gcs/index.js +172 -0
- package/dist/nosql/gearman/index.js +160 -0
- package/dist/nosql/geode/index.js +196 -0
- package/dist/nosql/graphdb/index.js +169 -0
- package/dist/nosql/graylog/index.js +188 -0
- package/dist/nosql/gridgain/index.js +171 -0
- package/dist/nosql/hazelcast/index.js +162 -0
- package/dist/nosql/hbase/index.js +230 -0
- package/dist/nosql/ignite/index.js +173 -0
- package/dist/nosql/immudb/index.js +184 -0
- package/dist/nosql/index.js +232 -0
- package/dist/nosql/infinispan/index.js +200 -0
- package/dist/nosql/influxdb/index.js +0 -0
- package/dist/nosql/kafka/index.js +234 -0
- package/dist/nosql/keyspaces/index.js +189 -0
- package/dist/nosql/kinesis/index.js +253 -0
- package/dist/nosql/leveldb/index.js +153 -0
- package/dist/nosql/lmdb/index.js +160 -0
- package/dist/nosql/loki/index.js +201 -0
- package/dist/nosql/marklogic/index.js +204 -0
- package/dist/nosql/materialize/index.js +145 -0
- package/dist/nosql/meilisearch/index.js +154 -0
- package/dist/nosql/memcached/index.js +223 -0
- package/dist/nosql/milvus/index.js +410 -0
- package/dist/nosql/minio/index.js +265 -0
- package/dist/nosql/momento/index.js +179 -0
- package/dist/nosql/mongodb/index.js +461 -0
- package/dist/nosql/nats/index.js +247 -0
- package/dist/nosql/nedb/index.js +164 -0
- package/dist/nosql/neo4j/index.js +450 -0
- package/dist/nosql/neptune/index.js +470 -0
- package/dist/nosql/nsq/index.js +200 -0
- package/dist/nosql/opensearch/index.js +186 -0
- package/dist/nosql/orientdb/index.js +175 -0
- package/dist/nosql/papertrail/index.js +200 -0
- package/dist/nosql/pinecone/index.js +0 -0
- package/dist/nosql/pinot/index.js +133 -0
- package/dist/nosql/pouchdb/index.js +172 -0
- package/dist/nosql/prometheus/index.js +174 -0
- package/dist/nosql/provendb/index.js +147 -0
- package/dist/nosql/pubsub/index.js +187 -0
- package/dist/nosql/pulsar/index.js +232 -0
- package/dist/nosql/qdrant/index.js +295 -0
- package/dist/nosql/qldb/index.js +192 -0
- package/dist/nosql/r2/index.js +281 -0
- package/dist/nosql/rabbitmq/index.js +237 -0
- package/dist/nosql/ravendb/index.js +175 -0
- package/dist/nosql/redis/index.js +607 -0
- package/dist/nosql/redpanda/index.js +237 -0
- package/dist/nosql/resque/index.js +203 -0
- package/dist/nosql/rethinkdb/index.js +232 -0
- package/dist/nosql/rocksdb/index.js +152 -0
- package/dist/nosql/rockset/index.js +126 -0
- package/dist/nosql/s3/index.js +298 -0
- package/dist/nosql/scylladb/index.js +178 -0
- package/dist/nosql/signoz/index.js +227 -0
- package/dist/nosql/sns/index.js +201 -0
- package/dist/nosql/solr/index.js +231 -0
- package/dist/nosql/splunk/index.js +227 -0
- package/dist/nosql/sqs/index.js +246 -0
- package/dist/nosql/stardog/index.js +169 -0
- package/dist/nosql/starrocks/index.js +170 -0
- package/dist/nosql/store.js +2 -0
- package/dist/nosql/sumologic/index.js +213 -0
- package/dist/nosql/surrealdb/index.js +179 -0
- package/dist/nosql/terminusdb/index.js +151 -0
- package/dist/nosql/tigergraph/index.js +469 -0
- package/dist/nosql/typesense/index.js +148 -0
- package/dist/nosql/unqlite/index.js +157 -0
- package/dist/nosql/upstash/index.js +167 -0
- package/dist/nosql/vercel-kv/index.js +166 -0
- package/dist/nosql/victoriametrics/index.js +213 -0
- package/dist/nosql/virtuoso/index.js +169 -0
- package/dist/nosql/weaviate/index.js +276 -0
- package/dist/operators/index.js +108 -0
- package/dist/operators.js +2690 -0
- package/dist/prisma-migrate/index.js +38 -0
- package/dist/prisma-migrate/migration-generator.js +125 -0
- package/dist/prisma-migrate/model-generator.js +172 -0
- package/dist/prisma-migrate/relations.js +100 -0
- package/dist/prisma-migrate/schema-parser.js +167 -0
- package/dist/prisma-migrate/type-mapper.js +40 -0
- package/dist/prorm.js +6832 -0
- package/dist/query-builders/cte-builder.js +80 -0
- package/dist/query-builders/functions/aggregate.js +390 -0
- package/dist/query-builders/functions/conditional.js +503 -0
- package/dist/query-builders/functions/datetime.js +695 -0
- package/dist/query-builders/functions/fulltext.js +439 -0
- package/dist/query-builders/functions/index.js +93 -0
- package/dist/query-builders/functions/json.js +427 -0
- package/dist/query-builders/functions/math.js +399 -0
- package/dist/query-builders/functions/string.js +518 -0
- package/dist/query-builders/functions/window.js +328 -0
- package/dist/query-builders/include-builder.js +323 -0
- package/dist/query-builders/index-expression-builder.js +242 -0
- package/dist/query-builders/index.js +161 -0
- package/dist/query-builders/insert-builder.js +164 -0
- package/dist/query-builders/model-helpers.js +38 -0
- package/dist/query-builders/order-limit-builder.js +239 -0
- package/dist/query-builders/sql-compiler.js +2040 -0
- package/dist/query-builders/subquery-builder.js +152 -0
- package/dist/query-builders/update-builder.js +182 -0
- package/dist/query-builders/view-builder.js +218 -0
- package/dist/query-builders/where-builder.js +1532 -0
- package/dist/query-interface.js +622 -0
- package/dist/query-optimizers/batch-optimizer.js +426 -0
- package/dist/query-optimizers/explain-plans.js +415 -0
- package/dist/query-optimizers/index.js +51 -0
- package/dist/query-optimizers/prepared-statement-cache.js +423 -0
- package/dist/query-optimizers/query-hints.js +438 -0
- package/dist/query-optimizers/query-optimizer.js +278 -0
- package/dist/query-optimizers/slow-query-logger.js +271 -0
- package/dist/replica-manager.js +507 -0
- package/dist/schema/index.js +15 -0
- package/dist/schema/migration-generator.js +374 -0
- package/dist/schema/schema-differ.js +549 -0
- package/dist/schema/types.js +6 -0
- package/dist/sql-constants.js +300 -0
- package/dist/sqlite-advanced.js +1047 -0
- package/dist/streams/index.js +12 -0
- package/dist/streams/transforms.js +178 -0
- package/dist/transaction.js +456 -0
- package/dist/types/index.js +180 -0
- package/dist/user-management.js +127 -0
- package/dist/utils/date.js +300 -0
- package/dist/utils/index.js +1079 -0
- package/dist/utils/string.js +161 -0
- package/dist/validators/index.js +19 -0
- package/dist/validators/validator.js +911 -0
- package/package.json +190 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ForeignTableRegistry = void 0;
|
|
4
|
+
exports.setForeignTableRedisClient = setForeignTableRedisClient;
|
|
5
|
+
exports.getForeignTableRedisClient = getForeignTableRedisClient;
|
|
6
|
+
exports.ForeignTable = ForeignTable;
|
|
7
|
+
exports.getForeignTableOptions = getForeignTableOptions;
|
|
8
|
+
exports.isForeignTable = isForeignTable;
|
|
9
|
+
exports.cacheForeignTableOptions = cacheForeignTableOptions;
|
|
10
|
+
exports.getCachedForeignTableOptions = getCachedForeignTableOptions;
|
|
11
|
+
exports.invalidateForeignTableCache = invalidateForeignTableCache;
|
|
12
|
+
exports.warmupForeignTableCache = warmupForeignTableCache;
|
|
13
|
+
let globalRedisClient = null;
|
|
14
|
+
function setForeignTableRedisClient(client) {
|
|
15
|
+
globalRedisClient = client;
|
|
16
|
+
}
|
|
17
|
+
function getForeignTableRedisClient() {
|
|
18
|
+
return globalRedisClient;
|
|
19
|
+
}
|
|
20
|
+
const FOREIGN_TABLE_KEY = '__orm_foreign_table__';
|
|
21
|
+
function ForeignTable(options) {
|
|
22
|
+
return function (target) {
|
|
23
|
+
const resolved = {
|
|
24
|
+
server: options.server,
|
|
25
|
+
foreignSchema: options.foreignSchema,
|
|
26
|
+
options: options.options,
|
|
27
|
+
userMappings: options.userMappings,
|
|
28
|
+
columns: options.columns,
|
|
29
|
+
ifNotExists: options.ifNotExists ?? true,
|
|
30
|
+
schema: options.schema ?? 'public',
|
|
31
|
+
cache: {
|
|
32
|
+
redis: options.cache?.redis ?? true,
|
|
33
|
+
ttl: options.cache?.ttl ?? 3600,
|
|
34
|
+
keyPrefix: options.cache?.keyPrefix ?? 'orm:foreign-table',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
target[FOREIGN_TABLE_KEY] = resolved;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function getForeignTableOptions(target) {
|
|
41
|
+
return target[FOREIGN_TABLE_KEY];
|
|
42
|
+
}
|
|
43
|
+
function isForeignTable(target) {
|
|
44
|
+
return !!target[FOREIGN_TABLE_KEY];
|
|
45
|
+
}
|
|
46
|
+
function getCacheKey(target, prefix = 'orm:foreign-table') {
|
|
47
|
+
return prefix + ':' + target.name;
|
|
48
|
+
}
|
|
49
|
+
function serializeOptions(opts) {
|
|
50
|
+
return JSON.stringify(opts);
|
|
51
|
+
}
|
|
52
|
+
function deserializeOptions(data) {
|
|
53
|
+
return JSON.parse(data);
|
|
54
|
+
}
|
|
55
|
+
async function cacheForeignTableOptions(target, options) {
|
|
56
|
+
const opts = options ?? getForeignTableOptions(target);
|
|
57
|
+
if (!opts)
|
|
58
|
+
throw new Error('[ORM] Class ' + target.name + ' does not have @ForeignTable decorator.');
|
|
59
|
+
const cacheConfig = opts.cache;
|
|
60
|
+
if (!cacheConfig?.redis)
|
|
61
|
+
return;
|
|
62
|
+
const redis = globalRedisClient;
|
|
63
|
+
if (!redis) {
|
|
64
|
+
console.warn('[ORM] Redis client not configured, skipping cache write.');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const key = getCacheKey(target, cacheConfig.keyPrefix);
|
|
68
|
+
const ttl = cacheConfig.ttl ?? 3600;
|
|
69
|
+
await redis.set(key, serializeOptions(opts), 'EX', ttl);
|
|
70
|
+
}
|
|
71
|
+
async function getCachedForeignTableOptions(target) {
|
|
72
|
+
const opts = getForeignTableOptions(target);
|
|
73
|
+
if (!opts)
|
|
74
|
+
return null;
|
|
75
|
+
const cacheConfig = opts.cache;
|
|
76
|
+
if (!cacheConfig?.redis)
|
|
77
|
+
return null;
|
|
78
|
+
const redis = globalRedisClient;
|
|
79
|
+
if (!redis)
|
|
80
|
+
return null;
|
|
81
|
+
const data = await redis.get(getCacheKey(target, cacheConfig.keyPrefix));
|
|
82
|
+
if (!data)
|
|
83
|
+
return null;
|
|
84
|
+
return deserializeOptions(data);
|
|
85
|
+
}
|
|
86
|
+
async function invalidateForeignTableCache(target) {
|
|
87
|
+
const opts = getForeignTableOptions(target);
|
|
88
|
+
if (!opts)
|
|
89
|
+
return;
|
|
90
|
+
const cacheConfig = opts.cache;
|
|
91
|
+
if (!cacheConfig?.redis)
|
|
92
|
+
return;
|
|
93
|
+
const redis = globalRedisClient;
|
|
94
|
+
if (!redis)
|
|
95
|
+
return;
|
|
96
|
+
await redis.del(getCacheKey(target, cacheConfig.keyPrefix));
|
|
97
|
+
}
|
|
98
|
+
async function warmupForeignTableCache(target, prorm) {
|
|
99
|
+
await cacheForeignTableOptions(target);
|
|
100
|
+
}
|
|
101
|
+
exports.ForeignTableRegistry = {
|
|
102
|
+
getOptions(target) {
|
|
103
|
+
return getForeignTableOptions(target);
|
|
104
|
+
},
|
|
105
|
+
isForeignTable(target) {
|
|
106
|
+
return isForeignTable(target);
|
|
107
|
+
},
|
|
108
|
+
getSQL(target) {
|
|
109
|
+
const opts = getForeignTableOptions(target);
|
|
110
|
+
if (!opts)
|
|
111
|
+
throw new Error('[ORM] Class ' + target.name + ' does not have a @ForeignTable decorator.');
|
|
112
|
+
if (!opts.server)
|
|
113
|
+
throw new Error('[ORM] @ForeignTable requires a server option.');
|
|
114
|
+
const schema = opts.schema ?? 'public';
|
|
115
|
+
const tableName = target.name;
|
|
116
|
+
const columns = opts.columns ?? {};
|
|
117
|
+
const columnDefs = Object.entries(columns)
|
|
118
|
+
.map(([name, col]) => {
|
|
119
|
+
let def = name + ' ' + col.type;
|
|
120
|
+
if (col.options)
|
|
121
|
+
def += ' ' + col.options;
|
|
122
|
+
return def;
|
|
123
|
+
})
|
|
124
|
+
.join(',\n ');
|
|
125
|
+
if (!columnDefs)
|
|
126
|
+
throw new Error('[ORM] @ForeignTable requires columns option.');
|
|
127
|
+
let sql = `CREATE FOREIGN TABLE "${tableName}" (\n ${columnDefs}\n) SERVER "${opts.server}"`;
|
|
128
|
+
if (opts.foreignSchema) {
|
|
129
|
+
sql += `\n OPTIONS (schema '${opts.foreignSchema}')`;
|
|
130
|
+
}
|
|
131
|
+
if (opts.ifNotExists) {
|
|
132
|
+
sql = sql.replace('CREATE FOREIGN TABLE', 'CREATE FOREIGN TABLE IF NOT EXISTS');
|
|
133
|
+
}
|
|
134
|
+
return sql;
|
|
135
|
+
},
|
|
136
|
+
};
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Generated Column decorators for the ORM.
|
|
4
|
+
*
|
|
5
|
+
* Supports database-level computed columns:
|
|
6
|
+
* - VIRTUAL: Computed on read, not stored in DB
|
|
7
|
+
* - STORED: Computed on write, physically stored in DB
|
|
8
|
+
* - IDENTITY: Auto-increment primary key configuration
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
*
|
|
12
|
+
* // Virtual computed column (default)
|
|
13
|
+
* @Generated()
|
|
14
|
+
* get fullName() {
|
|
15
|
+
* return `${this.firstName} ${this.lastName}`;
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* // Stored computed column
|
|
19
|
+
* @Generated('stored')
|
|
20
|
+
* get total() {
|
|
21
|
+
* return this.price * this.quantity;
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* // With custom expression
|
|
25
|
+
* @Generated({
|
|
26
|
+
* as: 'CONCAT(first_name, " ", last_name)',
|
|
27
|
+
* type: 'varchar(255)',
|
|
28
|
+
* stored: true
|
|
29
|
+
* })
|
|
30
|
+
* fullName: string;
|
|
31
|
+
*
|
|
32
|
+
* // Identity/Auto-increment configuration
|
|
33
|
+
* @Generated({
|
|
34
|
+
* identity: true,
|
|
35
|
+
* start: 1,
|
|
36
|
+
* increment: 1,
|
|
37
|
+
* cache: 1000
|
|
38
|
+
* })
|
|
39
|
+
* id: number;
|
|
40
|
+
*/
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.Generated = Generated;
|
|
43
|
+
exports.Identity = Identity;
|
|
44
|
+
exports.getGeneratedMetadata = getGeneratedMetadata;
|
|
45
|
+
exports.getIdentityMetadata = getIdentityMetadata;
|
|
46
|
+
exports.getAllGeneratedMetadata = getAllGeneratedMetadata;
|
|
47
|
+
exports.getAllIdentityMetadata = getAllIdentityMetadata;
|
|
48
|
+
exports.isGeneratedColumn = isGeneratedColumn;
|
|
49
|
+
exports.isIdentityColumn = isIdentityColumn;
|
|
50
|
+
exports.buildGeneratedSQL = buildGeneratedSQL;
|
|
51
|
+
exports.isStored = isStored;
|
|
52
|
+
require("reflect-metadata");
|
|
53
|
+
// ==================== Metadata Key ====================
|
|
54
|
+
/**
|
|
55
|
+
* Symbol for storing generated column metadata
|
|
56
|
+
*/
|
|
57
|
+
const GENERATED_METADATA_KEY = Symbol('prorm:generated');
|
|
58
|
+
/**
|
|
59
|
+
* Symbol for storing identity/auto-increment metadata
|
|
60
|
+
*/
|
|
61
|
+
const IDENTITY_METADATA_KEY = Symbol('prorm:identity');
|
|
62
|
+
// ==================== Decorators ====================
|
|
63
|
+
/**
|
|
64
|
+
* Decorator for generated/computed columns.
|
|
65
|
+
*
|
|
66
|
+
* Usage with getter (for computed properties):
|
|
67
|
+
*
|
|
68
|
+
* class User extends Model {
|
|
69
|
+
* @Generated()
|
|
70
|
+
* get fullName() {
|
|
71
|
+
* return `${this.firstName} ${this.lastName}`;
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* Usage with options:
|
|
76
|
+
*
|
|
77
|
+
* @Generated({
|
|
78
|
+
* as: 'CONCAT(first_name, " ", last_name)',
|
|
79
|
+
* type: 'varchar(255)',
|
|
80
|
+
* stored: true
|
|
81
|
+
* })
|
|
82
|
+
* fullName: string;
|
|
83
|
+
*
|
|
84
|
+
* @param options - Generated column options or just storage type
|
|
85
|
+
*/
|
|
86
|
+
function Generated(options) {
|
|
87
|
+
return function (target, propertyKey) {
|
|
88
|
+
const opts = normalizeOptions(options);
|
|
89
|
+
// Store metadata
|
|
90
|
+
const metadata = {
|
|
91
|
+
propertyName: String(propertyKey),
|
|
92
|
+
options: opts,
|
|
93
|
+
};
|
|
94
|
+
Reflect.defineMetadata(GENERATED_METADATA_KEY, metadata, target, String(propertyKey));
|
|
95
|
+
// Also handle identity separately if enabled
|
|
96
|
+
if (opts.identity) {
|
|
97
|
+
Reflect.defineMetadata(IDENTITY_METADATA_KEY, { propertyName: String(propertyKey), options: opts }, target, String(propertyKey));
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Decorator specifically for identity/auto-increment columns.
|
|
103
|
+
*
|
|
104
|
+
* Usage:
|
|
105
|
+
*
|
|
106
|
+
* @Generated({
|
|
107
|
+
* identity: true,
|
|
108
|
+
* start: 1,
|
|
109
|
+
* increment: 1,
|
|
110
|
+
* cache: 1000
|
|
111
|
+
* })
|
|
112
|
+
* id: number;
|
|
113
|
+
*
|
|
114
|
+
* @param options - Identity configuration options
|
|
115
|
+
*/
|
|
116
|
+
function Identity(options) {
|
|
117
|
+
return function (target, propertyKey) {
|
|
118
|
+
const opts = {
|
|
119
|
+
...options,
|
|
120
|
+
identity: true,
|
|
121
|
+
};
|
|
122
|
+
Reflect.defineMetadata(IDENTITY_METADATA_KEY, { propertyName: String(propertyKey), options: opts }, target, String(propertyKey));
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// ==================== Helper Functions ====================
|
|
126
|
+
/**
|
|
127
|
+
* Normalize options from various input formats
|
|
128
|
+
*/
|
|
129
|
+
function normalizeOptions(options) {
|
|
130
|
+
if (!options) {
|
|
131
|
+
// `stored` is left undefined here rather than defaulting to `false`,
|
|
132
|
+
// because the correct default depends on the target dialect (see
|
|
133
|
+
// `isStored`) and the dialect isn't known at decoration time.
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
if (typeof options === 'string') {
|
|
137
|
+
return { stored: options === 'stored' };
|
|
138
|
+
}
|
|
139
|
+
return options;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get generated column metadata for a property.
|
|
143
|
+
*
|
|
144
|
+
* @param target - The target class or prototype
|
|
145
|
+
* @param propertyKey - The property name
|
|
146
|
+
* @returns The generated metadata or undefined
|
|
147
|
+
*/
|
|
148
|
+
function getGeneratedMetadata(target, propertyKey) {
|
|
149
|
+
return Reflect.getMetadata(GENERATED_METADATA_KEY, target, propertyKey);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get identity metadata for a property.
|
|
153
|
+
*
|
|
154
|
+
* @param target - The target class or prototype
|
|
155
|
+
* @param propertyKey - The property name
|
|
156
|
+
* @returns The identity metadata or undefined
|
|
157
|
+
*/
|
|
158
|
+
function getIdentityMetadata(target, propertyKey) {
|
|
159
|
+
return Reflect.getMetadata(IDENTITY_METADATA_KEY, target, propertyKey);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get all generated column metadata for a class.
|
|
163
|
+
*
|
|
164
|
+
* @param target - The target class or prototype
|
|
165
|
+
* @returns Map of property names to their generated metadata
|
|
166
|
+
*/
|
|
167
|
+
function getAllGeneratedMetadata(target) {
|
|
168
|
+
const result = new Map();
|
|
169
|
+
// Get all own property keys
|
|
170
|
+
const keys = Object.getOwnPropertyNames(target);
|
|
171
|
+
for (const key of keys) {
|
|
172
|
+
const metadata = getGeneratedMetadata(target, key);
|
|
173
|
+
if (metadata) {
|
|
174
|
+
result.set(key, metadata);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Also check prototype chain for inherited metadata
|
|
178
|
+
const proto = Object.getPrototypeOf(target);
|
|
179
|
+
if (proto && Object.getPrototypeOf(proto) !== null) {
|
|
180
|
+
const inherited = getAllGeneratedMetadata(proto);
|
|
181
|
+
for (const [key, value] of inherited) {
|
|
182
|
+
if (!result.has(key)) {
|
|
183
|
+
result.set(key, value);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get all identity metadata for a class.
|
|
191
|
+
*
|
|
192
|
+
* @param target - The target class or prototype
|
|
193
|
+
* @returns Map of property names to their identity metadata
|
|
194
|
+
*/
|
|
195
|
+
function getAllIdentityMetadata(target) {
|
|
196
|
+
const result = new Map();
|
|
197
|
+
const keys = Object.getOwnPropertyNames(target);
|
|
198
|
+
for (const key of keys) {
|
|
199
|
+
const metadata = getIdentityMetadata(target, key);
|
|
200
|
+
if (metadata) {
|
|
201
|
+
result.set(key, metadata);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const proto = Object.getPrototypeOf(target);
|
|
205
|
+
if (proto && Object.getPrototypeOf(proto) !== null) {
|
|
206
|
+
const inherited = getAllIdentityMetadata(proto);
|
|
207
|
+
for (const [key, value] of inherited) {
|
|
208
|
+
if (!result.has(key)) {
|
|
209
|
+
result.set(key, value);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Check if a property is a generated column.
|
|
217
|
+
*
|
|
218
|
+
* @param target - The target class or prototype
|
|
219
|
+
* @param propertyKey - The property name
|
|
220
|
+
* @returns True if the property is generated
|
|
221
|
+
*/
|
|
222
|
+
function isGeneratedColumn(target, propertyKey) {
|
|
223
|
+
return !!getGeneratedMetadata(target, propertyKey);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Check if a property is an identity/auto-increment column.
|
|
227
|
+
*
|
|
228
|
+
* @param target - The target class or prototype
|
|
229
|
+
* @param propertyKey - The property name
|
|
230
|
+
* @returns True if the property is an identity column
|
|
231
|
+
*/
|
|
232
|
+
function isIdentityColumn(target, propertyKey) {
|
|
233
|
+
const metadata = getIdentityMetadata(target, propertyKey);
|
|
234
|
+
return !!metadata?.options.identity;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Build the SQL expression for a generated column.
|
|
238
|
+
*
|
|
239
|
+
* @param options - The generated column options
|
|
240
|
+
* @returns The SQL expression string
|
|
241
|
+
*/
|
|
242
|
+
function buildGeneratedSQL(options) {
|
|
243
|
+
if (options.as) {
|
|
244
|
+
return options.as;
|
|
245
|
+
}
|
|
246
|
+
// If no custom expression, return empty
|
|
247
|
+
return '';
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Check if generated column is stored (persisted) or virtual.
|
|
251
|
+
*
|
|
252
|
+
* When `options.stored` is explicitly set, that value is used as-is.
|
|
253
|
+
* When it is left unspecified, the default depends on the target dialect:
|
|
254
|
+
* - PostgreSQL (before v18) only supports `STORED` generated columns —
|
|
255
|
+
* `VIRTUAL` is not a valid option, so it defaults to `true` (stored).
|
|
256
|
+
* - MySQL/MariaDB support both `VIRTUAL` and `STORED`, and default to
|
|
257
|
+
* `VIRTUAL` (the lighter-weight option), so this defaults to `false`.
|
|
258
|
+
* - Other dialects (sqlite, mssql, oracle) also default to `false`
|
|
259
|
+
* (virtual/computed, not persisted), matching their typical defaults.
|
|
260
|
+
*
|
|
261
|
+
* @param options - The generated column options
|
|
262
|
+
* @param dialect - The target SQL dialect (defaults to 'mysql' for backwards compatibility)
|
|
263
|
+
* @returns True if stored, false if virtual
|
|
264
|
+
*/
|
|
265
|
+
function isStored(options, dialect = 'mysql') {
|
|
266
|
+
if (options.stored !== undefined) {
|
|
267
|
+
return options.stored;
|
|
268
|
+
}
|
|
269
|
+
// PostgreSQL doesn't support VIRTUAL generated columns before v18 —
|
|
270
|
+
// fall back to STORED, the only option it actually supports.
|
|
271
|
+
return dialect === 'postgres';
|
|
272
|
+
}
|
|
273
|
+
// ==================== Exports ====================
|
|
274
|
+
// Types are exported inline with the interfaces/classes above
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HasMany decorator for the ORM.
|
|
4
|
+
*
|
|
5
|
+
* Defines a one-to-many relationship between models.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
*
|
|
9
|
+
* @HasMany(() => Post)
|
|
10
|
+
* posts: Post[];
|
|
11
|
+
*
|
|
12
|
+
* @HasMany(() => Post, { as: 'articles' })
|
|
13
|
+
* articles: Post[];
|
|
14
|
+
*
|
|
15
|
+
* // With options
|
|
16
|
+
* @HasMany(() => Order, {
|
|
17
|
+
* foreignKey: { name: 'user_id', allowNull: false },
|
|
18
|
+
* onDelete: 'CASCADE',
|
|
19
|
+
* through: 'user_orders' // For belongsToMany
|
|
20
|
+
* })
|
|
21
|
+
* orders: Order[];
|
|
22
|
+
*
|
|
23
|
+
* // Self-referential
|
|
24
|
+
* @HasMany(() => Category, { as: 'children', foreignKey: 'parent_id' })
|
|
25
|
+
* children: Category[];
|
|
26
|
+
*
|
|
27
|
+
* // Nested hasMany with scope
|
|
28
|
+
* @HasMany(() => Comment, {
|
|
29
|
+
* as: 'replies',
|
|
30
|
+
* foreignKey: 'parent_id',
|
|
31
|
+
* scope: { deleted: false }
|
|
32
|
+
* })
|
|
33
|
+
* replies: Comment[];
|
|
34
|
+
*/
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getHasMany = getHasMany;
|
|
37
|
+
exports.getAllHasMany = getAllHasMany;
|
|
38
|
+
exports.HasMany = HasMany;
|
|
39
|
+
exports.processHasManyDecorators = processHasManyDecorators;
|
|
40
|
+
// ==================== Metadata Storage ====================
|
|
41
|
+
const HAS_MANY_KEY = '__orm_has_many__';
|
|
42
|
+
/**
|
|
43
|
+
* Get all @HasMany annotations attached to a model constructor.
|
|
44
|
+
*/
|
|
45
|
+
function getHasMany(target) {
|
|
46
|
+
return target[HAS_MANY_KEY] || [];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get all hasMany associations including inherited ones.
|
|
50
|
+
*/
|
|
51
|
+
function getAllHasMany(target) {
|
|
52
|
+
const associations = [];
|
|
53
|
+
let current = target;
|
|
54
|
+
while (current && current.prototype) {
|
|
55
|
+
const meta = getHasMany(current);
|
|
56
|
+
associations.push(...meta);
|
|
57
|
+
current = Object.getPrototypeOf(current);
|
|
58
|
+
if (current === Object.prototype)
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
return associations;
|
|
62
|
+
}
|
|
63
|
+
// ==================== Decorator ====================
|
|
64
|
+
/**
|
|
65
|
+
* Define a one-to-many relationship.
|
|
66
|
+
*
|
|
67
|
+
* This decorator stores metadata on the model class that can be used
|
|
68
|
+
* by the ORM to establish the association at model initialization time.
|
|
69
|
+
*
|
|
70
|
+
* @param target - A function that returns the target model class
|
|
71
|
+
* @param options - Optional configuration for the association
|
|
72
|
+
*/
|
|
73
|
+
function HasMany(target, options = {}) {
|
|
74
|
+
return function (prototype, propertyKey) {
|
|
75
|
+
const ModelClass = prototype.constructor;
|
|
76
|
+
if (!ModelClass[HAS_MANY_KEY]) {
|
|
77
|
+
ModelClass[HAS_MANY_KEY] = [];
|
|
78
|
+
}
|
|
79
|
+
ModelClass[HAS_MANY_KEY].push({
|
|
80
|
+
target,
|
|
81
|
+
options: {
|
|
82
|
+
as: options.as || propertyKey.toString(),
|
|
83
|
+
foreignKey: options.foreignKey,
|
|
84
|
+
constraints: options.constraints,
|
|
85
|
+
onDelete: options.onDelete,
|
|
86
|
+
onUpdate: options.onUpdate,
|
|
87
|
+
targetKey: options.targetKey,
|
|
88
|
+
sourceKey: options.sourceKey,
|
|
89
|
+
scope: options.scope,
|
|
90
|
+
through: options.through,
|
|
91
|
+
inverse: options.inverse,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Process @HasMany decorators and create association configuration.
|
|
98
|
+
*
|
|
99
|
+
* Call this to get the raw association definitions from decorators.
|
|
100
|
+
*
|
|
101
|
+
* @param ModelClass - The model class with @HasMany decorators
|
|
102
|
+
* @returns Array of association configurations
|
|
103
|
+
*/
|
|
104
|
+
function processHasManyDecorators(ModelClass) {
|
|
105
|
+
const decorators = getAllHasMany(ModelClass);
|
|
106
|
+
return decorators.map(({ target, options }) => {
|
|
107
|
+
const targetModel = target();
|
|
108
|
+
const foreignKey = typeof options.foreignKey === 'string'
|
|
109
|
+
? options.foreignKey
|
|
110
|
+
: options.foreignKey?.name
|
|
111
|
+
? options.foreignKey.name
|
|
112
|
+
: `${ModelClass.name}Id`;
|
|
113
|
+
return {
|
|
114
|
+
source: ModelClass,
|
|
115
|
+
target: targetModel,
|
|
116
|
+
foreignKey,
|
|
117
|
+
as: options.as || '',
|
|
118
|
+
options,
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
exports.default = {
|
|
123
|
+
HasMany,
|
|
124
|
+
getHasMany,
|
|
125
|
+
getAllHasMany,
|
|
126
|
+
processHasManyDecorators,
|
|
127
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HasOne decorator for the ORM.
|
|
4
|
+
*
|
|
5
|
+
* Defines a one-to-one relationship between models.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
*
|
|
9
|
+
* @HasOne(() => Profile)
|
|
10
|
+
* profile: Profile;
|
|
11
|
+
*
|
|
12
|
+
* @HasOne(() => Profile, { as: 'userProfile' })
|
|
13
|
+
* userProfile: Profile;
|
|
14
|
+
*
|
|
15
|
+
* // With options
|
|
16
|
+
* @HasOne(() => Profile, {
|
|
17
|
+
* foreignKey: { name: 'user_id', allowNull: false },
|
|
18
|
+
* onDelete: 'CASCADE'
|
|
19
|
+
* })
|
|
20
|
+
* profile: Profile;
|
|
21
|
+
*
|
|
22
|
+
* // Self-referential
|
|
23
|
+
* @HasOne(() => User, { as: 'manager', foreignKey: 'manager_id' })
|
|
24
|
+
* manager: User;
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.getHasOne = getHasOne;
|
|
28
|
+
exports.getAllHasOne = getAllHasOne;
|
|
29
|
+
exports.HasOne = HasOne;
|
|
30
|
+
exports.processHasOneDecorators = processHasOneDecorators;
|
|
31
|
+
// ==================== Metadata Storage ====================
|
|
32
|
+
const HAS_ONE_KEY = '__orm_has_one__';
|
|
33
|
+
/**
|
|
34
|
+
* Get all @HasOne annotations attached to a model constructor.
|
|
35
|
+
*/
|
|
36
|
+
function getHasOne(target) {
|
|
37
|
+
return target[HAS_ONE_KEY] || [];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get all hasOne associations including inherited ones.
|
|
41
|
+
*/
|
|
42
|
+
function getAllHasOne(target) {
|
|
43
|
+
const associations = [];
|
|
44
|
+
let current = target;
|
|
45
|
+
while (current && current.prototype) {
|
|
46
|
+
const meta = getHasOne(current);
|
|
47
|
+
associations.push(...meta);
|
|
48
|
+
current = Object.getPrototypeOf(current);
|
|
49
|
+
if (current === Object.prototype)
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
return associations;
|
|
53
|
+
}
|
|
54
|
+
// ==================== Decorator ====================
|
|
55
|
+
/**
|
|
56
|
+
* Define a one-to-one relationship.
|
|
57
|
+
*
|
|
58
|
+
* This decorator stores metadata on the model class that can be used
|
|
59
|
+
* by the ORM to establish the association at model initialization time.
|
|
60
|
+
*
|
|
61
|
+
* @param target - A function that returns the target model class
|
|
62
|
+
* @param options - Optional configuration for the association
|
|
63
|
+
*/
|
|
64
|
+
function HasOne(target, options = {}) {
|
|
65
|
+
return function (prototype, propertyKey) {
|
|
66
|
+
const ModelClass = prototype.constructor;
|
|
67
|
+
if (!ModelClass[HAS_ONE_KEY]) {
|
|
68
|
+
ModelClass[HAS_ONE_KEY] = [];
|
|
69
|
+
}
|
|
70
|
+
ModelClass[HAS_ONE_KEY].push({
|
|
71
|
+
target,
|
|
72
|
+
options: {
|
|
73
|
+
as: options.as || propertyKey.toString(),
|
|
74
|
+
foreignKey: options.foreignKey,
|
|
75
|
+
constraints: options.constraints,
|
|
76
|
+
onDelete: options.onDelete,
|
|
77
|
+
onUpdate: options.onUpdate,
|
|
78
|
+
targetKey: options.targetKey,
|
|
79
|
+
sourceKey: options.sourceKey,
|
|
80
|
+
inverse: options.inverse,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Process @HasOne decorators and create association configuration.
|
|
87
|
+
*
|
|
88
|
+
* Call this to get the raw association definitions from decorators.
|
|
89
|
+
*
|
|
90
|
+
* @param ModelClass - The model class with @HasOne decorators
|
|
91
|
+
* @returns Array of association configurations
|
|
92
|
+
*/
|
|
93
|
+
function processHasOneDecorators(ModelClass) {
|
|
94
|
+
const decorators = getAllHasOne(ModelClass);
|
|
95
|
+
return decorators.map(({ target, options }) => {
|
|
96
|
+
const targetModel = target();
|
|
97
|
+
const foreignKey = typeof options.foreignKey === 'string'
|
|
98
|
+
? options.foreignKey
|
|
99
|
+
: options.foreignKey?.name
|
|
100
|
+
? options.foreignKey.name
|
|
101
|
+
: `${ModelClass.name}Id`;
|
|
102
|
+
return {
|
|
103
|
+
source: ModelClass,
|
|
104
|
+
target: targetModel,
|
|
105
|
+
foreignKey,
|
|
106
|
+
as: options.as || '',
|
|
107
|
+
options,
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
exports.default = {
|
|
112
|
+
HasOne,
|
|
113
|
+
getHasOne,
|
|
114
|
+
getAllHasOne,
|
|
115
|
+
processHasOneDecorators,
|
|
116
|
+
};
|