@codedrifters/configulator 0.0.276 → 0.0.278
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.mts +244 -1
- package/lib/index.d.ts +245 -2
- package/lib/index.js +464 -48
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +459 -50
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.mjs
CHANGED
|
@@ -2867,20 +2867,26 @@ var createPackageSkill = {
|
|
|
2867
2867
|
" places the sub-project at `packages/<scope>/<name>`.",
|
|
2868
2868
|
"",
|
|
2869
2869
|
"6. **Tell the user how to synthesize.** Instruct them to run, from",
|
|
2870
|
-
" the repo root:",
|
|
2870
|
+
" the repo root, the safe three-step regen sequence:",
|
|
2871
2871
|
"",
|
|
2872
2872
|
" ```",
|
|
2873
|
+
" pnpm i",
|
|
2873
2874
|
" pnpm exec projen",
|
|
2874
|
-
" pnpm
|
|
2875
|
+
" pnpm i",
|
|
2875
2876
|
" ```",
|
|
2876
2877
|
"",
|
|
2877
|
-
" `pnpm
|
|
2878
|
-
"
|
|
2879
|
-
"
|
|
2878
|
+
" The leading `pnpm i` syncs `node_modules` with `pnpm-lock.yaml`",
|
|
2879
|
+
" so synth runs against the right configulator/projen/plugin",
|
|
2880
|
+
" versions \u2014 without it, `pnpm exec projen` may synth against a",
|
|
2881
|
+
" stale resolved version of any pnpm-managed component and produce",
|
|
2882
|
+
" phantom drift in generated files. `pnpm exec projen` regenerates",
|
|
2883
|
+
" the sub-project tree; the trailing `pnpm i` updates the workspace",
|
|
2884
|
+
" lockfile to pick up any dependency changes projen wrote during",
|
|
2885
|
+
" synth. Do **not** run these commands yourself \u2014 the user runs them.",
|
|
2880
2886
|
"",
|
|
2881
2887
|
"## Guardrails",
|
|
2882
2888
|
"",
|
|
2883
|
-
"- Never run `pnpm exec projen`, `pnpm install`, `pnpm build`,",
|
|
2889
|
+
"- Never run `pnpm exec projen`, `pnpm install`, `pnpm i`, `pnpm build`,",
|
|
2884
2890
|
" `pnpm test`, or any other package-manager, build, or test command.",
|
|
2885
2891
|
" Emit the projen block and instructions only.",
|
|
2886
2892
|
"- Never scaffold outside `packages/`. Deployable apps belong under",
|
|
@@ -2990,20 +2996,26 @@ var createAppSkill = {
|
|
|
2990
2996
|
" sub-project at `apps/<scope>/<name>`.",
|
|
2991
2997
|
"",
|
|
2992
2998
|
"6. **Tell the user how to synthesize.** Instruct them to run, from",
|
|
2993
|
-
" the repo root:",
|
|
2999
|
+
" the repo root, the safe three-step regen sequence:",
|
|
2994
3000
|
"",
|
|
2995
3001
|
" ```",
|
|
3002
|
+
" pnpm i",
|
|
2996
3003
|
" pnpm exec projen",
|
|
2997
|
-
" pnpm
|
|
3004
|
+
" pnpm i",
|
|
2998
3005
|
" ```",
|
|
2999
3006
|
"",
|
|
3000
|
-
" `pnpm
|
|
3001
|
-
"
|
|
3002
|
-
"
|
|
3007
|
+
" The leading `pnpm i` syncs `node_modules` with `pnpm-lock.yaml`",
|
|
3008
|
+
" so synth runs against the right configulator/projen/plugin",
|
|
3009
|
+
" versions \u2014 without it, `pnpm exec projen` may synth against a",
|
|
3010
|
+
" stale resolved version of any pnpm-managed component and produce",
|
|
3011
|
+
" phantom drift in generated files. `pnpm exec projen` regenerates",
|
|
3012
|
+
" the sub-project tree; the trailing `pnpm i` updates the workspace",
|
|
3013
|
+
" lockfile to pick up any dependency changes projen wrote during",
|
|
3014
|
+
" synth. Do **not** run these commands yourself \u2014 the user runs them.",
|
|
3003
3015
|
"",
|
|
3004
3016
|
"## Guardrails",
|
|
3005
3017
|
"",
|
|
3006
|
-
"- Never run `pnpm exec projen`, `pnpm install`, `pnpm build`,",
|
|
3018
|
+
"- Never run `pnpm exec projen`, `pnpm install`, `pnpm i`, `pnpm build`,",
|
|
3007
3019
|
" `pnpm test`, or any other package-manager, build, or test command.",
|
|
3008
3020
|
" Emit the projen block and instructions only.",
|
|
3009
3021
|
"- Never scaffold outside `apps/`. Shared libraries belong under",
|
|
@@ -3149,20 +3161,26 @@ var createSiteSkill = {
|
|
|
3149
3161
|
" `sites/<scope>/<name>`.",
|
|
3150
3162
|
"",
|
|
3151
3163
|
"6. **Tell the user how to synthesize.** Instruct them to run, from",
|
|
3152
|
-
" the repo root:",
|
|
3164
|
+
" the repo root, the safe three-step regen sequence:",
|
|
3153
3165
|
"",
|
|
3154
3166
|
" ```",
|
|
3167
|
+
" pnpm i",
|
|
3155
3168
|
" pnpm exec projen",
|
|
3156
|
-
" pnpm
|
|
3169
|
+
" pnpm i",
|
|
3157
3170
|
" ```",
|
|
3158
3171
|
"",
|
|
3159
|
-
" `pnpm
|
|
3160
|
-
"
|
|
3161
|
-
"
|
|
3172
|
+
" The leading `pnpm i` syncs `node_modules` with `pnpm-lock.yaml`",
|
|
3173
|
+
" so synth runs against the right configulator/projen/plugin",
|
|
3174
|
+
" versions \u2014 without it, `pnpm exec projen` may synth against a",
|
|
3175
|
+
" stale resolved version of any pnpm-managed component and produce",
|
|
3176
|
+
" phantom drift in generated files. `pnpm exec projen` regenerates",
|
|
3177
|
+
" the sub-project tree; the trailing `pnpm i` updates the workspace",
|
|
3178
|
+
" lockfile to pick up any dependency changes projen wrote during",
|
|
3179
|
+
" synth. Do **not** run these commands yourself \u2014 the user runs them.",
|
|
3162
3180
|
"",
|
|
3163
3181
|
"## Guardrails",
|
|
3164
3182
|
"",
|
|
3165
|
-
"- Never run `pnpm exec projen`, `pnpm install`, `pnpm build`,",
|
|
3183
|
+
"- Never run `pnpm exec projen`, `pnpm install`, `pnpm i`, `pnpm build`,",
|
|
3166
3184
|
" `pnpm test`, or any other package-manager, build, or test command.",
|
|
3167
3185
|
" Emit the projen block and instructions only.",
|
|
3168
3186
|
"- Never scaffold the monorepo-wide docs site under `sites/`. The",
|
|
@@ -3266,7 +3284,7 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
|
|
|
3266
3284
|
"## Important Notes",
|
|
3267
3285
|
"",
|
|
3268
3286
|
"- **Never edit generated files** \u2014 they are marked with `// ~~ Generated by projen`",
|
|
3269
|
-
"- **After modifying Projen configuration**, run `pnpm exec projen`
|
|
3287
|
+
"- **After modifying Projen configuration**, run the three-step regen sequence: `pnpm i`, then `pnpm exec projen`, then `pnpm i` again. The leading `pnpm i` syncs `node_modules` with the lockfile so synth runs against the right configulator/projen/plugin versions; the trailing `pnpm i` refreshes the lockfile to match anything projen rewrote in `package.json`.",
|
|
3270
3288
|
"- **Configure dependencies through Projen** \u2014 never use `npm install`, `pnpm add`, or `yarn add`. Add them to `deps` or `devDeps` in Projen config.",
|
|
3271
3289
|
"- **Export from index.ts** to maintain clean public APIs",
|
|
3272
3290
|
"",
|
|
@@ -3325,7 +3343,7 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
|
|
|
3325
3343
|
"",
|
|
3326
3344
|
"After making changes that need validation, tell the user the specific commands to run:",
|
|
3327
3345
|
"",
|
|
3328
|
-
"1. **After projen config changes** \u2014 tell the user to run `pnpm exec projen && pnpm
|
|
3346
|
+
"1. **After projen config changes** \u2014 tell the user to run the three-step regen sequence: `pnpm i && pnpm exec projen && pnpm i`",
|
|
3329
3347
|
"2. **After source code changes** \u2014 tell the user to run `pnpm --filter @codedrifters/<package> test`",
|
|
3330
3348
|
"3. **After multi-package changes** \u2014 tell the user to run `pnpm build:all`"
|
|
3331
3349
|
].join("\n"),
|
|
@@ -9101,7 +9119,7 @@ var githubWorkflowBundle = {
|
|
|
9101
9119
|
"",
|
|
9102
9120
|
"When the user says **open a PR** (or similar), follow these steps exactly:",
|
|
9103
9121
|
"",
|
|
9104
|
-
"1. **Regenerate project files** \u2014 run `pnpm exec projen
|
|
9122
|
+
"1. **Regenerate project files** \u2014 run the three-step regen sequence (`pnpm i`, then `pnpm exec projen`, then `pnpm i` again) to ensure all generated files are up to date. The leading `pnpm i` is required because `pnpm exec projen` synthesises against whatever version of configulator (and projen, and any projen plugins) is currently resolved in `node_modules`; if the lockfile has moved past `node_modules` (typically right after `git pull` lands a dependency upgrade, or on a fresh checkout), synth runs against stale templates and produces phantom drift in `.claude/`, `.github/labels.yml`, `CLAUDE.md`, and other generated files. The trailing `pnpm i` picks up any dependency changes projen wrote into `package.json` during synth. Check `git diff` after the third step \u2014 if there are changes, commit them before proceeding.",
|
|
9105
9123
|
"2. **Run the full monorepo build** \u2014 run `pnpm build:all` to compile, lint, and test all packages (mirrors the CI pipeline). This command requires the user to be authenticated to AWS on the prod account used for Turborepo remote caching (`readonlyaccess-prod-525259625215-us-east-1` profile). If the command fails due to AWS credentials, ask the user to authenticate first. If the build produces changes to turbo inputs (typically snapshot files or ESLint auto-fixes), commit those changes and run `pnpm build:all` again \u2014 the build must complete cleanly with no uncommitted changes.",
|
|
9106
9124
|
"3. **Check for uncommitted changes** \u2014 if any exist, commit them with a conventional commit message",
|
|
9107
9125
|
"4. **Pull and rebase from the default branch** \u2014 run `git pull origin {{repository.defaultBranch}} --rebase` to incorporate the latest changes and resolve any conflicts before pushing",
|
|
@@ -13799,7 +13817,7 @@ var issueWorkerSubAgent = {
|
|
|
13799
13817
|
"",
|
|
13800
13818
|
"Run the appropriate verification commands depending on what changed:",
|
|
13801
13819
|
"",
|
|
13802
|
-
"1. If Projen config was changed: `pnpm exec projen && pnpm
|
|
13820
|
+
"1. If Projen config was changed: run the three-step regen sequence `pnpm i && pnpm exec projen && pnpm i` (leading `pnpm i` syncs `node_modules` with the lockfile so synth runs against the right configulator/projen/plugin versions; trailing `pnpm i` refreshes the lockfile after synth)",
|
|
13803
13821
|
"2. Compile the affected package: `pnpm --filter @codedrifters/<package> compile`",
|
|
13804
13822
|
"3. Test the affected package: `pnpm --filter @codedrifters/<package> test`",
|
|
13805
13823
|
"4. If changes span multiple packages: `pnpm build:all`",
|
|
@@ -15090,7 +15108,7 @@ var pnpmBundle = {
|
|
|
15090
15108
|
"- Configure dependencies in Projen configuration files (`.projenrc.ts` or `projenrc/*.ts`)",
|
|
15091
15109
|
"- Add dependencies to `deps`, `devDeps`, or `peerDeps` arrays in project configuration",
|
|
15092
15110
|
'- Use catalog dependencies when available (e.g., `"aws-cdk-lib@catalog:"`)',
|
|
15093
|
-
"- Ask the user to run `pnpm exec projen`
|
|
15111
|
+
"- Ask the user to run the three-step regen sequence after updating dependency configuration: `pnpm i`, then `pnpm exec projen`, then `pnpm i` again. The leading `pnpm i` syncs `node_modules` with the lockfile so synth runs against the right configulator/projen/plugin versions; the trailing `pnpm i` picks up any dependency changes projen wrote during synth.",
|
|
15094
15112
|
"",
|
|
15095
15113
|
"**DO NOT:**",
|
|
15096
15114
|
"- Run `npm install some-package`",
|
|
@@ -16527,14 +16545,19 @@ var projenBundle = {
|
|
|
16527
16545
|
"",
|
|
16528
16546
|
"## Synthesizing Projen Configuration",
|
|
16529
16547
|
"",
|
|
16530
|
-
"After modifying any file in `projenrc/` or `.projenrc.ts`, regenerate project files:",
|
|
16548
|
+
"After modifying any file in `projenrc/` or `.projenrc.ts`, regenerate project files using the safe three-step sequence:",
|
|
16531
16549
|
"",
|
|
16532
16550
|
"```sh",
|
|
16551
|
+
"pnpm i",
|
|
16533
16552
|
"pnpm exec projen",
|
|
16534
|
-
"pnpm
|
|
16553
|
+
"pnpm i",
|
|
16535
16554
|
"```",
|
|
16536
16555
|
"",
|
|
16537
|
-
"
|
|
16556
|
+
"All three steps are required:",
|
|
16557
|
+
"",
|
|
16558
|
+
"1. The leading `pnpm i` guarantees `node_modules` matches `pnpm-lock.yaml` before synth. Without this step, `pnpm exec projen` may synth against a stale version of any pnpm-resolved component (configulator itself, projen, or any plugin) that the lockfile has already moved past \u2014 most commonly right after `git pull` updates the lockfile or on a fresh checkout. The result is phantom drift in `.claude/`, `.github/labels.yml`, `CLAUDE.md`, and other configulator-generated files that looks like a real bundle change but vanishes after running `pnpm i`.",
|
|
16559
|
+
"2. `pnpm exec projen` regenerates files against the now-synced templates.",
|
|
16560
|
+
"3. The trailing `pnpm i` picks up any dependency changes projen wrote into `package.json` during the synth pass and refreshes the lockfile.",
|
|
16538
16561
|
"",
|
|
16539
16562
|
"## Building",
|
|
16540
16563
|
"",
|
|
@@ -16615,7 +16638,7 @@ var projenBundle = {
|
|
|
16615
16638
|
"After finishing implementation work, validate that changes are correct by running the appropriate commands depending on what was changed:",
|
|
16616
16639
|
"",
|
|
16617
16640
|
"1. **Projen config changes** (`projenrc/`, `.projenrc.ts`):",
|
|
16618
|
-
" - Run `pnpm exec projen
|
|
16641
|
+
" - Run the three-step regen sequence: `pnpm i`, then `pnpm exec projen`, then `pnpm i` again",
|
|
16619
16642
|
" - Verify no unexpected generated file changes with `git diff`",
|
|
16620
16643
|
"",
|
|
16621
16644
|
"2. **Source code changes** (in a sub-package):",
|
|
@@ -16632,8 +16655,8 @@ var projenBundle = {
|
|
|
16632
16655
|
"",
|
|
16633
16656
|
"| Task | Command |",
|
|
16634
16657
|
"|------|---------|",
|
|
16635
|
-
"|
|
|
16636
|
-
"| Install deps | `pnpm
|
|
16658
|
+
"| Regenerate projen configuration | `pnpm i && pnpm exec projen && pnpm i` |",
|
|
16659
|
+
"| Install deps | `pnpm i` |",
|
|
16637
16660
|
"| Full monorepo build | `pnpm build:all` |",
|
|
16638
16661
|
"| Root build only | `pnpm build` |",
|
|
16639
16662
|
"| Compile one package | `pnpm --filter @codedrifters/<pkg> compile` |",
|
|
@@ -16691,7 +16714,7 @@ var projenBundle = {
|
|
|
16691
16714
|
"",
|
|
16692
16715
|
"## After Any Change",
|
|
16693
16716
|
"",
|
|
16694
|
-
"Run `pnpm exec projen
|
|
16717
|
+
"Run the three-step regen sequence to regenerate the output files: `pnpm i`, then `pnpm exec projen`, then `pnpm i` again. The leading `pnpm i` syncs `node_modules` with the lockfile before synth so `pnpm exec projen` runs against the right configulator/projen/plugin versions; the trailing `pnpm i` refreshes the lockfile for any dependency changes projen made during synth."
|
|
16695
16718
|
].join("\n"),
|
|
16696
16719
|
tags: ["workflow"]
|
|
16697
16720
|
},
|
|
@@ -16709,7 +16732,7 @@ var projenBundle = {
|
|
|
16709
16732
|
"- Edit Projen configuration in:",
|
|
16710
16733
|
" - `.projenrc.ts` (root)",
|
|
16711
16734
|
" - `projenrc/*.ts` (package-specific)",
|
|
16712
|
-
"- After making Projen changes, run `pnpm exec projen`
|
|
16735
|
+
"- After making Projen changes, run the three-step regen sequence: `pnpm i`, `pnpm exec projen`, `pnpm i`. The leading `pnpm i` ensures `node_modules` matches the lockfile so synth runs against the right configulator/projen/plugin versions; without it, synth can produce phantom drift in generated files. The trailing `pnpm i` picks up dependency changes projen wrote during synth.",
|
|
16713
16736
|
"",
|
|
16714
16737
|
"## Workspace Dependencies",
|
|
16715
16738
|
"",
|
|
@@ -26554,8 +26577,8 @@ var FALLBACKS = {
|
|
|
26554
26577
|
monorepoLayoutSeedBlock: ""
|
|
26555
26578
|
};
|
|
26556
26579
|
var TEMPLATE_RE = /\{\{(\w+(?:\.\w+)*)\}\}/g;
|
|
26557
|
-
function getNestedValue(obj,
|
|
26558
|
-
const parts =
|
|
26580
|
+
function getNestedValue(obj, path8) {
|
|
26581
|
+
const parts = path8.split(".");
|
|
26559
26582
|
let current = obj;
|
|
26560
26583
|
for (const part of parts) {
|
|
26561
26584
|
if (current == null || typeof current !== "object") {
|
|
@@ -29164,9 +29187,388 @@ function auditReportJsonSchema() {
|
|
|
29164
29187
|
};
|
|
29165
29188
|
}
|
|
29166
29189
|
|
|
29190
|
+
// src/docs-sync/scan/checks/api-diff-check.ts
|
|
29191
|
+
function parseApiRollup(rollup) {
|
|
29192
|
+
const fenceContents = extractFirstTsFence(rollup);
|
|
29193
|
+
if (fenceContents === void 0) {
|
|
29194
|
+
return [];
|
|
29195
|
+
}
|
|
29196
|
+
const lines = fenceContents.split("\n");
|
|
29197
|
+
const entries = [];
|
|
29198
|
+
let i = 0;
|
|
29199
|
+
while (i < lines.length) {
|
|
29200
|
+
const line = lines[i];
|
|
29201
|
+
const trimmed = line.trim();
|
|
29202
|
+
if (!trimmed.startsWith("export ")) {
|
|
29203
|
+
i += 1;
|
|
29204
|
+
continue;
|
|
29205
|
+
}
|
|
29206
|
+
const startIndex = i;
|
|
29207
|
+
let buffer = trimmed;
|
|
29208
|
+
let braceDepth = countBraceDelta(trimmed);
|
|
29209
|
+
let endsWithSemicolon = trimmed.endsWith(";");
|
|
29210
|
+
i += 1;
|
|
29211
|
+
while (i < lines.length && !isComplete(buffer, braceDepth, endsWithSemicolon)) {
|
|
29212
|
+
const next = lines[i];
|
|
29213
|
+
const nextTrimmed = next.trim();
|
|
29214
|
+
if (nextTrimmed.length === 0 || nextTrimmed.startsWith("//")) {
|
|
29215
|
+
i += 1;
|
|
29216
|
+
continue;
|
|
29217
|
+
}
|
|
29218
|
+
buffer = `${buffer} ${nextTrimmed}`;
|
|
29219
|
+
braceDepth += countBraceDelta(nextTrimmed);
|
|
29220
|
+
endsWithSemicolon = nextTrimmed.endsWith(";");
|
|
29221
|
+
i += 1;
|
|
29222
|
+
}
|
|
29223
|
+
const normalized = normalizeWhitespace(buffer);
|
|
29224
|
+
const name = extractDeclarationName(normalized);
|
|
29225
|
+
if (name) {
|
|
29226
|
+
entries.push({ name, signature: normalized });
|
|
29227
|
+
}
|
|
29228
|
+
if (name && normalized.startsWith("export {")) {
|
|
29229
|
+
const names = extractExportListNames(normalized);
|
|
29230
|
+
if (names.length > 1) {
|
|
29231
|
+
entries.pop();
|
|
29232
|
+
for (const exportName of names) {
|
|
29233
|
+
entries.push({ name: exportName, signature: normalized });
|
|
29234
|
+
}
|
|
29235
|
+
}
|
|
29236
|
+
}
|
|
29237
|
+
if (i === startIndex) {
|
|
29238
|
+
i += 1;
|
|
29239
|
+
}
|
|
29240
|
+
}
|
|
29241
|
+
const dedup = /* @__PURE__ */ new Map();
|
|
29242
|
+
for (const entry of entries) {
|
|
29243
|
+
if (!dedup.has(entry.name)) {
|
|
29244
|
+
dedup.set(entry.name, entry);
|
|
29245
|
+
}
|
|
29246
|
+
}
|
|
29247
|
+
return Array.from(dedup.values()).sort(
|
|
29248
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
29249
|
+
);
|
|
29250
|
+
}
|
|
29251
|
+
function diffApiRollups(baselineRollup, currentRollup) {
|
|
29252
|
+
const baseline = /* @__PURE__ */ new Map();
|
|
29253
|
+
for (const entry of parseApiRollup(baselineRollup)) {
|
|
29254
|
+
baseline.set(entry.name, entry);
|
|
29255
|
+
}
|
|
29256
|
+
const current = /* @__PURE__ */ new Map();
|
|
29257
|
+
for (const entry of parseApiRollup(currentRollup)) {
|
|
29258
|
+
current.set(entry.name, entry);
|
|
29259
|
+
}
|
|
29260
|
+
const added = [];
|
|
29261
|
+
const removed = [];
|
|
29262
|
+
const changed = [];
|
|
29263
|
+
for (const [name, entry] of current.entries()) {
|
|
29264
|
+
const before = baseline.get(name);
|
|
29265
|
+
if (!before) {
|
|
29266
|
+
added.push(entry);
|
|
29267
|
+
continue;
|
|
29268
|
+
}
|
|
29269
|
+
if (before.signature !== entry.signature) {
|
|
29270
|
+
changed.push(entry);
|
|
29271
|
+
}
|
|
29272
|
+
}
|
|
29273
|
+
for (const [name, entry] of baseline.entries()) {
|
|
29274
|
+
if (!current.has(name)) {
|
|
29275
|
+
removed.push(entry);
|
|
29276
|
+
}
|
|
29277
|
+
}
|
|
29278
|
+
added.sort((a, b) => a.name.localeCompare(b.name));
|
|
29279
|
+
removed.sort((a, b) => a.name.localeCompare(b.name));
|
|
29280
|
+
changed.sort((a, b) => a.name.localeCompare(b.name));
|
|
29281
|
+
return { added, removed, changed };
|
|
29282
|
+
}
|
|
29283
|
+
function createApiDiffCheck(options) {
|
|
29284
|
+
const baseline = options.baselineRollup;
|
|
29285
|
+
const current = options.currentRollup;
|
|
29286
|
+
const rollupPath = options.rollupPath ?? "";
|
|
29287
|
+
return {
|
|
29288
|
+
name: options.name ?? "apiDiff",
|
|
29289
|
+
run(_context) {
|
|
29290
|
+
const diff = diffApiRollups(baseline, current);
|
|
29291
|
+
const findings = [];
|
|
29292
|
+
for (const entry of diff.added) {
|
|
29293
|
+
findings.push({
|
|
29294
|
+
category: AuditCategory.ApiDiff,
|
|
29295
|
+
severity: AuditSeverity.Mechanical,
|
|
29296
|
+
location: { file: rollupPath, line: 0 },
|
|
29297
|
+
subject: entry.name,
|
|
29298
|
+
details: `New public export \`${entry.name}\` not present in baseline rollup.`,
|
|
29299
|
+
change: "added",
|
|
29300
|
+
symbol: entry.name,
|
|
29301
|
+
fixHint: "stub-tsdoc"
|
|
29302
|
+
});
|
|
29303
|
+
}
|
|
29304
|
+
for (const entry of diff.removed) {
|
|
29305
|
+
findings.push({
|
|
29306
|
+
category: AuditCategory.ApiDiff,
|
|
29307
|
+
severity: AuditSeverity.Advisory,
|
|
29308
|
+
location: { file: rollupPath, line: 0 },
|
|
29309
|
+
subject: entry.name,
|
|
29310
|
+
details: `Public export \`${entry.name}\` was present in baseline rollup but is gone in the current rollup.`,
|
|
29311
|
+
change: "removed",
|
|
29312
|
+
symbol: entry.name
|
|
29313
|
+
});
|
|
29314
|
+
}
|
|
29315
|
+
for (const entry of diff.changed) {
|
|
29316
|
+
findings.push({
|
|
29317
|
+
category: AuditCategory.ApiDiff,
|
|
29318
|
+
severity: AuditSeverity.Advisory,
|
|
29319
|
+
location: { file: rollupPath, line: 0 },
|
|
29320
|
+
subject: entry.name,
|
|
29321
|
+
details: `Public export \`${entry.name}\` signature changed since baseline rollup.`,
|
|
29322
|
+
change: "changed",
|
|
29323
|
+
symbol: entry.name
|
|
29324
|
+
});
|
|
29325
|
+
}
|
|
29326
|
+
return findings;
|
|
29327
|
+
}
|
|
29328
|
+
};
|
|
29329
|
+
}
|
|
29330
|
+
function extractFirstTsFence(rollup) {
|
|
29331
|
+
const lines = rollup.split("\n");
|
|
29332
|
+
let start = -1;
|
|
29333
|
+
for (let i = 0; i < lines.length; i++) {
|
|
29334
|
+
const line = lines[i].trim();
|
|
29335
|
+
if (line === "```ts" || line === "```typescript") {
|
|
29336
|
+
start = i + 1;
|
|
29337
|
+
break;
|
|
29338
|
+
}
|
|
29339
|
+
}
|
|
29340
|
+
if (start < 0) {
|
|
29341
|
+
return void 0;
|
|
29342
|
+
}
|
|
29343
|
+
for (let j = start; j < lines.length; j++) {
|
|
29344
|
+
if (lines[j].trim() === "```") {
|
|
29345
|
+
return lines.slice(start, j).join("\n");
|
|
29346
|
+
}
|
|
29347
|
+
}
|
|
29348
|
+
return lines.slice(start).join("\n");
|
|
29349
|
+
}
|
|
29350
|
+
function countBraceDelta(line) {
|
|
29351
|
+
let delta = 0;
|
|
29352
|
+
for (const ch of line) {
|
|
29353
|
+
if (ch === "{") {
|
|
29354
|
+
delta += 1;
|
|
29355
|
+
} else if (ch === "}") {
|
|
29356
|
+
delta -= 1;
|
|
29357
|
+
}
|
|
29358
|
+
}
|
|
29359
|
+
return delta;
|
|
29360
|
+
}
|
|
29361
|
+
function isComplete(buffer, braceDepth, endsWithSemicolon) {
|
|
29362
|
+
if (braceDepth > 0) {
|
|
29363
|
+
return false;
|
|
29364
|
+
}
|
|
29365
|
+
if (endsWithSemicolon) {
|
|
29366
|
+
return true;
|
|
29367
|
+
}
|
|
29368
|
+
return buffer.trimEnd().endsWith("}");
|
|
29369
|
+
}
|
|
29370
|
+
function normalizeWhitespace(s) {
|
|
29371
|
+
return s.replace(/\s+/g, " ").replace(/\(\s+/g, "(").replace(/\s+\)/g, ")").replace(/\[\s+/g, "[").replace(/\s+\]/g, "]").replace(/\{\s+/g, "{").replace(/\s+\}/g, "}").replace(/\s+,/g, ",").replace(/\s+;/g, ";").replace(/\s+:/g, ":").trim();
|
|
29372
|
+
}
|
|
29373
|
+
var DECLARATION_KEYWORDS = [
|
|
29374
|
+
"function",
|
|
29375
|
+
"class",
|
|
29376
|
+
"interface",
|
|
29377
|
+
"type",
|
|
29378
|
+
"enum",
|
|
29379
|
+
"const",
|
|
29380
|
+
"let",
|
|
29381
|
+
"var",
|
|
29382
|
+
"namespace",
|
|
29383
|
+
"abstract",
|
|
29384
|
+
"default",
|
|
29385
|
+
"async"
|
|
29386
|
+
];
|
|
29387
|
+
function extractDeclarationName(declaration) {
|
|
29388
|
+
const tokens = declaration.split(/\s+/);
|
|
29389
|
+
if (tokens.length === 0 || tokens[0] !== "export") {
|
|
29390
|
+
return void 0;
|
|
29391
|
+
}
|
|
29392
|
+
let cursor = 1;
|
|
29393
|
+
while (cursor < tokens.length && DECLARATION_KEYWORDS.includes(tokens[cursor])) {
|
|
29394
|
+
cursor += 1;
|
|
29395
|
+
}
|
|
29396
|
+
if (cursor >= tokens.length) {
|
|
29397
|
+
return void 0;
|
|
29398
|
+
}
|
|
29399
|
+
const candidate = tokens[cursor];
|
|
29400
|
+
if (candidate.startsWith("{")) {
|
|
29401
|
+
const stripped = candidate.replace(/^\{/, "").replace(/[},].*$/, "");
|
|
29402
|
+
return stripped || void 0;
|
|
29403
|
+
}
|
|
29404
|
+
const cleaned = candidate.replace(/[<(:;].*$/, "");
|
|
29405
|
+
return cleaned || void 0;
|
|
29406
|
+
}
|
|
29407
|
+
function extractExportListNames(declaration) {
|
|
29408
|
+
const open = declaration.indexOf("{");
|
|
29409
|
+
const close = declaration.indexOf("}", open);
|
|
29410
|
+
if (open < 0 || close < 0) {
|
|
29411
|
+
return [];
|
|
29412
|
+
}
|
|
29413
|
+
const inside = declaration.slice(open + 1, close);
|
|
29414
|
+
const names = [];
|
|
29415
|
+
for (const part of inside.split(",")) {
|
|
29416
|
+
const token = part.trim();
|
|
29417
|
+
if (!token) {
|
|
29418
|
+
continue;
|
|
29419
|
+
}
|
|
29420
|
+
const asMatch = token.match(/\sas\s+(\S+)$/);
|
|
29421
|
+
if (asMatch) {
|
|
29422
|
+
names.push(asMatch[1]);
|
|
29423
|
+
} else {
|
|
29424
|
+
names.push(token);
|
|
29425
|
+
}
|
|
29426
|
+
}
|
|
29427
|
+
return names;
|
|
29428
|
+
}
|
|
29429
|
+
|
|
29430
|
+
// src/docs-sync/scan/checks/reference-mismatch-check.ts
|
|
29431
|
+
function referenceRecordToFinding(record, signatureChangedSymbols) {
|
|
29432
|
+
if (signatureChangedSymbols.has(record.symbol)) {
|
|
29433
|
+
return {
|
|
29434
|
+
category: AuditCategory.ReferenceMismatches,
|
|
29435
|
+
severity: AuditSeverity.Advisory,
|
|
29436
|
+
location: { file: record.docPath, line: record.line },
|
|
29437
|
+
subject: record.symbol,
|
|
29438
|
+
details: `Inline reference \`${record.symbol}\` resolves to a symbol whose signature has changed; review the surrounding prose.`,
|
|
29439
|
+
mismatch: "signature-changed",
|
|
29440
|
+
symbol: record.symbol
|
|
29441
|
+
};
|
|
29442
|
+
}
|
|
29443
|
+
if (!record.isKnown) {
|
|
29444
|
+
return {
|
|
29445
|
+
category: AuditCategory.ReferenceMismatches,
|
|
29446
|
+
severity: AuditSeverity.Advisory,
|
|
29447
|
+
location: { file: record.docPath, line: record.line },
|
|
29448
|
+
subject: record.symbol,
|
|
29449
|
+
details: `Inline reference \`${record.symbol}\` does not match any known public export.`,
|
|
29450
|
+
mismatch: "unknown-symbol",
|
|
29451
|
+
symbol: record.symbol
|
|
29452
|
+
};
|
|
29453
|
+
}
|
|
29454
|
+
return void 0;
|
|
29455
|
+
}
|
|
29456
|
+
function createReferenceMismatchCheck(options) {
|
|
29457
|
+
const records = options.records;
|
|
29458
|
+
const signatureChangedSymbols = new Set(
|
|
29459
|
+
options.signatureChangedSymbols ?? []
|
|
29460
|
+
);
|
|
29461
|
+
return {
|
|
29462
|
+
name: options.name ?? "referenceMismatches",
|
|
29463
|
+
run(_context) {
|
|
29464
|
+
const findings = [];
|
|
29465
|
+
for (const record of records) {
|
|
29466
|
+
const finding = referenceRecordToFinding(
|
|
29467
|
+
record,
|
|
29468
|
+
signatureChangedSymbols
|
|
29469
|
+
);
|
|
29470
|
+
if (finding !== void 0) {
|
|
29471
|
+
findings.push(finding);
|
|
29472
|
+
}
|
|
29473
|
+
}
|
|
29474
|
+
return findings;
|
|
29475
|
+
}
|
|
29476
|
+
};
|
|
29477
|
+
}
|
|
29478
|
+
|
|
29479
|
+
// src/docs-sync/scan/checks/tsdoc-coverage-check.ts
|
|
29480
|
+
import * as path5 from "path";
|
|
29481
|
+
function tsdocRecordToFindings(record, context) {
|
|
29482
|
+
const findings = [];
|
|
29483
|
+
const file = relativizeFile(record.location.file, context.repoRoot);
|
|
29484
|
+
const line = record.location.line;
|
|
29485
|
+
const symbol = record.symbol;
|
|
29486
|
+
if (!record.hasSummary) {
|
|
29487
|
+
findings.push({
|
|
29488
|
+
category: AuditCategory.TsdocCoverage,
|
|
29489
|
+
severity: AuditSeverity.Mechanical,
|
|
29490
|
+
location: { file, line },
|
|
29491
|
+
subject: symbol,
|
|
29492
|
+
details: `Public export \`${symbol}\` is missing a TSDoc summary.`,
|
|
29493
|
+
shortfall: "missing-summary",
|
|
29494
|
+
symbol,
|
|
29495
|
+
fixHint: "stub-tsdoc"
|
|
29496
|
+
});
|
|
29497
|
+
return findings;
|
|
29498
|
+
}
|
|
29499
|
+
if (record.hasThinSummary) {
|
|
29500
|
+
findings.push({
|
|
29501
|
+
category: AuditCategory.TsdocCoverage,
|
|
29502
|
+
severity: AuditSeverity.Advisory,
|
|
29503
|
+
location: { file, line },
|
|
29504
|
+
subject: symbol,
|
|
29505
|
+
details: `Public export \`${symbol}\` carries a thin TSDoc summary; consider expanding it.`,
|
|
29506
|
+
shortfall: "thin-summary",
|
|
29507
|
+
symbol
|
|
29508
|
+
});
|
|
29509
|
+
}
|
|
29510
|
+
if (!record.hasParams && isParamCarryingKind(record)) {
|
|
29511
|
+
findings.push({
|
|
29512
|
+
category: AuditCategory.TsdocCoverage,
|
|
29513
|
+
severity: AuditSeverity.Advisory,
|
|
29514
|
+
location: { file, line },
|
|
29515
|
+
subject: symbol,
|
|
29516
|
+
details: `Public export \`${symbol}\` has parameters with no \`@param\` block tag.`,
|
|
29517
|
+
shortfall: "missing-params",
|
|
29518
|
+
symbol
|
|
29519
|
+
});
|
|
29520
|
+
}
|
|
29521
|
+
if (!record.hasReturns && isReturnCarryingKind(record)) {
|
|
29522
|
+
findings.push({
|
|
29523
|
+
category: AuditCategory.TsdocCoverage,
|
|
29524
|
+
severity: AuditSeverity.Advisory,
|
|
29525
|
+
location: { file, line },
|
|
29526
|
+
subject: symbol,
|
|
29527
|
+
details: `Public export \`${symbol}\` has a return value with no \`@returns\` block tag.`,
|
|
29528
|
+
shortfall: "missing-returns",
|
|
29529
|
+
symbol
|
|
29530
|
+
});
|
|
29531
|
+
}
|
|
29532
|
+
return findings;
|
|
29533
|
+
}
|
|
29534
|
+
function createTsdocCoverageCheck(options) {
|
|
29535
|
+
const records = options.records;
|
|
29536
|
+
return {
|
|
29537
|
+
name: options.name ?? "tsdocCoverage",
|
|
29538
|
+
run(context) {
|
|
29539
|
+
const findings = [];
|
|
29540
|
+
for (const record of records) {
|
|
29541
|
+
for (const finding of tsdocRecordToFindings(record, context)) {
|
|
29542
|
+
findings.push(finding);
|
|
29543
|
+
}
|
|
29544
|
+
}
|
|
29545
|
+
return findings;
|
|
29546
|
+
}
|
|
29547
|
+
};
|
|
29548
|
+
}
|
|
29549
|
+
function isParamCarryingKind(record) {
|
|
29550
|
+
return record.kind === "Function";
|
|
29551
|
+
}
|
|
29552
|
+
function isReturnCarryingKind(record) {
|
|
29553
|
+
return record.kind === "Function";
|
|
29554
|
+
}
|
|
29555
|
+
function relativizeFile(file, repoRoot) {
|
|
29556
|
+
if (!file) {
|
|
29557
|
+
return "";
|
|
29558
|
+
}
|
|
29559
|
+
if (!path5.isAbsolute(file)) {
|
|
29560
|
+
return toPosix3(file);
|
|
29561
|
+
}
|
|
29562
|
+
const rel = path5.relative(repoRoot, file);
|
|
29563
|
+
return toPosix3(rel);
|
|
29564
|
+
}
|
|
29565
|
+
function toPosix3(p) {
|
|
29566
|
+
return p.split(path5.sep).join("/");
|
|
29567
|
+
}
|
|
29568
|
+
|
|
29167
29569
|
// src/docs-sync/scan/run-scan.ts
|
|
29168
29570
|
import * as fs3 from "fs";
|
|
29169
|
-
import * as
|
|
29571
|
+
import * as path6 from "path";
|
|
29170
29572
|
var DEFAULT_AUDIT_REPORT_DIR = ".claude/state/docs-sync";
|
|
29171
29573
|
var SEVERITY_RANK = {
|
|
29172
29574
|
blocking: 0,
|
|
@@ -29181,7 +29583,7 @@ var AUDIT_CATEGORY_ORDER = [
|
|
|
29181
29583
|
AuditCategory.SampleFailures
|
|
29182
29584
|
];
|
|
29183
29585
|
function runScan(options) {
|
|
29184
|
-
const repoRoot =
|
|
29586
|
+
const repoRoot = path6.resolve(options.repoRoot);
|
|
29185
29587
|
const mode = options.mode;
|
|
29186
29588
|
const scope = options.scope ?? "";
|
|
29187
29589
|
const issueNumber = options.issueNumber;
|
|
@@ -29256,11 +29658,11 @@ function buildReport(args) {
|
|
|
29256
29658
|
};
|
|
29257
29659
|
}
|
|
29258
29660
|
function persistAuditReport(args) {
|
|
29259
|
-
const repoRoot =
|
|
29661
|
+
const repoRoot = path6.resolve(args.repoRoot);
|
|
29260
29662
|
const reportDir = args.reportDir ?? DEFAULT_AUDIT_REPORT_DIR;
|
|
29261
|
-
const targetDir =
|
|
29663
|
+
const targetDir = path6.resolve(repoRoot, reportDir);
|
|
29262
29664
|
fs3.mkdirSync(targetDir, { recursive: true });
|
|
29263
|
-
const targetFile =
|
|
29665
|
+
const targetFile = path6.join(
|
|
29264
29666
|
targetDir,
|
|
29265
29667
|
`${args.report.issueNumber}-audit.json`
|
|
29266
29668
|
);
|
|
@@ -29323,7 +29725,7 @@ function compareFindings(a, b) {
|
|
|
29323
29725
|
}
|
|
29324
29726
|
|
|
29325
29727
|
// src/docs-sync/tsdoc-coverage/coverage.ts
|
|
29326
|
-
import * as
|
|
29728
|
+
import * as path7 from "path";
|
|
29327
29729
|
import { TSDocParser } from "@microsoft/tsdoc";
|
|
29328
29730
|
import * as ts2 from "typescript";
|
|
29329
29731
|
var TsDocCoverageKind = {
|
|
@@ -29341,8 +29743,8 @@ var DEFAULT_THIN_SUMMARY_WORD_THRESHOLD = 4;
|
|
|
29341
29743
|
var DEFAULT_ENTRY_POINT = "src/index.ts";
|
|
29342
29744
|
function analyzeTsDocCoverage(options) {
|
|
29343
29745
|
const resolvedOptions = typeof options === "string" ? { packageRoot: options } : options;
|
|
29344
|
-
const packageRoot =
|
|
29345
|
-
const entryPoint =
|
|
29746
|
+
const packageRoot = path7.resolve(resolvedOptions.packageRoot);
|
|
29747
|
+
const entryPoint = path7.resolve(
|
|
29346
29748
|
packageRoot,
|
|
29347
29749
|
resolvedOptions.entryPoint ?? DEFAULT_ENTRY_POINT
|
|
29348
29750
|
);
|
|
@@ -29405,7 +29807,7 @@ function analyzeTsDocCoverage(options) {
|
|
|
29405
29807
|
}
|
|
29406
29808
|
function resolveCompilerOptions(packageRoot, tsconfigPath) {
|
|
29407
29809
|
if (tsconfigPath) {
|
|
29408
|
-
const absoluteTsconfig =
|
|
29810
|
+
const absoluteTsconfig = path7.resolve(packageRoot, tsconfigPath);
|
|
29409
29811
|
const configFile = ts2.readConfigFile(absoluteTsconfig, ts2.sys.readFile);
|
|
29410
29812
|
if (configFile.error) {
|
|
29411
29813
|
throw new Error(
|
|
@@ -29415,7 +29817,7 @@ function resolveCompilerOptions(packageRoot, tsconfigPath) {
|
|
|
29415
29817
|
const parsed = ts2.parseJsonConfigFileContent(
|
|
29416
29818
|
configFile.config,
|
|
29417
29819
|
ts2.sys,
|
|
29418
|
-
|
|
29820
|
+
path7.dirname(absoluteTsconfig)
|
|
29419
29821
|
);
|
|
29420
29822
|
return { ...parsed.options, noEmit: true };
|
|
29421
29823
|
}
|
|
@@ -29724,14 +30126,14 @@ var LAYOUT_ROOT_BY_PROJECT_TYPE = {
|
|
|
29724
30126
|
};
|
|
29725
30127
|
function validateMonorepoLayout(root) {
|
|
29726
30128
|
const violations = [];
|
|
29727
|
-
const rootOutdir =
|
|
30129
|
+
const rootOutdir = toPosix4(root.outdir);
|
|
29728
30130
|
for (const sub of root.subprojects) {
|
|
29729
30131
|
const className = sub.constructor.name;
|
|
29730
30132
|
const expectedRoot = expectedRootFor(sub, className);
|
|
29731
30133
|
if (expectedRoot === void 0) {
|
|
29732
30134
|
continue;
|
|
29733
30135
|
}
|
|
29734
|
-
const relOutdir = relativeOutdir(rootOutdir,
|
|
30136
|
+
const relOutdir = relativeOutdir(rootOutdir, toPosix4(sub.outdir));
|
|
29735
30137
|
if (!outdirMatchesRoot(relOutdir, expectedRoot)) {
|
|
29736
30138
|
violations.push({
|
|
29737
30139
|
projectName: sub.name,
|
|
@@ -29790,7 +30192,7 @@ function outdirMatchesRoot(relOutdir, expectedRoot) {
|
|
|
29790
30192
|
}
|
|
29791
30193
|
return segments.length >= 2;
|
|
29792
30194
|
}
|
|
29793
|
-
function
|
|
30195
|
+
function toPosix4(p) {
|
|
29794
30196
|
return p.replace(/\\/g, "/");
|
|
29795
30197
|
}
|
|
29796
30198
|
function relativeOutdir(rootOutdir, subOutdir) {
|
|
@@ -29879,8 +30281,8 @@ var ResetTask = class _ResetTask extends Component14 {
|
|
|
29879
30281
|
const resetTask = this.project.tasks.addTask(this.taskName, {
|
|
29880
30282
|
description: "Delete build artifacts specified by pathsToRemove option, or artifactsDirectory if pathsToRemove is empty"
|
|
29881
30283
|
});
|
|
29882
|
-
this.pathsToRemove.forEach((
|
|
29883
|
-
resetTask.exec(`[ -e "${
|
|
30284
|
+
this.pathsToRemove.forEach((path8) => {
|
|
30285
|
+
resetTask.exec(`[ -e "${path8}" ] && rm -rf ${path8} || true`);
|
|
29884
30286
|
});
|
|
29885
30287
|
const rootHasTurbo = TurboRepo.of(this.project.root) !== void 0;
|
|
29886
30288
|
const isSubproject = this.project !== this.project.root;
|
|
@@ -31801,7 +32203,7 @@ export const collections = {
|
|
|
31801
32203
|
`;
|
|
31802
32204
|
|
|
31803
32205
|
// src/typescript/typescript-config.ts
|
|
31804
|
-
import { relative as
|
|
32206
|
+
import { relative as relative7 } from "path";
|
|
31805
32207
|
import { Component as Component19 } from "projen";
|
|
31806
32208
|
import { ensureRelativePathStartsWithDot } from "projen/lib/util/path";
|
|
31807
32209
|
var TypeScriptConfig = class extends Component19 {
|
|
@@ -31820,7 +32222,7 @@ var TypeScriptConfig = class extends Component19 {
|
|
|
31820
32222
|
...tsPaths,
|
|
31821
32223
|
[dep.name]: [
|
|
31822
32224
|
ensureRelativePathStartsWithDot(
|
|
31823
|
-
|
|
32225
|
+
relative7(project.outdir, subproject.outdir)
|
|
31824
32226
|
)
|
|
31825
32227
|
]
|
|
31826
32228
|
};
|
|
@@ -31976,7 +32378,11 @@ export {
|
|
|
31976
32378
|
classifyRun,
|
|
31977
32379
|
companyProfileBundle,
|
|
31978
32380
|
compileFencedSamples,
|
|
32381
|
+
createApiDiffCheck,
|
|
32382
|
+
createReferenceMismatchCheck,
|
|
32383
|
+
createTsdocCoverageCheck,
|
|
31979
32384
|
customerProfileBundle,
|
|
32385
|
+
diffApiRollups,
|
|
31980
32386
|
docsSyncBundle,
|
|
31981
32387
|
emptyCategoryBuckets,
|
|
31982
32388
|
extractApiProcedure,
|
|
@@ -31991,11 +32397,13 @@ export {
|
|
|
31991
32397
|
maintenanceAuditBundle,
|
|
31992
32398
|
meetingAnalysisBundle,
|
|
31993
32399
|
orchestratorBundle,
|
|
32400
|
+
parseApiRollup,
|
|
31994
32401
|
peopleProfileBundle,
|
|
31995
32402
|
persistAuditReport,
|
|
31996
32403
|
pnpmBundle,
|
|
31997
32404
|
prReviewBundle,
|
|
31998
32405
|
projenBundle,
|
|
32406
|
+
referenceRecordToFinding,
|
|
31999
32407
|
regulatoryResearchBundle,
|
|
32000
32408
|
renderAgentTierCaseStatement,
|
|
32001
32409
|
renderAgentTierSection,
|
|
@@ -32058,6 +32466,7 @@ export {
|
|
|
32058
32466
|
slackBundle,
|
|
32059
32467
|
softwareProfileBundle,
|
|
32060
32468
|
standardsResearchBundle,
|
|
32469
|
+
tsdocRecordToFindings,
|
|
32061
32470
|
turborepoBundle,
|
|
32062
32471
|
typescriptBundle,
|
|
32063
32472
|
validateAgentTierConfig,
|