Skip to content

Commit 1b25ced

Browse files
claude[bot]claude
andauthored
test(types): pin the host-only resolution defect on a name the workspace can never contain (#16723)
The host-only example was `@objectstack/organizations`, a real cloud-private package when the pin was written. Once that package became a workspace member, pnpm's hoisted store carried it and the framework-anchored resolve succeeded on any built tree — so the assertion held in CI only because the shard running it had not built that package. Build order, not the property it asserts. The example is now `@fixture/host-only`, a scope this workspace cannot contain, and the case proves its own premise instead of assuming it: it first resolves the name FROM THE HOST APP (without which a name existing nowhere would satisfy the assertion vacuously), then requires the framework-side failure to name the BARE SPECIFIER. A reachable-but-unbuilt package throws MODULE_NOT_FOUND naming its missing entry file instead, so that throw can no longer satisfy this pin in either build state. Claude-Session: https://claude.ai/code/session_015QE8qk46e5CHJxyQEUjbf8 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5e53d73 commit 1b25ced

1 file changed

Lines changed: 41 additions & 8 deletions

File tree

packages/types/src/node.test.ts

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,20 @@ import {
4141
readHostDeclaration,
4242
} from './node.js';
4343

44-
/** The cloud-private package at the heart of cloud#1013. */
45-
const ORGANIZATIONS = '@objectstack/organizations';
44+
/**
45+
* The HOST-ONLY package the defect case below uses as its example: a name this
46+
* file writes into the fixture host app and that exists nowhere else.
47+
*
48+
* ⚠️ It must stay a `@fixture/*` name (#16552). The pin below was written
49+
* against `@objectstack/organizations`, a real cloud-private package at the
50+
* time. #16215 brought that package into this workspace, pnpm's hoisted store
51+
* started carrying it, and the assertion turned into a function of whether the
52+
* runner had BUILT it — green on a shard that had not (which is every CI shard
53+
* that runs this file), red on any full local build. A name the workspace owns
54+
* cannot state "the framework cannot resolve it", and no workspace name is safe
55+
* from becoming one; only a name the workspace can never contain is.
56+
*/
57+
const HOST_ONLY = '@fixture/host-only';
4658
/** A package that fails while it EVALUATES — not while it resolves. */
4759
const BROKEN = '@fixture/throws-on-load';
4860
/**
@@ -99,7 +111,7 @@ beforeAll(() => {
99111
JSON.stringify({
100112
name: 'host-app-fixture',
101113
type: 'module',
102-
dependencies: { [ORGANIZATIONS]: '*' },
114+
dependencies: { [HOST_ONLY]: '*' },
103115
// #4719 fixture amendment: the evaluation-crash case below imports this
104116
// package, and an undeclared name is no longer looked up in the host's
105117
// node_modules at all — so the crash it exists to prove would be masked by
@@ -111,9 +123,12 @@ beforeAll(() => {
111123
}),
112124
'utf8',
113125
);
126+
// Modelled on the real enterprise plugin (cloud#1013): the SHAPE is what
127+
// `serve` / `bootStack` construct, and the callers' cases below assert it. The
128+
// package NAME is deliberately fixture-only, for the reason given at HOST_ONLY.
114129
writeFixturePackage(
115130
hostRoot,
116-
ORGANIZATIONS,
131+
HOST_ONLY,
117132
'export class OrganizationsPlugin { name = "com.objectstack.organizations"; }\n',
118133
);
119134
writeFixturePackage(hostRoot, BROKEN, 'throw new Error("fixture package exploded on import");\n');
@@ -163,14 +178,32 @@ describe('host-app package resolution (cloud#1013, #4700)', () => {
163178
// node -e "require.resolve('@objectstack/organizations')" -> MODULE_NOT_FOUND
164179
// A bare `import()` in serve.ts / harness.ts resolved from exactly here,
165180
// which is why declaring the dependency in the app changed nothing.
166-
expect(() => createHostRequire(PACKAGE_ROOT).resolve(ORGANIZATIONS)).toThrow(
167-
/Cannot find module/,
181+
//
182+
// PREMISE, proved here instead of assumed (#16552). The sentence this case
183+
// states needs an example that IS host-only, and the old one silently
184+
// stopped being one. Both legs below are load-bearing:
185+
//
186+
// 1. the name resolves from the HOST APP — without this, a name that
187+
// exists nowhere at all satisfies leg 2 and the case pins nothing;
188+
// 2. and from the framework package it is ABSENT — asserted on the bare
189+
// specifier, not on `/Cannot find module/` alone, because those are two
190+
// different verdicts. A package the framework CAN see, whose entry file
191+
// merely is not on disk, also throws MODULE_NOT_FOUND — naming
192+
// `<store>/<pkg>/dist/index.js`, not the specifier. That throw is what
193+
// held this pin green in CI while the property went unguarded: the
194+
// example package was reachable and simply unbuilt on that shard. Read
195+
// as a bare-specifier failure, the pin can no longer be satisfied by an
196+
// unbuilt workspace package, in either build state.
197+
const fromHost = createHostRequire(hostRoot).resolve(HOST_ONLY);
198+
expect(fromHost).toContain(hostRoot);
199+
expect(() => createHostRequire(PACKAGE_ROOT).resolve(HOST_ONLY)).toThrow(
200+
new RegExp(`Cannot find module '${HOST_ONLY}'`),
168201
);
169202
});
170203

171204
it('resolves a package that exists ONLY in the host app', async () => {
172205
const importFromHost = createHostImporter(hostRoot);
173-
const mod = await importFromHost(ORGANIZATIONS);
206+
const mod = await importFromHost(HOST_ONLY);
174207
// The export `serve` and `bootStack` construct: `new mod.OrganizationsPlugin()`.
175208
expect(typeof mod.OrganizationsPlugin).toBe('function');
176209
expect(new mod.OrganizationsPlugin().name).toBe('com.objectstack.organizations');
@@ -548,7 +581,7 @@ describe('the undeclared fallback resolves from the CALLER (#10943)', () => {
548581
// The fix moves one branch. The declared path must still resolve from the
549582
// host app, and an undeclared-but-NODE_PATH-reachable package must still be
550583
// refused: a caller base is not a way back into the hoisted store.
551-
const mod = await createHostImporter(hostRoot, { fallbackImport })(ORGANIZATIONS);
584+
const mod = await createHostImporter(hostRoot, { fallbackImport })(HOST_ONLY);
552585
expect(new mod.OrganizationsPlugin().name).toBe('com.objectstack.organizations');
553586
const err = await createHostImporter(undeclaringRoot, { fallbackImport })(
554587
HOISTED_ONLY,

0 commit comments

Comments
 (0)