@ttt-productions/repo-guards 0.1.2 → 0.1.4

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.
@@ -1,7 +1,7 @@
1
1
  import ts from 'typescript';
2
2
  import type { GenericGuardDefinition } from '../../config.js';
3
3
  import type { FileView } from '../../reader/view.js';
4
- import type { Reviewed } from '../../reader/layout.js';
4
+ import { type Reviewed, type RootRole } from '../../reader/layout.js';
5
5
  export interface RateLimitFacts {
6
6
  /** The module that declares the presets and the surface map. */
7
7
  owner: string;
@@ -41,14 +41,29 @@ export declare const rateLimitGuard: GenericGuardDefinition<RateLimitFacts>;
41
41
  export interface LazyLoaderFacts {
42
42
  /** The memoizing loader every lazy import goes through (`lazyModule`). */
43
43
  loader: string;
44
- /** The Functions test runner configs, which never make every test concurrent. */
44
+ /** The roots whose code and tests the guard reads; `functions` alone when absent. */
45
+ roots?: readonly RootRole[];
46
+ /**
47
+ * Other module-level loaders whose `const x = name(() => import('…'))` is accepted, each with its
48
+ * why (a framework's own memoized component loader); one used nowhere is stale.
49
+ */
50
+ otherLoaders?: ReadonlyArray<{
51
+ name: string;
52
+ why: string;
53
+ }>;
54
+ /** The test runner configs, which never make every test concurrent. */
45
55
  testRunnerConfigs: readonly string[];
46
56
  /** Test files that overlap imports on purpose (the loader's own premise test), each with its why. */
47
57
  testExceptions: readonly Reviewed[];
48
58
  }
49
- /** Every dynamic import in production code that is not a module-level `const x = loader(() => import('…'))`. */
50
- export declare function strayDynamicImports(file: FileView, loader: string): {
59
+ /**
60
+ * Every dynamic import in production code that is not a module-level `const x = name(() => import('…'))`
61
+ * for one of `names`. `loaders` counts the uses of `names[0]`, the main loader; `used` holds every
62
+ * name that wrapped an import.
63
+ */
64
+ export declare function strayDynamicImports(file: FileView, names: string | readonly string[]): {
51
65
  loaders: number;
66
+ used: Set<string>;
52
67
  stray: ts.Node[];
53
68
  };
54
69
  /** Every place a test overlaps its own imports: a concurrent test, or `import()` inside a Promise combinator. */
@@ -1 +1 @@
1
- {"version":3,"file":"functions-build.d.ts","sourceRoot":"","sources":["../../../src/modules/backend/functions-build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"functions-build.d.ts","sourceRoot":"","sources":["../../../src/modules/backend/functions-build.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  // The guards over how the Functions tree is built and loaded: limiter charges name their preset and
2
- // their surface, every dynamic import is a module-level lazy loader, light functions never reach
3
- // heavy modules, and a split-codebase manifest covers every export exactly once.
2
+ // their surface, every dynamic import is a module-level lazy loader (in Functions and any other tree
3
+ // the app names), light functions never reach heavy modules, and a split-codebase manifest covers
4
+ // every export exactly once.
4
5
  import ts from 'typescript';
6
+ import { ROOT_ROLES } from '../../reader/layout.js';
5
7
  import { calleeName, forEachNode, lineOfNode } from '../../support/ast.js';
6
8
  import { namesProblem, reviewedProblems, textProblem } from '../../support/facts.js';
7
9
  import { moduleImports, namesModule } from '../../support/imports.js';
@@ -157,10 +159,16 @@ export const rateLimitGuard = {
157
159
  },
158
160
  };
159
161
  const isDynamicImport = (node) => ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword;
160
- /** Every dynamic import in production code that is not a module-level `const x = loader(() => import('…'))`. */
161
- export function strayDynamicImports(file, loader) {
162
+ /**
163
+ * Every dynamic import in production code that is not a module-level `const x = name(() => import('…'))`
164
+ * for one of `names`. `loaders` counts the uses of `names[0]`, the main loader; `used` holds every
165
+ * name that wrapped an import.
166
+ */
167
+ export function strayDynamicImports(file, names) {
168
+ const accepted = typeof names === 'string' ? [names] : names;
162
169
  const sf = file.sourceFile;
163
170
  const stray = [];
171
+ const used = new Set();
164
172
  let loaders = 0;
165
173
  forEachNode(sf, (node) => {
166
174
  if (!isDynamicImport(node))
@@ -176,7 +184,7 @@ export function strayDynamicImports(file, loader) {
176
184
  !!call &&
177
185
  ts.isCallExpression(call) &&
178
186
  ts.isIdentifier(call.expression) &&
179
- call.expression.text === loader &&
187
+ accepted.includes(call.expression.text) &&
180
188
  call.arguments.length === 1 &&
181
189
  call.arguments[0] === arrow &&
182
190
  !!declaration &&
@@ -188,12 +196,16 @@ export function strayDynamicImports(file, loader) {
188
196
  statement.parent === sf &&
189
197
  node.arguments.length === 1 &&
190
198
  ts.isStringLiteralLike(node.arguments[0]);
191
- if (ok)
192
- loaders += 1;
199
+ if (ok) {
200
+ const name = call.expression.text;
201
+ used.add(name);
202
+ if (name === accepted[0])
203
+ loaders += 1;
204
+ }
193
205
  else
194
206
  stray.push(node);
195
207
  });
196
- return { loaders, stray };
208
+ return { loaders, used, stray };
197
209
  }
198
210
  const COMBINATORS = new Set(['Promise.all', 'Promise.allSettled', 'Promise.race', 'Promise.any']);
199
211
  /** Every place a test overlaps its own imports: a concurrent test, or `import()` inside a Promise combinator. */
@@ -221,15 +233,27 @@ export const lazyLoaderGuard = {
221
233
  factProblems(facts) {
222
234
  const problems = [];
223
235
  textProblem(facts?.loader, 'loader', problems);
236
+ if (facts?.roots !== undefined) {
237
+ namesProblem(facts.roots, 'roots', problems);
238
+ if (Array.isArray(facts.roots)) {
239
+ for (const root of facts.roots)
240
+ if (!ROOT_ROLES.includes(root))
241
+ problems.push(`roots names ${String(root)}, which is not a root role`);
242
+ }
243
+ }
244
+ if (facts?.otherLoaders !== undefined)
245
+ reviewedProblems(facts.otherLoaders, 'otherLoaders', problems, { key: 'name' });
224
246
  namesProblem(facts?.testRunnerConfigs, 'testRunnerConfigs', problems);
225
247
  reviewedProblems(facts?.testExceptions, 'testExceptions', problems);
226
248
  return problems;
227
249
  },
228
250
  build(facts) {
251
+ const roots = facts.roots ?? ['functions'];
252
+ const others = (facts.otherLoaders ?? []).map((other) => other.name);
229
253
  return [
230
254
  {
231
- title: 'no Functions code can overlap two dynamic imports of one module',
232
- description: `Every dynamic import in Functions production code is a module-level \`const load… = ${facts.loader}(() => import('…'))\` ` +
255
+ title: 'no code can overlap two dynamic imports of one module',
256
+ description: `Every dynamic import in production code is a module-level \`const load… = ${facts.loader}(() => import('…'))\` ` +
233
257
  '(or a static import when laziness buys nothing): its first call starts the one import and every concurrent call ' +
234
258
  'awaits it. A bare `import()` lets two concurrent calls overlap, and the test runner hands the second the REAL ' +
235
259
  'module for a mocked one. Tests never overlap their own imports — no concurrent tests, no concurrent runner ' +
@@ -238,18 +262,24 @@ export const lazyLoaderGuard = {
238
262
  run(context) {
239
263
  const findings = [];
240
264
  let loaders = 0;
241
- for (const file of context.files(FUNCTIONS_CODE)) {
242
- const result = strayDynamicImports(file, facts.loader);
265
+ const used = new Set();
266
+ for (const file of context.files({ roots, kinds: ['code'], tests: false })) {
267
+ const result = strayDynamicImports(file, [facts.loader, ...others]);
243
268
  loaders += result.loaders;
269
+ for (const name of result.used)
270
+ used.add(name);
244
271
  for (const node of result.stray) {
245
272
  findings.push({ file: file.path, line: lineOfNode(file, node), detail: `${node.getText(file.sourceFile).slice(0, 80)} is not a module-level ${facts.loader} loader` });
246
273
  }
247
274
  }
248
275
  if (!loaders)
249
- findings.push({ file: '(functions)', detail: `no ${facts.loader} loader found, so the guard checks nothing` });
276
+ findings.push({ file: `(${roots.join(', ')})`, detail: `no ${facts.loader} loader found, so the guard checks nothing` });
277
+ for (const name of others)
278
+ if (!used.has(name))
279
+ findings.push({ file: '(otherLoaders)', detail: `stale other loader: ${name} wraps no import` });
250
280
  const exceptions = new Set(facts.testExceptions.map((e) => e.path));
251
281
  const overlapping = new Set();
252
- for (const file of context.files({ roots: ['functions'], kinds: ['code'], tests: 'only' })) {
282
+ for (const file of context.files({ roots, kinds: ['code'], tests: 'only' })) {
253
283
  const hits = overlappingTestImports(file);
254
284
  if (hits.length)
255
285
  overlapping.add(file.path);
@@ -1 +1 @@
1
- {"version":3,"file":"functions-build.js","sourceRoot":"","sources":["../../../src/modules/backend/functions-build.ts"],"names":[],"mappings":"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","sourcesContent":["// The guards over how the Functions tree is built and loaded: limiter charges name their preset and\n// their surface, every dynamic import is a module-level lazy loader, light functions never reach\n// heavy modules, and a split-codebase manifest covers every export exactly once.\n\nimport ts from 'typescript';\nimport type { GenericGuardDefinition } from '../../config.js';\nimport type { Finding, GuardContext } from '../../guard.js';\nimport type { Scope } from '../../reader/reader.js';\nimport type { FileView } from '../../reader/view.js';\nimport type { Reviewed } from '../../reader/layout.js';\nimport { calleeName, forEachNode, lineOfNode } from '../../support/ast.js';\nimport { namesProblem, reviewedProblems, textProblem } from '../../support/facts.js';\nimport { moduleImports, namesModule } from '../../support/imports.js';\nimport { resolveRelative } from '../../support/paths.js';\nimport { calleePath } from './shared.js';\n\nconst FUNCTIONS_CODE: Scope = { roots: ['functions'], kinds: ['code'], tests: false };\n\nconst CODE_EXTENSION = /\\.(?:[cm]?[jt]sx?)$/;\n\n/** The functions root's path; every module id in this file is relative to it, extension dropped. */\nfunction functionsRoot(context: GuardContext): string {\n const root = context.reader.layout.roots.functions;\n if (!root) throw new Error('repo-guards: a Functions guard runs and the layout declares no functions root');\n return root.path;\n}\n\nconst moduleIdOf = (root: string, path: string) => path.slice(root.length + 1).replace(CODE_EXTENSION, '');\n\n// ---------------------------------------------------------------------------------------------\n// Rate-limit charges name a preset, and each preset is charged only by its own surface.\n\nexport interface RateLimitFacts {\n /** The module that declares the presets and the surface map. */\n owner: string;\n /** The preset map's name (`RATE_LIMITS`). */\n presetMap: string;\n /** The map from a dedicated preset to the modules (Functions-root-relative, no extension) that charge it. */\n surfaceMap: string;\n /** The list of presets any module the surface map does not name may charge. */\n sharedPresets: string;\n /** The limiter call a module charges through (`checkRateLimit`). */\n chargeCall: string;\n /** The field each preset carries its store key prefix in (`prefix`). */\n prefixField: string;\n}\n\nconst isMapAccess = (node: ts.Node, map: string): node is ts.PropertyAccessExpression =>\n ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === map;\n\n/** Every place a module builds a limiter config itself instead of passing a named preset. */\nexport function inlineLimiterConfigs(file: FileView, facts: Pick<RateLimitFacts, 'presetMap' | 'chargeCall'>): Array<{ node: ts.Node; detail: string }> {\n const sf = file.sourceFile;\n const out: Array<{ node: ts.Node; detail: string }> = [];\n forEachNode(sf, (node) => {\n if (ts.isSpreadAssignment(node) && isMapAccess(node.expression, facts.presetMap)) {\n out.push({ node, detail: `spreads ${node.expression.getText(sf)} into a new config` });\n }\n if (ts.isCallExpression(node) && calleeName(node) === facts.chargeCall && node.arguments.some((a) => ts.isObjectLiteralExpression(a))) {\n out.push({ node, detail: `passes an inline config to ${facts.chargeCall}` });\n }\n });\n return out;\n}\n\n/** The presets a module charges: every `PRESET_MAP.X` its code names. */\nexport function presetsNamed(file: FileView, presetMap: string): string[] {\n const out = new Set<string>();\n forEachNode(file.sourceFile, (node) => {\n if (isMapAccess(node, presetMap)) out.add(node.name.text);\n });\n return [...out];\n}\n\n/** The owner's declarations: each preset's prefix, the surface map, and the shared presets. */\nexport function limiterDeclarations(owner: FileView, facts: RateLimitFacts) {\n const prefixes: string[] = [];\n const surfaces = new Map<string, string[]>();\n const shared = new Set<string>();\n let presetMapFound = false;\n let surfaceMapFound = false;\n let sharedFound = false;\n const strings = (node: ts.Expression): string[] =>\n ts.isArrayLiteralExpression(node) ? node.elements.filter(ts.isStringLiteralLike).map((e) => e.text) : [];\n const bare = (e: ts.Expression) => {\n let out = e;\n while (ts.isAsExpression(out) || ts.isSatisfiesExpression(out)) out = out.expression;\n return out;\n };\n forEachNode(owner.sourceFile, (node) => {\n if (!ts.isVariableDeclaration(node) || !ts.isIdentifier(node.name) || !node.initializer) return;\n const init = bare(node.initializer);\n if (node.name.text === facts.presetMap) {\n presetMapFound = true;\n forEachNode(init, (inner) => {\n if (ts.isPropertyAssignment(inner) && inner.name.getText() === facts.prefixField && ts.isStringLiteralLike(inner.initializer)) {\n prefixes.push(inner.initializer.text);\n }\n });\n }\n if (node.name.text === facts.sharedPresets) {\n sharedFound = true;\n strings(init).forEach((name) => shared.add(name));\n }\n if (node.name.text === facts.surfaceMap && ts.isObjectLiteralExpression(init)) {\n surfaceMapFound = true;\n for (const p of init.properties) {\n if (ts.isPropertyAssignment(p) && (ts.isIdentifier(p.name) || ts.isStringLiteralLike(p.name))) surfaces.set(p.name.text, strings(bare(p.initializer)));\n }\n }\n });\n return { prefixes, surfaces, shared, presetMapFound, surfaceMapFound, sharedFound };\n}\n\n/** Each charge that breaks the declared map: a dedicated preset from another module, or a listed module charging another preset. */\nexport function offendingCharges(\n charges: ReadonlyArray<{ module: string; presets: readonly string[] }>,\n surfaces: ReadonlyMap<string, readonly string[]>,\n shared: ReadonlySet<string>,\n): string[] {\n const listed = new Set([...surfaces.values()].flat());\n const out: string[] = [];\n for (const { module, presets } of charges) {\n for (const preset of presets) {\n const owners = surfaces.get(preset);\n const allowed = owners ? owners.includes(module) : shared.has(preset) && !listed.has(module);\n if (!allowed) out.push(`${module} charges ${preset}`);\n }\n }\n return out;\n}\n\nexport const rateLimitGuard: GenericGuardDefinition<RateLimitFacts> = {\n id: 'rateLimitSurfaces',\n absentWhen: 'the app runs no rate limiter',\n factProblems(facts) {\n const problems: string[] = [];\n for (const key of ['owner', 'presetMap', 'surfaceMap', 'sharedPresets', 'chargeCall', 'prefixField'] as const) textProblem(facts?.[key], key, problems);\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'every rate-limit charge names its own preset',\n description:\n `Every limiter charge passes a named ${facts.presetMap} preset — never an inline config to ${facts.chargeCall}, and ` +\n `never a preset spread into a new one — and every preset owns a distinct ${facts.prefixField}. A dedicated preset ` +\n `is charged only by the modules ${facts.surfaceMap} lists for it, and a listed module charges only its own presets; ` +\n `any other module charges only the ${facts.sharedPresets}. Otherwise two surfaces share one sliding window sized ` +\n `for neither. Every module the map lists must exist and charge its preset. Declare a new preset in ${facts.owner}.`,\n run(context) {\n const root = functionsRoot(context);\n const findings: Finding[] = [];\n const charges: Array<{ module: string; presets: string[] }> = [];\n let ownerFile: FileView | undefined;\n for (const file of context.files(FUNCTIONS_CODE)) {\n if (file.path === facts.owner) {\n ownerFile = file;\n continue;\n }\n for (const { node, detail } of inlineLimiterConfigs(file, facts)) findings.push({ file: file.path, line: lineOfNode(file, node), detail });\n const presets = presetsNamed(file, facts.presetMap);\n if (presets.length) charges.push({ module: moduleIdOf(root, file.path), presets });\n }\n if (!ownerFile) return [...findings, { file: facts.owner, detail: 'the limiter owner is gone or outside the Functions tree' }];\n const declared = limiterDeclarations(ownerFile, facts);\n if (!declared.presetMapFound || !declared.prefixes.length) findings.push({ file: facts.owner, detail: `no ${facts.presetMap} with a ${facts.prefixField} found` });\n if (!declared.surfaceMapFound) findings.push({ file: facts.owner, detail: `no ${facts.surfaceMap} object found` });\n if (!declared.sharedFound) findings.push({ file: facts.owner, detail: `no ${facts.sharedPresets} list found` });\n const dup = declared.prefixes.filter((p, i) => declared.prefixes.indexOf(p) !== i);\n for (const p of new Set(dup)) findings.push({ file: facts.owner, detail: `two presets share the ${facts.prefixField} ${p}` });\n for (const offense of offendingCharges(charges, declared.surfaces, declared.shared)) findings.push({ file: facts.owner, detail: offense });\n const charged = new Map(charges.map((c) => [c.module, c.presets]));\n for (const [preset, modules] of declared.surfaces) {\n for (const module of modules) if (!charged.get(module)?.includes(preset)) findings.push({ file: facts.owner, detail: `${preset} lists ${module}, which does not charge it` });\n }\n return findings;\n },\n },\n ];\n },\n};\n\n// ---------------------------------------------------------------------------------------------\n// Every dynamic import is a module-level lazy loader.\n\nexport interface LazyLoaderFacts {\n /** The memoizing loader every lazy import goes through (`lazyModule`). */\n loader: string;\n /** The Functions test runner configs, which never make every test concurrent. */\n testRunnerConfigs: readonly string[];\n /** Test files that overlap imports on purpose (the loader's own premise test), each with its why. */\n testExceptions: readonly Reviewed[];\n}\n\nconst isDynamicImport = (node: ts.Node): node is ts.CallExpression => ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword;\n\n/** Every dynamic import in production code that is not a module-level `const x = loader(() => import('…'))`. */\nexport function strayDynamicImports(file: FileView, loader: string): { loaders: number; stray: ts.Node[] } {\n const sf = file.sourceFile;\n const stray: ts.Node[] = [];\n let loaders = 0;\n forEachNode(sf, (node) => {\n if (!isDynamicImport(node)) return;\n const arrow = node.parent;\n const call = arrow?.parent;\n const declaration = call?.parent;\n const statement = declaration?.parent?.parent;\n const ok =\n !!arrow &&\n ts.isArrowFunction(arrow) &&\n arrow.body === node &&\n arrow.parameters.length === 0 &&\n !!call &&\n ts.isCallExpression(call) &&\n ts.isIdentifier(call.expression) &&\n call.expression.text === loader &&\n call.arguments.length === 1 &&\n call.arguments[0] === arrow &&\n !!declaration &&\n ts.isVariableDeclaration(declaration) &&\n declaration.initializer === call &&\n (declaration.parent.flags & ts.NodeFlags.Const) !== 0 &&\n statement !== undefined &&\n ts.isVariableStatement(statement) &&\n statement.parent === sf &&\n node.arguments.length === 1 &&\n ts.isStringLiteralLike(node.arguments[0]!);\n if (ok) loaders += 1;\n else stray.push(node);\n });\n return { loaders, stray };\n}\n\nconst COMBINATORS = new Set(['Promise.all', 'Promise.allSettled', 'Promise.race', 'Promise.any']);\n\n/** Every place a test overlaps its own imports: a concurrent test, or `import()` inside a Promise combinator. */\nexport function overlappingTestImports(file: FileView): Array<{ node: ts.Node; detail: string }> {\n const sf = file.sourceFile;\n const out: Array<{ node: ts.Node; detail: string }> = [];\n const visit = (node: ts.Node, inCombinator: boolean) => {\n let combinator = inCombinator;\n if (ts.isPropertyAccessExpression(node) && node.name.text === 'concurrent') out.push({ node, detail: `${node.getText(sf)} runs tests concurrently` });\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'concurrent') out.push({ node, detail: 'a concurrent test option' });\n if (ts.isCallExpression(node) && COMBINATORS.has(calleePath(node) ?? '')) combinator = true;\n if (inCombinator && isDynamicImport(node)) out.push({ node, detail: `${node.getText(sf)} overlaps the other imports of a Promise combinator` });\n ts.forEachChild(node, (child) => visit(child, combinator));\n };\n visit(sf, false);\n return out;\n}\n\nexport const lazyLoaderGuard: GenericGuardDefinition<LazyLoaderFacts> = {\n id: 'lazyLoader',\n absentWhen: false,\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.loader, 'loader', problems);\n namesProblem(facts?.testRunnerConfigs, 'testRunnerConfigs', problems);\n reviewedProblems(facts?.testExceptions, 'testExceptions', problems);\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'no Functions code can overlap two dynamic imports of one module',\n description:\n `Every dynamic import in Functions production code is a module-level \\`const load… = ${facts.loader}(() => import('…'))\\` ` +\n '(or a static import when laziness buys nothing): its first call starts the one import and every concurrent call ' +\n 'awaits it. A bare `import()` lets two concurrent calls overlap, and the test runner hands the second the REAL ' +\n 'module for a mocked one. Tests never overlap their own imports — no concurrent tests, no concurrent runner ' +\n 'config, no `import()` inside a Promise combinator; a test that does so on purpose is a reviewed exception with ' +\n 'its why, stale once it no longer does.',\n run(context) {\n const findings: Finding[] = [];\n let loaders = 0;\n for (const file of context.files(FUNCTIONS_CODE)) {\n const result = strayDynamicImports(file, facts.loader);\n loaders += result.loaders;\n for (const node of result.stray) {\n findings.push({ file: file.path, line: lineOfNode(file, node), detail: `${node.getText(file.sourceFile).slice(0, 80)} is not a module-level ${facts.loader} loader` });\n }\n }\n if (!loaders) findings.push({ file: '(functions)', detail: `no ${facts.loader} loader found, so the guard checks nothing` });\n const exceptions = new Set(facts.testExceptions.map((e) => e.path));\n const overlapping = new Set<string>();\n for (const file of context.files({ roots: ['functions'], kinds: ['code'], tests: 'only' })) {\n const hits = overlappingTestImports(file);\n if (hits.length) overlapping.add(file.path);\n if (exceptions.has(file.path)) continue;\n for (const { node, detail } of hits) findings.push({ file: file.path, line: lineOfNode(file, node), detail });\n }\n for (const path of exceptions) if (!overlapping.has(path)) findings.push({ file: path, detail: 'stale test exception: the file overlaps no import' });\n for (const config of facts.testRunnerConfigs) {\n if (!context.reader.exists(config)) findings.push({ file: config, detail: 'the test runner config no longer exists' });\n else {\n const view = context.file(config);\n const m = /\\bconcurrent\\s*:/.exec(view.code);\n if (m) findings.push({ file: config, line: view.lineOf(m.index), detail: 'the runner config makes tests concurrent' });\n }\n }\n return findings;\n },\n },\n ];\n },\n};\n\n// ---------------------------------------------------------------------------------------------\n// Light functions never reach heavy modules.\n\nexport interface LightFunctionFacts {\n /** The Functions entry module that exports every deployed function. */\n entryIndex: string;\n /** Exported functions whose static import closure is kept small. */\n lightFunctions: readonly string[];\n /** Packages a light closure never imports statically, with any subpath that is light, each with its why. */\n heavyPackages: ReadonlyArray<{ specifier: string; lightSubpaths: readonly string[]; why: string }>;\n /** Functions modules a light closure never reaches statically, each with its why. */\n heavyFiles: readonly Reviewed[];\n}\n\n/** A file's static runtime import edges: no `import()` (the lazy path), no `import type` / `export type`. */\nexport function staticEdges(file: FileView): string[] {\n return moduleImports(file.sourceFile, ['import', 'export'])\n .filter((site) => site.topLevel && !site.typeOnly)\n .map((site) => site.spec);\n}\n\n/** The repo-relative file a relative specifier names among `known`, or null. */\nexport function resolveModule(fromPath: string, spec: string, known: ReadonlySet<string>): string | null {\n const base = resolveRelative(fromPath, spec)?.path;\n if (base === undefined) return null;\n const stem = base.replace(/\\.[cm]?jsx?$/, '');\n const candidates = [base, `${stem}.ts`, `${stem}.tsx`, `${stem}.mts`, `${stem}.cts`, `${base}.ts`, `${base}.tsx`, `${base}/index.ts`, `${base}/index.tsx`];\n return candidates.find((c) => known.has(c)) ?? null;\n}\n\n/** Each exported name of a module, with the specifier it is re-exported from (when it is). */\nexport function exportsOf(file: FileView): { names: Map<string, string | null>; unreadable: ts.Node[] } {\n const names = new Map<string, string | null>();\n const unreadable: ts.Node[] = [];\n const exported = (node: ts.Node) => ts.canHaveModifiers(node) && !!ts.getModifiers(node)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);\n for (const stmt of file.sourceFile.statements) {\n if (ts.isExportDeclaration(stmt)) {\n const from = stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier) ? stmt.moduleSpecifier.text : null;\n if (stmt.exportClause && ts.isNamedExports(stmt.exportClause)) for (const e of stmt.exportClause.elements) names.set(e.name.text, from);\n else unreadable.push(stmt);\n } else if (ts.isVariableStatement(stmt) && exported(stmt)) {\n for (const d of stmt.declarationList.declarations) if (ts.isIdentifier(d.name)) names.set(d.name.text, null);\n } else if ((ts.isFunctionDeclaration(stmt) || ts.isClassDeclaration(stmt)) && exported(stmt) && stmt.name) {\n names.set(stmt.name.text, null);\n }\n }\n return { names, unreadable };\n}\n\nexport const lightFunctionGuard: GenericGuardDefinition<LightFunctionFacts> = {\n id: 'lightFunctions',\n absentWhen: 'the app designates no light functions',\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.entryIndex, 'entryIndex', problems);\n namesProblem(facts?.lightFunctions, 'lightFunctions', problems);\n reviewedProblems(facts?.heavyPackages, 'heavyPackages', problems, { key: 'specifier' });\n for (const p of facts?.heavyPackages ?? []) if (!Array.isArray(p?.lightSubpaths)) problems.push(`heavy package ${String(p?.specifier)} needs lightSubpaths (declare [] when none)`);\n reviewedProblems(facts?.heavyFiles, 'heavyFiles', problems);\n if (!facts?.heavyPackages?.length && !facts?.heavyFiles?.length) problems.push('neither heavyPackages nor heavyFiles names anything, so the guard checks nothing');\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'light functions never statically reach a heavy module',\n description:\n `The light functions (${facts.lightFunctions.join(', ')}) are hot interactive paths whose static import closure ` +\n 'is small by design: walking the static import graph from each one\\'s module (dynamic `import()` and type-only ' +\n 'imports are not edges) never reaches a heavy package or a heavy Functions module, which would load on every ' +\n 'cold start. Cut the edge — load the heavy module through the module-level lazy loader at its true usage site — ' +\n 'instead of relaxing the list. Every relative import must resolve, every light function must be exported by ' +\n 'the entry module, and every heavy file must exist.',\n timeoutMs: 120_000,\n run(context) {\n const findings: Finding[] = [];\n const files = context.files(FUNCTIONS_CODE);\n const known = new Set(files.map((f) => f.path));\n const graph = new Map<string, { internal: string[]; external: string[] }>();\n for (const file of files) {\n const internal: string[] = [];\n const external: string[] = [];\n for (const spec of staticEdges(file)) {\n if (!spec.startsWith('.')) external.push(spec);\n else {\n const target = resolveModule(file.path, spec, known);\n if (target) internal.push(target);\n else findings.push({ file: file.path, detail: `cannot resolve ${spec}, so the closure through it is unread` });\n }\n }\n graph.set(file.path, { internal, external });\n }\n for (const { path } of facts.heavyFiles) if (!known.has(path)) findings.push({ file: path, detail: 'stale heavy file: it is not a Functions module' });\n if (!known.has(facts.entryIndex)) return [...findings, { file: facts.entryIndex, detail: 'the entry module is gone or outside the Functions tree' }];\n const { names } = exportsOf(files.find((f) => f.path === facts.entryIndex)!);\n for (const fn of facts.lightFunctions) {\n const from = names.get(fn);\n const start = from ? resolveModule(facts.entryIndex, from, known) : null;\n if (!start) {\n findings.push({ file: facts.entryIndex, detail: `light function ${fn} is not re-exported from a Functions module` });\n continue;\n }\n const seen = new Set([start]);\n const externals = new Set<string>();\n const stack = [start];\n while (stack.length) {\n const node = graph.get(stack.pop()!);\n if (!node) continue;\n node.external.forEach((e) => externals.add(e));\n for (const next of node.internal) {\n if (seen.has(next)) continue;\n seen.add(next);\n stack.push(next);\n }\n }\n for (const spec of externals) {\n const heavy = facts.heavyPackages.find((p) => namesModule(spec, p.specifier) && !p.lightSubpaths.includes(spec));\n if (heavy) findings.push({ file: start, detail: `light function ${fn} statically reaches ${spec}` });\n }\n for (const { path } of facts.heavyFiles) if (seen.has(path)) findings.push({ file: start, detail: `light function ${fn} statically reaches ${path}` });\n }\n return findings;\n },\n },\n ];\n },\n};\n\n// ---------------------------------------------------------------------------------------------\n// The split-codebase manifest.\n\nexport interface CodebaseManifestFacts {\n /** The JSON manifest mapping each codebase name to the exports it deploys (`{ codebases: { name: [exports] } }`). */\n manifest: string;\n /** The Functions entry module that exports every deployed function. */\n entryIndex: string;\n /** The deploy config whose `functions` entries declare each codebase. */\n deployConfig: string;\n /** Each codebase entry's source folder, with `{codebase}` for its name. */\n sourceTemplate: string;\n /** Each codebase entry's predeploy commands, with `{codebase}` for its name. */\n predeployTemplate: readonly string[];\n}\n\nfunction readJson(context: GuardContext, path: string, findings: Finding[]): unknown {\n if (!context.reader.exists(path)) {\n findings.push({ file: path, detail: 'the file no longer exists' });\n return undefined;\n }\n try {\n return JSON.parse(context.file(path).text);\n } catch (err) {\n findings.push({ file: path, detail: `cannot be read as JSON (${(err as Error).message})` });\n return undefined;\n }\n}\n\nexport const codebaseManifestGuard: GenericGuardDefinition<CodebaseManifestFacts> = {\n id: 'codebaseManifest',\n absentWhen: 'the app deploys its Functions as one codebase',\n factProblems(facts) {\n const problems: string[] = [];\n for (const key of ['manifest', 'entryIndex', 'deployConfig', 'sourceTemplate'] as const) textProblem(facts?.[key], key, problems);\n if (typeof facts?.sourceTemplate === 'string' && !facts.sourceTemplate.includes('{codebase}')) problems.push('sourceTemplate names no {codebase}');\n namesProblem(facts?.predeployTemplate, 'predeployTemplate', problems, { nonEmpty: false });\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'the codebase manifest deploys every function exactly once',\n description:\n `${facts.manifest} maps every export of ${facts.entryIndex} to exactly one Functions codebase — none missing, none ` +\n `stale, none in two — and ${facts.deployConfig} declares exactly the manifest's codebases, each from its source ` +\n 'folder with its predeploy build. A function in no codebase never deploys; one in two deploys twice; a codebase ' +\n 'the deploy config does not declare is never built. The entry module re-exports by name, never `export *`.',\n run(context) {\n const findings: Finding[] = [];\n const manifest = readJson(context, facts.manifest, findings) as { codebases?: Record<string, unknown> } | undefined;\n const deploy = readJson(context, facts.deployConfig, findings) as { functions?: unknown } | undefined;\n if (!context.reader.exists(facts.entryIndex)) return [...findings, { file: facts.entryIndex, detail: 'the entry module no longer exists' }];\n const index = context.file(facts.entryIndex);\n const { names, unreadable } = exportsOf(index);\n for (const node of unreadable) findings.push({ file: index.path, line: lineOfNode(index, node), detail: 'export * hides which functions the module deploys' });\n if (!names.size) findings.push({ file: index.path, detail: 'no export found, so the guard checks nothing' });\n if (!manifest || typeof manifest.codebases !== 'object' || !manifest.codebases) {\n if (manifest) findings.push({ file: facts.manifest, detail: 'no codebases object' });\n return findings;\n }\n const seen = new Map<string, string>();\n for (const [codebase, list] of Object.entries(manifest.codebases)) {\n if (!Array.isArray(list)) {\n findings.push({ file: facts.manifest, detail: `codebase ${codebase} is not a list of exports` });\n continue;\n }\n for (const name of list as unknown[]) {\n if (typeof name !== 'string') continue;\n if (seen.has(name)) findings.push({ file: facts.manifest, detail: `${name} is in two codebases (${seen.get(name)} and ${codebase})` });\n seen.set(name, codebase);\n }\n }\n for (const name of names.keys()) if (!seen.has(name)) findings.push({ file: facts.manifest, detail: `${name} is exported but in no codebase` });\n for (const name of seen.keys()) if (!names.has(name)) findings.push({ file: facts.manifest, detail: `stale entry ${name}: the entry module does not export it` });\n if (!deploy) return findings;\n const entries = Array.isArray(deploy.functions) ? (deploy.functions as Array<Record<string, unknown>>) : null;\n if (!entries) return [...findings, { file: facts.deployConfig, detail: 'functions is not a list of codebase entries' }];\n const declared = entries.map((e) => String(e.codebase));\n const codebases = Object.keys(manifest.codebases);\n for (const cb of codebases) if (!declared.includes(cb)) findings.push({ file: facts.deployConfig, detail: `codebase ${cb} is not declared` });\n for (const cb of declared) if (!codebases.includes(cb)) findings.push({ file: facts.deployConfig, detail: `codebase ${cb} is not in the manifest` });\n for (const entry of entries) {\n const cb = String(entry.codebase);\n const source = facts.sourceTemplate.split('{codebase}').join(cb);\n if (entry.source !== source) findings.push({ file: facts.deployConfig, detail: `codebase ${cb} deploys from ${String(entry.source)}, not ${source}` });\n const predeploy = facts.predeployTemplate.map((t) => t.split('{codebase}').join(cb));\n if (JSON.stringify(entry.predeploy ?? []) !== JSON.stringify(predeploy)) {\n findings.push({ file: facts.deployConfig, detail: `codebase ${cb}'s predeploy is not ${JSON.stringify(predeploy)}` });\n }\n }\n return findings;\n },\n },\n ];\n },\n};\n"]}
1
+ {"version":3,"file":"functions-build.js","sourceRoot":"","sources":["../../../src/modules/backend/functions-build.ts"],"names":[],"mappings":"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","sourcesContent":["// The guards over how the Functions tree is built and loaded: limiter charges name their preset and\n// their surface, every dynamic import is a module-level lazy loader (in Functions and any other tree\n// the app names), light functions never reach heavy modules, and a split-codebase manifest covers\n// every export exactly once.\n\nimport ts from 'typescript';\nimport type { GenericGuardDefinition } from '../../config.js';\nimport type { Finding, GuardContext } from '../../guard.js';\nimport type { Scope } from '../../reader/reader.js';\nimport type { FileView } from '../../reader/view.js';\nimport { ROOT_ROLES, type Reviewed, type RootRole } from '../../reader/layout.js';\nimport { calleeName, forEachNode, lineOfNode } from '../../support/ast.js';\nimport { namesProblem, reviewedProblems, textProblem } from '../../support/facts.js';\nimport { moduleImports, namesModule } from '../../support/imports.js';\nimport { resolveRelative } from '../../support/paths.js';\nimport { calleePath } from './shared.js';\n\nconst FUNCTIONS_CODE: Scope = { roots: ['functions'], kinds: ['code'], tests: false };\n\nconst CODE_EXTENSION = /\\.(?:[cm]?[jt]sx?)$/;\n\n/** The functions root's path; every module id in this file is relative to it, extension dropped. */\nfunction functionsRoot(context: GuardContext): string {\n const root = context.reader.layout.roots.functions;\n if (!root) throw new Error('repo-guards: a Functions guard runs and the layout declares no functions root');\n return root.path;\n}\n\nconst moduleIdOf = (root: string, path: string) => path.slice(root.length + 1).replace(CODE_EXTENSION, '');\n\n// ---------------------------------------------------------------------------------------------\n// Rate-limit charges name a preset, and each preset is charged only by its own surface.\n\nexport interface RateLimitFacts {\n /** The module that declares the presets and the surface map. */\n owner: string;\n /** The preset map's name (`RATE_LIMITS`). */\n presetMap: string;\n /** The map from a dedicated preset to the modules (Functions-root-relative, no extension) that charge it. */\n surfaceMap: string;\n /** The list of presets any module the surface map does not name may charge. */\n sharedPresets: string;\n /** The limiter call a module charges through (`checkRateLimit`). */\n chargeCall: string;\n /** The field each preset carries its store key prefix in (`prefix`). */\n prefixField: string;\n}\n\nconst isMapAccess = (node: ts.Node, map: string): node is ts.PropertyAccessExpression =>\n ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === map;\n\n/** Every place a module builds a limiter config itself instead of passing a named preset. */\nexport function inlineLimiterConfigs(file: FileView, facts: Pick<RateLimitFacts, 'presetMap' | 'chargeCall'>): Array<{ node: ts.Node; detail: string }> {\n const sf = file.sourceFile;\n const out: Array<{ node: ts.Node; detail: string }> = [];\n forEachNode(sf, (node) => {\n if (ts.isSpreadAssignment(node) && isMapAccess(node.expression, facts.presetMap)) {\n out.push({ node, detail: `spreads ${node.expression.getText(sf)} into a new config` });\n }\n if (ts.isCallExpression(node) && calleeName(node) === facts.chargeCall && node.arguments.some((a) => ts.isObjectLiteralExpression(a))) {\n out.push({ node, detail: `passes an inline config to ${facts.chargeCall}` });\n }\n });\n return out;\n}\n\n/** The presets a module charges: every `PRESET_MAP.X` its code names. */\nexport function presetsNamed(file: FileView, presetMap: string): string[] {\n const out = new Set<string>();\n forEachNode(file.sourceFile, (node) => {\n if (isMapAccess(node, presetMap)) out.add(node.name.text);\n });\n return [...out];\n}\n\n/** The owner's declarations: each preset's prefix, the surface map, and the shared presets. */\nexport function limiterDeclarations(owner: FileView, facts: RateLimitFacts) {\n const prefixes: string[] = [];\n const surfaces = new Map<string, string[]>();\n const shared = new Set<string>();\n let presetMapFound = false;\n let surfaceMapFound = false;\n let sharedFound = false;\n const strings = (node: ts.Expression): string[] =>\n ts.isArrayLiteralExpression(node) ? node.elements.filter(ts.isStringLiteralLike).map((e) => e.text) : [];\n const bare = (e: ts.Expression) => {\n let out = e;\n while (ts.isAsExpression(out) || ts.isSatisfiesExpression(out)) out = out.expression;\n return out;\n };\n forEachNode(owner.sourceFile, (node) => {\n if (!ts.isVariableDeclaration(node) || !ts.isIdentifier(node.name) || !node.initializer) return;\n const init = bare(node.initializer);\n if (node.name.text === facts.presetMap) {\n presetMapFound = true;\n forEachNode(init, (inner) => {\n if (ts.isPropertyAssignment(inner) && inner.name.getText() === facts.prefixField && ts.isStringLiteralLike(inner.initializer)) {\n prefixes.push(inner.initializer.text);\n }\n });\n }\n if (node.name.text === facts.sharedPresets) {\n sharedFound = true;\n strings(init).forEach((name) => shared.add(name));\n }\n if (node.name.text === facts.surfaceMap && ts.isObjectLiteralExpression(init)) {\n surfaceMapFound = true;\n for (const p of init.properties) {\n if (ts.isPropertyAssignment(p) && (ts.isIdentifier(p.name) || ts.isStringLiteralLike(p.name))) surfaces.set(p.name.text, strings(bare(p.initializer)));\n }\n }\n });\n return { prefixes, surfaces, shared, presetMapFound, surfaceMapFound, sharedFound };\n}\n\n/** Each charge that breaks the declared map: a dedicated preset from another module, or a listed module charging another preset. */\nexport function offendingCharges(\n charges: ReadonlyArray<{ module: string; presets: readonly string[] }>,\n surfaces: ReadonlyMap<string, readonly string[]>,\n shared: ReadonlySet<string>,\n): string[] {\n const listed = new Set([...surfaces.values()].flat());\n const out: string[] = [];\n for (const { module, presets } of charges) {\n for (const preset of presets) {\n const owners = surfaces.get(preset);\n const allowed = owners ? owners.includes(module) : shared.has(preset) && !listed.has(module);\n if (!allowed) out.push(`${module} charges ${preset}`);\n }\n }\n return out;\n}\n\nexport const rateLimitGuard: GenericGuardDefinition<RateLimitFacts> = {\n id: 'rateLimitSurfaces',\n absentWhen: 'the app runs no rate limiter',\n factProblems(facts) {\n const problems: string[] = [];\n for (const key of ['owner', 'presetMap', 'surfaceMap', 'sharedPresets', 'chargeCall', 'prefixField'] as const) textProblem(facts?.[key], key, problems);\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'every rate-limit charge names its own preset',\n description:\n `Every limiter charge passes a named ${facts.presetMap} preset — never an inline config to ${facts.chargeCall}, and ` +\n `never a preset spread into a new one — and every preset owns a distinct ${facts.prefixField}. A dedicated preset ` +\n `is charged only by the modules ${facts.surfaceMap} lists for it, and a listed module charges only its own presets; ` +\n `any other module charges only the ${facts.sharedPresets}. Otherwise two surfaces share one sliding window sized ` +\n `for neither. Every module the map lists must exist and charge its preset. Declare a new preset in ${facts.owner}.`,\n run(context) {\n const root = functionsRoot(context);\n const findings: Finding[] = [];\n const charges: Array<{ module: string; presets: string[] }> = [];\n let ownerFile: FileView | undefined;\n for (const file of context.files(FUNCTIONS_CODE)) {\n if (file.path === facts.owner) {\n ownerFile = file;\n continue;\n }\n for (const { node, detail } of inlineLimiterConfigs(file, facts)) findings.push({ file: file.path, line: lineOfNode(file, node), detail });\n const presets = presetsNamed(file, facts.presetMap);\n if (presets.length) charges.push({ module: moduleIdOf(root, file.path), presets });\n }\n if (!ownerFile) return [...findings, { file: facts.owner, detail: 'the limiter owner is gone or outside the Functions tree' }];\n const declared = limiterDeclarations(ownerFile, facts);\n if (!declared.presetMapFound || !declared.prefixes.length) findings.push({ file: facts.owner, detail: `no ${facts.presetMap} with a ${facts.prefixField} found` });\n if (!declared.surfaceMapFound) findings.push({ file: facts.owner, detail: `no ${facts.surfaceMap} object found` });\n if (!declared.sharedFound) findings.push({ file: facts.owner, detail: `no ${facts.sharedPresets} list found` });\n const dup = declared.prefixes.filter((p, i) => declared.prefixes.indexOf(p) !== i);\n for (const p of new Set(dup)) findings.push({ file: facts.owner, detail: `two presets share the ${facts.prefixField} ${p}` });\n for (const offense of offendingCharges(charges, declared.surfaces, declared.shared)) findings.push({ file: facts.owner, detail: offense });\n const charged = new Map(charges.map((c) => [c.module, c.presets]));\n for (const [preset, modules] of declared.surfaces) {\n for (const module of modules) if (!charged.get(module)?.includes(preset)) findings.push({ file: facts.owner, detail: `${preset} lists ${module}, which does not charge it` });\n }\n return findings;\n },\n },\n ];\n },\n};\n\n// ---------------------------------------------------------------------------------------------\n// Every dynamic import is a module-level lazy loader.\n\nexport interface LazyLoaderFacts {\n /** The memoizing loader every lazy import goes through (`lazyModule`). */\n loader: string;\n /** The roots whose code and tests the guard reads; `functions` alone when absent. */\n roots?: readonly RootRole[];\n /**\n * Other module-level loaders whose `const x = name(() => import('…'))` is accepted, each with its\n * why (a framework's own memoized component loader); one used nowhere is stale.\n */\n otherLoaders?: ReadonlyArray<{ name: string; why: string }>;\n /** The test runner configs, which never make every test concurrent. */\n testRunnerConfigs: readonly string[];\n /** Test files that overlap imports on purpose (the loader's own premise test), each with its why. */\n testExceptions: readonly Reviewed[];\n}\n\nconst isDynamicImport = (node: ts.Node): node is ts.CallExpression => ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword;\n\n/**\n * Every dynamic import in production code that is not a module-level `const x = name(() => import('…'))`\n * for one of `names`. `loaders` counts the uses of `names[0]`, the main loader; `used` holds every\n * name that wrapped an import.\n */\nexport function strayDynamicImports(\n file: FileView,\n names: string | readonly string[],\n): { loaders: number; used: Set<string>; stray: ts.Node[] } {\n const accepted = typeof names === 'string' ? [names] : names;\n const sf = file.sourceFile;\n const stray: ts.Node[] = [];\n const used = new Set<string>();\n let loaders = 0;\n forEachNode(sf, (node) => {\n if (!isDynamicImport(node)) return;\n const arrow = node.parent;\n const call = arrow?.parent;\n const declaration = call?.parent;\n const statement = declaration?.parent?.parent;\n const ok =\n !!arrow &&\n ts.isArrowFunction(arrow) &&\n arrow.body === node &&\n arrow.parameters.length === 0 &&\n !!call &&\n ts.isCallExpression(call) &&\n ts.isIdentifier(call.expression) &&\n accepted.includes(call.expression.text) &&\n call.arguments.length === 1 &&\n call.arguments[0] === arrow &&\n !!declaration &&\n ts.isVariableDeclaration(declaration) &&\n declaration.initializer === call &&\n (declaration.parent.flags & ts.NodeFlags.Const) !== 0 &&\n statement !== undefined &&\n ts.isVariableStatement(statement) &&\n statement.parent === sf &&\n node.arguments.length === 1 &&\n ts.isStringLiteralLike(node.arguments[0]!);\n if (ok) {\n const name = (call as ts.CallExpression & { expression: ts.Identifier }).expression.text;\n used.add(name);\n if (name === accepted[0]) loaders += 1;\n } else stray.push(node);\n });\n return { loaders, used, stray };\n}\n\nconst COMBINATORS = new Set(['Promise.all', 'Promise.allSettled', 'Promise.race', 'Promise.any']);\n\n/** Every place a test overlaps its own imports: a concurrent test, or `import()` inside a Promise combinator. */\nexport function overlappingTestImports(file: FileView): Array<{ node: ts.Node; detail: string }> {\n const sf = file.sourceFile;\n const out: Array<{ node: ts.Node; detail: string }> = [];\n const visit = (node: ts.Node, inCombinator: boolean) => {\n let combinator = inCombinator;\n if (ts.isPropertyAccessExpression(node) && node.name.text === 'concurrent') out.push({ node, detail: `${node.getText(sf)} runs tests concurrently` });\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'concurrent') out.push({ node, detail: 'a concurrent test option' });\n if (ts.isCallExpression(node) && COMBINATORS.has(calleePath(node) ?? '')) combinator = true;\n if (inCombinator && isDynamicImport(node)) out.push({ node, detail: `${node.getText(sf)} overlaps the other imports of a Promise combinator` });\n ts.forEachChild(node, (child) => visit(child, combinator));\n };\n visit(sf, false);\n return out;\n}\n\nexport const lazyLoaderGuard: GenericGuardDefinition<LazyLoaderFacts> = {\n id: 'lazyLoader',\n absentWhen: false,\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.loader, 'loader', problems);\n if (facts?.roots !== undefined) {\n namesProblem(facts.roots, 'roots', problems);\n if (Array.isArray(facts.roots)) {\n for (const root of facts.roots) if (!ROOT_ROLES.includes(root)) problems.push(`roots names ${String(root)}, which is not a root role`);\n }\n }\n if (facts?.otherLoaders !== undefined) reviewedProblems(facts.otherLoaders, 'otherLoaders', problems, { key: 'name' });\n namesProblem(facts?.testRunnerConfigs, 'testRunnerConfigs', problems);\n reviewedProblems(facts?.testExceptions, 'testExceptions', problems);\n return problems;\n },\n build(facts) {\n const roots = facts.roots ?? ['functions'];\n const others = (facts.otherLoaders ?? []).map((other) => other.name);\n return [\n {\n title: 'no code can overlap two dynamic imports of one module',\n description:\n `Every dynamic import in production code is a module-level \\`const load… = ${facts.loader}(() => import('…'))\\` ` +\n '(or a static import when laziness buys nothing): its first call starts the one import and every concurrent call ' +\n 'awaits it. A bare `import()` lets two concurrent calls overlap, and the test runner hands the second the REAL ' +\n 'module for a mocked one. Tests never overlap their own imports — no concurrent tests, no concurrent runner ' +\n 'config, no `import()` inside a Promise combinator; a test that does so on purpose is a reviewed exception with ' +\n 'its why, stale once it no longer does.',\n run(context) {\n const findings: Finding[] = [];\n let loaders = 0;\n const used = new Set<string>();\n for (const file of context.files({ roots, kinds: ['code'], tests: false })) {\n const result = strayDynamicImports(file, [facts.loader, ...others]);\n loaders += result.loaders;\n for (const name of result.used) used.add(name);\n for (const node of result.stray) {\n findings.push({ file: file.path, line: lineOfNode(file, node), detail: `${node.getText(file.sourceFile).slice(0, 80)} is not a module-level ${facts.loader} loader` });\n }\n }\n if (!loaders) findings.push({ file: `(${roots.join(', ')})`, detail: `no ${facts.loader} loader found, so the guard checks nothing` });\n for (const name of others) if (!used.has(name)) findings.push({ file: '(otherLoaders)', detail: `stale other loader: ${name} wraps no import` });\n const exceptions = new Set(facts.testExceptions.map((e) => e.path));\n const overlapping = new Set<string>();\n for (const file of context.files({ roots, kinds: ['code'], tests: 'only' })) {\n const hits = overlappingTestImports(file);\n if (hits.length) overlapping.add(file.path);\n if (exceptions.has(file.path)) continue;\n for (const { node, detail } of hits) findings.push({ file: file.path, line: lineOfNode(file, node), detail });\n }\n for (const path of exceptions) if (!overlapping.has(path)) findings.push({ file: path, detail: 'stale test exception: the file overlaps no import' });\n for (const config of facts.testRunnerConfigs) {\n if (!context.reader.exists(config)) findings.push({ file: config, detail: 'the test runner config no longer exists' });\n else {\n const view = context.file(config);\n const m = /\\bconcurrent\\s*:/.exec(view.code);\n if (m) findings.push({ file: config, line: view.lineOf(m.index), detail: 'the runner config makes tests concurrent' });\n }\n }\n return findings;\n },\n },\n ];\n },\n};\n\n// ---------------------------------------------------------------------------------------------\n// Light functions never reach heavy modules.\n\nexport interface LightFunctionFacts {\n /** The Functions entry module that exports every deployed function. */\n entryIndex: string;\n /** Exported functions whose static import closure is kept small. */\n lightFunctions: readonly string[];\n /** Packages a light closure never imports statically, with any subpath that is light, each with its why. */\n heavyPackages: ReadonlyArray<{ specifier: string; lightSubpaths: readonly string[]; why: string }>;\n /** Functions modules a light closure never reaches statically, each with its why. */\n heavyFiles: readonly Reviewed[];\n}\n\n/** A file's static runtime import edges: no `import()` (the lazy path), no `import type` / `export type`. */\nexport function staticEdges(file: FileView): string[] {\n return moduleImports(file.sourceFile, ['import', 'export'])\n .filter((site) => site.topLevel && !site.typeOnly)\n .map((site) => site.spec);\n}\n\n/** The repo-relative file a relative specifier names among `known`, or null. */\nexport function resolveModule(fromPath: string, spec: string, known: ReadonlySet<string>): string | null {\n const base = resolveRelative(fromPath, spec)?.path;\n if (base === undefined) return null;\n const stem = base.replace(/\\.[cm]?jsx?$/, '');\n const candidates = [base, `${stem}.ts`, `${stem}.tsx`, `${stem}.mts`, `${stem}.cts`, `${base}.ts`, `${base}.tsx`, `${base}/index.ts`, `${base}/index.tsx`];\n return candidates.find((c) => known.has(c)) ?? null;\n}\n\n/** Each exported name of a module, with the specifier it is re-exported from (when it is). */\nexport function exportsOf(file: FileView): { names: Map<string, string | null>; unreadable: ts.Node[] } {\n const names = new Map<string, string | null>();\n const unreadable: ts.Node[] = [];\n const exported = (node: ts.Node) => ts.canHaveModifiers(node) && !!ts.getModifiers(node)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);\n for (const stmt of file.sourceFile.statements) {\n if (ts.isExportDeclaration(stmt)) {\n const from = stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier) ? stmt.moduleSpecifier.text : null;\n if (stmt.exportClause && ts.isNamedExports(stmt.exportClause)) for (const e of stmt.exportClause.elements) names.set(e.name.text, from);\n else unreadable.push(stmt);\n } else if (ts.isVariableStatement(stmt) && exported(stmt)) {\n for (const d of stmt.declarationList.declarations) if (ts.isIdentifier(d.name)) names.set(d.name.text, null);\n } else if ((ts.isFunctionDeclaration(stmt) || ts.isClassDeclaration(stmt)) && exported(stmt) && stmt.name) {\n names.set(stmt.name.text, null);\n }\n }\n return { names, unreadable };\n}\n\nexport const lightFunctionGuard: GenericGuardDefinition<LightFunctionFacts> = {\n id: 'lightFunctions',\n absentWhen: 'the app designates no light functions',\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.entryIndex, 'entryIndex', problems);\n namesProblem(facts?.lightFunctions, 'lightFunctions', problems);\n reviewedProblems(facts?.heavyPackages, 'heavyPackages', problems, { key: 'specifier' });\n for (const p of facts?.heavyPackages ?? []) if (!Array.isArray(p?.lightSubpaths)) problems.push(`heavy package ${String(p?.specifier)} needs lightSubpaths (declare [] when none)`);\n reviewedProblems(facts?.heavyFiles, 'heavyFiles', problems);\n if (!facts?.heavyPackages?.length && !facts?.heavyFiles?.length) problems.push('neither heavyPackages nor heavyFiles names anything, so the guard checks nothing');\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'light functions never statically reach a heavy module',\n description:\n `The light functions (${facts.lightFunctions.join(', ')}) are hot interactive paths whose static import closure ` +\n 'is small by design: walking the static import graph from each one\\'s module (dynamic `import()` and type-only ' +\n 'imports are not edges) never reaches a heavy package or a heavy Functions module, which would load on every ' +\n 'cold start. Cut the edge — load the heavy module through the module-level lazy loader at its true usage site — ' +\n 'instead of relaxing the list. Every relative import must resolve, every light function must be exported by ' +\n 'the entry module, and every heavy file must exist.',\n timeoutMs: 120_000,\n run(context) {\n const findings: Finding[] = [];\n const files = context.files(FUNCTIONS_CODE);\n const known = new Set(files.map((f) => f.path));\n const graph = new Map<string, { internal: string[]; external: string[] }>();\n for (const file of files) {\n const internal: string[] = [];\n const external: string[] = [];\n for (const spec of staticEdges(file)) {\n if (!spec.startsWith('.')) external.push(spec);\n else {\n const target = resolveModule(file.path, spec, known);\n if (target) internal.push(target);\n else findings.push({ file: file.path, detail: `cannot resolve ${spec}, so the closure through it is unread` });\n }\n }\n graph.set(file.path, { internal, external });\n }\n for (const { path } of facts.heavyFiles) if (!known.has(path)) findings.push({ file: path, detail: 'stale heavy file: it is not a Functions module' });\n if (!known.has(facts.entryIndex)) return [...findings, { file: facts.entryIndex, detail: 'the entry module is gone or outside the Functions tree' }];\n const { names } = exportsOf(files.find((f) => f.path === facts.entryIndex)!);\n for (const fn of facts.lightFunctions) {\n const from = names.get(fn);\n const start = from ? resolveModule(facts.entryIndex, from, known) : null;\n if (!start) {\n findings.push({ file: facts.entryIndex, detail: `light function ${fn} is not re-exported from a Functions module` });\n continue;\n }\n const seen = new Set([start]);\n const externals = new Set<string>();\n const stack = [start];\n while (stack.length) {\n const node = graph.get(stack.pop()!);\n if (!node) continue;\n node.external.forEach((e) => externals.add(e));\n for (const next of node.internal) {\n if (seen.has(next)) continue;\n seen.add(next);\n stack.push(next);\n }\n }\n for (const spec of externals) {\n const heavy = facts.heavyPackages.find((p) => namesModule(spec, p.specifier) && !p.lightSubpaths.includes(spec));\n if (heavy) findings.push({ file: start, detail: `light function ${fn} statically reaches ${spec}` });\n }\n for (const { path } of facts.heavyFiles) if (seen.has(path)) findings.push({ file: start, detail: `light function ${fn} statically reaches ${path}` });\n }\n return findings;\n },\n },\n ];\n },\n};\n\n// ---------------------------------------------------------------------------------------------\n// The split-codebase manifest.\n\nexport interface CodebaseManifestFacts {\n /** The JSON manifest mapping each codebase name to the exports it deploys (`{ codebases: { name: [exports] } }`). */\n manifest: string;\n /** The Functions entry module that exports every deployed function. */\n entryIndex: string;\n /** The deploy config whose `functions` entries declare each codebase. */\n deployConfig: string;\n /** Each codebase entry's source folder, with `{codebase}` for its name. */\n sourceTemplate: string;\n /** Each codebase entry's predeploy commands, with `{codebase}` for its name. */\n predeployTemplate: readonly string[];\n}\n\nfunction readJson(context: GuardContext, path: string, findings: Finding[]): unknown {\n if (!context.reader.exists(path)) {\n findings.push({ file: path, detail: 'the file no longer exists' });\n return undefined;\n }\n try {\n return JSON.parse(context.file(path).text);\n } catch (err) {\n findings.push({ file: path, detail: `cannot be read as JSON (${(err as Error).message})` });\n return undefined;\n }\n}\n\nexport const codebaseManifestGuard: GenericGuardDefinition<CodebaseManifestFacts> = {\n id: 'codebaseManifest',\n absentWhen: 'the app deploys its Functions as one codebase',\n factProblems(facts) {\n const problems: string[] = [];\n for (const key of ['manifest', 'entryIndex', 'deployConfig', 'sourceTemplate'] as const) textProblem(facts?.[key], key, problems);\n if (typeof facts?.sourceTemplate === 'string' && !facts.sourceTemplate.includes('{codebase}')) problems.push('sourceTemplate names no {codebase}');\n namesProblem(facts?.predeployTemplate, 'predeployTemplate', problems, { nonEmpty: false });\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'the codebase manifest deploys every function exactly once',\n description:\n `${facts.manifest} maps every export of ${facts.entryIndex} to exactly one Functions codebase — none missing, none ` +\n `stale, none in two — and ${facts.deployConfig} declares exactly the manifest's codebases, each from its source ` +\n 'folder with its predeploy build. A function in no codebase never deploys; one in two deploys twice; a codebase ' +\n 'the deploy config does not declare is never built. The entry module re-exports by name, never `export *`.',\n run(context) {\n const findings: Finding[] = [];\n const manifest = readJson(context, facts.manifest, findings) as { codebases?: Record<string, unknown> } | undefined;\n const deploy = readJson(context, facts.deployConfig, findings) as { functions?: unknown } | undefined;\n if (!context.reader.exists(facts.entryIndex)) return [...findings, { file: facts.entryIndex, detail: 'the entry module no longer exists' }];\n const index = context.file(facts.entryIndex);\n const { names, unreadable } = exportsOf(index);\n for (const node of unreadable) findings.push({ file: index.path, line: lineOfNode(index, node), detail: 'export * hides which functions the module deploys' });\n if (!names.size) findings.push({ file: index.path, detail: 'no export found, so the guard checks nothing' });\n if (!manifest || typeof manifest.codebases !== 'object' || !manifest.codebases) {\n if (manifest) findings.push({ file: facts.manifest, detail: 'no codebases object' });\n return findings;\n }\n const seen = new Map<string, string>();\n for (const [codebase, list] of Object.entries(manifest.codebases)) {\n if (!Array.isArray(list)) {\n findings.push({ file: facts.manifest, detail: `codebase ${codebase} is not a list of exports` });\n continue;\n }\n for (const name of list as unknown[]) {\n if (typeof name !== 'string') continue;\n if (seen.has(name)) findings.push({ file: facts.manifest, detail: `${name} is in two codebases (${seen.get(name)} and ${codebase})` });\n seen.set(name, codebase);\n }\n }\n for (const name of names.keys()) if (!seen.has(name)) findings.push({ file: facts.manifest, detail: `${name} is exported but in no codebase` });\n for (const name of seen.keys()) if (!names.has(name)) findings.push({ file: facts.manifest, detail: `stale entry ${name}: the entry module does not export it` });\n if (!deploy) return findings;\n const entries = Array.isArray(deploy.functions) ? (deploy.functions as Array<Record<string, unknown>>) : null;\n if (!entries) return [...findings, { file: facts.deployConfig, detail: 'functions is not a list of codebase entries' }];\n const declared = entries.map((e) => String(e.codebase));\n const codebases = Object.keys(manifest.codebases);\n for (const cb of codebases) if (!declared.includes(cb)) findings.push({ file: facts.deployConfig, detail: `codebase ${cb} is not declared` });\n for (const cb of declared) if (!codebases.includes(cb)) findings.push({ file: facts.deployConfig, detail: `codebase ${cb} is not in the manifest` });\n for (const entry of entries) {\n const cb = String(entry.codebase);\n const source = facts.sourceTemplate.split('{codebase}').join(cb);\n if (entry.source !== source) findings.push({ file: facts.deployConfig, detail: `codebase ${cb} deploys from ${String(entry.source)}, not ${source}` });\n const predeploy = facts.predeployTemplate.map((t) => t.split('{codebase}').join(cb));\n if (JSON.stringify(entry.predeploy ?? []) !== JSON.stringify(predeploy)) {\n findings.push({ file: facts.deployConfig, detail: `codebase ${cb}'s predeploy is not ${JSON.stringify(predeploy)}` });\n }\n }\n return findings;\n },\n },\n ];\n },\n};\n"]}
@@ -27,6 +27,16 @@ export interface MonitoringFacts {
27
27
  sdkInitFiles: readonly Reviewed[];
28
28
  /** The Functions test seam that records captures; tests use it instead of mocking the package. */
29
29
  functionsTestRecorder: string;
30
+ /**
31
+ * Entry points whose failures their core reports: the entry file, the core module it hands every
32
+ * event to, and the why (`[]` when there is none). An entry is stale when the core no longer
33
+ * captures, the entry file no longer imports it, or the entry file reports on its own.
34
+ */
35
+ reportedByCore: ReadonlyArray<{
36
+ path: string;
37
+ core: string;
38
+ why: string;
39
+ }>;
30
40
  }
31
41
  /** The entry-point shapes a file defines, or none when its failures reach monitoring. */
32
42
  export declare function unmonitoredEntryPoint(file: FileView, facts: Pick<MonitoringFacts, 'monitoringPackage' | 'captureCalls' | 'callableExits'>): string[];
@@ -1 +1 @@
1
- {"version":3,"file":"monitoring.d.ts","sourceRoot":"","sources":["../../../src/modules/backend/monitoring.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"monitoring.d.ts","sourceRoot":"","sources":["../../../src/modules/backend/monitoring.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import ts from 'typescript';
6
6
  import { calleeName, forEachNode, lineOfNode } from '../../support/ast.js';
7
7
  import { loaderProblem, namesProblem, reviewedProblems, textProblem } from '../../support/facts.js';
8
8
  import { MODULE_LOADS, moduleImports, namesModule } from '../../support/imports.js';
9
+ import { resolveRelative } from '../../support/paths.js';
9
10
  import { escapeRegExp } from '../../support/text.js';
10
11
  const FUNCTIONS_CODE = { roots: ['functions'], kinds: ['code'], tests: false };
11
12
  const APP_CODE = { roots: ['app'], kinds: ['code'], tests: false };
@@ -22,6 +23,23 @@ function matchIndexes(file, pattern) {
22
23
  out.push(m.index);
23
24
  return out;
24
25
  }
26
+ /** A module path without its source or emitted extension, for comparing an import to a file. */
27
+ const withoutExtension = (path) => path.replace(/\.(?:[cm]?[jt]sx?)$/, '');
28
+ /** True when a file imports the module at `corePath` for its values. */
29
+ function importsModule(file, corePath) {
30
+ const target = withoutExtension(corePath);
31
+ return file.imports.some(({ spec, typeOnly }) => {
32
+ if (typeOnly)
33
+ return false;
34
+ const resolved = resolveRelative(file.path, spec);
35
+ return resolved !== null && !resolved.escapes && withoutExtension(resolved.path) === target;
36
+ });
37
+ }
38
+ /** True when a file imports the monitoring package and calls one of its capture calls. */
39
+ function reportsToMonitoring(file, facts) {
40
+ const importsMonitoring = moduleImports(file.sourceFile, MODULE_LOADS).some(({ spec, typeOnly }) => !typeOnly && namesModule(spec, facts.monitoringPackage));
41
+ return importsMonitoring && facts.captureCalls.some((capture) => new RegExp(`\\b${escapeRegExp(capture)}\\s*\\(`).test(file.code));
42
+ }
25
43
  /** Every Cloud Functions entry-point shape, with the label a finding reports. */
26
44
  const ENTRY_POINT_SHAPES = [
27
45
  { shape: 'onCall', re: /\bonCall\s*(?:<[^>]*>)?\s*\(/ },
@@ -41,9 +59,7 @@ export function unmonitoredEntryPoint(file, facts) {
41
59
  return [];
42
60
  if (facts.callableExits.some((exit) => callPattern(exit).test(file.code)))
43
61
  return [];
44
- const importsMonitoring = moduleImports(file.sourceFile, MODULE_LOADS).some(({ spec, typeOnly }) => !typeOnly && namesModule(spec, facts.monitoringPackage));
45
- const captures = facts.captureCalls.some((capture) => new RegExp(`\\b${escapeRegExp(capture)}\\s*\\(`).test(file.code));
46
- return importsMonitoring && captures ? [] : shapes;
62
+ return reportsToMonitoring(file, facts) ? [] : shapes;
47
63
  }
48
64
  /** Every import of a provider SDK package. */
49
65
  export function providerSdkImports(file, sdks) {
@@ -79,6 +95,12 @@ export const monitoringGuard = {
79
95
  textProblem(facts?.providerInitCall, 'providerInitCall', problems);
80
96
  reviewedProblems(facts?.sdkInitFiles, 'sdkInitFiles', problems);
81
97
  textProblem(facts?.functionsTestRecorder, 'functionsTestRecorder', problems);
98
+ if (!Array.isArray(facts?.reportedByCore))
99
+ problems.push('reportedByCore is missing (declare [] when every entry point reports its own failures)');
100
+ for (const entry of facts?.reportedByCore ?? []) {
101
+ if (!entry?.path || !entry.core || !entry.why?.trim())
102
+ problems.push('a reportedByCore entry needs its entry file, its core module, and its why');
103
+ }
82
104
  return problems;
83
105
  },
84
106
  build(facts) {
@@ -90,13 +112,38 @@ export const monitoringGuard = {
90
112
  `or database trigger — either exits its callable through ${facts.callableExits.join(' / ') || 'the app\'s callable exit'} ` +
91
113
  `or imports ${facts.monitoringPackage} and calls ${facts.captureCalls.join(' / ')} on its failure path. A failure ` +
92
114
  'path that only writes a log line is not monitored: nothing watches the log, so a background trigger fails ' +
93
- 'invisibly. An import that is never called is not monitoring either.',
115
+ 'invisibly. An import that is never called is not monitoring either. An entry point whose core reports every ' +
116
+ 'failure is a reviewed entry naming that core, with its why; it is stale when the core no longer captures, ' +
117
+ 'the entry point no longer imports it, or the entry point reports on its own.',
94
118
  run(context) {
95
119
  const findings = [];
120
+ const reviewed = new Map(facts.reportedByCore.map((entry) => [entry.path, entry]));
121
+ const seen = new Set();
96
122
  for (const file of context.files(FUNCTIONS_CODE)) {
97
123
  const shapes = unmonitoredEntryPoint(file, facts);
98
- if (shapes.length)
99
- findings.push({ file: file.path, detail: `defines ${shapes.join(', ')} and reports no failure to monitoring` });
124
+ const entry = reviewed.get(file.path);
125
+ if (!entry) {
126
+ if (shapes.length)
127
+ findings.push({ file: file.path, detail: `defines ${shapes.join(', ')} and reports no failure to monitoring` });
128
+ continue;
129
+ }
130
+ seen.add(file.path);
131
+ if (!ENTRY_POINT_SHAPES.some(({ re }) => re.test(file.code))) {
132
+ findings.push({ file: file.path, detail: 'a reportedByCore entry for a file that defines no entry point' });
133
+ }
134
+ else if (!shapes.length) {
135
+ findings.push({ file: file.path, detail: 'a reportedByCore entry for an entry point that reports on its own' });
136
+ }
137
+ else if (!importsModule(file, entry.core)) {
138
+ findings.push({ file: file.path, detail: `a reportedByCore entry names ${entry.core}, which the entry point does not import` });
139
+ }
140
+ else if (!context.reader.exists(entry.core) || !reportsToMonitoring(context.file(entry.core), facts)) {
141
+ findings.push({ file: file.path, detail: `a reportedByCore entry names ${entry.core}, which reports no failure to monitoring` });
142
+ }
143
+ }
144
+ for (const entry of facts.reportedByCore) {
145
+ if (!seen.has(entry.path))
146
+ findings.push({ file: entry.path, detail: 'a reportedByCore entry for a file the Functions code does not hold' });
100
147
  }
101
148
  return findings;
102
149
  },