@orxataguy/tyr 1.0.11-beta.2 → 1.0.11-beta.4

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/loader.mjs CHANGED
@@ -13,10 +13,54 @@
13
13
  */
14
14
 
15
15
  import { transformSync } from 'esbuild';
16
- import { readFileSync } from 'fs';
17
- import { fileURLToPath } from 'url';
16
+ import { existsSync, readFileSync } from 'fs';
17
+ import { fileURLToPath, pathToFileURL } from 'url';
18
+ import { resolve as resolvePath, dirname } from 'path';
18
19
 
19
- const TS_RE = /\.m?[ct]?ts$/;
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
+ }
20
64
 
21
65
  /**
22
66
  * load() — intercept every ESM import whose URL ends in a TypeScript extension.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orxataguy/tyr",
3
- "version": "1.0.11-beta.2",
3
+ "version": "1.0.11-beta.4",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "tyr": "./bin/tyr.js"
@@ -4,17 +4,17 @@ 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.ts';
8
8
 
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 build from './sys/build';
14
- import config from './sys/config';
15
- import help from './sys/help';
9
+ import gen from './sys/gen.ts';
10
+ import rem from './sys/rem.ts';
11
+ import doc from './sys/doc.ts';
12
+ import ai from './sys/ai.ts';
13
+ import build from './sys/build.ts';
14
+ import config from './sys/config.ts';
15
+ import help from './sys/help.ts';
16
16
 
17
- import { TyrError } from './TyrError';
17
+ import { TyrError } from './TyrError.ts';
18
18
 
19
19
  interface TyrConfig {
20
20
  commands: Record<string, string>;