docs: docChangeType rejoint la Surface du contrat concept, et le bloc est epingle

docChangeType est publie depuis index.ts mais absent du bloc ## Surface du contrat
concept (celui que tire la declaration usage_ d'un consommateur) - rien ne le liait
aux exports reels, contrairement au bloc "### Today" de docs/api-contract.md.

Ajoute la signature au bloc, et ajoute un test qui epingle desormais ce bloc contre
les exports reels de l'entree, sur le meme principe que le test existant pour
docs/api-contract.md : verifie a la fois (retire temporairement l'export de
docChangeType pour confirmer que le test tombe, puis restaure).
This commit is contained in:
Sylvain Duchesne
2026-09-24 21:10:54 +02:00
parent ae44e13859
commit 2d2f96f74b
2 changed files with 47 additions and 0 deletions
@@ -103,6 +103,9 @@ export async function getObjects<T extends BaseType>(
export type RdfOrmConfig<T> = Scope & { where?: ...; orderBy?: ... }; // the SDK's own export type RdfOrmConfig<T> = Scope & { where?: ...; orderBy?: ... }; // the SDK's own
export function subscribeDoc(nuri: NuriLike, onChange: (r: DocChange, t: DocChangeType) => void): Unsubscribe; export function subscribeDoc(nuri: NuriLike, onChange: (r: DocChange, t: DocChangeType) => void): Unsubscribe;
export function subscribeDocs(nuris: NuriLike[], onChange: (r: DocChange, t: DocChangeType) => void): Unsubscribe; export function subscribeDocs(nuris: NuriLike[], onChange: (r: DocChange, t: DocChangeType) => void): Unsubscribe;
// Extracts the variant key from a DocChange - "State" / "Patch" / "TabInfo" / ... -
// a convenience over the verified payload shape, not an upstream call.
export function docChangeType(resp: DocChange): DocChangeType;
// ── low-level document / SPARQL primitives ─────────────────────────────── // ── low-level document / SPARQL primitives ───────────────────────────────
export const docs: { export const docs: {
+44
View File
@@ -324,3 +324,47 @@ test("the api-contract appendix lists exactly what the entry exports", () => {
expect({ missing, extra }).toEqual({ missing: [], extra: [] }); expect({ missing, extra }).toEqual({ missing: [], extra: [] });
}); });
// --- the concept contract's Surface block must match the code -------------
/**
* `.project/concepts/app-contract/polyfill-surface/contract_polyfill-surface.md` is the
* doc a consumer's `usage_` leaf pulls against — separate from `docs/api-contract.md`
* above, and with no check of its own: `docChangeType` was published and missing from its
* `## Surface` block, and nothing here or elsewhere caught it (T01.p). Unlike the other
* doc's per-subject "### Today" blocks, this one is a SINGLE fenced block under one
* heading, so the check is simpler: every `export` it shows must actually be exported.
*/
test("every `export` shown in the concept contract's Surface block is actually exported", () => {
const md = fs.readFileSync(
path.join(
import.meta.dir,
"..",
"..",
"..",
".project",
"concepts",
"app-contract",
"polyfill-surface",
"contract_polyfill-surface.md",
),
"utf8",
);
const start = md.indexOf("\n## Surface");
const end = md.indexOf("\n## Guarantees", start);
const section = md.slice(start, end);
const published = new Set(publishedNames());
const stale: string[] = [];
for (const block of section.matchAll(/```ts\n([\s\S]*?)```/g)) {
for (const line of block[1]!.split("\n")) {
const decl = line.match(
/^export (?:declare )?(?:async )?(?:const|function|class|interface|type) (\w+)/,
);
const name = decl?.[1];
if (name && !published.has(name) && !isNamespaceMember(name)) stale.push(name);
}
}
// A failure is a question, not a rename: has the symbol been removed (then say so and
// rule on why), or has the entry lost something this contract still promises?
expect([...new Set(stale)]).toEqual([]);
});