@orxataguy/tyr 1.0.11-beta.4 → 1.0.11-beta.8
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/bin/tyr.js +19 -37
- package/package.json +3 -4
- package/src/core/Kernel.ts +19 -45
- package/src/core/sys/help.ts +0 -1
- package/bin/loader.mjs +0 -98
package/bin/tyr.js
CHANGED
|
@@ -1,46 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
* Spawns Node.js with a custom ESM loader (bin/loader.mjs) that transpiles
|
|
6
|
-
* TypeScript files in-memory using esbuild. This replaces the previous tsx
|
|
7
|
-
* dependency, eliminating all disk-write overhead from TypeScript compilation
|
|
8
|
-
* caches (~/.cache/tsx).
|
|
9
|
-
*
|
|
10
|
-
* Compatibility: Node.js 18+
|
|
11
|
-
* The --loader flag is experimental in Node 22 but fully functional;
|
|
12
|
-
* NODE_NO_WARNINGS suppresses the deprecation notice.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { fileURLToPath, pathToFileURL } from 'url';
|
|
16
|
-
import { dirname, join } from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { dirname, resolve, join } from 'path';
|
|
17
4
|
import { spawn } from 'child_process';
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
18
6
|
|
|
19
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
-
const __dirname
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
const packageRoot = resolve(__dirname, '..');
|
|
21
10
|
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
const
|
|
11
|
+
// Locate tsx's CLI entry directly from its package.json — no shell, no .cmd wrappers
|
|
12
|
+
const tsxPkg = JSON.parse(readFileSync(join(packageRoot, 'node_modules', 'tsx', 'package.json'), 'utf-8'));
|
|
13
|
+
const tsxBinField = tsxPkg.bin;
|
|
14
|
+
const tsxBinRelative = typeof tsxBinField === 'string' ? tsxBinField : (tsxBinField.tsx ?? tsxBinField['tsx']);
|
|
15
|
+
const tsxEntry = join(packageRoot, 'node_modules', 'tsx', tsxBinRelative);
|
|
16
|
+
const entry = join(__dirname, 'tyr.ts');
|
|
25
17
|
|
|
26
|
-
const child = spawn(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
'--loader', loaderUrl,
|
|
30
|
-
'--no-warnings', // suppress ExperimentalWarning for --loader in Node 22
|
|
31
|
-
entry,
|
|
32
|
-
...process.argv.slice(2),
|
|
33
|
-
],
|
|
34
|
-
{
|
|
35
|
-
stdio: 'inherit',
|
|
36
|
-
env: { ...process.env },
|
|
37
|
-
}
|
|
38
|
-
);
|
|
18
|
+
const child = spawn(process.execPath, [tsxEntry, entry, ...process.argv.slice(2)], {
|
|
19
|
+
stdio: 'inherit'
|
|
20
|
+
});
|
|
39
21
|
|
|
40
|
-
child.on('exit',
|
|
41
|
-
child.on('error', (err)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
22
|
+
child.on('exit', (code) => process.exit(code ?? 0));
|
|
23
|
+
child.on('error', (err) => {
|
|
24
|
+
console.error(`Error: Could not start tyr. ${err.message}`);
|
|
25
|
+
console.error(`tsx not found at: ${tsxEntry}`);
|
|
26
|
+
console.error('Try reinstalling: npm install -g @orxataguy/tyr');
|
|
45
27
|
process.exit(1);
|
|
46
28
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orxataguy/tyr",
|
|
3
|
-
"version": "1.0.11-beta.
|
|
3
|
+
"version": "1.0.11-beta.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tyr": "./bin/tyr.js"
|
|
@@ -48,13 +48,13 @@
|
|
|
48
48
|
"chalk": "^5.6.2",
|
|
49
49
|
"cheerio": "^1.1.2",
|
|
50
50
|
"dotenv": "^17.2.3",
|
|
51
|
-
"esbuild": "^0.25.0",
|
|
52
51
|
"execa": "^6.1.0",
|
|
53
52
|
"find-config": "^1.0.0",
|
|
54
53
|
"inquirer": "^13.2.1",
|
|
55
54
|
"js-yaml": "^4.1.1",
|
|
56
55
|
"mongodb": "^7.2.0",
|
|
57
|
-
"mssql": "^12.2.0"
|
|
56
|
+
"mssql": "^12.2.0",
|
|
57
|
+
"tsx": "^4.21.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -62,7 +62,6 @@
|
|
|
62
62
|
"@vitest/coverage-v8": "^3.2.4",
|
|
63
63
|
"@vitest/ui": "^3.2.4",
|
|
64
64
|
"husky": "^9.1.7",
|
|
65
|
-
"tsx": "^4.21.0",
|
|
66
65
|
"typescript": "^5.9.3",
|
|
67
66
|
"vite": "^7.3.1",
|
|
68
67
|
"vitest": "^3.2.4"
|
package/src/core/Kernel.ts
CHANGED
|
@@ -4,17 +4,16 @@ import yaml from 'js-yaml';
|
|
|
4
4
|
import dotenv from 'dotenv';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
6
6
|
import { homedir } from 'os';
|
|
7
|
-
import { Container } from './Container
|
|
7
|
+
import { Container } from './Container';
|
|
8
8
|
|
|
9
|
-
import gen
|
|
10
|
-
import rem
|
|
11
|
-
import doc
|
|
12
|
-
import ai
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import help from './sys/help.ts';
|
|
9
|
+
import gen from './sys/gen';
|
|
10
|
+
import rem from './sys/rem';
|
|
11
|
+
import doc from './sys/doc';
|
|
12
|
+
import ai from './sys/ai';
|
|
13
|
+
import config from './sys/config';
|
|
14
|
+
import help from './sys/help';
|
|
16
15
|
|
|
17
|
-
import { TyrError } from './TyrError
|
|
16
|
+
import { TyrError } from './TyrError';
|
|
18
17
|
|
|
19
18
|
interface TyrConfig {
|
|
20
19
|
commands: Record<string, string>;
|
|
@@ -46,13 +45,6 @@ export class Kernel {
|
|
|
46
45
|
private frameworkRoot: string;
|
|
47
46
|
private userRoot: string;
|
|
48
47
|
|
|
49
|
-
/**
|
|
50
|
-
* In-process cache of CommandFactory functions keyed by command name.
|
|
51
|
-
* Avoids re-importing (and re-transpiling via the ESM loader) the same
|
|
52
|
-
* module on every run() call within the same process.
|
|
53
|
-
*/
|
|
54
|
-
private readonly _commandCache = new Map<string, CommandFactory>();
|
|
55
|
-
|
|
56
48
|
constructor() {
|
|
57
49
|
this.container = new Container();
|
|
58
50
|
this.config = null;
|
|
@@ -188,7 +180,6 @@ export class Kernel {
|
|
|
188
180
|
rem,
|
|
189
181
|
doc,
|
|
190
182
|
ai,
|
|
191
|
-
build,
|
|
192
183
|
};
|
|
193
184
|
|
|
194
185
|
if (systemCommands[commandName]) {
|
|
@@ -213,37 +204,20 @@ export class Kernel {
|
|
|
213
204
|
}
|
|
214
205
|
|
|
215
206
|
try {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
? scriptPath
|
|
225
|
-
: path.resolve(this.frameworkRoot, scriptPath);
|
|
226
|
-
|
|
227
|
-
// Prefer a pre-compiled JS file produced by `tyr build` (AOT path).
|
|
228
|
-
// Convention: ~/.tyr/dist/<basename>.js where basename = original filename with .ts → .js
|
|
229
|
-
const distFile = path.basename(absolutePath).replace(/\.ts$/, '.js');
|
|
230
|
-
const distPath = path.join(this.userRoot, 'dist', distFile);
|
|
231
|
-
const resolvedPath = fs.existsSync(distPath) ? distPath : absolutePath;
|
|
232
|
-
|
|
233
|
-
// Convert to file:// URL — required by ESM on Windows for absolute paths
|
|
234
|
-
const moduleUrl = pathToFileURL(resolvedPath).href;
|
|
235
|
-
const module = await import(moduleUrl);
|
|
236
|
-
|
|
237
|
-
if (typeof module.default !== 'function') {
|
|
238
|
-
throw new Error(`File ${scriptPath} does not export a default function.`);
|
|
239
|
-
}
|
|
207
|
+
// Absolute paths (user commands) are used directly; relative paths resolve from frameworkRoot
|
|
208
|
+
const absolutePath = path.isAbsolute(scriptPath)
|
|
209
|
+
? scriptPath
|
|
210
|
+
: path.resolve(this.frameworkRoot, scriptPath);
|
|
211
|
+
|
|
212
|
+
// Convert to file:// URL — required by ESM on Windows for absolute paths
|
|
213
|
+
const moduleUrl = pathToFileURL(absolutePath).href;
|
|
214
|
+
const module = await import(moduleUrl);
|
|
240
215
|
|
|
241
|
-
|
|
242
|
-
|
|
216
|
+
if (typeof module.default !== 'function') {
|
|
217
|
+
throw new Error(`File ${scriptPath} does not export a default function.`);
|
|
243
218
|
}
|
|
244
219
|
|
|
245
|
-
|
|
246
|
-
// reflects the current invocation — important for nested run() calls.
|
|
220
|
+
const commandFactory: CommandFactory = module.default;
|
|
247
221
|
const command = commandFactory(context);
|
|
248
222
|
await command(args.slice(1));
|
|
249
223
|
|
package/src/core/sys/help.ts
CHANGED
|
@@ -82,7 +82,6 @@ export default function help({ userRoot }: TyrContext) {
|
|
|
82
82
|
{ name: '--update', description: 'Actualiza ~/.tyr desde el repositorio git.', usage: 'tyr --update' },
|
|
83
83
|
{ name: '--upgrade', description: 'Actualiza el paquete npm de tyr.', usage: 'tyr --upgrade' },
|
|
84
84
|
{ name: 'gen', description: 'Genera un nuevo comando a partir de una descripción con IA.', usage: 'tyr gen <nombre> "<descripción>"' },
|
|
85
|
-
{ name: 'build', description: 'Compila AOT todos los comandos de map.yml a JS puro (elimina overhead de transpilación en ejecución).', usage: 'tyr build [--clean]' },
|
|
86
85
|
{ name: 'doc', description: 'Levanta la documentación del framework en el navegador.', usage: 'tyr doc' },
|
|
87
86
|
];
|
|
88
87
|
|
package/bin/loader.mjs
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* bin/loader.mjs
|
|
3
|
-
*
|
|
4
|
-
* Custom Node.js ESM loader for Tyr.
|
|
5
|
-
* Transpiles TypeScript files on-the-fly using esbuild.transformSync().
|
|
6
|
-
*
|
|
7
|
-
* Key properties:
|
|
8
|
-
* - Zero disk writes: all transpilation happens in memory — no ~/.cache/tsx or similar
|
|
9
|
-
* - Fast: esbuild native binary is 50-100× faster than the full TypeScript compiler
|
|
10
|
-
* - No type-checking: types are stripped, not verified (run tsc --noEmit separately)
|
|
11
|
-
*
|
|
12
|
-
* Registered via --loader flag in bin/tyr.js.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { transformSync } from 'esbuild';
|
|
16
|
-
import { existsSync, readFileSync } from 'fs';
|
|
17
|
-
import { fileURLToPath, pathToFileURL } from 'url';
|
|
18
|
-
import { resolve as resolvePath, dirname } from 'path';
|
|
19
|
-
|
|
20
|
-
const TS_RE = /\.m?[ct]?ts$/;
|
|
21
|
-
const NO_EXT_RE = /\/[^./]+$/; // path segment with no extension at the end
|
|
22
|
-
const EXT_MAP = { '.js': '.ts', '.mjs': '.mts', '.cjs': '.cts' };
|
|
23
|
-
const BARE_EXTS = ['.ts', '.mts', '.cts', '.js', '.mjs', '/index.ts', '/index.js'];
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* resolve() — handle two TypeScript-in-ESM conventions that Node cannot resolve natively:
|
|
27
|
-
*
|
|
28
|
-
* 1. Extensionless imports: './Container' → './Container.ts'
|
|
29
|
-
* 2. JS-extension imports: './Foo.js' → './Foo.ts' (TypeScript ESM idiom)
|
|
30
|
-
*
|
|
31
|
-
* Only relative imports are intercepted; bare specifiers (npm packages) go straight
|
|
32
|
-
* to the default resolver.
|
|
33
|
-
*/
|
|
34
|
-
export function resolve(specifier, context, next) {
|
|
35
|
-
if (!specifier.startsWith('.') || !context.parentURL) {
|
|
36
|
-
return next(specifier, context);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const parentDir = dirname(fileURLToPath(context.parentURL));
|
|
40
|
-
const fullPath = resolvePath(parentDir, specifier);
|
|
41
|
-
|
|
42
|
-
// Case 1: specifier ends with a JS extension — try the equivalent TS extension
|
|
43
|
-
for (const [jsExt, tsExt] of Object.entries(EXT_MAP)) {
|
|
44
|
-
if (specifier.endsWith(jsExt)) {
|
|
45
|
-
const tsPath = fullPath.slice(0, -jsExt.length) + tsExt;
|
|
46
|
-
if (existsSync(tsPath)) {
|
|
47
|
-
return { url: pathToFileURL(tsPath).href, shortCircuit: true };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Case 2: extensionless — probe TS then JS extensions
|
|
53
|
-
if (NO_EXT_RE.test(fullPath)) {
|
|
54
|
-
for (const ext of BARE_EXTS) {
|
|
55
|
-
const candidate = fullPath + ext;
|
|
56
|
-
if (existsSync(candidate)) {
|
|
57
|
-
return { url: pathToFileURL(candidate).href, shortCircuit: true };
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return next(specifier, context);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* load() — intercept every ESM import whose URL ends in a TypeScript extension.
|
|
67
|
-
*
|
|
68
|
-
* We do NOT exclude node_modules: the tyr package itself ships as .ts source
|
|
69
|
-
* (bin/tyr.ts, src/core/Kernel.ts, etc.) and those files ARE under node_modules
|
|
70
|
-
* when installed globally. Node.js 24's built-in strip-types refuses to handle
|
|
71
|
-
* .ts files under node_modules, so our loader must cover them.
|
|
72
|
-
*
|
|
73
|
-
* The TS_RE regex already limits interception to .ts/.mts/.cts files — the
|
|
74
|
-
* compiled .js files that third-party packages ship will never match it.
|
|
75
|
-
*/
|
|
76
|
-
export function load(url, context, next) {
|
|
77
|
-
const isTs = TS_RE.test(url);
|
|
78
|
-
if (!isTs) return next(url, context);
|
|
79
|
-
|
|
80
|
-
const filePath = fileURLToPath(url);
|
|
81
|
-
const source = readFileSync(filePath, 'utf8');
|
|
82
|
-
|
|
83
|
-
const { code, warnings } = transformSync(source, {
|
|
84
|
-
loader: 'ts',
|
|
85
|
-
format: 'esm',
|
|
86
|
-
target: 'node18',
|
|
87
|
-
sourcemap: 'inline', // inline maps so stack traces point to .ts lines
|
|
88
|
-
sourcefile: filePath,
|
|
89
|
-
// Do not inject helpers — keep output minimal
|
|
90
|
-
treeShaking: false,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
for (const w of warnings) {
|
|
94
|
-
process.stderr.write(`[tyr:loader] warning: ${w.text}\n`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return { format: 'module', source: code, shortCircuit: true };
|
|
98
|
-
}
|