@nu-art/build-and-install 0.401.0 → 0.401.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/BuildAndInstall.d.ts +40 -0
- package/BuildAndInstall.js +155 -0
- package/build-and-install-v3.d.ts +1 -44
- package/build-and-install-v3.js +1 -157
- package/build-and-install.js +11 -11
- package/config/consts.d.ts +43 -0
- package/config/consts.js +42 -0
- package/{core → config}/package/consts.d.ts +1 -1
- package/{core → config}/types/project-config.d.ts +3 -0
- package/core/FilesCache.d.ts +50 -0
- package/core/FilesCache.js +76 -0
- package/core/Unit_HelpPrinter.d.ts +16 -0
- package/core/Unit_HelpPrinter.js +47 -0
- package/core/params/params.d.ts +1 -41
- package/core/params/params.js +1 -332
- package/core/params.d.ts +50 -0
- package/core/params.js +441 -0
- package/{v3/core → core}/types.d.ts +1 -1
- package/{v3/UnitsDependencyMapper → dependencies}/UnitsDependencyMapper.d.ts +21 -1
- package/{v3/UnitsDependencyMapper → dependencies}/UnitsDependencyMapper.js +26 -3
- package/dependencies/types.d.ts +1 -0
- package/dependencies/types.js +1 -0
- package/exceptions/PhaseAggregatedException.d.ts +34 -0
- package/{core/exceptions → exceptions}/PhaseAggregatedException.js +26 -0
- package/exceptions/UnitPhaseException.d.ts +20 -0
- package/exceptions/UnitPhaseException.js +21 -0
- package/exports/ExportIndexCache.d.ts +25 -0
- package/exports/ExportIndexCache.js +115 -0
- package/exports/ExportMapper.d.ts +43 -0
- package/exports/ExportMapper.js +519 -0
- package/exports/IndicesMcpServer.d.ts +22 -0
- package/exports/IndicesMcpServer.js +220 -0
- package/exports/types.js +3 -0
- package/package.json +20 -9
- package/phases/PhaseManager.d.ts +130 -0
- package/{v3 → phases}/PhaseManager.js +99 -2
- package/{v3/phase → phases/definitions}/consts.d.ts +36 -0
- package/{v3/phase → phases/definitions}/consts.js +44 -2
- package/phases/definitions/types.d.ts +40 -0
- package/phases/index.d.ts +2 -0
- package/phases/index.js +2 -0
- package/run.js +10 -0
- package/runtime/RunningStatusHandler.d.ts +104 -0
- package/runtime/RunningStatusHandler.js +153 -0
- package/runtime/types.d.ts +1 -0
- package/runtime/types.js +2 -0
- package/{defaults → templates}/consts.d.ts +9 -0
- package/{defaults → templates}/consts.js +12 -2
- package/templates/firebase/functions/cloudbuild.yaml +17 -0
- package/templates/firebase/functions/dockerfile +19 -0
- package/templates/firebase/functions/service.yaml +49 -0
- package/{v3/units → units/base}/BaseUnit.d.ts +34 -4
- package/{v3/units → units/base}/BaseUnit.js +22 -2
- package/units/base/ProjectUnit.d.ts +32 -0
- package/units/base/ProjectUnit.js +25 -0
- package/units/base/types.js +1 -0
- package/units/discovery/UnitsMapper.d.ts +69 -0
- package/{v3/UnitsMapper → units/discovery}/UnitsMapper.js +50 -2
- package/units/discovery/resolvers/UnitMapper_Base.d.ts +65 -0
- package/units/discovery/resolvers/UnitMapper_Base.js +46 -0
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_FirebaseFunction.d.ts +5 -3
- package/units/discovery/resolvers/UnitMapper_FirebaseFunction.js +105 -0
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_FirebaseHosting.d.ts +3 -2
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_FirebaseHosting.js +14 -10
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_Node.d.ts +1 -1
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_Node.js +2 -2
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeLib.d.ts +24 -1
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeLib.js +24 -1
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeProject.d.ts +22 -1
- package/{v3/UnitsMapper → units/discovery}/resolvers/UnitMapper_NodeProject.js +22 -1
- package/units/discovery/types.js +1 -0
- package/units/implementations/Unit_NodeProject.d.ts +59 -0
- package/{v3/units → units/implementations}/Unit_NodeProject.js +65 -5
- package/units/implementations/Unit_PackageJson.d.ts +56 -0
- package/{v3/units → units/implementations}/Unit_PackageJson.js +39 -3
- package/{v3/units → units/implementations}/Unit_TypescriptLib.d.ts +40 -4
- package/{v3/units → units/implementations}/Unit_TypescriptLib.js +167 -17
- package/units/implementations/firebase/Unit_FirebaseFunctionsApp.d.ts +233 -0
- package/units/implementations/firebase/Unit_FirebaseFunctionsApp.js +804 -0
- package/units/implementations/firebase/Unit_FirebaseHostingApp.d.ts +113 -0
- package/units/implementations/firebase/Unit_FirebaseHostingApp.js +320 -0
- package/units/implementations/firebase/common.d.ts +26 -0
- package/units/implementations/firebase/common.js +65 -0
- package/units/index.d.ts +6 -0
- package/units/index.js +6 -0
- package/v3/core/Unit_HelpPrinter.d.ts +1 -16
- package/v3/core/Unit_HelpPrinter.js +1 -47
- package/{v3 → workspace}/Workspace.d.ts +30 -15
- package/{v3 → workspace}/Workspace.js +48 -35
- package/core/consts.d.ts +0 -13
- package/core/consts.js +0 -12
- package/core/exceptions/PhaseAggregatedException.d.ts +0 -8
- package/core/exceptions/UnitPhaseException.d.ts +0 -5
- package/core/exceptions/UnitPhaseException.js +0 -6
- package/old/PhaseRunnerDispatcher.d.ts +0 -24
- package/old/PhaseRunnerDispatcher.js +0 -32
- package/old/runner-dispatchers.d.ts +0 -10
- package/old/runner-dispatchers.js +0 -3
- package/v3/PhaseManager.d.ts +0 -27
- package/v3/RunningStatusHandler.d.ts +0 -18
- package/v3/RunningStatusHandler.js +0 -67
- package/v3/UnitsMapper/UnitsMapper.d.ts +0 -21
- package/v3/UnitsMapper/resolvers/UnitMapper_Base.d.ts +0 -23
- package/v3/UnitsMapper/resolvers/UnitMapper_Base.js +0 -16
- package/v3/UnitsMapper/resolvers/UnitMapper_FirebaseFunction.js +0 -66
- package/v3/core/FilesCache.d.ts +0 -7
- package/v3/core/FilesCache.js +0 -33
- package/v3/phase/types.d.ts +0 -10
- package/v3/units/ProjectUnit.d.ts +0 -18
- package/v3/units/ProjectUnit.js +0 -11
- package/v3/units/Unit_NodeProject.d.ts +0 -30
- package/v3/units/Unit_PackageJson.d.ts +0 -17
- package/v3/units/firebase/Unit_FirebaseFunctionsApp.d.ts +0 -64
- package/v3/units/firebase/Unit_FirebaseFunctionsApp.js +0 -306
- package/v3/units/firebase/Unit_FirebaseHostingApp.d.ts +0 -49
- package/v3/units/firebase/Unit_FirebaseHostingApp.js +0 -118
- package/v3/units/firebase/common.d.ts +0 -3
- package/v3/units/firebase/common.js +0 -13
- package/v3/units/index.d.ts +0 -6
- package/v3/units/index.js +0 -6
- /package/{core → config}/package/consts.js +0 -0
- /package/{core → config}/types/configs/firebasejson.d.ts +0 -0
- /package/{core → config}/types/configs/firebasejson.js +0 -0
- /package/{core → config}/types/configs/firebaserc.d.ts +0 -0
- /package/{core → config}/types/configs/firebaserc.js +0 -0
- /package/{core → config}/types/configs/index.d.ts +0 -0
- /package/{core → config}/types/configs/index.js +0 -0
- /package/{core → config}/types/configs/package-json.d.ts +0 -0
- /package/{core → config}/types/configs/package-json.js +0 -0
- /package/{core → config}/types/core.d.ts +0 -0
- /package/{core → config}/types/core.js +0 -0
- /package/{core → config}/types/index.d.ts +0 -0
- /package/{core → config}/types/index.js +0 -0
- /package/{core → config}/types/package/index.d.ts +0 -0
- /package/{core → config}/types/package/index.js +0 -0
- /package/{core → config}/types/package/package.d.ts +0 -0
- /package/{core → config}/types/package/package.js +0 -0
- /package/{core → config}/types/package/runtime-package.d.ts +0 -0
- /package/{core → config}/types/package/runtime-package.js +0 -0
- /package/{core → config}/types/project-config.js +0 -0
- /package/{v3/core → core}/types.js +0 -0
- /package/{v3/UnitsMapper/types.js → exports/types.d.ts} +0 -0
- /package/{v3/phase → phases/definitions}/index.d.ts +0 -0
- /package/{v3/phase → phases/definitions}/index.js +0 -0
- /package/{v3/phase → phases/definitions}/types.js +0 -0
- /package/{v3/units/types.js → run.d.ts} +0 -0
- /package/{defaults/backend-proxy → templates/backend/proxy}/proxy._ts +0 -0
- /package/{defaults/.firebase_config → templates/firebase/config}/database.rules.json +0 -0
- /package/{defaults/.firebase_config → templates/firebase/config}/firestore.indexes.json +0 -0
- /package/{defaults/.firebase_config → templates/firebase/config}/firestore.rules +0 -0
- /package/{defaults/.firebase_config → templates/firebase/config}/storage.rules +0 -0
- /package/{v3/units → units/base}/types.d.ts +0 -0
- /package/{v3/UnitsMapper → units/discovery}/resolvers/index.d.ts +0 -0
- /package/{v3/UnitsMapper → units/discovery}/resolvers/index.js +0 -0
- /package/{v3/UnitsMapper → units/discovery}/types.d.ts +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { resolve as pathResolve } from 'path';
|
|
2
|
+
import { FileSystemUtils } from '@nu-art/ts-common/utils/FileSystemUtils';
|
|
3
|
+
import { FilesCache } from '../core/FilesCache.js';
|
|
4
|
+
import { promises as fs } from 'fs';
|
|
5
|
+
import { glob } from 'node:fs/promises';
|
|
6
|
+
const cache = new Map();
|
|
7
|
+
export const ExportIndexCache = {
|
|
8
|
+
getIndexPath(projectRoot, packageName) {
|
|
9
|
+
return pathResolve(projectRoot, '.trash', 'indices', packageName);
|
|
10
|
+
},
|
|
11
|
+
async load(projectRoot, packageRoot, packageName) {
|
|
12
|
+
const cacheKey = packageRoot;
|
|
13
|
+
const cached = cache.get(cacheKey);
|
|
14
|
+
// Check if we need to reload based on index file mtime
|
|
15
|
+
const indexPath = ExportIndexCache.getIndexPath(projectRoot, packageName);
|
|
16
|
+
const indexFilePath = pathResolve(indexPath, '_export-for-import.json');
|
|
17
|
+
if (!await FileSystemUtils.file.exists(indexFilePath)) {
|
|
18
|
+
throw new Error(`Index file not found: ${indexFilePath}. Run 'bai --map-exports' to generate indices.`);
|
|
19
|
+
}
|
|
20
|
+
const indexStat = await fs.stat(indexFilePath);
|
|
21
|
+
const currentIndexMtime = indexStat.mtimeMs;
|
|
22
|
+
// If cached and mtime matches, return cached
|
|
23
|
+
if (cached && cached.indexMtime === currentIndexMtime) {
|
|
24
|
+
return cached;
|
|
25
|
+
}
|
|
26
|
+
// Load index files
|
|
27
|
+
const exports = await FilesCache.load.json(indexFilePath);
|
|
28
|
+
const byNameData = await FilesCache.load.json(pathResolve(indexPath, '_export-index-by-name.json'));
|
|
29
|
+
const byFileData = await FilesCache.load.json(pathResolve(indexPath, '_export-index-by-file.json'));
|
|
30
|
+
const byTypeData = await FilesCache.load.json(pathResolve(indexPath, '_export-index-by-type.json'));
|
|
31
|
+
// Convert to Maps for faster lookups
|
|
32
|
+
const byName = new Map();
|
|
33
|
+
for (const [name, symbol] of Object.entries(byNameData)) {
|
|
34
|
+
byName.set(name, symbol);
|
|
35
|
+
}
|
|
36
|
+
const byFile = new Map();
|
|
37
|
+
for (const [filePath, symbols] of Object.entries(byFileData)) {
|
|
38
|
+
byFile.set(filePath, symbols);
|
|
39
|
+
}
|
|
40
|
+
const byType = new Map();
|
|
41
|
+
for (const [type, symbols] of Object.entries(byTypeData)) {
|
|
42
|
+
byType.set(type, symbols);
|
|
43
|
+
}
|
|
44
|
+
// Calculate max source file mtime
|
|
45
|
+
const sourceMtime = await ExportIndexCache.calculateSourceMtime(packageRoot);
|
|
46
|
+
const cachedIndex = {
|
|
47
|
+
exports,
|
|
48
|
+
byName,
|
|
49
|
+
byFile,
|
|
50
|
+
byType,
|
|
51
|
+
indexMtime: currentIndexMtime,
|
|
52
|
+
sourceMtime,
|
|
53
|
+
packageRoot,
|
|
54
|
+
packageName,
|
|
55
|
+
projectRoot
|
|
56
|
+
};
|
|
57
|
+
cache.set(cacheKey, cachedIndex);
|
|
58
|
+
return cachedIndex;
|
|
59
|
+
},
|
|
60
|
+
async calculateSourceMtime(packageRoot) {
|
|
61
|
+
const srcMainTs = `${packageRoot}/src/main/**/*.ts`;
|
|
62
|
+
const srcMainTsx = `${packageRoot}/src/main/**/*.tsx`;
|
|
63
|
+
let maxMtime = 0;
|
|
64
|
+
try {
|
|
65
|
+
for await (const file of glob(srcMainTs, {})) {
|
|
66
|
+
const stat = await fs.stat(file);
|
|
67
|
+
maxMtime = Math.max(maxMtime, stat.mtimeMs);
|
|
68
|
+
}
|
|
69
|
+
for await (const file of glob(srcMainTsx, {})) {
|
|
70
|
+
const stat = await fs.stat(file);
|
|
71
|
+
maxMtime = Math.max(maxMtime, stat.mtimeMs);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
// If source files don't exist, return 0
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
return maxMtime;
|
|
79
|
+
},
|
|
80
|
+
async isStale(projectRoot, packageRoot, packageName) {
|
|
81
|
+
const indexPath = ExportIndexCache.getIndexPath(projectRoot, packageName);
|
|
82
|
+
const indexFilePath = pathResolve(indexPath, '_export-for-import.json');
|
|
83
|
+
if (!await FileSystemUtils.file.exists(indexFilePath)) {
|
|
84
|
+
return true; // No index file means it's stale
|
|
85
|
+
}
|
|
86
|
+
const indexStat = await fs.stat(indexFilePath);
|
|
87
|
+
const indexMtime = indexStat.mtimeMs;
|
|
88
|
+
const sourceMtime = await ExportIndexCache.calculateSourceMtime(packageRoot);
|
|
89
|
+
// Stale if any source file is newer than index file
|
|
90
|
+
return sourceMtime > indexMtime;
|
|
91
|
+
},
|
|
92
|
+
async getByName(projectRoot, packageRoot, packageName, symbolName) {
|
|
93
|
+
const cached = await ExportIndexCache.load(projectRoot, packageRoot, packageName);
|
|
94
|
+
return cached.byName.get(symbolName) || null;
|
|
95
|
+
},
|
|
96
|
+
async getByFile(projectRoot, packageRoot, packageName, filePath) {
|
|
97
|
+
const cached = await ExportIndexCache.load(projectRoot, packageRoot, packageName);
|
|
98
|
+
return cached.byFile.get(filePath) || [];
|
|
99
|
+
},
|
|
100
|
+
async getByType(projectRoot, packageRoot, packageName, symbolType) {
|
|
101
|
+
const cached = await ExportIndexCache.load(projectRoot, packageRoot, packageName);
|
|
102
|
+
return cached.byType.get(symbolType) || [];
|
|
103
|
+
},
|
|
104
|
+
async getAll(projectRoot, packageRoot, packageName) {
|
|
105
|
+
const cached = await ExportIndexCache.load(projectRoot, packageRoot, packageName);
|
|
106
|
+
return cached.exports;
|
|
107
|
+
},
|
|
108
|
+
invalidate(projectRoot, packageRoot, packageName) {
|
|
109
|
+
const cacheKey = packageRoot;
|
|
110
|
+
cache.delete(cacheKey);
|
|
111
|
+
},
|
|
112
|
+
clear() {
|
|
113
|
+
cache.clear();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
export type ExportSymbol = {
|
|
3
|
+
name: string;
|
|
4
|
+
filePath: string;
|
|
5
|
+
line: number;
|
|
6
|
+
symbolType: 'function' | 'class' | 'interface' | 'type' | 'enum' | 'variable' | 'constant' | 'default' | 're-export';
|
|
7
|
+
signature: string | null;
|
|
8
|
+
typeInfo: string | null;
|
|
9
|
+
genericSignature: string | null;
|
|
10
|
+
parentClass: string | null;
|
|
11
|
+
interfaces: string[];
|
|
12
|
+
};
|
|
13
|
+
export type ExportError = {
|
|
14
|
+
level: 'package' | 'folder' | 'file' | 'symbol';
|
|
15
|
+
path: string;
|
|
16
|
+
error: string;
|
|
17
|
+
stack?: string;
|
|
18
|
+
timestamp: string;
|
|
19
|
+
retryable: boolean;
|
|
20
|
+
context?: Record<string, any>;
|
|
21
|
+
};
|
|
22
|
+
export declare class ExportMapper {
|
|
23
|
+
static getIndexPath(projectRoot: string, packageName: string): string;
|
|
24
|
+
static generateIndexFiles(projectRoot: string, packageName: string, exports: ExportSymbol[]): Promise<void>;
|
|
25
|
+
static mapExports(projectRoot: string, packageRoot: string, packageName: string, sourceFiles: string[], retryErrors?: ExportError[]): Promise<{
|
|
26
|
+
exports: ExportSymbol[];
|
|
27
|
+
errors: ExportError[];
|
|
28
|
+
}>;
|
|
29
|
+
static createProgram(sourceFiles: string[], packageRoot: string): ts.Program;
|
|
30
|
+
static extractExportsFromFile(sourceFile: ts.SourceFile, checker: ts.TypeChecker, packageRoot: string, errors: ExportError[], errorMap?: Map<string, ExportError>): ExportSymbol[];
|
|
31
|
+
static extractSymbolMetadata(node: ts.Node, sourceFile: ts.SourceFile, checker: ts.TypeChecker, packageRoot: string, errors: ExportError[], name: string, symbolType: ExportSymbol['symbolType'], errorMap?: Map<string, ExportError>): ExportSymbol | null;
|
|
32
|
+
static extractGenericSignatures(node: ts.Node, checker: ts.TypeChecker): string | null;
|
|
33
|
+
static extractClassInheritance(node: ts.ClassDeclaration, checker: ts.TypeChecker): {
|
|
34
|
+
parentClass: string | null;
|
|
35
|
+
interfaces: string[];
|
|
36
|
+
};
|
|
37
|
+
static hasExportModifier(node: ts.Node): boolean;
|
|
38
|
+
static getLineNumber(sourceFile: ts.SourceFile, node: ts.Node): number;
|
|
39
|
+
static getRelativePath(absolutePath: string, packageRoot: string): string;
|
|
40
|
+
static loadPreviousErrors(projectRoot: string, packageName: string): Promise<ExportError[] | null>;
|
|
41
|
+
static writeErrors(projectRoot: string, packageName: string, errors: ExportError[]): Promise<void>;
|
|
42
|
+
static shouldRetryError(error: ExportError, retryErrors?: ExportError[]): boolean;
|
|
43
|
+
}
|
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import { resolve as pathResolve } from 'path';
|
|
3
|
+
import { FileSystemUtils } from '@nu-art/ts-common/utils/FileSystemUtils';
|
|
4
|
+
import { __stringify } from '@nu-art/ts-common';
|
|
5
|
+
import { CONST_TS_CONFIG } from '../config/consts.js';
|
|
6
|
+
import { existsSync, readFileSync } from 'fs';
|
|
7
|
+
export class ExportMapper {
|
|
8
|
+
static getIndexPath(projectRoot, packageName) {
|
|
9
|
+
return pathResolve(projectRoot, '.trash', 'indices', packageName);
|
|
10
|
+
}
|
|
11
|
+
static async generateIndexFiles(projectRoot, packageName, exports) {
|
|
12
|
+
const indexPath = ExportMapper.getIndexPath(projectRoot, packageName);
|
|
13
|
+
// Ensure directory exists
|
|
14
|
+
await FileSystemUtils.folder.create(indexPath);
|
|
15
|
+
// Generate by-name index
|
|
16
|
+
const byName = {};
|
|
17
|
+
for (const exp of exports) {
|
|
18
|
+
byName[exp.name] = exp;
|
|
19
|
+
}
|
|
20
|
+
const byNamePath = pathResolve(indexPath, '_export-index-by-name.json');
|
|
21
|
+
await FileSystemUtils.file.write(byNamePath, __stringify(byName, true));
|
|
22
|
+
// Generate by-file index
|
|
23
|
+
const byFile = {};
|
|
24
|
+
for (const exp of exports) {
|
|
25
|
+
if (!byFile[exp.filePath]) {
|
|
26
|
+
byFile[exp.filePath] = [];
|
|
27
|
+
}
|
|
28
|
+
byFile[exp.filePath].push(exp);
|
|
29
|
+
}
|
|
30
|
+
const byFilePath = pathResolve(indexPath, '_export-index-by-file.json');
|
|
31
|
+
await FileSystemUtils.file.write(byFilePath, __stringify(byFile, true));
|
|
32
|
+
// Generate by-type index
|
|
33
|
+
const byType = {};
|
|
34
|
+
for (const exp of exports) {
|
|
35
|
+
if (!byType[exp.symbolType]) {
|
|
36
|
+
byType[exp.symbolType] = [];
|
|
37
|
+
}
|
|
38
|
+
byType[exp.symbolType].push(exp);
|
|
39
|
+
}
|
|
40
|
+
const byTypePath = pathResolve(indexPath, '_export-index-by-type.json');
|
|
41
|
+
await FileSystemUtils.file.write(byTypePath, __stringify(byType, true));
|
|
42
|
+
}
|
|
43
|
+
static async mapExports(projectRoot, packageRoot, packageName, sourceFiles, retryErrors) {
|
|
44
|
+
const errors = [];
|
|
45
|
+
const exports = [];
|
|
46
|
+
// Create error map for quick lookup
|
|
47
|
+
const errorMap = new Map();
|
|
48
|
+
if (retryErrors) {
|
|
49
|
+
for (const error of retryErrors) {
|
|
50
|
+
errorMap.set(error.path, error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Package level: Create TypeScript program
|
|
54
|
+
let program;
|
|
55
|
+
try {
|
|
56
|
+
program = ExportMapper.createProgram(sourceFiles, packageRoot);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
errors.push({
|
|
60
|
+
level: 'package',
|
|
61
|
+
path: packageRoot,
|
|
62
|
+
error: error.message || String(error),
|
|
63
|
+
stack: error.stack,
|
|
64
|
+
timestamp: new Date().toISOString(),
|
|
65
|
+
retryable: true,
|
|
66
|
+
context: { operation: 'createProgram' }
|
|
67
|
+
});
|
|
68
|
+
return { exports, errors };
|
|
69
|
+
}
|
|
70
|
+
const checker = program.getTypeChecker();
|
|
71
|
+
// File level: Process each source file
|
|
72
|
+
for (const sourceFile of program.getSourceFiles()) {
|
|
73
|
+
// Skip node_modules and declaration files
|
|
74
|
+
if (sourceFile.fileName.includes('node_modules') || sourceFile.fileName.endsWith('.d.ts')) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// Only process files in src/main
|
|
78
|
+
if (!sourceFile.fileName.includes('/src/main/')) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const filePath = ExportMapper.getRelativePath(sourceFile.fileName, packageRoot);
|
|
82
|
+
const fileErrorKey = filePath;
|
|
83
|
+
// Check if this file had a previous non-retryable error - skip those
|
|
84
|
+
// If retryable error exists, we'll process it (retry)
|
|
85
|
+
// If no previous error, process normally
|
|
86
|
+
if (errorMap.has(fileErrorKey)) {
|
|
87
|
+
const prevError = errorMap.get(fileErrorKey);
|
|
88
|
+
if (!prevError.retryable) {
|
|
89
|
+
// Skip non-retryable errors
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
// If retryable, continue to process (retry it)
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const fileExports = ExportMapper.extractExportsFromFile(sourceFile, checker, packageRoot, errors, errorMap);
|
|
96
|
+
exports.push(...fileExports);
|
|
97
|
+
// Remove from error map if successfully processed
|
|
98
|
+
if (errorMap.has(fileErrorKey)) {
|
|
99
|
+
errorMap.delete(fileErrorKey);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
errors.push({
|
|
104
|
+
level: 'file',
|
|
105
|
+
path: filePath,
|
|
106
|
+
error: error.message || String(error),
|
|
107
|
+
stack: error.stack,
|
|
108
|
+
timestamp: new Date().toISOString(),
|
|
109
|
+
retryable: true,
|
|
110
|
+
context: { fileName: sourceFile.fileName }
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Add any remaining errors from retry that weren't resolved
|
|
115
|
+
for (const error of errorMap.values()) {
|
|
116
|
+
errors.push(error);
|
|
117
|
+
}
|
|
118
|
+
return { exports, errors };
|
|
119
|
+
}
|
|
120
|
+
static createProgram(sourceFiles, packageRoot) {
|
|
121
|
+
const tsConfigPath = pathResolve(packageRoot, 'src/main', CONST_TS_CONFIG);
|
|
122
|
+
let compilerOptions = {};
|
|
123
|
+
// Try to load tsconfig.json synchronously
|
|
124
|
+
if (existsSync(tsConfigPath)) {
|
|
125
|
+
try {
|
|
126
|
+
const configFileText = readFileSync(tsConfigPath, 'utf8');
|
|
127
|
+
const configFile = ts.parseConfigFileTextToJson(tsConfigPath, configFileText);
|
|
128
|
+
if (configFile.config) {
|
|
129
|
+
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, pathResolve(packageRoot, 'src/main'));
|
|
130
|
+
compilerOptions = parsedConfig.options;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
// Use default options if config loading fails
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Default compiler options
|
|
138
|
+
compilerOptions = {
|
|
139
|
+
...compilerOptions,
|
|
140
|
+
allowJs: true,
|
|
141
|
+
skipLibCheck: true,
|
|
142
|
+
noEmit: true,
|
|
143
|
+
};
|
|
144
|
+
return ts.createProgram(sourceFiles, compilerOptions);
|
|
145
|
+
}
|
|
146
|
+
static extractExportsFromFile(sourceFile, checker, packageRoot, errors, errorMap) {
|
|
147
|
+
const exports = [];
|
|
148
|
+
const filePath = ExportMapper.getRelativePath(sourceFile.fileName, packageRoot);
|
|
149
|
+
const visit = (node) => {
|
|
150
|
+
// Check for export declarations
|
|
151
|
+
if (ts.isVariableStatement(node) && ExportMapper.hasExportModifier(node)) {
|
|
152
|
+
// Export variable statements
|
|
153
|
+
for (const declaration of node.declarationList.declarations) {
|
|
154
|
+
if (ts.isIdentifier(declaration.name)) {
|
|
155
|
+
const symbol = ExportMapper.extractSymbolMetadata(node, sourceFile, checker, packageRoot, errors, declaration.name.text, 'variable', errorMap);
|
|
156
|
+
if (symbol)
|
|
157
|
+
exports.push(symbol);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else if (ts.isFunctionDeclaration(node) && ExportMapper.hasExportModifier(node) && node.name) {
|
|
162
|
+
// Export function
|
|
163
|
+
const symbol = ExportMapper.extractSymbolMetadata(node, sourceFile, checker, packageRoot, errors, node.name.text, 'function', errorMap);
|
|
164
|
+
if (symbol)
|
|
165
|
+
exports.push(symbol);
|
|
166
|
+
}
|
|
167
|
+
else if (ts.isClassDeclaration(node) && ExportMapper.hasExportModifier(node) && node.name) {
|
|
168
|
+
// Export class
|
|
169
|
+
const symbol = ExportMapper.extractSymbolMetadata(node, sourceFile, checker, packageRoot, errors, node.name.text, 'class', errorMap);
|
|
170
|
+
if (symbol)
|
|
171
|
+
exports.push(symbol);
|
|
172
|
+
}
|
|
173
|
+
else if (ts.isInterfaceDeclaration(node) && ExportMapper.hasExportModifier(node)) {
|
|
174
|
+
// Export interface
|
|
175
|
+
const symbol = ExportMapper.extractSymbolMetadata(node, sourceFile, checker, packageRoot, errors, node.name.text, 'interface', errorMap);
|
|
176
|
+
if (symbol)
|
|
177
|
+
exports.push(symbol);
|
|
178
|
+
}
|
|
179
|
+
else if (ts.isTypeAliasDeclaration(node) && ExportMapper.hasExportModifier(node)) {
|
|
180
|
+
// Export type
|
|
181
|
+
const symbol = ExportMapper.extractSymbolMetadata(node, sourceFile, checker, packageRoot, errors, node.name.text, 'type', errorMap);
|
|
182
|
+
if (symbol)
|
|
183
|
+
exports.push(symbol);
|
|
184
|
+
}
|
|
185
|
+
else if (ts.isEnumDeclaration(node) && ExportMapper.hasExportModifier(node)) {
|
|
186
|
+
// Export enum
|
|
187
|
+
const symbol = ExportMapper.extractSymbolMetadata(node, sourceFile, checker, packageRoot, errors, node.name.text, 'enum', errorMap);
|
|
188
|
+
if (symbol)
|
|
189
|
+
exports.push(symbol);
|
|
190
|
+
}
|
|
191
|
+
else if (ts.isExportAssignment(node)) {
|
|
192
|
+
// Default export
|
|
193
|
+
const symbol = ExportMapper.extractSymbolMetadata(node, sourceFile, checker, packageRoot, errors, 'default', 'default', errorMap);
|
|
194
|
+
if (symbol)
|
|
195
|
+
exports.push(symbol);
|
|
196
|
+
}
|
|
197
|
+
else if (ts.isExportDeclaration(node)) {
|
|
198
|
+
// Re-export
|
|
199
|
+
if (node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
200
|
+
const symbol = {
|
|
201
|
+
name: node.moduleSpecifier.text,
|
|
202
|
+
filePath,
|
|
203
|
+
line: ExportMapper.getLineNumber(sourceFile, node),
|
|
204
|
+
symbolType: 're-export',
|
|
205
|
+
signature: null,
|
|
206
|
+
typeInfo: node.moduleSpecifier.text,
|
|
207
|
+
genericSignature: null,
|
|
208
|
+
parentClass: null,
|
|
209
|
+
interfaces: []
|
|
210
|
+
};
|
|
211
|
+
exports.push(symbol);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
ts.forEachChild(node, visit);
|
|
215
|
+
};
|
|
216
|
+
visit(sourceFile);
|
|
217
|
+
return exports;
|
|
218
|
+
}
|
|
219
|
+
static extractSymbolMetadata(node, sourceFile, checker, packageRoot, errors, name, symbolType, errorMap) {
|
|
220
|
+
const filePath = ExportMapper.getRelativePath(sourceFile.fileName, packageRoot);
|
|
221
|
+
const symbolErrorKey = `${filePath}::${name}`;
|
|
222
|
+
// Check if this symbol had a previous non-retryable error
|
|
223
|
+
if (errorMap?.has(symbolErrorKey)) {
|
|
224
|
+
const prevError = errorMap.get(symbolErrorKey);
|
|
225
|
+
if (!prevError.retryable) {
|
|
226
|
+
// Skip non-retryable symbol errors
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
const line = ExportMapper.getLineNumber(sourceFile, node);
|
|
232
|
+
let signature = null;
|
|
233
|
+
let typeInfo = null;
|
|
234
|
+
let genericSignature = null;
|
|
235
|
+
let parentClass = null;
|
|
236
|
+
let interfaces = [];
|
|
237
|
+
// Extract generic signature
|
|
238
|
+
try {
|
|
239
|
+
genericSignature = ExportMapper.extractGenericSignatures(node, checker);
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
errors.push({
|
|
243
|
+
level: 'symbol',
|
|
244
|
+
path: symbolErrorKey,
|
|
245
|
+
error: `Failed to extract generic signature: ${error.message || String(error)}`,
|
|
246
|
+
stack: error.stack,
|
|
247
|
+
timestamp: new Date().toISOString(),
|
|
248
|
+
retryable: true,
|
|
249
|
+
context: { symbolName: name, symbolType, operation: 'extractGenericSignatures' }
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
// Extract signature and type info based on symbol type
|
|
253
|
+
if (symbolType === 'function' && ts.isFunctionDeclaration(node)) {
|
|
254
|
+
try {
|
|
255
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
256
|
+
if (symbol) {
|
|
257
|
+
const type = checker.getTypeOfSymbolAtLocation(symbol, node);
|
|
258
|
+
const signatures = checker.getSignaturesOfType(type, ts.SignatureKind.Call);
|
|
259
|
+
if (signatures.length > 0) {
|
|
260
|
+
signature = checker.signatureToString(signatures[0], node);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
errors.push({
|
|
266
|
+
level: 'symbol',
|
|
267
|
+
path: symbolErrorKey,
|
|
268
|
+
error: `Failed to extract function signature: ${error.message || String(error)}`,
|
|
269
|
+
stack: error.stack,
|
|
270
|
+
timestamp: new Date().toISOString(),
|
|
271
|
+
retryable: true,
|
|
272
|
+
context: { symbolName: name, symbolType, operation: 'extractFunctionSignature' }
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else if (symbolType === 'class' && ts.isClassDeclaration(node)) {
|
|
277
|
+
try {
|
|
278
|
+
// Extract class inheritance
|
|
279
|
+
const inheritance = ExportMapper.extractClassInheritance(node, checker);
|
|
280
|
+
parentClass = inheritance.parentClass;
|
|
281
|
+
interfaces = inheritance.interfaces;
|
|
282
|
+
// Build class signature
|
|
283
|
+
const parts = [];
|
|
284
|
+
parts.push('class', name);
|
|
285
|
+
if (genericSignature) {
|
|
286
|
+
parts[1] = `${name}${genericSignature}`;
|
|
287
|
+
}
|
|
288
|
+
if (parentClass) {
|
|
289
|
+
parts.push('extends', parentClass);
|
|
290
|
+
}
|
|
291
|
+
if (interfaces.length > 0) {
|
|
292
|
+
parts.push('implements', interfaces.join(', '));
|
|
293
|
+
}
|
|
294
|
+
signature = parts.join(' ');
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
errors.push({
|
|
298
|
+
level: 'symbol',
|
|
299
|
+
path: symbolErrorKey,
|
|
300
|
+
error: `Failed to extract class metadata: ${error.message || String(error)}`,
|
|
301
|
+
stack: error.stack,
|
|
302
|
+
timestamp: new Date().toISOString(),
|
|
303
|
+
retryable: true,
|
|
304
|
+
context: { symbolName: name, symbolType, operation: 'extractClassMetadata' }
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
else if (symbolType === 'interface' && ts.isInterfaceDeclaration(node)) {
|
|
309
|
+
try {
|
|
310
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
311
|
+
if (symbol) {
|
|
312
|
+
const type = checker.getTypeOfSymbolAtLocation(symbol, node);
|
|
313
|
+
typeInfo = checker.typeToString(type, node);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
errors.push({
|
|
318
|
+
level: 'symbol',
|
|
319
|
+
path: symbolErrorKey,
|
|
320
|
+
error: `Failed to extract interface type info: ${error.message || String(error)}`,
|
|
321
|
+
stack: error.stack,
|
|
322
|
+
timestamp: new Date().toISOString(),
|
|
323
|
+
retryable: true,
|
|
324
|
+
context: { symbolName: name, symbolType, operation: 'extractInterfaceTypeInfo' }
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
else if (symbolType === 'type' && ts.isTypeAliasDeclaration(node)) {
|
|
329
|
+
try {
|
|
330
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
331
|
+
if (symbol) {
|
|
332
|
+
const type = checker.getTypeOfSymbolAtLocation(symbol, node);
|
|
333
|
+
typeInfo = checker.typeToString(type, node);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
errors.push({
|
|
338
|
+
level: 'symbol',
|
|
339
|
+
path: symbolErrorKey,
|
|
340
|
+
error: `Failed to extract type info: ${error.message || String(error)}`,
|
|
341
|
+
stack: error.stack,
|
|
342
|
+
timestamp: new Date().toISOString(),
|
|
343
|
+
retryable: true,
|
|
344
|
+
context: { symbolName: name, symbolType, operation: 'extractTypeInfo' }
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
else if (symbolType === 'variable' || symbolType === 'constant') {
|
|
349
|
+
try {
|
|
350
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
351
|
+
if (symbol) {
|
|
352
|
+
const type = checker.getTypeOfSymbolAtLocation(symbol, node);
|
|
353
|
+
typeInfo = checker.typeToString(type, node);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
errors.push({
|
|
358
|
+
level: 'symbol',
|
|
359
|
+
path: symbolErrorKey,
|
|
360
|
+
error: `Failed to extract variable type info: ${error.message || String(error)}`,
|
|
361
|
+
stack: error.stack,
|
|
362
|
+
timestamp: new Date().toISOString(),
|
|
363
|
+
retryable: true,
|
|
364
|
+
context: { symbolName: name, symbolType, operation: 'extractVariableTypeInfo' }
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
const symbol = {
|
|
369
|
+
name,
|
|
370
|
+
filePath,
|
|
371
|
+
line,
|
|
372
|
+
symbolType,
|
|
373
|
+
signature,
|
|
374
|
+
typeInfo,
|
|
375
|
+
genericSignature,
|
|
376
|
+
parentClass,
|
|
377
|
+
interfaces
|
|
378
|
+
};
|
|
379
|
+
// Remove from error map if successfully processed (retry succeeded)
|
|
380
|
+
if (errorMap?.has(symbolErrorKey)) {
|
|
381
|
+
errorMap.delete(symbolErrorKey);
|
|
382
|
+
}
|
|
383
|
+
return symbol;
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
errors.push({
|
|
387
|
+
level: 'symbol',
|
|
388
|
+
path: symbolErrorKey,
|
|
389
|
+
error: error.message || String(error),
|
|
390
|
+
stack: error.stack,
|
|
391
|
+
timestamp: new Date().toISOString(),
|
|
392
|
+
retryable: true,
|
|
393
|
+
context: { symbolName: name, symbolType }
|
|
394
|
+
});
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
static extractGenericSignatures(node, checker) {
|
|
399
|
+
let typeParameters;
|
|
400
|
+
if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) {
|
|
401
|
+
typeParameters = node.typeParameters;
|
|
402
|
+
}
|
|
403
|
+
else if (ts.isClassDeclaration(node)) {
|
|
404
|
+
typeParameters = node.typeParameters;
|
|
405
|
+
}
|
|
406
|
+
else if (ts.isInterfaceDeclaration(node)) {
|
|
407
|
+
typeParameters = node.typeParameters;
|
|
408
|
+
}
|
|
409
|
+
else if (ts.isTypeAliasDeclaration(node)) {
|
|
410
|
+
typeParameters = node.typeParameters;
|
|
411
|
+
}
|
|
412
|
+
if (!typeParameters || typeParameters.length === 0) {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
const params = [];
|
|
416
|
+
for (const param of typeParameters) {
|
|
417
|
+
let paramStr = param.name.text;
|
|
418
|
+
if (param.constraint) {
|
|
419
|
+
paramStr += ` extends ${param.constraint.getText()}`;
|
|
420
|
+
}
|
|
421
|
+
if (param.default) {
|
|
422
|
+
paramStr += ` = ${param.default.getText()}`;
|
|
423
|
+
}
|
|
424
|
+
params.push(paramStr);
|
|
425
|
+
}
|
|
426
|
+
return `<${params.join(', ')}>`;
|
|
427
|
+
}
|
|
428
|
+
static extractClassInheritance(node, checker) {
|
|
429
|
+
let parentClass = null;
|
|
430
|
+
const interfaces = [];
|
|
431
|
+
if (!node.heritageClauses) {
|
|
432
|
+
return { parentClass, interfaces };
|
|
433
|
+
}
|
|
434
|
+
for (const clause of node.heritageClauses) {
|
|
435
|
+
if (clause.token === ts.SyntaxKind.ExtendsKeyword) {
|
|
436
|
+
// Extends clause
|
|
437
|
+
for (const type of clause.types) {
|
|
438
|
+
try {
|
|
439
|
+
const typeNode = checker.getTypeAtLocation(type);
|
|
440
|
+
parentClass = checker.typeToString(typeNode, type);
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
// If type checking fails, use the text
|
|
444
|
+
parentClass = type.getText();
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
else if (clause.token === ts.SyntaxKind.ImplementsKeyword) {
|
|
449
|
+
// Implements clause
|
|
450
|
+
for (const type of clause.types) {
|
|
451
|
+
try {
|
|
452
|
+
const typeNode = checker.getTypeAtLocation(type);
|
|
453
|
+
interfaces.push(checker.typeToString(typeNode, type));
|
|
454
|
+
}
|
|
455
|
+
catch (error) {
|
|
456
|
+
// If type checking fails, use the text
|
|
457
|
+
interfaces.push(type.getText());
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return { parentClass, interfaces };
|
|
463
|
+
}
|
|
464
|
+
static hasExportModifier(node) {
|
|
465
|
+
return (ts.canHaveModifiers(node) && (ts.getModifiers(node)?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword) ?? false));
|
|
466
|
+
}
|
|
467
|
+
static getLineNumber(sourceFile, node) {
|
|
468
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
469
|
+
return line + 1; // Convert to 1-based line number
|
|
470
|
+
}
|
|
471
|
+
static getRelativePath(absolutePath, packageRoot) {
|
|
472
|
+
const relative = absolutePath.replace(packageRoot, '').replace(/^\//, '');
|
|
473
|
+
return relative || absolutePath;
|
|
474
|
+
}
|
|
475
|
+
static async loadPreviousErrors(projectRoot, packageName) {
|
|
476
|
+
const indexPath = ExportMapper.getIndexPath(projectRoot, packageName);
|
|
477
|
+
const errorFilePath = pathResolve(indexPath, '_export-errors.json');
|
|
478
|
+
if (!await FileSystemUtils.file.exists(errorFilePath)) {
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
try {
|
|
482
|
+
const errorFile = await FileSystemUtils.file.read.json(errorFilePath);
|
|
483
|
+
return errorFile.errors || [];
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
static async writeErrors(projectRoot, packageName, errors) {
|
|
490
|
+
const indexPath = ExportMapper.getIndexPath(projectRoot, packageName);
|
|
491
|
+
await FileSystemUtils.folder.create(indexPath);
|
|
492
|
+
if (errors.length === 0) {
|
|
493
|
+
// Remove error file if no errors
|
|
494
|
+
const errorFilePath = pathResolve(indexPath, '_export-errors.json');
|
|
495
|
+
if (await FileSystemUtils.file.exists(errorFilePath)) {
|
|
496
|
+
await FileSystemUtils.file.delete(errorFilePath);
|
|
497
|
+
}
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
const errorFile = {
|
|
501
|
+
package: packageName,
|
|
502
|
+
timestamp: new Date().toISOString(),
|
|
503
|
+
errors
|
|
504
|
+
};
|
|
505
|
+
const errorFilePath = pathResolve(indexPath, '_export-errors.json');
|
|
506
|
+
await FileSystemUtils.file.write(errorFilePath, __stringify(errorFile, true));
|
|
507
|
+
}
|
|
508
|
+
static shouldRetryError(error, retryErrors) {
|
|
509
|
+
if (!error.retryable) {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
if (!retryErrors || retryErrors.length === 0) {
|
|
513
|
+
// If no retryErrors provided, don't retry (means we're not in retry mode)
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
// Check if this error exists in retryErrors (meaning it should be retried)
|
|
517
|
+
return retryErrors.some(e => e.path === error.path && e.level === error.level);
|
|
518
|
+
}
|
|
519
|
+
}
|