@flagshark/core 1.0.1 → 1.3.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.
Files changed (93) hide show
  1. package/dist/config/defaults.d.ts +3 -0
  2. package/dist/config/defaults.d.ts.map +1 -0
  3. package/dist/config/defaults.js +6 -0
  4. package/dist/config/defaults.js.map +1 -0
  5. package/dist/config/excluder.d.ts +18 -0
  6. package/dist/config/excluder.d.ts.map +1 -0
  7. package/dist/config/excluder.js +51 -0
  8. package/dist/config/excluder.js.map +1 -0
  9. package/dist/config/ignore-file.d.ts +6 -0
  10. package/dist/config/ignore-file.d.ts.map +1 -0
  11. package/dist/config/ignore-file.js +23 -0
  12. package/dist/config/ignore-file.js.map +1 -0
  13. package/dist/config/index.d.ts +7 -0
  14. package/dist/config/index.d.ts.map +1 -0
  15. package/dist/config/index.js +7 -0
  16. package/dist/config/index.js.map +1 -0
  17. package/dist/config/loader.d.ts +7 -0
  18. package/dist/config/loader.d.ts.map +1 -0
  19. package/dist/config/loader.js +47 -0
  20. package/dist/config/loader.js.map +1 -0
  21. package/dist/config/presets.d.ts +11 -0
  22. package/dist/config/presets.d.ts.map +1 -0
  23. package/dist/config/presets.js +70 -0
  24. package/dist/config/presets.js.map +1 -0
  25. package/dist/config/schema.d.ts +322 -0
  26. package/dist/config/schema.d.ts.map +1 -0
  27. package/dist/config/schema.js +63 -0
  28. package/dist/config/schema.js.map +1 -0
  29. package/dist/detection/detectors/go.d.ts +8 -2
  30. package/dist/detection/detectors/go.d.ts.map +1 -1
  31. package/dist/detection/detectors/go.js +8 -2
  32. package/dist/detection/detectors/go.js.map +1 -1
  33. package/dist/detection/detectors/javascript.d.ts +8 -2
  34. package/dist/detection/detectors/javascript.d.ts.map +1 -1
  35. package/dist/detection/detectors/javascript.js +8 -2
  36. package/dist/detection/detectors/javascript.js.map +1 -1
  37. package/dist/detection/detectors/python.d.ts +8 -2
  38. package/dist/detection/detectors/python.d.ts.map +1 -1
  39. package/dist/detection/detectors/python.js +8 -2
  40. package/dist/detection/detectors/python.js.map +1 -1
  41. package/dist/detection/detectors/typescript.d.ts +8 -2
  42. package/dist/detection/detectors/typescript.d.ts.map +1 -1
  43. package/dist/detection/detectors/typescript.js +8 -2
  44. package/dist/detection/detectors/typescript.js.map +1 -1
  45. package/dist/detection/helpers.d.ts +1 -1
  46. package/dist/detection/helpers.d.ts.map +1 -1
  47. package/dist/detection/helpers.js +9 -1
  48. package/dist/detection/helpers.js.map +1 -1
  49. package/dist/detection/index.d.ts +10 -0
  50. package/dist/detection/index.d.ts.map +1 -1
  51. package/dist/detection/index.js +31 -7
  52. package/dist/detection/index.js.map +1 -1
  53. package/dist/detection/interface.d.ts +1 -1
  54. package/dist/detection/interface.d.ts.map +1 -1
  55. package/dist/detection/registry.d.ts +1 -1
  56. package/dist/detection/registry.d.ts.map +1 -1
  57. package/dist/detection/tree-sitter/const-resolver.d.ts +8 -0
  58. package/dist/detection/tree-sitter/const-resolver.d.ts.map +1 -0
  59. package/dist/detection/tree-sitter/const-resolver.js +36 -0
  60. package/dist/detection/tree-sitter/const-resolver.js.map +1 -0
  61. package/dist/detection/tree-sitter/engine.d.ts +11 -0
  62. package/dist/detection/tree-sitter/engine.d.ts.map +1 -0
  63. package/dist/detection/tree-sitter/engine.js +81 -0
  64. package/dist/detection/tree-sitter/engine.js.map +1 -0
  65. package/dist/detection/tree-sitter/parser-cache.d.ts +6 -0
  66. package/dist/detection/tree-sitter/parser-cache.d.ts.map +1 -0
  67. package/dist/detection/tree-sitter/parser-cache.js +68 -0
  68. package/dist/detection/tree-sitter/parser-cache.js.map +1 -0
  69. package/dist/detection/tree-sitter/queries/go.scm +11 -0
  70. package/dist/detection/tree-sitter/queries/javascript.scm +13 -0
  71. package/dist/detection/tree-sitter/queries/python.scm +11 -0
  72. package/dist/detection/tree-sitter/queries/typescript.scm +11 -0
  73. package/dist/detection/tree-sitter/query-builder.d.ts +3 -0
  74. package/dist/detection/tree-sitter/query-builder.d.ts.map +1 -0
  75. package/dist/detection/tree-sitter/query-builder.js +7 -0
  76. package/dist/detection/tree-sitter/query-builder.js.map +1 -0
  77. package/dist/detection/tree-sitter/query-runner.d.ts +20 -0
  78. package/dist/detection/tree-sitter/query-runner.d.ts.map +1 -0
  79. package/dist/detection/tree-sitter/query-runner.js +83 -0
  80. package/dist/detection/tree-sitter/query-runner.js.map +1 -0
  81. package/dist/index.d.ts +1 -0
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +2 -0
  84. package/dist/index.js.map +1 -1
  85. package/dist/scan-repo.d.ts +27 -0
  86. package/dist/scan-repo.d.ts.map +1 -1
  87. package/dist/scan-repo.js +26 -5
  88. package/dist/scan-repo.js.map +1 -1
  89. package/dist/scanner.d.ts +11 -2
  90. package/dist/scanner.d.ts.map +1 -1
  91. package/dist/scanner.js +22 -7
  92. package/dist/scanner.js.map +1 -1
  93. package/package.json +12 -4
@@ -15,7 +15,7 @@ export declare class LanguageRegistry {
15
15
  /** Returns the appropriate detector for a file based on its extension. */
16
16
  getDetectorForFile(filename: string): LanguageDetector | undefined;
17
17
  /** Detects feature flags in a file using the appropriate language detector. */
18
- detectInFile(filename: string, content: string): FeatureFlag[] | null;
18
+ detectInFile(filename: string, content: string): FeatureFlag[] | Promise<FeatureFlag[]> | null;
19
19
  /** Returns all registered languages. */
20
20
  getSupportedLanguages(): Language[];
21
21
  /** Returns all supported file extensions (deduplicated). */
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/detection/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEhE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAwC;IAEzD,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAQ1C,oFAAoF;IACpF,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,gBAAgB,GAAG,SAAS;IAIzD,0EAA0E;IAC1E,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IASlE,+EAA+E;IAC/E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,IAAI;IAQrE,wCAAwC;IACxC,qBAAqB,IAAI,QAAQ,EAAE;IAInC,4DAA4D;IAC5D,sBAAsB,IAAI,MAAM,EAAE;CASnC;AAID,qDAAqD;AACrD,wBAAgB,kBAAkB,IAAI,gBAAgB,CAKrD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/detection/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEhE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAwC;IAEzD,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAQ1C,oFAAoF;IACpF,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,gBAAgB,GAAG,SAAS;IAIzD,0EAA0E;IAC1E,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IASlE,+EAA+E;IAC/E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,GAAG,IAAI;IAQ9F,wCAAwC;IACxC,qBAAqB,IAAI,QAAQ,EAAE;IAInC,4DAA4D;IAC5D,sBAAsB,IAAI,MAAM,EAAE;CASnC;AAID,qDAAqD;AACrD,wBAAgB,kBAAkB,IAAI,gBAAgB,CAKrD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
@@ -0,0 +1,8 @@
1
+ import type { Node } from 'web-tree-sitter';
2
+ /**
3
+ * If `node` is an identifier reference, look up its binding in the file's
4
+ * top-level `const NAME = '...'` declarations. Returns the string value
5
+ * or null. File-scope only — no nested scopes, no cross-file resolution.
6
+ */
7
+ export declare function resolveConstStringTS(node: Node, fileRoot: Node): string | null;
8
+ //# sourceMappingURL=const-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"const-resolver.d.ts","sourceRoot":"","sources":["../../../src/detection/tree-sitter/const-resolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAE3C;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAsB9E"}
@@ -0,0 +1,36 @@
1
+ import { extractStringLiteral } from './query-runner.js';
2
+ /**
3
+ * If `node` is an identifier reference, look up its binding in the file's
4
+ * top-level `const NAME = '...'` declarations. Returns the string value
5
+ * or null. File-scope only — no nested scopes, no cross-file resolution.
6
+ */
7
+ export function resolveConstStringTS(node, fileRoot) {
8
+ if (node.type !== 'identifier')
9
+ return null;
10
+ const name = node.text;
11
+ for (const child of fileRoot.namedChildren) {
12
+ if (!child)
13
+ continue;
14
+ if (child.type !== 'lexical_declaration')
15
+ continue;
16
+ if (child.children[0]?.type !== 'const')
17
+ continue;
18
+ for (const decl of child.namedChildren) {
19
+ if (!decl)
20
+ continue;
21
+ if (decl.type !== 'variable_declarator')
22
+ continue;
23
+ const nameNode = decl.childForFieldName('name');
24
+ const valueNode = decl.childForFieldName('value');
25
+ if (!nameNode || !valueNode)
26
+ continue;
27
+ if (nameNode.text !== name)
28
+ continue;
29
+ const literal = extractStringLiteral(valueNode);
30
+ if (literal !== null)
31
+ return literal;
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ //# sourceMappingURL=const-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"const-resolver.js","sourceRoot":"","sources":["../../../src/detection/tree-sitter/const-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAIxD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAU,EAAE,QAAc;IAC7D,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO,IAAI,CAAA;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;IAEtB,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3C,IAAI,CAAC,KAAK;YAAE,SAAQ;QACpB,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB;YAAE,SAAQ;QAClD,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,OAAO;YAAE,SAAQ;QAEjD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI;gBAAE,SAAQ;YACnB,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB;gBAAE,SAAQ;YACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAA;YAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAA;YACjD,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS;gBAAE,SAAQ;YACrC,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI;gBAAE,SAAQ;YACpC,MAAM,OAAO,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAA;YAC/C,IAAI,OAAO,KAAK,IAAI;gBAAE,OAAO,OAAO,CAAA;QACtC,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { FeatureFlag } from '../feature-flag.js';
2
+ import type { FeatureFlagProvider, Language } from '../interface.js';
3
+ /**
4
+ * Detect feature flags via tree-sitter. Mirrors detectFlagsWithRegex's contract.
5
+ *
6
+ * Import-gating: skip provider scans for files that don't contain the import pattern
7
+ * as a substring. Cheap text check before parsing — saves AST work on most files.
8
+ * Custom providers (no importPattern) always scan.
9
+ */
10
+ export declare function detectFlagsWithTreeSitter(filename: string, content: string, language: Language, providers: FeatureFlagProvider[]): Promise<FeatureFlag[]>;
11
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/detection/tree-sitter/engine.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAgB,MAAM,iBAAiB,CAAA;AAiBlF;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,mBAAmB,EAAE,GAC/B,OAAO,CAAC,WAAW,EAAE,CAAC,CA2DxB"}
@@ -0,0 +1,81 @@
1
+ import { deduplicateFlags } from '../helpers.js';
2
+ import { getImportPattern } from '../interface.js';
3
+ import { getParser } from './parser-cache.js';
4
+ import { getQuery, iterateCalls, getArgument, extractStringLiteral } from './query-runner.js';
5
+ import { resolveConstStringTS } from './const-resolver.js';
6
+ const FLAG_KEY_MAX_LENGTH = 256;
7
+ const INVALID_PREFIXES = ['http://', 'https://', 'file://', '/'];
8
+ function isValidFlagKey(key) {
9
+ if (key.length === 0 || key.length > FLAG_KEY_MAX_LENGTH)
10
+ return false;
11
+ for (const prefix of INVALID_PREFIXES) {
12
+ if (key.startsWith(prefix))
13
+ return false;
14
+ }
15
+ return true;
16
+ }
17
+ /**
18
+ * Detect feature flags via tree-sitter. Mirrors detectFlagsWithRegex's contract.
19
+ *
20
+ * Import-gating: skip provider scans for files that don't contain the import pattern
21
+ * as a substring. Cheap text check before parsing — saves AST work on most files.
22
+ * Custom providers (no importPattern) always scan.
23
+ */
24
+ export async function detectFlagsWithTreeSitter(filename, content, language, providers) {
25
+ const activeProviders = providers.filter((p) => {
26
+ if (!p.enabled)
27
+ return false;
28
+ if (p.methods.length === 0)
29
+ return false;
30
+ const importPat = getImportPattern(p);
31
+ if (!importPat)
32
+ return true;
33
+ return content.includes(importPat);
34
+ });
35
+ if (activeProviders.length === 0)
36
+ return [];
37
+ const methodLookup = new Map();
38
+ for (const provider of activeProviders) {
39
+ for (const method of provider.methods) {
40
+ if (method.flagKeyIndex < 0)
41
+ continue;
42
+ const list = methodLookup.get(method.name) ?? [];
43
+ list.push({ provider, method });
44
+ methodLookup.set(method.name, list);
45
+ }
46
+ }
47
+ if (methodLookup.size === 0)
48
+ return [];
49
+ const parser = await getParser(language);
50
+ const tree = parser.parse(content);
51
+ if (!tree)
52
+ return [];
53
+ const query = await getQuery(language);
54
+ const flags = [];
55
+ for (const { callNode, methodName, argsNode } of iterateCalls(tree, query)) {
56
+ const matches = methodLookup.get(methodName);
57
+ if (!matches)
58
+ continue;
59
+ for (const { provider, method } of matches) {
60
+ const arg = getArgument(argsNode, method.flagKeyIndex);
61
+ if (!arg)
62
+ continue;
63
+ let flagKey = extractStringLiteral(arg);
64
+ // Goal C: const-extraction for TypeScript/JavaScript
65
+ if (flagKey === null && (language === 'typescript' || language === 'javascript')) {
66
+ flagKey = resolveConstStringTS(arg, tree.rootNode);
67
+ }
68
+ if (!flagKey || !isValidFlagKey(flagKey))
69
+ continue;
70
+ flags.push({
71
+ name: flagKey,
72
+ filePath: filename,
73
+ lineNumber: callNode.startPosition.row + 1,
74
+ language,
75
+ provider: getImportPattern(provider) || provider.name,
76
+ });
77
+ }
78
+ }
79
+ return deduplicateFlags(flags);
80
+ }
81
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/detection/tree-sitter/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Parser } from 'web-tree-sitter';
2
+ import type { Language } from '../interface.js';
3
+ export declare function getParser(lang: Language): Promise<Parser>;
4
+ /** @internal — for tests only */
5
+ export declare function _resetParserCacheForTests(): void;
6
+ //# sourceMappingURL=parser-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser-cache.d.ts","sourceRoot":"","sources":["../../../src/detection/tree-sitter/parser-cache.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkC,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAExE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AA0C/C,wBAAsB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B/D;AAED,iCAAiC;AACjC,wBAAgB,yBAAyB,IAAI,IAAI,CAIhD"}
@@ -0,0 +1,68 @@
1
+ import { createRequire } from 'node:module';
2
+ import { Language as TreeSitterLanguage, Parser } from 'web-tree-sitter';
3
+ // Lazily created so that bundled CJS environments (where import.meta.url is
4
+ // unavailable) don't crash at module initialisation — we only need require_
5
+ // when FLAGSHARK_WASM_DIR is NOT set (i.e. normal npm / dev usage).
6
+ let require_ = null;
7
+ function getRequire() {
8
+ if (!require_) {
9
+ require_ = createRequire(import.meta.url);
10
+ }
11
+ return require_;
12
+ }
13
+ const WASM_RESOLUTION = {
14
+ typescript: 'tree-sitter-typescript/tree-sitter-typescript.wasm',
15
+ javascript: 'tree-sitter-javascript/tree-sitter-javascript.wasm',
16
+ go: 'tree-sitter-go/tree-sitter-go.wasm',
17
+ python: 'tree-sitter-python/tree-sitter-python.wasm',
18
+ };
19
+ const parsers = new Map();
20
+ const inFlight = new Map();
21
+ let initPromise = null;
22
+ async function ensureInit() {
23
+ if (!initPromise) {
24
+ initPromise = Parser.init();
25
+ }
26
+ await initPromise;
27
+ }
28
+ function resolveWasmPath(spec) {
29
+ // In an Action bundle, WASM files are copied next to action.cjs and resolved
30
+ // via process.env.FLAGSHARK_WASM_DIR (set by the bundle entry).
31
+ const bundleDir = process.env.FLAGSHARK_WASM_DIR;
32
+ if (bundleDir) {
33
+ const file = spec.split('/').pop();
34
+ return `${bundleDir}/${file}`;
35
+ }
36
+ return getRequire().resolve(spec);
37
+ }
38
+ export async function getParser(lang) {
39
+ await ensureInit();
40
+ const cached = parsers.get(lang);
41
+ if (cached)
42
+ return cached;
43
+ const pending = inFlight.get(lang);
44
+ if (pending)
45
+ return pending;
46
+ const wasmSpec = WASM_RESOLUTION[lang];
47
+ if (!wasmSpec) {
48
+ throw new Error(`No tree-sitter grammar registered for language: ${lang}`);
49
+ }
50
+ const load = (async () => {
51
+ const wasmPath = resolveWasmPath(wasmSpec);
52
+ const tsLang = await TreeSitterLanguage.load(wasmPath);
53
+ const parser = new Parser();
54
+ parser.setLanguage(tsLang);
55
+ parsers.set(lang, parser);
56
+ inFlight.delete(lang);
57
+ return parser;
58
+ })();
59
+ inFlight.set(lang, load);
60
+ return load;
61
+ }
62
+ /** @internal — for tests only */
63
+ export function _resetParserCacheForTests() {
64
+ parsers.clear();
65
+ inFlight.clear();
66
+ initPromise = null;
67
+ }
68
+ //# sourceMappingURL=parser-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser-cache.js","sourceRoot":"","sources":["../../../src/detection/tree-sitter/parser-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAIxE,4EAA4E;AAC5E,4EAA4E;AAC5E,oEAAoE;AACpE,IAAI,QAAQ,GAA4C,IAAI,CAAA;AAC5D,SAAS,UAAU;IACjB,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC3C,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,eAAe,GAAsC;IACzD,UAAU,EAAE,oDAAoD;IAChE,UAAU,EAAE,oDAAoD;IAChE,EAAE,EAAE,oCAAoC;IACxC,MAAM,EAAE,4CAA4C;CACrD,CAAA;AAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAA;AAC3C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAA;AACrD,IAAI,WAAW,GAAyB,IAAI,CAAA;AAE5C,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;IAC7B,CAAC;IACD,MAAM,WAAW,CAAA;AACnB,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,6EAA6E;IAC7E,gEAAgE;IAChE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAA;IAChD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAA;QACnC,OAAO,GAAG,SAAS,IAAI,IAAI,EAAE,CAAA;IAC/B,CAAC;IACD,OAAO,UAAU,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc;IAC5C,MAAM,UAAU,EAAE,CAAA;IAElB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAChC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IAEzB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAClC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAA;IAE3B,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;IACtC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,mDAAmD,IAAI,EAAE,CAAC,CAAA;IAC5E,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE;QACvB,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAA;QAC1C,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACtD,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAA;QAC3B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAC1B,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzB,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACrB,OAAO,MAAM,CAAA;IACf,CAAC,CAAC,EAAE,CAAA;IAEJ,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACxB,OAAO,IAAI,CAAA;AACb,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,yBAAyB;IACvC,OAAO,CAAC,KAAK,EAAE,CAAA;IACf,QAAQ,CAAC,KAAK,EAAE,CAAA;IAChB,WAAW,GAAG,IAAI,CAAA;AACpB,CAAC"}
@@ -0,0 +1,11 @@
1
+ ; Method call on a receiver: client.BoolVariation(...)
2
+ (call_expression
3
+ function: (selector_expression
4
+ operand: (_) @receiver
5
+ field: (field_identifier) @method)
6
+ arguments: (argument_list) @args) @call
7
+
8
+ ; Bare function call: BoolVariation(...)
9
+ (call_expression
10
+ function: (identifier) @method
11
+ arguments: (argument_list) @args) @call
@@ -0,0 +1,13 @@
1
+ ; tree-sitter-javascript's grammar uses identical node names to typescript
2
+ ; for these call shapes — we duplicate the file for clarity even though the
3
+ ; content is identical.
4
+
5
+ (call_expression
6
+ function: (member_expression
7
+ object: (_) @receiver
8
+ property: (property_identifier) @method)
9
+ arguments: (arguments) @args) @call
10
+
11
+ (call_expression
12
+ function: (identifier) @method
13
+ arguments: (arguments) @args) @call
@@ -0,0 +1,11 @@
1
+ ; Method call: client.variation(...)
2
+ (call
3
+ function: (attribute
4
+ object: (_) @receiver
5
+ attribute: (identifier) @method)
6
+ arguments: (argument_list) @args) @call
7
+
8
+ ; Bare function call: variation(...)
9
+ (call
10
+ function: (identifier) @method
11
+ arguments: (argument_list) @args) @call
@@ -0,0 +1,11 @@
1
+ ; Match method-style calls: <receiver>.<method>(<args>)
2
+ (call_expression
3
+ function: (member_expression
4
+ object: (_) @receiver
5
+ property: (property_identifier) @method)
6
+ arguments: (arguments) @args) @call
7
+
8
+ ; Match free-function calls: <method>(<args>)
9
+ (call_expression
10
+ function: (identifier) @method
11
+ arguments: (arguments) @args) @call
@@ -0,0 +1,3 @@
1
+ import type { Language } from '../interface.js';
2
+ export declare function buildMethodCallQuery(lang: Language): string;
3
+ //# sourceMappingURL=query-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-builder.d.ts","sourceRoot":"","sources":["../../../src/detection/tree-sitter/query-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAI/C,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAI3D"}
@@ -0,0 +1,7 @@
1
+ import { loadQueryText } from './query-runner.js';
2
+ export function buildMethodCallQuery(lang) {
3
+ // Today: just return the static query for the language.
4
+ // Future: synthesize per-method-set queries when we want predicate filtering inside the .scm.
5
+ return loadQueryText(lang);
6
+ }
7
+ //# sourceMappingURL=query-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-builder.js","sourceRoot":"","sources":["../../../src/detection/tree-sitter/query-builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,MAAM,UAAU,oBAAoB,CAAC,IAAc;IACjD,wDAAwD;IACxD,8FAA8F;IAC9F,OAAO,aAAa,CAAC,IAAI,CAAC,CAAA;AAC5B,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { Query } from 'web-tree-sitter';
2
+ import type { Node, Tree } from 'web-tree-sitter';
3
+ import type { Language } from '../interface.js';
4
+ /** Loads the .scm query text for a language, relative to this module. */
5
+ export declare function loadQueryText(lang: Language): string;
6
+ export declare function getQuery(lang: Language): Promise<Query>;
7
+ export interface MatchedCall {
8
+ callNode: Node;
9
+ methodName: string;
10
+ argsNode: Node;
11
+ }
12
+ /** Walks query matches and yields one MatchedCall per call expression. */
13
+ export declare function iterateCalls(tree: Tree, query: Query): Generator<MatchedCall>;
14
+ /** Returns the Nth argument node, or null if out of range. */
15
+ export declare function getArgument(argsNode: Node, index: number): Node | null;
16
+ /** Returns the string value if the node is a string literal, else null. */
17
+ export declare function extractStringLiteral(node: Node): string | null;
18
+ /** @internal — for tests */
19
+ export declare function _clearQueryCache(): void;
20
+ //# sourceMappingURL=query-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-runner.d.ts","sourceRoot":"","sources":["../../../src/detection/tree-sitter/query-runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAG/C,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CASpD;AAKD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAmB7D;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,IAAI,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,IAAI,CAAA;CACf;AAED,0EAA0E;AAC1E,wBAAiB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,CAS9E;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGtE;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAqB9D;AAED,4BAA4B;AAC5B,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC"}
@@ -0,0 +1,83 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { Query } from 'web-tree-sitter';
4
+ import { getParser } from './parser-cache.js';
5
+ /** Loads the .scm query text for a language, relative to this module. */
6
+ export function loadQueryText(lang) {
7
+ // In an Action bundle context, queries are vendored alongside the WASM grammars.
8
+ // FLAGSHARK_QUERIES_DIR (set by the action entry) points at dist/queries/.
9
+ const queriesDir = process.env.FLAGSHARK_QUERIES_DIR;
10
+ if (queriesDir) {
11
+ return readFileSync(`${queriesDir}/${lang}.scm`, 'utf-8');
12
+ }
13
+ const url = new URL(`./queries/${lang}.scm`, import.meta.url);
14
+ return readFileSync(fileURLToPath(url), 'utf-8');
15
+ }
16
+ const queryCache = new Map();
17
+ const inFlightQueries = new Map();
18
+ export async function getQuery(lang) {
19
+ const cached = queryCache.get(lang);
20
+ if (cached)
21
+ return cached;
22
+ const pending = inFlightQueries.get(lang);
23
+ if (pending)
24
+ return pending;
25
+ const load = (async () => {
26
+ const parser = await getParser(lang);
27
+ const tsLang = parser.language;
28
+ if (!tsLang)
29
+ throw new Error(`Parser for ${lang} has no language set`);
30
+ const query = new Query(tsLang, loadQueryText(lang));
31
+ queryCache.set(lang, query);
32
+ inFlightQueries.delete(lang);
33
+ return query;
34
+ })();
35
+ inFlightQueries.set(lang, load);
36
+ return load;
37
+ }
38
+ /** Walks query matches and yields one MatchedCall per call expression. */
39
+ export function* iterateCalls(tree, query) {
40
+ for (const match of query.matches(tree.rootNode)) {
41
+ const captures = match.captures;
42
+ const call = captures.find((c) => c.name === 'call')?.node;
43
+ const method = captures.find((c) => c.name === 'method')?.node;
44
+ const args = captures.find((c) => c.name === 'args')?.node;
45
+ if (!call || !method || !args)
46
+ continue;
47
+ yield { callNode: call, methodName: method.text, argsNode: args };
48
+ }
49
+ }
50
+ /** Returns the Nth argument node, or null if out of range. */
51
+ export function getArgument(argsNode, index) {
52
+ const realChildren = (argsNode.namedChildren.filter((n) => n !== null && n.type !== 'comment'));
53
+ return realChildren[index] ?? null;
54
+ }
55
+ /** Returns the string value if the node is a string literal, else null. */
56
+ export function extractStringLiteral(node) {
57
+ const type = node.type;
58
+ const text = node.text;
59
+ if (type === 'string' ||
60
+ type === 'string_literal' ||
61
+ type === 'interpreted_string_literal' ||
62
+ type === 'raw_string_literal' ||
63
+ type === 'template_string') {
64
+ if (text.length < 2)
65
+ return null;
66
+ const first = text[0];
67
+ const last = text[text.length - 1];
68
+ if (first === last && (first === '"' || first === "'" || first === '`')) {
69
+ return text.slice(1, -1);
70
+ }
71
+ if (text.startsWith('"""') && text.endsWith('"""'))
72
+ return text.slice(3, -3);
73
+ if (text.startsWith("'''") && text.endsWith("'''"))
74
+ return text.slice(3, -3);
75
+ }
76
+ return null;
77
+ }
78
+ /** @internal — for tests */
79
+ export function _clearQueryCache() {
80
+ queryCache.clear();
81
+ inFlightQueries.clear();
82
+ }
83
+ //# sourceMappingURL=query-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-runner.js","sourceRoot":"","sources":["../../../src/detection/tree-sitter/query-runner.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,4 +5,5 @@ export { collectFiles } from './scanner.js';
5
5
  export type { ScanOptions } from './scanner.js';
6
6
  export { scanRepo } from './scan-repo.js';
7
7
  export type { ScanRepoOptions, ScanRepoResult, ScanLogger } from './scan-repo.js';
8
+ export * from './config/index.js';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,sBAAsB,CAAA;AAGpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAGlF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,sBAAsB,CAAA;AAGpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAGlF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAGjF,cAAc,mBAAmB,CAAA"}
package/dist/index.js CHANGED
@@ -6,4 +6,6 @@ export { analyzeStaleness } from './staleness.js';
6
6
  export { collectFiles } from './scanner.js';
7
7
  // Re-export scanRepo orchestrator
8
8
  export { scanRepo } from './scan-repo.js';
9
+ // Config module
10
+ export * from './config/index.js';
9
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,cAAc,sBAAsB,CAAA;AAEpC,+BAA+B;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAGjD,gDAAgD;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAG3C,kCAAkC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,cAAc,sBAAsB,CAAA;AAEpC,+BAA+B;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAGjD,gDAAgD;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAG3C,kCAAkC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAGzC,gBAAgB;AAChB,cAAc,mBAAmB,CAAA"}
@@ -3,6 +3,8 @@
3
3
  * return a single result object that consumers can render however they like.
4
4
  */
5
5
  import type { StaleFlag } from './staleness.js';
6
+ import type { FlagsharkConfig } from './config/schema.js';
7
+ import type { EffectiveRules } from './config/excluder.js';
6
8
  export interface ScanLogger {
7
9
  debug: (...args: unknown[]) => void;
8
10
  info: (...args: unknown[]) => void;
@@ -36,6 +38,25 @@ export interface ScanRepoOptions {
36
38
  * Optional logger for debug/info/warn/error messages. Defaults to a no-op.
37
39
  */
38
40
  logger?: ScanLogger;
41
+ /** @internal — undocumented escape hatch for cross-engine smoke testing */
42
+ engine?: 'regex' | 'tree-sitter';
43
+ /**
44
+ * Explicit config to use. If undefined, scanRepo discovers .flagshark.yml
45
+ * from cwd upward.
46
+ */
47
+ config?: FlagsharkConfig;
48
+ /**
49
+ * Set true to skip auto-discovery of .flagshark.yml (used by --no-config).
50
+ */
51
+ noConfig?: boolean;
52
+ /**
53
+ * Set true to skip .flagsharkignore discovery (used by --no-ignore-file).
54
+ */
55
+ noIgnoreFile?: boolean;
56
+ /**
57
+ * When true, the result will include the list of excluded file paths.
58
+ */
59
+ collectExcludedPaths?: boolean;
39
60
  }
40
61
  export interface ScanRepoResult {
41
62
  /** Total count of unique flag names detected across the repository. */
@@ -62,6 +83,12 @@ export interface ScanRepoResult {
62
83
  healthScore: number;
63
84
  /** Wall-clock duration of the scan in milliseconds. */
64
85
  scanDuration: number;
86
+ /** Number of files skipped due to exclude rules (paths, presets, .flagsharkignore). */
87
+ excludedCount?: number;
88
+ /** Relative paths of excluded files. Only populated when collectExcludedPaths is true. */
89
+ excludedPaths?: string[];
90
+ /** Diagnostic — populated only when logger.debug level is active or callers explicitly opt in. */
91
+ effectiveExcludes?: EffectiveRules;
65
92
  }
66
93
  export declare function scanRepo(opts: ScanRepoOptions): Promise<ScanRepoResult>;
67
94
  //# sourceMappingURL=scan-repo.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scan-repo.d.ts","sourceRoot":"","sources":["../src/scan-repo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IACnC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IAClC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAA;IAEX;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IAEpB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAA;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAA;IAElB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAA;IAEpB;;;;OAIG;IACH,UAAU,EAAE,SAAS,EAAE,CAAA;IAEvB;;;OAGG;IACH,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAE3B,0EAA0E;IAC1E,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEzC;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAA;CACrB;AASD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAoD7E"}
1
+ {"version":3,"file":"scan-repo.d.ts","sourceRoot":"","sources":["../src/scan-repo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE1D,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IACnC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IAClC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAA;IAEX;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IAEpB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAA;IAEnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,OAAO,GAAG,aAAa,CAAA;IAEhC;;;OAGG;IACH,MAAM,CAAC,EAAE,eAAe,CAAA;IAExB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAA;IAElB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAA;IAEpB;;;;OAIG;IACH,UAAU,EAAE,SAAS,EAAE,CAAA;IAEvB;;;OAGG;IACH,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAE3B,0EAA0E;IAC1E,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEzC;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAA;IAEpB,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IAExB,kGAAkG;IAClG,iBAAiB,CAAC,EAAE,cAAc,CAAA;CACnC;AASD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA2E7E"}
package/dist/scan-repo.js CHANGED
@@ -3,9 +3,13 @@
3
3
  * return a single result object that consumers can render however they like.
4
4
  */
5
5
  import { collectFiles } from './scanner.js';
6
- import { createDefaultRegistry } from './detection/index.js';
6
+ import { createDefaultRegistry, createRegistryWithEngine } from './detection/index.js';
7
7
  import { PolyglotAnalyzer } from './detection/polyglot-analyzer.js';
8
8
  import { analyzeStaleness } from './staleness.js';
9
+ import { buildDefaultConfig } from './config/defaults.js';
10
+ import { buildExcluder } from './config/excluder.js';
11
+ import { loadConfigFile } from './config/loader.js';
12
+ import { loadIgnoreFile } from './config/ignore-file.js';
9
13
  const NOOP_LOGGER = {
10
14
  debug: () => { },
11
15
  info: () => { },
@@ -15,17 +19,31 @@ const NOOP_LOGGER = {
15
19
  export async function scanRepo(opts) {
16
20
  const start = performance.now();
17
21
  const logger = opts.logger ?? NOOP_LOGGER;
18
- const threshold = opts.threshold ?? 6;
19
- const registry = createDefaultRegistry();
22
+ const config = opts.config ??
23
+ (opts.noConfig
24
+ ? buildDefaultConfig()
25
+ : (await loadConfigFile(opts.cwd))?.config ?? buildDefaultConfig());
26
+ const threshold = opts.threshold ?? config.threshold ?? 6;
27
+ const ignoreFile = opts.noIgnoreFile ? null : await loadIgnoreFile(opts.cwd);
28
+ const excluder = buildExcluder({
29
+ config,
30
+ ignoreFilePatterns: ignoreFile?.patterns ?? [],
31
+ });
32
+ logger.debug('Effective excludes', excluder.effectiveRules);
33
+ const registry = opts.engine
34
+ ? createRegistryWithEngine(opts.engine)
35
+ : createDefaultRegistry();
20
36
  const supportedExtensions = new Set(registry.getSupportedExtensions());
21
37
  const analyzer = new PolyglotAnalyzer(registry, logger);
22
38
  logger.debug('Collecting files...');
23
- const files = collectFiles({
39
+ const { files, excludedCount, excludedPaths } = collectFiles({
24
40
  root: opts.cwd,
25
41
  supportedExtensions,
26
42
  diffRef: opts.diff,
43
+ excluder,
44
+ collectExcludedPaths: opts.collectExcludedPaths,
27
45
  });
28
- logger.debug(`Detected ${files.size} candidate files`);
46
+ logger.debug(`Detected ${files.size} candidate files (excluded ${excludedCount})`);
29
47
  const filesScanned = files.size;
30
48
  const analysisResult = await analyzer.analyzeFiles(files, opts.signal);
31
49
  const staleFlags = await analyzeStaleness(analysisResult.totalFlags, { thresholdMonths: threshold, repoRoot: opts.cwd });
@@ -50,6 +68,9 @@ export async function scanRepo(opts) {
50
68
  languageBreakdown: Object.fromEntries(analysisResult.languages),
51
69
  healthScore,
52
70
  scanDuration: Math.round(performance.now() - start),
71
+ excludedCount,
72
+ excludedPaths,
73
+ effectiveExcludes: excluder.effectiveRules,
53
74
  };
54
75
  }
55
76
  //# sourceMappingURL=scan-repo.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scan-repo.js","sourceRoot":"","sources":["../src/scan-repo.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scan-repo.js","sourceRoot":"","sources":["../src/scan-repo.ts"],"names":[],"mappings":"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"}