@veewo/gitnexus 1.3.8 → 1.3.10
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/README.md +5 -0
- package/dist/benchmark/runner.test.js +1 -1
- package/dist/benchmark/u2-e2e/analyze-parser.d.ts +22 -0
- package/dist/benchmark/u2-e2e/analyze-parser.js +89 -0
- package/dist/benchmark/u2-e2e/analyze-parser.test.js +13 -0
- package/dist/benchmark/u2-e2e/characterlist-assetref.d.ts +19 -0
- package/dist/benchmark/u2-e2e/characterlist-assetref.js +80 -0
- package/dist/benchmark/u2-e2e/characterlist-assetref.test.js +108 -0
- package/dist/benchmark/u2-e2e/config.d.ts +25 -0
- package/dist/benchmark/u2-e2e/config.js +86 -0
- package/dist/benchmark/u2-e2e/config.test.js +29 -0
- package/dist/benchmark/u2-e2e/metrics.d.ts +20 -0
- package/dist/benchmark/u2-e2e/metrics.js +34 -0
- package/dist/benchmark/u2-e2e/metrics.test.js +13 -0
- package/dist/benchmark/u2-e2e/neonspark-full-e2e.d.ts +33 -0
- package/dist/benchmark/u2-e2e/neonspark-full-e2e.js +439 -0
- package/dist/benchmark/u2-e2e/neonspark-full-e2e.test.js +40 -0
- package/dist/benchmark/u2-e2e/report.d.ts +58 -0
- package/dist/benchmark/u2-e2e/report.js +130 -0
- package/dist/benchmark/u2-e2e/report.test.js +58 -0
- package/dist/benchmark/u2-e2e/retrieval-runner.d.ts +21 -0
- package/dist/benchmark/u2-e2e/retrieval-runner.js +166 -0
- package/dist/benchmark/u2-e2e/retrieval-runner.test.d.ts +1 -0
- package/dist/benchmark/u2-e2e/retrieval-runner.test.js +145 -0
- package/dist/benchmark/u2-performance-sampler.d.ts +33 -0
- package/dist/benchmark/u2-performance-sampler.js +178 -0
- package/dist/benchmark/u2-performance-sampler.test.d.ts +1 -0
- package/dist/benchmark/u2-performance-sampler.test.js +34 -0
- package/dist/cli/ai-context.js +1 -1
- package/dist/cli/analyze-multi-scope-regression.test.js +10 -0
- package/dist/cli/analyze-options.d.ts +19 -0
- package/dist/cli/analyze-options.js +35 -0
- package/dist/cli/analyze-options.test.js +42 -1
- package/dist/cli/analyze-summary.d.ts +7 -0
- package/dist/cli/analyze-summary.js +37 -0
- package/dist/cli/analyze-summary.test.d.ts +1 -0
- package/dist/cli/analyze-summary.test.js +58 -0
- package/dist/cli/analyze.d.ts +1 -0
- package/dist/cli/analyze.js +64 -32
- package/dist/cli/benchmark-u2-e2e.d.ts +9 -0
- package/dist/cli/benchmark-u2-e2e.js +35 -0
- package/dist/cli/benchmark-u2-e2e.test.d.ts +1 -0
- package/dist/cli/benchmark-u2-e2e.test.js +7 -0
- package/dist/cli/index.js +21 -0
- package/dist/cli/repo-manager-alias.test.js +24 -1
- package/dist/cli/tool.d.ts +3 -0
- package/dist/cli/tool.js +2 -0
- package/dist/cli/unity-bindings.d.ts +8 -0
- package/dist/cli/unity-bindings.js +33 -0
- package/dist/cli/unity-bindings.test.d.ts +1 -0
- package/dist/cli/unity-bindings.test.js +24 -0
- package/dist/core/graph/types.d.ts +1 -1
- package/dist/core/ingestion/pipeline.d.ts +2 -4
- package/dist/core/ingestion/pipeline.js +12 -0
- package/dist/core/ingestion/unity-resource-processor.d.ts +26 -0
- package/dist/core/ingestion/unity-resource-processor.js +363 -0
- package/dist/core/ingestion/unity-resource-processor.test.d.ts +1 -0
- package/dist/core/ingestion/unity-resource-processor.test.js +599 -0
- package/dist/core/kuzu/kuzu-adapter.d.ts +6 -0
- package/dist/core/kuzu/kuzu-adapter.js +18 -7
- package/dist/core/kuzu/schema.d.ts +2 -2
- package/dist/core/kuzu/schema.js +22 -1
- package/dist/core/kuzu/schema.test.d.ts +1 -0
- package/dist/core/kuzu/schema.test.js +17 -0
- package/dist/core/unity/meta-index.d.ts +5 -0
- package/dist/core/unity/meta-index.js +113 -0
- package/dist/core/unity/meta-index.test.d.ts +1 -0
- package/dist/core/unity/meta-index.test.js +11 -0
- package/dist/core/unity/options.d.ts +2 -0
- package/dist/core/unity/options.js +9 -0
- package/dist/core/unity/options.test.d.ts +1 -0
- package/dist/core/unity/options.test.js +10 -0
- package/dist/core/unity/override-merger.d.ts +27 -0
- package/dist/core/unity/override-merger.js +35 -0
- package/dist/core/unity/override-merger.test.d.ts +1 -0
- package/dist/core/unity/override-merger.test.js +47 -0
- package/dist/core/unity/resolver.d.ts +79 -0
- package/dist/core/unity/resolver.js +384 -0
- package/dist/core/unity/resolver.test.d.ts +1 -0
- package/dist/core/unity/resolver.test.js +244 -0
- package/dist/core/unity/resource-hit-scanner.d.ts +10 -0
- package/dist/core/unity/resource-hit-scanner.js +60 -0
- package/dist/core/unity/resource-hit-scanner.test.d.ts +1 -0
- package/dist/core/unity/resource-hit-scanner.test.js +20 -0
- package/dist/core/unity/scan-context.d.ts +23 -0
- package/dist/core/unity/scan-context.js +318 -0
- package/dist/core/unity/scan-context.test.d.ts +1 -0
- package/dist/core/unity/scan-context.test.js +118 -0
- package/dist/core/unity/serialized-type-index.d.ts +10 -0
- package/dist/core/unity/serialized-type-index.js +105 -0
- package/dist/core/unity/serialized-type-index.test.d.ts +1 -0
- package/dist/core/unity/serialized-type-index.test.js +34 -0
- package/dist/core/unity/u2-thresholds.test.d.ts +1 -0
- package/dist/core/unity/u2-thresholds.test.js +71 -0
- package/dist/core/unity/yaml-object-graph.d.ts +9 -0
- package/dist/core/unity/yaml-object-graph.js +92 -0
- package/dist/core/unity/yaml-object-graph.test.d.ts +1 -0
- package/dist/core/unity/yaml-object-graph.test.js +49 -0
- package/dist/mcp/local/local-backend.js +12 -1
- package/dist/mcp/local/unity-enrichment.d.ts +6 -0
- package/dist/mcp/local/unity-enrichment.js +91 -0
- package/dist/mcp/local/unity-enrichment.test.d.ts +1 -0
- package/dist/mcp/local/unity-enrichment.test.js +130 -0
- package/dist/mcp/resources.js +1 -1
- package/dist/mcp/staleness.js +1 -1
- package/dist/mcp/tools.js +12 -0
- package/dist/storage/repo-manager.d.ts +6 -0
- package/dist/types/pipeline.d.ts +7 -0
- package/dist/types/pipeline.js +2 -0
- package/hooks/check-release-path-hygiene.mjs +108 -0
- package/package.json +16 -9
- package/dist/cli/analyze-custom-modules-regression.test.js +0 -75
- package/dist/cli/analyze-modules-diagnostics.test.js +0 -36
- package/dist/core/ingestion/modules/assignment-engine.d.ts +0 -33
- package/dist/core/ingestion/modules/assignment-engine.js +0 -179
- package/dist/core/ingestion/modules/assignment-engine.test.js +0 -111
- package/dist/core/ingestion/modules/config-loader.d.ts +0 -2
- package/dist/core/ingestion/modules/config-loader.js +0 -186
- package/dist/core/ingestion/modules/config-loader.test.js +0 -57
- package/dist/core/ingestion/modules/rule-matcher.d.ts +0 -12
- package/dist/core/ingestion/modules/rule-matcher.js +0 -63
- package/dist/core/ingestion/modules/rule-matcher.test.js +0 -58
- package/dist/core/ingestion/modules/types.d.ts +0 -44
- package/dist/core/ingestion/modules/types.js +0 -2
- package/dist/mcp/local/cluster-aggregation.d.ts +0 -20
- package/dist/mcp/local/cluster-aggregation.js +0 -48
- package/dist/mcp/local/cluster-aggregation.test.js +0 -22
- /package/dist/{cli/analyze-custom-modules-regression.test.d.ts → benchmark/u2-e2e/analyze-parser.test.d.ts} +0 -0
- /package/dist/{cli/analyze-modules-diagnostics.test.d.ts → benchmark/u2-e2e/characterlist-assetref.test.d.ts} +0 -0
- /package/dist/{core/ingestion/modules/assignment-engine.test.d.ts → benchmark/u2-e2e/config.test.d.ts} +0 -0
- /package/dist/{core/ingestion/modules/config-loader.test.d.ts → benchmark/u2-e2e/metrics.test.d.ts} +0 -0
- /package/dist/{core/ingestion/modules/rule-matcher.test.d.ts → benchmark/u2-e2e/neonspark-full-e2e.test.d.ts} +0 -0
- /package/dist/{mcp/local/cluster-aggregation.test.d.ts → benchmark/u2-e2e/report.test.d.ts} +0 -0
|
@@ -2,6 +2,25 @@ export interface AnalyzeScopeOptions {
|
|
|
2
2
|
scopeManifest?: string;
|
|
3
3
|
scopePrefix?: string[] | string;
|
|
4
4
|
}
|
|
5
|
+
export interface StoredAnalyzeOptions {
|
|
6
|
+
includeExtensions?: string[];
|
|
7
|
+
scopeRules?: string[];
|
|
8
|
+
repoAlias?: string;
|
|
9
|
+
embeddings?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ResolveAnalyzeOptionsInput extends AnalyzeScopeOptions {
|
|
12
|
+
extensions?: string;
|
|
13
|
+
repoAlias?: string;
|
|
14
|
+
embeddings?: boolean;
|
|
15
|
+
reuseOptions?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface EffectiveAnalyzeOptions {
|
|
18
|
+
includeExtensions: string[];
|
|
19
|
+
scopeRules: string[];
|
|
20
|
+
repoAlias?: string;
|
|
21
|
+
embeddings: boolean;
|
|
22
|
+
}
|
|
5
23
|
export declare function parseExtensionList(rawExtensions?: string): string[];
|
|
6
24
|
export declare function normalizeRepoAlias(repoAlias?: string): string | undefined;
|
|
7
25
|
export declare function resolveAnalyzeScopeRules(options?: AnalyzeScopeOptions): Promise<string[]>;
|
|
26
|
+
export declare function resolveEffectiveAnalyzeOptions(options?: ResolveAnalyzeOptionsInput, stored?: StoredAnalyzeOptions): Promise<EffectiveAnalyzeOptions>;
|
|
@@ -54,3 +54,38 @@ export async function resolveAnalyzeScopeRules(options) {
|
|
|
54
54
|
}
|
|
55
55
|
return normalizedRules;
|
|
56
56
|
}
|
|
57
|
+
function parseScopePrefixCount(scopePrefix) {
|
|
58
|
+
if (Array.isArray(scopePrefix))
|
|
59
|
+
return scopePrefix.length;
|
|
60
|
+
if (typeof scopePrefix === 'string')
|
|
61
|
+
return scopePrefix.trim() ? 1 : 0;
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
export async function resolveEffectiveAnalyzeOptions(options, stored) {
|
|
65
|
+
const includeExtensionsFromCli = parseExtensionList(options?.extensions);
|
|
66
|
+
const scopeRulesFromCli = await resolveAnalyzeScopeRules({
|
|
67
|
+
scopeManifest: options?.scopeManifest,
|
|
68
|
+
scopePrefix: options?.scopePrefix,
|
|
69
|
+
});
|
|
70
|
+
const repoAliasFromCli = normalizeRepoAlias(options?.repoAlias);
|
|
71
|
+
const hasCliExtensions = options?.extensions !== undefined;
|
|
72
|
+
const hasCliScope = Boolean(options?.scopeManifest) || parseScopePrefixCount(options?.scopePrefix) > 0;
|
|
73
|
+
const hasCliRepoAlias = options?.repoAlias !== undefined;
|
|
74
|
+
const canReuse = options?.reuseOptions !== false;
|
|
75
|
+
const includeExtensions = hasCliExtensions
|
|
76
|
+
? includeExtensionsFromCli
|
|
77
|
+
: (canReuse ? (stored?.includeExtensions || []) : []);
|
|
78
|
+
const scopeRules = hasCliScope
|
|
79
|
+
? scopeRulesFromCli
|
|
80
|
+
: (canReuse ? (stored?.scopeRules || []) : []);
|
|
81
|
+
const repoAlias = hasCliRepoAlias
|
|
82
|
+
? repoAliasFromCli
|
|
83
|
+
: (canReuse ? normalizeRepoAlias(stored?.repoAlias) : undefined);
|
|
84
|
+
const embeddings = options?.embeddings ?? (canReuse ? Boolean(stored?.embeddings) : false);
|
|
85
|
+
return {
|
|
86
|
+
includeExtensions: [...includeExtensions],
|
|
87
|
+
scopeRules: [...scopeRules],
|
|
88
|
+
repoAlias,
|
|
89
|
+
embeddings,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import fs from 'node:fs/promises';
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
-
import { normalizeRepoAlias, parseExtensionList, resolveAnalyzeScopeRules } from './analyze-options.js';
|
|
6
|
+
import { normalizeRepoAlias, parseExtensionList, resolveAnalyzeScopeRules, resolveEffectiveAnalyzeOptions, } from './analyze-options.js';
|
|
7
7
|
test('parseExtensionList normalizes dot prefixes', () => {
|
|
8
8
|
const exts = parseExtensionList('cs,.ts, go ');
|
|
9
9
|
assert.deepEqual(exts, ['.cs', '.ts', '.go']);
|
|
@@ -34,3 +34,44 @@ test('resolveAnalyzeScopeRules fails when manifest has no usable rule', async ()
|
|
|
34
34
|
await fs.writeFile(manifestPath, '# only comments\n\n', 'utf-8');
|
|
35
35
|
await assert.rejects(resolveAnalyzeScopeRules({ scopeManifest: manifestPath }), /no valid scope rules/i);
|
|
36
36
|
});
|
|
37
|
+
test('resolveEffectiveAnalyzeOptions reuses stored settings when CLI omits them', async () => {
|
|
38
|
+
const resolved = await resolveEffectiveAnalyzeOptions({}, {
|
|
39
|
+
includeExtensions: ['.cs'],
|
|
40
|
+
scopeRules: ['Assets/NEON/Code'],
|
|
41
|
+
repoAlias: 'neonspark-v1-subset',
|
|
42
|
+
embeddings: true,
|
|
43
|
+
});
|
|
44
|
+
assert.deepEqual(resolved.includeExtensions, ['.cs']);
|
|
45
|
+
assert.deepEqual(resolved.scopeRules, ['Assets/NEON/Code']);
|
|
46
|
+
assert.equal(resolved.repoAlias, 'neonspark-v1-subset');
|
|
47
|
+
assert.equal(resolved.embeddings, true);
|
|
48
|
+
});
|
|
49
|
+
test('resolveEffectiveAnalyzeOptions disables reuse via reuseOptions=false', async () => {
|
|
50
|
+
const resolved = await resolveEffectiveAnalyzeOptions({ reuseOptions: false }, {
|
|
51
|
+
includeExtensions: ['.cs'],
|
|
52
|
+
scopeRules: ['Assets/NEON/Code'],
|
|
53
|
+
repoAlias: 'neonspark-v1-subset',
|
|
54
|
+
embeddings: true,
|
|
55
|
+
});
|
|
56
|
+
assert.deepEqual(resolved.includeExtensions, []);
|
|
57
|
+
assert.deepEqual(resolved.scopeRules, []);
|
|
58
|
+
assert.equal(resolved.repoAlias, undefined);
|
|
59
|
+
assert.equal(resolved.embeddings, false);
|
|
60
|
+
});
|
|
61
|
+
test('resolveEffectiveAnalyzeOptions prefers explicit CLI values over stored settings', async () => {
|
|
62
|
+
const resolved = await resolveEffectiveAnalyzeOptions({
|
|
63
|
+
extensions: '.ts',
|
|
64
|
+
scopePrefix: ['src'],
|
|
65
|
+
repoAlias: 'new-alias',
|
|
66
|
+
embeddings: false,
|
|
67
|
+
}, {
|
|
68
|
+
includeExtensions: ['.cs'],
|
|
69
|
+
scopeRules: ['Assets/NEON/Code'],
|
|
70
|
+
repoAlias: 'old-alias',
|
|
71
|
+
embeddings: true,
|
|
72
|
+
});
|
|
73
|
+
assert.deepEqual(resolved.includeExtensions, ['.ts']);
|
|
74
|
+
assert.deepEqual(resolved.scopeRules, ['src']);
|
|
75
|
+
assert.equal(resolved.repoAlias, 'new-alias');
|
|
76
|
+
assert.equal(resolved.embeddings, false);
|
|
77
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface FallbackInsertStats {
|
|
2
|
+
attempted: number;
|
|
3
|
+
succeeded: number;
|
|
4
|
+
failed: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function formatUnityDiagnosticsSummary(diagnostics: string[] | undefined, previewLimit?: number): string[];
|
|
7
|
+
export declare function formatFallbackSummary(warnings: string[] | undefined, stats: FallbackInsertStats | undefined, previewLimit?: number): string[];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function formatUnityDiagnosticsSummary(diagnostics, previewLimit = 3) {
|
|
2
|
+
if (!diagnostics || diagnostics.length === 0) {
|
|
3
|
+
return [];
|
|
4
|
+
}
|
|
5
|
+
const limit = previewLimit > 0 ? previewLimit : diagnostics.length;
|
|
6
|
+
const preview = diagnostics.slice(0, limit);
|
|
7
|
+
const lines = [`Unity Diagnostics: ${diagnostics.length} message(s)`];
|
|
8
|
+
for (const message of preview) {
|
|
9
|
+
lines.push(`- ${message}`);
|
|
10
|
+
}
|
|
11
|
+
if (diagnostics.length > preview.length) {
|
|
12
|
+
lines.push(`... ${diagnostics.length - preview.length} more`);
|
|
13
|
+
}
|
|
14
|
+
return lines;
|
|
15
|
+
}
|
|
16
|
+
export function formatFallbackSummary(warnings, stats, previewLimit = 5) {
|
|
17
|
+
if (!warnings || warnings.length === 0) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
const safeStats = stats ?? {
|
|
21
|
+
attempted: 0,
|
|
22
|
+
succeeded: 0,
|
|
23
|
+
failed: 0,
|
|
24
|
+
};
|
|
25
|
+
const limit = previewLimit > 0 ? previewLimit : warnings.length;
|
|
26
|
+
const preview = warnings.slice(0, limit);
|
|
27
|
+
const lines = [
|
|
28
|
+
`Fallback edges: attempted=${safeStats.attempted}, succeeded=${safeStats.succeeded}, failed=${safeStats.failed}, pairTypes=${warnings.length}`,
|
|
29
|
+
];
|
|
30
|
+
for (const warning of preview) {
|
|
31
|
+
lines.push(`- ${warning}`);
|
|
32
|
+
}
|
|
33
|
+
if (warnings.length > preview.length) {
|
|
34
|
+
lines.push(`... ${warnings.length - preview.length} more`);
|
|
35
|
+
}
|
|
36
|
+
return lines;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { formatFallbackSummary, formatUnityDiagnosticsSummary } from './analyze-summary.js';
|
|
4
|
+
test('formatUnityDiagnosticsSummary returns empty when diagnostics are missing', () => {
|
|
5
|
+
const lines = formatUnityDiagnosticsSummary([]);
|
|
6
|
+
assert.deepEqual(lines, []);
|
|
7
|
+
});
|
|
8
|
+
test('formatUnityDiagnosticsSummary renders diagnostics with count and bullets', () => {
|
|
9
|
+
const lines = formatUnityDiagnosticsSummary([
|
|
10
|
+
'scanContext: scripts=4, guids=4, resources=0',
|
|
11
|
+
]);
|
|
12
|
+
assert.deepEqual(lines, [
|
|
13
|
+
'Unity Diagnostics: 1 message(s)',
|
|
14
|
+
'- scanContext: scripts=4, guids=4, resources=0',
|
|
15
|
+
]);
|
|
16
|
+
});
|
|
17
|
+
test('formatUnityDiagnosticsSummary truncates output after max preview items', () => {
|
|
18
|
+
const lines = formatUnityDiagnosticsSummary([
|
|
19
|
+
'diag-a',
|
|
20
|
+
'diag-b',
|
|
21
|
+
'diag-c',
|
|
22
|
+
'diag-d',
|
|
23
|
+
]);
|
|
24
|
+
assert.deepEqual(lines, [
|
|
25
|
+
'Unity Diagnostics: 4 message(s)',
|
|
26
|
+
'- diag-a',
|
|
27
|
+
'- diag-b',
|
|
28
|
+
'- diag-c',
|
|
29
|
+
'... 1 more',
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
test('formatFallbackSummary returns empty when no warnings exist', () => {
|
|
33
|
+
const lines = formatFallbackSummary([], {
|
|
34
|
+
attempted: 0,
|
|
35
|
+
succeeded: 0,
|
|
36
|
+
failed: 0,
|
|
37
|
+
});
|
|
38
|
+
assert.deepEqual(lines, []);
|
|
39
|
+
});
|
|
40
|
+
test('formatFallbackSummary renders attempted/succeeded/failed with warning preview', () => {
|
|
41
|
+
const lines = formatFallbackSummary([
|
|
42
|
+
'Method->Delegate (1233 edges): missing rel pair in schema',
|
|
43
|
+
'Class->Property (200 edges): missing rel pair in schema',
|
|
44
|
+
'Constructor->Property (97 edges): missing rel pair in schema',
|
|
45
|
+
'Function->Property (17 edges): missing rel pair in schema',
|
|
46
|
+
], {
|
|
47
|
+
attempted: 1547,
|
|
48
|
+
succeeded: 0,
|
|
49
|
+
failed: 1547,
|
|
50
|
+
}, 3);
|
|
51
|
+
assert.deepEqual(lines, [
|
|
52
|
+
'Fallback edges: attempted=1547, succeeded=0, failed=1547, pairTypes=4',
|
|
53
|
+
'- Method->Delegate (1233 edges): missing rel pair in schema',
|
|
54
|
+
'- Class->Property (200 edges): missing rel pair in schema',
|
|
55
|
+
'- Constructor->Property (97 edges): missing rel pair in schema',
|
|
56
|
+
'... 1 more',
|
|
57
|
+
]);
|
|
58
|
+
});
|
package/dist/cli/analyze.d.ts
CHANGED
package/dist/cli/analyze.js
CHANGED
|
@@ -18,7 +18,8 @@ import { getCurrentCommit, isGitRepo, getGitRoot } from '../storage/git.js';
|
|
|
18
18
|
import { generateAIContextFiles } from './ai-context.js';
|
|
19
19
|
import fs from 'fs/promises';
|
|
20
20
|
import { registerClaudeHook } from './claude-hooks.js';
|
|
21
|
-
import {
|
|
21
|
+
import { resolveEffectiveAnalyzeOptions } from './analyze-options.js';
|
|
22
|
+
import { formatFallbackSummary, formatUnityDiagnosticsSummary } from './analyze-summary.js';
|
|
22
23
|
const HEAP_MB = 8192;
|
|
23
24
|
const HEAP_FLAG = `--max-old-space-size=${HEAP_MB}`;
|
|
24
25
|
/** Re-exec the process with an 8GB heap if we're currently below that. */
|
|
@@ -61,22 +62,6 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
61
62
|
if (ensureHeap())
|
|
62
63
|
return;
|
|
63
64
|
console.log('\n GitNexus Analyzer\n');
|
|
64
|
-
let includeExtensions = [];
|
|
65
|
-
let scopeRules = [];
|
|
66
|
-
let repoAlias;
|
|
67
|
-
try {
|
|
68
|
-
includeExtensions = parseExtensionList(options?.extensions);
|
|
69
|
-
scopeRules = await resolveAnalyzeScopeRules({
|
|
70
|
-
scopeManifest: options?.scopeManifest,
|
|
71
|
-
scopePrefix: options?.scopePrefix,
|
|
72
|
-
});
|
|
73
|
-
repoAlias = normalizeRepoAlias(options?.repoAlias);
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
console.log(` ${error?.message || String(error)}\n`);
|
|
77
|
-
process.exitCode = 1;
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
65
|
let repoPath;
|
|
81
66
|
if (inputPath) {
|
|
82
67
|
repoPath = path.resolve(inputPath);
|
|
@@ -98,15 +83,52 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
98
83
|
const { storagePath, kuzuPath } = getStoragePaths(repoPath);
|
|
99
84
|
const currentCommit = getCurrentCommit(repoPath);
|
|
100
85
|
const existingMeta = await loadMeta(storagePath);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
86
|
+
let includeExtensions = [];
|
|
87
|
+
let scopeRules = [];
|
|
88
|
+
let repoAlias;
|
|
89
|
+
let embeddingsEnabled = false;
|
|
90
|
+
try {
|
|
91
|
+
const effectiveOptions = await resolveEffectiveAnalyzeOptions({
|
|
92
|
+
extensions: options?.extensions,
|
|
93
|
+
scopeManifest: options?.scopeManifest,
|
|
94
|
+
scopePrefix: options?.scopePrefix,
|
|
95
|
+
repoAlias: options?.repoAlias,
|
|
96
|
+
embeddings: options?.embeddings,
|
|
97
|
+
reuseOptions: options?.reuseOptions,
|
|
98
|
+
}, existingMeta?.analyzeOptions);
|
|
99
|
+
includeExtensions = effectiveOptions.includeExtensions;
|
|
100
|
+
scopeRules = effectiveOptions.scopeRules;
|
|
101
|
+
repoAlias = effectiveOptions.repoAlias;
|
|
102
|
+
embeddingsEnabled = effectiveOptions.embeddings;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.log(` ${error?.message || String(error)}\n`);
|
|
106
|
+
process.exitCode = 1;
|
|
108
107
|
return;
|
|
109
108
|
}
|
|
109
|
+
if (existingMeta && !options?.force && existingMeta.lastCommit === currentCommit) {
|
|
110
|
+
const hasScopePrefixInput = Array.isArray(options?.scopePrefix)
|
|
111
|
+
? options.scopePrefix.length > 0
|
|
112
|
+
: Boolean(options?.scopePrefix);
|
|
113
|
+
const hasCliOverrides = options?.extensions !== undefined ||
|
|
114
|
+
Boolean(options?.scopeManifest) ||
|
|
115
|
+
hasScopePrefixInput ||
|
|
116
|
+
options?.repoAlias !== undefined ||
|
|
117
|
+
options?.embeddings !== undefined ||
|
|
118
|
+
options?.reuseOptions === false;
|
|
119
|
+
if (!hasCliOverrides) {
|
|
120
|
+
console.log(' Already up to date\n');
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (options?.reuseOptions !== false &&
|
|
124
|
+
includeExtensions.length === 0 &&
|
|
125
|
+
scopeRules.length === 0 &&
|
|
126
|
+
!repoAlias &&
|
|
127
|
+
!embeddingsEnabled) {
|
|
128
|
+
console.log(' Already up to date\n');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
110
132
|
// Single progress bar for entire pipeline
|
|
111
133
|
const bar = new cliProgress.SingleBar({
|
|
112
134
|
format: ' {bar} {percentage}% | {phase}',
|
|
@@ -170,7 +192,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
170
192
|
// ── Cache embeddings from existing index before rebuild ────────────
|
|
171
193
|
let cachedEmbeddingNodeIds = new Set();
|
|
172
194
|
let cachedEmbeddings = [];
|
|
173
|
-
if (
|
|
195
|
+
if (embeddingsEnabled && existingMeta && !options?.force) {
|
|
174
196
|
try {
|
|
175
197
|
updateBar(0, 'Caching embeddings...');
|
|
176
198
|
await initKuzu(kuzuPath);
|
|
@@ -258,7 +280,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
258
280
|
let embeddingTime = '0.0';
|
|
259
281
|
let embeddingSkipped = true;
|
|
260
282
|
let embeddingSkipReason = 'off (use --embeddings to enable)';
|
|
261
|
-
if (
|
|
283
|
+
if (embeddingsEnabled) {
|
|
262
284
|
if (stats.nodes > EMBEDDING_NODE_LIMIT) {
|
|
263
285
|
embeddingSkipReason = `skipped (${stats.nodes.toLocaleString()} nodes > ${EMBEDDING_NODE_LIMIT.toLocaleString()} limit)`;
|
|
264
286
|
}
|
|
@@ -283,6 +305,12 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
283
305
|
repoPath,
|
|
284
306
|
lastCommit: currentCommit,
|
|
285
307
|
indexedAt: new Date().toISOString(),
|
|
308
|
+
analyzeOptions: {
|
|
309
|
+
includeExtensions,
|
|
310
|
+
scopeRules,
|
|
311
|
+
repoAlias,
|
|
312
|
+
embeddings: embeddingsEnabled,
|
|
313
|
+
},
|
|
286
314
|
stats: {
|
|
287
315
|
files: pipelineResult.totalFileCount,
|
|
288
316
|
nodes: stats.nodes,
|
|
@@ -350,6 +378,10 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
350
378
|
}
|
|
351
379
|
}
|
|
352
380
|
}
|
|
381
|
+
const unitySummaryLines = formatUnityDiagnosticsSummary(pipelineResult.unityResult?.diagnostics);
|
|
382
|
+
for (const line of unitySummaryLines) {
|
|
383
|
+
console.log(` ${line}`);
|
|
384
|
+
}
|
|
353
385
|
console.log(` ${stats.nodes.toLocaleString()} nodes | ${stats.edges.toLocaleString()} edges | ${pipelineResult.communityResult?.stats.totalCommunities || 0} clusters | ${pipelineResult.processResult?.stats.totalProcesses || 0} flows`);
|
|
354
386
|
console.log(` KuzuDB ${kuzuTime}s | FTS ${ftsTime}s | Embeddings ${embeddingSkipped ? embeddingSkipReason : embeddingTime + 's'}`);
|
|
355
387
|
if (includeExtensions.length > 0) {
|
|
@@ -362,13 +394,13 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
362
394
|
if (hookResult.registered) {
|
|
363
395
|
console.log(` Hooks: ${hookResult.message}`);
|
|
364
396
|
}
|
|
365
|
-
// Show
|
|
397
|
+
// Show fallback summary with pair-level preview and explicit outcomes
|
|
366
398
|
if (kuzuWarnings.length > 0) {
|
|
367
|
-
const
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}
|
|
371
|
-
console.log(
|
|
399
|
+
const fallbackLines = formatFallbackSummary(kuzuWarnings, kuzuResult.fallbackStats);
|
|
400
|
+
for (const line of fallbackLines) {
|
|
401
|
+
console.log(` ${line}`);
|
|
402
|
+
}
|
|
403
|
+
console.log(' Note: schema pair coverage should be updated when fallback failures are non-zero');
|
|
372
404
|
}
|
|
373
405
|
try {
|
|
374
406
|
await fs.access(getGlobalRegistryPath());
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface U2E2EArgs {
|
|
2
|
+
configPath: string;
|
|
3
|
+
reportDir?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function resolveU2E2EArgs(argv: string[]): U2E2EArgs;
|
|
6
|
+
export declare function benchmarkU2E2ECommand(options: {
|
|
7
|
+
config?: string;
|
|
8
|
+
reportDir?: string;
|
|
9
|
+
}): Promise<import("../benchmark/u2-e2e/neonspark-full-e2e.js").E2ERunFailure | import("../benchmark/u2-e2e/neonspark-full-e2e.js").E2ERunSuccess>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { runNeonsparkU2E2E } from '../benchmark/u2-e2e/neonspark-full-e2e.js';
|
|
3
|
+
export function resolveU2E2EArgs(argv) {
|
|
4
|
+
const findValue = (name) => {
|
|
5
|
+
const index = argv.indexOf(name);
|
|
6
|
+
if (index === -1 || index + 1 >= argv.length)
|
|
7
|
+
return undefined;
|
|
8
|
+
return argv[index + 1];
|
|
9
|
+
};
|
|
10
|
+
const config = findValue('--config') || '../benchmarks/u2-e2e/neonspark-full-u2-e2e.config.json';
|
|
11
|
+
const reportDir = findValue('--report-dir');
|
|
12
|
+
return {
|
|
13
|
+
configPath: path.resolve(config),
|
|
14
|
+
...(reportDir ? { reportDir: path.resolve(reportDir) } : {}),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function benchmarkU2E2ECommand(options) {
|
|
18
|
+
const result = await runNeonsparkU2E2E({
|
|
19
|
+
configPath: path.resolve(options.config || '../benchmarks/u2-e2e/neonspark-full-u2-e2e.config.json'),
|
|
20
|
+
reportDir: options.reportDir ? path.resolve(options.reportDir) : undefined,
|
|
21
|
+
});
|
|
22
|
+
if (result.status === 'failed') {
|
|
23
|
+
process.stderr.write(`FAIL\n`);
|
|
24
|
+
process.stderr.write(`Run ID: ${result.runId}\n`);
|
|
25
|
+
process.stderr.write(`Failed Gate: ${result.failedGate}\n`);
|
|
26
|
+
process.stderr.write(`Report: ${result.reportDir}\n`);
|
|
27
|
+
process.stderr.write(`Error: ${result.error}\n`);
|
|
28
|
+
process.exitCode = 1;
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
process.stderr.write('PASS\n');
|
|
32
|
+
process.stderr.write(`Run ID: ${result.runId}\n`);
|
|
33
|
+
process.stderr.write(`Report: ${result.reportDir}\n`);
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { resolveU2E2EArgs } from './benchmark-u2-e2e.js';
|
|
4
|
+
test('benchmark-u2-e2e resolves config and report directory', () => {
|
|
5
|
+
const out = resolveU2E2EArgs(['--config', 'benchmarks/u2-e2e/neonspark-full-u2-e2e.config.json']);
|
|
6
|
+
assert.match(out.configPath, /neonspark-full-u2-e2e\.config\.json$/);
|
|
7
|
+
});
|
package/dist/cli/index.js
CHANGED
|
@@ -36,6 +36,8 @@ import { queryCommand, contextCommand, impactCommand, cypherCommand } from './to
|
|
|
36
36
|
import { evalServerCommand } from './eval-server.js';
|
|
37
37
|
import { benchmarkUnityCommand } from './benchmark-unity.js';
|
|
38
38
|
import { benchmarkAgentContextCommand } from './benchmark-agent-context.js';
|
|
39
|
+
import { unityBindingsCommand } from './unity-bindings.js';
|
|
40
|
+
import { benchmarkU2E2ECommand } from './benchmark-u2-e2e.js';
|
|
39
41
|
function resolveCliVersion() {
|
|
40
42
|
try {
|
|
41
43
|
const currentFile = fileURLToPath(import.meta.url);
|
|
@@ -67,6 +69,7 @@ program
|
|
|
67
69
|
.command('analyze [path]')
|
|
68
70
|
.description('Index a repository (full analysis)')
|
|
69
71
|
.option('-f, --force', 'Force full re-index even if up to date')
|
|
72
|
+
.option('--no-reuse-options', 'Do not reuse stored analyze options from previous index')
|
|
70
73
|
.option('--embeddings', 'Enable embedding generation for semantic search (off by default)')
|
|
71
74
|
.option('--extensions <list>', 'Comma-separated file extensions to include (e.g. .cs,.ts)')
|
|
72
75
|
.option('--repo-alias <name>', 'Override indexed repository name with a stable alias')
|
|
@@ -121,6 +124,7 @@ program
|
|
|
121
124
|
.option('-g, --goal <text>', 'What you want to find')
|
|
122
125
|
.option('-l, --limit <n>', 'Max processes to return (default: 5)')
|
|
123
126
|
.option('--content', 'Include full symbol source code')
|
|
127
|
+
.option('--unity-resources <mode>', 'Unity resource retrieval mode: off|on|auto', 'off')
|
|
124
128
|
.action(queryCommand);
|
|
125
129
|
program
|
|
126
130
|
.command('context [name]')
|
|
@@ -129,7 +133,16 @@ program
|
|
|
129
133
|
.option('-u, --uid <uid>', 'Direct symbol UID (zero-ambiguity lookup)')
|
|
130
134
|
.option('-f, --file <path>', 'File path to disambiguate common names')
|
|
131
135
|
.option('--content', 'Include full symbol source code')
|
|
136
|
+
.option('--unity-resources <mode>', 'Unity resource retrieval mode: off|on|auto', 'off')
|
|
132
137
|
.action(contextCommand);
|
|
138
|
+
program
|
|
139
|
+
.command('unity-bindings <symbol>')
|
|
140
|
+
.description('Experimental: inspect Unity resource bindings for a C# symbol')
|
|
141
|
+
.option('--target-path <path>', 'Unity project root (default: cwd)')
|
|
142
|
+
.option('--json', 'Output JSON')
|
|
143
|
+
.action(async (symbol, options) => {
|
|
144
|
+
await unityBindingsCommand(symbol, options);
|
|
145
|
+
});
|
|
133
146
|
program
|
|
134
147
|
.command('impact <target>')
|
|
135
148
|
.description('Blast radius analysis: what breaks if you change a symbol')
|
|
@@ -181,4 +194,12 @@ program
|
|
|
181
194
|
.action(async (dataset, options) => {
|
|
182
195
|
await benchmarkAgentContextCommand(dataset, options);
|
|
183
196
|
});
|
|
197
|
+
program
|
|
198
|
+
.command('benchmark-u2-e2e')
|
|
199
|
+
.description('Run fail-fast full neonspark U2 E2E benchmark and emit evidence reports')
|
|
200
|
+
.option('--config <path>', 'Path to E2E config JSON')
|
|
201
|
+
.option('--report-dir <path>', 'Output directory for reports')
|
|
202
|
+
.action(async (options) => {
|
|
203
|
+
await benchmarkU2E2ECommand(options);
|
|
204
|
+
});
|
|
184
205
|
program.parse(process.argv);
|
|
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import fs from 'node:fs/promises';
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
-
import { readRegistry, registerRepo } from '../storage/repo-manager.js';
|
|
6
|
+
import { loadMeta, readRegistry, registerRepo, saveMeta } from '../storage/repo-manager.js';
|
|
7
7
|
function makeMeta(repoPath, lastCommit) {
|
|
8
8
|
return {
|
|
9
9
|
repoPath,
|
|
@@ -38,3 +38,26 @@ test('registerRepo stores alias and rejects collisions on different paths', asyn
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
|
+
test('saveMeta/loadMeta persists analyzeOptions for future re-index reuse', async () => {
|
|
42
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-meta-'));
|
|
43
|
+
const storagePath = path.join(tmpDir, '.gitnexus');
|
|
44
|
+
await saveMeta(storagePath, {
|
|
45
|
+
repoPath: tmpDir,
|
|
46
|
+
lastCommit: 'abc1234',
|
|
47
|
+
indexedAt: '2026-03-12T00:00:00.000Z',
|
|
48
|
+
analyzeOptions: {
|
|
49
|
+
includeExtensions: ['.cs'],
|
|
50
|
+
scopeRules: ['Assets/NEON/Code'],
|
|
51
|
+
repoAlias: 'neonspark-v1-subset',
|
|
52
|
+
embeddings: true,
|
|
53
|
+
},
|
|
54
|
+
stats: { files: 1, nodes: 2, edges: 3 },
|
|
55
|
+
});
|
|
56
|
+
const meta = await loadMeta(storagePath);
|
|
57
|
+
assert.deepEqual(meta?.analyzeOptions, {
|
|
58
|
+
includeExtensions: ['.cs'],
|
|
59
|
+
scopeRules: ['Assets/NEON/Code'],
|
|
60
|
+
repoAlias: 'neonspark-v1-subset',
|
|
61
|
+
embeddings: true,
|
|
62
|
+
});
|
|
63
|
+
});
|
package/dist/cli/tool.d.ts
CHANGED
|
@@ -13,18 +13,21 @@
|
|
|
13
13
|
* Note: Output goes to stderr because KuzuDB's native module captures stdout
|
|
14
14
|
* at the OS level during init. This is consistent with augment.ts.
|
|
15
15
|
*/
|
|
16
|
+
import type { UnityResourcesMode } from '../core/unity/options.js';
|
|
16
17
|
export declare function queryCommand(queryText: string, options?: {
|
|
17
18
|
repo?: string;
|
|
18
19
|
context?: string;
|
|
19
20
|
goal?: string;
|
|
20
21
|
limit?: string;
|
|
21
22
|
content?: boolean;
|
|
23
|
+
unityResources?: UnityResourcesMode;
|
|
22
24
|
}): Promise<void>;
|
|
23
25
|
export declare function contextCommand(name: string, options?: {
|
|
24
26
|
repo?: string;
|
|
25
27
|
file?: string;
|
|
26
28
|
uid?: string;
|
|
27
29
|
content?: boolean;
|
|
30
|
+
unityResources?: UnityResourcesMode;
|
|
28
31
|
}): Promise<void>;
|
|
29
32
|
export declare function impactCommand(target: string, options?: {
|
|
30
33
|
direction?: string;
|
package/dist/cli/tool.js
CHANGED
|
@@ -43,6 +43,7 @@ export async function queryCommand(queryText, options) {
|
|
|
43
43
|
goal: options?.goal,
|
|
44
44
|
limit: options?.limit ? parseInt(options.limit) : undefined,
|
|
45
45
|
include_content: options?.content ?? false,
|
|
46
|
+
unity_resources: options?.unityResources,
|
|
46
47
|
repo: options?.repo,
|
|
47
48
|
});
|
|
48
49
|
output(result);
|
|
@@ -58,6 +59,7 @@ export async function contextCommand(name, options) {
|
|
|
58
59
|
uid: options?.uid,
|
|
59
60
|
file_path: options?.file,
|
|
60
61
|
include_content: options?.content ?? false,
|
|
62
|
+
unity_resources: options?.unityResources,
|
|
61
63
|
repo: options?.repo,
|
|
62
64
|
});
|
|
63
65
|
output(result);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { resolveUnityBindings } from '../core/unity/resolver.js';
|
|
2
|
+
export declare function unityBindingsCommand(symbol: string, options: {
|
|
3
|
+
targetPath?: string;
|
|
4
|
+
json?: boolean;
|
|
5
|
+
}, deps?: {
|
|
6
|
+
resolver?: typeof resolveUnityBindings;
|
|
7
|
+
writeLine?: (line: string) => void;
|
|
8
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { resolveUnityBindings } from '../core/unity/resolver.js';
|
|
3
|
+
export async function unityBindingsCommand(symbol, options, deps) {
|
|
4
|
+
const resolver = deps?.resolver || resolveUnityBindings;
|
|
5
|
+
const writeLine = deps?.writeLine || ((line) => process.stderr.write(`${line}\n`));
|
|
6
|
+
const repoRoot = path.resolve(options.targetPath || process.cwd());
|
|
7
|
+
const result = await resolver({ repoRoot, symbol });
|
|
8
|
+
if (options.json) {
|
|
9
|
+
writeLine(JSON.stringify(result, null, 2));
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
writeLine(`Unity bindings for ${result.symbol}`);
|
|
13
|
+
writeLine(`Script: ${result.scriptPath}`);
|
|
14
|
+
writeLine(`GUID: ${result.scriptGuid}`);
|
|
15
|
+
writeLine(`Resource bindings: ${result.resourceBindings.length}`);
|
|
16
|
+
for (const binding of result.resourceBindings) {
|
|
17
|
+
writeLine(`- ${binding.resourceType} ${binding.resourcePath} [${binding.bindingKind}] component=${binding.componentObjectId}`);
|
|
18
|
+
}
|
|
19
|
+
writeLine(`Scalar fields: ${result.serializedFields.scalarFields.length}`);
|
|
20
|
+
for (const field of result.serializedFields.scalarFields) {
|
|
21
|
+
writeLine(`- ${field.name} = ${field.value} (${field.sourceLayer})`);
|
|
22
|
+
}
|
|
23
|
+
writeLine(`Reference fields: ${result.serializedFields.referenceFields.length}`);
|
|
24
|
+
for (const field of result.serializedFields.referenceFields) {
|
|
25
|
+
writeLine(`- ${field.name} -> ${field.guid || field.fileId || 'unresolved'} (${field.sourceLayer})`);
|
|
26
|
+
}
|
|
27
|
+
if (result.unityDiagnostics.length > 0) {
|
|
28
|
+
writeLine(`Diagnostics: ${result.unityDiagnostics.length}`);
|
|
29
|
+
for (const diagnostic of result.unityDiagnostics) {
|
|
30
|
+
writeLine(`- ${diagnostic}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { unityBindingsCommand } from './unity-bindings.js';
|
|
6
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const fixtureRoot = path.resolve(here, '../../src/core/unity/__fixtures__/mini-unity');
|
|
8
|
+
test('prints human readable summary by default', async () => {
|
|
9
|
+
const lines = [];
|
|
10
|
+
await unityBindingsCommand('MainUIManager', { targetPath: fixtureRoot }, { writeLine: (line) => lines.push(line) });
|
|
11
|
+
const output = lines.join('\n');
|
|
12
|
+
assert.match(output, /resource bindings/i);
|
|
13
|
+
assert.match(output, /MainUIManager/);
|
|
14
|
+
assert.match(output, /needPause/);
|
|
15
|
+
});
|
|
16
|
+
test('prints JSON when --json is enabled', async () => {
|
|
17
|
+
const lines = [];
|
|
18
|
+
await unityBindingsCommand('MainUIManager', { targetPath: fixtureRoot, json: true }, { writeLine: (line) => lines.push(line) });
|
|
19
|
+
const payload = JSON.parse(lines.join('\n'));
|
|
20
|
+
assert.equal(payload.symbol, 'MainUIManager');
|
|
21
|
+
assert.ok(Array.isArray(payload.resourceBindings));
|
|
22
|
+
assert.ok(Array.isArray(payload.serializedFields.scalarFields));
|
|
23
|
+
assert.ok(Array.isArray(payload.serializedFields.referenceFields));
|
|
24
|
+
});
|