@carno.js/orm 0.2.3
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/LICENSE +674 -0
- package/dist/SqlBuilder.d.ts +103 -0
- package/dist/SqlBuilder.js +618 -0
- package/dist/cache/cache-key-generator.d.ts +13 -0
- package/dist/cache/cache-key-generator.js +66 -0
- package/dist/cache/query-cache-manager.d.ts +14 -0
- package/dist/cache/query-cache-manager.js +44 -0
- package/dist/common/email.vo.d.ts +4 -0
- package/dist/common/email.vo.js +11 -0
- package/dist/common/uuid.d.ts +4 -0
- package/dist/common/uuid.js +10 -0
- package/dist/common/value-object.d.ts +95 -0
- package/dist/common/value-object.js +99 -0
- package/dist/constants.d.ts +6 -0
- package/dist/constants.js +9 -0
- package/dist/decorators/computed.decorator.d.ts +1 -0
- package/dist/decorators/computed.decorator.js +12 -0
- package/dist/decorators/entity.decorator.d.ts +3 -0
- package/dist/decorators/entity.decorator.js +12 -0
- package/dist/decorators/enum.decorator.d.ts +2 -0
- package/dist/decorators/enum.decorator.js +16 -0
- package/dist/decorators/event-hook.decorator.d.ts +4 -0
- package/dist/decorators/event-hook.decorator.js +31 -0
- package/dist/decorators/index.decorator.d.ts +17 -0
- package/dist/decorators/index.decorator.js +36 -0
- package/dist/decorators/one-many.decorator.d.ts +6 -0
- package/dist/decorators/one-many.decorator.js +42 -0
- package/dist/decorators/primary-key.decorator.d.ts +2 -0
- package/dist/decorators/primary-key.decorator.js +8 -0
- package/dist/decorators/property.decorator.d.ts +24 -0
- package/dist/decorators/property.decorator.js +44 -0
- package/dist/decorators/unique.decorator.d.ts +9 -0
- package/dist/decorators/unique.decorator.js +44 -0
- package/dist/domain/base-entity.d.ts +57 -0
- package/dist/domain/base-entity.js +198 -0
- package/dist/domain/collection.d.ts +6 -0
- package/dist/domain/collection.js +15 -0
- package/dist/domain/entities.d.ts +49 -0
- package/dist/domain/entities.js +259 -0
- package/dist/domain/reference.d.ts +86 -0
- package/dist/domain/reference.js +86 -0
- package/dist/driver/bun-driver.base.d.ts +72 -0
- package/dist/driver/bun-driver.base.js +270 -0
- package/dist/driver/bun-mysql.driver.d.ts +53 -0
- package/dist/driver/bun-mysql.driver.js +256 -0
- package/dist/driver/bun-pg.driver.d.ts +52 -0
- package/dist/driver/bun-pg.driver.js +263 -0
- package/dist/driver/driver.interface.d.ts +333 -0
- package/dist/driver/driver.interface.js +2 -0
- package/dist/entry.d.ts +2 -0
- package/dist/entry.js +13 -0
- package/dist/identity-map/entity-key-generator.d.ts +10 -0
- package/dist/identity-map/entity-key-generator.js +45 -0
- package/dist/identity-map/entity-registry.d.ts +11 -0
- package/dist/identity-map/entity-registry.js +41 -0
- package/dist/identity-map/identity-map-context.d.ts +9 -0
- package/dist/identity-map/identity-map-context.js +22 -0
- package/dist/identity-map/identity-map-integration.d.ts +5 -0
- package/dist/identity-map/identity-map-integration.js +37 -0
- package/dist/identity-map/identity-map.d.ts +11 -0
- package/dist/identity-map/identity-map.js +35 -0
- package/dist/identity-map/index.d.ts +5 -0
- package/dist/identity-map/index.js +14 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +48 -0
- package/dist/middleware/identity-map.middleware.d.ts +4 -0
- package/dist/middleware/identity-map.middleware.js +22 -0
- package/dist/orm-session-context.d.ts +16 -0
- package/dist/orm-session-context.js +22 -0
- package/dist/orm.d.ts +20 -0
- package/dist/orm.js +69 -0
- package/dist/orm.service.d.ts +13 -0
- package/dist/orm.service.js +361 -0
- package/dist/query/index-condition-builder.d.ts +41 -0
- package/dist/query/index-condition-builder.js +235 -0
- package/dist/query/model-transformer.d.ts +27 -0
- package/dist/query/model-transformer.js +201 -0
- package/dist/query/sql-column-manager.d.ts +28 -0
- package/dist/query/sql-column-manager.js +157 -0
- package/dist/query/sql-condition-builder.d.ts +51 -0
- package/dist/query/sql-condition-builder.js +264 -0
- package/dist/query/sql-join-manager.d.ts +39 -0
- package/dist/query/sql-join-manager.js +242 -0
- package/dist/query/sql-subquery-builder.d.ts +20 -0
- package/dist/query/sql-subquery-builder.js +119 -0
- package/dist/repository/Repository.d.ts +121 -0
- package/dist/repository/Repository.js +174 -0
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +17 -0
- package/dist/testing/with-database.d.ts +20 -0
- package/dist/testing/with-database.js +311 -0
- package/dist/transaction/transaction-context.d.ts +10 -0
- package/dist/transaction/transaction-context.js +19 -0
- package/dist/utils/value-processor.d.ts +14 -0
- package/dist/utils/value-processor.js +94 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +24 -0
- package/package.json +59 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.withDatabase = withDatabase;
|
|
40
|
+
const globby_1 = __importDefault(require("globby"));
|
|
41
|
+
const fs_1 = require("fs");
|
|
42
|
+
const path_1 = __importDefault(require("path"));
|
|
43
|
+
const core_1 = require("@carno.js/core");
|
|
44
|
+
const entities_1 = require("../domain/entities");
|
|
45
|
+
const orm_1 = require("../orm");
|
|
46
|
+
const orm_service_1 = require("../orm.service");
|
|
47
|
+
const bun_pg_driver_1 = require("../driver/bun-pg.driver");
|
|
48
|
+
const orm_session_context_1 = require("../orm-session-context");
|
|
49
|
+
const constants_1 = require("../constants");
|
|
50
|
+
const DEFAULT_SCHEMA = 'public';
|
|
51
|
+
const DEFAULT_CONNECTION = {
|
|
52
|
+
host: 'localhost',
|
|
53
|
+
port: 5432,
|
|
54
|
+
database: 'postgres',
|
|
55
|
+
username: 'postgres',
|
|
56
|
+
password: 'postgres',
|
|
57
|
+
driver: bun_pg_driver_1.BunPgDriver,
|
|
58
|
+
};
|
|
59
|
+
const sessionCache = new Map();
|
|
60
|
+
function getCacheKey(options) {
|
|
61
|
+
const connection = resolveConnection(options.connection);
|
|
62
|
+
const entitySignature = resolveEntitySignature();
|
|
63
|
+
return JSON.stringify({
|
|
64
|
+
host: connection.host,
|
|
65
|
+
port: connection.port,
|
|
66
|
+
database: connection.database,
|
|
67
|
+
schema: options.schema ?? DEFAULT_SCHEMA,
|
|
68
|
+
entityFile: options.entityFile,
|
|
69
|
+
migrationPath: connection.migrationPath,
|
|
70
|
+
entitySignature,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function resolveEntitySignature() {
|
|
74
|
+
const entities = core_1.Metadata.get(constants_1.ENTITIES, Reflect) || [];
|
|
75
|
+
return buildEntitySignature(entities);
|
|
76
|
+
}
|
|
77
|
+
function buildEntitySignature(entities) {
|
|
78
|
+
if (entities.length < 1) {
|
|
79
|
+
return 'none';
|
|
80
|
+
}
|
|
81
|
+
const names = entities.map((entity) => entity.target?.name ?? 'unknown');
|
|
82
|
+
return names.sort().join('|');
|
|
83
|
+
}
|
|
84
|
+
async function withDatabase(arg1, arg2, arg3) {
|
|
85
|
+
const { routine: targetRoutine, options: targetOptions, statements } = await normalizeArgs(arg1, arg2, arg3);
|
|
86
|
+
const cacheKey = getCacheKey(targetOptions);
|
|
87
|
+
let cachedSession = sessionCache.get(cacheKey);
|
|
88
|
+
const schemaStatements = await resolveSchemaStatements(statements, targetOptions);
|
|
89
|
+
if (!cachedSession) {
|
|
90
|
+
const session = await createSession(targetOptions);
|
|
91
|
+
cachedSession = {
|
|
92
|
+
orm: session.orm,
|
|
93
|
+
schema: session.schema,
|
|
94
|
+
storage: session.storage,
|
|
95
|
+
};
|
|
96
|
+
sessionCache.set(cacheKey, cachedSession);
|
|
97
|
+
}
|
|
98
|
+
await runWithSession(cachedSession, async () => {
|
|
99
|
+
const context = buildContext(cachedSession.orm);
|
|
100
|
+
await dropAndRecreateSchema(context, cachedSession.schema);
|
|
101
|
+
await prepareSchema(context, cachedSession.schema);
|
|
102
|
+
await createTables(context, schemaStatements);
|
|
103
|
+
await targetRoutine(context);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
async function createSession(options) {
|
|
107
|
+
const logger = selectLogger(options);
|
|
108
|
+
const orm = new orm_1.Orm(logger);
|
|
109
|
+
const storage = new entities_1.EntityStorage();
|
|
110
|
+
await initializeOrm(orm, storage, options);
|
|
111
|
+
return { orm, schema: options.schema ?? DEFAULT_SCHEMA, storage };
|
|
112
|
+
}
|
|
113
|
+
function selectLogger(options) {
|
|
114
|
+
if (options.logger) {
|
|
115
|
+
return options.logger;
|
|
116
|
+
}
|
|
117
|
+
const config = { applicationConfig: { logger: { level: 'info' } } };
|
|
118
|
+
return new core_1.LoggerService(config);
|
|
119
|
+
}
|
|
120
|
+
async function initializeOrm(orm, storage, options) {
|
|
121
|
+
if (options.entityFile) {
|
|
122
|
+
const entityFiles = await (0, globby_1.default)(options.entityFile, { absolute: true });
|
|
123
|
+
for (const file of entityFiles) {
|
|
124
|
+
await Promise.resolve(`${file}`).then(s => __importStar(require(s)));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const service = new orm_service_1.OrmService(orm, storage, options.entityFile);
|
|
128
|
+
const connection = resolveConnection(options.connection);
|
|
129
|
+
await service.onInit(connection);
|
|
130
|
+
}
|
|
131
|
+
async function runWithSession(session, routine) {
|
|
132
|
+
await orm_session_context_1.ormSessionContext.run({ orm: session.orm, storage: session.storage }, routine);
|
|
133
|
+
}
|
|
134
|
+
function resolveConnection(overrides) {
|
|
135
|
+
if (!overrides) {
|
|
136
|
+
return DEFAULT_CONNECTION;
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
...DEFAULT_CONNECTION,
|
|
140
|
+
...overrides,
|
|
141
|
+
driver: overrides.driver ?? bun_pg_driver_1.BunPgDriver,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function buildContext(orm) {
|
|
145
|
+
return {
|
|
146
|
+
orm,
|
|
147
|
+
executeSql: (sql) => executeSql(orm, sql),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
async function executeSql(orm, sql) {
|
|
151
|
+
if (!orm.driverInstance) {
|
|
152
|
+
throw new Error('Database driver not initialized. Call withDatabase() before executing SQL.');
|
|
153
|
+
}
|
|
154
|
+
const result = await orm.driverInstance.executeSql(sql);
|
|
155
|
+
return { rows: Array.isArray(result) ? result : [] };
|
|
156
|
+
}
|
|
157
|
+
async function createTables(context, statements) {
|
|
158
|
+
const payload = statements.filter(Boolean);
|
|
159
|
+
if (payload.length < 1) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
await executeStatements(context, payload);
|
|
163
|
+
}
|
|
164
|
+
async function executeStatements(context, statements) {
|
|
165
|
+
for (const statement of statements) {
|
|
166
|
+
await context.executeSql(statement);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function dropAndRecreateSchema(context, schema) {
|
|
170
|
+
await context.executeSql(`DROP SCHEMA IF EXISTS ${schema} CASCADE; CREATE SCHEMA ${schema};`);
|
|
171
|
+
}
|
|
172
|
+
async function normalizeArgs(tablesOrRoutine, routineOrOptions, optionsOrStatements) {
|
|
173
|
+
if (Array.isArray(tablesOrRoutine)) {
|
|
174
|
+
return {
|
|
175
|
+
routine: routineOrOptions,
|
|
176
|
+
options: optionsOrStatements ?? {},
|
|
177
|
+
statements: tablesOrRoutine,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
routine: tablesOrRoutine,
|
|
182
|
+
options: routineOrOptions ?? {},
|
|
183
|
+
statements: Array.isArray(optionsOrStatements) ? optionsOrStatements : [],
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
async function resolveSchemaStatements(statements, options) {
|
|
187
|
+
const explicit = statements.filter(Boolean);
|
|
188
|
+
if (explicit.length > 0) {
|
|
189
|
+
return explicit;
|
|
190
|
+
}
|
|
191
|
+
const fromMigrations = await loadStatementsFromMigrations(options);
|
|
192
|
+
return fromMigrations.filter(Boolean);
|
|
193
|
+
}
|
|
194
|
+
function normalizeGlobPatterns(patterns) {
|
|
195
|
+
return patterns.map(normalizeGlobPattern);
|
|
196
|
+
}
|
|
197
|
+
function normalizeGlobPattern(pattern) {
|
|
198
|
+
return pattern.replace(/\\/g, '/');
|
|
199
|
+
}
|
|
200
|
+
async function loadStatementsFromMigrations(options) {
|
|
201
|
+
const connection = resolveConnection(options.connection);
|
|
202
|
+
const patterns = await resolveMigrationPatterns(connection);
|
|
203
|
+
if (patterns.length < 1) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
const normalizedPatterns = normalizeGlobPatterns(patterns);
|
|
207
|
+
const files = await (0, globby_1.default)(normalizedPatterns, { absolute: true, expandDirectories: false });
|
|
208
|
+
if (files.length < 1) {
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
const orderedFiles = sortMigrationFiles(files);
|
|
212
|
+
return extractStatementsFromFiles(orderedFiles);
|
|
213
|
+
}
|
|
214
|
+
async function resolveMigrationPatterns(connection) {
|
|
215
|
+
if (connection.migrationPath) {
|
|
216
|
+
return [connection.migrationPath];
|
|
217
|
+
}
|
|
218
|
+
const inferred = await inferMigrationPathFromConfig();
|
|
219
|
+
if (inferred) {
|
|
220
|
+
return [inferred];
|
|
221
|
+
}
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
async function inferMigrationPathFromConfig() {
|
|
225
|
+
const configFile = await findConfigFile();
|
|
226
|
+
if (!configFile) {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
const contents = await safeReadFile(configFile);
|
|
230
|
+
if (!contents) {
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
return extractMigrationPath(contents, configFile);
|
|
234
|
+
}
|
|
235
|
+
async function findConfigFile() {
|
|
236
|
+
const candidates = [
|
|
237
|
+
'carno.config.ts',
|
|
238
|
+
'carno.config.js',
|
|
239
|
+
'carno.config.mjs',
|
|
240
|
+
'carno.config.cjs',
|
|
241
|
+
];
|
|
242
|
+
for (const file of candidates) {
|
|
243
|
+
const fullPath = path_1.default.resolve(process.cwd(), file);
|
|
244
|
+
const exists = await fileExists(fullPath);
|
|
245
|
+
if (exists) {
|
|
246
|
+
return fullPath;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
async function fileExists(target) {
|
|
252
|
+
try {
|
|
253
|
+
await fs_1.promises.access(target);
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async function safeReadFile(file) {
|
|
261
|
+
try {
|
|
262
|
+
return await fs_1.promises.readFile(file, 'utf8');
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function extractMigrationPath(source, file) {
|
|
269
|
+
const match = source.match(/migrationPath\s*:\s*['"`]([^'"`]+)['"`]/);
|
|
270
|
+
if (!match) {
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
const candidate = match[1].trim();
|
|
274
|
+
if (path_1.default.isAbsolute(candidate)) {
|
|
275
|
+
return candidate;
|
|
276
|
+
}
|
|
277
|
+
const baseDir = path_1.default.dirname(file);
|
|
278
|
+
return path_1.default.resolve(baseDir, candidate);
|
|
279
|
+
}
|
|
280
|
+
async function extractStatementsFromFiles(files) {
|
|
281
|
+
const statements = [];
|
|
282
|
+
for (const file of files) {
|
|
283
|
+
const payload = await safeReadFile(file);
|
|
284
|
+
if (!payload) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
const extracted = extractStatements(payload);
|
|
288
|
+
statements.push(...extracted);
|
|
289
|
+
}
|
|
290
|
+
return Array.from(new Set(statements));
|
|
291
|
+
}
|
|
292
|
+
function extractStatements(payload) {
|
|
293
|
+
const matches = payload.match(/(CREATE\s+(?:TABLE|TYPE|INDEX|SCHEMA)[\s\S]*?;|ALTER\s+TABLE[\s\S]*?\bADD\b[\s\S]*?;)/gi) ?? [];
|
|
294
|
+
return matches.map((statement) => statement.replace(/\s+/g, ' ').trim());
|
|
295
|
+
}
|
|
296
|
+
function sortMigrationFiles(files) {
|
|
297
|
+
return [...files].sort((first, second) => path_1.default.basename(first).localeCompare(path_1.default.basename(second), undefined, { numeric: true }));
|
|
298
|
+
}
|
|
299
|
+
async function prepareSchema(context, schema) {
|
|
300
|
+
await context.executeSql(buildCreateSchemaStatement(schema));
|
|
301
|
+
await ensureSearchPath(context, schema);
|
|
302
|
+
}
|
|
303
|
+
function buildCreateSchemaStatement(schema) {
|
|
304
|
+
return `CREATE SCHEMA IF NOT EXISTS ${schema};`;
|
|
305
|
+
}
|
|
306
|
+
async function ensureSearchPath(context, schema) {
|
|
307
|
+
await context.executeSql(buildSearchPathStatement(schema));
|
|
308
|
+
}
|
|
309
|
+
function buildSearchPathStatement(schema) {
|
|
310
|
+
return `SET search_path TO ${schema};`;
|
|
311
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SQL } from 'bun';
|
|
2
|
+
declare class TransactionContextManager {
|
|
3
|
+
private storage;
|
|
4
|
+
constructor();
|
|
5
|
+
run<T>(tx: SQL, callback: () => Promise<T>): Promise<T>;
|
|
6
|
+
getContext(): SQL | undefined;
|
|
7
|
+
hasContext(): boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const transactionContext: TransactionContextManager;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transactionContext = void 0;
|
|
4
|
+
const async_hooks_1 = require("async_hooks");
|
|
5
|
+
class TransactionContextManager {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.storage = new async_hooks_1.AsyncLocalStorage();
|
|
8
|
+
}
|
|
9
|
+
run(tx, callback) {
|
|
10
|
+
return this.storage.run({ tx }, callback);
|
|
11
|
+
}
|
|
12
|
+
getContext() {
|
|
13
|
+
return this.storage.getStore()?.tx;
|
|
14
|
+
}
|
|
15
|
+
hasContext() {
|
|
16
|
+
return this.storage.getStore() !== undefined;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.transactionContext = new TransactionContextManager();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Options } from '../domain/entities';
|
|
2
|
+
import { ValueOrInstance } from '../driver/driver.interface';
|
|
3
|
+
export declare class ValueProcessor {
|
|
4
|
+
static processForInsert<T>(values: Partial<{
|
|
5
|
+
[K in keyof T]: ValueOrInstance<T[K]>;
|
|
6
|
+
}>, options: Options): Record<string, any>;
|
|
7
|
+
static processForUpdate<T>(values: Partial<{
|
|
8
|
+
[K in keyof T]: ValueOrInstance<T[K]>;
|
|
9
|
+
}>, options: Options): Record<string, any>;
|
|
10
|
+
static getColumnName(propertyKey: string, entity: Options): string;
|
|
11
|
+
static createInstance(values: any, entity: Function, moment?: 'insert' | 'update' | undefined): any;
|
|
12
|
+
private static isValueObject;
|
|
13
|
+
private static isBaseEntity;
|
|
14
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValueProcessor = void 0;
|
|
4
|
+
const value_object_1 = require("../common/value-object");
|
|
5
|
+
const base_entity_1 = require("../domain/base-entity");
|
|
6
|
+
const entities_1 = require("../domain/entities");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
class ValueProcessor {
|
|
9
|
+
static processForInsert(values, options) {
|
|
10
|
+
const newValue = {};
|
|
11
|
+
for (const value in values) {
|
|
12
|
+
const columnName = ValueProcessor.getColumnName(value, options);
|
|
13
|
+
if (ValueProcessor.isValueObject(values[value])) {
|
|
14
|
+
newValue[columnName] = values[value].getValue();
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (ValueProcessor.isBaseEntity(values[value])) {
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
newValue[columnName] = values[value].id;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
newValue[columnName] = values[value];
|
|
23
|
+
}
|
|
24
|
+
return newValue;
|
|
25
|
+
}
|
|
26
|
+
static processForUpdate(values, options) {
|
|
27
|
+
const newValue = {};
|
|
28
|
+
for (const value in values) {
|
|
29
|
+
const columnName = ValueProcessor.getColumnName(value, options);
|
|
30
|
+
if (ValueProcessor.isValueObject(values[value])) {
|
|
31
|
+
newValue[columnName] = values[value].getValue();
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (ValueProcessor.isBaseEntity(values[value])) {
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
newValue[columnName] = values[value].id;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
newValue[columnName] = values[value];
|
|
40
|
+
}
|
|
41
|
+
return newValue;
|
|
42
|
+
}
|
|
43
|
+
static getColumnName(propertyKey, entity) {
|
|
44
|
+
if (propertyKey.startsWith('$')) {
|
|
45
|
+
return propertyKey;
|
|
46
|
+
}
|
|
47
|
+
const property = entity.properties[propertyKey];
|
|
48
|
+
const relation = entity.relations?.find(rel => rel.propertyKey === propertyKey);
|
|
49
|
+
if (!property) {
|
|
50
|
+
if (!relation) {
|
|
51
|
+
throw new Error('Property not found');
|
|
52
|
+
}
|
|
53
|
+
return relation.columnName || propertyKey;
|
|
54
|
+
}
|
|
55
|
+
return property.options.columnName || propertyKey;
|
|
56
|
+
}
|
|
57
|
+
static createInstance(values, entity, moment = undefined) {
|
|
58
|
+
const entityStorage = entities_1.EntityStorage.getInstance();
|
|
59
|
+
const entityOptions = entityStorage.get(entity);
|
|
60
|
+
const instance = new entity();
|
|
61
|
+
if (!entityOptions) {
|
|
62
|
+
throw new Error('Entity not found');
|
|
63
|
+
}
|
|
64
|
+
const property = Object.entries(entityOptions.properties);
|
|
65
|
+
const relations = entityOptions.relations;
|
|
66
|
+
property.forEach(([key, property]) => {
|
|
67
|
+
if (property.options.onInsert && moment === 'insert') {
|
|
68
|
+
instance[key] = property.options.onInsert();
|
|
69
|
+
}
|
|
70
|
+
if (property.options.onUpdate && moment === 'update') {
|
|
71
|
+
instance[key] = property.options.onUpdate();
|
|
72
|
+
}
|
|
73
|
+
const columnName = property.options.columnName;
|
|
74
|
+
if (columnName in values) {
|
|
75
|
+
instance[key] = values[columnName];
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
if (relations) {
|
|
79
|
+
for (const relation of relations) {
|
|
80
|
+
if (relation.relation === 'many-to-one') {
|
|
81
|
+
instance[relation.propertyKey] = values[relation.columnName];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return instance;
|
|
86
|
+
}
|
|
87
|
+
static isValueObject(value) {
|
|
88
|
+
return (0, utils_1.extendsFrom)(value_object_1.ValueObject, value?.constructor?.prototype);
|
|
89
|
+
}
|
|
90
|
+
static isBaseEntity(value) {
|
|
91
|
+
return value instanceof base_entity_1.BaseEntity;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.ValueProcessor = ValueProcessor;
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDefaultLength = getDefaultLength;
|
|
4
|
+
exports.toSnakeCase = toSnakeCase;
|
|
5
|
+
exports.extendsFrom = extendsFrom;
|
|
6
|
+
function getDefaultLength(type) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
function toSnakeCase(propertyKey1) {
|
|
10
|
+
propertyKey1 = propertyKey1[0].toLowerCase() + propertyKey1.slice(1);
|
|
11
|
+
return propertyKey1.replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
12
|
+
}
|
|
13
|
+
function extendsFrom(baseClass, instance) {
|
|
14
|
+
if (!instance)
|
|
15
|
+
return false;
|
|
16
|
+
let proto = Object.getPrototypeOf(instance);
|
|
17
|
+
while (proto) {
|
|
18
|
+
if (proto === baseClass.prototype) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
proto = Object.getPrototypeOf(proto);
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@carno.js/orm",
|
|
3
|
+
"version": "0.2.3",
|
|
4
|
+
"description": "A simple ORM for Carno.js.",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
".": {
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./testing": {
|
|
15
|
+
"types": "./dist/testing/index.d.ts",
|
|
16
|
+
"require": "./dist/testing/index.js",
|
|
17
|
+
"default": "./dist/testing/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"compile": "rm -rf ./dist tsconfig.tsbuildinfo && tsc --build --force",
|
|
22
|
+
"build": "tsc --build --force",
|
|
23
|
+
"prepublishOnly": "bun run build"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"commander": "^11.1.0",
|
|
27
|
+
"globby": "^10.0.2",
|
|
28
|
+
"reflect-metadata": "^0.1.13",
|
|
29
|
+
"ts-morph": "^27.0.0"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+ssh://git@github.com:mlusca/carno.js.git"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/uuid": "^9.0.6",
|
|
37
|
+
"uuid": "^9.0.1"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@carno.js/core": "^0.2.0"
|
|
41
|
+
},
|
|
42
|
+
"author": "",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"keywords": [
|
|
48
|
+
"carno",
|
|
49
|
+
"carno.js",
|
|
50
|
+
"orm",
|
|
51
|
+
"database",
|
|
52
|
+
"sql",
|
|
53
|
+
"postgres",
|
|
54
|
+
"postgresql",
|
|
55
|
+
"bun",
|
|
56
|
+
"value-object"
|
|
57
|
+
],
|
|
58
|
+
"gitHead": "179037d66f41ab7014a008b141afce3c9232190e"
|
|
59
|
+
}
|