feat(app-boot): register cordis:group beside cordis:include
A composition that shares one `isolate` realm across rows needs a `cordis:group` row, and a preset living outside this workspace — the authored ones under the Harness home — cannot resolve `@cordisjs/plugin-group` by name: Node's upward `node_modules` walk never reaches the harness from there. Registering it as a loader builtin beside `cordis:include` loads both through the ambient module pipeline instead. Record it in the preset Agent Note, which leans on the realm vocabulary without saying where the group row comes from, and drop the preset README's limitation claiming this builtin is unavailable — it described the state this change ends. The test's assertion had a vacuous escape: `provide` mints the root symbol unconditionally, so the `rootKey === undefined` disjunct could never hold and the comment claiming the root realm never learned the name was wrong. Pin both halves — the symbol exists, nothing is stored under it — and clean up the global the fixture writes.
This commit is contained in:
@@ -8,9 +8,8 @@ import { mkdtempSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { Context } from 'cordis'
|
||||
import { Context } from 'cordis'
|
||||
import type { Include } from '@cordisjs/plugin-include'
|
||||
import { Group } from '@cordisjs/plugin-loader'
|
||||
import { boot } from '../src/index.ts'
|
||||
|
||||
const NAME = 'dsh-test-bin'
|
||||
@@ -219,8 +218,10 @@ describe('loader tree replacement', () => {
|
||||
})
|
||||
|
||||
it('stops and restores descendants when an ancestor group is disabled and re-enabled', async () => {
|
||||
// No manual builtin registration: `boot()` supplies `cordis:group` beside
|
||||
// `cordis:include`, which is what lets a composition give one `isolate`
|
||||
// realm to a provider and its consumers together.
|
||||
const { ctx, dir, include } = await bootTree('- id: noop\n name: ./noop.mjs\n')
|
||||
ctx.loader.builtins.group = Group
|
||||
try {
|
||||
const config = (disabled: boolean) => [
|
||||
'- id: parent',
|
||||
@@ -253,7 +254,6 @@ describe('loader tree replacement', () => {
|
||||
const { ctx } = await bootTree('- id: noop\n name: ./noop.mjs\n', {
|
||||
'movable.mjs': plugin('movablePlugin', 'if (config.fail) throw new Error("candidate config failed")'),
|
||||
})
|
||||
ctx.loader.builtins.group = Group
|
||||
try {
|
||||
const groupId = await ctx.loader.create({ name: 'cordis:group', group: true, config: [] })
|
||||
const targetId = await ctx.loader.create({ name: './movable.mjs', config: { fail: false } })
|
||||
@@ -386,3 +386,46 @@ describe('include patches layered over one base', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('shipped builtins', () => {
|
||||
it('lets a booted composition share one isolate realm across a group of rows', async () => {
|
||||
// The reason `boot()` registers `cordis:group`: a composition — notably an
|
||||
// agent preset living outside this workspace, which cannot resolve
|
||||
// `@cordisjs/plugin-group` by name — gives a provider and its consumer one
|
||||
// named realm so the service stays out of the root realm while remaining
|
||||
// visible to the rows that need it.
|
||||
const { ctx } = await bootTree([
|
||||
'- id: realm',
|
||||
' name: cordis:group',
|
||||
' isolate:',
|
||||
' demoRealmSvc: true',
|
||||
' config:',
|
||||
' - id: provider',
|
||||
' name: ./provider.mjs',
|
||||
' - id: consumer',
|
||||
' name: ./consumer.mjs',
|
||||
'',
|
||||
].join('\n'), {
|
||||
'provider.mjs': 'export const name = "provider"\n'
|
||||
+ 'export function apply(ctx) { ctx.effect(() => ctx.reflect.provide("demoRealmSvc", { tag: "realm" })) }\n',
|
||||
'consumer.mjs': 'export const name = "consumer"\n'
|
||||
+ 'export const inject = ["demoRealmSvc"]\n'
|
||||
+ 'export function apply(ctx) { globalThis.__REALM_SEEN__ = ctx.get("demoRealmSvc").tag }\n',
|
||||
})
|
||||
try {
|
||||
expect((globalThis as { __REALM_SEEN__?: string }).__REALM_SEEN__).toBe('realm')
|
||||
// `provide` mints the root symbol unconditionally (cordis `reflect.ts`),
|
||||
// so the name IS in the root realm — pinned here because it is the half
|
||||
// that looks like the claim and is not. The claim is the other half: no
|
||||
// implementation is stored under that symbol, so the root realm cannot
|
||||
// resolve the service and a second composition mounting the same rows
|
||||
// cannot collide with this one.
|
||||
const rootKey = ctx.root[Context.isolate].demoRealmSvc
|
||||
expect(rootKey).toBeDefined()
|
||||
expect(ctx.reflect.store[rootKey!]).toBeUndefined()
|
||||
} finally {
|
||||
delete (globalThis as { __REALM_SEEN__?: string }).__REALM_SEEN__
|
||||
await ctx.fiber.dispose()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user