Ng eventually #1

Open
Sylvain wants to merge 110 commits from ng-eventually into main
8 changed files with 14 additions and 22 deletions
Showing only changes of commit c7cda38235 - Show all commits
+1 -1
View File
@@ -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=
-8
View File
@@ -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)
@@ -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/<package>/` 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
@@ -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/<package>` 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`.
@@ -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 <provider>`**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
@@ -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 `#<ref>&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 `#<ref>&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.
+2 -2
View File
@@ -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"
},
@@ -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);
}