From c7cda38235ff71b58b8e07c33f366809e3a43879 Mon Sep 17 00:00:00 2001 From: Sylvain Duchesne Date: Mon, 17 Aug 2026 12:35:28 +0200 Subject: [PATCH] Name the script for what it does, now that it serves two providers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `link-polyfill.ts` handled one provider. It now handles two through a registry, one of which is not a polyfill, so both the filename and the `link:` verb said something false — and a name that is short but wrong misleads more than an opaque one would. It becomes `overlay-local-checkout.ts`, which is the operation: it copy-overlays a local package checkout into node_modules for development. "link" also implied a symlink, which is precisely what the script exists NOT to do — its own header spends a paragraph on why. No behaviour changed: same registry, same copy, same `--once`, same watch loop, same assertion. Both providers exercised afterwards, each reporting the singletons it must preserve — one package for the data layer, two for the indexing package, whose own checkout carries `file:` links and would otherwise smuggle in a second verifier. Seven references repaired by rewriting the sentence that carried them rather than swapping a path, across the script, `package.json`, `.env.example` and four doctrine leaves. No compatibility alias left behind: an old name kept "just in case" would restore exactly the ambiguity being removed. --- .env.example | 2 +- .project/concepts/tech-stack/_debt.md | 8 -------- .../caveat_polyfill-overlay-needs-a-dev-restart.md | 4 ++-- .project/concepts/tech-stack/knowledge_deployment.md | 2 +- .../tech-stack/knowledge_stack-and-commands.md | 4 ++-- .project/concepts/tech-stack/rule_bun-first.md | 2 +- package.json | 4 ++-- .../{link-polyfill.ts => overlay-local-checkout.ts} | 10 +++++----- 8 files changed, 14 insertions(+), 22 deletions(-) delete mode 100644 .project/concepts/tech-stack/_debt.md rename scripts/{link-polyfill.ts => overlay-local-checkout.ts} (94%) diff --git a/.env.example b/.env.example index 8c6debf..0191217 100644 --- a/.env.example +++ b/.env.example @@ -45,6 +45,6 @@ NODE_ENV= # ── Outillage dev (facultatif) ───────────────────────────────────────────── # Override du chemin local du polyfill @ng-eventually/sdk pour `pnpm run -# link:polyfill` (lien local réactif). Défaut = ../nextgraph/ng-eventually-js/packages/sdk. +# overlay:polyfill` (overlay local réactif). Défaut = ../nextgraph/ng-eventually-js/packages/sdk. NG_EVENTUALLY_LOCAL= diff --git a/.project/concepts/tech-stack/_debt.md b/.project/concepts/tech-stack/_debt.md deleted file mode 100644 index 654bbb7..0000000 --- a/.project/concepts/tech-stack/_debt.md +++ /dev/null @@ -1,8 +0,0 @@ -# Doc-debt — tech-stack - -> Presence of a block = doc to update. Processed → delete the block; no blocks left → delete this file. -> One block = one "big change": `why` + `files` + `verify` (leaves to review). - -## Raw markers (consolidate into blocks, then delete) -- TOUCHED package.json @2026-08-17 (session 0b064e8b-1717-421f-a20e-a4318ad217b1) -- TOUCHED scripts/link-polyfill.ts @2026-08-17 (session 0b064e8b-1717-421f-a20e-a4318ad217b1) diff --git a/.project/concepts/tech-stack/caveat_polyfill-overlay-needs-a-dev-restart.md b/.project/concepts/tech-stack/caveat_polyfill-overlay-needs-a-dev-restart.md index 36fba0b..01ef259 100644 --- a/.project/concepts/tech-stack/caveat_polyfill-overlay-needs-a-dev-restart.md +++ b/.project/concepts/tech-stack/caveat_polyfill-overlay-needs-a-dev-restart.md @@ -6,7 +6,7 @@ last_checked: 2026-08-16 # Pitfall: refreshing the data-layer package never reaches a running dev server, not even across a rebuild -`pnpm run link:polyfill` overlays the local package into `node_modules/@ng-eventually/polyfill/` as real files, and keeps them current. **That is all it does.** A `bun run dev` already running goes on serving the package it loaded at startup, however many times the overlay is rewritten underneath it, and however many rebuilds happen in between. +`pnpm run overlay:polyfill` (or `overlay:indexing`, for the other provider) overlays the local checkout into `node_modules//` as real files, and keeps them current. **That is all it does.** A `bun run dev` already running goes on serving the package it loaded at startup, however many times the overlay is rewritten underneath it, and however many rebuilds happen in between. **VERIFIED, controlled sandbox test with this project's own bun.** A dependency resolving to copy A, overlaid with copy B: the running server still serves A at +3 s and +13 s after the overlay. An edit to **application source** then triggers a genuine rebuild — a new bundle hash confirms it — and the rebuilt bundle **still serves A**. Only a restart serves B. So the mechanism is not "the watcher never fires because `node_modules` is excluded" — a rebuild the watcher DOES trigger still carries the stale dependency forward; the server's resolution of that import is pinned at process start, and a rebuild does not re-resolve it. @@ -18,7 +18,7 @@ VERIFIED 2026-08-16, and it cost about an hour. A defect had been fixed on the p The dev server had been running for **six days**. It predated the package rename and the whole migration, and it was serving code from before the fix. The browser was running a different application from the one under test. -Two things made it hard to see. The failure mode is **silence** — nothing warns that the served code is old. And `scripts/link-polyfill.ts` explicitly promised the opposite, that `bun --hot` would reload the copied file live; that claim is now corrected in the script, but a reader who trusted it would rule out the true cause first, which is exactly what happened. +Two things made it hard to see. The failure mode is **silence** — nothing warns that the served code is old. And `scripts/overlay-local-checkout.ts` explicitly promised the opposite, that `bun --hot` would reload the copied file live; that claim is now corrected in the script, but a reader who trusted it would rule out the true cause first, which is exactly what happened. ## The reflex to build diff --git a/.project/concepts/tech-stack/knowledge_deployment.md b/.project/concepts/tech-stack/knowledge_deployment.md index 4cc1b2f..2750bc4 100644 --- a/.project/concepts/tech-stack/knowledge_deployment.md +++ b/.project/concepts/tech-stack/knowledge_deployment.md @@ -58,4 +58,4 @@ A `Dockerfile` exists (multi-stage Bun Alpine). **Installation goes through pnpm `bun run dev` = **`portless festipod bun --hot src/index.ts`** — it goes through the **`portless`** wrapper (an external port-management tool), not a bare `bun --hot`. HMR is active outside production. -**Reactive local link to the SDK**: in production the `@ng-eventually/polyfill` dependency comes from Gitea (git+https, pinned by `pnpm-lock.yaml`). When the provider's package has to be exercised from a local checkout, `pnpm run link:polyfill` (script `scripts/link-polyfill.ts`) replaces `node_modules/@ng-eventually/polyfill` with a **real copy** of that checkout (location overridable with `NG_EVENTUALLY_LOCAL`) — **without** its own `node_modules/@ng-org` — and resyncs on every edit. Copying rather than symlinking is what keeps **a single `@ng-org/*` instance** installed: a symlink would drag in a second one and the SDK would stop working. To go back to the committed state: `pnpm install`. +**Reactive local overlay for the SDK**: in production the `@ng-eventually/polyfill` dependency comes from Gitea (git+https, pinned by `pnpm-lock.yaml`), and `@ng-helpers/indexing` likewise. When a provider's package has to be exercised from a local checkout, `pnpm run overlay:polyfill` or `pnpm run overlay:indexing` (script `scripts/overlay-local-checkout.ts`, one provider per run) replaces `node_modules/` with a **real copy** of that checkout (location overridable with `NG_EVENTUALLY_LOCAL` / `NG_HELPERS_LOCAL`) — **without** its own `node_modules/*` — and resyncs on every edit. Copying rather than symlinking is what keeps a **single instance** of every package the provider shares with Festipod installed (`@ng-org/*`, and for `indexing`, `@ng-eventually/polyfill` itself): a symlink would drag in a second one and the SDK would stop working. To go back to the committed state: `pnpm install`. diff --git a/.project/concepts/tech-stack/knowledge_stack-and-commands.md b/.project/concepts/tech-stack/knowledge_stack-and-commands.md index b104621..59b269e 100644 --- a/.project/concepts/tech-stack/knowledge_stack-and-commands.md +++ b/.project/concepts/tech-stack/knowledge_stack-and-commands.md @@ -1,6 +1,6 @@ --- type: knowledge -summary: Stack components (Bun runtime/build/test, install through pnpm, React, NextGraph, Storybook, Cucumber, Tailwind-inside-the-build) and the real list of package.json scripts, quirks included (cucumber through node+tsx, link:polyfill for the reactive local link) +summary: Stack components (Bun runtime/build/test, install through pnpm, React, NextGraph, Storybook, Cucumber, Tailwind-inside-the-build) and the real list of package.json scripts, quirks included (cucumber through node+tsx, overlay:polyfill/overlay:indexing for the reactive local overlay) --- # Stack & commands @@ -33,7 +33,7 @@ summary: Stack components (Bun runtime/build/test, install through pnpm, React, | `steps:extract` | `bun scripts/extract-step-definitions.ts` | | `build:orm` | `rdf-orm build --input ./src/shared/shapes/shex --output ./src/shared/shapes/orm` | | `build:ng` | `bash scripts/build-ng-packages.sh` — (re)builds the NextGraph packages from a local source (optional tool) | -| `link:polyfill` | `bun scripts/link-polyfill.ts` — **reactive** local link to `@ng-eventually/polyfill` (copy-overlay + watcher). Details in [[knowledge_deployment]]. | +| `overlay:polyfill` / `overlay:indexing` | `bun scripts/overlay-local-checkout.ts ` — **reactive** local overlay of a provider's checkout (`@ng-eventually/polyfill` or `@ng-helpers/indexing`; copy-overlay + watcher, `--once` for a single pass). Details in [[knowledge_deployment]]. | | `storybook` / `build-storybook` | Storybook dev (6006) / static build | ## Pitfalls diff --git a/.project/concepts/tech-stack/rule_bun-first.md b/.project/concepts/tech-stack/rule_bun-first.md index 7e3a768..9f8f74f 100644 --- a/.project/concepts/tech-stack/rule_bun-first.md +++ b/.project/concepts/tech-stack/rule_bun-first.md @@ -30,7 +30,7 @@ API details: [[knowledge_bun-apis]]. **Dependencies are installed with `pnpm install`, not `bun install`.** Everything else stays on Bun: **runtime, build, test, scripts** (`bun run dev`, `bun build`, `bun test`, `bunx`). Only the installation step changes package manager. -**Why.** The data SDK is installed from a Gitea repository as a **subdirectory** git dependency: `git+https://…/ng-eventually.git#main&path:/packages/polyfill`. pnpm (≥ 10.26) resolves that `#&path:/…` format and guarantees a **single** instance of `@ng-org/*`; `bun install` does not handle this workflow cleanly. The reference lockfile is therefore `pnpm-lock.yaml`, and the reactive local link goes through `pnpm run link:polyfill` (see [[knowledge_deployment]]). +**Why.** The data SDK is installed from a Gitea repository as a **subdirectory** git dependency: `git+https://…/ng-eventually.git#main&path:/packages/polyfill`. pnpm (≥ 10.26) resolves that `#&path:/…` format and guarantees a **single** instance of `@ng-org/*`; `bun install` does not handle this workflow cleanly. The reference lockfile is therefore `pnpm-lock.yaml`, and the reactive local overlay goes through `pnpm run overlay:polyfill` (`overlay:indexing` for the other provider; see [[knowledge_deployment]]). **Practical consequence.** npm scripts that relied on `node_modules/.bin/*` may break (pnpm puts shell shims there, not JS entries) — call the package's actual JS entry (e.g. `node_modules/@cucumber/cucumber/bin/cucumber.js`) rather than the `.bin/` shim. diff --git a/package.json b/package.json index 4f14fbc..74efa09 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,8 @@ "build:orm": "rdf-orm build --input ./src/shared/shapes/shex --output ./src/shared/shapes/orm", "validate": "bun scripts/validate.ts", "build:ng": "bash scripts/build-ng-packages.sh", - "link:polyfill": "bun scripts/link-polyfill.ts polyfill", - "link:indexing": "bun scripts/link-polyfill.ts indexing", + "overlay:polyfill": "bun scripts/overlay-local-checkout.ts polyfill", + "overlay:indexing": "bun scripts/overlay-local-checkout.ts indexing", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build" }, diff --git a/scripts/link-polyfill.ts b/scripts/overlay-local-checkout.ts similarity index 94% rename from scripts/link-polyfill.ts rename to scripts/overlay-local-checkout.ts index 9230f74..ae279ad 100644 --- a/scripts/link-polyfill.ts +++ b/scripts/overlay-local-checkout.ts @@ -1,7 +1,7 @@ #!/usr/bin/env bun /** - * link-polyfill.ts — Reactive local overlay of a data-layer PROVIDER's checkout into - * node_modules. One script, one provider per run; only the paths differ between them. + * overlay-local-checkout.ts — Reactive local overlay of a data-layer PROVIDER's checkout + * into node_modules. One script, one provider per run; only the paths differ between them. * * PROVIDERS (first non-flag argument; defaults to `polyfill`): * polyfill → node_modules/@ng-eventually/polyfill override: NG_EVENTUALLY_LOCAL @@ -36,11 +36,11 @@ * an hour to learn. Watching copies the files; it does not make anything reload them. * * USAGE (reactive dev): - * Terminal 1: pnpm run link:polyfill # or: pnpm run link:indexing + * Terminal 1: pnpm run overlay:polyfill # or: pnpm run overlay:indexing * Terminal 2: bun run dev # portless festipod bun --hot src/index.ts * Edit the checkout's src → it lands in node_modules → RESTART dev to pick it up. * - * pnpm run link:indexing --once # overlay + verify, no watch (CI / one-shot) + * pnpm run overlay:indexing --once # overlay + verify, no watch (CI / one-shot) * Return to the committed git-installed dependencies: pnpm install */ import { existsSync, lstatSync, mkdirSync, rmSync, cpSync, copyFileSync, realpathSync } from "node:fs"; @@ -83,7 +83,7 @@ const ONCE = args.includes("--once"); const KEY = args.find((a) => !a.startsWith("-")) ?? "polyfill"; function fail(msg: string): never { - console.error(`✖ link:${KEY} — ${msg}`); + console.error(`✖ overlay:${KEY} — ${msg}`); process.exit(1); }