Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions packages/core/src/plugin-type-closed-set.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,21 @@
// The COMPILE-TIME half — a non-member literal or a `string`-typed value no
// longer type-checks against the PUBLISHED `Plugin.type` — lives in
// `packages/rest/src/plugin-type-closed-set.pin.test.ts`, deliberately NOT
// here: `@objectstack/core` has no `typecheck` script (type-check DEBT ledger
// entry), so a `@ts-expect-error` in this package is a phantom pin no tsc
// program a `typecheck` script runs would ever evaluate —
// `check:type-check-coverage` refuses exactly that. The rest package's
// `tsconfig.test.json` program is compiled by its `typecheck` script and reads
// core's BUILT `.d.ts`, so the pin over there guards the published contract.
// here. The rest package's `tsconfig.test.json` program is compiled by its
// `typecheck` script and resolves `@objectstack/core` to core's BUILT
// `dist/index.d.ts`, so the pin over there guards the contract consumers
// actually resolve.
//
// ⚠️ This used to read as though the split were forced — that
// `@objectstack/core` "has no `typecheck` script (type-check DEBT ledger
// entry)", making a `@ts-expect-error` here a phantom pin
// `check:type-check-coverage` refuses. False on this tree: #14613 split a
// `tsconfig.test.json` out of the build config, `package.json`'s `typecheck`
// NAMES it (via `check:test-typecheck --project`), and this package holds no
// DEBT entry. A directive here WOULD be evaluated — against `./types.ts`,
// this package's own SOURCE. The published `.d.ts` is what those pins are
// about and only the rest program reads it, which is a reason that outlives
// any package's script list.

import { describe, it, expect } from 'vitest';
import { CORE_PLUGIN_TYPES, PluginSchema } from '@objectstack/spec/kernel';
Expand Down
41 changes: 30 additions & 11 deletions packages/rest/src/plugin-type-closed-set.pin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,37 @@
// COMPILE-TIME pins for the closed `Plugin.type` set on the PUBLISHED surface
// of `@objectstack/core` (#13925): `type?: PluginType`, a union DERIVED from
// the spec's `CORE_PLUGIN_TYPES` (`'standard' | (typeof CORE_PLUGIN_TYPES)[number]`),
// replacing the `type?: string` that let any spelling through while the Zod
// gate (`PluginSchema.type`) refused it at parse.
// replacing the `type?: string` that let any spelling through.
//
// Why the pins live in THIS package: `@objectstack/core` has no `typecheck`
// script (it is a type-check DEBT ledger entry), so a `@ts-expect-error` there
// is a phantom pin — no tsc program a `typecheck` script runs ever evaluates
// it, and `check:type-check-coverage` refuses it. This package's
// `tsconfig.test.json` program IS run by its `typecheck` script
// (`check:test-typecheck`, EXACT per-file ratchet: an unlisted file must stay
// at zero errors), and it resolves `@objectstack/core` to the BUILT
// `dist/index.d.ts` — so these directives pin the contract consumers actually
// see. Same placement as `plugin-metadata-retired-fields.pin.test.ts`.
// ⚠️ This header used to end that sentence "while the Zod gate
// (`PluginSchema.type`) refused it at parse". Measured false (#16049, from
// #15638): `PluginSchema` had no runtime caller, kernel plugin objects were
// never parsed, and an off-set `type` was accepted and stored verbatim — the
// compiler was the only arm there was. Since #16049 the runtime arm is on the
// BOOT path: `PluginLoader.validatePluginContract` runs `PluginSchema` over
// every plugin object `kernel.use()` loads and raises
// `PLUGIN_CONTRACT_VIOLATION` naming the first violated key.
// `packages/core/src/types.ts` was corrected when that was measured; this
// header carried the same wording and was missed.
//
// Why the pins live in THIS package: this package's `tsconfig.test.json`
// program IS run by its `typecheck` script (`check:test-typecheck`, EXACT
// per-file ratchet: an unlisted file must stay at zero errors), and it
// resolves `@objectstack/core` to the BUILT `dist/index.d.ts` — so these
// directives pin the contract consumers actually see.
//
// ⚠️ NOT because core cannot compile a pin — this header used to say
// `@objectstack/core` "has no `typecheck` script (it is a type-check DEBT
// ledger entry)", and that is false on this tree. #14613 split a
// `tsconfig.test.json` out of core's build config and core's `typecheck`
// NAMES it (via `check:test-typecheck --project`), so a `@ts-expect-error`
// over there is compiled rather than the phantom pin
// `check:type-check-coverage` refuses, and core holds no DEBT entry. What
// core's program cannot do is read core's own PUBLISHED surface: it compiles
// `src`, so a pin there would read `./types.ts` — the declaration — not the
// `.d.ts` the build emits from it. That reason is durable where the
// script-list one was not. Same placement as
// `plugin-metadata-retired-fields.pin.test.ts`.
//
// Failure channel, proven able to fail by ablation on the narrowing PR:
// reverting `type?: PluginType` to `type?: string` (and rebuilding core's
Expand Down
Loading