assertloom 0.0.0-stage → 0.1.0
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 +21 -0
- package/README.md +346 -2
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.js +14 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/openai.d.ts +9 -0
- package/dist/ai/openai.js +57 -0
- package/dist/ai/openai.js.map +1 -0
- package/dist/ai/pricing.d.ts +27 -0
- package/dist/ai/pricing.js +76 -0
- package/dist/ai/pricing.js.map +1 -0
- package/dist/ai/prompts.d.ts +27 -0
- package/dist/ai/prompts.js +89 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/ai/provider.d.ts +26 -0
- package/dist/ai/provider.js +4 -0
- package/dist/ai/provider.js.map +1 -0
- package/dist/ai/redact.d.ts +5 -0
- package/dist/ai/redact.js +31 -0
- package/dist/ai/redact.js.map +1 -0
- package/dist/analyzer/dependencies.d.ts +16 -0
- package/dist/analyzer/dependencies.js +168 -0
- package/dist/analyzer/dependencies.js.map +1 -0
- package/dist/analyzer/format.d.ts +3 -0
- package/dist/analyzer/format.js +14 -0
- package/dist/analyzer/format.js.map +1 -0
- package/dist/analyzer/functions.d.ts +4 -0
- package/dist/analyzer/functions.js +274 -0
- package/dist/analyzer/functions.js.map +1 -0
- package/dist/analyzer/index.d.ts +5 -0
- package/dist/analyzer/index.js +29 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/analyzer/parser.d.ts +11 -0
- package/dist/analyzer/parser.js +38 -0
- package/dist/analyzer/parser.js.map +1 -0
- package/dist/analyzer/usage.d.ts +16 -0
- package/dist/analyzer/usage.js +159 -0
- package/dist/analyzer/usage.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +2 -0
- package/dist/cli/commands/analyze.js +49 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +3 -0
- package/dist/cli/commands/generate.js +200 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/run.d.ts +4 -0
- package/dist/cli/commands/run.js +53 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +16 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/program.d.ts +2 -0
- package/dist/cli/program.js +18 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/report.d.ts +3 -0
- package/dist/cli/report.js +36 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/validateFile.d.ts +5 -0
- package/dist/cli/validateFile.js +43 -0
- package/dist/cli/validateFile.js.map +1 -0
- package/dist/errors.d.ts +4 -0
- package/dist/errors.js +8 -0
- package/dist/errors.js.map +1 -0
- package/dist/generator/diff.d.ts +5 -0
- package/dist/generator/diff.js +56 -0
- package/dist/generator/diff.js.map +1 -0
- package/dist/generator/importPlan.d.ts +15 -0
- package/dist/generator/importPlan.js +62 -0
- package/dist/generator/importPlan.js.map +1 -0
- package/dist/generator/index.d.ts +5 -0
- package/dist/generator/index.js +6 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/mocks.d.ts +48 -0
- package/dist/generator/mocks.js +356 -0
- package/dist/generator/mocks.js.map +1 -0
- package/dist/generator/schema.d.ts +40 -0
- package/dist/generator/schema.js +15 -0
- package/dist/generator/schema.js.map +1 -0
- package/dist/generator/testGenerator.d.ts +33 -0
- package/dist/generator/testGenerator.js +80 -0
- package/dist/generator/testGenerator.js.map +1 -0
- package/dist/generator/testWriter.d.ts +22 -0
- package/dist/generator/testWriter.js +93 -0
- package/dist/generator/testWriter.js.map +1 -0
- package/dist/generator/validate.d.ts +31 -0
- package/dist/generator/validate.js +180 -0
- package/dist/generator/validate.js.map +1 -0
- package/dist/repair/classifyFailure.d.ts +11 -0
- package/dist/repair/classifyFailure.js +26 -0
- package/dist/repair/classifyFailure.js.map +1 -0
- package/dist/repair/index.d.ts +2 -0
- package/dist/repair/index.js +3 -0
- package/dist/repair/index.js.map +1 -0
- package/dist/repair/repairLoop.d.ts +74 -0
- package/dist/repair/repairLoop.js +219 -0
- package/dist/repair/repairLoop.js.map +1 -0
- package/dist/repair/schema.d.ts +17 -0
- package/dist/repair/schema.js +14 -0
- package/dist/repair/schema.js.map +1 -0
- package/dist/runner/coverage.d.ts +5 -0
- package/dist/runner/coverage.js +42 -0
- package/dist/runner/coverage.js.map +1 -0
- package/dist/runner/index.d.ts +4 -0
- package/dist/runner/index.js +4 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/runner/jestConfig.d.ts +11 -0
- package/dist/runner/jestConfig.js +103 -0
- package/dist/runner/jestConfig.js.map +1 -0
- package/dist/runner/jestRunner.d.ts +14 -0
- package/dist/runner/jestRunner.js +140 -0
- package/dist/runner/jestRunner.js.map +1 -0
- package/dist/runner/networkGuard.d.ts +4 -0
- package/dist/runner/networkGuard.js +55 -0
- package/dist/runner/networkGuard.js.map +1 -0
- package/dist/runner/project.d.ts +30 -0
- package/dist/runner/project.js +86 -0
- package/dist/runner/project.js.map +1 -0
- package/dist/runner/results.d.ts +32 -0
- package/dist/runner/results.js +58 -0
- package/dist/runner/results.js.map +1 -0
- package/dist/runner/types.d.ts +39 -0
- package/dist/runner/types.js +2 -0
- package/dist/runner/types.js.map +1 -0
- package/dist/types/index.d.ts +95 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +66 -4
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { formatSignature } from "../analyzer/format.js";
|
|
2
|
+
const BODY_RULES = `- Call target functions only through the binding names listed. They are already imported; Assertloom writes the imports, describe blocks, and it() wrappers.
|
|
3
|
+
- Do not write import or require statements, describe/it/test wrappers, or jest.mock calls.
|
|
4
|
+
- Assert the behavior of the source as written. Work out expected values by reading the code; never guess. If you cannot be sure of an exact value, assert something you can verify (type, length, ordering, a relationship between outputs).
|
|
5
|
+
- Tests must be deterministic: no real network or file system access, real timers, Date.now(), or Math.random().
|
|
6
|
+
- Dependencies listed under "Mocks" are already mocked by Assertloom and reset before every test, so every jest.fn() returns undefined until the test configures it. In each test, set up exactly what the code path needs with mockResolvedValue, mockRejectedValue, mockReturnValue, mockReturnValueOnce, or mockImplementation. In TypeScript, wrap mocks with jest.mocked(...) and cast fake values with \`as any\` when they are partial.
|
|
7
|
+
- Shape fake values like the real API the source expects (for example, fetch responses need \`ok\`, \`status\`, and \`json: async () => data\`).
|
|
8
|
+
- Where it matters, assert how dependencies were called with toHaveBeenCalledWith or toHaveBeenCalledTimes.
|
|
9
|
+
- Functions in the source call each other directly, so spying on them has no effect, and \`module.exports\`/\`exports\` in a test refer to the test file itself. Control behavior through the mocked dependencies and real inputs instead.
|
|
10
|
+
- Tests must pass on every operating system. Never hardcode path separators in expected values; build expected paths with the same functions the source uses (such as path.join, when it is imported in the test file) or use expect.stringContaining.
|
|
11
|
+
- For async functions, use await, or await expect(...).rejects for rejections.
|
|
12
|
+
- Use toBeCloseTo for floating-point results and toEqual for objects and arrays.
|
|
13
|
+
- For generators, collect values with Array.from() or spread syntax.
|
|
14
|
+
- In TypeScript, arguments must match the declared parameter types. If an error case needs an invalid argument, cast it with \`as any\`.`;
|
|
15
|
+
export const GENERATION_SYSTEM_PROMPT = `You are Assertloom, a tool that writes Jest unit tests for JavaScript and TypeScript code.
|
|
16
|
+
|
|
17
|
+
For each target function you are given, return test cases. Each case has a short name (the \`it\` title), a category, and a body: the statements that go inside the test callback.
|
|
18
|
+
|
|
19
|
+
Rules:
|
|
20
|
+
${BODY_RULES}
|
|
21
|
+
- Cover each function with normal cases (typical input) and edge cases (empty values, zero, negative numbers, boundaries, unicode where relevant). Add error cases when the source throws or rejects, using toThrow / rejects.toThrow and matching the message when the source shows it.
|
|
22
|
+
- For functions that use mocked dependencies, also cover failure paths: make the dependency reject or return an error result, then assert what the source does (rejects with its own message, rethrows, or falls back to a default).
|
|
23
|
+
- Write 3 to 6 cases per function. Each case should check one behavior with a few focused expect() calls.`;
|
|
24
|
+
export const REPAIR_SYSTEM_PROMPT = `You are Assertloom, a tool that repairs failing Jest tests it generated. You cannot change the source code; only the tests.
|
|
25
|
+
|
|
26
|
+
For each failing test you are given, return exactly one repair with one of these actions:
|
|
27
|
+
- fix: the test is wrong (a miscalculated expected value, a wrong assumption about behavior, a missing await, a mock that was not configured or returns the wrong shape — "Cannot read properties of undefined" often means a mock still returns undefined). Return a corrected body that keeps testing the same behavior, with expected values derived from the source.
|
|
28
|
+
- skip: the test's expectation matches what the function clearly intends (its name, documentation, or error messages), but the source does something else. This is likely a bug in the source; do not rewrite the test to match buggy behavior. Explain the suspected bug in the reason.
|
|
29
|
+
- remove: the test cannot be made deterministic or tests something outside the function.
|
|
30
|
+
|
|
31
|
+
Prefer fix. Use the failure message: "Expected"/"Received" lines show what the code actually returned.
|
|
32
|
+
|
|
33
|
+
Body rules for fix:
|
|
34
|
+
${BODY_RULES}`;
|
|
35
|
+
function mocksSection(mockSummary) {
|
|
36
|
+
return mockSummary ? `\nMocks (already set up in the test file):\n${mockSummary}\n` : "\nMocks: none. The source has no dependencies that need mocking.\n";
|
|
37
|
+
}
|
|
38
|
+
export function buildGenerationPrompt({ analysis, code, bindings, testFileName, mockSummary }) {
|
|
39
|
+
const language = analysis.language === "typescript" ? "typescript" : "javascript";
|
|
40
|
+
const targets = bindings
|
|
41
|
+
.map(({ binding, fn }) => {
|
|
42
|
+
const notes = [
|
|
43
|
+
binding !== fn.name ? `declared as \`${fn.name}\` in the source` : "",
|
|
44
|
+
fn.throws ? "throws in its own body" : "",
|
|
45
|
+
`defined at line ${fn.line}`,
|
|
46
|
+
].filter(Boolean);
|
|
47
|
+
return `- \`${binding}\`: \`${formatSignature(fn, binding)}\` (${notes.join("; ")})`;
|
|
48
|
+
})
|
|
49
|
+
.join("\n");
|
|
50
|
+
return `Write Jest tests for the target functions in \`${analysis.file}\`.
|
|
51
|
+
|
|
52
|
+
Test file: \`${testFileName}\` (${language}, Jest globals available)
|
|
53
|
+
|
|
54
|
+
Target functions (use these binding names exactly):
|
|
55
|
+
${targets}
|
|
56
|
+
${mocksSection(mockSummary)}
|
|
57
|
+
Source of \`${analysis.file}\`:
|
|
58
|
+
\`\`\`${language}
|
|
59
|
+
${code}
|
|
60
|
+
\`\`\``;
|
|
61
|
+
}
|
|
62
|
+
export const MAX_FAILURE_MESSAGE_CHARS = 1200;
|
|
63
|
+
export function buildRepairPrompt(input) {
|
|
64
|
+
const language = input.analysis.language === "typescript" ? "typescript" : "javascript";
|
|
65
|
+
const failures = input.targets
|
|
66
|
+
.map((t, i) => {
|
|
67
|
+
const message = t.message.length > MAX_FAILURE_MESSAGE_CHARS ? `${t.message.slice(0, MAX_FAILURE_MESSAGE_CHARS)}\n…(truncated)` : t.message;
|
|
68
|
+
return `### ${i + 1}. \`${t.binding.binding}\` › ${JSON.stringify(t.testName)}
|
|
69
|
+
Signature: \`${formatSignature(t.binding.fn, t.binding.binding)}\`
|
|
70
|
+
Failure (${t.failureCategory}):
|
|
71
|
+
\`\`\`
|
|
72
|
+
${message}
|
|
73
|
+
\`\`\`
|
|
74
|
+
Current body:
|
|
75
|
+
\`\`\`${language}
|
|
76
|
+
${t.body}
|
|
77
|
+
\`\`\``;
|
|
78
|
+
})
|
|
79
|
+
.join("\n\n");
|
|
80
|
+
return `Repair attempt ${input.attempt}: ${input.targets.length} generated test${input.targets.length === 1 ? "" : "s"} in the tests for \`${input.analysis.file}\` failed.
|
|
81
|
+
|
|
82
|
+
${failures}
|
|
83
|
+
${mocksSection(input.mockSummary)}
|
|
84
|
+
Source of \`${input.analysis.file}\` (read-only):
|
|
85
|
+
\`\`\`${language}
|
|
86
|
+
${input.code}
|
|
87
|
+
\`\`\``;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/ai/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import { UserError } from "../errors.js";
|
|
3
|
+
export declare class ProviderError extends UserError {
|
|
4
|
+
}
|
|
5
|
+
export interface StructuredRequest<T> {
|
|
6
|
+
system: string;
|
|
7
|
+
prompt: string;
|
|
8
|
+
schema: z.ZodType<T>;
|
|
9
|
+
schemaName: string;
|
|
10
|
+
maxOutputTokens: number;
|
|
11
|
+
}
|
|
12
|
+
export interface TokenUsage {
|
|
13
|
+
inputTokens: number;
|
|
14
|
+
outputTokens: number;
|
|
15
|
+
}
|
|
16
|
+
export interface StructuredResponse<T> {
|
|
17
|
+
data: T;
|
|
18
|
+
model: string;
|
|
19
|
+
usage: TokenUsage;
|
|
20
|
+
}
|
|
21
|
+
/** A model that returns JSON validated against a Zod schema. Implement this to add a provider. */
|
|
22
|
+
export interface LLMProvider {
|
|
23
|
+
readonly name: string;
|
|
24
|
+
readonly model: string;
|
|
25
|
+
generateStructured<T>(request: StructuredRequest<T>): Promise<StructuredResponse<T>>;
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/ai/provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,OAAO,aAAc,SAAQ,SAAS;CAAG"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const SECRET_PATTERNS = [
|
|
2
|
+
/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
3
|
+
/\bsk-(?:proj-|ant-)?[A-Za-z0-9_-]{20,}/g,
|
|
4
|
+
/\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{16,}/g,
|
|
5
|
+
/\bBearer\s+[A-Za-z0-9._~+/-]{16,}=*/g,
|
|
6
|
+
/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,
|
|
7
|
+
/\bgh[pousr]_[A-Za-z0-9]{36,}\b/g,
|
|
8
|
+
/\bxox[abprs]-[A-Za-z0-9-]{10,}/g,
|
|
9
|
+
/\bAIza[0-9A-Za-z_-]{35}\b/g,
|
|
10
|
+
/\b[a-z][a-z0-9+.-]*:\/\/[^\s:/@'"`]+:[^\s@'"`]+@/gi,
|
|
11
|
+
];
|
|
12
|
+
const ASSIGNED_SECRET = /\b([A-Za-z0-9_]*(?:secret|password|passwd|api_?key|token|credential|authorization)[A-Za-z0-9_]*["']?\s*(?:[:=]|===?|!==?)\s*)(["'`])((?:(?!\2)[^\n\\]|\\.){8,})\2/gi;
|
|
13
|
+
/** Replaces likely credentials with a placeholder before code leaves the machine. */
|
|
14
|
+
export function redactSecrets(code) {
|
|
15
|
+
let redactions = 0;
|
|
16
|
+
let result = code;
|
|
17
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
18
|
+
result = result.replace(pattern, () => {
|
|
19
|
+
redactions++;
|
|
20
|
+
return "<redacted>";
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
result = result.replace(ASSIGNED_SECRET, (match, prefix, quote, value) => {
|
|
24
|
+
if (value.includes("<redacted>"))
|
|
25
|
+
return match;
|
|
26
|
+
redactions++;
|
|
27
|
+
return `${prefix}${quote}<redacted>${quote}`;
|
|
28
|
+
});
|
|
29
|
+
return { code: result, redactions };
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/ai/redact.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAa;IAChC,6EAA6E;IAC7E,yCAAyC;IACzC,gDAAgD;IAChD,sCAAsC;IACtC,gCAAgC;IAChC,iCAAiC;IACjC,iCAAiC;IACjC,4BAA4B;IAC5B,oDAAoD;CACrD,CAAC;AAEF,MAAM,eAAe,GACnB,qKAAqK,CAAC;AAExK,qFAAqF;AACrF,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,MAAM,GAAG,IAAI,CAAC;IAElB,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE;YACpC,UAAU,EAAE,CAAC;YACb,OAAO,YAAY,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAc,EAAE,KAAa,EAAE,KAAa,EAAE,EAAE;QAC/F,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/C,UAAU,EAAE,CAAC;QACb,OAAO,GAAG,MAAM,GAAG,KAAK,aAAa,KAAK,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { File, Node } from "@babel/types";
|
|
2
|
+
import type { DependencySummary, ImportCategory, ImportInfo } from "../types/index.js";
|
|
3
|
+
export interface ImportScan {
|
|
4
|
+
imports: ImportInfo[];
|
|
5
|
+
/** Top-level runtime bindings created by imports, keyed by local name. */
|
|
6
|
+
bindings: Map<string, string>;
|
|
7
|
+
/** `require()` and `import()` call nodes, mapped to the module they load. */
|
|
8
|
+
callSites: Map<Node, string>;
|
|
9
|
+
usesCommonJsExports: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function classifySource(source: string): {
|
|
12
|
+
category: ImportCategory;
|
|
13
|
+
packageName?: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function scanImports(ast: File): ImportScan;
|
|
16
|
+
export declare function summarizeDependencies(imports: ImportInfo[]): DependencySummary;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { builtinModules } from "node:module";
|
|
2
|
+
import traverse from "@babel/traverse";
|
|
3
|
+
export function classifySource(source) {
|
|
4
|
+
if (source.startsWith(".") || source.startsWith("/") || source.startsWith("#")) {
|
|
5
|
+
return { category: "local" };
|
|
6
|
+
}
|
|
7
|
+
if (source.startsWith("node:") || builtinModules.includes(source)) {
|
|
8
|
+
return { category: "builtin" };
|
|
9
|
+
}
|
|
10
|
+
const segments = source.split("/");
|
|
11
|
+
const packageName = source.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
|
|
12
|
+
return { category: "external", packageName };
|
|
13
|
+
}
|
|
14
|
+
function stringValue(node) {
|
|
15
|
+
if (node?.type === "StringLiteral")
|
|
16
|
+
return node.value;
|
|
17
|
+
if (node?.type === "TemplateLiteral" && node.expressions.length === 0)
|
|
18
|
+
return node.quasis[0].value.cooked ?? undefined;
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
function moduleName(node) {
|
|
22
|
+
return node.type === "StringLiteral" ? node.value : node.type === "Identifier" ? node.name : "";
|
|
23
|
+
}
|
|
24
|
+
function isRequireCall(path) {
|
|
25
|
+
const callee = path.node.callee;
|
|
26
|
+
return callee.type === "Identifier" && callee.name === "require" && !path.scope.hasBinding("require");
|
|
27
|
+
}
|
|
28
|
+
function isCommonJsExportTarget(node) {
|
|
29
|
+
if (node.type !== "MemberExpression")
|
|
30
|
+
return false;
|
|
31
|
+
if (node.object.type === "Identifier") {
|
|
32
|
+
return (node.object.name === "exports" ||
|
|
33
|
+
(node.object.name === "module" && node.property.type === "Identifier" && node.property.name === "exports"));
|
|
34
|
+
}
|
|
35
|
+
return isCommonJsExportTarget(node.object);
|
|
36
|
+
}
|
|
37
|
+
export function scanImports(ast) {
|
|
38
|
+
const imports = [];
|
|
39
|
+
const bindings = new Map();
|
|
40
|
+
const callSites = new Map();
|
|
41
|
+
let usesCommonJsExports = false;
|
|
42
|
+
const add = (source, info) => {
|
|
43
|
+
imports.push({ source, ...classifySource(source), ...info });
|
|
44
|
+
};
|
|
45
|
+
traverse(ast, {
|
|
46
|
+
ImportDeclaration(path) {
|
|
47
|
+
const node = path.node;
|
|
48
|
+
const source = node.source.value;
|
|
49
|
+
const typeOnly = node.importKind === "type" ||
|
|
50
|
+
(node.specifiers.length > 0 && node.specifiers.every((s) => s.type === "ImportSpecifier" && s.importKind === "type"));
|
|
51
|
+
const specifiers = node.specifiers.map((s) => {
|
|
52
|
+
if (s.type === "ImportDefaultSpecifier")
|
|
53
|
+
return { kind: "default", imported: "default", local: s.local.name };
|
|
54
|
+
if (s.type === "ImportNamespaceSpecifier")
|
|
55
|
+
return { kind: "namespace", imported: "*", local: s.local.name };
|
|
56
|
+
return { kind: "named", imported: moduleName(s.imported), local: s.local.name };
|
|
57
|
+
});
|
|
58
|
+
if (!typeOnly) {
|
|
59
|
+
for (const s of node.specifiers) {
|
|
60
|
+
if (s.type === "ImportSpecifier" && s.importKind === "type")
|
|
61
|
+
continue;
|
|
62
|
+
bindings.set(s.local.name, source);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
add(source, { kind: "import", typeOnly, specifiers, line: node.loc?.start.line ?? 0 });
|
|
66
|
+
},
|
|
67
|
+
ExportNamedDeclaration(path) {
|
|
68
|
+
const node = path.node;
|
|
69
|
+
if (!node.source)
|
|
70
|
+
return;
|
|
71
|
+
const specifiers = node.specifiers.map((s) => s.type === "ExportNamespaceSpecifier"
|
|
72
|
+
? { kind: "namespace", imported: "*", local: moduleName(s.exported) }
|
|
73
|
+
: { kind: "named", imported: moduleName(s.type === "ExportSpecifier" ? s.local : s.exported), local: moduleName(s.exported) });
|
|
74
|
+
add(node.source.value, {
|
|
75
|
+
kind: "re-export",
|
|
76
|
+
typeOnly: node.exportKind === "type",
|
|
77
|
+
specifiers,
|
|
78
|
+
line: node.loc?.start.line ?? 0,
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
ExportAllDeclaration(path) {
|
|
82
|
+
const node = path.node;
|
|
83
|
+
add(node.source.value, {
|
|
84
|
+
kind: "re-export",
|
|
85
|
+
typeOnly: node.exportKind === "type",
|
|
86
|
+
specifiers: [{ kind: "namespace", imported: "*", local: "*" }],
|
|
87
|
+
line: node.loc?.start.line ?? 0,
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
ImportExpression(path) {
|
|
91
|
+
const source = stringValue(path.node.source);
|
|
92
|
+
if (!source)
|
|
93
|
+
return;
|
|
94
|
+
callSites.set(path.node, source);
|
|
95
|
+
add(source, { kind: "dynamic-import", typeOnly: false, specifiers: [], line: path.node.loc?.start.line ?? 0 });
|
|
96
|
+
},
|
|
97
|
+
CallExpression(path) {
|
|
98
|
+
if (!isRequireCall(path))
|
|
99
|
+
return;
|
|
100
|
+
const source = stringValue(path.node.arguments[0]);
|
|
101
|
+
if (!source)
|
|
102
|
+
return;
|
|
103
|
+
callSites.set(path.node, source);
|
|
104
|
+
const specifiers = [];
|
|
105
|
+
const declarator = path.parentPath;
|
|
106
|
+
if (declarator.isVariableDeclarator() && declarator.node.init === path.node) {
|
|
107
|
+
const id = declarator.node.id;
|
|
108
|
+
if (id.type === "Identifier") {
|
|
109
|
+
specifiers.push({ kind: "namespace", imported: "*", local: id.name });
|
|
110
|
+
}
|
|
111
|
+
else if (id.type === "ObjectPattern") {
|
|
112
|
+
for (const prop of id.properties) {
|
|
113
|
+
if (prop.type === "ObjectProperty" && prop.value.type === "Identifier") {
|
|
114
|
+
specifiers.push({ kind: "named", imported: moduleName(prop.key), local: prop.value.name });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (path.scope.getProgramParent() === path.scope) {
|
|
119
|
+
for (const s of specifiers)
|
|
120
|
+
bindings.set(s.local, source);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
add(source, { kind: "require", typeOnly: false, specifiers, line: path.node.loc?.start.line ?? 0 });
|
|
124
|
+
},
|
|
125
|
+
AssignmentExpression(path) {
|
|
126
|
+
if (isCommonJsExportTarget(path.node.left))
|
|
127
|
+
usesCommonJsExports = true;
|
|
128
|
+
},
|
|
129
|
+
// `const client = new PrismaClient()` makes `client` a stand-in for "@prisma/client".
|
|
130
|
+
VariableDeclarator(path) {
|
|
131
|
+
const { id, init } = path.node;
|
|
132
|
+
if (id.type !== "Identifier" || !init || path.scope !== path.scope.getProgramParent())
|
|
133
|
+
return;
|
|
134
|
+
if (init.type === "ArrowFunctionExpression" || init.type === "FunctionExpression")
|
|
135
|
+
return;
|
|
136
|
+
const programScope = path.scope;
|
|
137
|
+
path.traverse({
|
|
138
|
+
Identifier(idPath) {
|
|
139
|
+
if (bindings.has(id.name) || !idPath.isReferencedIdentifier())
|
|
140
|
+
return;
|
|
141
|
+
const source = bindings.get(idPath.node.name);
|
|
142
|
+
if (source && idPath.scope.getBinding(idPath.node.name) === programScope.getBinding(idPath.node.name)) {
|
|
143
|
+
bindings.set(id.name, source);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
imports.sort((a, b) => a.line - b.line);
|
|
150
|
+
return { imports, bindings, callSites, usesCommonJsExports };
|
|
151
|
+
}
|
|
152
|
+
export function summarizeDependencies(imports) {
|
|
153
|
+
const local = new Set();
|
|
154
|
+
const external = new Set();
|
|
155
|
+
const builtin = new Set();
|
|
156
|
+
for (const entry of imports) {
|
|
157
|
+
if (entry.typeOnly)
|
|
158
|
+
continue;
|
|
159
|
+
if (entry.category === "local")
|
|
160
|
+
local.add(entry.source);
|
|
161
|
+
else if (entry.category === "builtin")
|
|
162
|
+
builtin.add(entry.source.replace(/^node:/, ""));
|
|
163
|
+
else if (entry.packageName)
|
|
164
|
+
external.add(entry.packageName);
|
|
165
|
+
}
|
|
166
|
+
return { local: [...local].sort(), external: [...external].sort(), builtin: [...builtin].sort() };
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../src/analyzer/dependencies.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Renders a function like `async fetchJson<T>(url: string, init?: RequestInit): Promise<T>`. */
|
|
2
|
+
export function formatSignature(fn, name = fn.name) {
|
|
3
|
+
const params = fn.parameters
|
|
4
|
+
.map((p) => {
|
|
5
|
+
const optionalMark = p.optional && !p.rest && !p.defaultValue ? "?" : "";
|
|
6
|
+
const type = p.type ? `: ${p.type}` : "";
|
|
7
|
+
const defaultValue = p.defaultValue ? ` = ${p.defaultValue}` : "";
|
|
8
|
+
return `${p.rest ? "..." : ""}${p.name}${optionalMark}${type}${defaultValue}`;
|
|
9
|
+
})
|
|
10
|
+
.join(", ");
|
|
11
|
+
const prefix = `${fn.async ? "async " : ""}${fn.generator ? "*" : ""}`;
|
|
12
|
+
return `${prefix}${name}${fn.typeParameters ?? ""}(${params})${fn.returnType ? `: ${fn.returnType}` : ""}`;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/analyzer/format.ts"],"names":[],"mappings":"AAEA,iGAAiG;AACjG,MAAM,UAAU,eAAe,CAAC,EAAgB,EAAE,IAAI,GAAG,EAAE,CAAC,IAAI;IAC9D,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU;SACzB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,YAAY,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,MAAM,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,GAAG,YAAY,GAAG,IAAI,GAAG,YAAY,EAAE,CAAC;IAChF,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACvE,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC,cAAc,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC7G,CAAC"}
|