@yoinkingfish/parser 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CodeCarto Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Analyzers — higher-level enrichment (framework detection, category inference).
3
+ * Stubbed in Phase 1; architects the extension point for future heuristics.
4
+ */
5
+ export type AnalyzerResult = Record<string, unknown>;
6
+ export interface Analyzer {
7
+ name: string;
8
+ analyze(_ctx: unknown): Promise<AnalyzerResult>;
9
+ }
10
+ export declare const analyzers: Analyzer[];
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzers/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAErD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,eAAO,MAAM,SAAS,EAAE,QAAQ,EAAO,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Analyzers — higher-level enrichment (framework detection, category inference).
3
+ * Stubbed in Phase 1; architects the extension point for future heuristics.
4
+ */
5
+ export const analyzers = [];
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzers/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,CAAC,MAAM,SAAS,GAAe,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @codecarto/parser — public surface.
3
+ * Phase 1: placeholder exports so the monorepo builds and types resolve.
4
+ * Full scanner / AST / resolver implementations land in Phase 2–3.
5
+ */
6
+ export * from "./scanners/index.js";
7
+ export * from "./parsers/index.js";
8
+ export * from "./resolvers/index.js";
9
+ export * from "./analyzers/index.js";
10
+ export type { CodeNode, CodeLink, CodeGraph } from "@yoinkingfish/shared";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AAGrC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @codecarto/parser — public surface.
3
+ * Phase 1: placeholder exports so the monorepo builds and types resolve.
4
+ * Full scanner / AST / resolver implementations land in Phase 2–3.
5
+ */
6
+ export * from "./scanners/index.js";
7
+ export * from "./parsers/index.js";
8
+ export * from "./resolvers/index.js";
9
+ export * from "./analyzers/index.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Parsers — LanguageParser abstraction and registry.
3
+ */
4
+ export interface ParseContext {
5
+ filePath: string;
6
+ relativePath: string;
7
+ root: string;
8
+ tsConfigPaths?: Record<string, string[]>;
9
+ }
10
+ export interface RawDependency {
11
+ specifier: string;
12
+ type: "import" | "require" | "dynamic-import" | "unknown";
13
+ line?: number;
14
+ }
15
+ export interface ParseResult {
16
+ filePath: string;
17
+ relativePath?: string;
18
+ language: string;
19
+ dependencies: RawDependency[];
20
+ parseError?: string;
21
+ }
22
+ export interface LanguageParser {
23
+ readonly supportedExtensions: string[];
24
+ parseFile(source: string, context: ParseContext): Promise<ParseResult>;
25
+ }
26
+ export declare const parserRegistry: LanguageParser[];
27
+ export declare function getParserForExtension(ext: string): LanguageParser | undefined;
28
+ export declare function getParserForFile(filePath: string): LanguageParser | undefined;
29
+ export { TypeScriptParser } from "./typescript-parser.js";
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAAC;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IACvC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACxE;AAID,eAAO,MAAM,cAAc,EAAE,cAAc,EAAe,CAAC;AAE3D,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAG7E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAG7E;AAGD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Parsers — LanguageParser abstraction and registry.
3
+ */
4
+ import { TypeScriptParser } from "./typescript-parser.js";
5
+ // Registry — add new language parsers here
6
+ const tsParser = new TypeScriptParser();
7
+ export const parserRegistry = [tsParser];
8
+ export function getParserForExtension(ext) {
9
+ const lower = ext.toLowerCase().replace(/^\./, "");
10
+ return parserRegistry.find((p) => p.supportedExtensions.includes(lower));
11
+ }
12
+ export function getParserForFile(filePath) {
13
+ const ext = filePath.split(".").pop() ?? "";
14
+ return getParserForExtension(ext);
15
+ }
16
+ // Re-export concrete parsers
17
+ export { TypeScriptParser } from "./typescript-parser.js";
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AA4B1D,6CAA6C;AAC7C,MAAM,QAAQ,GAAG,IAAI,gBAAgB,EAAE,CAAC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAqB,CAAC,QAAQ,CAAC,CAAC;AAE3D,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnD,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IAC5C,OAAO,qBAAqB,CAAC,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,6BAA6B;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * TypeScript / JavaScript parser - AST-based via ts-morph.
3
+ * Handles: import, export, require, dynamic import.
4
+ * Gracefully degrades on malformed files.
5
+ */
6
+ import type { LanguageParser, ParseContext, ParseResult } from "./index.js";
7
+ export declare class TypeScriptParser implements LanguageParser {
8
+ readonly supportedExtensions: string[];
9
+ parseFile(source: string, context: ParseContext): Promise<ParseResult>;
10
+ }
11
+ //# sourceMappingURL=typescript-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/typescript-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC;AAmB3F,qBAAa,gBAAiB,YAAW,cAAc;IACrD,QAAQ,CAAC,mBAAmB,WAA0D;IAEhF,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;CAqG7E"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * TypeScript / JavaScript parser - AST-based via ts-morph.
3
+ * Handles: import, export, require, dynamic import.
4
+ * Gracefully degrades on malformed files.
5
+ */
6
+ import { Project, SyntaxKind } from "ts-morph";
7
+ // Reusable in-memory project - no filesystem reads, no tsconfig auto-load
8
+ function createProject() {
9
+ return new Project({
10
+ useInMemoryFileSystem: true,
11
+ skipAddingFilesFromTsConfig: true,
12
+ skipFileDependencyResolution: true,
13
+ compilerOptions: {
14
+ allowJs: true,
15
+ jsx: 2, // React JSX
16
+ esModuleInterop: true,
17
+ target: 99, // Latest
18
+ module: 99,
19
+ strict: false,
20
+ },
21
+ });
22
+ }
23
+ export class TypeScriptParser {
24
+ supportedExtensions = ["ts", "tsx", "js", "jsx", "mjs", "cjs", "mts", "cts"];
25
+ async parseFile(source, context) {
26
+ const { filePath } = context;
27
+ const dependencies = [];
28
+ const language = detectLanguage(filePath);
29
+ try {
30
+ const project = createProject();
31
+ const sourceFile = project.createSourceFile(filePath, source, { overwrite: true });
32
+ // Static imports: `import x from "./foo"` and `import "./side-effect"`
33
+ for (const imp of sourceFile.getImportDeclarations()) {
34
+ const spec = imp.getModuleSpecifierValue();
35
+ if (!spec)
36
+ continue;
37
+ const isTypeOnly = imp.isTypeOnly();
38
+ dependencies.push({
39
+ specifier: spec,
40
+ type: isTypeOnly ? "import" : "import",
41
+ line: imp.getStartLineNumber(),
42
+ });
43
+ }
44
+ // Re-exports: `export * from "./foo"` or `export {x} from "./y"`
45
+ for (const exp of sourceFile.getExportDeclarations()) {
46
+ const spec = exp.getModuleSpecifierValue();
47
+ if (!spec)
48
+ continue;
49
+ dependencies.push({
50
+ specifier: spec,
51
+ type: "import",
52
+ line: exp.getStartLineNumber(),
53
+ });
54
+ }
55
+ // Call expressions: require("...") and import("...")
56
+ const calls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);
57
+ for (const call of calls) {
58
+ const expr = call.getExpression();
59
+ const exprText = expr.getText();
60
+ const args = call.getArguments();
61
+ // require("specifier")
62
+ if (exprText === "require" && args.length === 1) {
63
+ const arg = args[0];
64
+ const spec = extractStringLiteral(arg.getText());
65
+ if (spec !== null) {
66
+ dependencies.push({
67
+ specifier: spec,
68
+ type: "require",
69
+ line: call.getStartLineNumber(),
70
+ });
71
+ }
72
+ else {
73
+ // Non-literal require - uncertain
74
+ dependencies.push({
75
+ specifier: args[0].getText().slice(0, 80),
76
+ type: "unknown",
77
+ line: call.getStartLineNumber(),
78
+ });
79
+ }
80
+ continue;
81
+ }
82
+ // dynamic import("specifier") - CallExpression where expression is ImportKeyword
83
+ if (expr.getKind() === SyntaxKind.ImportKeyword && args.length >= 1) {
84
+ const spec = extractStringLiteral(args[0].getText());
85
+ dependencies.push({
86
+ specifier: spec ?? args[0].getText().slice(0, 80),
87
+ type: spec !== null ? "dynamic-import" : "unknown",
88
+ line: call.getStartLineNumber(),
89
+ });
90
+ continue;
91
+ }
92
+ }
93
+ // Also check for `import = require` (TypeScript)
94
+ const importEquals = sourceFile.getDescendantsOfKind(SyntaxKind.ImportEqualsDeclaration);
95
+ for (const ie of importEquals) {
96
+ const modRef = ie.getModuleReference();
97
+ const text = modRef.getText();
98
+ const match = text.match(/require\s*\(\s*["']([^"']+)["']\s*\)/);
99
+ if (match) {
100
+ dependencies.push({
101
+ specifier: match[1],
102
+ type: "require",
103
+ line: ie.getStartLineNumber(),
104
+ });
105
+ }
106
+ }
107
+ return {
108
+ filePath,
109
+ language,
110
+ dependencies: dedupe(dependencies),
111
+ };
112
+ }
113
+ catch (err) {
114
+ return {
115
+ filePath,
116
+ language,
117
+ dependencies: dedupe(dependencies),
118
+ parseError: err.message.slice(0, 500),
119
+ };
120
+ }
121
+ }
122
+ }
123
+ function detectLanguage(filePath) {
124
+ const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
125
+ if (ext === "ts" || ext === "tsx" || ext === "mts" || ext === "cts")
126
+ return "typescript";
127
+ return "javascript";
128
+ }
129
+ function extractStringLiteral(text) {
130
+ const trimmed = text.trim();
131
+ // Handle "spec", 'spec', `spec` - only return for quoted strings, not template with expressions
132
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
133
+ return trimmed.slice(1, -1);
134
+ }
135
+ if (trimmed.startsWith("`") && trimmed.endsWith("`") && !trimmed.includes("${")) {
136
+ return trimmed.slice(1, -1);
137
+ }
138
+ return null;
139
+ }
140
+ function dedupe(deps) {
141
+ const seen = new Set();
142
+ const out = [];
143
+ for (const d of deps) {
144
+ const key = `${d.type}::${d.specifier}`;
145
+ if (!seen.has(key)) {
146
+ seen.add(key);
147
+ out.push(d);
148
+ }
149
+ }
150
+ return out;
151
+ }
152
+ //# sourceMappingURL=typescript-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-parser.js","sourceRoot":"","sources":["../../src/parsers/typescript-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Resolvers — map raw specifiers like "./utils" to concrete file paths.
3
+ * Handles:
4
+ * - relative: ./utils, ../components/Button
5
+ * - extension omission: ./utils -> ./utils.ts / .tsx / .js / .jsx / index.*
6
+ * - index resolution: ./utils -> ./utils/index.ts
7
+ * - tsconfig `paths` aliases: @/* -> src/*, @components/* -> src/components/*
8
+ * - package.json baseUrl handling (via tsconfig)
9
+ * External packages (react, lodash) are reported as unresolved (external).
10
+ */
11
+ export interface ResolveContext {
12
+ importerPath: string;
13
+ importerRelative: string;
14
+ root: string;
15
+ existingFiles: Set<string>;
16
+ existingAbsFiles?: Set<string>;
17
+ tsConfigPaths?: Record<string, string[]>;
18
+ tsConfigBaseUrl?: string;
19
+ }
20
+ export interface ResolvedDependency {
21
+ rawSpecifier: string;
22
+ resolvedPath: string | null;
23
+ resolvedAbsolute: string | null;
24
+ resolved: boolean;
25
+ external: boolean;
26
+ }
27
+ export declare function resolveImport(specifier: string, ctx: ResolveContext): ResolvedDependency;
28
+ /** Load tsconfig paths lazily — caller can pass pre-parsed */
29
+ export declare function parseTsconfigPaths(tsconfigContent: string, configDir: string): {
30
+ paths?: Record<string, string[]>;
31
+ baseUrl?: string;
32
+ };
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resolvers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACzC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAKD,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,kBAAkB,CA+BxF;AAkID,8DAA8D;AAC9D,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAWrI"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Resolvers — map raw specifiers like "./utils" to concrete file paths.
3
+ * Handles:
4
+ * - relative: ./utils, ../components/Button
5
+ * - extension omission: ./utils -> ./utils.ts / .tsx / .js / .jsx / index.*
6
+ * - index resolution: ./utils -> ./utils/index.ts
7
+ * - tsconfig `paths` aliases: @/* -> src/*, @components/* -> src/components/*
8
+ * - package.json baseUrl handling (via tsconfig)
9
+ * External packages (react, lodash) are reported as unresolved (external).
10
+ */
11
+ import path from "node:path";
12
+ import fs from "node:fs";
13
+ const EXTENSIONS_TRY_ORDER = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"];
14
+ const INDEX_FILES = ["index.ts", "index.tsx", "index.js", "index.jsx", "index.mjs", "index.cjs"];
15
+ export function resolveImport(specifier, ctx) {
16
+ const raw = specifier.trim();
17
+ if (!raw)
18
+ return { rawSpecifier: specifier, resolvedPath: null, resolvedAbsolute: null, resolved: false, external: false };
19
+ // Absolute or URL — treat as external
20
+ if (raw.startsWith("http://") || raw.startsWith("https://") || raw.startsWith("data:")) {
21
+ return { rawSpecifier: specifier, resolvedPath: null, resolvedAbsolute: null, resolved: false, external: true };
22
+ }
23
+ // Try tsconfig paths alias first (longest prefix wins)
24
+ if (ctx.tsConfigPaths) {
25
+ const aliasResolved = tryResolveAlias(raw, ctx);
26
+ if (aliasResolved)
27
+ return aliasResolved;
28
+ }
29
+ // Relative or root-relative?
30
+ if (raw.startsWith(".") || raw.startsWith("/")) {
31
+ return resolveRelative(raw, ctx);
32
+ }
33
+ // Bare specifier — check if it's actually a local file with bare import + baseUrl?
34
+ // For now treat as external (npm package). Future: check baseUrl + paths fallback
35
+ // Example: `import x from "utils"` with baseUrl src -> src/utils
36
+ // We handle this only if baseUrl present and file exists
37
+ if (ctx.tsConfigBaseUrl) {
38
+ const baseResolved = tryResolveBaseUrl(raw, ctx);
39
+ if (baseResolved)
40
+ return baseResolved;
41
+ }
42
+ // External package
43
+ return { rawSpecifier: specifier, resolvedPath: null, resolvedAbsolute: null, resolved: false, external: true };
44
+ }
45
+ function resolveRelative(specifier, ctx) {
46
+ const importerDir = path.dirname(ctx.importerPath);
47
+ const importerDirRel = path.posix.dirname(ctx.importerRelative);
48
+ // Resolve to absolute attempted path
49
+ const attemptedAbs = path.resolve(importerDir, specifier);
50
+ const attemptedRel = path.posix.normalize(path.posix.join(importerDirRel, specifier));
51
+ // 1. Exact match (with extension)
52
+ if (ctx.existingFiles.has(attemptedRel) || (ctx.existingAbsFiles?.has(attemptedAbs) ?? fileExists(attemptedAbs))) {
53
+ // Ensure we return normalized rel with extension if present
54
+ const foundRel = ctx.existingFiles.has(attemptedRel) ? attemptedRel : toRel(attemptedAbs, ctx.root);
55
+ if (foundRel)
56
+ return { rawSpecifier: specifier, resolvedPath: foundRel, resolvedAbsolute: attemptedAbs, resolved: true, external: false };
57
+ }
58
+ // 2. Try appending extensions: ./utils -> ./utils.ts etc.
59
+ for (const ext of EXTENSIONS_TRY_ORDER) {
60
+ const tryRel = attemptedRel + ext;
61
+ const tryAbs = attemptedAbs + ext;
62
+ if (ctx.existingFiles.has(tryRel) || (ctx.existingAbsFiles?.has(tryAbs) ?? fileExists(tryAbs))) {
63
+ return { rawSpecifier: specifier, resolvedPath: tryRel, resolvedAbsolute: tryAbs, resolved: true, external: false };
64
+ }
65
+ }
66
+ // 3. Try index files: ./utils -> ./utils/index.ts
67
+ for (const idx of INDEX_FILES) {
68
+ const tryRel = path.posix.join(attemptedRel, idx);
69
+ const tryAbs = path.join(attemptedAbs, idx);
70
+ if (ctx.existingFiles.has(tryRel) || (ctx.existingAbsFiles?.has(tryAbs) ?? fileExists(tryAbs))) {
71
+ return { rawSpecifier: specifier, resolvedPath: tryRel, resolvedAbsolute: tryAbs, resolved: true, external: false };
72
+ }
73
+ }
74
+ // 4. Not found — unresolved local (missing file)
75
+ return { rawSpecifier: specifier, resolvedPath: null, resolvedAbsolute: null, resolved: false, external: false };
76
+ }
77
+ function tryResolveAlias(specifier, ctx) {
78
+ const paths = ctx.tsConfigPaths;
79
+ // Sort patterns by longest prefix to handle @components/* before @/*
80
+ const patterns = Object.keys(paths).sort((a, b) => b.length - a.length);
81
+ for (const pattern of patterns) {
82
+ const targets = paths[pattern];
83
+ if (!targets || targets.length === 0)
84
+ continue;
85
+ const isWildcard = pattern.includes("*");
86
+ let matched = false;
87
+ let wildcardPart = "";
88
+ if (isWildcard) {
89
+ const [prefix, suffix] = pattern.split("*");
90
+ if (specifier.startsWith(prefix) && specifier.endsWith(suffix)) {
91
+ matched = true;
92
+ wildcardPart = specifier.slice(prefix.length, specifier.length - suffix.length);
93
+ }
94
+ }
95
+ else {
96
+ if (specifier === pattern)
97
+ matched = true;
98
+ }
99
+ if (!matched)
100
+ continue;
101
+ for (const target of targets) {
102
+ const mapped = isWildcard ? target.replace("*", wildcardPart) : target;
103
+ // Target is relative to baseUrl or root; resolve against root
104
+ const base = ctx.tsConfigBaseUrl ?? ctx.root;
105
+ const tryAbs = path.resolve(base, mapped);
106
+ const tryRel = toRel(tryAbs, ctx.root);
107
+ if (!tryRel)
108
+ continue;
109
+ // Try exact, extensions, index similar to relative
110
+ if (ctx.existingFiles.has(tryRel) || fileExists(tryAbs)) {
111
+ return { rawSpecifier: specifier, resolvedPath: tryRel, resolvedAbsolute: tryAbs, resolved: true, external: false };
112
+ }
113
+ for (const ext of EXTENSIONS_TRY_ORDER) {
114
+ if (ctx.existingFiles.has(tryRel + ext) || fileExists(tryAbs + ext)) {
115
+ return { rawSpecifier: specifier, resolvedPath: tryRel + ext, resolvedAbsolute: tryAbs + ext, resolved: true, external: false };
116
+ }
117
+ }
118
+ for (const idx of INDEX_FILES) {
119
+ const idxRel = path.posix.join(tryRel, idx);
120
+ const idxAbs = path.join(tryAbs, idx);
121
+ if (ctx.existingFiles.has(idxRel) || fileExists(idxAbs)) {
122
+ return { rawSpecifier: specifier, resolvedPath: idxRel, resolvedAbsolute: idxAbs, resolved: true, external: false };
123
+ }
124
+ }
125
+ }
126
+ }
127
+ return null;
128
+ }
129
+ function tryResolveBaseUrl(specifier, ctx) {
130
+ const base = ctx.tsConfigBaseUrl;
131
+ const tryAbs = path.resolve(base, specifier);
132
+ const tryRel = toRel(tryAbs, ctx.root);
133
+ if (!tryRel)
134
+ return null;
135
+ if (ctx.existingFiles.has(tryRel) || fileExists(tryAbs)) {
136
+ return { rawSpecifier: specifier, resolvedPath: tryRel, resolvedAbsolute: tryAbs, resolved: true, external: false };
137
+ }
138
+ for (const ext of EXTENSIONS_TRY_ORDER) {
139
+ if (ctx.existingFiles.has(tryRel + ext) || fileExists(tryAbs + ext)) {
140
+ return { rawSpecifier: specifier, resolvedPath: tryRel + ext, resolvedAbsolute: tryAbs + ext, resolved: true, external: false };
141
+ }
142
+ }
143
+ for (const idx of INDEX_FILES) {
144
+ const idxRel = path.posix.join(tryRel, idx);
145
+ const idxAbs = path.join(tryAbs, idx);
146
+ if (ctx.existingFiles.has(idxRel) || fileExists(idxAbs)) {
147
+ return { rawSpecifier: specifier, resolvedPath: idxRel, resolvedAbsolute: idxAbs, resolved: true, external: false };
148
+ }
149
+ }
150
+ return null;
151
+ }
152
+ function fileExists(abs) {
153
+ try {
154
+ return fs.existsSync(abs) && fs.statSync(abs).isFile();
155
+ }
156
+ catch {
157
+ return false;
158
+ }
159
+ }
160
+ function toRel(abs, root) {
161
+ const rel = path.relative(root, abs);
162
+ if (rel.startsWith("..") || path.isAbsolute(rel))
163
+ return null;
164
+ return rel.split(path.sep).join(path.posix.sep);
165
+ }
166
+ /** Load tsconfig paths lazily — caller can pass pre-parsed */
167
+ export function parseTsconfigPaths(tsconfigContent, configDir) {
168
+ try {
169
+ const json = JSON.parse(tsconfigContent.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, ""));
170
+ const compilerOptions = json.compilerOptions ?? {};
171
+ const paths = compilerOptions.paths;
172
+ const baseUrlRaw = compilerOptions.baseUrl;
173
+ const baseUrl = baseUrlRaw ? path.resolve(configDir, baseUrlRaw) : undefined;
174
+ return { paths, baseUrl };
175
+ }
176
+ catch {
177
+ return {};
178
+ }
179
+ }
180
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resolvers/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Scanners — file discovery pipeline.
3
+ * Local-first, streaming-capable, safe for large monorepos.
4
+ */
5
+ export interface ScanOptions {
6
+ root: string;
7
+ ignore?: string[];
8
+ concurrency?: number;
9
+ maxFileSizeBytes?: number;
10
+ /** Respect .gitignore if present (default: true) */
11
+ respectGitignore?: boolean;
12
+ }
13
+ export interface DiscoveredFile {
14
+ absolutePath: string;
15
+ relativePath: string;
16
+ extension: string;
17
+ language?: string;
18
+ sizeBytes: number;
19
+ }
20
+ export interface ScanResult {
21
+ files: DiscoveredFile[];
22
+ skipped: Array<{
23
+ path: string;
24
+ reason: string;
25
+ }>;
26
+ stats: {
27
+ totalDiscovered: number;
28
+ totalIncluded: number;
29
+ ignoredByPattern: number;
30
+ ignoredBinary: number;
31
+ ignoredTooLarge: number;
32
+ unsupportedLanguage: number;
33
+ };
34
+ }
35
+ /**
36
+ * Discover files under `root`.
37
+ * - Respects DEFAULT_IGNORE_GLOBS + user ignores
38
+ * - Skips binary/assets by extension
39
+ * - Skips files > maxFileSizeBytes
40
+ * - Never follows symlinked directories (prevents cycles)
41
+ * - Records skip reasons for graceful degradation reporting
42
+ */
43
+ export declare function scanRepository(options: ScanOptions): Promise<DiscoveredFile[]>;
44
+ export declare function scanRepositoryDetailed(options: ScanOptions): Promise<ScanResult>;
45
+ /** Helper: classify a file's language from its extension */
46
+ export declare function getLanguageForExtension(ext: string): string | undefined;
47
+ /** Helper: check if extension is ignored as binary */
48
+ export declare function isIgnoredExtension(ext: string): boolean;
49
+ /** Helper: check if extension is supported for parsing */
50
+ export declare function isSupportedExtension(ext: string): boolean;
51
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanners/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,KAAK,EAAE;QACL,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;CACH;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAGpF;AAED,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAmHtF;AAgCD,4DAA4D;AAC5D,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGvE;AAED,sDAAsD;AACtD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,0DAA0D;AAC1D,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEzD"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Scanners — file discovery pipeline.
3
+ * Local-first, streaming-capable, safe for large monorepos.
4
+ */
5
+ import fs from "node:fs/promises";
6
+ import path from "node:path";
7
+ import fg from "fast-glob";
8
+ import { DEFAULT_IGNORE_GLOBS, IGNORED_EXTENSIONS, SUPPORTED_EXTENSIONS, LANGUAGE_BY_EXTENSION, DEFAULT_MAX_FILE_SIZE_BYTES, DEFAULT_CONCURRENCY, } from "@yoinkingfish/shared";
9
+ /**
10
+ * Discover files under `root`.
11
+ * - Respects DEFAULT_IGNORE_GLOBS + user ignores
12
+ * - Skips binary/assets by extension
13
+ * - Skips files > maxFileSizeBytes
14
+ * - Never follows symlinked directories (prevents cycles)
15
+ * - Records skip reasons for graceful degradation reporting
16
+ */
17
+ export async function scanRepository(options) {
18
+ const result = await scanRepositoryDetailed(options);
19
+ return result.files;
20
+ }
21
+ export async function scanRepositoryDetailed(options) {
22
+ const root = path.resolve(options.root);
23
+ // Validate root exists and is directory
24
+ const stat = await fs.stat(root);
25
+ if (!stat.isDirectory())
26
+ throw new Error(`Not a directory: ${root}`);
27
+ const ignorePatterns = buildIgnorePatterns(options);
28
+ const maxSize = options.maxFileSizeBytes ?? DEFAULT_MAX_FILE_SIZE_BYTES;
29
+ const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
30
+ // fast-glob — never follow symlinked dirs, suppress errors for permission issues
31
+ const entries = await fg("**/*", {
32
+ cwd: root,
33
+ dot: false,
34
+ onlyFiles: true,
35
+ followSymbolicLinks: false,
36
+ suppressErrors: true,
37
+ ignore: ignorePatterns,
38
+ absolute: false,
39
+ stats: false,
40
+ });
41
+ const files = [];
42
+ const skipped = [];
43
+ let ignoredBinary = 0;
44
+ let ignoredTooLarge = 0;
45
+ let unsupportedLanguage = 0;
46
+ // Batch stat with concurrency limit
47
+ const queue = [...entries];
48
+ const workers = [];
49
+ async function worker() {
50
+ while (queue.length > 0) {
51
+ const relPosix = queue.pop();
52
+ // Normalize to POSIX already, but ensure Windows sep handled
53
+ const rel = relPosix.split("/").join(path.posix.sep);
54
+ const ext = path.extname(rel).slice(1).toLowerCase();
55
+ // Binary / asset fast-path — count before stat to save I/O
56
+ if (ext && IGNORED_EXTENSIONS.has(ext)) {
57
+ ignoredBinary++;
58
+ skipped.push({ path: rel, reason: "binary/asset" });
59
+ continue;
60
+ }
61
+ const abs = path.join(root, relPosix);
62
+ let sizeBytes;
63
+ try {
64
+ const s = await fs.stat(abs);
65
+ // Skip directories that slipped through, and symlinked dirs
66
+ if (!s.isFile()) {
67
+ skipped.push({ path: rel, reason: "not a file" });
68
+ continue;
69
+ }
70
+ // lstat check for symlink file? We allow symlink files but not dirs
71
+ // If file is symlink to outside root, skip for security
72
+ if (s.isSymbolicLink?.()) {
73
+ skipped.push({ path: rel, reason: "symlink" });
74
+ continue;
75
+ }
76
+ sizeBytes = s.size;
77
+ }
78
+ catch (err) {
79
+ skipped.push({ path: rel, reason: `stat failed: ${err.message}` });
80
+ continue;
81
+ }
82
+ if (sizeBytes > maxSize) {
83
+ ignoredTooLarge++;
84
+ skipped.push({ path: rel, reason: `too large (${sizeBytes} > ${maxSize})` });
85
+ continue;
86
+ }
87
+ const language = ext ? LANGUAGE_BY_EXTENSION[ext] : undefined;
88
+ if (ext && !SUPPORTED_EXTENSIONS.has(ext) && !IGNORED_EXTENSIONS.has(ext)) {
89
+ // Count as unsupported but still keep file for stats? Spec says detected / parser unavailable
90
+ // We keep it in skipped/unsupported list but NOT in files (files = parsable)
91
+ // However we want to report unsupportedFiles later — so we track
92
+ unsupportedLanguage++;
93
+ skipped.push({ path: rel, reason: `unsupported language: .${ext}` });
94
+ // For Phase 2, we still return only parsable files; unsupported are in skipped
95
+ // If you want to include them for reporting, caller can use ScanResult.skipped
96
+ continue;
97
+ }
98
+ files.push({
99
+ absolutePath: abs,
100
+ relativePath: rel,
101
+ extension: ext,
102
+ language,
103
+ sizeBytes,
104
+ });
105
+ }
106
+ }
107
+ const workerCount = Math.min(concurrency, Math.max(1, Math.ceil(entries.length / 32)));
108
+ for (let i = 0; i < workerCount; i++)
109
+ workers.push(worker());
110
+ await Promise.all(workers);
111
+ // Deterministic sort
112
+ files.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
113
+ skipped.sort((a, b) => a.path.localeCompare(b.path));
114
+ return {
115
+ files,
116
+ skipped,
117
+ stats: {
118
+ totalDiscovered: entries.length,
119
+ totalIncluded: files.length,
120
+ ignoredByPattern: entries.length - files.length - ignoredBinary - ignoredTooLarge - unsupportedLanguage, // approximation
121
+ ignoredBinary,
122
+ ignoredTooLarge,
123
+ unsupportedLanguage,
124
+ },
125
+ };
126
+ }
127
+ function buildIgnorePatterns(options) {
128
+ const patterns = [...DEFAULT_IGNORE_GLOBS];
129
+ // User ignores — normalize to glob
130
+ if (options.ignore) {
131
+ for (const p of options.ignore) {
132
+ const trimmed = p.trim();
133
+ if (!trimmed)
134
+ continue;
135
+ // If user gave `node_modules`, convert to `**/node_modules/**`
136
+ if (!trimmed.includes("*") && !trimmed.includes("/")) {
137
+ patterns.push(`**/${trimmed}/**`);
138
+ }
139
+ else {
140
+ patterns.push(trimmed);
141
+ }
142
+ }
143
+ }
144
+ // Also ignore dotfiles that are often not source (keep .gitignore itself ignored via .git/**)
145
+ // Do not ignore hidden source like .codecarto — handled elsewhere
146
+ // Respect .gitignore if requested
147
+ // We don't auto-load it into fast-glob via `gitignore: true` because fast-glob's gitignore
148
+ // support requires extra plugin; instead we can optionally read .gitignore and append patterns
149
+ // For Phase 2 minimal, we just keep DEFAULT_IGNORE; .gitignore handling lands in Phase 3 if needed
150
+ // Placeholder for future:
151
+ // if (options.respectGitignore !== false) { patterns.push(...readGitignore(root)); }
152
+ return patterns;
153
+ }
154
+ /** Helper: classify a file's language from its extension */
155
+ export function getLanguageForExtension(ext) {
156
+ const lower = ext.toLowerCase().replace(/^\./, "");
157
+ return LANGUAGE_BY_EXTENSION[lower];
158
+ }
159
+ /** Helper: check if extension is ignored as binary */
160
+ export function isIgnoredExtension(ext) {
161
+ return IGNORED_EXTENSIONS.has(ext.toLowerCase().replace(/^\./, ""));
162
+ }
163
+ /** Helper: check if extension is supported for parsing */
164
+ export function isSupportedExtension(ext) {
165
+ return SUPPORTED_EXTENSIONS.has(ext.toLowerCase().replace(/^\./, ""));
166
+ }
167
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanners/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAgC9B;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAoB;IACvD,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,KAAK,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAoB;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,wCAAwC;IACxC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;IAErE,MAAM,cAAc,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,IAAI,2BAA2B,CAAC;IACxE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,mBAAmB,CAAC;IAE/D,iFAAiF;IACjF,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE;QAC/B,GAAG,EAAE,IAAI;QACT,GAAG,EAAE,KAAK;QACV,SAAS,EAAE,IAAI;QACf,mBAAmB,EAAE,KAAK;QAC1B,cAAc,EAAE,IAAI;QACpB,MAAM,EAAE,cAAc;QACtB,QAAQ,EAAE,KAAK;QACf,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;IAEH,MAAM,KAAK,GAAqB,EAAE,CAAC;IACnC,MAAM,OAAO,GAA0B,EAAE,CAAC;IAC1C,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAE5B,oCAAoC;IACpC,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAC3B,MAAM,OAAO,GAAoB,EAAE,CAAC;IAEpC,KAAK,UAAU,MAAM;QACnB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;YAC9B,6DAA6D;YAC7D,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACrD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YAErD,2DAA2D;YAC3D,IAAI,GAAG,IAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvC,aAAa,EAAE,CAAC;gBAChB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;gBACpD,SAAS;YACX,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACtC,IAAI,SAAiB,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC7B,4DAA4D;gBAC5D,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;oBAChB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;oBAClD,SAAS;gBACX,CAAC;gBACD,oEAAoE;gBACpE,wDAAwD;gBACxD,IAAI,CAAC,CAAC,cAAc,EAAE,EAAE,EAAE,CAAC;oBACzB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;oBAC/C,SAAS;gBACX,CAAC;gBACD,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC;YACrB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,gBAAiB,GAAa,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC9E,SAAS;YACX,CAAC;YAED,IAAI,SAAS,GAAG,OAAO,EAAE,CAAC;gBACxB,eAAe,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,cAAc,SAAS,MAAM,OAAO,GAAG,EAAE,CAAC,CAAC;gBAC7E,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9D,IAAI,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1E,8FAA8F;gBAC9F,6EAA6E;gBAC7E,iEAAiE;gBACjE,mBAAmB,EAAE,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,0BAA0B,GAAG,EAAE,EAAE,CAAC,CAAC;gBACrE,+EAA+E;gBAC/E,+EAA+E;gBAC/E,SAAS;YACX,CAAC;YAED,KAAK,CAAC,IAAI,CAAC;gBACT,YAAY,EAAE,GAAG;gBACjB,YAAY,EAAE,GAAG;gBACjB,SAAS,EAAE,GAAG;gBACd,QAAQ;gBACR,SAAS;aACV,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACvF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAE3B,qBAAqB;IACrB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAErD,OAAO;QACL,KAAK;QACL,OAAO;QACP,KAAK,EAAE;YACL,eAAe,EAAE,OAAO,CAAC,MAAM;YAC/B,aAAa,EAAE,KAAK,CAAC,MAAM;YAC3B,gBAAgB,EAAE,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,aAAa,GAAG,eAAe,GAAG,mBAAmB,EAAE,gBAAgB;YACzH,aAAa;YACb,eAAe;YACf,mBAAmB;SACpB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAoB;IAC/C,MAAM,QAAQ,GAAa,CAAC,GAAG,oBAAoB,CAAC,CAAC;IAErD,mCAAmC;IACnC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,+DAA+D;YAC/D,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrD,QAAQ,CAAC,IAAI,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,8FAA8F;IAC9F,kEAAkE;IAElE,kCAAkC;IAClC,2FAA2F;IAC3F,+FAA+F;IAC/F,mGAAmG;IACnG,0BAA0B;IAC1B,qFAAqF;IAErF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnD,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,OAAO,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,OAAO,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;AACxE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@yoinkingfish/parser",
3
+ "version": "0.1.1",
4
+ "description": "CodeCarto parser — file discovery, AST parsing, import resolution",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "dependencies": {
18
+ "fast-glob": "^3.3.2",
19
+ "ts-morph": "^23.0.0",
20
+ "zod": "^3.23.8",
21
+ "@yoinkingfish/shared": "0.1.1"
22
+ },
23
+ "devDependencies": {
24
+ "@types/node": "^22.7.4",
25
+ "rimraf": "^6.0.1",
26
+ "typescript": "^5.6.3",
27
+ "vitest": "^2.1.8"
28
+ },
29
+ "scripts": {
30
+ "build": "tsc -p tsconfig.json",
31
+ "dev": "tsc -p tsconfig.json --watch",
32
+ "typecheck": "tsc --noEmit -p tsconfig.json",
33
+ "clean": "rimraf dist",
34
+ "test": "vitest run"
35
+ }
36
+ }