metal-orm 1.0.49 → 1.0.50
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/package.json
CHANGED
|
@@ -1,8 +1,107 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
1
2
|
import process from 'node:process';
|
|
2
3
|
import path from 'node:path';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
3
5
|
import { parseArgs as parseCliArgs } from 'node:util';
|
|
4
6
|
|
|
5
7
|
const DIALECTS = new Set(['postgres', 'mysql', 'sqlite', 'mssql']);
|
|
8
|
+
const NODE_NEXT_MODULE_RESOLUTIONS = new Set(['node16', 'nodenext']);
|
|
9
|
+
|
|
10
|
+
const TS_CONFIG_BASE_NAMES = ['tsconfig.json', 'tsconfig.base.json', 'tsconfig.app.json', 'tsconfig.build.json'];
|
|
11
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
12
|
+
|
|
13
|
+
const normalizeCompilerOption = value => (typeof value === 'string' ? value.trim().toLowerCase() : '');
|
|
14
|
+
|
|
15
|
+
const hasNodeNextModuleResolution = compilerOptions => {
|
|
16
|
+
if (!compilerOptions || typeof compilerOptions !== 'object') return false;
|
|
17
|
+
const moduleResolution = normalizeCompilerOption(compilerOptions.moduleResolution);
|
|
18
|
+
const moduleOption = normalizeCompilerOption(compilerOptions.module);
|
|
19
|
+
return (
|
|
20
|
+
NODE_NEXT_MODULE_RESOLUTIONS.has(moduleResolution) || NODE_NEXT_MODULE_RESOLUTIONS.has(moduleOption)
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const resolveExtendsPath = (extendsValue, baseDir) => {
|
|
25
|
+
if (!extendsValue || typeof extendsValue !== 'string') return undefined;
|
|
26
|
+
const candidatePaths = [];
|
|
27
|
+
const normalizedValue = extendsValue.trim();
|
|
28
|
+
candidatePaths.push(path.resolve(baseDir, normalizedValue));
|
|
29
|
+
if (!path.extname(normalizedValue)) {
|
|
30
|
+
candidatePaths.push(`${path.resolve(baseDir, normalizedValue)}.json`);
|
|
31
|
+
}
|
|
32
|
+
for (const candidate of candidatePaths) {
|
|
33
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
return nodeRequire.resolve(normalizedValue, { paths: [baseDir] });
|
|
37
|
+
} catch {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const inspectTsConfig = (configPath, visited) => {
|
|
43
|
+
if (!configPath) return false;
|
|
44
|
+
const normalized = path.resolve(configPath);
|
|
45
|
+
if (visited.has(normalized)) return false;
|
|
46
|
+
if (!fs.existsSync(normalized)) return false;
|
|
47
|
+
visited.add(normalized);
|
|
48
|
+
let raw;
|
|
49
|
+
try {
|
|
50
|
+
raw = fs.readFileSync(normalized, 'utf8');
|
|
51
|
+
} catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
let parsed;
|
|
55
|
+
try {
|
|
56
|
+
parsed = JSON.parse(raw);
|
|
57
|
+
} catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (hasNodeNextModuleResolution(parsed.compilerOptions)) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
if (parsed.extends) {
|
|
64
|
+
const extended = resolveExtendsPath(parsed.extends, path.dirname(normalized));
|
|
65
|
+
if (extended && inspectTsConfig(extended, visited)) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const discoverTsConfigPaths = cwd => {
|
|
73
|
+
const candidates = new Set();
|
|
74
|
+
for (const name of TS_CONFIG_BASE_NAMES) {
|
|
75
|
+
const fullPath = path.join(cwd, name);
|
|
76
|
+
if (fs.existsSync(fullPath)) {
|
|
77
|
+
candidates.add(fullPath);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const entries = fs.readdirSync(cwd);
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
const lower = entry.toLowerCase();
|
|
84
|
+
if (lower.startsWith('tsconfig') && lower.endsWith('.json')) {
|
|
85
|
+
candidates.add(path.join(cwd, entry));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} catch {
|
|
89
|
+
// ignore readdir errors
|
|
90
|
+
}
|
|
91
|
+
return Array.from(candidates);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const shouldUseJsImportExtensions = cwd => {
|
|
95
|
+
const paths = discoverTsConfigPaths(cwd);
|
|
96
|
+
if (!paths.length) return false;
|
|
97
|
+
const visited = new Set();
|
|
98
|
+
for (const configPath of paths) {
|
|
99
|
+
if (inspectTsConfig(configPath, visited)) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
};
|
|
6
105
|
|
|
7
106
|
export const parseOptions = (argv = process.argv.slice(2), env = process.env, cwd = process.cwd()) => {
|
|
8
107
|
const parser = {
|
|
@@ -52,6 +151,8 @@ export const parseOptions = (argv = process.argv.slice(2), env = process.env, cw
|
|
|
52
151
|
dryRun: Boolean(values['dry-run'])
|
|
53
152
|
};
|
|
54
153
|
|
|
154
|
+
opts.useJsImportExtensions = shouldUseJsImportExtensions(cwd);
|
|
155
|
+
|
|
55
156
|
if (!DIALECTS.has(opts.dialect)) {
|
|
56
157
|
throw new Error(`Unsupported dialect "${opts.dialect}". Supported: ${Array.from(DIALECTS).join(', ')}`);
|
|
57
158
|
}
|
|
@@ -257,11 +257,16 @@ const buildMetalOrmImportStatement = names => {
|
|
|
257
257
|
return `import { ${ordered.join(', ')} } from 'metal-orm';`;
|
|
258
258
|
};
|
|
259
259
|
|
|
260
|
-
const
|
|
260
|
+
const appendJsExtension = (specifier, useExtension) => (useExtension ? `${specifier}.js` : specifier);
|
|
261
|
+
|
|
262
|
+
const getRelativeModuleSpecifier = (from, to, extension = '') => {
|
|
261
263
|
const rel = path.relative(path.dirname(from), to).replace(/\\/g, '/');
|
|
262
|
-
if (!rel)
|
|
264
|
+
if (!rel) {
|
|
265
|
+
return './';
|
|
266
|
+
}
|
|
263
267
|
const withoutExt = rel.replace(/\.ts$/i, '');
|
|
264
|
-
|
|
268
|
+
const normalized = withoutExt.startsWith('.') ? withoutExt : `./${withoutExt}`;
|
|
269
|
+
return `${normalized}${extension}`;
|
|
265
270
|
};
|
|
266
271
|
|
|
267
272
|
export const renderEntityFile = (schema, options) => {
|
|
@@ -368,7 +373,8 @@ export const renderSplitEntityFiles = (schema, options) => {
|
|
|
368
373
|
importLines.push(metalImportStatement);
|
|
369
374
|
}
|
|
370
375
|
for (const targetClass of Array.from(relationImports).sort()) {
|
|
371
|
-
|
|
376
|
+
const specifier = appendJsExtension(`./${targetClass}`, options.useJsImportExtensions);
|
|
377
|
+
importLines.push(`import { ${targetClass} } from '${specifier}';`);
|
|
372
378
|
}
|
|
373
379
|
|
|
374
380
|
const lines = [
|
|
@@ -404,7 +410,11 @@ export const renderSplitIndexFile = (metadata, options) => {
|
|
|
404
410
|
for (const table of metadata.tables) {
|
|
405
411
|
const className = metadata.classNames.get(table.name);
|
|
406
412
|
const filePath = path.join(options.outDir, `${className}.ts`);
|
|
407
|
-
const moduleSpecifier = getRelativeModuleSpecifier(
|
|
413
|
+
const moduleSpecifier = getRelativeModuleSpecifier(
|
|
414
|
+
options.out,
|
|
415
|
+
filePath,
|
|
416
|
+
options.useJsImportExtensions ? '.js' : ''
|
|
417
|
+
);
|
|
408
418
|
importLines.push(`import { ${className} } from '${moduleSpecifier}';`);
|
|
409
419
|
exportedClasses.push(className);
|
|
410
420
|
}
|