refactor: renommer client → sdk, et fusionner les deux portes en une

Deux mouvements de surface, aucun changement de comportement.

**`packages/client` → `packages/sdk`, `@ng-eventually/client` → `@ng-eventually/sdk`.**
« client » ne disait rien : ce paquet EST le SDK que l'application appelle, et c'est
tout ce qu'elle appelle. L'ancien nom reste comme mot-clé de recherche dans
`docs/source-layout-by-fate.md` et le tableau des paquets du README.

**Une seule entrée.** L'entrée `./polyfill` disparaît ; ses symboles applicatifs —
`configure`, `configureStoreRegistry`, `setCurrentUser`, `connectedUser` et leurs types
— vivent dans un bloc `POLYFILL-ERA` de `src/index.ts`.

Ce que la seconde porte portait mérite d'être nommé avant d'être retiré : *ce qu'on
importe de ce chemin est exactement ce qu'on supprimera à la migration*. Une seule
porte perd ce signal — rien à la ligne d'import ne distingue `configure`, qui part, de
`docs`, que le vrai SDK remplace sur place. Trois choses le portent désormais : le bloc
lui-même, l'inventaire d'exports de `docs/api-contract.md` (épinglé par
`test/vocabulary.test.ts`, donc il ne peut pas rancir en silence), et le contrôle de
vocabulaire sur les noms publiés.

**Six symboles quittent la surface au passage**, et la fusion est ce qui a rendu le
choix visible plutôt qu'hérité :

- `getConfig` / `getStoreRegistryDeps` — câblage interne, atteint par
  `shared-wallet/bootstrap` ;
- `resetConfig` / `resetStoreRegistry` / `resetCaps` — remises à zéro de test, atteintes
  par leur chemin interne, ce qui est leur raison d'être ;
- le `share` direct — `inbox.share` a toujours été la même fonction, et la publier deux
  fois brouillait la frontière qu'elle servait à marquer.

Corrections d'affirmations fausses trouvées en chemin : le contrat annonçait `isNuri` /
`hasReadCap` sur la porte SDK alors qu'ils ne sont plus exportés depuis le passage au
permissif en entrée (`NuriLike` validé à la porte) ; le README du paquet documentait
`capFor`, `shareCap`, `getCaps` et `publishRepoLink`, dont aucun n'existe ; et le README
de l'app d'exemple affirmait que la suite e2e la pilote, ce qui reste à faire.

179 tests unitaires, typecheck bibliothèque / exemple / harnais, e2e 42/42 contre le
broker en ligne — mesuré une fois après le renommage, une fois après la fusion.
This commit is contained in:
Sylvain Duchesne
2026-08-07 11:05:19 +02:00
parent 0832338201
commit 0eb25286c8
85 changed files with 423 additions and 413 deletions
+4 -4
View File
@@ -1,12 +1,12 @@
# Notebook — the library's example application
A minimal application written against `@ng-eventually/client`, in plain DOM.
A minimal application written against `@ng-eventually/sdk`, in plain DOM.
It exists for two reasons, and the second is the one that matters.
**It shows how to use the library.** Every call in `app.ts` is what a real consumer writes. There is no test scaffolding, no privileged import, no reaching into the library's internals — it resolves `@ng-eventually/client` as an external consumer does. If something reads awkwardly here, it reads awkwardly for everyone.
**It shows how to use the library.** Every call in `app.ts` is what a real consumer writes. There is no test scaffolding, no privileged import, no reaching into the library's internals — it resolves `@ng-eventually/sdk` as an external consumer does. If something reads awkwardly here, it reads awkwardly for everyone.
**It is what the e2e suite drives.** The suite used to talk to a bag of methods on `window.__sdk`, which proved the functions ran but never that an application could be written with them. That gap shipped a real defect: a document's inbox was green in tests and unusable in practice, because the harness handed an address across an identity boundary through a variable — something no application can do. This app can only do what an application can do.
**It is what the e2e suite is meant to drive** — and does not yet, which this line says out loud rather than implying otherwise. The suite still talks to a bag of methods on `window.__sdk` (`packages/sdk/e2e/sdk-entry.ts`), which proves the functions run but never that an application can be written with them. That gap shipped a real defect once: a document's inbox was green in tests and unusable in practice, because the harness handed an address across an identity boundary through a variable — something no application can do. This app can only do what an application can do, which is why the applicative scenarios belong here.
It has already paid for itself twice: writing it surfaced that `UnionSubject` returned `string` where the values are always document references (so a consumer had to cast whatever it had just read before passing it back), and that the access gate normalized what a user typed but not what the URL carried.
@@ -16,4 +16,4 @@ Signing in, writing notes by scope, listing one's own, reading a note received a
## Running it
The e2e suite builds and serves it (`packages/client/e2e/`). To open it by hand you need a wallet: serve the folder with a bundled `app.js` and a `/shared-wallet.ngw`, and set `__NOTEBOOK_WALLET_PASSWORD__`.
The e2e suite builds and serves it (`packages/sdk/e2e/`). To open it by hand you need a wallet: serve the folder with a bundled `app.js` and a `/shared-wallet.ngw`, and set `__NOTEBOOK_WALLET_PASSWORD__`.
+7 -3
View File
@@ -1,5 +1,5 @@
/**
* Notebook — a minimal application written against `@ng-eventually/client`.
* Notebook — a minimal application written against `@ng-eventually/sdk`.
*
* It exists for two reasons, and the second is the one that matters:
*
@@ -28,6 +28,7 @@
*/
import {
// SDK-shaped — these survive migration, the real SDK replaces them in place.
docs,
ensureIdentity,
inbox,
@@ -36,8 +37,11 @@ import {
subscribeDoc,
type Nuri,
type Scope,
} from "@ng-eventually/client";
import { configure, configureStoreRegistry, setCurrentUser } from "@ng-eventually/client/polyfill";
// Polyfill-era — these three go away, and they are the whole of what goes away.
configure,
configureStoreRegistry,
setCurrentUser,
} from "@ng-eventually/sdk";
import { ng as realNg, init as realInit } from "@ng-org/web";
// --- the domain, such as it is ---------------------------------------------
+2 -2
View File
@@ -2,9 +2,9 @@
"name": "@ng-eventually/example-notebook",
"private": true,
"type": "module",
"description": "A minimal application written against @ng-eventually/client — the library's usage example, and what the e2e suite drives.",
"description": "A minimal application written against @ng-eventually/sdk \u2014 the library's usage example, and what the e2e suite drives.",
"dependencies": {
"@ng-eventually/client": "workspace:*",
"@ng-eventually/sdk": "workspace:*",
"@ng-org/web": "0.1.2-alpha.13"
}
}
+2 -5
View File
@@ -10,11 +10,8 @@
"DOM"
],
"paths": {
"@ng-eventually/client": [
"../../packages/client/src/index.ts"
],
"@ng-eventually/client/polyfill": [
"../../packages/client/src/polyfill.ts"
"@ng-eventually/sdk": [
"../../packages/sdk/src/index.ts"
],
"@ng-org/web": [
"../../node_modules/.bun/@ng-org+web@0.1.2-alpha.13/node_modules/@ng-org/web/dist/index.d.ts"