Skip to content

Commit 3b84dd6

Browse files
committed
fix(core): resolve the register-contract guard in file-mapped alias configs (#7378 patch round)
Two halves, both measured before choosing: - packages/core/metadata-service-contract.ts: the '@objectstack/spec/api' import becomes TYPE-ONLY (erased at compile time) with the refusal code as a typed literal against the closed set — the storage-service.ts precedent. The module every consumer loads now makes one runtime subpath demand instead of two. '/shared' cannot be erased: pluralToSingular is a runtime value with ONE owner (copying the map would be the folk normalization the #7378 row-2 ruling forbids). - Five vitest configs alias the bare '@objectstack/spec' to spec/src/index.ts (a FILE, prefix-matched) with per-subpath entries and no '/shared' entry, so the guard's import resolved to spec/src/index.ts/shared - ENOTDIR at load: driver-memory (23 test files dead) and plugin-hono-server (16 dead) in CI, knowledge-ragflow / plugin-dev / knowledge-memory latently. Each gains the '/shared' entry in its config's own established pattern. check:test-source-alias was green throughout - its reachability walk stops at the package boundary, one hop short of the aliased dependency's own import surface; filed as #8351. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RDTnVvsgA6cUZ4xFVtPZRy
1 parent f66ce20 commit 3b84dd6

6 files changed

Lines changed: 54 additions & 2 deletions

File tree

‎packages/core/src/metadata-service-contract.ts‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,26 @@
7878
* `packages/objectql/src/metadata-service-roundtrip-conformance.test.ts`.
7979
*/
8080

81-
import { StandardErrorCode } from '@objectstack/spec/api';
81+
// The `/api` import is TYPE-ONLY on purpose — erased at compile time, so this
82+
// module makes no runtime demand on that subpath. This module is loaded by
83+
// every consumer of `@objectstack/core`, and several packages' vitest configs
84+
// alias the bare `@objectstack/spec` specifier to `spec/src/index.ts` (a FILE)
85+
// with per-subpath entries spelled out above it; an alias list matches by
86+
// PREFIX, so any subpath NOT spelled out resolves under the file and dies with
87+
// ENOTDIR at import time (measured: `@objectstack/plugin-hono-server` and
88+
// `@objectstack/driver-memory`, 39 test files dead at load between them). The
89+
// typed literal below keeps the closed-set compile check without the runtime
90+
// import — the `packages/spec/src/contracts/storage-service.ts` pattern.
91+
// `/shared` cannot get the same treatment: `pluralToSingular` is a runtime
92+
// value and its map has ONE owner (#7378 row 2 — copying it here would be the
93+
// per-implementation folk normalization the ruling forbids), so the consumer
94+
// configs carry a `/shared` alias entry instead.
95+
import type { StandardErrorCode } from '@objectstack/spec/api';
8296
import { pluralToSingular } from '@objectstack/spec/shared';
8397

98+
/** The standard catalog's generic argument-validation code, type-checked against the closed set. */
99+
const REGISTER_REFUSAL_CODE: StandardErrorCode = 'VALIDATION_ERROR';
100+
84101
/**
85102
* The canonical spelling an `IMetadataService` type store is keyed on
86103
* (#7378 row 2). Folds a plural manifest spelling to the singular metadata
@@ -102,7 +119,7 @@ export function canonicalMetadataServiceType(type: string): string {
102119
*/
103120
function registerRefusal(message: string): Error & { code: string; status: number } {
104121
const err = new Error(message) as Error & { code: string; status: number };
105-
err.code = StandardErrorCode.enum.VALIDATION_ERROR;
122+
err.code = REGISTER_REFUSAL_CODE;
106123
err.status = 400;
107124
return err;
108125
}

‎packages/drivers/driver-memory/vitest.config.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ export default defineConfig({
2020
'@objectstack/spec/system': path.resolve(__dirname, '../../spec/src/system/index.ts'),
2121
// [ADR-0105 D1] Reached transitively via `@objectstack/types` (tenancy posture).
2222
'@objectstack/spec/security': path.resolve(__dirname, '../../spec/src/security/index.ts'),
23+
// [#7378] Reached transitively: `@objectstack/core` (aliased to src above)
24+
// resolves the metadata register contract's plural→singular fold from this
25+
// subpath (`pluralToSingular`). An alias list matches by PREFIX, so without
26+
// this entry the bare `@objectstack/spec` alias below wins and yields the
27+
// nonsensical `spec/src/index.ts/shared` — ENOTDIR at import time for every
28+
// test file that transitively loads `@objectstack/core`.
29+
'@objectstack/spec/shared': path.resolve(__dirname, '../../spec/src/shared/index.ts'),
2330
'@objectstack/spec': path.resolve(__dirname, '../../spec/src/index.ts'),
2431
},
2532
},

‎packages/plugins/knowledge-memory/vitest.config.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ export default defineConfig({
1919
'@objectstack/spec/system': path.resolve(__dirname, '../../spec/src/system/index.ts'),
2020
// [ADR-0105 D1] Reached transitively via `@objectstack/types` (tenancy posture).
2121
'@objectstack/spec/security': path.resolve(__dirname, '../../spec/src/security/index.ts'),
22+
// [#7378] Reached transitively: `@objectstack/core` (aliased to src above)
23+
// resolves the metadata register contract's plural→singular fold from this
24+
// subpath (`pluralToSingular`). An alias list matches by PREFIX, so without
25+
// this entry the bare `@objectstack/spec` alias below wins and yields the
26+
// nonsensical `spec/src/index.ts/shared` — ENOTDIR at import time for every
27+
// test file that transitively loads `@objectstack/core`.
28+
'@objectstack/spec/shared': path.resolve(__dirname, '../../spec/src/shared/index.ts'),
2229
'@objectstack/spec': path.resolve(__dirname, '../../spec/src/index.ts'),
2330
},
2431
},

‎packages/plugins/knowledge-ragflow/vitest.config.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ export default defineConfig({
1919
'@objectstack/spec/system': path.resolve(__dirname, '../../spec/src/system/index.ts'),
2020
// [ADR-0105 D1] Reached transitively via `@objectstack/types` (tenancy posture).
2121
'@objectstack/spec/security': path.resolve(__dirname, '../../spec/src/security/index.ts'),
22+
// [#7378] Reached transitively: `@objectstack/core` (aliased to src above)
23+
// resolves the metadata register contract's plural→singular fold from this
24+
// subpath (`pluralToSingular`). An alias list matches by PREFIX, so without
25+
// this entry the bare `@objectstack/spec` alias below wins and yields the
26+
// nonsensical `spec/src/index.ts/shared` — ENOTDIR at import time for every
27+
// test file that transitively loads `@objectstack/core`.
28+
'@objectstack/spec/shared': path.resolve(__dirname, '../../spec/src/shared/index.ts'),
2229
'@objectstack/spec': path.resolve(__dirname, '../../spec/src/index.ts'),
2330
},
2431
},

‎packages/plugins/plugin-dev/vitest.config.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ export default defineConfig({
2424
'@objectstack/spec/system': path.resolve(__dirname, '../../spec/src/system/index.ts'),
2525
// [ADR-0105 D1] Reached transitively via `@objectstack/types` (tenancy posture).
2626
'@objectstack/spec/security': path.resolve(__dirname, '../../spec/src/security/index.ts'),
27+
// [#7378] Reached transitively: `@objectstack/core` (aliased to src above)
28+
// resolves the metadata register contract's plural→singular fold from this
29+
// subpath (`pluralToSingular`). An alias list matches by PREFIX, so without
30+
// this entry the bare `@objectstack/spec` alias below wins and yields the
31+
// nonsensical `spec/src/index.ts/shared` — ENOTDIR at import time for every
32+
// test file that transitively loads `@objectstack/core`.
33+
'@objectstack/spec/shared': path.resolve(__dirname, '../../spec/src/shared/index.ts'),
2734
'@objectstack/spec': path.resolve(__dirname, '../../spec/src/index.ts'),
2835
},
2936
},

‎packages/plugins/plugin-hono-server/vitest.config.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ export default defineConfig({
2222
// nonsensical `spec/src/index.ts/security`.
2323
'@objectstack/spec/security': path.resolve(__dirname, '../../spec/src/security/index.ts'),
2424
'@objectstack/spec/system': path.resolve(__dirname, '../../spec/src/system/index.ts'),
25+
// [#7378] Reached transitively: `@objectstack/core` (aliased to src above)
26+
// resolves the metadata register contract's plural→singular fold from this
27+
// subpath (`pluralToSingular`). An alias list matches by PREFIX, so without
28+
// this entry the bare `@objectstack/spec` alias below wins and yields the
29+
// nonsensical `spec/src/index.ts/shared` — ENOTDIR at import time for every
30+
// test file that transitively loads `@objectstack/core`.
31+
'@objectstack/spec/shared': path.resolve(__dirname, '../../spec/src/shared/index.ts'),
2532
'@objectstack/spec': path.resolve(__dirname, '../../spec/src/index.ts'),
2633
},
2734
},

0 commit comments

Comments
 (0)