mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-03 02:21:44 +00:00
Some checks are pending
CodeQL / Analyze (python) (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / ci (push) Blocked by required conditions
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
* fix(web): drop TypeScript 7-incompatible tsconfig paths Remove baseUrl and the dead ../shared include so web project references typecheck under TypeScript 7. Co-authored-by: Cursor <cursoragent@cursor.com> * test(cli): parse TypeScript with a TypeScript 6 API package Keep AST guards working after the named typescript package becomes 7, which no longer ships the Compiler API. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(lint): pin root TypeScript to the 6 API package Give typescript-eslint a TypeScript 6 peer so syntax-only lint still installs after CLI and web move to TypeScript 7. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(deps): compile first-party packages with TypeScript 7.0.2 Unify CLI and web on the same native compiler line as gitnexus-shared so typecheck and emit no longer split 5.x versus 7.x. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(ci): describe parent TypeScript 7 as the shared compiler Stop saying web compiles shared with TypeScript 5 now that the parent lockfile is 7. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): compile shared from parent TypeScript on Vercel and skill-evolution Stop isolated npm installs in gitnexus-shared so those paths do not pull a second TypeScript 7 optional-platform tree. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: record TypeScript 7 typecheck and Dependabot major-split policy Keep contributor typecheck commands, and stop Dependabot from bumping shared onto a different TypeScript major than CLI and web. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(lint): pin root TypeScript to 5.9 so npm ci satisfies eslint peers typescript-eslint 8 peers typescript below 6.0.0, so the typescript6 alias made quality lint npm ci fail with ERESOLVE. Co-authored-by: Cursor <cursoragent@cursor.com> * test(cli): drop the TypeScript 6 Compiler API package TypeScript 7.0 has no classic createProgram surface, so parse-only guards now use Babel and Mode 4 uses the TypeScript 7 Checker. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: align contributor setup with parent TypeScript 7 compile Stop telling clones to npm-install gitnexus-shared; CI and Vercel already emit that package from a parent lib/tsc.js shim. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(web): typecheck React JSX on TypeScript 7 with explicit DOM libs TypeScript 7 no longer implies DOM or auto-includes @types, so the web app must declare React/JSX settings while Vite keeps plugin-react. Co-authored-by: Cursor <cursoragent@cursor.com> * test: pin Vercel --include=dev and share parse-only string helpers Production npm ci omits the web TypeScript unless --include=dev is on that install. Move staticStringValue next to the other Babel walk helpers so CLI help and contract tests share one source. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
105 lines
4.1 KiB
TypeScript
105 lines
4.1 KiB
TypeScript
/**
|
|
* Reads the bare-name sets in `src/config/ignore-service.ts` out of source.
|
|
*
|
|
* Those sets are module-private, and exporting them purely to be testable would
|
|
* widen a production surface to satisfy a test — the call
|
|
* `receiver-twin-list-drift.test.ts` documents. So the guards read the source
|
|
* instead, through `@babel/parser` (`parse-typescript-source.ts`).
|
|
*
|
|
* Using an AST parser for TypeScript syntax is what makes the guards
|
|
* trustworthy. A text scanner has to decide whether a delimiter opens a comment
|
|
* or sits inside a string, and it gets that wrong in both directions here: the
|
|
* ignore-list comments quote paths and carry an apostrophe (`Next.js's`), while
|
|
* a glob string such as `'** / *'` contains a comment-open sequence. It also
|
|
* has to guess which bracket belongs to the declaration rather than to a type
|
|
* annotation. Each of those is a way to silently read fewer members — and a
|
|
* guard that quietly stops seeing members is the exact defect these guards
|
|
* exist to catch.
|
|
*
|
|
* `setEntries` therefore refuses anything that is not a plain list of string
|
|
* literals, rather than skipping the members it cannot resolve.
|
|
*/
|
|
import { readFileSync } from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import * as t from '@babel/types';
|
|
import { forEachChild, nodeText, parseTypeScript } from './parse-typescript-source.js';
|
|
|
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
|
|
|
|
/** The analyzer's ignore rules — the sets every guard in this family reads. */
|
|
export const IGNORE_SERVICE_PATH = path.join(
|
|
REPO_ROOT,
|
|
'gitnexus',
|
|
'src',
|
|
'config',
|
|
'ignore-service.ts',
|
|
);
|
|
|
|
/** The browser upload pre-filter, whose excluded-directory set must not drift from the above. */
|
|
export const UPLOAD_FILTER_PATH = path.join(
|
|
REPO_ROOT,
|
|
'gitnexus-web',
|
|
'src',
|
|
'lib',
|
|
'upload-filter.ts',
|
|
);
|
|
|
|
export const readSource = (file: string): string => readFileSync(file, 'utf8');
|
|
|
|
/**
|
|
* The string literals `setName` is constructed from, in declaration order.
|
|
*
|
|
* Throws — never returns a short list — when the declaration is missing or holds
|
|
* anything other than plain string literals (a spread, an interpolation, a
|
|
* concatenation, a computed value).
|
|
*/
|
|
export const setEntries = (source: string, setName: string): string[] => {
|
|
const { ast } = parseTypeScript('ignore-set-source.ts', source);
|
|
|
|
let elements: t.ArrayExpression['elements'] | undefined;
|
|
const visit = (node: t.Node): void => {
|
|
if (
|
|
elements === undefined &&
|
|
t.isVariableDeclarator(node) &&
|
|
t.isIdentifier(node.id) &&
|
|
node.id.name === setName &&
|
|
node.init !== undefined &&
|
|
node.init !== null &&
|
|
t.isNewExpression(node.init) &&
|
|
node.init.arguments.length === 1 &&
|
|
t.isArrayExpression(node.init.arguments[0])
|
|
) {
|
|
elements = node.init.arguments[0].elements;
|
|
return;
|
|
}
|
|
forEachChild(node, visit);
|
|
};
|
|
visit(ast);
|
|
|
|
if (elements === undefined) {
|
|
throw new Error(`${setName} is not declared as \`new Set([...])\` — update this test`);
|
|
}
|
|
|
|
const unresolvable = elements.filter((element) => !t.isStringLiteral(element));
|
|
if (unresolvable.length > 0) {
|
|
const first = unresolvable[0];
|
|
const excerpt = first && typeof first === 'object' ? nodeText(source, first) : String(first);
|
|
throw new Error(
|
|
`${setName} holds ${unresolvable.length} member(s) that are not plain string literals ` +
|
|
`(first: \`${excerpt}\`). A source-reading guard cannot resolve ` +
|
|
`those, so switch this set to a runtime assertion rather than letting the guard see fewer members.`,
|
|
);
|
|
}
|
|
|
|
return elements.map((element) => (element as t.StringLiteral).value);
|
|
};
|
|
|
|
/**
|
|
* True when `setName` is mutated by `.add(...)` anywhere in `source`.
|
|
*
|
|
* `setEntries` reads the declaration only, so a member appended afterwards would
|
|
* be invisible to it. The guards assert this is false rather than under-reporting.
|
|
*/
|
|
export const hasRuntimeAdd = (source: string, setName: string): boolean =>
|
|
new RegExp(`\\b${setName}\\s*\\.\\s*add\\s*\\(`).test(source);
|