@lowgular/code-graph 0.1.1 → 0.1.2

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.
Files changed (44) hide show
  1. package/bin/cli.js +2458 -5
  2. package/lib.js +2430 -0
  3. package/package.json +3 -2
  4. package/code-graph-v2/code.graph.js +0 -37
  5. package/code-graph-v2/config-from-query.js +0 -131
  6. package/code-graph-v2/extractors/extractor.js +0 -27
  7. package/code-graph-v2/extractors/index.js +0 -1
  8. package/code-graph-v2/graph-builder/code-graph.builder.js +0 -49
  9. package/code-graph-v2/graph-builder/index.js +0 -1
  10. package/code-graph-v2/graph-builder/node.processor.js +0 -22
  11. package/code-graph-v2/graph-builder/relationship.processor.js +0 -55
  12. package/code-graph-v2/graph-builder/type.processor.js +0 -21
  13. package/code-graph-v2/index.js +0 -4
  14. package/code-graph-v2/tools/build-code-graph.tool.js +0 -19
  15. package/code-graph-v2/utils.js +0 -34
  16. package/codegular/index.js +0 -5
  17. package/codegular/node.js +0 -71
  18. package/codegular/program.js +0 -100
  19. package/codegular/string.js +0 -121
  20. package/codegular/type-checker.js +0 -133
  21. package/codegular/type.js +0 -356
  22. package/codegular/utils.js +0 -335
  23. package/cypher/index.js +0 -1
  24. package/cypher/lib/executor/condition-evaluator.js +0 -135
  25. package/cypher/lib/executor/executor.js +0 -60
  26. package/cypher/lib/executor/graph.js +0 -0
  27. package/cypher/lib/executor/match-engine.js +0 -130
  28. package/cypher/lib/executor/pattern-matcher.js +0 -86
  29. package/cypher/lib/executor/relationship-navigator.js +0 -41
  30. package/cypher/lib/executor/result-formatter.js +0 -149
  31. package/cypher/lib/executor/traverse-engine.js +0 -141
  32. package/cypher/lib/executor/utils.js +0 -14
  33. package/cypher/lib/graph.stub.js +0 -38
  34. package/cypher/lib/index.js +0 -32
  35. package/cypher/lib/lexer.js +0 -376
  36. package/cypher/lib/parser.js +0 -586
  37. package/cypher/lib/validator/query-validator.js +0 -75
  38. package/cypher/lib/validator/supported-features.config.js +0 -83
  39. package/cypher/lib/validator/unsupported-features.config.js +0 -124
  40. package/cypher-cli.js +0 -41
  41. package/infra/code-graph.js +0 -147
  42. package/main.js +0 -0
  43. package/resources-cli.js +0 -75
  44. package/run-cli.js +0 -43
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@lowgular/code-graph",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Run Cypher queries against a TypeScript code graph built from tsconfig",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "./bin/cli.js",
8
8
  "exports": {
9
- ".": "./bin/cli.js"
9
+ ".": "./bin/cli.js",
10
+ "./lib": "./lib.js"
10
11
  },
11
12
  "bin": {
12
13
  "code-graph": "./bin/cli.js"
@@ -1,37 +0,0 @@
1
- const addNode = (graph, node) => {
2
- graph.nodesById[node.id] = node;
3
- return graph;
4
- };
5
- const getEdgeKey = (edge) => {
6
- return `${edge.source}|${edge.target}|${edge.type}`;
7
- };
8
- const addEdge = (graph, edge) => {
9
- const edgeKey = getEdgeKey(edge);
10
- const sourceEdges = graph.edgesBySource[edge.source];
11
- if (sourceEdges) {
12
- const sourceEdgeKeys = new Set(sourceEdges.map(getEdgeKey));
13
- if (sourceEdgeKeys.has(edgeKey)) {
14
- return graph;
15
- }
16
- }
17
- const targetEdges = graph.edgesByTarget[edge.target];
18
- if (targetEdges) {
19
- const targetEdgeKeys = new Set(targetEdges.map(getEdgeKey));
20
- if (targetEdgeKeys.has(edgeKey)) {
21
- return graph;
22
- }
23
- }
24
- if (!graph.edgesBySource[edge.source]) {
25
- graph.edgesBySource[edge.source] = [];
26
- }
27
- graph.edgesBySource[edge.source].push(edge);
28
- if (!graph.edgesByTarget[edge.target]) {
29
- graph.edgesByTarget[edge.target] = [];
30
- }
31
- graph.edgesByTarget[edge.target].push(edge);
32
- return graph;
33
- };
34
- export {
35
- addEdge,
36
- addNode
37
- };
@@ -1,131 +0,0 @@
1
- const STANDARD_NODE_PROPERTIES = {
2
- firstIdentifier: `helpers.getDescendantsBy(args.current, (node) => node.kind === args.ts.SyntaxKind.Identifier)[0]?.getText() ?? null`,
3
- initializer: `args.current.initializer ? args.current.initializer?.getText() : null`,
4
- name: `args.current.name?.getText() ?? null`,
5
- filePath: `args.sourceFile.fileName`,
6
- text: `args.current.getText()`,
7
- type: `(() => { try { const t = args.typeChecker.getTypeAtLocation(args.current); return t ? args.typeChecker.typeToString(t) : null; } catch { return null; } })()`
8
- };
9
- const SUPPORTED_RELATIONSHIPS = {
10
- // --- Traversal relationships ---
11
- HAS_DESCENDANTS: (labels) => labels.length > 0 ? `helpers.getDescendantsBy(args.current, (node) => ${buildKindFilter(labels)})` : `helpers.getDescendantsBy(args.current, () => true)`,
12
- HAS_ANCESTORS: (labels) => labels.length > 0 ? `helpers.getAncestorsBy(args.current, (node) => ${buildKindFilter(labels)})` : `helpers.getAncestorsBy(args.current, () => true)`,
13
- HAS_TYPE: () => `helpers.getType(args.current)`,
14
- HAS_NAME: () => `args.current.name ? [args.current.name] : []`,
15
- // --- Direct AST property relationships ---
16
- HAS_INITIALIZER: () => `args.current.initializer ? [args.current.initializer] : []`,
17
- HAS_PARAMETERS: () => `args.current.parameters ? [...args.current.parameters] : []`,
18
- HAS_EXPRESSION: () => `args.current.expression ? [args.current.expression] : []`,
19
- HAS_TYPE_ANNOTATION: () => `args.current.type ? [args.current.type] : []`,
20
- HAS_BODY: () => `args.current.body ? [args.current.body] : []`,
21
- HAS_MEMBERS: () => `args.current.members ? [...args.current.members] : []`,
22
- HAS_PROPERTIES: () => `args.current.properties ? [...args.current.properties] : []`,
23
- HAS_ARGUMENTS: () => `args.current.arguments ? [...args.current.arguments] : []`,
24
- HAS_DECORATORS: () => `args.ts.getDecorators(args.current) || []`,
25
- // --- Heritage relationships ---
26
- EXTENDS: () => `(() => { const c = (args.current.heritageClauses || []).find(c => c.token === args.ts.SyntaxKind.ExtendsKeyword); return c ? [...c.types] : []; })()`,
27
- IMPLEMENTS: () => `(() => { const c = (args.current.heritageClauses || []).find(c => c.token === args.ts.SyntaxKind.ImplementsKeyword); return c ? [...c.types] : []; })()`
28
- };
29
- const buildConfigFromQuery = (query) => {
30
- const nodeExtractors = {};
31
- const matchStatements = query.statements.filter(
32
- (s) => s.type === "MatchStatement"
33
- );
34
- const variableToLabels = {};
35
- for (const match of matchStatements) {
36
- for (const pattern of match.patterns) {
37
- if (pattern.variable && pattern.labels.length > 0) {
38
- variableToLabels[pattern.variable] = pattern.labels;
39
- }
40
- }
41
- }
42
- for (const match of matchStatements) {
43
- buildExtractorsFromMatch(match, nodeExtractors, variableToLabels);
44
- }
45
- return { nodeExtractors };
46
- };
47
- const resolveLabels = (pattern, variableToLabels) => {
48
- if (pattern.labels.length > 0)
49
- return pattern.labels;
50
- if (pattern.variable && variableToLabels[pattern.variable]) {
51
- return variableToLabels[pattern.variable];
52
- }
53
- return [];
54
- };
55
- const buildExtractorsFromMatch = (match, rootNodeExtractors, variableToLabels) => {
56
- const { patterns, relationships } = match;
57
- if (patterns.length === 0)
58
- return;
59
- const rootPattern = patterns[0];
60
- const rootLabels = resolveLabels(rootPattern, variableToLabels);
61
- for (const label of rootLabels) {
62
- rootNodeExtractors[label] ??= {
63
- properties: { ...STANDARD_NODE_PROPERTIES }
64
- };
65
- }
66
- if (!relationships || relationships.length === 0)
67
- return;
68
- let currentExtractors = rootNodeExtractors;
69
- for (let i = 0; i < relationships.length; i++) {
70
- const rel = relationships[i];
71
- const sourcePattern = patterns[i];
72
- const targetPattern = patterns[i + 1];
73
- if (!targetPattern)
74
- break;
75
- const edgeType = resolveEdgeType(rel.edgeType);
76
- const codeGenerator = getCodeGenerator(edgeType);
77
- const sourceLabels = resolveLabels(sourcePattern, variableToLabels);
78
- const targetLabels = resolveLabels(targetPattern, variableToLabels);
79
- const targetNodeExtractors = {};
80
- if (targetLabels.length === 0) {
81
- targetNodeExtractors["*"] = {
82
- properties: { ...STANDARD_NODE_PROPERTIES }
83
- };
84
- } else {
85
- for (const label of targetLabels) {
86
- targetNodeExtractors[label] = {
87
- properties: { ...STANDARD_NODE_PROPERTIES }
88
- };
89
- }
90
- }
91
- for (const sourceLabel of sourceLabels) {
92
- currentExtractors[sourceLabel] ??= {
93
- properties: { ...STANDARD_NODE_PROPERTIES }
94
- };
95
- currentExtractors[sourceLabel].relationships ??= {};
96
- currentExtractors[sourceLabel].relationships[edgeType] = {
97
- extractorCode: codeGenerator(targetLabels),
98
- nodeExtractors: targetNodeExtractors
99
- };
100
- }
101
- currentExtractors = targetNodeExtractors;
102
- }
103
- };
104
- const resolveEdgeType = (edgeType) => {
105
- if (!edgeType) {
106
- throw new Error(
107
- `Relationship type is required in auto-config mode. Supported: ${Object.keys(SUPPORTED_RELATIONSHIPS).join(", ")}`
108
- );
109
- }
110
- if (Array.isArray(edgeType)) {
111
- throw new Error(
112
- `Union relationship types are not supported in auto-config. Got: ${edgeType.join("|")}`
113
- );
114
- }
115
- return edgeType;
116
- };
117
- const getCodeGenerator = (edgeType) => {
118
- const generator = SUPPORTED_RELATIONSHIPS[edgeType];
119
- if (!generator) {
120
- throw new Error(
121
- `Unsupported relationship type: "${edgeType}". Auto-config supports: ${Object.keys(SUPPORTED_RELATIONSHIPS).join(", ")}`
122
- );
123
- }
124
- return generator;
125
- };
126
- const buildKindFilter = (labels) => {
127
- return labels.map((l) => `node.kind === args.ts.SyntaxKind.${l}`).join(" || ");
128
- };
129
- export {
130
- buildConfigFromQuery
131
- };
@@ -1,27 +0,0 @@
1
- function executeExtractor(code, context) {
2
- try {
3
- const fn = new Function(
4
- ...Object.keys(context),
5
- `
6
- return ${code}
7
- `
8
- );
9
- return fn(...Object.values(context));
10
- } catch (error) {
11
- throw new Error(`Extractor execution failed: ${error.message}`);
12
- }
13
- }
14
- function extractNodeProperties(context, propertyExectorMap = {}) {
15
- const properties = {};
16
- for (const [propertyName, extractorCode] of Object.entries(
17
- propertyExectorMap
18
- )) {
19
- const value = executeExtractor(extractorCode, context);
20
- properties[propertyName] = value;
21
- }
22
- return properties;
23
- }
24
- export {
25
- executeExtractor,
26
- extractNodeProperties
27
- };
@@ -1 +0,0 @@
1
- export * from "./extractor.js";
@@ -1,49 +0,0 @@
1
- import * as ts from "typescript";
2
- import {
3
- getAncestorsBy,
4
- getDescendantsBy,
5
- getDescendantsByKind,
6
- getSolutionSourceFiles
7
- } from "../../codegular/index.js";
8
- import { processNode } from "./node.processor.js";
9
- const buildCodeGraph = (program, config) => {
10
- const codeGraph = {
11
- nodesById: {},
12
- edgesBySource: {},
13
- edgesByTarget: {}
14
- };
15
- const sourceFiles = getSolutionSourceFiles(program);
16
- sourceFiles.forEach((sourceFile) => {
17
- Object.keys(config.nodeExtractors).forEach((kindName) => {
18
- const nodes = getDescendantsByKind(sourceFile, ts.SyntaxKind[kindName]);
19
- nodes.forEach((node) => {
20
- const extractorContext = {
21
- args: {
22
- current: node,
23
- sourceFile,
24
- typeChecker: program.getTypeChecker(),
25
- ts
26
- },
27
- helpers: {
28
- getDescendantsBy,
29
- getAncestorsBy,
30
- getType: (node2) => []
31
- // TODO: add type extraction
32
- // getType(
33
- // node,
34
- // program.getTypeChecker(),
35
- // new TypeResolutionTracker(),
36
- // ),
37
- // getDeclarations: (node: ts.Type | ts.Node) =>
38
- // getDeclarations(node, context.typeChecker),
39
- }
40
- };
41
- processNode(extractorContext, config.nodeExtractors, codeGraph);
42
- });
43
- });
44
- });
45
- return codeGraph;
46
- };
47
- export {
48
- buildCodeGraph
49
- };
@@ -1 +0,0 @@
1
- export * from "./code-graph.builder.js";
@@ -1,22 +0,0 @@
1
- import { addNode } from "../code.graph.js";
2
- import {
3
- extractNodeProperties
4
- } from "../extractors/index.js";
5
- import { generateNodeId, getSyntaxKindName } from "../utils.js";
6
- import { processRelationships } from "./relationship.processor.js";
7
- const processNode = (context, nodeExtractors, codeGraph) => {
8
- const nodeId = generateNodeId(context.args.current);
9
- const kindName = getSyntaxKindName(context.args.current.kind);
10
- const nodeConfig = nodeExtractors[kindName] ?? nodeExtractors["*"];
11
- const graphNode = {
12
- ...nodeConfig && nodeConfig.properties ? extractNodeProperties(context, nodeConfig.properties) : {},
13
- id: nodeId,
14
- labels: [kindName]
15
- };
16
- addNode(codeGraph, graphNode);
17
- processRelationships(nodeId, context, nodeConfig, codeGraph);
18
- return graphNode;
19
- };
20
- export {
21
- processNode
22
- };
@@ -1,55 +0,0 @@
1
- import { addEdge } from "../code.graph.js";
2
- import { executeExtractor } from "../extractors/index.js";
3
- import { processNode } from "./node.processor.js";
4
- import { processType } from "./type.processor.js";
5
- function isTsNode(obj) {
6
- return obj && "kind" in obj && typeof obj.kind === "number";
7
- }
8
- function isTsType(obj) {
9
- return obj && "flags" in obj && typeof obj.flags === "number" && !("kind" in obj);
10
- }
11
- const processRelationships = (parentId, context, nodeConfig, codeGraph) => {
12
- if (nodeConfig?.relationships) {
13
- for (const relationshipName of Object.keys(nodeConfig.relationships)) {
14
- const relationshipExtractorFnCode = nodeConfig.relationships[relationshipName].extractorCode;
15
- const relationshipNodeExtractors = nodeConfig.relationships[relationshipName].nodeExtractors;
16
- Object.keys(relationshipNodeExtractors).forEach((label) => {
17
- const children = executeExtractor(relationshipExtractorFnCode, context);
18
- children.forEach(
19
- (child) => {
20
- if (isTsType(child)) {
21
- const childNode = processType(
22
- { ...context, args: { ...context.args, current: child } },
23
- relationshipNodeExtractors,
24
- codeGraph
25
- );
26
- addEdge(codeGraph, {
27
- source: parentId,
28
- target: childNode.id,
29
- type: relationshipName
30
- });
31
- } else if (isTsNode(child)) {
32
- const childNode = processNode(
33
- { ...context, args: { ...context.args, current: child } },
34
- relationshipNodeExtractors,
35
- codeGraph
36
- );
37
- addEdge(codeGraph, {
38
- source: parentId,
39
- target: childNode.id,
40
- type: relationshipName
41
- });
42
- } else {
43
- throw new Error(
44
- `The code provided: ${relationshipExtractorFnCode} returned an invalid child: ${child}. We support only ts.Node and ts.Type array returns from executed code`
45
- );
46
- }
47
- }
48
- );
49
- });
50
- }
51
- }
52
- };
53
- export {
54
- processRelationships
55
- };
@@ -1,21 +0,0 @@
1
- import { addNode } from "../code.graph.js";
2
- import { extractNodeProperties } from "../extractors/index.js";
3
- import { processRelationships } from "./relationship.processor.js";
4
- const processType = (context, nodeExtractors, codeGraph) => {
5
- const nodeId = context.args.typeChecker.typeToString(
6
- context.args.current
7
- );
8
- const kindName = "Type";
9
- const nodeConfig = nodeExtractors[kindName];
10
- const graphNode = {
11
- ...nodeConfig && nodeConfig.properties ? extractNodeProperties(context, nodeConfig.properties) : {},
12
- id: nodeId,
13
- labels: [kindName]
14
- };
15
- addNode(codeGraph, graphNode);
16
- processRelationships(nodeId, context, nodeConfig, codeGraph);
17
- return graphNode;
18
- };
19
- export {
20
- processType
21
- };
@@ -1,4 +0,0 @@
1
- export * from "./config-from-query.js";
2
- export * from "./extractors/index.js";
3
- export * from "./graph-builder/index.js";
4
- export * from "./tools/build-code-graph.tool.js";
@@ -1,19 +0,0 @@
1
- import { writeFileSync } from "fs";
2
- import { createProgramFromTsConfig } from "../../codegular/index.js";
3
- import { buildCodeGraph } from "../graph-builder/index.js";
4
- async function buildCodeGraphTool(tsConfigPath, config) {
5
- const program = createProgramFromTsConfig(tsConfigPath);
6
- const graph = buildCodeGraph(program, config);
7
- const nodeCount = Object.keys(graph.nodesById).length;
8
- const edgeCount = Object.values(graph.edgesBySource).flat().length;
9
- const graphPath = tsConfigPath.replace("tsconfig.json", "code-graph.json");
10
- writeFileSync(graphPath, JSON.stringify(graph, null, 2));
11
- return {
12
- graphPath,
13
- nodeCount,
14
- edgeCount
15
- };
16
- }
17
- export {
18
- buildCodeGraphTool
19
- };
@@ -1,34 +0,0 @@
1
- import ts from "typescript";
2
- const getSyntaxKindName = (kind) => {
3
- return ts.SyntaxKind[kind];
4
- };
5
- const generateNodeId = (n) => {
6
- const s = n.getSourceFile();
7
- const start = s.getLineAndCharacterOfPosition(n.getStart(s));
8
- const end = s.getLineAndCharacterOfPosition(n.getEnd());
9
- return `${s.fileName}.${start.line}.${start.character}.${end.line}.${end.character}`;
10
- };
11
- const extractFromNodeId = (nodeId) => {
12
- const parts = nodeId.split(".");
13
- const endCharacter = parts.pop();
14
- const endLine = parts.pop();
15
- const startCharacter = parts.pop();
16
- const startLine = parts.pop();
17
- const filePath = parts.join(".");
18
- return {
19
- filePath,
20
- start: {
21
- line: parseInt(startLine),
22
- character: parseInt(startCharacter)
23
- },
24
- end: {
25
- line: parseInt(endLine),
26
- character: parseInt(endCharacter)
27
- }
28
- };
29
- };
30
- export {
31
- extractFromNodeId,
32
- generateNodeId,
33
- getSyntaxKindName
34
- };
@@ -1,5 +0,0 @@
1
- export * from "./node.js";
2
- export * from "./program.js";
3
- export * from "./string.js";
4
- export * from "./type-checker.js";
5
- export * from "./utils.js";
package/codegular/node.js DELETED
@@ -1,71 +0,0 @@
1
- import * as ts from "typescript";
2
- import { getNameByIdentifier } from "./string.js";
3
- const { forEachChild, SyntaxKind } = ts;
4
- const hasKind = (kinds) => (child) => kinds.includes(child.kind);
5
- const hasName = (names) => (child) => names.includes(getNameByIdentifier(child));
6
- const hasDecorator = (decoratorName) => (child) => findByDecorator(child, decoratorName) !== void 0;
7
- const hasAnyDecoratorName = (node, decoratorNames) => {
8
- const decorators = getChildrenBy(node, hasKind([SyntaxKind.Decorator]));
9
- return decorators.find((d) => {
10
- return getChildrenBy(d, hasKind([SyntaxKind.CallExpression])).find(
11
- (callExpr) => {
12
- return decoratorNames.includes(getNameByIdentifier(callExpr));
13
- }
14
- ) !== void 0;
15
- }) !== void 0;
16
- };
17
- const every = () => true;
18
- function getChildrenBy(node, findFunc = every) {
19
- const elements = [];
20
- forEachChild(node, (child) => {
21
- if (!findFunc(child)) {
22
- return;
23
- }
24
- elements.push(child);
25
- });
26
- return elements;
27
- }
28
- function findChildOrThrow(node, findFunc) {
29
- let element;
30
- forEachChild(node, (child) => {
31
- if (element)
32
- return;
33
- if (findFunc(child)) {
34
- element = child;
35
- return;
36
- }
37
- });
38
- if (element === void 0) {
39
- throw new Error("Could not find child");
40
- }
41
- return element;
42
- }
43
- const getDecoratorName = (d) => {
44
- return getNameByIdentifier(
45
- getChildrenBy(d, hasKind([SyntaxKind.CallExpression]))[0]
46
- );
47
- };
48
- const findByDecorator = (node, decoratorName) => {
49
- const decorators = getChildrenBy(node, hasKind([SyntaxKind.Decorator]));
50
- if (decorators.length === 0) {
51
- return void 0;
52
- }
53
- return decorators.find((d) => {
54
- return getChildrenBy(d, hasKind([SyntaxKind.CallExpression])).find(
55
- (callExpr) => {
56
- return getNameByIdentifier(callExpr) === decoratorName;
57
- }
58
- ) !== void 0;
59
- });
60
- };
61
- export {
62
- every,
63
- findByDecorator,
64
- findChildOrThrow,
65
- getChildrenBy,
66
- getDecoratorName,
67
- hasAnyDecoratorName,
68
- hasDecorator,
69
- hasKind,
70
- hasName
71
- };
@@ -1,100 +0,0 @@
1
- import * as path from "path";
2
- import * as ts from "typescript";
3
- const createSourceFileFromContent = (fileName, content) => {
4
- return ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, true);
5
- };
6
- const createProgramFromFileSystem = (fileSystem) => {
7
- const compilerOptions = {
8
- target: ts.ScriptTarget.ES2020,
9
- module: ts.ModuleKind.CommonJS,
10
- moduleResolution: ts.ModuleResolutionKind.NodeJs,
11
- allowSyntheticDefaultImports: true,
12
- esModuleInterop: true,
13
- skipLibCheck: true,
14
- lib: ["ES2020", "DOM"]
15
- };
16
- const compilerHost = ts.createCompilerHost(compilerOptions);
17
- const originalGetSourceFile = compilerHost.getSourceFile;
18
- compilerHost.getSourceFile = (fileName, languageVersion) => {
19
- if (fileSystem[fileName]) {
20
- return ts.createSourceFile(
21
- fileName,
22
- fileSystem[fileName],
23
- languageVersion,
24
- true
25
- );
26
- }
27
- return originalGetSourceFile(fileName, languageVersion);
28
- };
29
- const fileNames = Object.keys(fileSystem);
30
- return ts.createProgram(fileNames, compilerOptions, compilerHost);
31
- };
32
- const createHybridProgram = (generatedFiles, options) => {
33
- const rootPath = path.resolve(options?.workspaceRoot ?? process.cwd());
34
- const fileSystem = {};
35
- for (const { filePath, code } of generatedFiles) {
36
- const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(rootPath, filePath);
37
- fileSystem[absolutePath] = code;
38
- }
39
- const rootNames = Object.keys(fileSystem).filter(
40
- (p) => p.endsWith(".ts")
41
- );
42
- const compilerOptions = {
43
- target: ts.ScriptTarget.ES2020,
44
- module: ts.ModuleKind.ESNext,
45
- moduleResolution: ts.ModuleResolutionKind.Node10,
46
- allowSyntheticDefaultImports: true,
47
- esModuleInterop: true,
48
- skipLibCheck: true,
49
- lib: ["ES2020", "DOM"],
50
- strict: true
51
- };
52
- const compilerHost = ts.createCompilerHost(compilerOptions);
53
- const originalGetSourceFile = compilerHost.getSourceFile;
54
- compilerHost.getCurrentDirectory = () => rootPath;
55
- compilerHost.getSourceFile = (fileName, languageVersion) => {
56
- const normalized = path.normalize(fileName);
57
- const content = fileSystem[normalized] ?? fileSystem[fileName] ?? fileSystem[path.resolve(rootPath, fileName)];
58
- if (content !== void 0) {
59
- return ts.createSourceFile(
60
- fileName,
61
- content,
62
- languageVersion,
63
- true
64
- );
65
- }
66
- return originalGetSourceFile.call(
67
- compilerHost,
68
- fileName,
69
- languageVersion
70
- );
71
- };
72
- return ts.createProgram(rootNames, compilerOptions, compilerHost);
73
- };
74
- const createProgramFromTsConfig = (configPath) => {
75
- const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
76
- if (configFile.error) {
77
- const errorMessage = ts.formatDiagnostic(configFile.error, {
78
- getCurrentDirectory: () => process.cwd(),
79
- getNewLine: () => "\n",
80
- getCanonicalFileName: (fileName) => fileName
81
- });
82
- throw new Error(`Error reading tsconfig at ${configPath}: ${errorMessage}`);
83
- }
84
- const parsedConfig = ts.parseJsonConfigFileContent(
85
- configFile.config,
86
- ts.sys,
87
- path.dirname(configPath)
88
- );
89
- return ts.createProgram(
90
- parsedConfig.fileNames,
91
- parsedConfig.options,
92
- ts.createCompilerHost(parsedConfig.options)
93
- );
94
- };
95
- export {
96
- createHybridProgram,
97
- createProgramFromFileSystem,
98
- createProgramFromTsConfig,
99
- createSourceFileFromContent
100
- };