@zigrivers/scaffold 3.9.1 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -8
- package/dist/cli/commands/adopt.d.ts +2 -0
- package/dist/cli/commands/adopt.d.ts.map +1 -1
- package/dist/cli/commands/adopt.js +428 -58
- package/dist/cli/commands/adopt.js.map +1 -1
- package/dist/cli/commands/adopt.performance.test.d.ts +2 -0
- package/dist/cli/commands/adopt.performance.test.d.ts.map +1 -0
- package/dist/cli/commands/adopt.performance.test.js +30 -0
- package/dist/cli/commands/adopt.performance.test.js.map +1 -0
- package/dist/cli/commands/adopt.test.js +18 -6
- package/dist/cli/commands/adopt.test.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +70 -207
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/init.test.js +114 -3
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/cli/init-flag-families.d.ts +86 -0
- package/dist/cli/init-flag-families.d.ts.map +1 -0
- package/dist/cli/init-flag-families.js +418 -0
- package/dist/cli/init-flag-families.js.map +1 -0
- package/dist/cli/init-flag-families.test.d.ts +2 -0
- package/dist/cli/init-flag-families.test.d.ts.map +1 -0
- package/dist/cli/init-flag-families.test.js +268 -0
- package/dist/cli/init-flag-families.test.js.map +1 -0
- package/dist/cli/utils/coerce.d.ts +8 -0
- package/dist/cli/utils/coerce.d.ts.map +1 -0
- package/dist/cli/utils/coerce.js +12 -0
- package/dist/cli/utils/coerce.js.map +1 -0
- package/dist/cli/utils/coerce.test.d.ts +2 -0
- package/dist/cli/utils/coerce.test.d.ts.map +1 -0
- package/dist/cli/utils/coerce.test.js +29 -0
- package/dist/cli/utils/coerce.test.js.map +1 -0
- package/dist/config/schema.d.ts +6 -6
- package/dist/config/schema.js +2 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/config/schema.test.js +10 -4
- package/dist/config/schema.test.js.map +1 -1
- package/dist/e2e/adopt-multi-type.test.d.ts +2 -0
- package/dist/e2e/adopt-multi-type.test.d.ts.map +1 -0
- package/dist/e2e/adopt-multi-type.test.js +35 -0
- package/dist/e2e/adopt-multi-type.test.js.map +1 -0
- package/dist/e2e/game-pipeline.test.js +1 -1
- package/dist/e2e/game-pipeline.test.js.map +1 -1
- package/dist/e2e/project-type-overlays.test.js +19 -18
- package/dist/e2e/project-type-overlays.test.js.map +1 -1
- package/dist/project/__frozen-schemas__/schema-v3.9.2.d.ts +2891 -0
- package/dist/project/__frozen-schemas__/schema-v3.9.2.d.ts.map +1 -0
- package/dist/project/__frozen-schemas__/schema-v3.9.2.js +177 -0
- package/dist/project/__frozen-schemas__/schema-v3.9.2.js.map +1 -0
- package/dist/project/adopt.d.ts +38 -2
- package/dist/project/adopt.d.ts.map +1 -1
- package/dist/project/adopt.error-messages.test.d.ts +2 -0
- package/dist/project/adopt.error-messages.test.d.ts.map +1 -0
- package/dist/project/adopt.error-messages.test.js +112 -0
- package/dist/project/adopt.error-messages.test.js.map +1 -0
- package/dist/project/adopt.forward-compat.test.d.ts +2 -0
- package/dist/project/adopt.forward-compat.test.d.ts.map +1 -0
- package/dist/project/adopt.forward-compat.test.js +71 -0
- package/dist/project/adopt.forward-compat.test.js.map +1 -0
- package/dist/project/adopt.js +218 -27
- package/dist/project/adopt.js.map +1 -1
- package/dist/project/adopt.merge.test.d.ts +2 -0
- package/dist/project/adopt.merge.test.d.ts.map +1 -0
- package/dist/project/adopt.merge.test.js +62 -0
- package/dist/project/adopt.merge.test.js.map +1 -0
- package/dist/project/adopt.re-adoption.test.d.ts +2 -0
- package/dist/project/adopt.re-adoption.test.d.ts.map +1 -0
- package/dist/project/adopt.re-adoption.test.js +222 -0
- package/dist/project/adopt.re-adoption.test.js.map +1 -0
- package/dist/project/adopt.test.js +72 -27
- package/dist/project/adopt.test.js.map +1 -1
- package/dist/project/detectors/backend.d.ts +4 -0
- package/dist/project/detectors/backend.d.ts.map +1 -0
- package/dist/project/detectors/backend.js +199 -0
- package/dist/project/detectors/backend.js.map +1 -0
- package/dist/project/detectors/backend.test.d.ts +2 -0
- package/dist/project/detectors/backend.test.d.ts.map +1 -0
- package/dist/project/detectors/backend.test.js +64 -0
- package/dist/project/detectors/backend.test.js.map +1 -0
- package/dist/project/detectors/browser-extension.d.ts +4 -0
- package/dist/project/detectors/browser-extension.d.ts.map +1 -0
- package/dist/project/detectors/browser-extension.js +61 -0
- package/dist/project/detectors/browser-extension.js.map +1 -0
- package/dist/project/detectors/browser-extension.test.d.ts +2 -0
- package/dist/project/detectors/browser-extension.test.d.ts.map +1 -0
- package/dist/project/detectors/browser-extension.test.js +64 -0
- package/dist/project/detectors/browser-extension.test.js.map +1 -0
- package/dist/project/detectors/cli.d.ts +4 -0
- package/dist/project/detectors/cli.d.ts.map +1 -0
- package/dist/project/detectors/cli.js +68 -0
- package/dist/project/detectors/cli.js.map +1 -0
- package/dist/project/detectors/cli.test.d.ts +2 -0
- package/dist/project/detectors/cli.test.d.ts.map +1 -0
- package/dist/project/detectors/cli.test.js +70 -0
- package/dist/project/detectors/cli.test.js.map +1 -0
- package/dist/project/detectors/context.d.ts +105 -0
- package/dist/project/detectors/context.d.ts.map +1 -0
- package/dist/project/detectors/context.js +652 -0
- package/dist/project/detectors/context.js.map +1 -0
- package/dist/project/detectors/context.test.d.ts +2 -0
- package/dist/project/detectors/context.test.d.ts.map +1 -0
- package/dist/project/detectors/context.test.js +240 -0
- package/dist/project/detectors/context.test.js.map +1 -0
- package/dist/project/detectors/data-pipeline.d.ts +4 -0
- package/dist/project/detectors/data-pipeline.d.ts.map +1 -0
- package/dist/project/detectors/data-pipeline.js +97 -0
- package/dist/project/detectors/data-pipeline.js.map +1 -0
- package/dist/project/detectors/data-pipeline.test.d.ts +2 -0
- package/dist/project/detectors/data-pipeline.test.d.ts.map +1 -0
- package/dist/project/detectors/data-pipeline.test.js +67 -0
- package/dist/project/detectors/data-pipeline.test.js.map +1 -0
- package/dist/project/detectors/disambiguate.d.ts +12 -0
- package/dist/project/detectors/disambiguate.d.ts.map +1 -0
- package/dist/project/detectors/disambiguate.js +87 -0
- package/dist/project/detectors/disambiguate.js.map +1 -0
- package/dist/project/detectors/disambiguate.test.d.ts +2 -0
- package/dist/project/detectors/disambiguate.test.d.ts.map +1 -0
- package/dist/project/detectors/disambiguate.test.js +114 -0
- package/dist/project/detectors/disambiguate.test.js.map +1 -0
- package/dist/project/detectors/file-text-match.d.ts +3 -0
- package/dist/project/detectors/file-text-match.d.ts.map +1 -0
- package/dist/project/detectors/file-text-match.js +60 -0
- package/dist/project/detectors/file-text-match.js.map +1 -0
- package/dist/project/detectors/file-text-match.test.d.ts +2 -0
- package/dist/project/detectors/file-text-match.test.d.ts.map +1 -0
- package/dist/project/detectors/file-text-match.test.js +81 -0
- package/dist/project/detectors/file-text-match.test.js.map +1 -0
- package/dist/project/detectors/game.d.ts +18 -0
- package/dist/project/detectors/game.d.ts.map +1 -0
- package/dist/project/detectors/game.js +83 -0
- package/dist/project/detectors/game.js.map +1 -0
- package/dist/project/detectors/game.test.d.ts +2 -0
- package/dist/project/detectors/game.test.d.ts.map +1 -0
- package/dist/project/detectors/game.test.js +87 -0
- package/dist/project/detectors/game.test.js.map +1 -0
- package/dist/project/detectors/index.d.ts +5 -0
- package/dist/project/detectors/index.d.ts.map +1 -0
- package/dist/project/detectors/index.js +29 -0
- package/dist/project/detectors/index.js.map +1 -0
- package/dist/project/detectors/library.d.ts +4 -0
- package/dist/project/detectors/library.d.ts.map +1 -0
- package/dist/project/detectors/library.js +117 -0
- package/dist/project/detectors/library.js.map +1 -0
- package/dist/project/detectors/library.test.d.ts +2 -0
- package/dist/project/detectors/library.test.d.ts.map +1 -0
- package/dist/project/detectors/library.test.js +73 -0
- package/dist/project/detectors/library.test.js.map +1 -0
- package/dist/project/detectors/ml.d.ts +4 -0
- package/dist/project/detectors/ml.d.ts.map +1 -0
- package/dist/project/detectors/ml.js +112 -0
- package/dist/project/detectors/ml.js.map +1 -0
- package/dist/project/detectors/ml.test.d.ts +2 -0
- package/dist/project/detectors/ml.test.d.ts.map +1 -0
- package/dist/project/detectors/ml.test.js +75 -0
- package/dist/project/detectors/ml.test.js.map +1 -0
- package/dist/project/detectors/mobile-app.d.ts +4 -0
- package/dist/project/detectors/mobile-app.d.ts.map +1 -0
- package/dist/project/detectors/mobile-app.js +58 -0
- package/dist/project/detectors/mobile-app.js.map +1 -0
- package/dist/project/detectors/mobile-app.test.d.ts +2 -0
- package/dist/project/detectors/mobile-app.test.d.ts.map +1 -0
- package/dist/project/detectors/mobile-app.test.js +57 -0
- package/dist/project/detectors/mobile-app.test.js.map +1 -0
- package/dist/project/detectors/required-fields.d.ts +4 -0
- package/dist/project/detectors/required-fields.d.ts.map +1 -0
- package/dist/project/detectors/required-fields.js +13 -0
- package/dist/project/detectors/required-fields.js.map +1 -0
- package/dist/project/detectors/required-fields.test.d.ts +2 -0
- package/dist/project/detectors/required-fields.test.d.ts.map +1 -0
- package/dist/project/detectors/required-fields.test.js +24 -0
- package/dist/project/detectors/required-fields.test.js.map +1 -0
- package/dist/project/detectors/resolve-detection.d.ts +18 -0
- package/dist/project/detectors/resolve-detection.d.ts.map +1 -0
- package/dist/project/detectors/resolve-detection.js +184 -0
- package/dist/project/detectors/resolve-detection.js.map +1 -0
- package/dist/project/detectors/resolve-detection.test.d.ts +2 -0
- package/dist/project/detectors/resolve-detection.test.d.ts.map +1 -0
- package/dist/project/detectors/resolve-detection.test.js +158 -0
- package/dist/project/detectors/resolve-detection.test.js.map +1 -0
- package/dist/project/detectors/types.d.ts +56 -0
- package/dist/project/detectors/types.d.ts.map +1 -0
- package/dist/project/detectors/types.js +9 -0
- package/dist/project/detectors/types.js.map +1 -0
- package/dist/project/detectors/web-app.d.ts +15 -0
- package/dist/project/detectors/web-app.d.ts.map +1 -0
- package/dist/project/detectors/web-app.js +228 -0
- package/dist/project/detectors/web-app.js.map +1 -0
- package/dist/project/detectors/web-app.test.d.ts +2 -0
- package/dist/project/detectors/web-app.test.d.ts.map +1 -0
- package/dist/project/detectors/web-app.test.js +95 -0
- package/dist/project/detectors/web-app.test.js.map +1 -0
- package/dist/types/config.d.ts +41 -17
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/enums.d.ts +2 -1
- package/dist/types/enums.d.ts.map +1 -1
- package/dist/types/enums.js +1 -0
- package/dist/types/enums.js.map +1 -1
- package/dist/utils/errors.d.ts +7 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +38 -0
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/errors.test.js +42 -1
- package/dist/utils/errors.test.js.map +1 -1
- package/dist/wizard/flags.d.ts +82 -0
- package/dist/wizard/flags.d.ts.map +1 -0
- package/dist/wizard/flags.js +19 -0
- package/dist/wizard/flags.js.map +1 -0
- package/dist/wizard/questions.d.ts +10 -45
- package/dist/wizard/questions.d.ts.map +1 -1
- package/dist/wizard/questions.js +119 -156
- package/dist/wizard/questions.js.map +1 -1
- package/dist/wizard/questions.test.js +73 -55
- package/dist/wizard/questions.test.js.map +1 -1
- package/dist/wizard/wizard.d.ts +11 -45
- package/dist/wizard/wizard.d.ts.map +1 -1
- package/dist/wizard/wizard.js +10 -46
- package/dist/wizard/wizard.js.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disambiguate.js","sourceRoot":"","sources":["../../../src/project/detectors/disambiguate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disambiguate.test.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/disambiguate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any -- test mocks need flexible typing */
|
|
2
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
3
|
+
import { disambiguate } from './disambiguate.js';
|
|
4
|
+
vi.mock('@inquirer/prompts', () => ({
|
|
5
|
+
select: vi.fn(),
|
|
6
|
+
ExitPromptError: class extends Error {
|
|
7
|
+
name = 'ExitPromptError';
|
|
8
|
+
},
|
|
9
|
+
}));
|
|
10
|
+
const mockMatch = (type, confidence, evidenceCount = 2) => ({
|
|
11
|
+
projectType: type,
|
|
12
|
+
confidence,
|
|
13
|
+
partialConfig: {},
|
|
14
|
+
evidence: Array(evidenceCount).fill({ signal: 'test' }),
|
|
15
|
+
});
|
|
16
|
+
describe('disambiguate', () => {
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
vi.clearAllMocks();
|
|
19
|
+
// Simulate interactive TTY
|
|
20
|
+
Object.defineProperty(process.stdin, 'isTTY', { value: true, configurable: true });
|
|
21
|
+
Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
|
|
22
|
+
delete process.env.CI;
|
|
23
|
+
});
|
|
24
|
+
it('returns no-eligible-matches for empty input', async () => {
|
|
25
|
+
const result = await disambiguate([], { interactive: true, acceptLowConfidence: false });
|
|
26
|
+
expect(result.chosen).toBeNull();
|
|
27
|
+
expect(result.skipReason).toBe('no-eligible-matches');
|
|
28
|
+
});
|
|
29
|
+
it('returns skipReason auto under --auto', async () => {
|
|
30
|
+
const result = await disambiguate([mockMatch('web-app', 'high'), mockMatch('backend', 'high')], { interactive: false, acceptLowConfidence: false });
|
|
31
|
+
expect(result.chosen).toBeNull();
|
|
32
|
+
expect(result.skipReason).toBe('auto');
|
|
33
|
+
});
|
|
34
|
+
it('returns nonTtyFallback when stdin not TTY', async () => {
|
|
35
|
+
Object.defineProperty(process.stdin, 'isTTY', { value: false, configurable: true });
|
|
36
|
+
const result = await disambiguate([mockMatch('web-app', 'high'), mockMatch('backend', 'high')], { interactive: true, acceptLowConfidence: false });
|
|
37
|
+
expect(result.chosen).toBeNull();
|
|
38
|
+
expect(result.skipReason).toBe('auto');
|
|
39
|
+
expect(result.nonTtyFallback).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
it('returns nonTtyFallback when CI env set', async () => {
|
|
42
|
+
process.env.CI = 'true';
|
|
43
|
+
const result = await disambiguate([mockMatch('web-app', 'high'), mockMatch('backend', 'high')], { interactive: true, acceptLowConfidence: false });
|
|
44
|
+
expect(result.skipReason).toBe('auto');
|
|
45
|
+
expect(result.nonTtyFallback).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
it('filters low matches unless forced', async () => {
|
|
48
|
+
const matches = [mockMatch('web-app', 'high'), mockMatch('library', 'low')];
|
|
49
|
+
// We don't actually prompt here — using --auto to check filtering behavior
|
|
50
|
+
const result = await disambiguate(matches, { interactive: false, acceptLowConfidence: false });
|
|
51
|
+
expect(result.skipReason).toBe('auto');
|
|
52
|
+
});
|
|
53
|
+
it('includes low matches when acceptLowConfidence is true', async () => {
|
|
54
|
+
const matches = [mockMatch('web-app', 'high'), mockMatch('library', 'low')];
|
|
55
|
+
const result = await disambiguate(matches, { interactive: false, acceptLowConfidence: true });
|
|
56
|
+
expect(result.skipReason).toBe('auto');
|
|
57
|
+
});
|
|
58
|
+
it('interactive prompt returns chosen match when select resolves to a match', async () => {
|
|
59
|
+
const { select } = await import('@inquirer/prompts');
|
|
60
|
+
vi.mocked(select).mockResolvedValueOnce(mockMatch('backend', 'high'));
|
|
61
|
+
const result = await disambiguate([mockMatch('web-app', 'high'), mockMatch('backend', 'high')], { interactive: true, acceptLowConfidence: false });
|
|
62
|
+
expect(result.chosen?.projectType).toBe('backend');
|
|
63
|
+
expect(result.skipReason).toBeUndefined();
|
|
64
|
+
});
|
|
65
|
+
it('user-skipped (None of these) → skipReason user-skipped', async () => {
|
|
66
|
+
const { select } = await import('@inquirer/prompts');
|
|
67
|
+
vi.mocked(select).mockResolvedValueOnce(null); // "None of these"
|
|
68
|
+
const result = await disambiguate([mockMatch('web-app', 'high'), mockMatch('backend', 'high')], { interactive: true, acceptLowConfidence: false });
|
|
69
|
+
expect(result.chosen).toBeNull();
|
|
70
|
+
expect(result.skipReason).toBe('user-skipped');
|
|
71
|
+
});
|
|
72
|
+
it('ExitPromptError (Ctrl-C) → skipReason user-cancelled', async () => {
|
|
73
|
+
const { select, ExitPromptError } = await import('@inquirer/prompts');
|
|
74
|
+
vi.mocked(select).mockRejectedValueOnce(new ExitPromptError('User cancelled'));
|
|
75
|
+
const result = await disambiguate([mockMatch('web-app', 'high'), mockMatch('backend', 'high')], { interactive: true, acceptLowConfidence: false });
|
|
76
|
+
expect(result.chosen).toBeNull();
|
|
77
|
+
expect(result.skipReason).toBe('user-cancelled');
|
|
78
|
+
});
|
|
79
|
+
it('non-ExitPromptError is re-thrown', async () => {
|
|
80
|
+
const { select } = await import('@inquirer/prompts');
|
|
81
|
+
vi.mocked(select).mockRejectedValueOnce(new Error('unexpected'));
|
|
82
|
+
await expect(disambiguate([mockMatch('web-app', 'high'), mockMatch('backend', 'high')], { interactive: true, acceptLowConfidence: false })).rejects.toThrow('unexpected');
|
|
83
|
+
});
|
|
84
|
+
it('sort order: high before medium before low', async () => {
|
|
85
|
+
const { select } = await import('@inquirer/prompts');
|
|
86
|
+
let choicesArg = [];
|
|
87
|
+
vi.mocked(select).mockImplementationOnce(async ({ choices }) => {
|
|
88
|
+
choicesArg = choices;
|
|
89
|
+
return choices[0].value;
|
|
90
|
+
});
|
|
91
|
+
await disambiguate([
|
|
92
|
+
mockMatch('library', 'low'),
|
|
93
|
+
mockMatch('backend', 'medium'),
|
|
94
|
+
mockMatch('web-app', 'high'),
|
|
95
|
+
], { interactive: true, acceptLowConfidence: true });
|
|
96
|
+
// First choice is web-app (high tier)
|
|
97
|
+
expect(choicesArg[0].value.projectType).toBe('web-app');
|
|
98
|
+
// Last meaningful choice is library (low tier)
|
|
99
|
+
expect(choicesArg[2].value.projectType).toBe('library');
|
|
100
|
+
// Last choice is the "None of these" sentinel
|
|
101
|
+
expect(choicesArg[3].value).toBeNull();
|
|
102
|
+
});
|
|
103
|
+
it('Case F: low-only matches render with "weak signals" header', async () => {
|
|
104
|
+
const { select } = await import('@inquirer/prompts');
|
|
105
|
+
let messageArg = '';
|
|
106
|
+
vi.mocked(select).mockImplementationOnce(async ({ message, choices }) => {
|
|
107
|
+
messageArg = message;
|
|
108
|
+
return choices[0].value;
|
|
109
|
+
});
|
|
110
|
+
await disambiguate([mockMatch('library', 'low')], { interactive: true, acceptLowConfidence: true });
|
|
111
|
+
expect(messageArg).toContain('weak signals');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
//# sourceMappingURL=disambiguate.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disambiguate.test.js","sourceRoot":"","sources":["../../../src/project/detectors/disambiguate.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-text-match.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/file-text-match.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAsCzD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAcxF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/project/detectors/file-text-match.ts
|
|
2
|
+
// Strips comments and template literal content from JS/TS source
|
|
3
|
+
// before doing substring or regex matches, to reduce false positives.
|
|
4
|
+
export function stripJsTsComments(content) {
|
|
5
|
+
// Step 1: strip /* */ and /** */ comments
|
|
6
|
+
const result = content.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
7
|
+
// Step 2: strip single-line // comments (respecting strings)
|
|
8
|
+
// inTemplate MUST persist across line boundaries — template literals can
|
|
9
|
+
// span multiple lines in JS/TS. inSingle/inDouble reset per line because
|
|
10
|
+
// raw string literals can't span newlines, and prevWasBackslash also
|
|
11
|
+
// resets because a backslash doesn't escape a newline for line-comment
|
|
12
|
+
// purposes. See file-text-match.test.ts for regression coverage.
|
|
13
|
+
const lines = result.split('\n');
|
|
14
|
+
let inTemplate = false;
|
|
15
|
+
const stripped = lines.map(line => {
|
|
16
|
+
let inSingle = false, inDouble = false;
|
|
17
|
+
let prevWasBackslash = false;
|
|
18
|
+
for (let i = 0; i < line.length; i++) {
|
|
19
|
+
const ch = line[i];
|
|
20
|
+
if (!inSingle && !inDouble && !inTemplate && ch === '/' && line[i + 1] === '/') {
|
|
21
|
+
return line.slice(0, i);
|
|
22
|
+
}
|
|
23
|
+
if (prevWasBackslash) {
|
|
24
|
+
// This char is escaped — ignore it for toggle logic
|
|
25
|
+
prevWasBackslash = false;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (ch === '\\') {
|
|
29
|
+
prevWasBackslash = true;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (!inDouble && !inTemplate && ch === '\'')
|
|
33
|
+
inSingle = !inSingle;
|
|
34
|
+
else if (!inSingle && !inTemplate && ch === '"')
|
|
35
|
+
inDouble = !inDouble;
|
|
36
|
+
else if (!inSingle && !inDouble && ch === '`')
|
|
37
|
+
inTemplate = !inTemplate;
|
|
38
|
+
}
|
|
39
|
+
return line;
|
|
40
|
+
}).join('\n');
|
|
41
|
+
// Step 3: blank out template literal contents
|
|
42
|
+
return stripped.replace(/`[^`]*`/g, '``');
|
|
43
|
+
}
|
|
44
|
+
export function matchesConfigExport(content, key, value) {
|
|
45
|
+
const stripped = stripJsTsComments(content);
|
|
46
|
+
// Find the export boundary
|
|
47
|
+
const markers = ['module.exports', 'export default', 'defineConfig('];
|
|
48
|
+
let exportIdx = -1;
|
|
49
|
+
for (const marker of markers) {
|
|
50
|
+
const idx = stripped.indexOf(marker);
|
|
51
|
+
if (idx >= 0 && (exportIdx === -1 || idx < exportIdx))
|
|
52
|
+
exportIdx = idx;
|
|
53
|
+
}
|
|
54
|
+
const region = exportIdx >= 0 ? stripped.slice(exportIdx) : stripped;
|
|
55
|
+
const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
56
|
+
const escapedValue = value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
57
|
+
const pattern = new RegExp(`\\b${escapedKey}\\s*:\\s*['"]${escapedValue}['"]`);
|
|
58
|
+
return pattern.test(region);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=file-text-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-text-match.js","sourceRoot":"","sources":["../../../src/project/detectors/file-text-match.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-text-match.test.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/file-text-match.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { stripJsTsComments, matchesConfigExport } from './file-text-match.js';
|
|
3
|
+
describe('stripJsTsComments', () => {
|
|
4
|
+
it('strips single-line comments', () => {
|
|
5
|
+
expect(stripJsTsComments('const x = 1 // comment')).toBe('const x = 1 ');
|
|
6
|
+
});
|
|
7
|
+
it('strips block comments', () => {
|
|
8
|
+
expect(stripJsTsComments('const x = /* c */ 1')).toBe('const x = 1');
|
|
9
|
+
});
|
|
10
|
+
it('strips JSDoc', () => {
|
|
11
|
+
expect(stripJsTsComments('/** @param x */\nconst f = 1')).toContain('const f = 1');
|
|
12
|
+
});
|
|
13
|
+
it('does not strip // inside strings', () => {
|
|
14
|
+
expect(stripJsTsComments('const url = "http://example.com"')).toContain('http://example.com');
|
|
15
|
+
});
|
|
16
|
+
it('blanks template literal contents', () => {
|
|
17
|
+
expect(stripJsTsComments('const x = `output: "export"`')).toBe('const x = ``');
|
|
18
|
+
});
|
|
19
|
+
it('handles escaped backslashes before quote correctly', () => {
|
|
20
|
+
// The string literal is: const path = "C:\\" // comment
|
|
21
|
+
// That's a string containing a single backslash, followed by // comment.
|
|
22
|
+
// Before the fix, the \\ before " would confuse the escape tracker and
|
|
23
|
+
// leave the comment stripper in a bad state.
|
|
24
|
+
const input = 'const path = "C:\\\\" // comment';
|
|
25
|
+
const output = stripJsTsComments(input);
|
|
26
|
+
// The // comment should be stripped (it's outside the string)
|
|
27
|
+
expect(output).toBe('const path = "C:\\\\" ');
|
|
28
|
+
});
|
|
29
|
+
// F2: multi-line template literals must not reset `inTemplate` state at
|
|
30
|
+
// line boundaries. Before the fix, a `//` on an interior template line was
|
|
31
|
+
// sliced as a comment, destroying the closing backtick and corrupting
|
|
32
|
+
// downstream regex matches.
|
|
33
|
+
it('does not slice // inside a multi-line template literal', () => {
|
|
34
|
+
// Template spans 3 lines; middle line has `//` which is NOT a comment.
|
|
35
|
+
const input = 'const t = `line1\n// line2\nline3`';
|
|
36
|
+
const output = stripJsTsComments(input);
|
|
37
|
+
// After Step 3, the entire template collapses to ``.
|
|
38
|
+
// The output should start with the declaration and end with the
|
|
39
|
+
// collapsed template. Critically, nothing after the template start
|
|
40
|
+
// should be sliced off.
|
|
41
|
+
expect(output.startsWith('const t = ')).toBe(true);
|
|
42
|
+
expect(output.endsWith('``')).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
it('preserves multi-line template literals with embedded // patterns', () => {
|
|
45
|
+
// A SQL-style template literal on 3 lines with `//` on the middle line.
|
|
46
|
+
// Before the fix, line 2's `//` was misread as a line comment and the
|
|
47
|
+
// closing backtick was sliced off.
|
|
48
|
+
const input = 'const sql = `\nSELECT * FROM users // not a comment\nWHERE id = 1`';
|
|
49
|
+
const output = stripJsTsComments(input);
|
|
50
|
+
// Step 3 blanks the template to `` — assert the collapsed backticks survive.
|
|
51
|
+
expect(output).toContain('``');
|
|
52
|
+
// And the declaration prefix must be intact.
|
|
53
|
+
expect(output.startsWith('const sql = ')).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('matchesConfigExport', () => {
|
|
57
|
+
it('matches a primitive export default directive', () => {
|
|
58
|
+
const content = 'export default { output: \'export\' }';
|
|
59
|
+
expect(matchesConfigExport(content, 'output', 'export')).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
it('matches module.exports variant', () => {
|
|
62
|
+
const content = 'module.exports = { output: "standalone" }';
|
|
63
|
+
expect(matchesConfigExport(content, 'output', 'standalone')).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
it('matches defineConfig() wrapper', () => {
|
|
66
|
+
expect(matchesConfigExport('export default defineConfig({ output: \'hybrid\' })', 'output', 'hybrid')).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
it('does not match inside line comments', () => {
|
|
69
|
+
const content = '// output: \'export\'\nexport default {}';
|
|
70
|
+
expect(matchesConfigExport(content, 'output', 'export')).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
it('does not match inside template literals', () => {
|
|
73
|
+
const content = 'const s = `output: \'export\'`\nexport default {}';
|
|
74
|
+
expect(matchesConfigExport(content, 'output', 'export')).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
it('does not match dynamic expressions', () => {
|
|
77
|
+
const content = 'export default { output: process.env.X ? \'export\' : undefined }';
|
|
78
|
+
expect(matchesConfigExport(content, 'output', 'export')).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=file-text-match.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-text-match.test.js","sourceRoot":"","sources":["../../../src/project/detectors/file-text-match.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SignalContext } from './context.js';
|
|
2
|
+
import type { GameMatch } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Detects game projects by engine signature (per spec Section 5.9):
|
|
5
|
+
* Unity → Assets/ directory containing any *.meta file
|
|
6
|
+
* Unreal → *.uproject at root
|
|
7
|
+
* Godot → project.godot at root
|
|
8
|
+
* Bevy → Cargo.toml with bevy dep → engine: 'custom'
|
|
9
|
+
* Love2D → conf.lua + main.lua at root → engine: 'custom'
|
|
10
|
+
* JS games → phaser, babylonjs, or (three + index.html) → engine: 'custom'
|
|
11
|
+
*
|
|
12
|
+
* Precedence: Unity > Unreal > Godot > Bevy > Love2D > JS (locked by regression test
|
|
13
|
+
* in src/project/adopt.test.ts — "Unity wins precedence when multi-engine signatures coexist").
|
|
14
|
+
*
|
|
15
|
+
* IMPORTANT: this detector ONLY uses the SignalContext API — no direct fs/path imports.
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectGame(ctx: SignalContext): GameMatch | null;
|
|
18
|
+
//# sourceMappingURL=game.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/game.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAG3C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,CA0E/D"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { evidence } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Detects game projects by engine signature (per spec Section 5.9):
|
|
4
|
+
* Unity → Assets/ directory containing any *.meta file
|
|
5
|
+
* Unreal → *.uproject at root
|
|
6
|
+
* Godot → project.godot at root
|
|
7
|
+
* Bevy → Cargo.toml with bevy dep → engine: 'custom'
|
|
8
|
+
* Love2D → conf.lua + main.lua at root → engine: 'custom'
|
|
9
|
+
* JS games → phaser, babylonjs, or (three + index.html) → engine: 'custom'
|
|
10
|
+
*
|
|
11
|
+
* Precedence: Unity > Unreal > Godot > Bevy > Love2D > JS (locked by regression test
|
|
12
|
+
* in src/project/adopt.test.ts — "Unity wins precedence when multi-engine signatures coexist").
|
|
13
|
+
*
|
|
14
|
+
* IMPORTANT: this detector ONLY uses the SignalContext API — no direct fs/path imports.
|
|
15
|
+
*/
|
|
16
|
+
export function detectGame(ctx) {
|
|
17
|
+
// Unity — Assets/ with at least one .meta file
|
|
18
|
+
if (ctx.dirExists('Assets')) {
|
|
19
|
+
const assetsEntries = ctx.listDir('Assets');
|
|
20
|
+
if (assetsEntries.some(name => name.endsWith('.meta'))) {
|
|
21
|
+
return {
|
|
22
|
+
projectType: 'game',
|
|
23
|
+
confidence: 'high',
|
|
24
|
+
partialConfig: { engine: 'unity' },
|
|
25
|
+
evidence: [evidence('unity-assets-meta', 'Assets/')],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Unreal — any *.uproject at root
|
|
30
|
+
const uproject = ctx.rootEntries().find(f => f.endsWith('.uproject'));
|
|
31
|
+
if (uproject) {
|
|
32
|
+
return {
|
|
33
|
+
projectType: 'game',
|
|
34
|
+
confidence: 'high',
|
|
35
|
+
partialConfig: { engine: 'unreal' },
|
|
36
|
+
evidence: [evidence('unreal-uproject', uproject)],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Godot — project.godot at root
|
|
40
|
+
if (ctx.hasFile('project.godot')) {
|
|
41
|
+
return {
|
|
42
|
+
projectType: 'game',
|
|
43
|
+
confidence: 'high',
|
|
44
|
+
partialConfig: { engine: 'godot' },
|
|
45
|
+
evidence: [evidence('godot-project', 'project.godot')],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// Bevy — Rust game engine
|
|
49
|
+
if (ctx.hasDep('bevy', 'cargo')) {
|
|
50
|
+
return {
|
|
51
|
+
projectType: 'game',
|
|
52
|
+
confidence: 'high',
|
|
53
|
+
partialConfig: { engine: 'custom' },
|
|
54
|
+
evidence: [evidence('bevy-dep', 'Cargo.toml')],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// Love2D — Lua game engine. conf.lua + main.lua at root is the canonical signature.
|
|
58
|
+
if (ctx.hasFile('conf.lua') && ctx.hasFile('main.lua')) {
|
|
59
|
+
return {
|
|
60
|
+
projectType: 'game',
|
|
61
|
+
confidence: 'high',
|
|
62
|
+
partialConfig: { engine: 'custom' },
|
|
63
|
+
evidence: [evidence('love2d-conf', 'conf.lua')],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// JavaScript game engines — Phaser / Babylon / Three.js with an HTML entry
|
|
67
|
+
const hasJsGameDep = ctx.hasDep('phaser', 'npm')
|
|
68
|
+
|| ctx.hasDep('babylonjs', 'npm')
|
|
69
|
+
|| ctx.hasDep('@babylonjs/core', 'npm')
|
|
70
|
+
|| (ctx.hasDep('three', 'npm') && ctx.hasFile('index.html'));
|
|
71
|
+
if (hasJsGameDep) {
|
|
72
|
+
return {
|
|
73
|
+
projectType: 'game',
|
|
74
|
+
confidence: 'high',
|
|
75
|
+
partialConfig: { engine: 'custom' },
|
|
76
|
+
evidence: [
|
|
77
|
+
evidence('js-game-dep', 'package.json', 'phaser/babylonjs/three with HTML entry suggests browser game'),
|
|
78
|
+
],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=game.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"game.js","sourceRoot":"","sources":["../../../src/project/detectors/game.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"game.test.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/game.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { createSignalContext, createFakeSignalContext } from './context.js';
|
|
5
|
+
import { detectGame } from './game.js';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
const FIXTURES = path.join(__dirname, '../../../tests/fixtures/adopt/detectors/game');
|
|
9
|
+
describe('detectGame', () => {
|
|
10
|
+
it('detects Unity from Assets/*.meta', () => {
|
|
11
|
+
const ctx = createSignalContext(path.join(FIXTURES, 'unity-only'));
|
|
12
|
+
const match = detectGame(ctx);
|
|
13
|
+
expect(match).toBeTruthy();
|
|
14
|
+
expect(match?.projectType).toBe('game');
|
|
15
|
+
expect(match?.partialConfig.engine).toBe('unity');
|
|
16
|
+
expect(match?.confidence).toBe('high');
|
|
17
|
+
});
|
|
18
|
+
it('detects Unreal from *.uproject', () => {
|
|
19
|
+
const ctx = createSignalContext(path.join(FIXTURES, 'unreal-only'));
|
|
20
|
+
const match = detectGame(ctx);
|
|
21
|
+
expect(match?.partialConfig.engine).toBe('unreal');
|
|
22
|
+
});
|
|
23
|
+
it('detects Godot from project.godot', () => {
|
|
24
|
+
const ctx = createSignalContext(path.join(FIXTURES, 'godot-only'));
|
|
25
|
+
const match = detectGame(ctx);
|
|
26
|
+
expect(match?.partialConfig.engine).toBe('godot');
|
|
27
|
+
});
|
|
28
|
+
it('detects Bevy as custom engine', () => {
|
|
29
|
+
const ctx = createSignalContext(path.join(FIXTURES, 'bevy'));
|
|
30
|
+
const match = detectGame(ctx);
|
|
31
|
+
expect(match?.partialConfig.engine).toBe('custom');
|
|
32
|
+
});
|
|
33
|
+
it('returns null when no game signature exists', () => {
|
|
34
|
+
const ctx = createFakeSignalContext({
|
|
35
|
+
rootEntries: ['package.json'],
|
|
36
|
+
files: { 'package.json': '{"name":"demo"}' },
|
|
37
|
+
packageJson: { name: 'demo' },
|
|
38
|
+
});
|
|
39
|
+
expect(detectGame(ctx)).toBeNull();
|
|
40
|
+
});
|
|
41
|
+
it('Unity precedence: picks Unity when Unity + Unreal both present', () => {
|
|
42
|
+
const multiEngine = path.join(FIXTURES, 'multi-engine');
|
|
43
|
+
const ctx = createSignalContext(multiEngine);
|
|
44
|
+
const match = detectGame(ctx);
|
|
45
|
+
expect(match?.partialConfig.engine).toBe('unity');
|
|
46
|
+
});
|
|
47
|
+
it('emits evidence with signal and file', () => {
|
|
48
|
+
const ctx = createSignalContext(path.join(FIXTURES, 'godot-only'));
|
|
49
|
+
const match = detectGame(ctx);
|
|
50
|
+
expect(match?.evidence).toContainEqual({
|
|
51
|
+
signal: 'godot-project', file: 'project.godot', note: undefined,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
it('detects Love2D from conf.lua + main.lua', () => {
|
|
55
|
+
const ctx = createFakeSignalContext({
|
|
56
|
+
rootEntries: ['conf.lua', 'main.lua'],
|
|
57
|
+
files: { 'conf.lua': 'function love.conf(t) end', 'main.lua': 'function love.draw() end' },
|
|
58
|
+
});
|
|
59
|
+
const match = detectGame(ctx);
|
|
60
|
+
expect(match?.partialConfig.engine).toBe('custom');
|
|
61
|
+
expect(match?.evidence[0].signal).toBe('love2d-conf');
|
|
62
|
+
});
|
|
63
|
+
it('detects JS game from phaser npm dep', () => {
|
|
64
|
+
const ctx = createFakeSignalContext({
|
|
65
|
+
rootEntries: ['package.json'],
|
|
66
|
+
files: { 'package.json': '{"name":"x"}' },
|
|
67
|
+
packageJson: { name: 'x', dependencies: { phaser: '3.80' } },
|
|
68
|
+
});
|
|
69
|
+
const match = detectGame(ctx);
|
|
70
|
+
expect(match?.partialConfig.engine).toBe('custom');
|
|
71
|
+
expect(match?.evidence[0].signal).toBe('js-game-dep');
|
|
72
|
+
});
|
|
73
|
+
it('requires index.html alongside three for JS game detection', () => {
|
|
74
|
+
// three alone is not enough — could be a visualization project
|
|
75
|
+
const ctx = createFakeSignalContext({
|
|
76
|
+
rootEntries: ['package.json'],
|
|
77
|
+
files: { 'package.json': '{"name":"x"}' },
|
|
78
|
+
packageJson: { name: 'x', dependencies: { three: '0.160' } },
|
|
79
|
+
});
|
|
80
|
+
expect(detectGame(ctx)).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
it('returns null for empty directory', () => {
|
|
83
|
+
const ctx = createFakeSignalContext({ rootEntries: [] });
|
|
84
|
+
expect(detectGame(ctx)).toBeNull();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=game.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"game.test.js","sourceRoot":"","sources":["../../../src/project/detectors/game.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SignalContext } from './context.js';
|
|
2
|
+
import type { Detector, DetectionMatch } from './types.js';
|
|
3
|
+
export declare const ALL_DETECTORS: readonly Detector[];
|
|
4
|
+
export declare function runDetectors(ctx: SignalContext, detectors?: readonly Detector[]): DetectionMatch[];
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAa1D,eAAO,MAAM,aAAa,EAAE,SAAS,QAAQ,EAO5C,CAAA;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,aAAa,EAClB,SAAS,GAAE,SAAS,QAAQ,EAAkB,GAC7C,cAAc,EAAE,CAOlB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { detectGame } from './game.js';
|
|
2
|
+
import { detectBrowserExtension } from './browser-extension.js';
|
|
3
|
+
import { detectMobileApp } from './mobile-app.js';
|
|
4
|
+
import { detectDataPipeline } from './data-pipeline.js';
|
|
5
|
+
import { detectWebApp } from './web-app.js';
|
|
6
|
+
import { detectBackend } from './backend.js';
|
|
7
|
+
import { detectMl } from './ml.js';
|
|
8
|
+
import { detectCli } from './cli.js';
|
|
9
|
+
import { detectLibrary } from './library.js';
|
|
10
|
+
// Order is a PERFORMANCE optimization only. Correctness does NOT depend on order
|
|
11
|
+
// — all matches are collected and disambiguated per Section 3 Case A-G.
|
|
12
|
+
export const ALL_DETECTORS = [
|
|
13
|
+
// Tier 1: distinctive root-file detectors (cheap distinctive failures)
|
|
14
|
+
detectGame, detectBrowserExtension, detectMobileApp, detectDataPipeline,
|
|
15
|
+
// Tier 2: dep-heavy detectors
|
|
16
|
+
detectWebApp, detectBackend, detectMl, detectCli,
|
|
17
|
+
// Tier 3: catch-all
|
|
18
|
+
detectLibrary,
|
|
19
|
+
];
|
|
20
|
+
export function runDetectors(ctx, detectors = ALL_DETECTORS) {
|
|
21
|
+
const matches = [];
|
|
22
|
+
for (const detect of detectors) {
|
|
23
|
+
const match = detect(ctx);
|
|
24
|
+
if (match)
|
|
25
|
+
matches.push(match);
|
|
26
|
+
}
|
|
27
|
+
return matches;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/project/detectors/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C,iFAAiF;AACjF,wEAAwE;AACxE,MAAM,CAAC,MAAM,aAAa,GAAwB;IAChD,uEAAuE;IACvE,UAAU,EAAE,sBAAsB,EAAE,eAAe,EAAE,kBAAkB;IACvE,8BAA8B;IAC9B,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS;IAChD,oBAAoB;IACpB,aAAa;CACd,CAAA;AAED,MAAM,UAAU,YAAY,CAC1B,GAAkB,EAClB,YAAiC,aAAa;IAE9C,MAAM,OAAO,GAAqB,EAAE,CAAA;IACpC,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;QACzB,IAAI,KAAK;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAChC,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/library.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,YAAY,CAAA;AAGjE,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,GAAG,IAAI,CA6GrE"}
|