@soda-gql/common 0.11.26 → 0.12.1
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/dist/{canonical-id-DHdeYIsT.cjs → canonical-id-CcqNJHU4.cjs} +2 -2
- package/dist/{canonical-id-DHdeYIsT.cjs.map → canonical-id-CcqNJHU4.cjs.map} +1 -1
- package/dist/{canonical-id-9alor9gv.mjs → canonical-id-U2VNaQ86.mjs} +2 -2
- package/dist/{canonical-id-9alor9gv.mjs.map → canonical-id-U2VNaQ86.mjs.map} +1 -1
- package/dist/canonical-id.cjs +2 -2
- package/dist/canonical-id.mjs +2 -2
- package/dist/{index-BCu9PNbZ.d.mts → index-B1w5x8e3.d.mts} +25 -2
- package/dist/index-B1w5x8e3.d.mts.map +1 -0
- package/dist/{index-BMl8pzFY.d.cts → index-BDPAGTeS.d.cts} +25 -2
- package/dist/index-BDPAGTeS.d.cts.map +1 -0
- package/dist/index.cjs +5 -4
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +3 -3
- package/dist/{portable-B3K3IE7E.cjs → portable-B75a5KJA.cjs} +2 -2
- package/dist/{portable-B3K3IE7E.cjs.map → portable-B75a5KJA.cjs.map} +1 -1
- package/dist/portable.cjs +1 -1
- package/dist/{utils-Rs7YbafF.cjs → utils-C2CEQL5v.cjs} +45 -2
- package/dist/utils-C2CEQL5v.cjs.map +1 -0
- package/dist/{utils-ZCE_eqCf.mjs → utils-DlhM4qvh.mjs} +39 -2
- package/dist/utils-DlhM4qvh.mjs.map +1 -0
- package/dist/utils.cjs +2 -1
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +2 -2
- package/dist/{zod-DjI3IUH3.cjs → zod-DQuWqRtm.cjs} +2 -2
- package/dist/{zod-DjI3IUH3.cjs.map → zod-DQuWqRtm.cjs.map} +1 -1
- package/dist/zod.cjs +1 -1
- package/package.json +12 -11
- package/dist/index-BCu9PNbZ.d.mts.map +0 -1
- package/dist/index-BMl8pzFY.d.cts.map +0 -1
- package/dist/utils-Rs7YbafF.cjs.map +0 -1
- package/dist/utils-ZCE_eqCf.mjs.map +0 -1
|
@@ -25,7 +25,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
28
|
-
const require_utils = require('./utils-
|
|
28
|
+
const require_utils = require('./utils-C2CEQL5v.cjs');
|
|
29
29
|
let node_path = require("node:path");
|
|
30
30
|
let zod = require("zod");
|
|
31
31
|
zod = __toESM(zod);
|
|
@@ -316,4 +316,4 @@ Object.defineProperty(exports, 'validateCanonicalId', {
|
|
|
316
316
|
return validateCanonicalId;
|
|
317
317
|
}
|
|
318
318
|
});
|
|
319
|
-
//# sourceMappingURL=canonical-id-
|
|
319
|
+
//# sourceMappingURL=canonical-id-CcqNJHU4.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical-id-DHdeYIsT.cjs","names":["CanonicalIdSchema: z.ZodType<CanonicalId>","z","resolved","normalized","normalizePath","idParts","scopeStack: ScopeFrame[]","frame: ScopeFrame","exportBinding: string | undefined"],"sources":["../src/canonical-id/canonical-id.ts","../src/canonical-id/path-tracker.ts"],"sourcesContent":["import { isAbsolute, relative, resolve } from \"node:path\";\nimport z from \"zod\";\nimport { normalizePath } from \"../utils\";\n\nexport type CanonicalId = string & { readonly __brand: \"CanonicalId\" };\n\nconst canonicalIdSeparator = \"::\" as const;\n\nexport const CanonicalIdSchema: z.ZodType<CanonicalId> = z.string() as unknown as z.ZodType<CanonicalId>;\n\n/**\n * Options for creating a canonical ID.\n */\nexport type CreateCanonicalIdOptions = {\n /**\n * Base directory for relative path computation.\n * When provided, the canonical ID will use a relative path from baseDir.\n * When undefined, an absolute path is required and used as-is.\n */\n readonly baseDir?: string;\n};\n\n/**\n * Create a canonical ID from a file path and AST path.\n *\n * @param filePath - The file path (absolute, or relative if baseDir is provided)\n * @param astPath - The AST path identifying the definition within the file\n * @param options - Optional configuration including baseDir for relative path support\n * @returns A canonical ID in the format \"{path}::{astPath}\"\n */\nexport const createCanonicalId = (filePath: string, astPath: string, options?: CreateCanonicalIdOptions): CanonicalId => {\n const { baseDir } = options ?? {};\n\n if (baseDir) {\n // With baseDir, compute relative path\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(baseDir, filePath);\n const resolved = resolve(absolutePath);\n const relativePath = relative(baseDir, resolved);\n const normalized = normalizePath(relativePath);\n\n const idParts = [normalized, astPath];\n return idParts.join(canonicalIdSeparator) as CanonicalId;\n }\n\n // Without baseDir, require absolute path (legacy behavior)\n if (!isAbsolute(filePath)) {\n throw new Error(\"[INTERNAL] CANONICAL_ID_REQUIRES_ABSOLUTE_PATH\");\n }\n\n const resolved = resolve(filePath);\n const normalized = normalizePath(resolved);\n\n // Create a 2-part ID: {absPath}::{astPath}\n // astPath uniquely identifies the definition's location in the AST (e.g., \"MyComponent.useQuery.def\")\n const idParts = [normalized, astPath];\n\n return idParts.join(canonicalIdSeparator) as CanonicalId;\n};\n\n/**\n * Check if a canonical ID uses a relative path.\n * Relative canonical IDs do not start with '/'.\n *\n * @param canonicalId - The canonical ID to check\n * @returns true if the canonical ID uses a relative path\n */\nexport const isRelativeCanonicalId = (canonicalId: CanonicalId | string): boolean => {\n return !canonicalId.startsWith(\"/\");\n};\n\n/**\n * Parse a canonical ID into its components.\n * @param canonicalId - The canonical ID to parse (e.g., \"/app/src/user.ts::userFragment\")\n * @returns An object with filePath and astPath\n */\nexport const parseCanonicalId = (\n canonicalId: CanonicalId | string,\n): {\n filePath: string;\n astPath: string;\n} => {\n const idx = canonicalId.indexOf(canonicalIdSeparator);\n if (idx === -1) {\n return { filePath: canonicalId, astPath: \"\" };\n }\n return {\n filePath: canonicalId.slice(0, idx),\n astPath: canonicalId.slice(idx + canonicalIdSeparator.length),\n };\n};\n\n/**\n * Validation result for canonical ID format.\n */\nexport type CanonicalIdValidationResult = { readonly isValid: true } | { readonly isValid: false; readonly reason: string };\n\n/**\n * Validate a canonical ID format.\n * A valid canonical ID has format: \"{filePath}::{astPath}\"\n * where both filePath and astPath are non-empty.\n *\n * @param canonicalId - The canonical ID to validate\n * @returns Validation result with isValid boolean and optional error reason\n */\nexport const validateCanonicalId = (canonicalId: string): CanonicalIdValidationResult => {\n const idx = canonicalId.indexOf(canonicalIdSeparator);\n\n if (idx === -1) {\n return { isValid: false, reason: \"missing '::' separator\" };\n }\n\n const filePath = canonicalId.slice(0, idx);\n const astPath = canonicalId.slice(idx + canonicalIdSeparator.length);\n\n if (filePath === \"\") {\n return { isValid: false, reason: \"empty file path\" };\n }\n\n if (astPath === \"\") {\n return { isValid: false, reason: \"empty AST path\" };\n }\n\n return { isValid: true };\n};\n","/**\n * Canonical path tracker for AST traversal.\n *\n * This module provides a stateful helper that tracks scope information during\n * AST traversal to generate canonical IDs. It's designed to integrate with\n * existing plugin visitor patterns (Babel, SWC, TypeScript) without requiring\n * a separate AST traversal.\n *\n * Usage pattern:\n * 1. Plugin creates tracker at file/program entry\n * 2. Plugin calls enterScope/exitScope during its traversal\n * 3. Plugin calls registerDefinition when discovering GQL definitions\n * 4. Tracker provides canonical ID information\n */\n\nimport type { CanonicalId } from \"./canonical-id\";\nimport { createCanonicalId } from \"./canonical-id\";\n\n/**\n * Scope frame for tracking AST path segments\n */\nexport type ScopeFrame = {\n /** Name segment (e.g., \"MyComponent\", \"useQuery\", \"arrow#1\") */\n readonly nameSegment: string;\n /** Kind of scope */\n readonly kind: \"function\" | \"class\" | \"variable\" | \"property\" | \"method\" | \"expression\";\n /** Occurrence index for disambiguation */\n readonly occurrence: number;\n};\n\n/**\n * Opaque handle for scope tracking\n */\nexport type ScopeHandle = {\n readonly __brand: \"ScopeHandle\";\n readonly depth: number;\n};\n\n/**\n * Canonical path tracker interface\n */\nexport interface CanonicalPathTracker {\n /**\n * Enter a new scope during traversal\n * @param options Scope information\n * @returns Handle to use when exiting the scope\n */\n enterScope(options: { segment: string; kind: ScopeFrame[\"kind\"]; stableKey?: string }): ScopeHandle;\n\n /**\n * Exit a scope during traversal\n * @param handle Handle returned from enterScope\n */\n exitScope(handle: ScopeHandle): void;\n\n /**\n * Register a definition discovered during traversal\n * @returns Definition metadata including astPath and canonical ID information\n */\n registerDefinition(): {\n astPath: string;\n isTopLevel: boolean;\n exportBinding?: string;\n };\n\n /**\n * Resolve a canonical ID from an astPath\n * @param astPath AST path string\n * @returns Canonical ID\n */\n resolveCanonicalId(astPath: string): CanonicalId;\n\n /**\n * Register an export binding\n * @param local Local variable name\n * @param exported Exported name\n */\n registerExportBinding(local: string, exported: string): void;\n\n /**\n * Get current scope depth\n * @returns Current depth (0 = top level)\n */\n currentDepth(): number;\n}\n\n/**\n * Build AST path from scope stack (internal helper)\n */\nconst _buildAstPath = (stack: readonly ScopeFrame[]): string => {\n return stack.map((frame) => frame.nameSegment).join(\".\");\n};\n\n/**\n * Create a canonical path tracker\n *\n * @param options Configuration options\n * @returns Tracker instance\n *\n * @example\n * ```typescript\n * // In a Babel plugin\n * const tracker = createCanonicalTracker({ filePath: state.filename });\n *\n * const visitor = {\n * FunctionDeclaration: {\n * enter(path) {\n * const handle = tracker.enterScope({\n * segment: path.node.id.name,\n * kind: 'function'\n * });\n * },\n * exit(path) {\n * tracker.exitScope(handle);\n * }\n * }\n * };\n * ```\n */\nexport const createCanonicalTracker = (options: {\n filePath: string;\n /**\n * Base directory for relative path computation in canonical IDs.\n * When provided, canonical IDs will use relative paths from baseDir.\n */\n baseDir?: string;\n getExportName?: (localName: string) => string | undefined;\n}): CanonicalPathTracker => {\n const { filePath, baseDir, getExportName } = options;\n\n // Scope stack\n const scopeStack: ScopeFrame[] = [];\n\n // Occurrence counters for disambiguating duplicate names\n const occurrenceCounters = new Map<string, number>();\n\n // Used paths for ensuring uniqueness\n const usedPaths = new Set<string>();\n\n // Export bindings map\n const exportBindings = new Map<string, string>();\n\n const getNextOccurrence = (key: string): number => {\n const current = occurrenceCounters.get(key) ?? 0;\n occurrenceCounters.set(key, current + 1);\n return current;\n };\n\n const ensureUniquePath = (basePath: string): string => {\n let path = basePath;\n let suffix = 0;\n while (usedPaths.has(path)) {\n suffix++;\n path = `${basePath}$${suffix}`;\n }\n usedPaths.add(path);\n return path;\n };\n\n return {\n enterScope({ segment, kind, stableKey }): ScopeHandle {\n const key = stableKey ?? `${kind}:${segment}`;\n const occurrence = getNextOccurrence(key);\n\n const frame: ScopeFrame = {\n nameSegment: segment,\n kind,\n occurrence,\n };\n\n scopeStack.push(frame);\n\n return {\n __brand: \"ScopeHandle\",\n depth: scopeStack.length - 1,\n } as ScopeHandle;\n },\n\n exitScope(handle: ScopeHandle): void {\n // Validate handle depth matches current stack\n if (handle.depth !== scopeStack.length - 1) {\n throw new Error(`[INTERNAL] Invalid scope exit: expected depth ${scopeStack.length - 1}, got ${handle.depth}`);\n }\n scopeStack.pop();\n },\n\n registerDefinition(): {\n astPath: string;\n isTopLevel: boolean;\n exportBinding?: string;\n } {\n const basePath = _buildAstPath(scopeStack);\n const astPath = ensureUniquePath(basePath);\n const isTopLevel = scopeStack.length === 0;\n\n // Check export binding if provided\n let exportBinding: string | undefined;\n if (getExportName && isTopLevel) {\n // For top-level definitions, try to get export name\n // This is a simplified version - real logic depends on how the definition is bound\n exportBinding = undefined;\n }\n\n return {\n astPath,\n isTopLevel,\n exportBinding,\n };\n },\n\n resolveCanonicalId(astPath: string): CanonicalId {\n return createCanonicalId(filePath, astPath, { baseDir });\n },\n\n registerExportBinding(local: string, exported: string): void {\n exportBindings.set(local, exported);\n },\n\n currentDepth(): number {\n return scopeStack.length;\n },\n };\n};\n\n/**\n * Helper to create occurrence tracker (for backward compatibility)\n */\nexport const createOccurrenceTracker = (): {\n getNextOccurrence: (key: string) => number;\n} => {\n const occurrenceCounters = new Map<string, number>();\n\n return {\n getNextOccurrence(key: string): number {\n const current = occurrenceCounters.get(key) ?? 0;\n occurrenceCounters.set(key, current + 1);\n return current;\n },\n };\n};\n\n/**\n * Helper to create path tracker (for backward compatibility)\n */\nexport const createPathTracker = (): {\n ensureUniquePath: (basePath: string) => string;\n} => {\n const usedPaths = new Set<string>();\n\n return {\n ensureUniquePath(basePath: string): string {\n let path = basePath;\n let suffix = 0;\n while (usedPaths.has(path)) {\n suffix++;\n path = `${basePath}$${suffix}`;\n }\n usedPaths.add(path);\n return path;\n },\n };\n};\n\n/**\n * Build AST path from scope stack (for backward compatibility)\n */\nexport const buildAstPath = (stack: readonly ScopeFrame[]): string => {\n return stack.map((frame) => frame.nameSegment).join(\".\");\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,MAAM,uBAAuB;AAE7B,MAAaA,oBAA4CC,YAAE,QAAQ;;;;;;;;;AAsBnE,MAAa,qBAAqB,UAAkB,SAAiB,YAAoD;CACvH,MAAM,EAAE,YAAY,WAAW,EAAE;AAEjC,KAAI,SAAS;EAEX,MAAM,yCAA0B,SAAS,GAAG,kCAAmB,SAAS,SAAS;EACjF,MAAMC,oCAAmB,aAAa;EACtC,MAAM,uCAAwB,SAASA,WAAS;EAChD,MAAMC,eAAaC,4BAAc,aAAa;EAE9C,MAAMC,YAAU,CAACF,cAAY,QAAQ;AACrC,SAAOE,UAAQ,KAAK,qBAAqB;;AAI3C,KAAI,2BAAY,SAAS,EAAE;AACzB,QAAM,IAAI,MAAM,iDAAiD;;CAGnE,MAAM,kCAAmB,SAAS;CAClC,MAAM,aAAaD,4BAAc,SAAS;CAI1C,MAAM,UAAU,CAAC,YAAY,QAAQ;AAErC,QAAO,QAAQ,KAAK,qBAAqB;;;;;;;;;AAU3C,MAAa,yBAAyB,gBAA+C;AACnF,QAAO,CAAC,YAAY,WAAW,IAAI;;;;;;;AAQrC,MAAa,oBACX,gBAIG;CACH,MAAM,MAAM,YAAY,QAAQ,qBAAqB;AACrD,KAAI,QAAQ,CAAC,GAAG;AACd,SAAO;GAAE,UAAU;GAAa,SAAS;GAAI;;AAE/C,QAAO;EACL,UAAU,YAAY,MAAM,GAAG,IAAI;EACnC,SAAS,YAAY,MAAM,MAAM,qBAAqB,OAAO;EAC9D;;;;;;;;;;AAgBH,MAAa,uBAAuB,gBAAqD;CACvF,MAAM,MAAM,YAAY,QAAQ,qBAAqB;AAErD,KAAI,QAAQ,CAAC,GAAG;AACd,SAAO;GAAE,SAAS;GAAO,QAAQ;GAA0B;;CAG7D,MAAM,WAAW,YAAY,MAAM,GAAG,IAAI;CAC1C,MAAM,UAAU,YAAY,MAAM,MAAM,qBAAqB,OAAO;AAEpE,KAAI,aAAa,IAAI;AACnB,SAAO;GAAE,SAAS;GAAO,QAAQ;GAAmB;;AAGtD,KAAI,YAAY,IAAI;AAClB,SAAO;GAAE,SAAS;GAAO,QAAQ;GAAkB;;AAGrD,QAAO,EAAE,SAAS,MAAM;;;;;;;;ACjC1B,MAAM,iBAAiB,UAAyC;AAC9D,QAAO,MAAM,KAAK,UAAU,MAAM,YAAY,CAAC,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6B1D,MAAa,0BAA0B,YAQX;CAC1B,MAAM,EAAE,UAAU,SAAS,kBAAkB;CAG7C,MAAME,aAA2B,EAAE;CAGnC,MAAM,qBAAqB,IAAI,KAAqB;CAGpD,MAAM,YAAY,IAAI,KAAa;CAGnC,MAAM,iBAAiB,IAAI,KAAqB;CAEhD,MAAM,qBAAqB,QAAwB;EACjD,MAAM,UAAU,mBAAmB,IAAI,IAAI,IAAI;AAC/C,qBAAmB,IAAI,KAAK,UAAU,EAAE;AACxC,SAAO;;CAGT,MAAM,oBAAoB,aAA6B;EACrD,IAAI,OAAO;EACX,IAAI,SAAS;AACb,SAAO,UAAU,IAAI,KAAK,EAAE;AAC1B;AACA,UAAO,GAAG,SAAS,GAAG;;AAExB,YAAU,IAAI,KAAK;AACnB,SAAO;;AAGT,QAAO;EACL,WAAW,EAAE,SAAS,MAAM,aAA0B;GACpD,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG;GACpC,MAAM,aAAa,kBAAkB,IAAI;GAEzC,MAAMC,QAAoB;IACxB,aAAa;IACb;IACA;IACD;AAED,cAAW,KAAK,MAAM;AAEtB,UAAO;IACL,SAAS;IACT,OAAO,WAAW,SAAS;IAC5B;;EAGH,UAAU,QAA2B;AAEnC,OAAI,OAAO,UAAU,WAAW,SAAS,GAAG;AAC1C,UAAM,IAAI,MAAM,iDAAiD,WAAW,SAAS,EAAE,QAAQ,OAAO,QAAQ;;AAEhH,cAAW,KAAK;;EAGlB,qBAIE;GACA,MAAM,WAAW,cAAc,WAAW;GAC1C,MAAM,UAAU,iBAAiB,SAAS;GAC1C,MAAM,aAAa,WAAW,WAAW;GAGzC,IAAIC;AACJ,OAAI,iBAAiB,YAAY;AAG/B,oBAAgB;;AAGlB,UAAO;IACL;IACA;IACA;IACD;;EAGH,mBAAmB,SAA8B;AAC/C,UAAO,kBAAkB,UAAU,SAAS,EAAE,SAAS,CAAC;;EAG1D,sBAAsB,OAAe,UAAwB;AAC3D,kBAAe,IAAI,OAAO,SAAS;;EAGrC,eAAuB;AACrB,UAAO,WAAW;;EAErB;;;;;AAMH,MAAa,gCAER;CACH,MAAM,qBAAqB,IAAI,KAAqB;AAEpD,QAAO,EACL,kBAAkB,KAAqB;EACrC,MAAM,UAAU,mBAAmB,IAAI,IAAI,IAAI;AAC/C,qBAAmB,IAAI,KAAK,UAAU,EAAE;AACxC,SAAO;IAEV;;;;;AAMH,MAAa,0BAER;CACH,MAAM,YAAY,IAAI,KAAa;AAEnC,QAAO,EACL,iBAAiB,UAA0B;EACzC,IAAI,OAAO;EACX,IAAI,SAAS;AACb,SAAO,UAAU,IAAI,KAAK,EAAE;AAC1B;AACA,UAAO,GAAG,SAAS,GAAG;;AAExB,YAAU,IAAI,KAAK;AACnB,SAAO;IAEV;;;;;AAMH,MAAa,gBAAgB,UAAyC;AACpE,QAAO,MAAM,KAAK,UAAU,MAAM,YAAY,CAAC,KAAK,IAAI"}
|
|
1
|
+
{"version":3,"file":"canonical-id-CcqNJHU4.cjs","names":["CanonicalIdSchema: z.ZodType<CanonicalId>","z","resolved","normalized","normalizePath","idParts","scopeStack: ScopeFrame[]","frame: ScopeFrame","exportBinding: string | undefined"],"sources":["../src/canonical-id/canonical-id.ts","../src/canonical-id/path-tracker.ts"],"sourcesContent":["import { isAbsolute, relative, resolve } from \"node:path\";\nimport z from \"zod\";\nimport { normalizePath } from \"../utils\";\n\nexport type CanonicalId = string & { readonly __brand: \"CanonicalId\" };\n\nconst canonicalIdSeparator = \"::\" as const;\n\nexport const CanonicalIdSchema: z.ZodType<CanonicalId> = z.string() as unknown as z.ZodType<CanonicalId>;\n\n/**\n * Options for creating a canonical ID.\n */\nexport type CreateCanonicalIdOptions = {\n /**\n * Base directory for relative path computation.\n * When provided, the canonical ID will use a relative path from baseDir.\n * When undefined, an absolute path is required and used as-is.\n */\n readonly baseDir?: string;\n};\n\n/**\n * Create a canonical ID from a file path and AST path.\n *\n * @param filePath - The file path (absolute, or relative if baseDir is provided)\n * @param astPath - The AST path identifying the definition within the file\n * @param options - Optional configuration including baseDir for relative path support\n * @returns A canonical ID in the format \"{path}::{astPath}\"\n */\nexport const createCanonicalId = (filePath: string, astPath: string, options?: CreateCanonicalIdOptions): CanonicalId => {\n const { baseDir } = options ?? {};\n\n if (baseDir) {\n // With baseDir, compute relative path\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(baseDir, filePath);\n const resolved = resolve(absolutePath);\n const relativePath = relative(baseDir, resolved);\n const normalized = normalizePath(relativePath);\n\n const idParts = [normalized, astPath];\n return idParts.join(canonicalIdSeparator) as CanonicalId;\n }\n\n // Without baseDir, require absolute path (legacy behavior)\n if (!isAbsolute(filePath)) {\n throw new Error(\"[INTERNAL] CANONICAL_ID_REQUIRES_ABSOLUTE_PATH\");\n }\n\n const resolved = resolve(filePath);\n const normalized = normalizePath(resolved);\n\n // Create a 2-part ID: {absPath}::{astPath}\n // astPath uniquely identifies the definition's location in the AST (e.g., \"MyComponent.useQuery.def\")\n const idParts = [normalized, astPath];\n\n return idParts.join(canonicalIdSeparator) as CanonicalId;\n};\n\n/**\n * Check if a canonical ID uses a relative path.\n * Relative canonical IDs do not start with '/'.\n *\n * @param canonicalId - The canonical ID to check\n * @returns true if the canonical ID uses a relative path\n */\nexport const isRelativeCanonicalId = (canonicalId: CanonicalId | string): boolean => {\n return !canonicalId.startsWith(\"/\");\n};\n\n/**\n * Parse a canonical ID into its components.\n * @param canonicalId - The canonical ID to parse (e.g., \"/app/src/user.ts::userFragment\")\n * @returns An object with filePath and astPath\n */\nexport const parseCanonicalId = (\n canonicalId: CanonicalId | string,\n): {\n filePath: string;\n astPath: string;\n} => {\n const idx = canonicalId.indexOf(canonicalIdSeparator);\n if (idx === -1) {\n return { filePath: canonicalId, astPath: \"\" };\n }\n return {\n filePath: canonicalId.slice(0, idx),\n astPath: canonicalId.slice(idx + canonicalIdSeparator.length),\n };\n};\n\n/**\n * Validation result for canonical ID format.\n */\nexport type CanonicalIdValidationResult = { readonly isValid: true } | { readonly isValid: false; readonly reason: string };\n\n/**\n * Validate a canonical ID format.\n * A valid canonical ID has format: \"{filePath}::{astPath}\"\n * where both filePath and astPath are non-empty.\n *\n * @param canonicalId - The canonical ID to validate\n * @returns Validation result with isValid boolean and optional error reason\n */\nexport const validateCanonicalId = (canonicalId: string): CanonicalIdValidationResult => {\n const idx = canonicalId.indexOf(canonicalIdSeparator);\n\n if (idx === -1) {\n return { isValid: false, reason: \"missing '::' separator\" };\n }\n\n const filePath = canonicalId.slice(0, idx);\n const astPath = canonicalId.slice(idx + canonicalIdSeparator.length);\n\n if (filePath === \"\") {\n return { isValid: false, reason: \"empty file path\" };\n }\n\n if (astPath === \"\") {\n return { isValid: false, reason: \"empty AST path\" };\n }\n\n return { isValid: true };\n};\n","/**\n * Canonical path tracker for AST traversal.\n *\n * This module provides a stateful helper that tracks scope information during\n * AST traversal to generate canonical IDs. It's designed to integrate with\n * existing plugin visitor patterns (Babel, SWC, TypeScript) without requiring\n * a separate AST traversal.\n *\n * Usage pattern:\n * 1. Plugin creates tracker at file/program entry\n * 2. Plugin calls enterScope/exitScope during its traversal\n * 3. Plugin calls registerDefinition when discovering GQL definitions\n * 4. Tracker provides canonical ID information\n */\n\nimport type { CanonicalId } from \"./canonical-id\";\nimport { createCanonicalId } from \"./canonical-id\";\n\n/**\n * Scope frame for tracking AST path segments\n */\nexport type ScopeFrame = {\n /** Name segment (e.g., \"MyComponent\", \"useQuery\", \"arrow#1\") */\n readonly nameSegment: string;\n /** Kind of scope */\n readonly kind: \"function\" | \"class\" | \"variable\" | \"property\" | \"method\" | \"expression\";\n /** Occurrence index for disambiguation */\n readonly occurrence: number;\n};\n\n/**\n * Opaque handle for scope tracking\n */\nexport type ScopeHandle = {\n readonly __brand: \"ScopeHandle\";\n readonly depth: number;\n};\n\n/**\n * Canonical path tracker interface\n */\nexport interface CanonicalPathTracker {\n /**\n * Enter a new scope during traversal\n * @param options Scope information\n * @returns Handle to use when exiting the scope\n */\n enterScope(options: { segment: string; kind: ScopeFrame[\"kind\"]; stableKey?: string }): ScopeHandle;\n\n /**\n * Exit a scope during traversal\n * @param handle Handle returned from enterScope\n */\n exitScope(handle: ScopeHandle): void;\n\n /**\n * Register a definition discovered during traversal\n * @returns Definition metadata including astPath and canonical ID information\n */\n registerDefinition(): {\n astPath: string;\n isTopLevel: boolean;\n exportBinding?: string;\n };\n\n /**\n * Resolve a canonical ID from an astPath\n * @param astPath AST path string\n * @returns Canonical ID\n */\n resolveCanonicalId(astPath: string): CanonicalId;\n\n /**\n * Register an export binding\n * @param local Local variable name\n * @param exported Exported name\n */\n registerExportBinding(local: string, exported: string): void;\n\n /**\n * Get current scope depth\n * @returns Current depth (0 = top level)\n */\n currentDepth(): number;\n}\n\n/**\n * Build AST path from scope stack (internal helper)\n */\nconst _buildAstPath = (stack: readonly ScopeFrame[]): string => {\n return stack.map((frame) => frame.nameSegment).join(\".\");\n};\n\n/**\n * Create a canonical path tracker\n *\n * @param options Configuration options\n * @returns Tracker instance\n *\n * @example\n * ```typescript\n * // In a Babel plugin\n * const tracker = createCanonicalTracker({ filePath: state.filename });\n *\n * const visitor = {\n * FunctionDeclaration: {\n * enter(path) {\n * const handle = tracker.enterScope({\n * segment: path.node.id.name,\n * kind: 'function'\n * });\n * },\n * exit(path) {\n * tracker.exitScope(handle);\n * }\n * }\n * };\n * ```\n */\nexport const createCanonicalTracker = (options: {\n filePath: string;\n /**\n * Base directory for relative path computation in canonical IDs.\n * When provided, canonical IDs will use relative paths from baseDir.\n */\n baseDir?: string;\n getExportName?: (localName: string) => string | undefined;\n}): CanonicalPathTracker => {\n const { filePath, baseDir, getExportName } = options;\n\n // Scope stack\n const scopeStack: ScopeFrame[] = [];\n\n // Occurrence counters for disambiguating duplicate names\n const occurrenceCounters = new Map<string, number>();\n\n // Used paths for ensuring uniqueness\n const usedPaths = new Set<string>();\n\n // Export bindings map\n const exportBindings = new Map<string, string>();\n\n const getNextOccurrence = (key: string): number => {\n const current = occurrenceCounters.get(key) ?? 0;\n occurrenceCounters.set(key, current + 1);\n return current;\n };\n\n const ensureUniquePath = (basePath: string): string => {\n let path = basePath;\n let suffix = 0;\n while (usedPaths.has(path)) {\n suffix++;\n path = `${basePath}$${suffix}`;\n }\n usedPaths.add(path);\n return path;\n };\n\n return {\n enterScope({ segment, kind, stableKey }): ScopeHandle {\n const key = stableKey ?? `${kind}:${segment}`;\n const occurrence = getNextOccurrence(key);\n\n const frame: ScopeFrame = {\n nameSegment: segment,\n kind,\n occurrence,\n };\n\n scopeStack.push(frame);\n\n return {\n __brand: \"ScopeHandle\",\n depth: scopeStack.length - 1,\n } as ScopeHandle;\n },\n\n exitScope(handle: ScopeHandle): void {\n // Validate handle depth matches current stack\n if (handle.depth !== scopeStack.length - 1) {\n throw new Error(`[INTERNAL] Invalid scope exit: expected depth ${scopeStack.length - 1}, got ${handle.depth}`);\n }\n scopeStack.pop();\n },\n\n registerDefinition(): {\n astPath: string;\n isTopLevel: boolean;\n exportBinding?: string;\n } {\n const basePath = _buildAstPath(scopeStack);\n const astPath = ensureUniquePath(basePath);\n const isTopLevel = scopeStack.length === 0;\n\n // Check export binding if provided\n let exportBinding: string | undefined;\n if (getExportName && isTopLevel) {\n // For top-level definitions, try to get export name\n // This is a simplified version - real logic depends on how the definition is bound\n exportBinding = undefined;\n }\n\n return {\n astPath,\n isTopLevel,\n exportBinding,\n };\n },\n\n resolveCanonicalId(astPath: string): CanonicalId {\n return createCanonicalId(filePath, astPath, { baseDir });\n },\n\n registerExportBinding(local: string, exported: string): void {\n exportBindings.set(local, exported);\n },\n\n currentDepth(): number {\n return scopeStack.length;\n },\n };\n};\n\n/**\n * Helper to create occurrence tracker (for backward compatibility)\n */\nexport const createOccurrenceTracker = (): {\n getNextOccurrence: (key: string) => number;\n} => {\n const occurrenceCounters = new Map<string, number>();\n\n return {\n getNextOccurrence(key: string): number {\n const current = occurrenceCounters.get(key) ?? 0;\n occurrenceCounters.set(key, current + 1);\n return current;\n },\n };\n};\n\n/**\n * Helper to create path tracker (for backward compatibility)\n */\nexport const createPathTracker = (): {\n ensureUniquePath: (basePath: string) => string;\n} => {\n const usedPaths = new Set<string>();\n\n return {\n ensureUniquePath(basePath: string): string {\n let path = basePath;\n let suffix = 0;\n while (usedPaths.has(path)) {\n suffix++;\n path = `${basePath}$${suffix}`;\n }\n usedPaths.add(path);\n return path;\n },\n };\n};\n\n/**\n * Build AST path from scope stack (for backward compatibility)\n */\nexport const buildAstPath = (stack: readonly ScopeFrame[]): string => {\n return stack.map((frame) => frame.nameSegment).join(\".\");\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,MAAM,uBAAuB;AAE7B,MAAaA,oBAA4CC,YAAE,QAAQ;;;;;;;;;AAsBnE,MAAa,qBAAqB,UAAkB,SAAiB,YAAoD;CACvH,MAAM,EAAE,YAAY,WAAW,EAAE;AAEjC,KAAI,SAAS;EAEX,MAAM,yCAA0B,SAAS,GAAG,kCAAmB,SAAS,SAAS;EACjF,MAAMC,oCAAmB,aAAa;EACtC,MAAM,uCAAwB,SAASA,WAAS;EAChD,MAAMC,eAAaC,4BAAc,aAAa;EAE9C,MAAMC,YAAU,CAACF,cAAY,QAAQ;AACrC,SAAOE,UAAQ,KAAK,qBAAqB;;AAI3C,KAAI,2BAAY,SAAS,EAAE;AACzB,QAAM,IAAI,MAAM,iDAAiD;;CAGnE,MAAM,kCAAmB,SAAS;CAClC,MAAM,aAAaD,4BAAc,SAAS;CAI1C,MAAM,UAAU,CAAC,YAAY,QAAQ;AAErC,QAAO,QAAQ,KAAK,qBAAqB;;;;;;;;;AAU3C,MAAa,yBAAyB,gBAA+C;AACnF,QAAO,CAAC,YAAY,WAAW,IAAI;;;;;;;AAQrC,MAAa,oBACX,gBAIG;CACH,MAAM,MAAM,YAAY,QAAQ,qBAAqB;AACrD,KAAI,QAAQ,CAAC,GAAG;AACd,SAAO;GAAE,UAAU;GAAa,SAAS;GAAI;;AAE/C,QAAO;EACL,UAAU,YAAY,MAAM,GAAG,IAAI;EACnC,SAAS,YAAY,MAAM,MAAM,qBAAqB,OAAO;EAC9D;;;;;;;;;;AAgBH,MAAa,uBAAuB,gBAAqD;CACvF,MAAM,MAAM,YAAY,QAAQ,qBAAqB;AAErD,KAAI,QAAQ,CAAC,GAAG;AACd,SAAO;GAAE,SAAS;GAAO,QAAQ;GAA0B;;CAG7D,MAAM,WAAW,YAAY,MAAM,GAAG,IAAI;CAC1C,MAAM,UAAU,YAAY,MAAM,MAAM,qBAAqB,OAAO;AAEpE,KAAI,aAAa,IAAI;AACnB,SAAO;GAAE,SAAS;GAAO,QAAQ;GAAmB;;AAGtD,KAAI,YAAY,IAAI;AAClB,SAAO;GAAE,SAAS;GAAO,QAAQ;GAAkB;;AAGrD,QAAO,EAAE,SAAS,MAAM;;;;;;;;ACjC1B,MAAM,iBAAiB,UAAyC;AAC9D,QAAO,MAAM,KAAK,UAAU,MAAM,YAAY,CAAC,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6B1D,MAAa,0BAA0B,YAQX;CAC1B,MAAM,EAAE,UAAU,SAAS,kBAAkB;CAG7C,MAAME,aAA2B,EAAE;CAGnC,MAAM,qBAAqB,IAAI,KAAqB;CAGpD,MAAM,YAAY,IAAI,KAAa;CAGnC,MAAM,iBAAiB,IAAI,KAAqB;CAEhD,MAAM,qBAAqB,QAAwB;EACjD,MAAM,UAAU,mBAAmB,IAAI,IAAI,IAAI;AAC/C,qBAAmB,IAAI,KAAK,UAAU,EAAE;AACxC,SAAO;;CAGT,MAAM,oBAAoB,aAA6B;EACrD,IAAI,OAAO;EACX,IAAI,SAAS;AACb,SAAO,UAAU,IAAI,KAAK,EAAE;AAC1B;AACA,UAAO,GAAG,SAAS,GAAG;;AAExB,YAAU,IAAI,KAAK;AACnB,SAAO;;AAGT,QAAO;EACL,WAAW,EAAE,SAAS,MAAM,aAA0B;GACpD,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG;GACpC,MAAM,aAAa,kBAAkB,IAAI;GAEzC,MAAMC,QAAoB;IACxB,aAAa;IACb;IACA;IACD;AAED,cAAW,KAAK,MAAM;AAEtB,UAAO;IACL,SAAS;IACT,OAAO,WAAW,SAAS;IAC5B;;EAGH,UAAU,QAA2B;AAEnC,OAAI,OAAO,UAAU,WAAW,SAAS,GAAG;AAC1C,UAAM,IAAI,MAAM,iDAAiD,WAAW,SAAS,EAAE,QAAQ,OAAO,QAAQ;;AAEhH,cAAW,KAAK;;EAGlB,qBAIE;GACA,MAAM,WAAW,cAAc,WAAW;GAC1C,MAAM,UAAU,iBAAiB,SAAS;GAC1C,MAAM,aAAa,WAAW,WAAW;GAGzC,IAAIC;AACJ,OAAI,iBAAiB,YAAY;AAG/B,oBAAgB;;AAGlB,UAAO;IACL;IACA;IACA;IACD;;EAGH,mBAAmB,SAA8B;AAC/C,UAAO,kBAAkB,UAAU,SAAS,EAAE,SAAS,CAAC;;EAG1D,sBAAsB,OAAe,UAAwB;AAC3D,kBAAe,IAAI,OAAO,SAAS;;EAGrC,eAAuB;AACrB,UAAO,WAAW;;EAErB;;;;;AAMH,MAAa,gCAER;CACH,MAAM,qBAAqB,IAAI,KAAqB;AAEpD,QAAO,EACL,kBAAkB,KAAqB;EACrC,MAAM,UAAU,mBAAmB,IAAI,IAAI,IAAI;AAC/C,qBAAmB,IAAI,KAAK,UAAU,EAAE;AACxC,SAAO;IAEV;;;;;AAMH,MAAa,0BAER;CACH,MAAM,YAAY,IAAI,KAAa;AAEnC,QAAO,EACL,iBAAiB,UAA0B;EACzC,IAAI,OAAO;EACX,IAAI,SAAS;AACb,SAAO,UAAU,IAAI,KAAK,EAAE;AAC1B;AACA,UAAO,GAAG,SAAS,GAAG;;AAExB,YAAU,IAAI,KAAK;AACnB,SAAO;IAEV;;;;;AAMH,MAAa,gBAAgB,UAAyC;AACpE,QAAO,MAAM,KAAK,UAAU,MAAM,YAAY,CAAC,KAAK,IAAI"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as normalizePath } from "./utils-DlhM4qvh.mjs";
|
|
2
2
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
3
|
import z$1 from "zod";
|
|
4
4
|
|
|
@@ -229,4 +229,4 @@ const buildAstPath = (stack) => {
|
|
|
229
229
|
|
|
230
230
|
//#endregion
|
|
231
231
|
export { CanonicalIdSchema as a, parseCanonicalId as c, createPathTracker as i, validateCanonicalId as l, createCanonicalTracker as n, createCanonicalId as o, createOccurrenceTracker as r, isRelativeCanonicalId as s, buildAstPath as t };
|
|
232
|
-
//# sourceMappingURL=canonical-id-
|
|
232
|
+
//# sourceMappingURL=canonical-id-U2VNaQ86.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical-id-9alor9gv.mjs","names":["CanonicalIdSchema: z.ZodType<CanonicalId>","z","resolved","normalized","idParts","scopeStack: ScopeFrame[]","frame: ScopeFrame","exportBinding: string | undefined"],"sources":["../src/canonical-id/canonical-id.ts","../src/canonical-id/path-tracker.ts"],"sourcesContent":["import { isAbsolute, relative, resolve } from \"node:path\";\nimport z from \"zod\";\nimport { normalizePath } from \"../utils\";\n\nexport type CanonicalId = string & { readonly __brand: \"CanonicalId\" };\n\nconst canonicalIdSeparator = \"::\" as const;\n\nexport const CanonicalIdSchema: z.ZodType<CanonicalId> = z.string() as unknown as z.ZodType<CanonicalId>;\n\n/**\n * Options for creating a canonical ID.\n */\nexport type CreateCanonicalIdOptions = {\n /**\n * Base directory for relative path computation.\n * When provided, the canonical ID will use a relative path from baseDir.\n * When undefined, an absolute path is required and used as-is.\n */\n readonly baseDir?: string;\n};\n\n/**\n * Create a canonical ID from a file path and AST path.\n *\n * @param filePath - The file path (absolute, or relative if baseDir is provided)\n * @param astPath - The AST path identifying the definition within the file\n * @param options - Optional configuration including baseDir for relative path support\n * @returns A canonical ID in the format \"{path}::{astPath}\"\n */\nexport const createCanonicalId = (filePath: string, astPath: string, options?: CreateCanonicalIdOptions): CanonicalId => {\n const { baseDir } = options ?? {};\n\n if (baseDir) {\n // With baseDir, compute relative path\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(baseDir, filePath);\n const resolved = resolve(absolutePath);\n const relativePath = relative(baseDir, resolved);\n const normalized = normalizePath(relativePath);\n\n const idParts = [normalized, astPath];\n return idParts.join(canonicalIdSeparator) as CanonicalId;\n }\n\n // Without baseDir, require absolute path (legacy behavior)\n if (!isAbsolute(filePath)) {\n throw new Error(\"[INTERNAL] CANONICAL_ID_REQUIRES_ABSOLUTE_PATH\");\n }\n\n const resolved = resolve(filePath);\n const normalized = normalizePath(resolved);\n\n // Create a 2-part ID: {absPath}::{astPath}\n // astPath uniquely identifies the definition's location in the AST (e.g., \"MyComponent.useQuery.def\")\n const idParts = [normalized, astPath];\n\n return idParts.join(canonicalIdSeparator) as CanonicalId;\n};\n\n/**\n * Check if a canonical ID uses a relative path.\n * Relative canonical IDs do not start with '/'.\n *\n * @param canonicalId - The canonical ID to check\n * @returns true if the canonical ID uses a relative path\n */\nexport const isRelativeCanonicalId = (canonicalId: CanonicalId | string): boolean => {\n return !canonicalId.startsWith(\"/\");\n};\n\n/**\n * Parse a canonical ID into its components.\n * @param canonicalId - The canonical ID to parse (e.g., \"/app/src/user.ts::userFragment\")\n * @returns An object with filePath and astPath\n */\nexport const parseCanonicalId = (\n canonicalId: CanonicalId | string,\n): {\n filePath: string;\n astPath: string;\n} => {\n const idx = canonicalId.indexOf(canonicalIdSeparator);\n if (idx === -1) {\n return { filePath: canonicalId, astPath: \"\" };\n }\n return {\n filePath: canonicalId.slice(0, idx),\n astPath: canonicalId.slice(idx + canonicalIdSeparator.length),\n };\n};\n\n/**\n * Validation result for canonical ID format.\n */\nexport type CanonicalIdValidationResult = { readonly isValid: true } | { readonly isValid: false; readonly reason: string };\n\n/**\n * Validate a canonical ID format.\n * A valid canonical ID has format: \"{filePath}::{astPath}\"\n * where both filePath and astPath are non-empty.\n *\n * @param canonicalId - The canonical ID to validate\n * @returns Validation result with isValid boolean and optional error reason\n */\nexport const validateCanonicalId = (canonicalId: string): CanonicalIdValidationResult => {\n const idx = canonicalId.indexOf(canonicalIdSeparator);\n\n if (idx === -1) {\n return { isValid: false, reason: \"missing '::' separator\" };\n }\n\n const filePath = canonicalId.slice(0, idx);\n const astPath = canonicalId.slice(idx + canonicalIdSeparator.length);\n\n if (filePath === \"\") {\n return { isValid: false, reason: \"empty file path\" };\n }\n\n if (astPath === \"\") {\n return { isValid: false, reason: \"empty AST path\" };\n }\n\n return { isValid: true };\n};\n","/**\n * Canonical path tracker for AST traversal.\n *\n * This module provides a stateful helper that tracks scope information during\n * AST traversal to generate canonical IDs. It's designed to integrate with\n * existing plugin visitor patterns (Babel, SWC, TypeScript) without requiring\n * a separate AST traversal.\n *\n * Usage pattern:\n * 1. Plugin creates tracker at file/program entry\n * 2. Plugin calls enterScope/exitScope during its traversal\n * 3. Plugin calls registerDefinition when discovering GQL definitions\n * 4. Tracker provides canonical ID information\n */\n\nimport type { CanonicalId } from \"./canonical-id\";\nimport { createCanonicalId } from \"./canonical-id\";\n\n/**\n * Scope frame for tracking AST path segments\n */\nexport type ScopeFrame = {\n /** Name segment (e.g., \"MyComponent\", \"useQuery\", \"arrow#1\") */\n readonly nameSegment: string;\n /** Kind of scope */\n readonly kind: \"function\" | \"class\" | \"variable\" | \"property\" | \"method\" | \"expression\";\n /** Occurrence index for disambiguation */\n readonly occurrence: number;\n};\n\n/**\n * Opaque handle for scope tracking\n */\nexport type ScopeHandle = {\n readonly __brand: \"ScopeHandle\";\n readonly depth: number;\n};\n\n/**\n * Canonical path tracker interface\n */\nexport interface CanonicalPathTracker {\n /**\n * Enter a new scope during traversal\n * @param options Scope information\n * @returns Handle to use when exiting the scope\n */\n enterScope(options: { segment: string; kind: ScopeFrame[\"kind\"]; stableKey?: string }): ScopeHandle;\n\n /**\n * Exit a scope during traversal\n * @param handle Handle returned from enterScope\n */\n exitScope(handle: ScopeHandle): void;\n\n /**\n * Register a definition discovered during traversal\n * @returns Definition metadata including astPath and canonical ID information\n */\n registerDefinition(): {\n astPath: string;\n isTopLevel: boolean;\n exportBinding?: string;\n };\n\n /**\n * Resolve a canonical ID from an astPath\n * @param astPath AST path string\n * @returns Canonical ID\n */\n resolveCanonicalId(astPath: string): CanonicalId;\n\n /**\n * Register an export binding\n * @param local Local variable name\n * @param exported Exported name\n */\n registerExportBinding(local: string, exported: string): void;\n\n /**\n * Get current scope depth\n * @returns Current depth (0 = top level)\n */\n currentDepth(): number;\n}\n\n/**\n * Build AST path from scope stack (internal helper)\n */\nconst _buildAstPath = (stack: readonly ScopeFrame[]): string => {\n return stack.map((frame) => frame.nameSegment).join(\".\");\n};\n\n/**\n * Create a canonical path tracker\n *\n * @param options Configuration options\n * @returns Tracker instance\n *\n * @example\n * ```typescript\n * // In a Babel plugin\n * const tracker = createCanonicalTracker({ filePath: state.filename });\n *\n * const visitor = {\n * FunctionDeclaration: {\n * enter(path) {\n * const handle = tracker.enterScope({\n * segment: path.node.id.name,\n * kind: 'function'\n * });\n * },\n * exit(path) {\n * tracker.exitScope(handle);\n * }\n * }\n * };\n * ```\n */\nexport const createCanonicalTracker = (options: {\n filePath: string;\n /**\n * Base directory for relative path computation in canonical IDs.\n * When provided, canonical IDs will use relative paths from baseDir.\n */\n baseDir?: string;\n getExportName?: (localName: string) => string | undefined;\n}): CanonicalPathTracker => {\n const { filePath, baseDir, getExportName } = options;\n\n // Scope stack\n const scopeStack: ScopeFrame[] = [];\n\n // Occurrence counters for disambiguating duplicate names\n const occurrenceCounters = new Map<string, number>();\n\n // Used paths for ensuring uniqueness\n const usedPaths = new Set<string>();\n\n // Export bindings map\n const exportBindings = new Map<string, string>();\n\n const getNextOccurrence = (key: string): number => {\n const current = occurrenceCounters.get(key) ?? 0;\n occurrenceCounters.set(key, current + 1);\n return current;\n };\n\n const ensureUniquePath = (basePath: string): string => {\n let path = basePath;\n let suffix = 0;\n while (usedPaths.has(path)) {\n suffix++;\n path = `${basePath}$${suffix}`;\n }\n usedPaths.add(path);\n return path;\n };\n\n return {\n enterScope({ segment, kind, stableKey }): ScopeHandle {\n const key = stableKey ?? `${kind}:${segment}`;\n const occurrence = getNextOccurrence(key);\n\n const frame: ScopeFrame = {\n nameSegment: segment,\n kind,\n occurrence,\n };\n\n scopeStack.push(frame);\n\n return {\n __brand: \"ScopeHandle\",\n depth: scopeStack.length - 1,\n } as ScopeHandle;\n },\n\n exitScope(handle: ScopeHandle): void {\n // Validate handle depth matches current stack\n if (handle.depth !== scopeStack.length - 1) {\n throw new Error(`[INTERNAL] Invalid scope exit: expected depth ${scopeStack.length - 1}, got ${handle.depth}`);\n }\n scopeStack.pop();\n },\n\n registerDefinition(): {\n astPath: string;\n isTopLevel: boolean;\n exportBinding?: string;\n } {\n const basePath = _buildAstPath(scopeStack);\n const astPath = ensureUniquePath(basePath);\n const isTopLevel = scopeStack.length === 0;\n\n // Check export binding if provided\n let exportBinding: string | undefined;\n if (getExportName && isTopLevel) {\n // For top-level definitions, try to get export name\n // This is a simplified version - real logic depends on how the definition is bound\n exportBinding = undefined;\n }\n\n return {\n astPath,\n isTopLevel,\n exportBinding,\n };\n },\n\n resolveCanonicalId(astPath: string): CanonicalId {\n return createCanonicalId(filePath, astPath, { baseDir });\n },\n\n registerExportBinding(local: string, exported: string): void {\n exportBindings.set(local, exported);\n },\n\n currentDepth(): number {\n return scopeStack.length;\n },\n };\n};\n\n/**\n * Helper to create occurrence tracker (for backward compatibility)\n */\nexport const createOccurrenceTracker = (): {\n getNextOccurrence: (key: string) => number;\n} => {\n const occurrenceCounters = new Map<string, number>();\n\n return {\n getNextOccurrence(key: string): number {\n const current = occurrenceCounters.get(key) ?? 0;\n occurrenceCounters.set(key, current + 1);\n return current;\n },\n };\n};\n\n/**\n * Helper to create path tracker (for backward compatibility)\n */\nexport const createPathTracker = (): {\n ensureUniquePath: (basePath: string) => string;\n} => {\n const usedPaths = new Set<string>();\n\n return {\n ensureUniquePath(basePath: string): string {\n let path = basePath;\n let suffix = 0;\n while (usedPaths.has(path)) {\n suffix++;\n path = `${basePath}$${suffix}`;\n }\n usedPaths.add(path);\n return path;\n },\n };\n};\n\n/**\n * Build AST path from scope stack (for backward compatibility)\n */\nexport const buildAstPath = (stack: readonly ScopeFrame[]): string => {\n return stack.map((frame) => frame.nameSegment).join(\".\");\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"canonical-id-U2VNaQ86.mjs","names":["CanonicalIdSchema: z.ZodType<CanonicalId>","z","resolved","normalized","idParts","scopeStack: ScopeFrame[]","frame: ScopeFrame","exportBinding: string | undefined"],"sources":["../src/canonical-id/canonical-id.ts","../src/canonical-id/path-tracker.ts"],"sourcesContent":["import { isAbsolute, relative, resolve } from \"node:path\";\nimport z from \"zod\";\nimport { normalizePath } from \"../utils\";\n\nexport type CanonicalId = string & { readonly __brand: \"CanonicalId\" };\n\nconst canonicalIdSeparator = \"::\" as const;\n\nexport const CanonicalIdSchema: z.ZodType<CanonicalId> = z.string() as unknown as z.ZodType<CanonicalId>;\n\n/**\n * Options for creating a canonical ID.\n */\nexport type CreateCanonicalIdOptions = {\n /**\n * Base directory for relative path computation.\n * When provided, the canonical ID will use a relative path from baseDir.\n * When undefined, an absolute path is required and used as-is.\n */\n readonly baseDir?: string;\n};\n\n/**\n * Create a canonical ID from a file path and AST path.\n *\n * @param filePath - The file path (absolute, or relative if baseDir is provided)\n * @param astPath - The AST path identifying the definition within the file\n * @param options - Optional configuration including baseDir for relative path support\n * @returns A canonical ID in the format \"{path}::{astPath}\"\n */\nexport const createCanonicalId = (filePath: string, astPath: string, options?: CreateCanonicalIdOptions): CanonicalId => {\n const { baseDir } = options ?? {};\n\n if (baseDir) {\n // With baseDir, compute relative path\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(baseDir, filePath);\n const resolved = resolve(absolutePath);\n const relativePath = relative(baseDir, resolved);\n const normalized = normalizePath(relativePath);\n\n const idParts = [normalized, astPath];\n return idParts.join(canonicalIdSeparator) as CanonicalId;\n }\n\n // Without baseDir, require absolute path (legacy behavior)\n if (!isAbsolute(filePath)) {\n throw new Error(\"[INTERNAL] CANONICAL_ID_REQUIRES_ABSOLUTE_PATH\");\n }\n\n const resolved = resolve(filePath);\n const normalized = normalizePath(resolved);\n\n // Create a 2-part ID: {absPath}::{astPath}\n // astPath uniquely identifies the definition's location in the AST (e.g., \"MyComponent.useQuery.def\")\n const idParts = [normalized, astPath];\n\n return idParts.join(canonicalIdSeparator) as CanonicalId;\n};\n\n/**\n * Check if a canonical ID uses a relative path.\n * Relative canonical IDs do not start with '/'.\n *\n * @param canonicalId - The canonical ID to check\n * @returns true if the canonical ID uses a relative path\n */\nexport const isRelativeCanonicalId = (canonicalId: CanonicalId | string): boolean => {\n return !canonicalId.startsWith(\"/\");\n};\n\n/**\n * Parse a canonical ID into its components.\n * @param canonicalId - The canonical ID to parse (e.g., \"/app/src/user.ts::userFragment\")\n * @returns An object with filePath and astPath\n */\nexport const parseCanonicalId = (\n canonicalId: CanonicalId | string,\n): {\n filePath: string;\n astPath: string;\n} => {\n const idx = canonicalId.indexOf(canonicalIdSeparator);\n if (idx === -1) {\n return { filePath: canonicalId, astPath: \"\" };\n }\n return {\n filePath: canonicalId.slice(0, idx),\n astPath: canonicalId.slice(idx + canonicalIdSeparator.length),\n };\n};\n\n/**\n * Validation result for canonical ID format.\n */\nexport type CanonicalIdValidationResult = { readonly isValid: true } | { readonly isValid: false; readonly reason: string };\n\n/**\n * Validate a canonical ID format.\n * A valid canonical ID has format: \"{filePath}::{astPath}\"\n * where both filePath and astPath are non-empty.\n *\n * @param canonicalId - The canonical ID to validate\n * @returns Validation result with isValid boolean and optional error reason\n */\nexport const validateCanonicalId = (canonicalId: string): CanonicalIdValidationResult => {\n const idx = canonicalId.indexOf(canonicalIdSeparator);\n\n if (idx === -1) {\n return { isValid: false, reason: \"missing '::' separator\" };\n }\n\n const filePath = canonicalId.slice(0, idx);\n const astPath = canonicalId.slice(idx + canonicalIdSeparator.length);\n\n if (filePath === \"\") {\n return { isValid: false, reason: \"empty file path\" };\n }\n\n if (astPath === \"\") {\n return { isValid: false, reason: \"empty AST path\" };\n }\n\n return { isValid: true };\n};\n","/**\n * Canonical path tracker for AST traversal.\n *\n * This module provides a stateful helper that tracks scope information during\n * AST traversal to generate canonical IDs. It's designed to integrate with\n * existing plugin visitor patterns (Babel, SWC, TypeScript) without requiring\n * a separate AST traversal.\n *\n * Usage pattern:\n * 1. Plugin creates tracker at file/program entry\n * 2. Plugin calls enterScope/exitScope during its traversal\n * 3. Plugin calls registerDefinition when discovering GQL definitions\n * 4. Tracker provides canonical ID information\n */\n\nimport type { CanonicalId } from \"./canonical-id\";\nimport { createCanonicalId } from \"./canonical-id\";\n\n/**\n * Scope frame for tracking AST path segments\n */\nexport type ScopeFrame = {\n /** Name segment (e.g., \"MyComponent\", \"useQuery\", \"arrow#1\") */\n readonly nameSegment: string;\n /** Kind of scope */\n readonly kind: \"function\" | \"class\" | \"variable\" | \"property\" | \"method\" | \"expression\";\n /** Occurrence index for disambiguation */\n readonly occurrence: number;\n};\n\n/**\n * Opaque handle for scope tracking\n */\nexport type ScopeHandle = {\n readonly __brand: \"ScopeHandle\";\n readonly depth: number;\n};\n\n/**\n * Canonical path tracker interface\n */\nexport interface CanonicalPathTracker {\n /**\n * Enter a new scope during traversal\n * @param options Scope information\n * @returns Handle to use when exiting the scope\n */\n enterScope(options: { segment: string; kind: ScopeFrame[\"kind\"]; stableKey?: string }): ScopeHandle;\n\n /**\n * Exit a scope during traversal\n * @param handle Handle returned from enterScope\n */\n exitScope(handle: ScopeHandle): void;\n\n /**\n * Register a definition discovered during traversal\n * @returns Definition metadata including astPath and canonical ID information\n */\n registerDefinition(): {\n astPath: string;\n isTopLevel: boolean;\n exportBinding?: string;\n };\n\n /**\n * Resolve a canonical ID from an astPath\n * @param astPath AST path string\n * @returns Canonical ID\n */\n resolveCanonicalId(astPath: string): CanonicalId;\n\n /**\n * Register an export binding\n * @param local Local variable name\n * @param exported Exported name\n */\n registerExportBinding(local: string, exported: string): void;\n\n /**\n * Get current scope depth\n * @returns Current depth (0 = top level)\n */\n currentDepth(): number;\n}\n\n/**\n * Build AST path from scope stack (internal helper)\n */\nconst _buildAstPath = (stack: readonly ScopeFrame[]): string => {\n return stack.map((frame) => frame.nameSegment).join(\".\");\n};\n\n/**\n * Create a canonical path tracker\n *\n * @param options Configuration options\n * @returns Tracker instance\n *\n * @example\n * ```typescript\n * // In a Babel plugin\n * const tracker = createCanonicalTracker({ filePath: state.filename });\n *\n * const visitor = {\n * FunctionDeclaration: {\n * enter(path) {\n * const handle = tracker.enterScope({\n * segment: path.node.id.name,\n * kind: 'function'\n * });\n * },\n * exit(path) {\n * tracker.exitScope(handle);\n * }\n * }\n * };\n * ```\n */\nexport const createCanonicalTracker = (options: {\n filePath: string;\n /**\n * Base directory for relative path computation in canonical IDs.\n * When provided, canonical IDs will use relative paths from baseDir.\n */\n baseDir?: string;\n getExportName?: (localName: string) => string | undefined;\n}): CanonicalPathTracker => {\n const { filePath, baseDir, getExportName } = options;\n\n // Scope stack\n const scopeStack: ScopeFrame[] = [];\n\n // Occurrence counters for disambiguating duplicate names\n const occurrenceCounters = new Map<string, number>();\n\n // Used paths for ensuring uniqueness\n const usedPaths = new Set<string>();\n\n // Export bindings map\n const exportBindings = new Map<string, string>();\n\n const getNextOccurrence = (key: string): number => {\n const current = occurrenceCounters.get(key) ?? 0;\n occurrenceCounters.set(key, current + 1);\n return current;\n };\n\n const ensureUniquePath = (basePath: string): string => {\n let path = basePath;\n let suffix = 0;\n while (usedPaths.has(path)) {\n suffix++;\n path = `${basePath}$${suffix}`;\n }\n usedPaths.add(path);\n return path;\n };\n\n return {\n enterScope({ segment, kind, stableKey }): ScopeHandle {\n const key = stableKey ?? `${kind}:${segment}`;\n const occurrence = getNextOccurrence(key);\n\n const frame: ScopeFrame = {\n nameSegment: segment,\n kind,\n occurrence,\n };\n\n scopeStack.push(frame);\n\n return {\n __brand: \"ScopeHandle\",\n depth: scopeStack.length - 1,\n } as ScopeHandle;\n },\n\n exitScope(handle: ScopeHandle): void {\n // Validate handle depth matches current stack\n if (handle.depth !== scopeStack.length - 1) {\n throw new Error(`[INTERNAL] Invalid scope exit: expected depth ${scopeStack.length - 1}, got ${handle.depth}`);\n }\n scopeStack.pop();\n },\n\n registerDefinition(): {\n astPath: string;\n isTopLevel: boolean;\n exportBinding?: string;\n } {\n const basePath = _buildAstPath(scopeStack);\n const astPath = ensureUniquePath(basePath);\n const isTopLevel = scopeStack.length === 0;\n\n // Check export binding if provided\n let exportBinding: string | undefined;\n if (getExportName && isTopLevel) {\n // For top-level definitions, try to get export name\n // This is a simplified version - real logic depends on how the definition is bound\n exportBinding = undefined;\n }\n\n return {\n astPath,\n isTopLevel,\n exportBinding,\n };\n },\n\n resolveCanonicalId(astPath: string): CanonicalId {\n return createCanonicalId(filePath, astPath, { baseDir });\n },\n\n registerExportBinding(local: string, exported: string): void {\n exportBindings.set(local, exported);\n },\n\n currentDepth(): number {\n return scopeStack.length;\n },\n };\n};\n\n/**\n * Helper to create occurrence tracker (for backward compatibility)\n */\nexport const createOccurrenceTracker = (): {\n getNextOccurrence: (key: string) => number;\n} => {\n const occurrenceCounters = new Map<string, number>();\n\n return {\n getNextOccurrence(key: string): number {\n const current = occurrenceCounters.get(key) ?? 0;\n occurrenceCounters.set(key, current + 1);\n return current;\n },\n };\n};\n\n/**\n * Helper to create path tracker (for backward compatibility)\n */\nexport const createPathTracker = (): {\n ensureUniquePath: (basePath: string) => string;\n} => {\n const usedPaths = new Set<string>();\n\n return {\n ensureUniquePath(basePath: string): string {\n let path = basePath;\n let suffix = 0;\n while (usedPaths.has(path)) {\n suffix++;\n path = `${basePath}$${suffix}`;\n }\n usedPaths.add(path);\n return path;\n },\n };\n};\n\n/**\n * Build AST path from scope stack (for backward compatibility)\n */\nexport const buildAstPath = (stack: readonly ScopeFrame[]): string => {\n return stack.map((frame) => frame.nameSegment).join(\".\");\n};\n"],"mappings":"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"}
|
package/dist/canonical-id.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_canonical_id = require('./canonical-id-
|
|
2
|
-
require('./utils-
|
|
1
|
+
const require_canonical_id = require('./canonical-id-CcqNJHU4.cjs');
|
|
2
|
+
require('./utils-C2CEQL5v.cjs');
|
|
3
3
|
|
|
4
4
|
exports.CanonicalIdSchema = require_canonical_id.CanonicalIdSchema;
|
|
5
5
|
exports.buildAstPath = require_canonical_id.buildAstPath;
|
package/dist/canonical-id.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./utils-
|
|
2
|
-
import { a as CanonicalIdSchema, c as parseCanonicalId, i as createPathTracker, l as validateCanonicalId, n as createCanonicalTracker, o as createCanonicalId, r as createOccurrenceTracker, s as isRelativeCanonicalId, t as buildAstPath } from "./canonical-id-
|
|
1
|
+
import "./utils-DlhM4qvh.mjs";
|
|
2
|
+
import { a as CanonicalIdSchema, c as parseCanonicalId, i as createPathTracker, l as validateCanonicalId, n as createCanonicalTracker, o as createCanonicalId, r as createOccurrenceTracker, s as isRelativeCanonicalId, t as buildAstPath } from "./canonical-id-U2VNaQ86.mjs";
|
|
3
3
|
|
|
4
4
|
export { CanonicalIdSchema, buildAstPath, createCanonicalId, createCanonicalTracker, createOccurrenceTracker, createPathTracker, isRelativeCanonicalId, parseCanonicalId, validateCanonicalId };
|
|
@@ -135,5 +135,28 @@ declare const isRelativeSpecifier: (specifier: string) => boolean;
|
|
|
135
135
|
*/
|
|
136
136
|
declare const isExternalSpecifier: (specifier: string) => boolean;
|
|
137
137
|
//#endregion
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
//#region packages/common/src/utils/swc-span.d.ts
|
|
139
|
+
/**
|
|
140
|
+
* SWC span position converter: UTF-8 byte offsets → UTF-16 code unit indices.
|
|
141
|
+
*
|
|
142
|
+
* SWC (Rust-based) returns span positions as UTF-8 byte offsets.
|
|
143
|
+
* JavaScript strings use UTF-16 code units for indexing.
|
|
144
|
+
* For ASCII-only content these are identical, but for multi-byte
|
|
145
|
+
* characters the positions diverge.
|
|
146
|
+
*/
|
|
147
|
+
type SwcSpanConverter = {
|
|
148
|
+
/** UTF-8 byte length of the source string */
|
|
149
|
+
readonly byteLength: number;
|
|
150
|
+
/** Convert a UTF-8 byte offset (within the source) to a UTF-16 code unit index */
|
|
151
|
+
readonly byteOffsetToCharIndex: (byteOffset: number) => number;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Create a converter that maps UTF-8 byte offsets to UTF-16 char indices
|
|
155
|
+
* for the given source string.
|
|
156
|
+
*
|
|
157
|
+
* Includes a fast path for ASCII-only sources (zero allocation).
|
|
158
|
+
*/
|
|
159
|
+
declare const createSwcSpanConverter: (source: string) => SwcSpanConverter;
|
|
160
|
+
//#endregion
|
|
161
|
+
export { isExternalSpecifier as a, parseJsExtension as c, cachedFn as d, AliasResolver as f, readTsconfigPaths as g, TsconfigReadError as h, MODULE_EXTENSION_CANDIDATES as i, resolveRelativeImportWithExistenceCheck as l, TsconfigPathsConfig as m, createSwcSpanConverter as n, isRelativeSpecifier as o, createAliasResolver as p, JsExtensionInfo as r, normalizePath as s, SwcSpanConverter as t, resolveRelativeImportWithReferences as u };
|
|
162
|
+
//# sourceMappingURL=index-B1w5x8e3.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-B1w5x8e3.d.mts","names":[],"sources":["../src/utils/tsconfig.ts","../src/utils/alias-resolver.ts","../src/utils/cached-fn.ts","../src/utils/path.ts","../src/utils/swc-span.ts"],"sourcesContent":[],"mappings":";;;;;;AAQA;AAUA;AA4Ba,KAtCD,mBAAA,GAgGX;EA1D+D;EAA4B,SAAA,OAAA,EAAA,MAAA;EAAnC;EAAM,SAAA,KAAA,EAlC7C,QAkC6C,CAlCpC,MAkCoC,CAAA,MAAA,EAAA,SAAA,MAAA,EAAA,CAAA,CAAA;;;;ACtC/D;AAoJa,KD1ID,iBAAA,GCyKX;;;;AC3LD;;;;ACQA;AAgBA;AAsBA;AAiBa,cHjBA,iBGiB+E,EAAA,CAAA,YAAA,EAAA,MAAA,EAAA,GHjBnC,MGiBmC,CHjB5B,mBGiB4B,GAAA,IAAA,EHjBA,iBGiBA,CAAA;;;;;AHvD5F;AAUY,KCVA,aAAA,GDUiB;EA4BhB;;;;;;;;ACtCb;AAoJA;;;;AC5JA;;;cD4Ja,8BAA+B,wBAAsB;;;cC5JrD,wBAAyB;MAAA;;AFQtC,CAAA;;;;;;AAAA;AAUA;AA4Ba,cGtCA,2BHgGZ,EAAA,SAAA,CAAA,KAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA;;;;AA1D8D,KGtBnD,eAAA,GHsBmD;;;;ECtCnD,SAAA,WAAa,EAAA,MAAA;EAoJZ;;;;AC5Jb;;;;ACQA;AAgBA;AAsBA;AAiBA;AAUA;AA+EA;;;AAAuD,cA1G1C,gBA0G0C,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,GA1GF,eA0GE,GAAA,IAAA;;;;;AA4D1C,cArJA,aAqJ+G,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,MAAA;AAK5H;;;;AChNA;AAaA;;;cDmDa;;;;;;;;;;;;;;;cA+EA;;;;;;;cAOC,YAAY,KAAK;;;;;cAqDlB;;;;cAKA;;;;;;AHjNb;AAUA;AA4BA;;;AAAyD,KIrC7C,gBAAA,GJqC6C;EAAM;;;;ACtC/D,CAAA;AAoJA;;;;AC5JA;;cEsBa,4CAA2C"}
|
|
@@ -135,5 +135,28 @@ declare const isRelativeSpecifier: (specifier: string) => boolean;
|
|
|
135
135
|
*/
|
|
136
136
|
declare const isExternalSpecifier: (specifier: string) => boolean;
|
|
137
137
|
//#endregion
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
//#region packages/common/src/utils/swc-span.d.ts
|
|
139
|
+
/**
|
|
140
|
+
* SWC span position converter: UTF-8 byte offsets → UTF-16 code unit indices.
|
|
141
|
+
*
|
|
142
|
+
* SWC (Rust-based) returns span positions as UTF-8 byte offsets.
|
|
143
|
+
* JavaScript strings use UTF-16 code units for indexing.
|
|
144
|
+
* For ASCII-only content these are identical, but for multi-byte
|
|
145
|
+
* characters the positions diverge.
|
|
146
|
+
*/
|
|
147
|
+
type SwcSpanConverter = {
|
|
148
|
+
/** UTF-8 byte length of the source string */
|
|
149
|
+
readonly byteLength: number;
|
|
150
|
+
/** Convert a UTF-8 byte offset (within the source) to a UTF-16 code unit index */
|
|
151
|
+
readonly byteOffsetToCharIndex: (byteOffset: number) => number;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Create a converter that maps UTF-8 byte offsets to UTF-16 char indices
|
|
155
|
+
* for the given source string.
|
|
156
|
+
*
|
|
157
|
+
* Includes a fast path for ASCII-only sources (zero allocation).
|
|
158
|
+
*/
|
|
159
|
+
declare const createSwcSpanConverter: (source: string) => SwcSpanConverter;
|
|
160
|
+
//#endregion
|
|
161
|
+
export { isExternalSpecifier as a, parseJsExtension as c, cachedFn as d, AliasResolver as f, readTsconfigPaths as g, TsconfigReadError as h, MODULE_EXTENSION_CANDIDATES as i, resolveRelativeImportWithExistenceCheck as l, TsconfigPathsConfig as m, createSwcSpanConverter as n, isRelativeSpecifier as o, createAliasResolver as p, JsExtensionInfo as r, normalizePath as s, SwcSpanConverter as t, resolveRelativeImportWithReferences as u };
|
|
162
|
+
//# sourceMappingURL=index-BDPAGTeS.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BDPAGTeS.d.cts","names":[],"sources":["../src/utils/tsconfig.ts","../src/utils/alias-resolver.ts","../src/utils/cached-fn.ts","../src/utils/path.ts","../src/utils/swc-span.ts"],"sourcesContent":[],"mappings":";;;;;;AAQA;AAUA;AA4Ba,KAtCD,mBAAA,GAgGX;EA1D+D;EAA4B,SAAA,OAAA,EAAA,MAAA;EAAnC;EAAM,SAAA,KAAA,EAlC7C,QAkC6C,CAlCpC,MAkCoC,CAAA,MAAA,EAAA,SAAA,MAAA,EAAA,CAAA,CAAA;;;;ACtC/D;AAoJa,KD1ID,iBAAA,GCyKX;;;;AC3LD;;;;ACQA;AAgBA;AAsBA;AAiBa,cHjBA,iBGiB+E,EAAA,CAAA,YAAA,EAAA,MAAA,EAAA,GHjBnC,MGiBmC,CHjB5B,mBGiB4B,GAAA,IAAA,EHjBA,iBGiBA,CAAA;;;;;AHvD5F;AAUY,KCVA,aAAA,GDUiB;EA4BhB;;;;;;;;ACtCb;AAoJA;;;;AC5JA;;;cD4Ja,8BAA+B,wBAAsB;;;cC5JrD,wBAAyB;MAAA;;AFQtC,CAAA;;;;;;AAAA;AAUA;AA4Ba,cGtCA,2BHgGZ,EAAA,SAAA,CAAA,KAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA;;;;AA1D8D,KGtBnD,eAAA,GHsBmD;;;;ECtCnD,SAAA,WAAa,EAAA,MAAA;EAoJZ;;;;AC5Jb;;;;ACQA;AAgBA;AAsBA;AAiBA;AAUA;AA+EA;;;AAAuD,cA1G1C,gBA0G0C,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,GA1GF,eA0GE,GAAA,IAAA;;;;;AA4D1C,cArJA,aAqJ+G,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,MAAA;AAK5H;;;;AChNA;AAaA;;;cDmDa;;;;;;;;;;;;;;;cA+EA;;;;;;;cAOC,YAAY,KAAK;;;;;cAqDlB;;;;cAKA;;;;;;AHjNb;AAUA;AA4BA;;;AAAyD,KIrC7C,gBAAA,GJqC6C;EAAM;;;;ACtC/D,CAAA;AAoJA;;;;AC5JA;;cEsBa,4CAA2C"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const require_canonical_id = require('./canonical-id-
|
|
2
|
-
const require_utils = require('./utils-
|
|
3
|
-
const require_portable = require('./portable-
|
|
4
|
-
const require_zod = require('./zod-
|
|
1
|
+
const require_canonical_id = require('./canonical-id-CcqNJHU4.cjs');
|
|
2
|
+
const require_utils = require('./utils-C2CEQL5v.cjs');
|
|
3
|
+
const require_portable = require('./portable-B75a5KJA.cjs');
|
|
4
|
+
const require_zod = require('./zod-DQuWqRtm.cjs');
|
|
5
5
|
let neverthrow = require("neverthrow");
|
|
6
6
|
|
|
7
7
|
//#region packages/common/src/scheduler/types.ts
|
|
@@ -278,6 +278,7 @@ exports.createPathTracker = require_canonical_id.createPathTracker;
|
|
|
278
278
|
exports.createPortableFS = require_portable.createPortableFS;
|
|
279
279
|
exports.createPortableHasher = require_portable.createPortableHasher;
|
|
280
280
|
exports.createSchedulerError = createSchedulerError;
|
|
281
|
+
exports.createSwcSpanConverter = require_utils.createSwcSpanConverter;
|
|
281
282
|
exports.createSyncScheduler = createSyncScheduler;
|
|
282
283
|
exports.defineSchemaFor = require_zod.defineSchemaFor;
|
|
283
284
|
exports.getPortableFS = require_portable.getPortableFS;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as createCanonicalTracker, c as CanonicalId, d as CreateCanonicalIdOptions, f as createCanonicalId, h as validateCanonicalId, i as buildAstPath, l as CanonicalIdSchema, m as parseCanonicalId, n as ScopeFrame, o as createOccurrenceTracker, p as isRelativeCanonicalId, r as ScopeHandle, s as createPathTracker, t as CanonicalPathTracker, u as CanonicalIdValidationResult } from "./index-DZSebwar.cjs";
|
|
2
2
|
import { a as __resetPortableHasherForTests, c as PortableFS, d as getPortableFS, i as PortableHasher, l as __resetPortableFSForTests, n as runtime, o as createPortableHasher, r as HashAlgorithm, s as getPortableHasher, t as resetPortableForTests, u as createPortableFS } from "./index-CbQyueYV.cjs";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as isExternalSpecifier, c as parseJsExtension, d as cachedFn, f as AliasResolver, g as readTsconfigPaths, h as TsconfigReadError, i as MODULE_EXTENSION_CANDIDATES, l as resolveRelativeImportWithExistenceCheck, m as TsconfigPathsConfig, n as createSwcSpanConverter, o as isRelativeSpecifier, p as createAliasResolver, r as JsExtensionInfo, s as normalizePath, t as SwcSpanConverter, u as resolveRelativeImportWithReferences } from "./index-BDPAGTeS.cjs";
|
|
4
4
|
import { n as ShapeFor, r as defineSchemaFor, t as SchemaFor } from "./index-LHYortIn.cjs";
|
|
5
5
|
import { Result } from "neverthrow";
|
|
6
6
|
|
|
@@ -216,5 +216,5 @@ declare const Effects: {
|
|
|
216
216
|
*/
|
|
217
217
|
declare const createSyncScheduler: () => SyncScheduler;
|
|
218
218
|
//#endregion
|
|
219
|
-
export { AliasResolver, type AsyncScheduler, CanonicalId, CanonicalIdSchema, CanonicalIdValidationResult, CanonicalPathTracker, CreateCanonicalIdOptions, DeferEffect, Effect, type EffectGenerator, type EffectGeneratorFn, type EffectResult, Effects, HashAlgorithm, JsExtensionInfo, MODULE_EXTENSION_CANDIDATES, ParallelEffect, PortableFS, PortableHasher, PureEffect, type SchedulerError, SchemaFor, ScopeFrame, ScopeHandle, ShapeFor, type SyncScheduler, TsconfigPathsConfig, TsconfigReadError, YieldEffect, __resetPortableFSForTests, __resetPortableHasherForTests, buildAstPath, cachedFn, createAliasResolver, createAsyncScheduler, createCanonicalId, createCanonicalTracker, createOccurrenceTracker, createPathTracker, createPortableFS, createPortableHasher, createSchedulerError, createSyncScheduler, defineSchemaFor, getPortableFS, getPortableHasher, isExternalSpecifier, isRelativeCanonicalId, isRelativeSpecifier, normalizePath, parseCanonicalId, parseJsExtension, readTsconfigPaths, resetPortableForTests, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences, runtime, validateCanonicalId };
|
|
219
|
+
export { AliasResolver, type AsyncScheduler, CanonicalId, CanonicalIdSchema, CanonicalIdValidationResult, CanonicalPathTracker, CreateCanonicalIdOptions, DeferEffect, Effect, type EffectGenerator, type EffectGeneratorFn, type EffectResult, Effects, HashAlgorithm, JsExtensionInfo, MODULE_EXTENSION_CANDIDATES, ParallelEffect, PortableFS, PortableHasher, PureEffect, type SchedulerError, SchemaFor, ScopeFrame, ScopeHandle, ShapeFor, SwcSpanConverter, type SyncScheduler, TsconfigPathsConfig, TsconfigReadError, YieldEffect, __resetPortableFSForTests, __resetPortableHasherForTests, buildAstPath, cachedFn, createAliasResolver, createAsyncScheduler, createCanonicalId, createCanonicalTracker, createOccurrenceTracker, createPathTracker, createPortableFS, createPortableHasher, createSchedulerError, createSwcSpanConverter, createSyncScheduler, defineSchemaFor, getPortableFS, getPortableHasher, isExternalSpecifier, isRelativeCanonicalId, isRelativeSpecifier, normalizePath, parseCanonicalId, parseJsExtension, readTsconfigPaths, resetPortableForTests, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences, runtime, validateCanonicalId };
|
|
220
220
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as createCanonicalTracker, c as CanonicalId, d as CreateCanonicalIdOptions, f as createCanonicalId, h as validateCanonicalId, i as buildAstPath, l as CanonicalIdSchema, m as parseCanonicalId, n as ScopeFrame, o as createOccurrenceTracker, p as isRelativeCanonicalId, r as ScopeHandle, s as createPathTracker, t as CanonicalPathTracker, u as CanonicalIdValidationResult } from "./index-AqkJhrm3.mjs";
|
|
2
2
|
import { a as __resetPortableHasherForTests, c as PortableFS, d as getPortableFS, i as PortableHasher, l as __resetPortableFSForTests, n as runtime, o as createPortableHasher, r as HashAlgorithm, s as getPortableHasher, t as resetPortableForTests, u as createPortableFS } from "./index-BMa2_rDb.mjs";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as isExternalSpecifier, c as parseJsExtension, d as cachedFn, f as AliasResolver, g as readTsconfigPaths, h as TsconfigReadError, i as MODULE_EXTENSION_CANDIDATES, l as resolveRelativeImportWithExistenceCheck, m as TsconfigPathsConfig, n as createSwcSpanConverter, o as isRelativeSpecifier, p as createAliasResolver, r as JsExtensionInfo, s as normalizePath, t as SwcSpanConverter, u as resolveRelativeImportWithReferences } from "./index-B1w5x8e3.mjs";
|
|
4
4
|
import { n as ShapeFor, r as defineSchemaFor, t as SchemaFor } from "./index-Dit86qkX.mjs";
|
|
5
5
|
import { Result } from "neverthrow";
|
|
6
6
|
|
|
@@ -216,5 +216,5 @@ declare const Effects: {
|
|
|
216
216
|
*/
|
|
217
217
|
declare const createSyncScheduler: () => SyncScheduler;
|
|
218
218
|
//#endregion
|
|
219
|
-
export { AliasResolver, type AsyncScheduler, CanonicalId, CanonicalIdSchema, CanonicalIdValidationResult, CanonicalPathTracker, CreateCanonicalIdOptions, DeferEffect, Effect, type EffectGenerator, type EffectGeneratorFn, type EffectResult, Effects, HashAlgorithm, JsExtensionInfo, MODULE_EXTENSION_CANDIDATES, ParallelEffect, PortableFS, PortableHasher, PureEffect, type SchedulerError, SchemaFor, ScopeFrame, ScopeHandle, ShapeFor, type SyncScheduler, TsconfigPathsConfig, TsconfigReadError, YieldEffect, __resetPortableFSForTests, __resetPortableHasherForTests, buildAstPath, cachedFn, createAliasResolver, createAsyncScheduler, createCanonicalId, createCanonicalTracker, createOccurrenceTracker, createPathTracker, createPortableFS, createPortableHasher, createSchedulerError, createSyncScheduler, defineSchemaFor, getPortableFS, getPortableHasher, isExternalSpecifier, isRelativeCanonicalId, isRelativeSpecifier, normalizePath, parseCanonicalId, parseJsExtension, readTsconfigPaths, resetPortableForTests, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences, runtime, validateCanonicalId };
|
|
219
|
+
export { AliasResolver, type AsyncScheduler, CanonicalId, CanonicalIdSchema, CanonicalIdValidationResult, CanonicalPathTracker, CreateCanonicalIdOptions, DeferEffect, Effect, type EffectGenerator, type EffectGeneratorFn, type EffectResult, Effects, HashAlgorithm, JsExtensionInfo, MODULE_EXTENSION_CANDIDATES, ParallelEffect, PortableFS, PortableHasher, PureEffect, type SchedulerError, SchemaFor, ScopeFrame, ScopeHandle, ShapeFor, SwcSpanConverter, type SyncScheduler, TsconfigPathsConfig, TsconfigReadError, YieldEffect, __resetPortableFSForTests, __resetPortableHasherForTests, buildAstPath, cachedFn, createAliasResolver, createAsyncScheduler, createCanonicalId, createCanonicalTracker, createOccurrenceTracker, createPathTracker, createPortableFS, createPortableHasher, createSchedulerError, createSwcSpanConverter, createSyncScheduler, defineSchemaFor, getPortableFS, getPortableHasher, isExternalSpecifier, isRelativeCanonicalId, isRelativeSpecifier, normalizePath, parseCanonicalId, parseJsExtension, readTsconfigPaths, resetPortableForTests, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences, runtime, validateCanonicalId };
|
|
220
220
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as getPortableHasher, c as getPortableFS, i as createPortableHasher, n as runtime, o as __resetPortableFSForTests, r as __resetPortableHasherForTests, s as createPortableFS, t as resetPortableForTests } from "./portable-BFrcBOaX.mjs";
|
|
2
|
-
import { a as
|
|
3
|
-
import { a as CanonicalIdSchema, c as parseCanonicalId, i as createPathTracker, l as validateCanonicalId, n as createCanonicalTracker, o as createCanonicalId, r as createOccurrenceTracker, s as isRelativeCanonicalId, t as buildAstPath } from "./canonical-id-
|
|
2
|
+
import { a as MODULE_EXTENSION_CANDIDATES, c as normalizePath, d as resolveRelativeImportWithReferences, i as createAliasResolver, l as parseJsExtension, n as createSwcSpanConverter, o as isExternalSpecifier, r as cachedFn, s as isRelativeSpecifier, t as readTsconfigPaths, u as resolveRelativeImportWithExistenceCheck } from "./utils-DlhM4qvh.mjs";
|
|
3
|
+
import { a as CanonicalIdSchema, c as parseCanonicalId, i as createPathTracker, l as validateCanonicalId, n as createCanonicalTracker, o as createCanonicalId, r as createOccurrenceTracker, s as isRelativeCanonicalId, t as buildAstPath } from "./canonical-id-U2VNaQ86.mjs";
|
|
4
4
|
import { t as defineSchemaFor } from "./zod-DeSimXdI.mjs";
|
|
5
5
|
import { err, ok } from "neverthrow";
|
|
6
6
|
|
|
@@ -257,5 +257,5 @@ const isSchedulerError = (error) => {
|
|
|
257
257
|
};
|
|
258
258
|
|
|
259
259
|
//#endregion
|
|
260
|
-
export { CanonicalIdSchema, DeferEffect, Effect, Effects, MODULE_EXTENSION_CANDIDATES, ParallelEffect, PureEffect, YieldEffect, __resetPortableFSForTests, __resetPortableHasherForTests, buildAstPath, cachedFn, createAliasResolver, createAsyncScheduler, createCanonicalId, createCanonicalTracker, createOccurrenceTracker, createPathTracker, createPortableFS, createPortableHasher, createSchedulerError, createSyncScheduler, defineSchemaFor, getPortableFS, getPortableHasher, isExternalSpecifier, isRelativeCanonicalId, isRelativeSpecifier, normalizePath, parseCanonicalId, parseJsExtension, readTsconfigPaths, resetPortableForTests, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences, runtime, validateCanonicalId };
|
|
260
|
+
export { CanonicalIdSchema, DeferEffect, Effect, Effects, MODULE_EXTENSION_CANDIDATES, ParallelEffect, PureEffect, YieldEffect, __resetPortableFSForTests, __resetPortableHasherForTests, buildAstPath, cachedFn, createAliasResolver, createAsyncScheduler, createCanonicalId, createCanonicalTracker, createOccurrenceTracker, createPathTracker, createPortableFS, createPortableHasher, createSchedulerError, createSwcSpanConverter, createSyncScheduler, defineSchemaFor, getPortableFS, getPortableHasher, isExternalSpecifier, isRelativeCanonicalId, isRelativeSpecifier, normalizePath, parseCanonicalId, parseJsExtension, readTsconfigPaths, resetPortableForTests, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences, runtime, validateCanonicalId };
|
|
261
261
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_canonical_id = require('./canonical-id-
|
|
1
|
+
const require_canonical_id = require('./canonical-id-CcqNJHU4.cjs');
|
|
2
2
|
let node_crypto = require("node:crypto");
|
|
3
3
|
|
|
4
4
|
//#region packages/common/src/portable/fs.ts
|
|
@@ -236,4 +236,4 @@ Object.defineProperty(exports, 'runtime', {
|
|
|
236
236
|
return runtime;
|
|
237
237
|
}
|
|
238
238
|
});
|
|
239
|
-
//# sourceMappingURL=portable-
|
|
239
|
+
//# sourceMappingURL=portable-B75a5KJA.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portable-B3K3IE7E.cjs","names":["nodeFsPromises: FSPromises | null","nodeFsSync: FSSync | null","pathModule: { dirname: (path: string) => string } | null","pathModule","fsInstance: PortableFS | null","hasherInstance: PortableHasher | null"],"sources":["../src/portable/fs.ts","../src/portable/hash.ts","../src/portable/runtime.ts"],"sourcesContent":["/**\n * Portable filesystem API using Node.js fs\n */\n\nexport interface PortableFS {\n readFile(path: string): Promise<string>;\n writeFile(path: string, content: string): Promise<void>;\n /**\n * Write a file atomically using temp file + rename pattern.\n * This prevents partial/corrupt writes on crash.\n */\n writeFileAtomic(path: string, content: string): Promise<void>;\n exists(path: string): Promise<boolean>;\n stat(path: string): Promise<{ mtime: Date; size: number }>;\n rename(oldPath: string, newPath: string): Promise<void>;\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;\n /**\n * Write a file synchronously and atomically using temp file + rename pattern.\n * Safe for use in beforeExit handlers.\n */\n writeFileSyncAtomic(path: string, content: string): void;\n /**\n * Remove a file. Does not throw if file doesn't exist.\n */\n unlink(path: string): Promise<void>;\n /**\n * Remove a file synchronously. Does not throw if file doesn't exist.\n */\n unlinkSync(path: string): void;\n /**\n * Read a file synchronously.\n */\n readFileSync(path: string): string;\n}\n\ninterface FSPromises {\n readFile: (path: string, encoding: string) => Promise<string>;\n writeFile: (path: string, content: string, encoding: string) => Promise<void>;\n access: (path: string) => Promise<void>;\n stat: (path: string) => Promise<{\n mtime: Date;\n size: number;\n isDirectory: () => boolean;\n }>;\n rename: (oldPath: string, newPath: string) => Promise<void>;\n mkdir: (path: string, options?: { recursive?: boolean }) => Promise<void>;\n unlink: (path: string) => Promise<void>;\n}\n\ninterface FSSync {\n writeFileSync: (path: string, content: string, encoding: string) => void;\n renameSync: (oldPath: string, newPath: string) => void;\n unlinkSync: (path: string) => void;\n readFileSync: (path: string, encoding: string) => string;\n mkdirSync: (path: string, options?: { recursive?: boolean }) => void;\n}\n\n// Cache the fs/promises import\nlet nodeFsPromises: FSPromises | null = null;\nconst getNodeFS = async (): Promise<FSPromises> => {\n if (!nodeFsPromises) {\n const fs = await import(\"node:fs/promises\");\n nodeFsPromises = fs as FSPromises;\n }\n return nodeFsPromises;\n};\n\n// Cache the sync fs import\nlet nodeFsSync: FSSync | null = null;\nconst getNodeFSSync = (): FSSync => {\n if (!nodeFsSync) {\n // Use require for sync loading\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n nodeFsSync = require(\"node:fs\") as FSSync;\n }\n return nodeFsSync;\n};\n\n// Cache path module\nlet pathModule: { dirname: (path: string) => string } | null = null;\nconst getPathModule = (): { dirname: (path: string) => string } => {\n if (!pathModule) {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n pathModule = require(\"node:path\") as { dirname: (path: string) => string };\n }\n return pathModule;\n};\n\n/**\n * Generate a unique temp file path for atomic write.\n */\nconst getTempPath = (targetPath: string): string => {\n return `${targetPath}.${process.pid}.${Date.now()}.tmp`;\n};\n\nexport function createPortableFS(): PortableFS {\n return {\n async readFile(path) {\n const nodeFS = await getNodeFS();\n return await nodeFS.readFile(path, \"utf-8\");\n },\n\n async writeFile(path, content) {\n const nodeFS = await getNodeFS();\n // Auto-create parent directories like Bun.write does\n const pathModule = await import(\"node:path\");\n const dir = pathModule.dirname(path);\n await nodeFS.mkdir(dir, { recursive: true });\n await nodeFS.writeFile(path, content, \"utf-8\");\n },\n\n async writeFileAtomic(path, content) {\n const nodeFS = await getNodeFS();\n const pathMod = await import(\"node:path\");\n const dir = pathMod.dirname(path);\n const tempPath = getTempPath(path);\n\n try {\n await nodeFS.mkdir(dir, { recursive: true });\n await nodeFS.writeFile(tempPath, content, \"utf-8\");\n await nodeFS.rename(tempPath, path);\n } catch (error) {\n // Clean up temp file on failure\n try {\n await nodeFS.unlink(tempPath);\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n },\n\n async exists(path) {\n const nodeFS = await getNodeFS();\n try {\n await nodeFS.access(path);\n return true;\n } catch {\n return false;\n }\n },\n\n async stat(path) {\n const nodeFS = await getNodeFS();\n const stats = await nodeFS.stat(path);\n return { mtime: stats.mtime, size: stats.size };\n },\n\n async rename(oldPath, newPath) {\n const nodeFS = await getNodeFS();\n await nodeFS.rename(oldPath, newPath);\n },\n\n async mkdir(path, options) {\n const nodeFS = await getNodeFS();\n await nodeFS.mkdir(path, options);\n },\n\n writeFileSyncAtomic(path, content) {\n const fsSync = getNodeFSSync();\n const pathMod = getPathModule();\n const tempPath = getTempPath(path);\n\n // Ensure parent directory exists\n const dir = pathMod.dirname(path);\n fsSync.mkdirSync(dir, { recursive: true });\n\n try {\n fsSync.writeFileSync(tempPath, content, \"utf-8\");\n fsSync.renameSync(tempPath, path);\n } catch (error) {\n // Clean up temp file on failure\n try {\n fsSync.unlinkSync(tempPath);\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n },\n\n async unlink(path) {\n const nodeFS = await getNodeFS();\n try {\n await nodeFS.unlink(path);\n } catch (error) {\n // Ignore ENOENT (file not found)\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n },\n\n unlinkSync(path) {\n const fsSync = getNodeFSSync();\n try {\n fsSync.unlinkSync(path);\n } catch (error) {\n // Ignore ENOENT (file not found)\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n },\n\n readFileSync(path) {\n const fsSync = getNodeFSSync();\n return fsSync.readFileSync(path, \"utf-8\");\n },\n };\n}\n\n// Singleton to avoid recreating instances\nlet fsInstance: PortableFS | null = null;\n\nexport function getPortableFS(): PortableFS {\n if (!fsInstance) {\n fsInstance = createPortableFS();\n }\n return fsInstance;\n}\n\n/**\n * Reset the filesystem singleton for testing\n * @internal\n */\nexport function __resetPortableFSForTests(): void {\n fsInstance = null;\n}\n","/**\n * Portable hashing API using Node.js crypto\n */\n\nimport { createHash } from \"node:crypto\";\n\nexport type HashAlgorithm = \"sha256\" | \"xxhash\";\n\nexport interface PortableHasher {\n hash(content: string, algorithm?: HashAlgorithm): string;\n}\n\nexport function createPortableHasher(): PortableHasher {\n return {\n hash(content, algorithm = \"xxhash\") {\n if (algorithm === \"sha256\") {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n }\n // xxhash fallback: use sha256 truncated to 16 chars\n const sha256Hash = createHash(\"sha256\").update(content).digest(\"hex\");\n return sha256Hash.substring(0, 16);\n },\n };\n}\n\n// Singleton to avoid recreating instances\nlet hasherInstance: PortableHasher | null = null;\n\nexport function getPortableHasher(): PortableHasher {\n if (!hasherInstance) {\n hasherInstance = createPortableHasher();\n }\n return hasherInstance;\n}\n\n/**\n * Reset the hasher singleton for testing\n * @internal\n */\nexport function __resetPortableHasherForTests(): void {\n hasherInstance = null;\n}\n","/**\n * Runtime detection utilities for portable API implementation\n * Note: Bun-specific code has been removed. Node.js APIs are always used.\n */\n\nexport const runtime = {\n isBun: false,\n isNode: typeof process !== \"undefined\",\n supportsWebCrypto: typeof crypto !== \"undefined\" && typeof crypto.subtle !== \"undefined\",\n} as const;\n\n/**\n * Reset runtime state for testing purposes only\n * @internal\n */\nexport function resetPortableForTests(): void {\n // This is a marker function that portable modules can use\n // to reset their singleton state in tests\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"portable-B75a5KJA.cjs","names":["nodeFsPromises: FSPromises | null","nodeFsSync: FSSync | null","pathModule: { dirname: (path: string) => string } | null","pathModule","fsInstance: PortableFS | null","hasherInstance: PortableHasher | null"],"sources":["../src/portable/fs.ts","../src/portable/hash.ts","../src/portable/runtime.ts"],"sourcesContent":["/**\n * Portable filesystem API using Node.js fs\n */\n\nexport interface PortableFS {\n readFile(path: string): Promise<string>;\n writeFile(path: string, content: string): Promise<void>;\n /**\n * Write a file atomically using temp file + rename pattern.\n * This prevents partial/corrupt writes on crash.\n */\n writeFileAtomic(path: string, content: string): Promise<void>;\n exists(path: string): Promise<boolean>;\n stat(path: string): Promise<{ mtime: Date; size: number }>;\n rename(oldPath: string, newPath: string): Promise<void>;\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;\n /**\n * Write a file synchronously and atomically using temp file + rename pattern.\n * Safe for use in beforeExit handlers.\n */\n writeFileSyncAtomic(path: string, content: string): void;\n /**\n * Remove a file. Does not throw if file doesn't exist.\n */\n unlink(path: string): Promise<void>;\n /**\n * Remove a file synchronously. Does not throw if file doesn't exist.\n */\n unlinkSync(path: string): void;\n /**\n * Read a file synchronously.\n */\n readFileSync(path: string): string;\n}\n\ninterface FSPromises {\n readFile: (path: string, encoding: string) => Promise<string>;\n writeFile: (path: string, content: string, encoding: string) => Promise<void>;\n access: (path: string) => Promise<void>;\n stat: (path: string) => Promise<{\n mtime: Date;\n size: number;\n isDirectory: () => boolean;\n }>;\n rename: (oldPath: string, newPath: string) => Promise<void>;\n mkdir: (path: string, options?: { recursive?: boolean }) => Promise<void>;\n unlink: (path: string) => Promise<void>;\n}\n\ninterface FSSync {\n writeFileSync: (path: string, content: string, encoding: string) => void;\n renameSync: (oldPath: string, newPath: string) => void;\n unlinkSync: (path: string) => void;\n readFileSync: (path: string, encoding: string) => string;\n mkdirSync: (path: string, options?: { recursive?: boolean }) => void;\n}\n\n// Cache the fs/promises import\nlet nodeFsPromises: FSPromises | null = null;\nconst getNodeFS = async (): Promise<FSPromises> => {\n if (!nodeFsPromises) {\n const fs = await import(\"node:fs/promises\");\n nodeFsPromises = fs as FSPromises;\n }\n return nodeFsPromises;\n};\n\n// Cache the sync fs import\nlet nodeFsSync: FSSync | null = null;\nconst getNodeFSSync = (): FSSync => {\n if (!nodeFsSync) {\n // Use require for sync loading\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n nodeFsSync = require(\"node:fs\") as FSSync;\n }\n return nodeFsSync;\n};\n\n// Cache path module\nlet pathModule: { dirname: (path: string) => string } | null = null;\nconst getPathModule = (): { dirname: (path: string) => string } => {\n if (!pathModule) {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n pathModule = require(\"node:path\") as { dirname: (path: string) => string };\n }\n return pathModule;\n};\n\n/**\n * Generate a unique temp file path for atomic write.\n */\nconst getTempPath = (targetPath: string): string => {\n return `${targetPath}.${process.pid}.${Date.now()}.tmp`;\n};\n\nexport function createPortableFS(): PortableFS {\n return {\n async readFile(path) {\n const nodeFS = await getNodeFS();\n return await nodeFS.readFile(path, \"utf-8\");\n },\n\n async writeFile(path, content) {\n const nodeFS = await getNodeFS();\n // Auto-create parent directories like Bun.write does\n const pathModule = await import(\"node:path\");\n const dir = pathModule.dirname(path);\n await nodeFS.mkdir(dir, { recursive: true });\n await nodeFS.writeFile(path, content, \"utf-8\");\n },\n\n async writeFileAtomic(path, content) {\n const nodeFS = await getNodeFS();\n const pathMod = await import(\"node:path\");\n const dir = pathMod.dirname(path);\n const tempPath = getTempPath(path);\n\n try {\n await nodeFS.mkdir(dir, { recursive: true });\n await nodeFS.writeFile(tempPath, content, \"utf-8\");\n await nodeFS.rename(tempPath, path);\n } catch (error) {\n // Clean up temp file on failure\n try {\n await nodeFS.unlink(tempPath);\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n },\n\n async exists(path) {\n const nodeFS = await getNodeFS();\n try {\n await nodeFS.access(path);\n return true;\n } catch {\n return false;\n }\n },\n\n async stat(path) {\n const nodeFS = await getNodeFS();\n const stats = await nodeFS.stat(path);\n return { mtime: stats.mtime, size: stats.size };\n },\n\n async rename(oldPath, newPath) {\n const nodeFS = await getNodeFS();\n await nodeFS.rename(oldPath, newPath);\n },\n\n async mkdir(path, options) {\n const nodeFS = await getNodeFS();\n await nodeFS.mkdir(path, options);\n },\n\n writeFileSyncAtomic(path, content) {\n const fsSync = getNodeFSSync();\n const pathMod = getPathModule();\n const tempPath = getTempPath(path);\n\n // Ensure parent directory exists\n const dir = pathMod.dirname(path);\n fsSync.mkdirSync(dir, { recursive: true });\n\n try {\n fsSync.writeFileSync(tempPath, content, \"utf-8\");\n fsSync.renameSync(tempPath, path);\n } catch (error) {\n // Clean up temp file on failure\n try {\n fsSync.unlinkSync(tempPath);\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n },\n\n async unlink(path) {\n const nodeFS = await getNodeFS();\n try {\n await nodeFS.unlink(path);\n } catch (error) {\n // Ignore ENOENT (file not found)\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n },\n\n unlinkSync(path) {\n const fsSync = getNodeFSSync();\n try {\n fsSync.unlinkSync(path);\n } catch (error) {\n // Ignore ENOENT (file not found)\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n },\n\n readFileSync(path) {\n const fsSync = getNodeFSSync();\n return fsSync.readFileSync(path, \"utf-8\");\n },\n };\n}\n\n// Singleton to avoid recreating instances\nlet fsInstance: PortableFS | null = null;\n\nexport function getPortableFS(): PortableFS {\n if (!fsInstance) {\n fsInstance = createPortableFS();\n }\n return fsInstance;\n}\n\n/**\n * Reset the filesystem singleton for testing\n * @internal\n */\nexport function __resetPortableFSForTests(): void {\n fsInstance = null;\n}\n","/**\n * Portable hashing API using Node.js crypto\n */\n\nimport { createHash } from \"node:crypto\";\n\nexport type HashAlgorithm = \"sha256\" | \"xxhash\";\n\nexport interface PortableHasher {\n hash(content: string, algorithm?: HashAlgorithm): string;\n}\n\nexport function createPortableHasher(): PortableHasher {\n return {\n hash(content, algorithm = \"xxhash\") {\n if (algorithm === \"sha256\") {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n }\n // xxhash fallback: use sha256 truncated to 16 chars\n const sha256Hash = createHash(\"sha256\").update(content).digest(\"hex\");\n return sha256Hash.substring(0, 16);\n },\n };\n}\n\n// Singleton to avoid recreating instances\nlet hasherInstance: PortableHasher | null = null;\n\nexport function getPortableHasher(): PortableHasher {\n if (!hasherInstance) {\n hasherInstance = createPortableHasher();\n }\n return hasherInstance;\n}\n\n/**\n * Reset the hasher singleton for testing\n * @internal\n */\nexport function __resetPortableHasherForTests(): void {\n hasherInstance = null;\n}\n","/**\n * Runtime detection utilities for portable API implementation\n * Note: Bun-specific code has been removed. Node.js APIs are always used.\n */\n\nexport const runtime = {\n isBun: false,\n isNode: typeof process !== \"undefined\",\n supportsWebCrypto: typeof crypto !== \"undefined\" && typeof crypto.subtle !== \"undefined\",\n} as const;\n\n/**\n * Reset runtime state for testing purposes only\n * @internal\n */\nexport function resetPortableForTests(): void {\n // This is a marker function that portable modules can use\n // to reset their singleton state in tests\n}\n"],"mappings":"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"}
|
package/dist/portable.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_portable = require('./portable-
|
|
1
|
+
const require_portable = require('./portable-B75a5KJA.cjs');
|
|
2
2
|
|
|
3
3
|
exports.__resetPortableFSForTests = require_portable.__resetPortableFSForTests;
|
|
4
4
|
exports.__resetPortableHasherForTests = require_portable.__resetPortableHasherForTests;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_canonical_id = require('./canonical-id-
|
|
1
|
+
const require_canonical_id = require('./canonical-id-CcqNJHU4.cjs');
|
|
2
2
|
let node_path = require("node:path");
|
|
3
3
|
let node_fs = require("node:fs");
|
|
4
4
|
let neverthrow = require("neverthrow");
|
|
@@ -305,6 +305,43 @@ const cachedFn = (fn) => {
|
|
|
305
305
|
return ensure;
|
|
306
306
|
};
|
|
307
307
|
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region packages/common/src/utils/swc-span.ts
|
|
310
|
+
/**
|
|
311
|
+
* Create a converter that maps UTF-8 byte offsets to UTF-16 char indices
|
|
312
|
+
* for the given source string.
|
|
313
|
+
*
|
|
314
|
+
* Includes a fast path for ASCII-only sources (zero allocation).
|
|
315
|
+
*/
|
|
316
|
+
const createSwcSpanConverter = (source) => {
|
|
317
|
+
const byteLength = Buffer.byteLength(source, "utf8");
|
|
318
|
+
if (byteLength === source.length) {
|
|
319
|
+
return {
|
|
320
|
+
byteLength,
|
|
321
|
+
byteOffsetToCharIndex: (byteOffset) => byteOffset
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
const byteToChar = new Uint32Array(byteLength + 1);
|
|
325
|
+
let bytePos = 0;
|
|
326
|
+
for (let charIdx = 0; charIdx < source.length; charIdx++) {
|
|
327
|
+
const codePoint = source.codePointAt(charIdx);
|
|
328
|
+
if (codePoint === undefined) break;
|
|
329
|
+
const bytesForCodePoint = codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
|
|
330
|
+
for (let b = 0; b < bytesForCodePoint; b++) {
|
|
331
|
+
byteToChar[bytePos + b] = charIdx;
|
|
332
|
+
}
|
|
333
|
+
bytePos += bytesForCodePoint;
|
|
334
|
+
if (codePoint > 65535) {
|
|
335
|
+
charIdx++;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
byteToChar[byteLength] = source.length;
|
|
339
|
+
return {
|
|
340
|
+
byteLength,
|
|
341
|
+
byteOffsetToCharIndex: (byteOffset) => byteToChar[byteOffset] ?? source.length
|
|
342
|
+
};
|
|
343
|
+
};
|
|
344
|
+
|
|
308
345
|
//#endregion
|
|
309
346
|
//#region packages/common/src/utils/tsconfig.ts
|
|
310
347
|
/**
|
|
@@ -386,6 +423,12 @@ Object.defineProperty(exports, 'createAliasResolver', {
|
|
|
386
423
|
return createAliasResolver;
|
|
387
424
|
}
|
|
388
425
|
});
|
|
426
|
+
Object.defineProperty(exports, 'createSwcSpanConverter', {
|
|
427
|
+
enumerable: true,
|
|
428
|
+
get: function () {
|
|
429
|
+
return createSwcSpanConverter;
|
|
430
|
+
}
|
|
431
|
+
});
|
|
389
432
|
Object.defineProperty(exports, 'isExternalSpecifier', {
|
|
390
433
|
enumerable: true,
|
|
391
434
|
get: function () {
|
|
@@ -428,4 +471,4 @@ Object.defineProperty(exports, 'resolveRelativeImportWithReferences', {
|
|
|
428
471
|
return resolveRelativeImportWithReferences;
|
|
429
472
|
}
|
|
430
473
|
});
|
|
431
|
-
//# sourceMappingURL=utils-
|
|
474
|
+
//# sourceMappingURL=utils-C2CEQL5v.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-C2CEQL5v.cjs","names":["JS_TO_TS_EXTENSION_MAP: Readonly<Record<string, readonly string[]>>","cached: { value: T } | null","content: string","parsed: unknown","resolvedPaths: Record<string, readonly string[]>"],"sources":["../src/utils/path.ts","../src/utils/alias-resolver.ts","../src/utils/cached-fn.ts","../src/utils/swc-span.ts","../src/utils/tsconfig.ts"],"sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { dirname, join, normalize, resolve } from \"node:path\";\n\n/**\n * File extensions to try when resolving module specifiers.\n * Ordered to match TypeScript's module resolution order.\n * @see https://www.typescriptlang.org/docs/handbook/module-resolution.html\n */\nexport const MODULE_EXTENSION_CANDIDATES = [\".ts\", \".tsx\", \".mts\", \".cts\", \".js\", \".mjs\", \".cjs\", \".jsx\"] as const;\n\n/**\n * Mapping from JS extensions to their corresponding TS extensions.\n * Used for ESM-style imports where .js is written but .ts is the actual source.\n */\nconst JS_TO_TS_EXTENSION_MAP: Readonly<Record<string, readonly string[]>> = {\n \".js\": [\".ts\", \".tsx\"],\n \".mjs\": [\".mts\"],\n \".cjs\": [\".cts\"],\n \".jsx\": [\".tsx\"],\n};\n\n/**\n * Result of parsing a JS extension from a specifier.\n */\nexport type JsExtensionInfo = {\n /** The specifier without the JS extension */\n readonly base: string;\n /** The JS extension found (e.g., \".js\", \".mjs\") */\n readonly jsExtension: string;\n /** The corresponding TS extensions to try (e.g., [\".ts\", \".tsx\"] for \".js\") */\n readonly tsExtensions: readonly string[];\n};\n\n/**\n * Parse a JS extension from a specifier for ESM-style import resolution.\n * Returns the base path (without extension), the JS extension, and corresponding TS extensions.\n *\n * @param specifier - The import specifier to parse\n * @returns Object with base, jsExtension, and tsExtensions, or null if no JS extension found\n *\n * @example\n * parseJsExtension(\"./foo.js\") // { base: \"./foo\", jsExtension: \".js\", tsExtensions: [\".ts\", \".tsx\"] }\n * parseJsExtension(\"./foo.mjs\") // { base: \"./foo\", jsExtension: \".mjs\", tsExtensions: [\".mts\"] }\n * parseJsExtension(\"./foo\") // null\n * parseJsExtension(\"./foo.ts\") // null\n */\nexport const parseJsExtension = (specifier: string): JsExtensionInfo | null => {\n for (const [ext, tsExts] of Object.entries(JS_TO_TS_EXTENSION_MAP)) {\n if (specifier.endsWith(ext)) {\n return {\n base: specifier.slice(0, -ext.length),\n jsExtension: ext,\n tsExtensions: tsExts,\n };\n }\n }\n return null;\n};\n\n/**\n * Normalize path to use forward slashes (cross-platform).\n * Ensures consistent path handling across platforms.\n */\nexport const normalizePath = (value: string): string => normalize(value).replace(/\\\\/g, \"/\");\n\n/**\n * Resolve a relative import specifier to an absolute file path.\n * Tries the specifier as-is, with extensions, and as a directory with index files.\n *\n * @param from - Absolute path to the importing file\n * @param specifier - Relative module specifier (must start with '.')\n * @returns Absolute POSIX path to the resolved file, or null if not found\n */\nexport const resolveRelativeImportWithExistenceCheck = ({\n filePath,\n specifier,\n}: {\n filePath: string;\n specifier: string;\n}): string | null => {\n // Handle ESM-style imports with JS extensions (e.g., \"./foo.js\" -> \"./foo.ts\")\n const jsExtInfo = parseJsExtension(specifier);\n if (jsExtInfo) {\n const baseWithoutExt = resolve(dirname(filePath), jsExtInfo.base);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Fall back to actual JS file if it exists\n const jsCandidate = `${baseWithoutExt}${jsExtInfo.jsExtension}`;\n if (existsSync(jsCandidate)) {\n try {\n const stat = statSync(jsCandidate);\n if (stat.isFile()) {\n return normalizePath(jsCandidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n }\n\n const base = resolve(dirname(filePath), specifier);\n\n // Try with extensions first (most common case)\n // This handles cases like \"./constants\" resolving to \"./constants.ts\"\n // even when a \"./constants\" directory exists\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${base}${ext}`;\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(base, `index${ext}`);\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try exact path last (only if it's a file, not directory)\n if (existsSync(base)) {\n try {\n const stat = statSync(base);\n if (stat.isFile()) {\n return normalizePath(base);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n};\n\n/**\n * Resolve a relative import specifier to an absolute file path.\n * Tries the specifier as-is, with extensions, and as a directory with index files.\n *\n * @param from - Absolute path to the importing file\n * @param specifier - Relative module specifier (must start with '.')\n * @returns Absolute POSIX path to the resolved file, or null if not found\n */\nexport const resolveRelativeImportWithReferences = <_>({\n filePath,\n specifier,\n references,\n}: {\n filePath: string;\n specifier: string;\n references: Map<string, _> | Set<string>;\n}): string | null => {\n // Handle ESM-style imports with JS extensions (e.g., \"./foo.js\" -> \"./foo.ts\")\n const jsExtInfo = parseJsExtension(specifier);\n if (jsExtInfo) {\n const baseWithoutExt = resolve(dirname(filePath), jsExtInfo.base);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Fall back to actual JS file if it exists in references\n const jsCandidate = `${baseWithoutExt}${jsExtInfo.jsExtension}`;\n if (references.has(jsCandidate)) {\n return normalizePath(jsCandidate);\n }\n\n return null;\n }\n\n const base = resolve(dirname(filePath), specifier);\n\n // Try exact path first\n if (references.has(base)) {\n return normalizePath(base);\n }\n\n // Try with extensions\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${base}${ext}`;\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(base, `index${ext}`);\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n return null;\n};\n\n/**\n * Check if a module specifier is relative (starts with '.' or '..')\n */\nexport const isRelativeSpecifier = (specifier: string): boolean => specifier.startsWith(\"./\") || specifier.startsWith(\"../\");\n\n/**\n * Check if a module specifier is external (package name, not relative)\n */\nexport const isExternalSpecifier = (specifier: string): boolean => !isRelativeSpecifier(specifier);\n","import { existsSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { MODULE_EXTENSION_CANDIDATES, normalizePath, parseJsExtension } from \"./path\";\nimport type { TsconfigPathsConfig } from \"./tsconfig\";\n\n/**\n * Alias resolver interface for resolving path aliases to file paths.\n */\nexport type AliasResolver = {\n /**\n * Resolve an alias specifier to an absolute file path.\n * Returns null if the specifier doesn't match any alias pattern\n * or if the resolved file doesn't exist.\n */\n readonly resolve: (specifier: string) => string | null;\n};\n\n/**\n * Match a specifier against a tsconfig path pattern.\n * Returns the captured wildcard portion or null if no match.\n *\n * Pattern rules:\n * - Exact match: \"@/utils\" matches \"@/utils\" exactly, captures \"\"\n * - Wildcard: \"@/*\" matches \"@/foo\", captures \"foo\"\n * - Wildcard with suffix: \"*.js\" matches \"foo.js\", captures \"foo\"\n */\nconst matchPattern = (specifier: string, pattern: string): string | null => {\n const starIndex = pattern.indexOf(\"*\");\n\n if (starIndex === -1) {\n // Exact match - no wildcard\n return specifier === pattern ? \"\" : null;\n }\n\n const prefix = pattern.slice(0, starIndex);\n const suffix = pattern.slice(starIndex + 1);\n\n if (!specifier.startsWith(prefix)) {\n return null;\n }\n\n if (suffix && !specifier.endsWith(suffix)) {\n return null;\n }\n\n // Extract the wildcard capture\n const captured = specifier.slice(prefix.length, suffix ? specifier.length - suffix.length : undefined);\n\n return captured;\n};\n\n/**\n * Apply a captured wildcard to a target path.\n */\nconst applyCapture = (target: string, captured: string): string => {\n const starIndex = target.indexOf(\"*\");\n if (starIndex === -1) {\n return target;\n }\n return target.slice(0, starIndex) + captured + target.slice(starIndex + 1);\n};\n\n/**\n * Try to resolve a path to an actual file, applying extension resolution.\n * Handles ESM-style imports with JS extensions.\n */\nconst resolveToFile = (basePath: string): string | null => {\n // Handle ESM-style JS extension imports\n const jsExtInfo = parseJsExtension(basePath);\n if (jsExtInfo) {\n const baseWithoutExt = basePath.slice(0, -jsExtInfo.jsExtension.length);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n // Fall back to actual JS file\n if (existsSync(basePath)) {\n try {\n const stat = statSync(basePath);\n if (stat.isFile()) {\n return normalizePath(basePath);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n }\n\n // Try exact path first (for paths with explicit extension)\n if (existsSync(basePath)) {\n try {\n const stat = statSync(basePath);\n if (stat.isFile()) {\n return normalizePath(basePath);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n // Try with extensions\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${basePath}${ext}`;\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(basePath, `index${ext}`);\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n return null;\n};\n\n/**\n * Create an alias resolver from tsconfig paths configuration.\n *\n * Resolution behavior:\n * 1. Try each pattern in order (first match wins per TS spec)\n * 2. For each matched pattern, try all target paths in order\n * 3. For each target, apply extension resolution\n * 4. Return first found file, or null if none found\n */\nexport const createAliasResolver = (config: TsconfigPathsConfig): AliasResolver => {\n const { paths } = config;\n const patterns = Object.keys(paths);\n\n return {\n resolve: (specifier: string): string | null => {\n // Try each pattern in order (first match wins per TS spec)\n for (const pattern of patterns) {\n const captured = matchPattern(specifier, pattern);\n if (captured === null) {\n continue;\n }\n\n const targets = paths[pattern];\n if (!targets) {\n continue;\n }\n\n // Try each target path in order\n for (const target of targets) {\n const resolvedTarget = applyCapture(target, captured);\n const result = resolveToFile(resolvedTarget);\n if (result) {\n return result;\n }\n }\n }\n\n return null;\n },\n };\n};\n","export const cachedFn = <T>(fn: () => T) => {\n let cached: { value: T } | null = null;\n\n const ensure = () => (cached ??= { value: fn() }).value;\n ensure.clear = () => {\n cached = null;\n };\n\n return ensure;\n};\n","/**\n * SWC span position converter: UTF-8 byte offsets → UTF-16 code unit indices.\n *\n * SWC (Rust-based) returns span positions as UTF-8 byte offsets.\n * JavaScript strings use UTF-16 code units for indexing.\n * For ASCII-only content these are identical, but for multi-byte\n * characters the positions diverge.\n */\n\nexport type SwcSpanConverter = {\n /** UTF-8 byte length of the source string */\n readonly byteLength: number;\n /** Convert a UTF-8 byte offset (within the source) to a UTF-16 code unit index */\n readonly byteOffsetToCharIndex: (byteOffset: number) => number;\n};\n\n/**\n * Create a converter that maps UTF-8 byte offsets to UTF-16 char indices\n * for the given source string.\n *\n * Includes a fast path for ASCII-only sources (zero allocation).\n */\nexport const createSwcSpanConverter = (source: string): SwcSpanConverter => {\n const byteLength = Buffer.byteLength(source, \"utf8\");\n\n // Fast path: ASCII-only — byte offsets equal char indices\n if (byteLength === source.length) {\n return {\n byteLength,\n byteOffsetToCharIndex: (byteOffset: number) => byteOffset,\n };\n }\n\n // Build lookup table: byteOffset → charIndex\n const byteToChar = new Uint32Array(byteLength + 1);\n let bytePos = 0;\n\n for (let charIdx = 0; charIdx < source.length; charIdx++) {\n const codePoint = source.codePointAt(charIdx);\n if (codePoint === undefined) break;\n const bytesForCodePoint = codePoint <= 0x7f ? 1 : codePoint <= 0x7ff ? 2 : codePoint <= 0xffff ? 3 : 4;\n\n for (let b = 0; b < bytesForCodePoint; b++) {\n byteToChar[bytePos + b] = charIdx;\n }\n bytePos += bytesForCodePoint;\n\n // Astral code points use a surrogate pair (2 UTF-16 code units)\n if (codePoint > 0xffff) {\n charIdx++;\n }\n }\n\n // Sentinel: end-of-string\n byteToChar[byteLength] = source.length;\n\n return {\n byteLength,\n byteOffsetToCharIndex: (byteOffset: number) => byteToChar[byteOffset] ?? source.length,\n };\n};\n","import { readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { err, ok, type Result } from \"neverthrow\";\n\n/**\n * Parsed tsconfig.json paths configuration.\n * All paths are resolved to absolute paths.\n */\nexport type TsconfigPathsConfig = {\n /** Absolute base URL for path resolution */\n readonly baseUrl: string;\n /** Path mappings with absolute paths */\n readonly paths: Readonly<Record<string, readonly string[]>>;\n};\n\n/**\n * Error types for tsconfig reading.\n */\nexport type TsconfigReadError = {\n readonly code: \"TSCONFIG_READ_FAILED\" | \"TSCONFIG_PARSE_FAILED\" | \"TSCONFIG_INVALID\";\n readonly message: string;\n};\n\n/**\n * Strip JSON comments and trailing commas for parsing.\n * Handles both line comments (//) and block comments.\n */\nconst stripJsonComments = (json: string): string => {\n return (\n json\n // Remove block comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n // Remove line comments\n .replace(/\\/\\/.*/g, \"\")\n // Remove trailing commas before } or ]\n .replace(/,(\\s*[}\\]])/g, \"$1\")\n );\n};\n\n/**\n * Read and parse tsconfig.json to extract paths configuration.\n * Currently does not support `extends` - reads only the specified file.\n *\n * @param tsconfigPath - Absolute path to tsconfig.json\n * @returns Parsed paths configuration or null if no paths defined\n */\nexport const readTsconfigPaths = (tsconfigPath: string): Result<TsconfigPathsConfig | null, TsconfigReadError> => {\n // Read file\n let content: string;\n try {\n content = readFileSync(tsconfigPath, \"utf-8\");\n } catch (error) {\n return err({\n code: \"TSCONFIG_READ_FAILED\",\n message: `Failed to read tsconfig.json: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Parse JSON (with comment stripping)\n let parsed: unknown;\n try {\n const cleaned = stripJsonComments(content);\n parsed = JSON.parse(cleaned);\n } catch (error) {\n return err({\n code: \"TSCONFIG_PARSE_FAILED\",\n message: `Failed to parse tsconfig.json: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Validate structure\n if (typeof parsed !== \"object\" || parsed === null) {\n return err({\n code: \"TSCONFIG_INVALID\",\n message: \"tsconfig.json must be an object\",\n });\n }\n\n const config = parsed as Record<string, unknown>;\n const compilerOptions = config.compilerOptions as Record<string, unknown> | undefined;\n\n // Return null if no paths defined\n if (!compilerOptions?.paths) {\n return ok(null);\n }\n\n // Resolve baseUrl\n const tsconfigDir = dirname(tsconfigPath);\n const baseUrl = typeof compilerOptions.baseUrl === \"string\" ? resolve(tsconfigDir, compilerOptions.baseUrl) : tsconfigDir;\n\n // Resolve paths to absolute paths\n const rawPaths = compilerOptions.paths as Record<string, string[]>;\n const resolvedPaths: Record<string, readonly string[]> = {};\n\n for (const [pattern, targets] of Object.entries(rawPaths)) {\n if (Array.isArray(targets)) {\n resolvedPaths[pattern] = targets.map((target) => resolve(baseUrl, target));\n }\n }\n\n return ok({\n baseUrl,\n paths: resolvedPaths,\n });\n};\n"],"mappings":"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"}
|
|
@@ -304,6 +304,43 @@ const cachedFn = (fn) => {
|
|
|
304
304
|
return ensure;
|
|
305
305
|
};
|
|
306
306
|
|
|
307
|
+
//#endregion
|
|
308
|
+
//#region packages/common/src/utils/swc-span.ts
|
|
309
|
+
/**
|
|
310
|
+
* Create a converter that maps UTF-8 byte offsets to UTF-16 char indices
|
|
311
|
+
* for the given source string.
|
|
312
|
+
*
|
|
313
|
+
* Includes a fast path for ASCII-only sources (zero allocation).
|
|
314
|
+
*/
|
|
315
|
+
const createSwcSpanConverter = (source) => {
|
|
316
|
+
const byteLength = Buffer.byteLength(source, "utf8");
|
|
317
|
+
if (byteLength === source.length) {
|
|
318
|
+
return {
|
|
319
|
+
byteLength,
|
|
320
|
+
byteOffsetToCharIndex: (byteOffset) => byteOffset
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
const byteToChar = new Uint32Array(byteLength + 1);
|
|
324
|
+
let bytePos = 0;
|
|
325
|
+
for (let charIdx = 0; charIdx < source.length; charIdx++) {
|
|
326
|
+
const codePoint = source.codePointAt(charIdx);
|
|
327
|
+
if (codePoint === undefined) break;
|
|
328
|
+
const bytesForCodePoint = codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
|
|
329
|
+
for (let b = 0; b < bytesForCodePoint; b++) {
|
|
330
|
+
byteToChar[bytePos + b] = charIdx;
|
|
331
|
+
}
|
|
332
|
+
bytePos += bytesForCodePoint;
|
|
333
|
+
if (codePoint > 65535) {
|
|
334
|
+
charIdx++;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
byteToChar[byteLength] = source.length;
|
|
338
|
+
return {
|
|
339
|
+
byteLength,
|
|
340
|
+
byteOffsetToCharIndex: (byteOffset) => byteToChar[byteOffset] ?? source.length
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
|
|
307
344
|
//#endregion
|
|
308
345
|
//#region packages/common/src/utils/tsconfig.ts
|
|
309
346
|
/**
|
|
@@ -367,5 +404,5 @@ const readTsconfigPaths = (tsconfigPath) => {
|
|
|
367
404
|
};
|
|
368
405
|
|
|
369
406
|
//#endregion
|
|
370
|
-
export {
|
|
371
|
-
//# sourceMappingURL=utils-
|
|
407
|
+
export { MODULE_EXTENSION_CANDIDATES as a, normalizePath as c, resolveRelativeImportWithReferences as d, createAliasResolver as i, parseJsExtension as l, createSwcSpanConverter as n, isExternalSpecifier as o, cachedFn as r, isRelativeSpecifier as s, readTsconfigPaths as t, resolveRelativeImportWithExistenceCheck as u };
|
|
408
|
+
//# sourceMappingURL=utils-DlhM4qvh.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-DlhM4qvh.mjs","names":["JS_TO_TS_EXTENSION_MAP: Readonly<Record<string, readonly string[]>>","cached: { value: T } | null","content: string","parsed: unknown","resolvedPaths: Record<string, readonly string[]>"],"sources":["../src/utils/path.ts","../src/utils/alias-resolver.ts","../src/utils/cached-fn.ts","../src/utils/swc-span.ts","../src/utils/tsconfig.ts"],"sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { dirname, join, normalize, resolve } from \"node:path\";\n\n/**\n * File extensions to try when resolving module specifiers.\n * Ordered to match TypeScript's module resolution order.\n * @see https://www.typescriptlang.org/docs/handbook/module-resolution.html\n */\nexport const MODULE_EXTENSION_CANDIDATES = [\".ts\", \".tsx\", \".mts\", \".cts\", \".js\", \".mjs\", \".cjs\", \".jsx\"] as const;\n\n/**\n * Mapping from JS extensions to their corresponding TS extensions.\n * Used for ESM-style imports where .js is written but .ts is the actual source.\n */\nconst JS_TO_TS_EXTENSION_MAP: Readonly<Record<string, readonly string[]>> = {\n \".js\": [\".ts\", \".tsx\"],\n \".mjs\": [\".mts\"],\n \".cjs\": [\".cts\"],\n \".jsx\": [\".tsx\"],\n};\n\n/**\n * Result of parsing a JS extension from a specifier.\n */\nexport type JsExtensionInfo = {\n /** The specifier without the JS extension */\n readonly base: string;\n /** The JS extension found (e.g., \".js\", \".mjs\") */\n readonly jsExtension: string;\n /** The corresponding TS extensions to try (e.g., [\".ts\", \".tsx\"] for \".js\") */\n readonly tsExtensions: readonly string[];\n};\n\n/**\n * Parse a JS extension from a specifier for ESM-style import resolution.\n * Returns the base path (without extension), the JS extension, and corresponding TS extensions.\n *\n * @param specifier - The import specifier to parse\n * @returns Object with base, jsExtension, and tsExtensions, or null if no JS extension found\n *\n * @example\n * parseJsExtension(\"./foo.js\") // { base: \"./foo\", jsExtension: \".js\", tsExtensions: [\".ts\", \".tsx\"] }\n * parseJsExtension(\"./foo.mjs\") // { base: \"./foo\", jsExtension: \".mjs\", tsExtensions: [\".mts\"] }\n * parseJsExtension(\"./foo\") // null\n * parseJsExtension(\"./foo.ts\") // null\n */\nexport const parseJsExtension = (specifier: string): JsExtensionInfo | null => {\n for (const [ext, tsExts] of Object.entries(JS_TO_TS_EXTENSION_MAP)) {\n if (specifier.endsWith(ext)) {\n return {\n base: specifier.slice(0, -ext.length),\n jsExtension: ext,\n tsExtensions: tsExts,\n };\n }\n }\n return null;\n};\n\n/**\n * Normalize path to use forward slashes (cross-platform).\n * Ensures consistent path handling across platforms.\n */\nexport const normalizePath = (value: string): string => normalize(value).replace(/\\\\/g, \"/\");\n\n/**\n * Resolve a relative import specifier to an absolute file path.\n * Tries the specifier as-is, with extensions, and as a directory with index files.\n *\n * @param from - Absolute path to the importing file\n * @param specifier - Relative module specifier (must start with '.')\n * @returns Absolute POSIX path to the resolved file, or null if not found\n */\nexport const resolveRelativeImportWithExistenceCheck = ({\n filePath,\n specifier,\n}: {\n filePath: string;\n specifier: string;\n}): string | null => {\n // Handle ESM-style imports with JS extensions (e.g., \"./foo.js\" -> \"./foo.ts\")\n const jsExtInfo = parseJsExtension(specifier);\n if (jsExtInfo) {\n const baseWithoutExt = resolve(dirname(filePath), jsExtInfo.base);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Fall back to actual JS file if it exists\n const jsCandidate = `${baseWithoutExt}${jsExtInfo.jsExtension}`;\n if (existsSync(jsCandidate)) {\n try {\n const stat = statSync(jsCandidate);\n if (stat.isFile()) {\n return normalizePath(jsCandidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n }\n\n const base = resolve(dirname(filePath), specifier);\n\n // Try with extensions first (most common case)\n // This handles cases like \"./constants\" resolving to \"./constants.ts\"\n // even when a \"./constants\" directory exists\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${base}${ext}`;\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(base, `index${ext}`);\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try exact path last (only if it's a file, not directory)\n if (existsSync(base)) {\n try {\n const stat = statSync(base);\n if (stat.isFile()) {\n return normalizePath(base);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n};\n\n/**\n * Resolve a relative import specifier to an absolute file path.\n * Tries the specifier as-is, with extensions, and as a directory with index files.\n *\n * @param from - Absolute path to the importing file\n * @param specifier - Relative module specifier (must start with '.')\n * @returns Absolute POSIX path to the resolved file, or null if not found\n */\nexport const resolveRelativeImportWithReferences = <_>({\n filePath,\n specifier,\n references,\n}: {\n filePath: string;\n specifier: string;\n references: Map<string, _> | Set<string>;\n}): string | null => {\n // Handle ESM-style imports with JS extensions (e.g., \"./foo.js\" -> \"./foo.ts\")\n const jsExtInfo = parseJsExtension(specifier);\n if (jsExtInfo) {\n const baseWithoutExt = resolve(dirname(filePath), jsExtInfo.base);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Fall back to actual JS file if it exists in references\n const jsCandidate = `${baseWithoutExt}${jsExtInfo.jsExtension}`;\n if (references.has(jsCandidate)) {\n return normalizePath(jsCandidate);\n }\n\n return null;\n }\n\n const base = resolve(dirname(filePath), specifier);\n\n // Try exact path first\n if (references.has(base)) {\n return normalizePath(base);\n }\n\n // Try with extensions\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${base}${ext}`;\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(base, `index${ext}`);\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n return null;\n};\n\n/**\n * Check if a module specifier is relative (starts with '.' or '..')\n */\nexport const isRelativeSpecifier = (specifier: string): boolean => specifier.startsWith(\"./\") || specifier.startsWith(\"../\");\n\n/**\n * Check if a module specifier is external (package name, not relative)\n */\nexport const isExternalSpecifier = (specifier: string): boolean => !isRelativeSpecifier(specifier);\n","import { existsSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { MODULE_EXTENSION_CANDIDATES, normalizePath, parseJsExtension } from \"./path\";\nimport type { TsconfigPathsConfig } from \"./tsconfig\";\n\n/**\n * Alias resolver interface for resolving path aliases to file paths.\n */\nexport type AliasResolver = {\n /**\n * Resolve an alias specifier to an absolute file path.\n * Returns null if the specifier doesn't match any alias pattern\n * or if the resolved file doesn't exist.\n */\n readonly resolve: (specifier: string) => string | null;\n};\n\n/**\n * Match a specifier against a tsconfig path pattern.\n * Returns the captured wildcard portion or null if no match.\n *\n * Pattern rules:\n * - Exact match: \"@/utils\" matches \"@/utils\" exactly, captures \"\"\n * - Wildcard: \"@/*\" matches \"@/foo\", captures \"foo\"\n * - Wildcard with suffix: \"*.js\" matches \"foo.js\", captures \"foo\"\n */\nconst matchPattern = (specifier: string, pattern: string): string | null => {\n const starIndex = pattern.indexOf(\"*\");\n\n if (starIndex === -1) {\n // Exact match - no wildcard\n return specifier === pattern ? \"\" : null;\n }\n\n const prefix = pattern.slice(0, starIndex);\n const suffix = pattern.slice(starIndex + 1);\n\n if (!specifier.startsWith(prefix)) {\n return null;\n }\n\n if (suffix && !specifier.endsWith(suffix)) {\n return null;\n }\n\n // Extract the wildcard capture\n const captured = specifier.slice(prefix.length, suffix ? specifier.length - suffix.length : undefined);\n\n return captured;\n};\n\n/**\n * Apply a captured wildcard to a target path.\n */\nconst applyCapture = (target: string, captured: string): string => {\n const starIndex = target.indexOf(\"*\");\n if (starIndex === -1) {\n return target;\n }\n return target.slice(0, starIndex) + captured + target.slice(starIndex + 1);\n};\n\n/**\n * Try to resolve a path to an actual file, applying extension resolution.\n * Handles ESM-style imports with JS extensions.\n */\nconst resolveToFile = (basePath: string): string | null => {\n // Handle ESM-style JS extension imports\n const jsExtInfo = parseJsExtension(basePath);\n if (jsExtInfo) {\n const baseWithoutExt = basePath.slice(0, -jsExtInfo.jsExtension.length);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n // Fall back to actual JS file\n if (existsSync(basePath)) {\n try {\n const stat = statSync(basePath);\n if (stat.isFile()) {\n return normalizePath(basePath);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n }\n\n // Try exact path first (for paths with explicit extension)\n if (existsSync(basePath)) {\n try {\n const stat = statSync(basePath);\n if (stat.isFile()) {\n return normalizePath(basePath);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n // Try with extensions\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${basePath}${ext}`;\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(basePath, `index${ext}`);\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n return null;\n};\n\n/**\n * Create an alias resolver from tsconfig paths configuration.\n *\n * Resolution behavior:\n * 1. Try each pattern in order (first match wins per TS spec)\n * 2. For each matched pattern, try all target paths in order\n * 3. For each target, apply extension resolution\n * 4. Return first found file, or null if none found\n */\nexport const createAliasResolver = (config: TsconfigPathsConfig): AliasResolver => {\n const { paths } = config;\n const patterns = Object.keys(paths);\n\n return {\n resolve: (specifier: string): string | null => {\n // Try each pattern in order (first match wins per TS spec)\n for (const pattern of patterns) {\n const captured = matchPattern(specifier, pattern);\n if (captured === null) {\n continue;\n }\n\n const targets = paths[pattern];\n if (!targets) {\n continue;\n }\n\n // Try each target path in order\n for (const target of targets) {\n const resolvedTarget = applyCapture(target, captured);\n const result = resolveToFile(resolvedTarget);\n if (result) {\n return result;\n }\n }\n }\n\n return null;\n },\n };\n};\n","export const cachedFn = <T>(fn: () => T) => {\n let cached: { value: T } | null = null;\n\n const ensure = () => (cached ??= { value: fn() }).value;\n ensure.clear = () => {\n cached = null;\n };\n\n return ensure;\n};\n","/**\n * SWC span position converter: UTF-8 byte offsets → UTF-16 code unit indices.\n *\n * SWC (Rust-based) returns span positions as UTF-8 byte offsets.\n * JavaScript strings use UTF-16 code units for indexing.\n * For ASCII-only content these are identical, but for multi-byte\n * characters the positions diverge.\n */\n\nexport type SwcSpanConverter = {\n /** UTF-8 byte length of the source string */\n readonly byteLength: number;\n /** Convert a UTF-8 byte offset (within the source) to a UTF-16 code unit index */\n readonly byteOffsetToCharIndex: (byteOffset: number) => number;\n};\n\n/**\n * Create a converter that maps UTF-8 byte offsets to UTF-16 char indices\n * for the given source string.\n *\n * Includes a fast path for ASCII-only sources (zero allocation).\n */\nexport const createSwcSpanConverter = (source: string): SwcSpanConverter => {\n const byteLength = Buffer.byteLength(source, \"utf8\");\n\n // Fast path: ASCII-only — byte offsets equal char indices\n if (byteLength === source.length) {\n return {\n byteLength,\n byteOffsetToCharIndex: (byteOffset: number) => byteOffset,\n };\n }\n\n // Build lookup table: byteOffset → charIndex\n const byteToChar = new Uint32Array(byteLength + 1);\n let bytePos = 0;\n\n for (let charIdx = 0; charIdx < source.length; charIdx++) {\n const codePoint = source.codePointAt(charIdx);\n if (codePoint === undefined) break;\n const bytesForCodePoint = codePoint <= 0x7f ? 1 : codePoint <= 0x7ff ? 2 : codePoint <= 0xffff ? 3 : 4;\n\n for (let b = 0; b < bytesForCodePoint; b++) {\n byteToChar[bytePos + b] = charIdx;\n }\n bytePos += bytesForCodePoint;\n\n // Astral code points use a surrogate pair (2 UTF-16 code units)\n if (codePoint > 0xffff) {\n charIdx++;\n }\n }\n\n // Sentinel: end-of-string\n byteToChar[byteLength] = source.length;\n\n return {\n byteLength,\n byteOffsetToCharIndex: (byteOffset: number) => byteToChar[byteOffset] ?? source.length,\n };\n};\n","import { readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { err, ok, type Result } from \"neverthrow\";\n\n/**\n * Parsed tsconfig.json paths configuration.\n * All paths are resolved to absolute paths.\n */\nexport type TsconfigPathsConfig = {\n /** Absolute base URL for path resolution */\n readonly baseUrl: string;\n /** Path mappings with absolute paths */\n readonly paths: Readonly<Record<string, readonly string[]>>;\n};\n\n/**\n * Error types for tsconfig reading.\n */\nexport type TsconfigReadError = {\n readonly code: \"TSCONFIG_READ_FAILED\" | \"TSCONFIG_PARSE_FAILED\" | \"TSCONFIG_INVALID\";\n readonly message: string;\n};\n\n/**\n * Strip JSON comments and trailing commas for parsing.\n * Handles both line comments (//) and block comments.\n */\nconst stripJsonComments = (json: string): string => {\n return (\n json\n // Remove block comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n // Remove line comments\n .replace(/\\/\\/.*/g, \"\")\n // Remove trailing commas before } or ]\n .replace(/,(\\s*[}\\]])/g, \"$1\")\n );\n};\n\n/**\n * Read and parse tsconfig.json to extract paths configuration.\n * Currently does not support `extends` - reads only the specified file.\n *\n * @param tsconfigPath - Absolute path to tsconfig.json\n * @returns Parsed paths configuration or null if no paths defined\n */\nexport const readTsconfigPaths = (tsconfigPath: string): Result<TsconfigPathsConfig | null, TsconfigReadError> => {\n // Read file\n let content: string;\n try {\n content = readFileSync(tsconfigPath, \"utf-8\");\n } catch (error) {\n return err({\n code: \"TSCONFIG_READ_FAILED\",\n message: `Failed to read tsconfig.json: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Parse JSON (with comment stripping)\n let parsed: unknown;\n try {\n const cleaned = stripJsonComments(content);\n parsed = JSON.parse(cleaned);\n } catch (error) {\n return err({\n code: \"TSCONFIG_PARSE_FAILED\",\n message: `Failed to parse tsconfig.json: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Validate structure\n if (typeof parsed !== \"object\" || parsed === null) {\n return err({\n code: \"TSCONFIG_INVALID\",\n message: \"tsconfig.json must be an object\",\n });\n }\n\n const config = parsed as Record<string, unknown>;\n const compilerOptions = config.compilerOptions as Record<string, unknown> | undefined;\n\n // Return null if no paths defined\n if (!compilerOptions?.paths) {\n return ok(null);\n }\n\n // Resolve baseUrl\n const tsconfigDir = dirname(tsconfigPath);\n const baseUrl = typeof compilerOptions.baseUrl === \"string\" ? resolve(tsconfigDir, compilerOptions.baseUrl) : tsconfigDir;\n\n // Resolve paths to absolute paths\n const rawPaths = compilerOptions.paths as Record<string, string[]>;\n const resolvedPaths: Record<string, readonly string[]> = {};\n\n for (const [pattern, targets] of Object.entries(rawPaths)) {\n if (Array.isArray(targets)) {\n resolvedPaths[pattern] = targets.map((target) => resolve(baseUrl, target));\n }\n }\n\n return ok({\n baseUrl,\n paths: resolvedPaths,\n });\n};\n"],"mappings":";;;;;;;;;;AAQA,MAAa,8BAA8B;CAAC;CAAO;CAAQ;CAAQ;CAAQ;CAAO;CAAQ;CAAQ;CAAO;;;;;AAMzG,MAAMA,yBAAsE;CAC1E,OAAO,CAAC,OAAO,OAAO;CACtB,QAAQ,CAAC,OAAO;CAChB,QAAQ,CAAC,OAAO;CAChB,QAAQ,CAAC,OAAO;CACjB;;;;;;;;;;;;;;AA2BD,MAAa,oBAAoB,cAA8C;AAC7E,MAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,uBAAuB,EAAE;AAClE,MAAI,UAAU,SAAS,IAAI,EAAE;AAC3B,UAAO;IACL,MAAM,UAAU,MAAM,GAAG,CAAC,IAAI,OAAO;IACrC,aAAa;IACb,cAAc;IACf;;;AAGL,QAAO;;;;;;AAOT,MAAa,iBAAiB,UAA0B,UAAU,MAAM,CAAC,QAAQ,OAAO,IAAI;;;;;;;;;AAU5F,MAAa,2CAA2C,EACtD,UACA,gBAImB;CAEnB,MAAM,YAAY,iBAAiB,UAAU;AAC7C,KAAI,WAAW;EACb,MAAM,iBAAiB,QAAQ,QAAQ,SAAS,EAAE,UAAU,KAAK;AAGjE,OAAK,MAAM,OAAO,UAAU,cAAc;GACxC,MAAM,YAAY,GAAG,iBAAiB;AACtC,OAAI,WAAW,UAAU,EAAE;AACzB,WAAO,cAAc,UAAU;;;EAKnC,MAAM,cAAc,GAAG,iBAAiB,UAAU;AAClD,MAAI,WAAW,YAAY,EAAE;AAC3B,OAAI;IACF,MAAM,OAAO,SAAS,YAAY;AAClC,QAAI,KAAK,QAAQ,EAAE;AACjB,YAAO,cAAc,YAAY;;WAE7B;;AAKV,SAAO;;CAGT,MAAM,OAAO,QAAQ,QAAQ,SAAS,EAAE,UAAU;AAKlD,MAAK,MAAM,OAAO,6BAA6B;EAC7C,MAAM,YAAY,GAAG,OAAO;AAC5B,MAAI,WAAW,UAAU,EAAE;AACzB,UAAO,cAAc,UAAU;;;AAKnC,MAAK,MAAM,OAAO,6BAA6B;EAC7C,MAAM,YAAY,KAAK,MAAM,QAAQ,MAAM;AAC3C,MAAI,WAAW,UAAU,EAAE;AACzB,UAAO,cAAc,UAAU;;;AAKnC,KAAI,WAAW,KAAK,EAAE;AACpB,MAAI;GACF,MAAM,OAAO,SAAS,KAAK;AAC3B,OAAI,KAAK,QAAQ,EAAE;AACjB,WAAO,cAAc,KAAK;;UAEtB;;AAKV,QAAO;;;;;;;;;;AAWT,MAAa,uCAA0C,EACrD,UACA,WACA,iBAKmB;CAEnB,MAAM,YAAY,iBAAiB,UAAU;AAC7C,KAAI,WAAW;EACb,MAAM,iBAAiB,QAAQ,QAAQ,SAAS,EAAE,UAAU,KAAK;AAGjE,OAAK,MAAM,OAAO,UAAU,cAAc;GACxC,MAAM,YAAY,GAAG,iBAAiB;AACtC,OAAI,WAAW,IAAI,UAAU,EAAE;AAC7B,WAAO,cAAc,UAAU;;;EAKnC,MAAM,cAAc,GAAG,iBAAiB,UAAU;AAClD,MAAI,WAAW,IAAI,YAAY,EAAE;AAC/B,UAAO,cAAc,YAAY;;AAGnC,SAAO;;CAGT,MAAM,OAAO,QAAQ,QAAQ,SAAS,EAAE,UAAU;AAGlD,KAAI,WAAW,IAAI,KAAK,EAAE;AACxB,SAAO,cAAc,KAAK;;AAI5B,MAAK,MAAM,OAAO,6BAA6B;EAC7C,MAAM,YAAY,GAAG,OAAO;AAC5B,MAAI,WAAW,IAAI,UAAU,EAAE;AAC7B,UAAO,cAAc,UAAU;;;AAKnC,MAAK,MAAM,OAAO,6BAA6B;EAC7C,MAAM,YAAY,KAAK,MAAM,QAAQ,MAAM;AAC3C,MAAI,WAAW,IAAI,UAAU,EAAE;AAC7B,UAAO,cAAc,UAAU;;;AAInC,QAAO;;;;;AAMT,MAAa,uBAAuB,cAA+B,UAAU,WAAW,KAAK,IAAI,UAAU,WAAW,MAAM;;;;AAK5H,MAAa,uBAAuB,cAA+B,CAAC,oBAAoB,UAAU;;;;;;;;;;;;;AC/LlG,MAAM,gBAAgB,WAAmB,YAAmC;CAC1E,MAAM,YAAY,QAAQ,QAAQ,IAAI;AAEtC,KAAI,cAAc,CAAC,GAAG;AAEpB,SAAO,cAAc,UAAU,KAAK;;CAGtC,MAAM,SAAS,QAAQ,MAAM,GAAG,UAAU;CAC1C,MAAM,SAAS,QAAQ,MAAM,YAAY,EAAE;AAE3C,KAAI,CAAC,UAAU,WAAW,OAAO,EAAE;AACjC,SAAO;;AAGT,KAAI,UAAU,CAAC,UAAU,SAAS,OAAO,EAAE;AACzC,SAAO;;CAIT,MAAM,WAAW,UAAU,MAAM,OAAO,QAAQ,SAAS,UAAU,SAAS,OAAO,SAAS,UAAU;AAEtG,QAAO;;;;;AAMT,MAAM,gBAAgB,QAAgB,aAA6B;CACjE,MAAM,YAAY,OAAO,QAAQ,IAAI;AACrC,KAAI,cAAc,CAAC,GAAG;AACpB,SAAO;;AAET,QAAO,OAAO,MAAM,GAAG,UAAU,GAAG,WAAW,OAAO,MAAM,YAAY,EAAE;;;;;;AAO5E,MAAM,iBAAiB,aAAoC;CAEzD,MAAM,YAAY,iBAAiB,SAAS;AAC5C,KAAI,WAAW;EACb,MAAM,iBAAiB,SAAS,MAAM,GAAG,CAAC,UAAU,YAAY,OAAO;AAGvE,OAAK,MAAM,OAAO,UAAU,cAAc;GACxC,MAAM,YAAY,GAAG,iBAAiB;AACtC,OAAI,WAAW,UAAU,EAAE;AACzB,QAAI;KACF,MAAM,OAAO,SAAS,UAAU;AAChC,SAAI,KAAK,QAAQ,EAAE;AACjB,aAAO,cAAc,UAAU;;YAE3B;;;AAOZ,MAAI,WAAW,SAAS,EAAE;AACxB,OAAI;IACF,MAAM,OAAO,SAAS,SAAS;AAC/B,QAAI,KAAK,QAAQ,EAAE;AACjB,YAAO,cAAc,SAAS;;WAE1B;;AAKV,SAAO;;AAIT,KAAI,WAAW,SAAS,EAAE;AACxB,MAAI;GACF,MAAM,OAAO,SAAS,SAAS;AAC/B,OAAI,KAAK,QAAQ,EAAE;AACjB,WAAO,cAAc,SAAS;;UAE1B;;AAMV,MAAK,MAAM,OAAO,6BAA6B;EAC7C,MAAM,YAAY,GAAG,WAAW;AAChC,MAAI,WAAW,UAAU,EAAE;AACzB,OAAI;IACF,MAAM,OAAO,SAAS,UAAU;AAChC,QAAI,KAAK,QAAQ,EAAE;AACjB,YAAO,cAAc,UAAU;;WAE3B;;;AAOZ,MAAK,MAAM,OAAO,6BAA6B;EAC7C,MAAM,YAAY,KAAK,UAAU,QAAQ,MAAM;AAC/C,MAAI,WAAW,UAAU,EAAE;AACzB,OAAI;IACF,MAAM,OAAO,SAAS,UAAU;AAChC,QAAI,KAAK,QAAQ,EAAE;AACjB,YAAO,cAAc,UAAU;;WAE3B;;;AAMZ,QAAO;;;;;;;;;;;AAYT,MAAa,uBAAuB,WAA+C;CACjF,MAAM,EAAE,UAAU;CAClB,MAAM,WAAW,OAAO,KAAK,MAAM;AAEnC,QAAO,EACL,UAAU,cAAqC;AAE7C,OAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,WAAW,aAAa,WAAW,QAAQ;AACjD,OAAI,aAAa,MAAM;AACrB;;GAGF,MAAM,UAAU,MAAM;AACtB,OAAI,CAAC,SAAS;AACZ;;AAIF,QAAK,MAAM,UAAU,SAAS;IAC5B,MAAM,iBAAiB,aAAa,QAAQ,SAAS;IACrD,MAAM,SAAS,cAAc,eAAe;AAC5C,QAAI,QAAQ;AACV,YAAO;;;;AAKb,SAAO;IAEV;;;;;AC1LH,MAAa,YAAe,OAAgB;CAC1C,IAAIC,SAA8B;CAElC,MAAM,gBAAgB,WAAW,EAAE,OAAO,IAAI,EAAE,EAAE;AAClD,QAAO,cAAc;AACnB,WAAS;;AAGX,QAAO;;;;;;;;;;;ACcT,MAAa,0BAA0B,WAAqC;CAC1E,MAAM,aAAa,OAAO,WAAW,QAAQ,OAAO;AAGpD,KAAI,eAAe,OAAO,QAAQ;AAChC,SAAO;GACL;GACA,wBAAwB,eAAuB;GAChD;;CAIH,MAAM,aAAa,IAAI,YAAY,aAAa,EAAE;CAClD,IAAI,UAAU;AAEd,MAAK,IAAI,UAAU,GAAG,UAAU,OAAO,QAAQ,WAAW;EACxD,MAAM,YAAY,OAAO,YAAY,QAAQ;AAC7C,MAAI,cAAc,UAAW;EAC7B,MAAM,oBAAoB,aAAa,MAAO,IAAI,aAAa,OAAQ,IAAI,aAAa,QAAS,IAAI;AAErG,OAAK,IAAI,IAAI,GAAG,IAAI,mBAAmB,KAAK;AAC1C,cAAW,UAAU,KAAK;;AAE5B,aAAW;AAGX,MAAI,YAAY,OAAQ;AACtB;;;AAKJ,YAAW,cAAc,OAAO;AAEhC,QAAO;EACL;EACA,wBAAwB,eAAuB,WAAW,eAAe,OAAO;EACjF;;;;;;;;;AChCH,MAAM,qBAAqB,SAAyB;AAClD,QACE,KAEG,QAAQ,qBAAqB,GAAG,CAEhC,QAAQ,WAAW,GAAG,CAEtB,QAAQ,gBAAgB,KAAK;;;;;;;;;AAWpC,MAAa,qBAAqB,iBAAgF;CAEhH,IAAIC;AACJ,KAAI;AACF,YAAU,aAAa,cAAc,QAAQ;UACtC,OAAO;AACd,SAAO,IAAI;GACT,MAAM;GACN,SAAS,iCAAiC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GACjG,CAAC;;CAIJ,IAAIC;AACJ,KAAI;EACF,MAAM,UAAU,kBAAkB,QAAQ;AAC1C,WAAS,KAAK,MAAM,QAAQ;UACrB,OAAO;AACd,SAAO,IAAI;GACT,MAAM;GACN,SAAS,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAClG,CAAC;;AAIJ,KAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,SAAO,IAAI;GACT,MAAM;GACN,SAAS;GACV,CAAC;;CAGJ,MAAM,SAAS;CACf,MAAM,kBAAkB,OAAO;AAG/B,KAAI,CAAC,iBAAiB,OAAO;AAC3B,SAAO,GAAG,KAAK;;CAIjB,MAAM,cAAc,QAAQ,aAAa;CACzC,MAAM,UAAU,OAAO,gBAAgB,YAAY,WAAW,QAAQ,aAAa,gBAAgB,QAAQ,GAAG;CAG9G,MAAM,WAAW,gBAAgB;CACjC,MAAMC,gBAAmD,EAAE;AAE3D,MAAK,MAAM,CAAC,SAAS,YAAY,OAAO,QAAQ,SAAS,EAAE;AACzD,MAAI,MAAM,QAAQ,QAAQ,EAAE;AAC1B,iBAAc,WAAW,QAAQ,KAAK,WAAW,QAAQ,SAAS,OAAO,CAAC;;;AAI9E,QAAO,GAAG;EACR;EACA,OAAO;EACR,CAAC"}
|
package/dist/utils.cjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
const require_utils = require('./utils-
|
|
1
|
+
const require_utils = require('./utils-C2CEQL5v.cjs');
|
|
2
2
|
|
|
3
3
|
exports.MODULE_EXTENSION_CANDIDATES = require_utils.MODULE_EXTENSION_CANDIDATES;
|
|
4
4
|
exports.cachedFn = require_utils.cachedFn;
|
|
5
5
|
exports.createAliasResolver = require_utils.createAliasResolver;
|
|
6
|
+
exports.createSwcSpanConverter = require_utils.createSwcSpanConverter;
|
|
6
7
|
exports.isExternalSpecifier = require_utils.isExternalSpecifier;
|
|
7
8
|
exports.isRelativeSpecifier = require_utils.isRelativeSpecifier;
|
|
8
9
|
exports.normalizePath = require_utils.normalizePath;
|
package/dist/utils.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { AliasResolver, JsExtensionInfo, MODULE_EXTENSION_CANDIDATES, TsconfigPathsConfig, TsconfigReadError, cachedFn, createAliasResolver, isExternalSpecifier, isRelativeSpecifier, normalizePath, parseJsExtension, readTsconfigPaths, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences };
|
|
1
|
+
import { a as isExternalSpecifier, c as parseJsExtension, d as cachedFn, f as AliasResolver, g as readTsconfigPaths, h as TsconfigReadError, i as MODULE_EXTENSION_CANDIDATES, l as resolveRelativeImportWithExistenceCheck, m as TsconfigPathsConfig, n as createSwcSpanConverter, o as isRelativeSpecifier, p as createAliasResolver, r as JsExtensionInfo, s as normalizePath, t as SwcSpanConverter, u as resolveRelativeImportWithReferences } from "./index-BDPAGTeS.cjs";
|
|
2
|
+
export { AliasResolver, JsExtensionInfo, MODULE_EXTENSION_CANDIDATES, SwcSpanConverter, TsconfigPathsConfig, TsconfigReadError, cachedFn, createAliasResolver, createSwcSpanConverter, isExternalSpecifier, isRelativeSpecifier, normalizePath, parseJsExtension, readTsconfigPaths, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences };
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { AliasResolver, JsExtensionInfo, MODULE_EXTENSION_CANDIDATES, TsconfigPathsConfig, TsconfigReadError, cachedFn, createAliasResolver, isExternalSpecifier, isRelativeSpecifier, normalizePath, parseJsExtension, readTsconfigPaths, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences };
|
|
1
|
+
import { a as isExternalSpecifier, c as parseJsExtension, d as cachedFn, f as AliasResolver, g as readTsconfigPaths, h as TsconfigReadError, i as MODULE_EXTENSION_CANDIDATES, l as resolveRelativeImportWithExistenceCheck, m as TsconfigPathsConfig, n as createSwcSpanConverter, o as isRelativeSpecifier, p as createAliasResolver, r as JsExtensionInfo, s as normalizePath, t as SwcSpanConverter, u as resolveRelativeImportWithReferences } from "./index-B1w5x8e3.mjs";
|
|
2
|
+
export { AliasResolver, JsExtensionInfo, MODULE_EXTENSION_CANDIDATES, SwcSpanConverter, TsconfigPathsConfig, TsconfigReadError, cachedFn, createAliasResolver, createSwcSpanConverter, isExternalSpecifier, isRelativeSpecifier, normalizePath, parseJsExtension, readTsconfigPaths, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences };
|
package/dist/utils.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as MODULE_EXTENSION_CANDIDATES, c as normalizePath, d as resolveRelativeImportWithReferences, i as createAliasResolver, l as parseJsExtension, n as createSwcSpanConverter, o as isExternalSpecifier, r as cachedFn, s as isRelativeSpecifier, t as readTsconfigPaths, u as resolveRelativeImportWithExistenceCheck } from "./utils-DlhM4qvh.mjs";
|
|
2
2
|
|
|
3
|
-
export { MODULE_EXTENSION_CANDIDATES, cachedFn, createAliasResolver, isExternalSpecifier, isRelativeSpecifier, normalizePath, parseJsExtension, readTsconfigPaths, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences };
|
|
3
|
+
export { MODULE_EXTENSION_CANDIDATES, cachedFn, createAliasResolver, createSwcSpanConverter, isExternalSpecifier, isRelativeSpecifier, normalizePath, parseJsExtension, readTsconfigPaths, resolveRelativeImportWithExistenceCheck, resolveRelativeImportWithReferences };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_canonical_id = require('./canonical-id-
|
|
1
|
+
const require_canonical_id = require('./canonical-id-CcqNJHU4.cjs');
|
|
2
2
|
let zod = require("zod");
|
|
3
3
|
|
|
4
4
|
//#region packages/common/src/zod/schema-helper.ts
|
|
@@ -13,4 +13,4 @@ Object.defineProperty(exports, 'defineSchemaFor', {
|
|
|
13
13
|
return defineSchemaFor;
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
|
-
//# sourceMappingURL=zod-
|
|
16
|
+
//# sourceMappingURL=zod-DQuWqRtm.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zod-
|
|
1
|
+
{"version":3,"file":"zod-DQuWqRtm.cjs","names":["z"],"sources":["../src/zod/schema-helper.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// biome-ignore lint/suspicious/noExplicitAny: abstract type\nexport type SchemaFor<TOutput> = z.ZodType<TOutput, any, any>;\n\nexport type ShapeFor<TOutput extends object> = { [K in keyof TOutput]-?: SchemaFor<TOutput[K]> };\n\nexport function defineSchemaFor<TOutput extends object>() {\n return <TShape extends ShapeFor<NoInfer<TOutput>>>(shape: TShape & { [K in Exclude<keyof TShape, keyof TOutput>]: never }) =>\n z.object(shape).strict();\n}\n"],"mappings":";;;;AAOA,SAAgB,kBAA0C;AACxD,SAAmD,UACjDA,MAAE,OAAO,MAAM,CAAC,QAAQ"}
|
package/dist/zod.cjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soda-gql/common",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Shared utilities for soda-gql packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -46,16 +46,6 @@
|
|
|
46
46
|
"module": "./dist/index.mjs",
|
|
47
47
|
"types": "./dist/index.d.mts",
|
|
48
48
|
"exports": {
|
|
49
|
-
"./test": {
|
|
50
|
-
"@soda-gql": "./@devx-test.ts"
|
|
51
|
-
},
|
|
52
|
-
"./zod": {
|
|
53
|
-
"@soda-gql": "./@x-zod.ts",
|
|
54
|
-
"types": "./dist/zod.d.mts",
|
|
55
|
-
"import": "./dist/zod.mjs",
|
|
56
|
-
"require": "./dist/zod.cjs",
|
|
57
|
-
"default": "./dist/zod.mjs"
|
|
58
|
-
},
|
|
59
49
|
".": {
|
|
60
50
|
"@soda-gql": "./@x-index.ts",
|
|
61
51
|
"types": "./dist/index.d.mts",
|
|
@@ -84,9 +74,20 @@
|
|
|
84
74
|
"require": "./dist/portable.cjs",
|
|
85
75
|
"default": "./dist/portable.mjs"
|
|
86
76
|
},
|
|
77
|
+
"./test": {
|
|
78
|
+
"@soda-gql": "./@devx-test.ts"
|
|
79
|
+
},
|
|
80
|
+
"./zod": {
|
|
81
|
+
"@soda-gql": "./@x-zod.ts",
|
|
82
|
+
"types": "./dist/zod.d.mts",
|
|
83
|
+
"import": "./dist/zod.mjs",
|
|
84
|
+
"require": "./dist/zod.cjs",
|
|
85
|
+
"default": "./dist/zod.mjs"
|
|
86
|
+
},
|
|
87
87
|
"./package.json": "./package.json"
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
|
+
"neverthrow": "^8.1.1",
|
|
90
91
|
"zod": "^4.1.11"
|
|
91
92
|
},
|
|
92
93
|
"devDependencies": {},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BCu9PNbZ.d.mts","names":[],"sources":["../src/utils/tsconfig.ts","../src/utils/alias-resolver.ts","../src/utils/cached-fn.ts","../src/utils/path.ts"],"sourcesContent":[],"mappings":";;;;;;AAQA;AAUA;AA4Ba,KAtCD,mBAAA,GAgGX;EA1D+D;EAA4B,SAAA,OAAA,EAAA,MAAA;EAAnC;EAAM,SAAA,KAAA,EAlC7C,QAkC6C,CAlCpC,MAkCoC,CAAA,MAAA,EAAA,SAAA,MAAA,EAAA,CAAA,CAAA;;;;ACtC/D;AAoJa,KD1ID,iBAAA,GCyKX;;;;AC3LD;;;;ACQA;AAgBA;AAsBA;AAiBa,cHjBA,iBGiB+E,EAAA,CAAA,YAAA,EAAA,MAAA,EAAA,GHjBnC,MGiBmC,CHjB5B,mBGiB4B,GAAA,IAAA,EHjBA,iBGiBA,CAAA;;;;;AHvD5F;AAUY,KCVA,aAAA,GDUiB;EA4BhB;;;;;;;;ACtCb;AAoJA;;;;AC5JA;;;cD4Ja,8BAA+B,wBAAsB;;;cC5JrD,wBAAyB;MAAA;;AFQtC,CAAA;;;;;;AAAA;AAUA;AA4Ba,cGtCA,2BHgGZ,EAAA,SAAA,CAAA,KAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA;;;;AA1D8D,KGtBnD,eAAA,GHsBmD;;;;ECtCnD,SAAA,WAAa,EAAA,MAAA;EAoJZ;;;;AC5Jb;;;;ACQA;AAgBA;AAsBA;AAiBA;AAUA;AA+EA;;;AAAuD,cA1G1C,gBA0G0C,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,GA1GF,eA0GE,GAAA,IAAA;;;;;AA4D1C,cArJA,aAqJ+G,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,MAAA;AAK5H;;;;;;;;cAhJa;;;;;;;;;;;;;;;cA+EA;;;;;;;cAOC,YAAY,KAAK;;;;;cAqDlB;;;;cAKA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BMl8pzFY.d.cts","names":[],"sources":["../src/utils/tsconfig.ts","../src/utils/alias-resolver.ts","../src/utils/cached-fn.ts","../src/utils/path.ts"],"sourcesContent":[],"mappings":";;;;;;AAQA;AAUA;AA4Ba,KAtCD,mBAAA,GAgGX;EA1D+D;EAA4B,SAAA,OAAA,EAAA,MAAA;EAAnC;EAAM,SAAA,KAAA,EAlC7C,QAkC6C,CAlCpC,MAkCoC,CAAA,MAAA,EAAA,SAAA,MAAA,EAAA,CAAA,CAAA;;;;ACtC/D;AAoJa,KD1ID,iBAAA,GCyKX;;;;AC3LD;;;;ACQA;AAgBA;AAsBA;AAiBa,cHjBA,iBGiB+E,EAAA,CAAA,YAAA,EAAA,MAAA,EAAA,GHjBnC,MGiBmC,CHjB5B,mBGiB4B,GAAA,IAAA,EHjBA,iBGiBA,CAAA;;;;;AHvD5F;AAUY,KCVA,aAAA,GDUiB;EA4BhB;;;;;;;;ACtCb;AAoJA;;;;AC5JA;;;cD4Ja,8BAA+B,wBAAsB;;;cC5JrD,wBAAyB;MAAA;;AFQtC,CAAA;;;;;;AAAA;AAUA;AA4Ba,cGtCA,2BHgGZ,EAAA,SAAA,CAAA,KAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA;;;;AA1D8D,KGtBnD,eAAA,GHsBmD;;;;ECtCnD,SAAA,WAAa,EAAA,MAAA;EAoJZ;;;;AC5Jb;;;;ACQA;AAgBA;AAsBA;AAiBA;AAUA;AA+EA;;;AAAuD,cA1G1C,gBA0G0C,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,GA1GF,eA0GE,GAAA,IAAA;;;;;AA4D1C,cArJA,aAqJ+G,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,MAAA;AAK5H;;;;;;;;cAhJa;;;;;;;;;;;;;;;cA+EA;;;;;;;cAOC,YAAY,KAAK;;;;;cAqDlB;;;;cAKA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils-Rs7YbafF.cjs","names":["JS_TO_TS_EXTENSION_MAP: Readonly<Record<string, readonly string[]>>","cached: { value: T } | null","content: string","parsed: unknown","resolvedPaths: Record<string, readonly string[]>"],"sources":["../src/utils/path.ts","../src/utils/alias-resolver.ts","../src/utils/cached-fn.ts","../src/utils/tsconfig.ts"],"sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { dirname, join, normalize, resolve } from \"node:path\";\n\n/**\n * File extensions to try when resolving module specifiers.\n * Ordered to match TypeScript's module resolution order.\n * @see https://www.typescriptlang.org/docs/handbook/module-resolution.html\n */\nexport const MODULE_EXTENSION_CANDIDATES = [\".ts\", \".tsx\", \".mts\", \".cts\", \".js\", \".mjs\", \".cjs\", \".jsx\"] as const;\n\n/**\n * Mapping from JS extensions to their corresponding TS extensions.\n * Used for ESM-style imports where .js is written but .ts is the actual source.\n */\nconst JS_TO_TS_EXTENSION_MAP: Readonly<Record<string, readonly string[]>> = {\n \".js\": [\".ts\", \".tsx\"],\n \".mjs\": [\".mts\"],\n \".cjs\": [\".cts\"],\n \".jsx\": [\".tsx\"],\n};\n\n/**\n * Result of parsing a JS extension from a specifier.\n */\nexport type JsExtensionInfo = {\n /** The specifier without the JS extension */\n readonly base: string;\n /** The JS extension found (e.g., \".js\", \".mjs\") */\n readonly jsExtension: string;\n /** The corresponding TS extensions to try (e.g., [\".ts\", \".tsx\"] for \".js\") */\n readonly tsExtensions: readonly string[];\n};\n\n/**\n * Parse a JS extension from a specifier for ESM-style import resolution.\n * Returns the base path (without extension), the JS extension, and corresponding TS extensions.\n *\n * @param specifier - The import specifier to parse\n * @returns Object with base, jsExtension, and tsExtensions, or null if no JS extension found\n *\n * @example\n * parseJsExtension(\"./foo.js\") // { base: \"./foo\", jsExtension: \".js\", tsExtensions: [\".ts\", \".tsx\"] }\n * parseJsExtension(\"./foo.mjs\") // { base: \"./foo\", jsExtension: \".mjs\", tsExtensions: [\".mts\"] }\n * parseJsExtension(\"./foo\") // null\n * parseJsExtension(\"./foo.ts\") // null\n */\nexport const parseJsExtension = (specifier: string): JsExtensionInfo | null => {\n for (const [ext, tsExts] of Object.entries(JS_TO_TS_EXTENSION_MAP)) {\n if (specifier.endsWith(ext)) {\n return {\n base: specifier.slice(0, -ext.length),\n jsExtension: ext,\n tsExtensions: tsExts,\n };\n }\n }\n return null;\n};\n\n/**\n * Normalize path to use forward slashes (cross-platform).\n * Ensures consistent path handling across platforms.\n */\nexport const normalizePath = (value: string): string => normalize(value).replace(/\\\\/g, \"/\");\n\n/**\n * Resolve a relative import specifier to an absolute file path.\n * Tries the specifier as-is, with extensions, and as a directory with index files.\n *\n * @param from - Absolute path to the importing file\n * @param specifier - Relative module specifier (must start with '.')\n * @returns Absolute POSIX path to the resolved file, or null if not found\n */\nexport const resolveRelativeImportWithExistenceCheck = ({\n filePath,\n specifier,\n}: {\n filePath: string;\n specifier: string;\n}): string | null => {\n // Handle ESM-style imports with JS extensions (e.g., \"./foo.js\" -> \"./foo.ts\")\n const jsExtInfo = parseJsExtension(specifier);\n if (jsExtInfo) {\n const baseWithoutExt = resolve(dirname(filePath), jsExtInfo.base);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Fall back to actual JS file if it exists\n const jsCandidate = `${baseWithoutExt}${jsExtInfo.jsExtension}`;\n if (existsSync(jsCandidate)) {\n try {\n const stat = statSync(jsCandidate);\n if (stat.isFile()) {\n return normalizePath(jsCandidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n }\n\n const base = resolve(dirname(filePath), specifier);\n\n // Try with extensions first (most common case)\n // This handles cases like \"./constants\" resolving to \"./constants.ts\"\n // even when a \"./constants\" directory exists\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${base}${ext}`;\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(base, `index${ext}`);\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try exact path last (only if it's a file, not directory)\n if (existsSync(base)) {\n try {\n const stat = statSync(base);\n if (stat.isFile()) {\n return normalizePath(base);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n};\n\n/**\n * Resolve a relative import specifier to an absolute file path.\n * Tries the specifier as-is, with extensions, and as a directory with index files.\n *\n * @param from - Absolute path to the importing file\n * @param specifier - Relative module specifier (must start with '.')\n * @returns Absolute POSIX path to the resolved file, or null if not found\n */\nexport const resolveRelativeImportWithReferences = <_>({\n filePath,\n specifier,\n references,\n}: {\n filePath: string;\n specifier: string;\n references: Map<string, _> | Set<string>;\n}): string | null => {\n // Handle ESM-style imports with JS extensions (e.g., \"./foo.js\" -> \"./foo.ts\")\n const jsExtInfo = parseJsExtension(specifier);\n if (jsExtInfo) {\n const baseWithoutExt = resolve(dirname(filePath), jsExtInfo.base);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Fall back to actual JS file if it exists in references\n const jsCandidate = `${baseWithoutExt}${jsExtInfo.jsExtension}`;\n if (references.has(jsCandidate)) {\n return normalizePath(jsCandidate);\n }\n\n return null;\n }\n\n const base = resolve(dirname(filePath), specifier);\n\n // Try exact path first\n if (references.has(base)) {\n return normalizePath(base);\n }\n\n // Try with extensions\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${base}${ext}`;\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(base, `index${ext}`);\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n return null;\n};\n\n/**\n * Check if a module specifier is relative (starts with '.' or '..')\n */\nexport const isRelativeSpecifier = (specifier: string): boolean => specifier.startsWith(\"./\") || specifier.startsWith(\"../\");\n\n/**\n * Check if a module specifier is external (package name, not relative)\n */\nexport const isExternalSpecifier = (specifier: string): boolean => !isRelativeSpecifier(specifier);\n","import { existsSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { MODULE_EXTENSION_CANDIDATES, normalizePath, parseJsExtension } from \"./path\";\nimport type { TsconfigPathsConfig } from \"./tsconfig\";\n\n/**\n * Alias resolver interface for resolving path aliases to file paths.\n */\nexport type AliasResolver = {\n /**\n * Resolve an alias specifier to an absolute file path.\n * Returns null if the specifier doesn't match any alias pattern\n * or if the resolved file doesn't exist.\n */\n readonly resolve: (specifier: string) => string | null;\n};\n\n/**\n * Match a specifier against a tsconfig path pattern.\n * Returns the captured wildcard portion or null if no match.\n *\n * Pattern rules:\n * - Exact match: \"@/utils\" matches \"@/utils\" exactly, captures \"\"\n * - Wildcard: \"@/*\" matches \"@/foo\", captures \"foo\"\n * - Wildcard with suffix: \"*.js\" matches \"foo.js\", captures \"foo\"\n */\nconst matchPattern = (specifier: string, pattern: string): string | null => {\n const starIndex = pattern.indexOf(\"*\");\n\n if (starIndex === -1) {\n // Exact match - no wildcard\n return specifier === pattern ? \"\" : null;\n }\n\n const prefix = pattern.slice(0, starIndex);\n const suffix = pattern.slice(starIndex + 1);\n\n if (!specifier.startsWith(prefix)) {\n return null;\n }\n\n if (suffix && !specifier.endsWith(suffix)) {\n return null;\n }\n\n // Extract the wildcard capture\n const captured = specifier.slice(prefix.length, suffix ? specifier.length - suffix.length : undefined);\n\n return captured;\n};\n\n/**\n * Apply a captured wildcard to a target path.\n */\nconst applyCapture = (target: string, captured: string): string => {\n const starIndex = target.indexOf(\"*\");\n if (starIndex === -1) {\n return target;\n }\n return target.slice(0, starIndex) + captured + target.slice(starIndex + 1);\n};\n\n/**\n * Try to resolve a path to an actual file, applying extension resolution.\n * Handles ESM-style imports with JS extensions.\n */\nconst resolveToFile = (basePath: string): string | null => {\n // Handle ESM-style JS extension imports\n const jsExtInfo = parseJsExtension(basePath);\n if (jsExtInfo) {\n const baseWithoutExt = basePath.slice(0, -jsExtInfo.jsExtension.length);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n // Fall back to actual JS file\n if (existsSync(basePath)) {\n try {\n const stat = statSync(basePath);\n if (stat.isFile()) {\n return normalizePath(basePath);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n }\n\n // Try exact path first (for paths with explicit extension)\n if (existsSync(basePath)) {\n try {\n const stat = statSync(basePath);\n if (stat.isFile()) {\n return normalizePath(basePath);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n // Try with extensions\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${basePath}${ext}`;\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(basePath, `index${ext}`);\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n return null;\n};\n\n/**\n * Create an alias resolver from tsconfig paths configuration.\n *\n * Resolution behavior:\n * 1. Try each pattern in order (first match wins per TS spec)\n * 2. For each matched pattern, try all target paths in order\n * 3. For each target, apply extension resolution\n * 4. Return first found file, or null if none found\n */\nexport const createAliasResolver = (config: TsconfigPathsConfig): AliasResolver => {\n const { paths } = config;\n const patterns = Object.keys(paths);\n\n return {\n resolve: (specifier: string): string | null => {\n // Try each pattern in order (first match wins per TS spec)\n for (const pattern of patterns) {\n const captured = matchPattern(specifier, pattern);\n if (captured === null) {\n continue;\n }\n\n const targets = paths[pattern];\n if (!targets) {\n continue;\n }\n\n // Try each target path in order\n for (const target of targets) {\n const resolvedTarget = applyCapture(target, captured);\n const result = resolveToFile(resolvedTarget);\n if (result) {\n return result;\n }\n }\n }\n\n return null;\n },\n };\n};\n","export const cachedFn = <T>(fn: () => T) => {\n let cached: { value: T } | null = null;\n\n const ensure = () => (cached ??= { value: fn() }).value;\n ensure.clear = () => {\n cached = null;\n };\n\n return ensure;\n};\n","import { readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { err, ok, type Result } from \"neverthrow\";\n\n/**\n * Parsed tsconfig.json paths configuration.\n * All paths are resolved to absolute paths.\n */\nexport type TsconfigPathsConfig = {\n /** Absolute base URL for path resolution */\n readonly baseUrl: string;\n /** Path mappings with absolute paths */\n readonly paths: Readonly<Record<string, readonly string[]>>;\n};\n\n/**\n * Error types for tsconfig reading.\n */\nexport type TsconfigReadError = {\n readonly code: \"TSCONFIG_READ_FAILED\" | \"TSCONFIG_PARSE_FAILED\" | \"TSCONFIG_INVALID\";\n readonly message: string;\n};\n\n/**\n * Strip JSON comments and trailing commas for parsing.\n * Handles both line comments (//) and block comments.\n */\nconst stripJsonComments = (json: string): string => {\n return (\n json\n // Remove block comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n // Remove line comments\n .replace(/\\/\\/.*/g, \"\")\n // Remove trailing commas before } or ]\n .replace(/,(\\s*[}\\]])/g, \"$1\")\n );\n};\n\n/**\n * Read and parse tsconfig.json to extract paths configuration.\n * Currently does not support `extends` - reads only the specified file.\n *\n * @param tsconfigPath - Absolute path to tsconfig.json\n * @returns Parsed paths configuration or null if no paths defined\n */\nexport const readTsconfigPaths = (tsconfigPath: string): Result<TsconfigPathsConfig | null, TsconfigReadError> => {\n // Read file\n let content: string;\n try {\n content = readFileSync(tsconfigPath, \"utf-8\");\n } catch (error) {\n return err({\n code: \"TSCONFIG_READ_FAILED\",\n message: `Failed to read tsconfig.json: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Parse JSON (with comment stripping)\n let parsed: unknown;\n try {\n const cleaned = stripJsonComments(content);\n parsed = JSON.parse(cleaned);\n } catch (error) {\n return err({\n code: \"TSCONFIG_PARSE_FAILED\",\n message: `Failed to parse tsconfig.json: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Validate structure\n if (typeof parsed !== \"object\" || parsed === null) {\n return err({\n code: \"TSCONFIG_INVALID\",\n message: \"tsconfig.json must be an object\",\n });\n }\n\n const config = parsed as Record<string, unknown>;\n const compilerOptions = config.compilerOptions as Record<string, unknown> | undefined;\n\n // Return null if no paths defined\n if (!compilerOptions?.paths) {\n return ok(null);\n }\n\n // Resolve baseUrl\n const tsconfigDir = dirname(tsconfigPath);\n const baseUrl = typeof compilerOptions.baseUrl === \"string\" ? resolve(tsconfigDir, compilerOptions.baseUrl) : tsconfigDir;\n\n // Resolve paths to absolute paths\n const rawPaths = compilerOptions.paths as Record<string, string[]>;\n const resolvedPaths: Record<string, readonly string[]> = {};\n\n for (const [pattern, targets] of Object.entries(rawPaths)) {\n if (Array.isArray(targets)) {\n resolvedPaths[pattern] = targets.map((target) => resolve(baseUrl, target));\n }\n }\n\n return ok({\n baseUrl,\n paths: resolvedPaths,\n });\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils-ZCE_eqCf.mjs","names":["JS_TO_TS_EXTENSION_MAP: Readonly<Record<string, readonly string[]>>","cached: { value: T } | null","content: string","parsed: unknown","resolvedPaths: Record<string, readonly string[]>"],"sources":["../src/utils/path.ts","../src/utils/alias-resolver.ts","../src/utils/cached-fn.ts","../src/utils/tsconfig.ts"],"sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { dirname, join, normalize, resolve } from \"node:path\";\n\n/**\n * File extensions to try when resolving module specifiers.\n * Ordered to match TypeScript's module resolution order.\n * @see https://www.typescriptlang.org/docs/handbook/module-resolution.html\n */\nexport const MODULE_EXTENSION_CANDIDATES = [\".ts\", \".tsx\", \".mts\", \".cts\", \".js\", \".mjs\", \".cjs\", \".jsx\"] as const;\n\n/**\n * Mapping from JS extensions to their corresponding TS extensions.\n * Used for ESM-style imports where .js is written but .ts is the actual source.\n */\nconst JS_TO_TS_EXTENSION_MAP: Readonly<Record<string, readonly string[]>> = {\n \".js\": [\".ts\", \".tsx\"],\n \".mjs\": [\".mts\"],\n \".cjs\": [\".cts\"],\n \".jsx\": [\".tsx\"],\n};\n\n/**\n * Result of parsing a JS extension from a specifier.\n */\nexport type JsExtensionInfo = {\n /** The specifier without the JS extension */\n readonly base: string;\n /** The JS extension found (e.g., \".js\", \".mjs\") */\n readonly jsExtension: string;\n /** The corresponding TS extensions to try (e.g., [\".ts\", \".tsx\"] for \".js\") */\n readonly tsExtensions: readonly string[];\n};\n\n/**\n * Parse a JS extension from a specifier for ESM-style import resolution.\n * Returns the base path (without extension), the JS extension, and corresponding TS extensions.\n *\n * @param specifier - The import specifier to parse\n * @returns Object with base, jsExtension, and tsExtensions, or null if no JS extension found\n *\n * @example\n * parseJsExtension(\"./foo.js\") // { base: \"./foo\", jsExtension: \".js\", tsExtensions: [\".ts\", \".tsx\"] }\n * parseJsExtension(\"./foo.mjs\") // { base: \"./foo\", jsExtension: \".mjs\", tsExtensions: [\".mts\"] }\n * parseJsExtension(\"./foo\") // null\n * parseJsExtension(\"./foo.ts\") // null\n */\nexport const parseJsExtension = (specifier: string): JsExtensionInfo | null => {\n for (const [ext, tsExts] of Object.entries(JS_TO_TS_EXTENSION_MAP)) {\n if (specifier.endsWith(ext)) {\n return {\n base: specifier.slice(0, -ext.length),\n jsExtension: ext,\n tsExtensions: tsExts,\n };\n }\n }\n return null;\n};\n\n/**\n * Normalize path to use forward slashes (cross-platform).\n * Ensures consistent path handling across platforms.\n */\nexport const normalizePath = (value: string): string => normalize(value).replace(/\\\\/g, \"/\");\n\n/**\n * Resolve a relative import specifier to an absolute file path.\n * Tries the specifier as-is, with extensions, and as a directory with index files.\n *\n * @param from - Absolute path to the importing file\n * @param specifier - Relative module specifier (must start with '.')\n * @returns Absolute POSIX path to the resolved file, or null if not found\n */\nexport const resolveRelativeImportWithExistenceCheck = ({\n filePath,\n specifier,\n}: {\n filePath: string;\n specifier: string;\n}): string | null => {\n // Handle ESM-style imports with JS extensions (e.g., \"./foo.js\" -> \"./foo.ts\")\n const jsExtInfo = parseJsExtension(specifier);\n if (jsExtInfo) {\n const baseWithoutExt = resolve(dirname(filePath), jsExtInfo.base);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Fall back to actual JS file if it exists\n const jsCandidate = `${baseWithoutExt}${jsExtInfo.jsExtension}`;\n if (existsSync(jsCandidate)) {\n try {\n const stat = statSync(jsCandidate);\n if (stat.isFile()) {\n return normalizePath(jsCandidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n }\n\n const base = resolve(dirname(filePath), specifier);\n\n // Try with extensions first (most common case)\n // This handles cases like \"./constants\" resolving to \"./constants.ts\"\n // even when a \"./constants\" directory exists\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${base}${ext}`;\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(base, `index${ext}`);\n if (existsSync(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try exact path last (only if it's a file, not directory)\n if (existsSync(base)) {\n try {\n const stat = statSync(base);\n if (stat.isFile()) {\n return normalizePath(base);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n};\n\n/**\n * Resolve a relative import specifier to an absolute file path.\n * Tries the specifier as-is, with extensions, and as a directory with index files.\n *\n * @param from - Absolute path to the importing file\n * @param specifier - Relative module specifier (must start with '.')\n * @returns Absolute POSIX path to the resolved file, or null if not found\n */\nexport const resolveRelativeImportWithReferences = <_>({\n filePath,\n specifier,\n references,\n}: {\n filePath: string;\n specifier: string;\n references: Map<string, _> | Set<string>;\n}): string | null => {\n // Handle ESM-style imports with JS extensions (e.g., \"./foo.js\" -> \"./foo.ts\")\n const jsExtInfo = parseJsExtension(specifier);\n if (jsExtInfo) {\n const baseWithoutExt = resolve(dirname(filePath), jsExtInfo.base);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Fall back to actual JS file if it exists in references\n const jsCandidate = `${baseWithoutExt}${jsExtInfo.jsExtension}`;\n if (references.has(jsCandidate)) {\n return normalizePath(jsCandidate);\n }\n\n return null;\n }\n\n const base = resolve(dirname(filePath), specifier);\n\n // Try exact path first\n if (references.has(base)) {\n return normalizePath(base);\n }\n\n // Try with extensions\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${base}${ext}`;\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(base, `index${ext}`);\n if (references.has(candidate)) {\n return normalizePath(candidate);\n }\n }\n\n return null;\n};\n\n/**\n * Check if a module specifier is relative (starts with '.' or '..')\n */\nexport const isRelativeSpecifier = (specifier: string): boolean => specifier.startsWith(\"./\") || specifier.startsWith(\"../\");\n\n/**\n * Check if a module specifier is external (package name, not relative)\n */\nexport const isExternalSpecifier = (specifier: string): boolean => !isRelativeSpecifier(specifier);\n","import { existsSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { MODULE_EXTENSION_CANDIDATES, normalizePath, parseJsExtension } from \"./path\";\nimport type { TsconfigPathsConfig } from \"./tsconfig\";\n\n/**\n * Alias resolver interface for resolving path aliases to file paths.\n */\nexport type AliasResolver = {\n /**\n * Resolve an alias specifier to an absolute file path.\n * Returns null if the specifier doesn't match any alias pattern\n * or if the resolved file doesn't exist.\n */\n readonly resolve: (specifier: string) => string | null;\n};\n\n/**\n * Match a specifier against a tsconfig path pattern.\n * Returns the captured wildcard portion or null if no match.\n *\n * Pattern rules:\n * - Exact match: \"@/utils\" matches \"@/utils\" exactly, captures \"\"\n * - Wildcard: \"@/*\" matches \"@/foo\", captures \"foo\"\n * - Wildcard with suffix: \"*.js\" matches \"foo.js\", captures \"foo\"\n */\nconst matchPattern = (specifier: string, pattern: string): string | null => {\n const starIndex = pattern.indexOf(\"*\");\n\n if (starIndex === -1) {\n // Exact match - no wildcard\n return specifier === pattern ? \"\" : null;\n }\n\n const prefix = pattern.slice(0, starIndex);\n const suffix = pattern.slice(starIndex + 1);\n\n if (!specifier.startsWith(prefix)) {\n return null;\n }\n\n if (suffix && !specifier.endsWith(suffix)) {\n return null;\n }\n\n // Extract the wildcard capture\n const captured = specifier.slice(prefix.length, suffix ? specifier.length - suffix.length : undefined);\n\n return captured;\n};\n\n/**\n * Apply a captured wildcard to a target path.\n */\nconst applyCapture = (target: string, captured: string): string => {\n const starIndex = target.indexOf(\"*\");\n if (starIndex === -1) {\n return target;\n }\n return target.slice(0, starIndex) + captured + target.slice(starIndex + 1);\n};\n\n/**\n * Try to resolve a path to an actual file, applying extension resolution.\n * Handles ESM-style imports with JS extensions.\n */\nconst resolveToFile = (basePath: string): string | null => {\n // Handle ESM-style JS extension imports\n const jsExtInfo = parseJsExtension(basePath);\n if (jsExtInfo) {\n const baseWithoutExt = basePath.slice(0, -jsExtInfo.jsExtension.length);\n\n // Try corresponding TS extensions first\n for (const ext of jsExtInfo.tsExtensions) {\n const candidate = `${baseWithoutExt}${ext}`;\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n // Fall back to actual JS file\n if (existsSync(basePath)) {\n try {\n const stat = statSync(basePath);\n if (stat.isFile()) {\n return normalizePath(basePath);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n return null;\n }\n\n // Try exact path first (for paths with explicit extension)\n if (existsSync(basePath)) {\n try {\n const stat = statSync(basePath);\n if (stat.isFile()) {\n return normalizePath(basePath);\n }\n } catch {\n // Ignore stat errors\n }\n }\n\n // Try with extensions\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = `${basePath}${ext}`;\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n // Try as directory with index files\n for (const ext of MODULE_EXTENSION_CANDIDATES) {\n const candidate = join(basePath, `index${ext}`);\n if (existsSync(candidate)) {\n try {\n const stat = statSync(candidate);\n if (stat.isFile()) {\n return normalizePath(candidate);\n }\n } catch {\n // Ignore stat errors\n }\n }\n }\n\n return null;\n};\n\n/**\n * Create an alias resolver from tsconfig paths configuration.\n *\n * Resolution behavior:\n * 1. Try each pattern in order (first match wins per TS spec)\n * 2. For each matched pattern, try all target paths in order\n * 3. For each target, apply extension resolution\n * 4. Return first found file, or null if none found\n */\nexport const createAliasResolver = (config: TsconfigPathsConfig): AliasResolver => {\n const { paths } = config;\n const patterns = Object.keys(paths);\n\n return {\n resolve: (specifier: string): string | null => {\n // Try each pattern in order (first match wins per TS spec)\n for (const pattern of patterns) {\n const captured = matchPattern(specifier, pattern);\n if (captured === null) {\n continue;\n }\n\n const targets = paths[pattern];\n if (!targets) {\n continue;\n }\n\n // Try each target path in order\n for (const target of targets) {\n const resolvedTarget = applyCapture(target, captured);\n const result = resolveToFile(resolvedTarget);\n if (result) {\n return result;\n }\n }\n }\n\n return null;\n },\n };\n};\n","export const cachedFn = <T>(fn: () => T) => {\n let cached: { value: T } | null = null;\n\n const ensure = () => (cached ??= { value: fn() }).value;\n ensure.clear = () => {\n cached = null;\n };\n\n return ensure;\n};\n","import { readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { err, ok, type Result } from \"neverthrow\";\n\n/**\n * Parsed tsconfig.json paths configuration.\n * All paths are resolved to absolute paths.\n */\nexport type TsconfigPathsConfig = {\n /** Absolute base URL for path resolution */\n readonly baseUrl: string;\n /** Path mappings with absolute paths */\n readonly paths: Readonly<Record<string, readonly string[]>>;\n};\n\n/**\n * Error types for tsconfig reading.\n */\nexport type TsconfigReadError = {\n readonly code: \"TSCONFIG_READ_FAILED\" | \"TSCONFIG_PARSE_FAILED\" | \"TSCONFIG_INVALID\";\n readonly message: string;\n};\n\n/**\n * Strip JSON comments and trailing commas for parsing.\n * Handles both line comments (//) and block comments.\n */\nconst stripJsonComments = (json: string): string => {\n return (\n json\n // Remove block comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n // Remove line comments\n .replace(/\\/\\/.*/g, \"\")\n // Remove trailing commas before } or ]\n .replace(/,(\\s*[}\\]])/g, \"$1\")\n );\n};\n\n/**\n * Read and parse tsconfig.json to extract paths configuration.\n * Currently does not support `extends` - reads only the specified file.\n *\n * @param tsconfigPath - Absolute path to tsconfig.json\n * @returns Parsed paths configuration or null if no paths defined\n */\nexport const readTsconfigPaths = (tsconfigPath: string): Result<TsconfigPathsConfig | null, TsconfigReadError> => {\n // Read file\n let content: string;\n try {\n content = readFileSync(tsconfigPath, \"utf-8\");\n } catch (error) {\n return err({\n code: \"TSCONFIG_READ_FAILED\",\n message: `Failed to read tsconfig.json: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Parse JSON (with comment stripping)\n let parsed: unknown;\n try {\n const cleaned = stripJsonComments(content);\n parsed = JSON.parse(cleaned);\n } catch (error) {\n return err({\n code: \"TSCONFIG_PARSE_FAILED\",\n message: `Failed to parse tsconfig.json: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Validate structure\n if (typeof parsed !== \"object\" || parsed === null) {\n return err({\n code: \"TSCONFIG_INVALID\",\n message: \"tsconfig.json must be an object\",\n });\n }\n\n const config = parsed as Record<string, unknown>;\n const compilerOptions = config.compilerOptions as Record<string, unknown> | undefined;\n\n // Return null if no paths defined\n if (!compilerOptions?.paths) {\n return ok(null);\n }\n\n // Resolve baseUrl\n const tsconfigDir = dirname(tsconfigPath);\n const baseUrl = typeof compilerOptions.baseUrl === \"string\" ? resolve(tsconfigDir, compilerOptions.baseUrl) : tsconfigDir;\n\n // Resolve paths to absolute paths\n const rawPaths = compilerOptions.paths as Record<string, string[]>;\n const resolvedPaths: Record<string, readonly string[]> = {};\n\n for (const [pattern, targets] of Object.entries(rawPaths)) {\n if (Array.isArray(targets)) {\n resolvedPaths[pattern] = targets.map((target) => resolve(baseUrl, target));\n }\n }\n\n return ok({\n baseUrl,\n paths: resolvedPaths,\n });\n};\n"],"mappings":"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"}
|