@opetope/react 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +67 -50
- package/dist/act-delivery.d.ts +20 -0
- package/dist/command-hook.d.ts +8 -1
- package/dist/contribution-frame-DL0dyVP4.js +2 -0
- package/dist/contribution-frame-DL0dyVP4.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/scenario-mount.d.ts +2 -1
- package/dist/scenario-types.d.ts +4 -0
- package/dist/testing.js +3 -3
- package/dist/testing.js.map +1 -1
- package/package.json +5 -5
- package/dist/contribution-frame-D7_DN6Y2.js +0 -2
- package/dist/contribution-frame-D7_DN6Y2.js.map +0 -1
package/dist/testing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","sources":["../src/scenario-diagnostics.ts","../src/scenario-mount.ts","../src/scenario-slot.tsx","../src/scenario-wait.ts","../src/scenario.ts"],"sourcesContent":["import type { RuntimeActivitySnapshot, RuntimeGraphSnapshot } from '@opetope/runtime/internal';\n\nimport type { ScenarioOwnership } from './scenario-types';\n\nfunction instanceFacts(instance: RuntimeGraphSnapshot['runtime']['instances'][number]): readonly string[] {\n if (instance.state.kind === 'ready') return [];\n\n const waiting = instance.state.kind === 'waiting' ? ` (${instance.state.reason})` : '';\n\n return [`Feature ${instance.label}: ${instance.state.kind}${waiting}.`];\n}\n\nfunction callFact(call: RuntimeActivitySnapshot['calls'][number]): string {\n if (call.lane === null) return `Command ${call.declaration}: ${call.state}; lane parallel; blockers none (parallel).`;\n\n const blockers = call.lane.blockedBy === 'unknown' ? 'unknown' : call.lane.blockedBy.join(', ');\n\n return `Command ${call.declaration}: ${call.state}; lane ${call.lane.declaration}; blockers ${blockers}.`;\n}\n\nfunction activityFacts(activity: RuntimeActivitySnapshot | undefined): readonly string[] {\n if (activity === undefined) return ['Runtime activity: unknown.'];\n\n const facts: string[] = [];\n\n if (activity.freshness === 'stale' || activity.truncated) {\n facts.push(`Activity: ${activity.freshness}${activity.truncated ? ', truncated' : ''}; completeness unknown.`);\n }\n\n return [\n ...facts,\n ...activity.features.map(\n feature => `Feature ${feature.feature}: ${feature.phase}; body ${feature.body}; host demand unknown.`,\n ),\n ...activity.calls.map(callFact),\n ...activity.resources.map(\n resource => `Resource ${resource.id}: ${resource.state}; leases ${String(resource.leases)}.`,\n ),\n ];\n}\n\nfunction explainSnapshot(snapshot: RuntimeGraphSnapshot): string {\n const facts = [\n ...snapshot.runtime.conditions.flatMap(condition =>\n condition.state.kind === 'true' ? [] : [`Condition ${condition.label}: ${condition.state.kind}.`],\n ),\n ...snapshot.runtime.instances.flatMap(instanceFacts),\n ...activityFacts(snapshot.activity),\n ];\n\n return facts.length === 0\n ? 'No registered runtime blocker observed; external UI and host work are unknown.'\n : facts.join('\\n');\n}\n\n/* D206: the failure carries the producer's same data-only graph/activity facts, without product payloads. */\n/**\n * The failure carries the producer's same data-only graph/activity facts, without product payloads.\n */\nclass ScenarioTimeoutError extends Error {\n readonly code = 'timeout';\n\n constructor(\n readonly label: string,\n readonly timeoutMs: number,\n readonly snapshot: RuntimeGraphSnapshot,\n readonly history: readonly RuntimeGraphSnapshot[],\n ) {\n super(`Scenario timed out after ${String(timeoutMs)}ms: ${label}.\\n${explainSnapshot(snapshot)}`);\n this.name = 'ScenarioTimeoutError';\n }\n}\n\nfunction ownershipComplete(activity: RuntimeActivitySnapshot | undefined, successfullyClosed: boolean): boolean {\n if (!successfullyClosed || activity === undefined) return false;\n\n return activity.closed && !activity.truncated;\n}\n\nfunction ownershipReasons(\n activity: RuntimeActivitySnapshot | undefined,\n complete: boolean,\n successfullyClosed: boolean,\n): readonly string[] {\n if (activity === undefined) return ['Runtime activity is unavailable.'];\n\n const reasons: string[] = [];\n\n if (activity.truncated) reasons.push('The activity snapshot is truncated.');\n\n if (activity.freshness === 'stale' && !complete) reasons.push('The activity snapshot is stale.');\n\n if (!successfullyClosed) reasons.push('Successful application and mount cleanup has not been observed.');\n\n return Object.freeze(reasons);\n}\n\nfunction ownershipCounts(\n activity: RuntimeActivitySnapshot | undefined,\n complete: boolean,\n): Pick<ScenarioOwnership, 'calls' | 'features' | 'resources'> {\n if (activity === undefined || activity.truncated || (activity.freshness === 'stale' && !complete)) {\n return { calls: 'unknown', features: 'unknown', resources: 'unknown' };\n }\n\n return { calls: activity.calls.length, features: activity.features.length, resources: activity.resources.length };\n}\n\nfunction scenarioOwnership(snapshot: RuntimeGraphSnapshot, successfullyClosed: boolean): ScenarioOwnership {\n const activity = snapshot.activity;\n const complete = ownershipComplete(activity, successfullyClosed);\n\n return Object.freeze({\n ...ownershipCounts(activity, complete),\n closed: successfullyClosed,\n reasons: ownershipReasons(activity, complete, successfullyClosed),\n scope: 'registered-runtime',\n status: complete ? 'complete' : 'unknown',\n });\n}\n\nexport { scenarioOwnership, ScenarioTimeoutError };\n","import type { ScenarioHostMount } from './scenario-types';\n\n/** A reservation exists before the host callback, so reentrant close also owns a mount returned later. */\nclass ScenarioMountLease<Mounted extends ScenarioHostMount> {\n get closed(): boolean {\n return this.completion !== undefined;\n }\n private available = false;\n private completion: Promise<void> | undefined;\n private handle: Mounted | undefined;\n private reject: ((error: unknown) => void) | undefined;\n\n private resolve: (() => void) | undefined;\n\n constructor(private readonly released: (failed: boolean, error?: unknown) => void) {}\n\n readonly close = (): Promise<void> => {\n if (this.completion !== undefined) return this.completion;\n\n this.completion = new Promise<void>((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n\n if (this.available) this.releaseAvailable();\n\n return this.completion;\n };\n\n provide(handle: Mounted | undefined): void {\n this.available = true;\n this.handle = handle;\n\n if (this.closed) this.releaseAvailable();\n }\n\n private finish(failed: boolean, error?: unknown): void {\n const resolve = this.resolve;\n const reject = this.reject;\n this.resolve = undefined;\n this.reject = undefined;\n this.released(failed, error);\n\n if (!failed) resolve?.();\n else reject?.(error);\n }\n\n private releaseAvailable(): void {\n const handle = this.handle;\n this.handle = undefined;\n this.available = false;\n try {\n Promise.resolve(handle?.unmount()).then(\n () => this.finish(false),\n (error: unknown) => this.finish(true, error),\n );\n } catch (error) {\n this.finish(true, error);\n }\n }\n}\n\nexport { ScenarioMountLease };\n","import { createElement } from 'react';\nimport type { FC, ReactNode } from 'react';\n\nimport { declarationId } from '@opetope/core';\n\nimport { contributionAuthority, ContributionMount } from './contribution-frame';\nimport type { ContributionValue, ModelFixture } from './contribution-frame';\nimport { useReadable } from './readable-hooks';\nimport type { SlotComponentProperties, SlotContribution, SlotProperties, SlotTarget } from './slot';\n\n/*\n * Two forms, as `renderRoot` had (D19): without `contribution` the harness mounts what the target published, with it\n * the harness mounts one fixture contribution so a component test needs no generation.\n */\n/**\n * Two forms, as `renderRoot` had: without `contribution` the harness mounts what the target published.\n */\ntype SlotTestFixture<Props extends SlotProperties> = {\n readonly contribution?: SlotContribution<Props>;\n readonly models?: readonly ModelFixture[];\n readonly props?: SlotComponentProperties<Props>;\n /*\n * Where a contained mount failure is reported (D256). A component test has no feature to report to, so without it\n * the failure is detached and the assertion has nothing to read.\n */\n /**\n * Where a contained mount failure is reported.\n */\n readonly reporter?: (error: unknown) => void;\n};\n\ninterface SlotTestHarness<Props extends SlotProperties> {\n readonly Slot: FC;\n readonly updateProps: (props: SlotComponentProperties<Props>) => void;\n}\n\nconst testingContributionId = declarationId('testing.contribution');\n\n/**\n * Mounts the contributions of one slot the way a host does, with optional model fixtures for a component test. D19 and D85: the same\n * ContributionMount is shared by component tests and the application scenario harness (D206).\n */\nfunction createSlotHarness<Props extends SlotProperties>(\n target: SlotTarget<Props>,\n fixture: SlotTestFixture<Props> = {},\n): SlotTestHarness<Props> & { readonly close: () => void } {\n const fixtures = fixture.models ?? [];\n let current: object = fixture.props ?? {};\n const listeners = new Set<() => void>();\n const props = {\n getSnapshot: (): object => current,\n subscribe: (listener: () => void): (() => void) => {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n };\n\n const supplied = fixture.contribution;\n const reported = fixture.reporter;\n const fixtureAuthority = reported === undefined ? undefined : { models: [], reporter: reported };\n const Mounted: FC = (): ReactNode => {\n const published = useReadable(target.entries);\n const slotProps = useReadable(props);\n const entries =\n supplied === undefined\n ? published.map(\n entry =>\n [entry.id, entry.value as ContributionValue, contributionAuthority(entry) ?? fixtureAuthority] as const,\n )\n : [[testingContributionId, supplied as unknown as ContributionValue, fixtureAuthority] as const];\n\n return entries.map(([contributionId, contribution, authority]) =>\n createElement(ContributionMount, {\n authority,\n contribution,\n contributionId,\n fixtures,\n key: contributionId,\n slotProps,\n targetId: target.id,\n }),\n );\n };\n\n return Object.freeze({\n close: (): void => {\n current = {};\n listeners.clear();\n },\n Slot: Mounted,\n updateProps: (next: SlotComponentProperties<Props>): void => {\n current = next;\n\n for (const listener of [...listeners]) listener();\n },\n });\n}\n\n/**\n * Mounts one slot contribution under the React test harness.\n */\nfunction renderSlot<Props extends SlotProperties>(\n target: SlotTarget<Props>,\n fixture: SlotTestFixture<Props> = {},\n): SlotTestHarness<Props> {\n const harness = createSlotHarness(target, fixture);\n\n return Object.freeze({ Slot: harness.Slot, updateProps: harness.updateProps });\n}\n\nexport { createSlotHarness, renderSlot };\nexport type { SlotTestFixture, SlotTestHarness };\n","import type { RuntimeGraphSnapshot } from '@opetope/runtime/internal';\n\nimport { ScenarioTimeoutError } from './scenario-diagnostics';\nimport type { ScenarioWaitOptions } from './scenario-types';\n\nfunction positiveDuration(value: number, label: string): number {\n if (!Number.isFinite(value) || value <= 0 || value > 2_147_483_647) {\n throw new RangeError(`${label} must be a finite duration from 0 (exclusive) to 2147483647ms.`);\n }\n\n return value;\n}\n\ninterface ScenarioWaitSource {\n readonly getSnapshot: () => RuntimeGraphSnapshot;\n readonly history: () => readonly RuntimeGraphSnapshot[];\n readonly timeoutMs: number;\n}\n\ntype ScenarioWaitRead =\n | { readonly kind: 'source'; readonly read: () => unknown }\n | { readonly kind: 'graph'; readonly read: (snapshot: RuntimeGraphSnapshot) => unknown };\n\nclass ScenarioWaiters {\n private readonly listeners = new Set<() => void>();\n private readonly pending = new Set<(error: Error) => void>();\n\n constructor(private readonly source: ScenarioWaitSource) {}\n\n cancel(): void {\n for (const reject of [...this.pending]) reject(new Error('Scenario is closing.'));\n }\n\n deadline<Value>(result: PromiseLike<Value>, label: string, timeoutMs = this.source.timeoutMs): Promise<Value> {\n positiveDuration(timeoutMs, 'Scenario timeoutMs');\n\n return new Promise<Value>((resolve, reject) => {\n const timer = setTimeout(() => reject(this.timeout(label, timeoutMs)), timeoutMs);\n Promise.resolve(result).then(\n value => {\n clearTimeout(timer);\n resolve(value);\n },\n (error: unknown) => {\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n }\n\n readonly notify = (): void => {\n for (const listener of [...this.listeners]) listener();\n };\n\n waitFor(\n request: ScenarioWaitRead,\n accept: ((value: unknown) => boolean) | undefined,\n options: ScenarioWaitOptions,\n ): Promise<unknown> {\n const timeoutMs = positiveDuration(options.timeoutMs ?? this.source.timeoutMs, 'Scenario timeoutMs');\n const pollIntervalMs = positiveDuration(options.pollIntervalMs ?? 10, 'Scenario pollIntervalMs');\n const readValue = request.kind === 'source' ? request.read : () => request.read(this.source.getSnapshot());\n const synchronous = (value: unknown, half: 'reads' | 'decides'): unknown => {\n if (\n value !== null &&\n (typeof value === 'object' || typeof value === 'function') &&\n typeof Reflect.get(value, 'then') === 'function'\n ) {\n throw new TypeError(`Scenario.waitFor ${half} synchronously; put an awaited read inside eventually.`);\n }\n return value;\n };\n\n return new Promise<unknown>((resolve, reject) => {\n let done = false;\n let dispose = (): void => undefined;\n const finish = (value: unknown, failed = false): void => {\n if (done) return;\n done = true;\n dispose();\n if (failed) reject(value);\n else resolve(value);\n };\n const check = (): void => {\n if (done) return;\n try {\n const value = synchronous(readValue(), 'reads');\n const accepted =\n accept === undefined\n ? value !== false && value !== null && value !== undefined\n : synchronous(accept(value), 'decides');\n if (accepted) finish(value);\n } catch (error) {\n finish(error, true);\n }\n };\n const cancel = (error: Error): void => finish(error, true);\n const deadline = setTimeout(\n () =>\n finish(\n this.timeout(options.label ?? (request.kind === 'source' ? 'waitFor(source)' : 'waitFor'), timeoutMs),\n true,\n ),\n timeoutMs,\n );\n const poll = setInterval(check, pollIntervalMs);\n dispose = (): void => {\n clearTimeout(deadline);\n clearInterval(poll);\n this.listeners.delete(check);\n this.pending.delete(cancel);\n };\n this.listeners.add(check);\n this.pending.add(cancel);\n check();\n });\n }\n\n private timeout(label: string, timeoutMs: number): ScenarioTimeoutError {\n return new ScenarioTimeoutError(label, timeoutMs, this.source.getSnapshot(), this.source.history());\n }\n}\n\nexport { positiveDuration, ScenarioWaiters };\n","import type { Readable, ResourceView } from '@opetope/core';\nimport { createAggregateError, hasOwn, isResourceView } from '@opetope/core/internal';\nimport { openApplication } from '@opetope/runtime';\nimport type {\n Application,\n ApplicationConditionBinding,\n ApplicationExecution,\n ApplicationImportBinding,\n ErrorReporter,\n} from '@opetope/runtime';\nimport { createInspectionSession, testingTimeoutMs } from '@opetope/runtime/internal';\nimport type { OpenApplicationOptions, RuntimeGraphSnapshot, RuntimeInspectionSession } from '@opetope/runtime/internal';\n\nimport { scenarioOwnership } from './scenario-diagnostics';\nimport { ScenarioMountLease } from './scenario-mount';\nimport { createSlotHarness } from './scenario-slot';\nimport type {\n Scenario,\n ScenarioFeatures,\n ScenarioHost,\n ScenarioHostMount,\n ScenarioMount,\n ScenarioOptions,\n ScenarioReadWithoutAccept,\n ScenarioWaitOptions,\n} from './scenario-types';\nimport { positiveDuration, ScenarioWaiters } from './scenario-wait';\nimport type { SlotComponentProperties, SlotProperties, SlotTarget } from './slot';\n\nfunction boundedCapacity(value: number, label: string): number {\n if (!Number.isSafeInteger(value) || value < 1 || value > 10_000) {\n throw new RangeError(`${label} must be an integer from 1 to 10000.`);\n }\n\n return value;\n}\n\nfunction validateHost(host: unknown): void {\n if (host === null || typeof host !== 'object' || !('mount' in host) || typeof host.mount !== 'function') {\n throw new TypeError('Scenario requires a host.mount(Component) adapter.');\n }\n}\n\n/** A callable structural Readable still names a source, so its protocol wins over the callback form. */\nfunction isScenarioWaitSource(value: unknown): value is Readable<unknown> | ResourceView<unknown> {\n if (isResourceView(value)) return true;\n if ((typeof value !== 'object' || value === null) && typeof value !== 'function') return false;\n\n return 'getSnapshot' in value && typeof value.getSnapshot === 'function';\n}\n\n/**\n * What the scenario hands to `openApplication`: absence is preserved separately from an explicitly invalid value,\n * so the condition-dependent type and the D281 omissions behave exactly as they do for a host.\n */\nfunction applicationOpenOptions<const Features extends ScenarioFeatures>(\n options: ScenarioOptions<\n Features,\n ScenarioHostMount,\n readonly ApplicationConditionBinding[],\n readonly ApplicationImportBinding[],\n ErrorReporter | 'collect'\n >,\n reporter: ErrorReporter,\n): OpenApplicationOptions<Features> {\n return {\n ...(options.cleanupFailure === undefined ? {} : { cleanupFailure: options.cleanupFailure }),\n ...(hasOwn(options, 'conditions') ? { conditions: options.conditions } : {}),\n /*\n * D366: a scenario opens a real application, so the window of a lease is the host's word here too. D407: the\n * word is the key, as it already is for `conditions` and `imports` beside it — a `grace` written as `undefined`\n * travels to `openApplication` and is refused there, instead of being dropped here into the `0` of a host that\n * wrote no window at all.\n */\n ...(hasOwn(options, 'grace') ? { grace: options.grace! } : {}),\n ...(hasOwn(options, 'imports') ? { imports: options.imports } : {}),\n reporter,\n } as OpenApplicationOptions<Features>;\n}\n\n/** A collecting reporter retains the same array until after the scenario closes. */\nfunction scenarioReporter(choice: ErrorReporter | 'collect'): {\n readonly reporter: ErrorReporter;\n readonly reported?: unknown[];\n} {\n if (choice !== 'collect') return { reporter: choice };\n const reported: unknown[] = [];\n return { reported, reporter: error => void reported.push(error) };\n}\n\n/* D206: one real application, its existing inspection session and renderer-owned Slot ingress. */\n/**\n * One real application, its existing inspection session and renderer-owned Slot ingress.\n */\nfunction createScenario<\n const Features extends ScenarioFeatures,\n Mounted extends ScenarioHostMount,\n const Bindings extends readonly ApplicationConditionBinding[] = readonly [],\n const Imports extends readonly ApplicationImportBinding[] = readonly [],\n const Choice extends ErrorReporter | 'collect' = ErrorReporter,\n>(\n application: Application<Features>,\n options: ScenarioOptions<NoInfer<Features>, Mounted, Bindings, Imports, Choice>,\n): Scenario<Mounted, Choice> {\n const timeoutMs = options.timeoutMs;\n if (timeoutMs !== undefined) positiveDuration(timeoutMs, 'Scenario timeoutMs');\n const historyCapacity = boundedCapacity(options.historyCapacity ?? 64, 'Scenario historyCapacity');\n const activityCapacity = boundedCapacity(options.activityCapacity ?? 256, 'Scenario activityCapacity');\n let host: ScenarioHost<Mounted> | undefined = options.host;\n\n validateHost(host);\n\n const { reported, reporter } = scenarioReporter(options.reporter);\n let execution: ApplicationExecution | undefined = openApplication(\n application,\n applicationOpenOptions(options, reporter),\n );\n let session: RuntimeInspectionSession;\n try {\n session = createInspectionSession(execution, { activityCapacity, ringCapacity: historyCapacity });\n } catch (error) {\n void execution.ready.catch(() => undefined);\n void execution.close().catch(() => undefined);\n throw error;\n }\n\n let phase: 'closed' | 'closing' | 'open' = 'open';\n let successfullyClosed = false;\n let capturing = false;\n const records: RuntimeGraphSnapshot[] = [];\n const mounts = new Set<ScenarioMountLease<Mounted>>();\n const mountFailures: unknown[] = [];\n const getSnapshot = (): RuntimeGraphSnapshot => session.getSnapshot();\n const history = (): readonly RuntimeGraphSnapshot[] => Object.freeze([...records]);\n const waiters = new ScenarioWaiters({\n getSnapshot,\n history,\n get timeoutMs() {\n return timeoutMs ?? testingTimeoutMs();\n },\n });\n const capture = (): void => {\n if (capturing) return;\n\n capturing = true;\n try {\n const snapshot = getSnapshot();\n const previous = records[records.length - 1];\n\n if (previous?.stateRevision !== snapshot.stateRevision || previous.activity !== snapshot.activity) {\n records.push(snapshot);\n\n if (records.length > historyCapacity) records.shift();\n }\n } finally {\n capturing = false;\n }\n waiters.notify();\n };\n const release = session.subscribe(capture);\n capture();\n const ready = waiters.deadline(execution.ready, 'application ready');\n // A test may deliberately inspect loading without awaiting ready; rejection remains observable to that caller.\n void ready.catch(() => undefined);\n\n let physicalClose: Promise<void> | undefined;\n let closeAttempt: Promise<void> | undefined;\n const startClose = (): Promise<void> => {\n if (physicalClose !== undefined) return physicalClose;\n\n let resolve!: () => void;\n let reject!: (error: unknown) => void;\n physicalClose = new Promise<void>((accept, refuse) => {\n resolve = accept;\n reject = refuse;\n });\n phase = 'closing';\n waiters.cancel();\n const drains: Promise<void>[] = [];\n // Fence before any foreign unmount callback can reenter UI ingress; join all physical drains afterwards.\n try {\n drains.push(execution!.close());\n } catch (error) {\n drains.push(Promise.reject(error));\n }\n drains.push(...[...mounts].map(mount => mount.close()));\n void Promise.allSettled(drains).then(results => {\n const failures = [\n ...new Set([\n ...mountFailures,\n ...results.flatMap(result => (result.status === 'rejected' ? [result.reason as unknown] : [])),\n ]),\n ];\n mountFailures.length = 0;\n phase = 'closed';\n try {\n capture();\n } catch (error) {\n failures.push(error);\n } finally {\n release();\n session.close();\n mounts.clear();\n execution = undefined;\n host = undefined;\n }\n successfullyClosed = failures.length === 0;\n\n if (failures.length === 0) resolve();\n else reject(createAggregateError(failures, 'Scenario cleanup failed.'));\n });\n\n return physicalClose;\n };\n\n const close = (): Promise<void> => {\n if (closeAttempt !== undefined) return closeAttempt;\n\n const drain = startClose();\n\n // A nested close during unmount may have installed the same attempt already.\n if (closeAttempt !== undefined) return closeAttempt;\n\n closeAttempt = waiters.deadline(drain, 'scenario close');\n void closeAttempt.catch(() => {\n // A deadline cannot cancel physical work. A later close can await that same drain with a new deadline.\n if (phase === 'closing') closeAttempt = undefined;\n });\n\n return closeAttempt;\n };\n\n const mount: Scenario<Mounted>['mount'] = <Props extends SlotProperties>(\n target: SlotTarget<Props>,\n fixture: { readonly props?: SlotComponentProperties<Props> } = {},\n ): ScenarioMount<Props, Mounted> => {\n if (phase !== 'open') throw new Error('Scenario is closing.');\n\n const slot = createSlotHarness(target, fixture);\n const lease = new ScenarioMountLease<Mounted>((failed, error) => {\n mounts.delete(lease);\n slot.close();\n\n if (failed) mountFailures.push(error);\n });\n mounts.add(lease);\n let mounted: Mounted;\n try {\n mounted = host!.mount(slot.Slot);\n\n if (mounted === null || typeof mounted !== 'object' || typeof mounted.unmount !== 'function') {\n throw new TypeError('Scenario host.mount must return an unmount() handle.');\n }\n\n lease.provide(mounted);\n } catch (error) {\n lease.provide(undefined);\n void lease.close().catch(() => undefined);\n throw error;\n }\n\n return Object.freeze({\n host: mounted,\n unmount: lease.close,\n updateProps: (props: SlotComponentProperties<Props>): void => {\n if (phase !== 'open' || lease.closed) throw new Error('Scenario mount is closed.');\n\n slot.updateProps(props);\n waiters.notify();\n },\n });\n };\n\n function scenarioWaitFor<Value>(\n read: ScenarioReadWithoutAccept<Value>,\n options?: ScenarioWaitOptions,\n ): Promise<Exclude<Value, false | null | undefined>>;\n function scenarioWaitFor<Value, Narrowed extends Value>(\n source: Readable<Value> | ResourceView<Value>,\n accept: (value: Value) => value is Narrowed,\n options?: ScenarioWaitOptions,\n ): Promise<Narrowed>;\n function scenarioWaitFor<Value>(\n source: Readable<Value> | ResourceView<Value>,\n accept: (value: Value) => boolean,\n options?: ScenarioWaitOptions,\n ): Promise<Value>;\n function scenarioWaitFor<Value, Narrowed extends Value>(\n read: (snapshot: RuntimeGraphSnapshot) => Value,\n accept: (value: Value) => value is Narrowed,\n options?: ScenarioWaitOptions,\n ): Promise<Narrowed>;\n function scenarioWaitFor<Value>(\n read: (snapshot: RuntimeGraphSnapshot) => Value,\n accept: (value: Value) => boolean,\n options?: ScenarioWaitOptions,\n ): Promise<Value>;\n function scenarioWaitFor(\n read: ((snapshot: RuntimeGraphSnapshot) => unknown) | Readable<unknown> | ResourceView<unknown>,\n second?: ScenarioWaitOptions | ((value: unknown) => boolean),\n third?: ScenarioWaitOptions,\n ): Promise<unknown> {\n if (phase !== 'open') return Promise.reject(new Error('Scenario is closing.'));\n const accept = typeof second === 'function' ? second : undefined;\n const waitOptions = (accept === undefined ? second : third) ?? {};\n const request = isResourceView(read)\n ? { kind: 'source' as const, read: () => read.observe().getSnapshot() }\n : isScenarioWaitSource(read)\n ? { kind: 'source' as const, read: () => read.getSnapshot() }\n : { kind: 'graph' as const, read };\n return waiters.waitFor(request, accept, waitOptions as ScenarioWaitOptions);\n }\n\n const scenario = {\n close,\n getSnapshot,\n history,\n mount,\n notify: (): void => {\n if (phase === 'open') waiters.notify();\n },\n ownership: () => scenarioOwnership(getSnapshot(), successfullyClosed),\n ready,\n waitFor: scenarioWaitFor,\n };\n if (reported !== undefined) {\n Object.defineProperty(scenario, 'reported', { enumerable: true, get: () => Object.freeze([...reported]) });\n }\n return Object.freeze(scenario) as unknown as Scenario<Mounted, Choice>;\n}\n\nexport { createScenario };\n"],"names":["instanceFacts","instance","waiting","callFact","call","blockers","activityFacts","activity","facts","feature","resource","explainSnapshot","snapshot","condition","ScenarioTimeoutError","label","timeoutMs","history","ownershipComplete","successfullyClosed","ownershipReasons","complete","reasons","ownershipCounts","scenarioOwnership","ScenarioMountLease","released","resolve","reject","handle","failed","error","testingContributionId","declarationId","createSlotHarness","target","fixture","fixtures","current","listeners","props","listener","supplied","reported","fixtureAuthority","published","useReadable","slotProps","entry","contributionAuthority","contributionId","contribution","authority","createElement","ContributionMount","next","renderSlot","harness","positiveDuration","value","ScenarioWaiters","source","result","timer","request","accept","options","pollIntervalMs","readValue","synchronous","half","done","dispose","finish","check","cancel","deadline","poll","boundedCapacity","validateHost","host","isScenarioWaitSource","isResourceView","applicationOpenOptions","reporter","hasOwn","scenarioReporter","choice","createScenario","application","historyCapacity","activityCapacity","execution","openApplication","session","createInspectionSession","phase","capturing","records","mounts","mountFailures","getSnapshot","waiters","testingTimeoutMs","capture","previous","release","ready","physicalClose","closeAttempt","startClose","refuse","drains","mount","results","failures","createAggregateError","close","drain","slot","lease","mounted","scenarioWaitFor","read","second","third","waitOptions","scenario"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"testing.js","sources":["../src/scenario-diagnostics.ts","../src/scenario-mount.ts","../src/scenario-slot.tsx","../src/scenario-wait.ts","../src/scenario.ts"],"sourcesContent":["import type { RuntimeActivitySnapshot, RuntimeGraphSnapshot } from '@opetope/runtime/internal';\n\nimport type { ScenarioOwnership } from './scenario-types';\n\nfunction instanceFacts(instance: RuntimeGraphSnapshot['runtime']['instances'][number]): readonly string[] {\n if (instance.state.kind === 'ready') return [];\n\n const waiting = instance.state.kind === 'waiting' ? ` (${instance.state.reason})` : '';\n\n return [`Feature ${instance.label}: ${instance.state.kind}${waiting}.`];\n}\n\nfunction callFact(call: RuntimeActivitySnapshot['calls'][number]): string {\n if (call.lane === null) return `Command ${call.declaration}: ${call.state}; lane parallel; blockers none (parallel).`;\n\n const blockers = call.lane.blockedBy === 'unknown' ? 'unknown' : call.lane.blockedBy.join(', ');\n\n return `Command ${call.declaration}: ${call.state}; lane ${call.lane.declaration}; blockers ${blockers}.`;\n}\n\nfunction activityFacts(activity: RuntimeActivitySnapshot | undefined): readonly string[] {\n if (activity === undefined) return ['Runtime activity: unknown.'];\n\n const facts: string[] = [];\n\n if (activity.freshness === 'stale' || activity.truncated) {\n facts.push(`Activity: ${activity.freshness}${activity.truncated ? ', truncated' : ''}; completeness unknown.`);\n }\n\n return [\n ...facts,\n ...activity.features.map(\n feature => `Feature ${feature.feature}: ${feature.phase}; body ${feature.body}; host demand unknown.`,\n ),\n ...activity.calls.map(callFact),\n ...activity.resources.map(\n resource => `Resource ${resource.id}: ${resource.state}; leases ${String(resource.leases)}.`,\n ),\n ];\n}\n\nfunction explainSnapshot(snapshot: RuntimeGraphSnapshot): string {\n const facts = [\n ...snapshot.runtime.conditions.flatMap(condition =>\n condition.state.kind === 'true' ? [] : [`Condition ${condition.label}: ${condition.state.kind}.`],\n ),\n ...snapshot.runtime.instances.flatMap(instanceFacts),\n ...activityFacts(snapshot.activity),\n ];\n\n return facts.length === 0\n ? 'No registered runtime blocker observed; external UI and host work are unknown.'\n : facts.join('\\n');\n}\n\n/* D206: the failure carries the producer's same data-only graph/activity facts, without product payloads. */\n/**\n * The failure carries the producer's same data-only graph/activity facts, without product payloads.\n */\nclass ScenarioTimeoutError extends Error {\n readonly code = 'timeout';\n\n constructor(\n readonly label: string,\n readonly timeoutMs: number,\n readonly snapshot: RuntimeGraphSnapshot,\n readonly history: readonly RuntimeGraphSnapshot[],\n ) {\n super(`Scenario timed out after ${String(timeoutMs)}ms: ${label}.\\n${explainSnapshot(snapshot)}`);\n this.name = 'ScenarioTimeoutError';\n }\n}\n\nfunction ownershipComplete(activity: RuntimeActivitySnapshot | undefined, successfullyClosed: boolean): boolean {\n if (!successfullyClosed || activity === undefined) return false;\n\n return activity.closed && !activity.truncated;\n}\n\nfunction ownershipReasons(\n activity: RuntimeActivitySnapshot | undefined,\n complete: boolean,\n successfullyClosed: boolean,\n): readonly string[] {\n if (activity === undefined) return ['Runtime activity is unavailable.'];\n\n const reasons: string[] = [];\n\n if (activity.truncated) reasons.push('The activity snapshot is truncated.');\n\n if (activity.freshness === 'stale' && !complete) reasons.push('The activity snapshot is stale.');\n\n if (!successfullyClosed) reasons.push('Successful application and mount cleanup has not been observed.');\n\n return Object.freeze(reasons);\n}\n\nfunction ownershipCounts(\n activity: RuntimeActivitySnapshot | undefined,\n complete: boolean,\n): Pick<ScenarioOwnership, 'calls' | 'features' | 'resources'> {\n if (activity === undefined || activity.truncated || (activity.freshness === 'stale' && !complete)) {\n return { calls: 'unknown', features: 'unknown', resources: 'unknown' };\n }\n\n return { calls: activity.calls.length, features: activity.features.length, resources: activity.resources.length };\n}\n\nfunction scenarioOwnership(snapshot: RuntimeGraphSnapshot, successfullyClosed: boolean): ScenarioOwnership {\n const activity = snapshot.activity;\n const complete = ownershipComplete(activity, successfullyClosed);\n\n return Object.freeze({\n ...ownershipCounts(activity, complete),\n closed: successfullyClosed,\n reasons: ownershipReasons(activity, complete, successfullyClosed),\n scope: 'registered-runtime',\n status: complete ? 'complete' : 'unknown',\n });\n}\n\nexport { scenarioOwnership, ScenarioTimeoutError };\n","import { actNow } from './act-delivery';\nimport type { ScenarioHostMount } from './scenario-types';\n\n/** A reservation exists before the host callback, so reentrant close also owns a mount returned later. */\nclass ScenarioMountLease<Mounted extends ScenarioHostMount> {\n get closed(): boolean {\n return this.completion !== undefined;\n }\n private available = false;\n private completion: Promise<void> | undefined;\n private handle: Mounted | undefined;\n private reject: ((error: unknown) => void) | undefined;\n\n private resolve: (() => void) | undefined;\n\n constructor(\n private readonly released: (failed: boolean, error?: unknown) => void,\n private readonly act: ((callback: () => unknown) => PromiseLike<unknown>) | undefined,\n ) {}\n\n readonly close = (): Promise<void> => {\n if (this.completion !== undefined) return this.completion;\n\n this.completion = new Promise<void>((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n\n if (this.available) this.releaseAvailable();\n\n return this.completion;\n };\n\n provide(handle: Mounted | undefined): void {\n this.available = true;\n this.handle = handle;\n\n if (this.closed) this.releaseAvailable();\n }\n\n private finish(failed: boolean, error?: unknown): void {\n const resolve = this.resolve;\n const reject = this.reject;\n this.resolve = undefined;\n this.reject = undefined;\n this.released(failed, error);\n\n if (!failed) resolve?.();\n else reject?.(error);\n }\n\n private releaseAvailable(): void {\n const handle = this.handle;\n this.handle = undefined;\n this.available = false;\n try {\n const unmount = (): unknown => handle?.unmount();\n // D541: an unmount inside the renderer's act, so the cleanup it commits is flushed before `unmount` answers.\n Promise.resolve(this.act === undefined ? unmount() : actNow(this.act, unmount)).then(\n () => this.finish(false),\n (error: unknown) => this.finish(true, error),\n );\n } catch (error) {\n this.finish(true, error);\n }\n }\n}\n\nexport { ScenarioMountLease };\n","import { createElement } from 'react';\nimport type { FC, ReactNode } from 'react';\n\nimport { declarationId } from '@opetope/core';\n\nimport { contributionAuthority, ContributionMount } from './contribution-frame';\nimport type { ContributionValue, ModelFixture } from './contribution-frame';\nimport { useReadable } from './readable-hooks';\nimport type { SlotComponentProperties, SlotContribution, SlotProperties, SlotTarget } from './slot';\n\n/*\n * Two forms, as `renderRoot` had (D19): without `contribution` the harness mounts what the target published, with it\n * the harness mounts one fixture contribution so a component test needs no generation.\n */\n/**\n * Two forms, as `renderRoot` had: without `contribution` the harness mounts what the target published.\n */\ntype SlotTestFixture<Props extends SlotProperties> = {\n readonly contribution?: SlotContribution<Props>;\n readonly models?: readonly ModelFixture[];\n readonly props?: SlotComponentProperties<Props>;\n /*\n * Where a contained mount failure is reported (D256). A component test has no feature to report to, so without it\n * the failure is detached and the assertion has nothing to read.\n */\n /**\n * Where a contained mount failure is reported.\n */\n readonly reporter?: (error: unknown) => void;\n};\n\ninterface SlotTestHarness<Props extends SlotProperties> {\n readonly Slot: FC;\n readonly updateProps: (props: SlotComponentProperties<Props>) => void;\n}\n\nconst testingContributionId = declarationId('testing.contribution');\n\n/**\n * Mounts the contributions of one slot the way a host does, with optional model fixtures for a component test. D19 and D85: the same\n * ContributionMount is shared by component tests and the application scenario harness (D206).\n */\nfunction createSlotHarness<Props extends SlotProperties>(\n target: SlotTarget<Props>,\n fixture: SlotTestFixture<Props> = {},\n): SlotTestHarness<Props> & { readonly close: () => void } {\n const fixtures = fixture.models ?? [];\n let current: object = fixture.props ?? {};\n const listeners = new Set<() => void>();\n const props = {\n getSnapshot: (): object => current,\n subscribe: (listener: () => void): (() => void) => {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n };\n\n const supplied = fixture.contribution;\n const reported = fixture.reporter;\n const fixtureAuthority = reported === undefined ? undefined : { models: [], reporter: reported };\n const Mounted: FC = (): ReactNode => {\n const published = useReadable(target.entries);\n const slotProps = useReadable(props);\n const entries =\n supplied === undefined\n ? published.map(\n entry =>\n [entry.id, entry.value as ContributionValue, contributionAuthority(entry) ?? fixtureAuthority] as const,\n )\n : [[testingContributionId, supplied as unknown as ContributionValue, fixtureAuthority] as const];\n\n return entries.map(([contributionId, contribution, authority]) =>\n createElement(ContributionMount, {\n authority,\n contribution,\n contributionId,\n fixtures,\n key: contributionId,\n slotProps,\n targetId: target.id,\n }),\n );\n };\n\n return Object.freeze({\n close: (): void => {\n current = {};\n listeners.clear();\n },\n Slot: Mounted,\n updateProps: (next: SlotComponentProperties<Props>): void => {\n current = next;\n\n for (const listener of [...listeners]) listener();\n },\n });\n}\n\n/**\n * Mounts one slot contribution under the React test harness.\n */\nfunction renderSlot<Props extends SlotProperties>(\n target: SlotTarget<Props>,\n fixture: SlotTestFixture<Props> = {},\n): SlotTestHarness<Props> {\n const harness = createSlotHarness(target, fixture);\n\n return Object.freeze({ Slot: harness.Slot, updateProps: harness.updateProps });\n}\n\nexport { createSlotHarness, renderSlot };\nexport type { SlotTestFixture, SlotTestHarness };\n","import type { RuntimeGraphSnapshot } from '@opetope/runtime/internal';\n\nimport { ScenarioTimeoutError } from './scenario-diagnostics';\nimport type { ScenarioWaitOptions } from './scenario-types';\n\nfunction positiveDuration(value: number, label: string): number {\n if (!Number.isFinite(value) || value <= 0 || value > 2_147_483_647) {\n throw new RangeError(`${label} must be a finite duration from 0 (exclusive) to 2147483647ms.`);\n }\n\n return value;\n}\n\ninterface ScenarioWaitSource {\n readonly getSnapshot: () => RuntimeGraphSnapshot;\n readonly history: () => readonly RuntimeGraphSnapshot[];\n readonly timeoutMs: number;\n}\n\ntype ScenarioWaitRead =\n | { readonly kind: 'source'; readonly read: () => unknown }\n | { readonly kind: 'graph'; readonly read: (snapshot: RuntimeGraphSnapshot) => unknown };\n\nclass ScenarioWaiters {\n private readonly listeners = new Set<() => void>();\n private readonly pending = new Set<(error: Error) => void>();\n\n constructor(private readonly source: ScenarioWaitSource) {}\n\n cancel(): void {\n for (const reject of [...this.pending]) reject(new Error('Scenario is closing.'));\n }\n\n deadline<Value>(result: PromiseLike<Value>, label: string, timeoutMs = this.source.timeoutMs): Promise<Value> {\n positiveDuration(timeoutMs, 'Scenario timeoutMs');\n\n return new Promise<Value>((resolve, reject) => {\n const timer = setTimeout(() => reject(this.timeout(label, timeoutMs)), timeoutMs);\n Promise.resolve(result).then(\n value => {\n clearTimeout(timer);\n resolve(value);\n },\n (error: unknown) => {\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n }\n\n readonly notify = (): void => {\n for (const listener of [...this.listeners]) listener();\n };\n\n waitFor(\n request: ScenarioWaitRead,\n accept: ((value: unknown) => boolean) | undefined,\n options: ScenarioWaitOptions,\n ): Promise<unknown> {\n const timeoutMs = positiveDuration(options.timeoutMs ?? this.source.timeoutMs, 'Scenario timeoutMs');\n const pollIntervalMs = positiveDuration(options.pollIntervalMs ?? 10, 'Scenario pollIntervalMs');\n const readValue = request.kind === 'source' ? request.read : () => request.read(this.source.getSnapshot());\n const synchronous = (value: unknown, half: 'reads' | 'decides'): unknown => {\n if (\n value !== null &&\n (typeof value === 'object' || typeof value === 'function') &&\n typeof Reflect.get(value, 'then') === 'function'\n ) {\n throw new TypeError(`Scenario.waitFor ${half} synchronously; put an awaited read inside eventually.`);\n }\n return value;\n };\n\n return new Promise<unknown>((resolve, reject) => {\n let done = false;\n let dispose = (): void => undefined;\n const finish = (value: unknown, failed = false): void => {\n if (done) return;\n done = true;\n dispose();\n if (failed) reject(value);\n else resolve(value);\n };\n const check = (): void => {\n if (done) return;\n try {\n const value = synchronous(readValue(), 'reads');\n const accepted =\n accept === undefined\n ? value !== false && value !== null && value !== undefined\n : synchronous(accept(value), 'decides');\n if (accepted) finish(value);\n } catch (error) {\n finish(error, true);\n }\n };\n const cancel = (error: Error): void => finish(error, true);\n const deadline = setTimeout(\n () =>\n finish(\n this.timeout(options.label ?? (request.kind === 'source' ? 'waitFor(source)' : 'waitFor'), timeoutMs),\n true,\n ),\n timeoutMs,\n );\n const poll = setInterval(check, pollIntervalMs);\n dispose = (): void => {\n clearTimeout(deadline);\n clearInterval(poll);\n this.listeners.delete(check);\n this.pending.delete(cancel);\n };\n this.listeners.add(check);\n this.pending.add(cancel);\n check();\n });\n }\n\n private timeout(label: string, timeoutMs: number): ScenarioTimeoutError {\n return new ScenarioTimeoutError(label, timeoutMs, this.source.getSnapshot(), this.source.history());\n }\n}\n\nexport { positiveDuration, ScenarioWaiters };\n","import type { Readable, ResourceView } from '@opetope/core';\nimport { createAggregateError, hasOwn, isResourceView } from '@opetope/core/internal';\nimport { openApplication } from '@opetope/runtime';\nimport type {\n Application,\n ApplicationConditionBinding,\n ApplicationExecution,\n ApplicationImportBinding,\n ErrorReporter,\n} from '@opetope/runtime';\nimport { createInspectionSession, testingTimeoutMs } from '@opetope/runtime/internal';\nimport type { OpenApplicationOptions, RuntimeGraphSnapshot, RuntimeInspectionSession } from '@opetope/runtime/internal';\n\nimport { actNow, installAct } from './act-delivery';\nimport type { ActFunction } from './act-delivery';\nimport { scenarioOwnership } from './scenario-diagnostics';\nimport { ScenarioMountLease } from './scenario-mount';\nimport { createSlotHarness } from './scenario-slot';\nimport type {\n Scenario,\n ScenarioFeatures,\n ScenarioHost,\n ScenarioHostMount,\n ScenarioMount,\n ScenarioOptions,\n ScenarioReadWithoutAccept,\n ScenarioWaitOptions,\n} from './scenario-types';\nimport { positiveDuration, ScenarioWaiters } from './scenario-wait';\nimport type { SlotComponentProperties, SlotProperties, SlotTarget } from './slot';\n\nfunction boundedCapacity(value: number, label: string): number {\n if (!Number.isSafeInteger(value) || value < 1 || value > 10_000) {\n throw new RangeError(`${label} must be an integer from 1 to 10000.`);\n }\n\n return value;\n}\n\nfunction validateHost(host: unknown): void {\n if (host === null || typeof host !== 'object' || !('mount' in host) || typeof host.mount !== 'function') {\n throw new TypeError('Scenario requires a host.mount(Component) adapter.');\n }\n}\n\n/** A callable structural Readable still names a source, so its protocol wins over the callback form. */\nfunction isScenarioWaitSource(value: unknown): value is Readable<unknown> | ResourceView<unknown> {\n if (isResourceView(value)) return true;\n if ((typeof value !== 'object' || value === null) && typeof value !== 'function') return false;\n\n return 'getSnapshot' in value && typeof value.getSnapshot === 'function';\n}\n\n/**\n * What the scenario hands to `openApplication`: absence is preserved separately from an explicitly invalid value,\n * so the condition-dependent type and the D281 omissions behave exactly as they do for a host.\n */\nfunction applicationOpenOptions<const Features extends ScenarioFeatures>(\n options: ScenarioOptions<\n Features,\n ScenarioHostMount,\n readonly ApplicationConditionBinding[],\n readonly ApplicationImportBinding[],\n ErrorReporter | 'collect'\n >,\n reporter: ErrorReporter,\n): OpenApplicationOptions<Features> {\n return {\n ...(options.cleanupFailure === undefined ? {} : { cleanupFailure: options.cleanupFailure }),\n ...(hasOwn(options, 'conditions') ? { conditions: options.conditions } : {}),\n /*\n * D366: a scenario opens a real application, so the window of a lease is the host's word here too. D407: the\n * word is the key, as it already is for `conditions` and `imports` beside it — a `grace` written as `undefined`\n * travels to `openApplication` and is refused there, instead of being dropped here into the `0` of a host that\n * wrote no window at all.\n */\n ...(hasOwn(options, 'grace') ? { grace: options.grace! } : {}),\n ...(hasOwn(options, 'imports') ? { imports: options.imports } : {}),\n reporter,\n } as OpenApplicationOptions<Features>;\n}\n\nconst keepNothing = (): void => undefined;\n\n/** D407: a written `act` is the renderer's function; one written as anything else is refused, not dropped. */\nfunction readAct(options: { readonly act?: ActFunction }): ActFunction | undefined {\n if (hasOwn(options, 'act') && typeof options.act !== 'function') {\n throw new TypeError(\"Scenario act must be the renderer's act function; leave it out to render without one.\");\n }\n\n return options.act;\n}\n\n/** A collecting reporter retains the same array until after the scenario closes. */\nfunction scenarioReporter(choice: ErrorReporter | 'collect'): {\n readonly reporter: ErrorReporter;\n readonly reported?: unknown[];\n} {\n if (choice !== 'collect') return { reporter: choice };\n const reported: unknown[] = [];\n return { reported, reporter: error => void reported.push(error) };\n}\n\n/* D206: one real application, its existing inspection session and renderer-owned Slot ingress. */\n/**\n * One real application, its existing inspection session and renderer-owned Slot ingress.\n */\nfunction createScenario<\n const Features extends ScenarioFeatures,\n Mounted extends ScenarioHostMount,\n const Bindings extends readonly ApplicationConditionBinding[] = readonly [],\n const Imports extends readonly ApplicationImportBinding[] = readonly [],\n const Choice extends ErrorReporter | 'collect' = ErrorReporter,\n>(\n application: Application<Features>,\n options: ScenarioOptions<NoInfer<Features>, Mounted, Bindings, Imports, Choice>,\n): Scenario<Mounted, Choice> {\n const timeoutMs = options.timeoutMs;\n if (timeoutMs !== undefined) positiveDuration(timeoutMs, 'Scenario timeoutMs');\n const act = readAct(options);\n // D541: a step on the tree runs inside the renderer's act when the scenario was given one.\n const acted = <Value>(run: () => Value): Value => (act === undefined ? run() : actNow(act, run));\n // D541: installed while a tree of this scenario is mounted, so the deliveries it subscribes run inside `act`.\n const installMountAct = (): (() => void) => (act === undefined ? keepNothing : installAct(act));\n const historyCapacity = boundedCapacity(options.historyCapacity ?? 64, 'Scenario historyCapacity');\n const activityCapacity = boundedCapacity(options.activityCapacity ?? 256, 'Scenario activityCapacity');\n let host: ScenarioHost<Mounted> | undefined = options.host;\n\n validateHost(host);\n\n const { reported, reporter } = scenarioReporter(options.reporter);\n let execution: ApplicationExecution | undefined = openApplication(\n application,\n applicationOpenOptions(options, reporter),\n );\n let session: RuntimeInspectionSession;\n try {\n session = createInspectionSession(execution, { activityCapacity, ringCapacity: historyCapacity });\n } catch (error) {\n void execution.ready.catch(() => undefined);\n void execution.close().catch(() => undefined);\n throw error;\n }\n\n let phase: 'closed' | 'closing' | 'open' = 'open';\n let successfullyClosed = false;\n let capturing = false;\n const records: RuntimeGraphSnapshot[] = [];\n const mounts = new Set<ScenarioMountLease<Mounted>>();\n const mountFailures: unknown[] = [];\n const getSnapshot = (): RuntimeGraphSnapshot => session.getSnapshot();\n const history = (): readonly RuntimeGraphSnapshot[] => Object.freeze([...records]);\n const waiters = new ScenarioWaiters({\n getSnapshot,\n history,\n get timeoutMs() {\n return timeoutMs ?? testingTimeoutMs();\n },\n });\n const capture = (): void => {\n if (capturing) return;\n\n capturing = true;\n try {\n const snapshot = getSnapshot();\n const previous = records[records.length - 1];\n\n if (previous?.stateRevision !== snapshot.stateRevision || previous.activity !== snapshot.activity) {\n records.push(snapshot);\n\n if (records.length > historyCapacity) records.shift();\n }\n } finally {\n capturing = false;\n }\n waiters.notify();\n };\n const release = session.subscribe(capture);\n capture();\n const ready = waiters.deadline(execution.ready, 'application ready');\n // A test may deliberately inspect loading without awaiting ready; rejection remains observable to that caller.\n void ready.catch(() => undefined);\n\n let physicalClose: Promise<void> | undefined;\n let closeAttempt: Promise<void> | undefined;\n const startClose = (): Promise<void> => {\n if (physicalClose !== undefined) return physicalClose;\n\n let resolve!: () => void;\n let reject!: (error: unknown) => void;\n physicalClose = new Promise<void>((accept, refuse) => {\n resolve = accept;\n reject = refuse;\n });\n phase = 'closing';\n waiters.cancel();\n const drains: Promise<void>[] = [];\n // Fence before any foreign unmount callback can reenter UI ingress; join all physical drains afterwards.\n try {\n drains.push(execution!.close());\n } catch (error) {\n drains.push(Promise.reject(error));\n }\n drains.push(...[...mounts].map(mount => mount.close()));\n void Promise.allSettled(drains).then(results => {\n const failures = [\n ...new Set([\n ...mountFailures,\n ...results.flatMap(result => (result.status === 'rejected' ? [result.reason as unknown] : [])),\n ]),\n ];\n mountFailures.length = 0;\n phase = 'closed';\n try {\n capture();\n } catch (error) {\n failures.push(error);\n } finally {\n release();\n session.close();\n mounts.clear();\n execution = undefined;\n host = undefined;\n }\n successfullyClosed = failures.length === 0;\n\n if (failures.length === 0) resolve();\n else reject(createAggregateError(failures, 'Scenario cleanup failed.'));\n });\n\n return physicalClose;\n };\n\n const attemptClose = (): Promise<void> => {\n const drain = startClose();\n\n // A nested close during unmount may have installed the same attempt already.\n if (closeAttempt !== undefined) return closeAttempt;\n\n closeAttempt = waiters.deadline(drain, 'scenario close');\n void closeAttempt.catch(() => {\n // A deadline cannot cancel physical work. A later close can await that same drain with a new deadline.\n if (phase === 'closing') closeAttempt = undefined;\n });\n\n return closeAttempt;\n };\n // D541: the fence, the waits it cancels, the retirement it publishes to mounted components and their unmount share\n // one synchronous act scope; the drain that follows has no tree left to render.\n const close = (): Promise<void> => closeAttempt ?? acted(attemptClose);\n\n const mount: Scenario<Mounted>['mount'] = <Props extends SlotProperties>(\n target: SlotTarget<Props>,\n fixture: { readonly props?: SlotComponentProperties<Props> } = {},\n ): ScenarioMount<Props, Mounted> => {\n if (phase !== 'open') throw new Error('Scenario is closing.');\n\n const slot = createSlotHarness(target, fixture);\n const uninstallAct = installMountAct();\n const lease = new ScenarioMountLease<Mounted>((failed, error) => {\n mounts.delete(lease);\n slot.close();\n uninstallAct();\n\n if (failed) mountFailures.push(error);\n }, act);\n mounts.add(lease);\n let mounted: Mounted;\n try {\n mounted = acted(() => host!.mount(slot.Slot));\n\n if (mounted === null || typeof mounted !== 'object' || typeof mounted.unmount !== 'function') {\n throw new TypeError('Scenario host.mount must return an unmount() handle.');\n }\n\n lease.provide(mounted);\n } catch (error) {\n // D541: a host that failed mounts no tree, so its `act` is removed before the failure reaches the test.\n uninstallAct();\n lease.provide(undefined);\n void lease.close().catch(() => undefined);\n throw error;\n }\n\n return Object.freeze({\n host: mounted,\n unmount: lease.close,\n updateProps: (props: SlotComponentProperties<Props>): void => {\n if (phase !== 'open' || lease.closed) throw new Error('Scenario mount is closed.');\n\n acted(() => slot.updateProps(props));\n waiters.notify();\n },\n });\n };\n\n function scenarioWaitFor<Value>(\n read: ScenarioReadWithoutAccept<Value>,\n options?: ScenarioWaitOptions,\n ): Promise<Exclude<Value, false | null | undefined>>;\n function scenarioWaitFor<Value, Narrowed extends Value>(\n source: Readable<Value> | ResourceView<Value>,\n accept: (value: Value) => value is Narrowed,\n options?: ScenarioWaitOptions,\n ): Promise<Narrowed>;\n function scenarioWaitFor<Value>(\n source: Readable<Value> | ResourceView<Value>,\n accept: (value: Value) => boolean,\n options?: ScenarioWaitOptions,\n ): Promise<Value>;\n function scenarioWaitFor<Value, Narrowed extends Value>(\n read: (snapshot: RuntimeGraphSnapshot) => Value,\n accept: (value: Value) => value is Narrowed,\n options?: ScenarioWaitOptions,\n ): Promise<Narrowed>;\n function scenarioWaitFor<Value>(\n read: (snapshot: RuntimeGraphSnapshot) => Value,\n accept: (value: Value) => boolean,\n options?: ScenarioWaitOptions,\n ): Promise<Value>;\n function scenarioWaitFor(\n read: ((snapshot: RuntimeGraphSnapshot) => unknown) | Readable<unknown> | ResourceView<unknown>,\n second?: ScenarioWaitOptions | ((value: unknown) => boolean),\n third?: ScenarioWaitOptions,\n ): Promise<unknown> {\n if (phase !== 'open') return Promise.reject(new Error('Scenario is closing.'));\n const accept = typeof second === 'function' ? second : undefined;\n const waitOptions = (accept === undefined ? second : third) ?? {};\n const request = isResourceView(read)\n ? { kind: 'source' as const, read: () => read.observe().getSnapshot() }\n : isScenarioWaitSource(read)\n ? { kind: 'source' as const, read: () => read.getSnapshot() }\n : { kind: 'graph' as const, read };\n return waiters.waitFor(request, accept, waitOptions as ScenarioWaitOptions);\n }\n\n const scenario = {\n close,\n getSnapshot,\n history,\n mount,\n notify: (): void => {\n if (phase === 'open') waiters.notify();\n },\n ownership: () => scenarioOwnership(getSnapshot(), successfullyClosed),\n ready,\n waitFor: scenarioWaitFor,\n };\n if (reported !== undefined) {\n Object.defineProperty(scenario, 'reported', { enumerable: true, get: () => Object.freeze([...reported]) });\n }\n return Object.freeze(scenario) as unknown as Scenario<Mounted, Choice>;\n}\n\nexport { createScenario };\n"],"names":["instanceFacts","instance","waiting","callFact","call","blockers","activityFacts","activity","facts","feature","resource","explainSnapshot","snapshot","condition","ScenarioTimeoutError","label","timeoutMs","history","ownershipComplete","successfullyClosed","ownershipReasons","complete","reasons","ownershipCounts","scenarioOwnership","ScenarioMountLease","released","act","resolve","reject","handle","failed","error","unmount","actNow","testingContributionId","declarationId","createSlotHarness","target","fixture","fixtures","current","listeners","props","listener","supplied","reported","fixtureAuthority","published","useReadable","slotProps","entry","contributionAuthority","contributionId","contribution","authority","createElement","ContributionMount","next","renderSlot","harness","positiveDuration","value","ScenarioWaiters","source","result","timer","request","accept","options","pollIntervalMs","readValue","synchronous","half","done","dispose","finish","check","cancel","deadline","poll","boundedCapacity","validateHost","host","isScenarioWaitSource","isResourceView","applicationOpenOptions","reporter","hasOwn","keepNothing","readAct","scenarioReporter","choice","createScenario","application","acted","run","installMountAct","installAct","historyCapacity","activityCapacity","execution","openApplication","session","createInspectionSession","phase","capturing","records","mounts","mountFailures","getSnapshot","waiters","testingTimeoutMs","capture","previous","release","ready","physicalClose","closeAttempt","startClose","refuse","drains","mount","results","failures","createAggregateError","attemptClose","drain","close","slot","uninstallAct","lease","mounted","scenarioWaitFor","read","second","third","waitOptions","scenario"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opetope/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20.19.0"
|
|
6
6
|
},
|
|
@@ -49,16 +49,16 @@
|
|
|
49
49
|
}
|
|
50
50
|
],
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@opetope/core": "0.
|
|
53
|
-
"@opetope/runtime": "0.
|
|
52
|
+
"@opetope/core": "0.16.0",
|
|
53
|
+
"@opetope/runtime": "0.16.0",
|
|
54
54
|
"@testing-library/react": "16.3.3",
|
|
55
55
|
"@types/react": "19.2.18",
|
|
56
56
|
"react": "19.2.8",
|
|
57
57
|
"react-dom": "19.2.8"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"@opetope/core": "0.
|
|
61
|
-
"@opetope/runtime": "0.
|
|
60
|
+
"@opetope/core": "0.16.0",
|
|
61
|
+
"@opetope/runtime": "0.16.0",
|
|
62
62
|
"react": ">=19.0.0 <20"
|
|
63
63
|
},
|
|
64
64
|
"sideEffects": false,
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{jsx as h}from"react/jsx-runtime";import{useContext as D,createContext as P,useRef as M,useCallback as p,useSyncExternalStore as S,useLayoutEffect as f,useInsertionEffect as R,memo as W,useMemo as m,useState as N}from"react";import{createAggregateError as A,isResourceView as g,resourceViewDemands as U,isCallTarget as K,isModel as G,isReadable as O,createLifetimeController as H,createCallController as J,reportDetachedError as w,getContributionOwner as Q,setStateFromOwner as X,createState as Y,closeStateFromOwner as k}from"@opetope/core/internal";import{isResourceValue as Z,reportRuntimeFailure as _,requireContributionModelPlans as ee,openContributionModels as te}from"@opetope/runtime/internal";import{a as d,u as ne,b as se}from"./contribution-isolation-Ig70xFiC.js";const F=P(void 0);function ie(){const n=D(F);if(n===void 0)throw new d("missing","Opetope hook was called outside a contribution mount.");return n}function C(n){return Z(n)}function j(n){const e=n.pagination;if(!(typeof e!="object"||e===null))return e}function z(n){return{loadNext:e=>j(n).loadNext(e),refresh:()=>n.refresh(),reset:()=>n.reset(),retry:()=>n.retry()}}function re(n,e){const t=e.get(n);if(t!==void 0)return t;const s=z(n);return e.set(n,s),s}const v=new Set;function x(n,e=[]){for(const t of n){const s=t.dispose;t.dispose=void 0;try{s==null||s()}catch(i){e.push(i)}}if(e.length===1)throw e[0];if(e.length>1)throw A(e,"Model selection sources failed to release.")}class I{enabled=!1;leases=new Map;listeners=new Set;retained=v;sources=new Set;subscriptions=new Map;close(){this.enabled=!1,this.sources=new Set,this.retained=v,this.releaseAll()}commit(e,t=v){this.sources=e,this.retained=t,this.enabled=!0;try{this.synchronize()}catch(s){this.enabled=!1,this.releaseAll([s])}}subscribe=e=>{const t={notify:e};this.listeners.add(t);try{this.subscribeSources()}catch(s){this.listeners.delete(t),this.releaseAll([s])}return()=>{this.listeners.delete(t),this.listeners.size===0&&this.releaseAll()}};add(e){const t={dispose:void 0};this.subscriptions.set(e,t);const s=e.subscribe(this.notify);if(typeof s!="function")throw new TypeError("Model selection source must return a disposer.");this.subscriptions.get(e)===t?t.dispose=s:s()}notify=()=>{for(const e of[...this.listeners])this.listeners.has(e)&&e.notify()};releaseAll(e){const t=[...this.subscriptions.values(),...this.leases.values()];this.subscriptions.clear(),this.leases.clear(),x(t,e)}removeUnselected(){const e=[];for(const[t,s]of this.subscriptions)this.sources.has(t)||(this.subscriptions.delete(t),e.push(s));for(const[t,s]of this.leases)this.retained.has(t)||(this.leases.delete(t),e.push(s));x(e)}retain(e){const t={dispose:void 0};this.leases.set(e,t);const s=e.acquire();if(typeof s!="function")throw new TypeError("Model selection resource must answer a release disposer.");this.leases.get(e)===t?t.dispose=s:s()}ready(){return this.enabled&&this.listeners.size>0}retainSelected(){for(const e of this.retained){if(!this.enabled)return;this.retained.has(e)&&!this.leases.has(e)&&this.retain(e)}}subscribeSources(){for(const e of this.sources){if(!this.ready())return;this.sources.has(e)&&!this.subscriptions.has(e)&&this.add(e)}}synchronize(){this.removeUnselected(),this.subscribeSources(),this.retainSelected()}}class oe{store=new I;observations=new WeakMap;observe(e){let t=this.observations.get(e);return t===void 0&&(t=e.observe(),this.observations.set(e,t)),t}commit(e){const t=this.observations.get(e);t===void 0?this.store.close():this.store.commit(new Set([t]),new Set(U(e)))}}function ae(n){const e=M(void 0);let t=e.current;t===void 0&&(t={views:void 0},e.current=t);let s,i;if(g(n)){const a=t.views??(t.views=new oe);s=a.observe(n),i=a.store}else s=n,i=s;const r=p(a=>i.subscribe(a),[i]),c=p(()=>s.getSnapshot(),[s]),o=S(r,c,c);return f(()=>{var a;(a=t.views)==null||a.commit(n)},[t,n]),o}function E(n){return ae(n)}const y=new WeakMap;function ce(n){if(arguments.length>1)throw new d("binding-invalid","Command follows the target it binds; binding options are forbidden.");if(!K(n))throw new d("binding-invalid","Command target is not authentic.");return y.set(n,{target:n}),n}function de(n){const e=y.get(n);if(e===void 0)throw new d("binding-invalid","Command binding is not authentic.");return e}function $(n){return typeof n=="object"&&n!==null&&y.has(n)}const ue=Symbol("opetope.model-binding"),le=Symbol("opetope.model-binding-identity"),he=Object.freeze({}),B=new WeakMap;function fe(n,e,t){if(typeof t!="string")throw new d("binding-invalid",`Model ${n.id} accepts only string fields.`);const s=Object.getOwnPropertyDescriptor(e,t);if((s==null?void 0:s.enumerable)!==!0||!("value"in s))throw new d("binding-invalid",`Model ${n.id}.${t} requires an enumerable data binding.`);return s.value}function me(n){return O(n)||C(n)||g(n)||typeof n=="function"}function be(n,e){const t=[],s=Reflect.ownKeys(e);if(s.length===0)throw new d("binding-invalid",`Model ${n.id} requires at least one field.`);for(const i of s){const r=fe(n,e,i);if(!me(r)){if(!$(r))throw new d("binding-invalid",`Model ${n.id}.${String(i)} requires a Readable, a Resource, a ResourceView or a bound command.`);t.push(r)}}return Object.freeze(t)}function T(n,e){if(!G(n))throw new d("binding-invalid","Model declaration is not authentic.");if(typeof e!="object"||e===null)throw new d("binding-invalid",`Model ${n.id} requires a record binding.`);const t=be(n,e),s=Object.freeze({[ue]:he,[le]:!0});return B.set(s,{commands:t,declaration:n,model:e}),s}function pe(n){const e=B.get(n);if(e===void 0)throw new d("binding-invalid","Model binding is not authentic.");return e}let ge=0;function we(n){const e=new Map,t=[],s=new Set;for(const i of n){const r=pe(i);if(e.has(r.declaration))throw new d("duplicate",`Model ${r.declaration.id} is bound twice in one mount.`);e.set(r.declaration,r.model);for(const c of r.commands)s.has(c)||(s.add(c),t.push(c))}return{commands:Object.freeze(t),frame:{commandRecords:new Map,models:e}}}class Ce{frame;authority;boundCommands;closeTicket=0;isActive;lifetime;onClose;released=!1;rendererAttached=!1;renderListeners=new Set;state="detached";constructor(e,t){const s=++ge;this.lifetime=H({id:`contribution.${String(s)}`}),this.isActive=t==null?void 0:t.isActive,this.onClose=t==null?void 0:t.onClose;const{commands:i,frame:r}=we(e);this.frame=r,this.boundCommands=i,this.buildCommandRecords(s)}attach(){if(this.state==="closing")return this.closeTicket+=1,this.state="active",this.rendererAttached=!0,!0;if(this.state==="closed")return!1;if(this.state==="active")throw new d("duplicate","One contribution mount cannot mount twice.");const e=this.createAuthority(this.lifetime.open());try{for(const t of this.frame.commandRecords.values())t.controller.activate()}catch(t){throw this.authority=e,this.state="active",this.close(),t}return this.authority=e,this.rendererAttached=!0,this.state="active",!0}close(){if(this.state==="closed")return;this.state="closed",this.closeTicket+=1,this.lifetime.close(),this.authority=void 0;for(const t of this.frame.commandRecords.values())t.controller.close();const e=this.onClose;this.onClose=void 0,e==null||e(),this.publishRenderable(),this.rendererAttached||this.releaseFrame()}detach(){if(!this.rendererAttached)return;if(this.rendererAttached=!1,this.state==="closed"){this.releaseFrame();return}if(this.state!=="active")return;this.state="closing";const e=++this.closeTicket;queueMicrotask(()=>{this.state==="closing"&&e===this.closeTicket&&this.close()})}diagnostics(){const e=[...this.frame.commandRecords.values()].map(t=>t.controller.diagnostics());return Object.freeze({active:this.state==="active",calls:Object.freeze(e),commandRecords:this.frame.commandRecords.size,models:this.frame.models.size})}getRenderableSnapshot=()=>this.state!=="closed"&&(this.isActive===void 0||this.isActive());releaseClosedFrame(){this.state==="closed"&&this.releaseFrame()}subscribeRenderable=e=>{if(this.state==="closed")return()=>{};const t={listener:e};this.renderListeners.add(t);let s=!0;return()=>{s&&(s=!1,this.renderListeners.delete(t))}};buildCommandRecords(e){let t=0;for(const s of this.boundCommands){de(s);const i=J(s,{captureAuthority:this.captureAuthority,id:`contributionCommand.${String(e)}.${String(++t)}`,scheduling:{policy:"parallel"}});this.frame.commandRecords.set(s,{controller:i,invoker:Object.freeze({run:i.run})})}}captureAuthority=()=>{const e=this.authority;if(this.state!=="active"||e===void 0)throw new d("inactive","Contribution mount is not active.");return e.assertCurrent(),e};createAuthority(e){return Object.freeze({assertCurrent:()=>{if(this.state!=="active")throw new d("inactive","Contribution mount is not active.");e.assertCurrent()},isCurrent:()=>this.state==="active"&&e.isCurrent()})}publishRenderable(){for(const{listener:e}of[...this.renderListeners])try{e()}catch(t){w(t)}}releaseFrame(){this.released||(this.released=!0,this.frame.commandRecords.clear(),this.frame.models.clear(),this.boundCommands=[],this.renderListeners.clear())}}function ve({children:n,mount:e}){const t=S(e.subscribeRenderable,e.getRenderableSnapshot,e.getRenderableSnapshot);return R(()=>{if(e.attach())return()=>e.detach()},[e]),f(()=>{t||e.releaseClosedFrame()},[e,t]),t?h(F,{value:e.frame,children:n}):null}function q(n){const e=n.bundle;n.bundle=void 0,e==null||e.frame.close()}function ye(n,e){if(typeof e!="object"||e===null)return T(n,e);const t=i=>O(i)||C(i)||g(i)||typeof i=="function"||$(i),s=Object.entries(e).map(([i,r])=>[i,t(r)?r:ce(r)]);return T(n,Object.fromEntries(s))}function Me(n){return Q(n)}const Se={models:[]};function L(n,e){try{n()}catch(t){throw A([e,t],"Contribution mount setup and cleanup failed.",{cause:e})}throw e}function Re(n,e,t,s){const i=Y(e),{models:r,reporter:c}=s??Se;try{const o=ee(n.models),a=o.length===0?void 0:te(o,i,c);return{bundle:a,models:[...r,...(a==null?void 0:a.models)??[],...t],props:i}}catch(o){return L(()=>k(i),o)}}function Ae(n,e,t,s){const{bundle:i,models:r,props:c}=Re(n,e,t,s);let o=!1;const a=()=>{if(!o){o=!0;try{i==null||i.close().catch(w)}finally{k(c)}}};try{return{frame:new Ce(r.map(([u,b])=>ye(u,b)),{isActive:()=>!o,onClose:a}),isOpen:()=>!o,props:c}}catch(l){return L(a,l)}}function Oe(n,e){return h(n,{...e})}function ke({bundle:n,contribution:e}){const t=E(n.props),s=m(()=>e.props===void 0?t:e.props(t),[t,e]);return h(ve,{mount:n.frame,children:Oe(e.Component,s)})}function Fe({authority:n,contribution:e,fixtures:t,slotProps:s}){const i=m(()=>({authority:n,bundle:void 0,contribution:e,fixtures:t,retired:!1}),[n,e,t]),[r,c]=N(void 0),o=(r==null?void 0:r.owner)===i?r.bundle:void 0,a=M(s);return f(()=>{a.current=s}),R(()=>()=>{i.retired=!0,queueMicrotask(()=>{try{q(i)}catch(l){w(l)}})},[i]),f(()=>{const l=i.bundle??(i.bundle=Ae(i.contribution,a.current,i.fixtures??[],i.authority));return c(u=>(u==null?void 0:u.owner)===i?u:{bundle:l,owner:i}),()=>{i.retired&&q(i)}},[i]),f(()=>{(o==null?void 0:o.isOpen())===!0&&X(o.props,s)},[o,s]),o===void 0?null:h(ke,{bundle:o,contribution:e})}function je(n){const{authority:e,contribution:t,contributionId:s,fixtures:i,targetId:r}=n,c=ne(),o=m(()=>({authority:e,contribution:t,fixtures:i}),[e,t,i]),a=e==null?void 0:e.feature,l=m(()=>({contribution:s,feature:a,target:r}),[s,a,r]),u=e==null?void 0:e.reporter,b=p(V=>_(V,u),[u]);return h(se,{content:c,identity:o,report:b,source:l,children:h(Fe,{...n})})}const ze=W(je);export{ze as M,ie as a,I as b,Me as c,z as d,C as i,j as p,re as r,E as u};
|
|
2
|
-
//# sourceMappingURL=contribution-frame-D7_DN6Y2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contribution-frame-D7_DN6Y2.js","sources":["../src/mount-context.tsx","../src/resource-command.ts","../src/model-selection-store.ts","../src/readable-hooks.ts","../src/command.ts","../src/model-binding.ts","../src/mount-frame.ts","../src/mount-provider.tsx","../src/contribution-frame.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\n\nimport { ContributionError } from './errors';\nimport type { Frame } from './mount-frame';\n\nconst FrameContext = createContext<Frame | undefined>(undefined);\n\nfunction useFrame(): Frame {\n const frame = useContext(FrameContext);\n\n if (frame === undefined) {\n throw new ContributionError('missing', 'Opetope hook was called outside a contribution mount.');\n }\n\n return frame;\n}\n\nexport { FrameContext, useFrame };\n","/*\n * D359: the verbs of a Resource, exposed with their own outcome, and the recognition that answers\n * «is this selected field a Resource». A consumer keeps a status — `inFlight` until the operation settles, the\n * settled `outcome` — while the Resource stays owned by the model that declared it: cancelling this wait cancels the\n * wait and not the load.\n */\n\nimport type {\n PaginationOutcome,\n PaginationState,\n Resource,\n ResourceOperationOutcome,\n ResourcePagination,\n ResourceState,\n} from '@opetope/core';\nimport type { ResourceKey } from '@opetope/core/internal';\nimport { isResourceValue } from '@opetope/runtime/internal';\n\nimport type { ResourceVerbHook } from './resource-verb-hook';\n\n/**\n * D439: the widest Resource, and the name says so. `Resource<never, ResourceKey>` said the opposite in both\n * arguments — `never` is the narrowest `Data` a reader can be handed and a named `Key` *requires* `state.key`, so\n * hardly any member of the family fitted it. Nothing was refused, because every value reaches this name through a\n * cast, which is exactly why the name could drift. `ResourceKeyField<never>` requires no field, so\n * `Resource<unknown, never, 'consumers' | 'model'>` is the one form every Resource satisfies — keyed or not, paginated or not.\n */\ntype AnyResource = Resource<unknown, never, 'consumers' | 'model'>;\n\n/**\n * D349, D359: a Resource is a structural contract a host may implement with an ordinary object, so the question the\n * type of a selected field asked is answered by the runtime that owns it — the registry of the materializations it\n * built, and the structural contract for everything else. Asking it here a second time would let the two answers\n * drift, and a host adapter typed as a hook reaches the render where `state` is `undefined` and `refresh.run()`\n * throws.\n */\nfunction isResource(value: unknown): boolean {\n return isResourceValue(value);\n}\n\n/*\n * D356, D486: the nested capability — the projected pagination state and a stable `loadNext`. `state` is the one\n * source of the status a view shows: it is shared by every consumer and survives a remount, which a command's own\n * `inFlight` and `outcome` did not, and it keeps its identity until the cursor, the kind or the error moves, so it is\n * also the key a list asks for the next page by. `loadNext` is a plain function that stays the same while the\n * component holds the same Resource, and it answers the outcome of the page it asked for.\n */\n/**\n * The nested capability — the projected pagination state and a stable `loadNext`.\n */\ntype ResourcePaginationHook<Cursor extends ResourceKey> = Readonly<{\n loadNext: (options?: { readonly retry?: boolean }) => Promise<PaginationOutcome<Cursor>>;\n state: PaginationState<Cursor>;\n}>;\n\n/*\n * D359: what `useResource` answers, and what a field of a `useModel` selection whose value is a Resource answers.\n * Producer failures are settled Resource outcomes; the consumer's cancellation of a wait is `cancelled` directly.\n */\n/**\n * What `useResource` answers, and what a field of a `useModel` selection whose value is a Resource answers.\n */\ntype ResourceHook<Data, Key extends ResourceKey = never> = Readonly<{\n /**\n * Present when the Resource was paginated (`ctx.resource.paginate`); `undefined` for every other Resource.\n */\n pagination: ResourcePaginationHook<ResourceKey> | undefined;\n refresh: ResourceVerbHook;\n reset: ResourceVerbHook;\n retry: ResourceVerbHook;\n state: ResourceState<Data, Key>;\n}>;\n\ntype PaginatedResourceHook<Data, Key extends ResourceKey, Cursor extends ResourceKey> = Omit<\n ResourceHook<Data, Key>,\n 'pagination'\n> &\n Readonly<{ pagination: ResourcePaginationHook<Cursor> }>;\n\ntype ResourceInvokers = Readonly<{\n /** D486: not a command — the stable function `pagination.loadNext` is, one per Resource identity. */\n loadNext: (options?: { readonly retry?: boolean }) => Promise<unknown>;\n refresh: () => Promise<ResourceOperationOutcome>;\n reset: () => Promise<ResourceOperationOutcome>;\n retry: () => Promise<ResourceOperationOutcome>;\n}>;\n\nfunction paginationOf(resource: AnyResource): ResourcePagination<ResourceKey, 'consumers' | 'model'> | undefined {\n const capability = (resource as { readonly pagination?: unknown }).pagination;\n\n if (typeof capability !== 'object' || capability === null) return undefined;\n\n return capability as ResourcePagination<ResourceKey, 'consumers' | 'model'>;\n}\n\n/**\n * One set per Resource identity. Selected and standalone hooks both pick their controller by the identity of the\n * invoker, so a set rebuilt on every render would reset `inFlight`, drop `outcome` and change `run` — which is why it\n * is memoised against the Resource itself and never assembled during a render.\n */\nfunction createResourceInvokers(resource: AnyResource): ResourceInvokers {\n // D349: a Resource is a structural contract, so every verb is called through it and never as a detached function.\n return {\n // Only a paginated Resource hands this out, and the capability it calls through is the one it was selected with.\n loadNext: options => paginationOf(resource)!.loadNext(options),\n refresh: () => resource.refresh(),\n reset: () => resource.reset(),\n retry: () => resource.retry(),\n };\n}\n\nfunction resourceInvokers(resource: AnyResource, cache: WeakMap<object, ResourceInvokers>): ResourceInvokers {\n const existing = cache.get(resource);\n\n if (existing !== undefined) return existing;\n\n const invokers = createResourceInvokers(resource);\n cache.set(resource, invokers);\n\n return invokers;\n}\n\n/**\n * The one module of this package that talks to the runtime about a materialization, so the rest of React reads the\n * recognition and the key type from here instead of routing to `@opetope/runtime/internal` of its own.\n */\nexport { createResourceInvokers, isResource, paginationOf, resourceInvokers };\nexport type { AnyResource, PaginatedResourceHook, ResourceHook, ResourceInvokers, ResourceKey, ResourcePaginationHook };\n","import type { Readable } from '@opetope/core';\nimport { createAggregateError } from '@opetope/core/internal';\n\nimport type { ResourceDemand } from '@opetope/core/internal';\n\ntype Subscription = { dispose: (() => void) | undefined };\ntype Listener = Readonly<{ notify: () => void }>;\n\nconst noLeases: ReadonlySet<ResourceDemand> = new Set();\n\nfunction releaseSubscriptions(subscriptions: Iterable<Subscription>, failures: unknown[] = []): void {\n for (const subscription of subscriptions) {\n const dispose = subscription.dispose;\n subscription.dispose = undefined;\n\n try {\n dispose?.();\n } catch (error) {\n failures.push(error);\n }\n }\n\n if (failures.length === 1) throw failures[0];\n\n if (failures.length > 1) throw createAggregateError(failures, 'Model selection sources failed to release.');\n}\n\n/** A subscription set, not a scheduler: source notifications use React's snapshot consistency check. */\nclass ModelSelectionStore {\n private enabled = false;\n /** D359: one lease per Resource identity, diffed like a subscription, so an unchanged selection takes none. */\n private readonly leases = new Map<ResourceDemand, Subscription>();\n private readonly listeners = new Set<Listener>();\n private retained: ReadonlySet<ResourceDemand> = noLeases;\n private sources: ReadonlySet<Readable<unknown>> = new Set();\n private readonly subscriptions = new Map<Readable<unknown>, Subscription>();\n\n close(): void {\n this.enabled = false;\n this.sources = new Set();\n this.retained = noLeases;\n this.releaseAll();\n }\n\n commit(sources: ReadonlySet<Readable<unknown>>, retained: ReadonlySet<ResourceDemand> = noLeases): void {\n this.sources = sources;\n this.retained = retained;\n this.enabled = true;\n\n try {\n this.synchronize();\n } catch (error) {\n this.enabled = false;\n this.releaseAll([error]);\n }\n }\n\n subscribe = (notify: () => void): (() => void) => {\n const listener = { notify };\n this.listeners.add(listener);\n\n try {\n this.subscribeSources();\n } catch (error) {\n this.listeners.delete(listener);\n this.releaseAll([error]);\n }\n\n return () => {\n this.listeners.delete(listener);\n\n if (this.listeners.size === 0) this.releaseAll();\n };\n };\n\n private add(source: Readable<unknown>): void {\n const subscription: Subscription = { dispose: undefined };\n // Reserve before foreign code: a synchronous notification may replace or close this selection.\n this.subscriptions.set(source, subscription);\n const dispose = source.subscribe(this.notify);\n\n if (typeof dispose !== 'function') throw new TypeError('Model selection source must return a disposer.');\n\n if (this.subscriptions.get(source) === subscription) subscription.dispose = dispose;\n else dispose();\n }\n\n private notify = (): void => {\n for (const listener of [...this.listeners]) {\n if (this.listeners.has(listener)) listener.notify();\n }\n };\n\n private releaseAll(failures?: unknown[]): void {\n const held = [...this.subscriptions.values(), ...this.leases.values()];\n this.subscriptions.clear();\n this.leases.clear();\n releaseSubscriptions(held, failures);\n }\n\n private removeUnselected(): void {\n const removed: Subscription[] = [];\n\n for (const [source, subscription] of this.subscriptions) {\n if (this.sources.has(source)) continue;\n\n this.subscriptions.delete(source);\n removed.push(subscription);\n }\n\n for (const [resource, lease] of this.leases) {\n if (this.retained.has(resource)) continue;\n\n this.leases.delete(resource);\n removed.push(lease);\n }\n\n releaseSubscriptions(removed);\n }\n\n /**\n * D321: `retain()` is reentrant — it reaches `activate()`, the target subscription, the first read and the\n * publication that follows, all synchronously — and a listener woken there may rebuild or close this selection.\n * The record is reserved first, the lease is taken second, and it is kept only if the record is still this one.\n */\n private retain(resource: ResourceDemand): void {\n const lease: Subscription = { dispose: undefined };\n this.leases.set(resource, lease);\n const release = resource.acquire();\n\n if (typeof release !== 'function') throw new TypeError('Model selection resource must answer a release disposer.');\n\n if (this.leases.get(resource) === lease) lease.dispose = release;\n else release();\n }\n\n /** Foreign code inside a subscription or a lease may replace this selection, so both loops ask again. */\n private ready(): boolean {\n return this.enabled && this.listeners.size > 0;\n }\n\n private retainSelected(): void {\n for (const resource of this.retained) {\n // A committed selection owns demand before React installs its passive subscription.\n if (!this.enabled) return;\n\n if (this.retained.has(resource) && !this.leases.has(resource)) this.retain(resource);\n }\n }\n\n private subscribeSources(): void {\n for (const source of this.sources) {\n if (!this.ready()) return;\n\n if (this.sources.has(source) && !this.subscriptions.has(source)) this.add(source);\n }\n }\n\n private synchronize(): void {\n this.removeUnselected();\n this.subscribeSources();\n this.retainSelected();\n }\n}\n\nexport { ModelSelectionStore };\n","import { useCallback, useLayoutEffect, useRef, useSyncExternalStore } from 'react';\n\nimport type { Readable, Resource, ResourceKey, ResourceView } from '@opetope/core';\nimport { isResourceView, resourceViewDemands } from '@opetope/core/internal';\nimport type { ResourceDemand } from '@opetope/core/internal';\n\nimport { ModelSelectionStore } from './model-selection-store';\n\ntype SourceValue<Source> =\n Source extends ResourceView<infer Value> ? Value : Source extends Readable<infer Value> ? Value : never;\n\n/**\n * D469: what a mount that has read a view keeps for the rest of its life. `observe()` is asked once per view, so a\n * structural view whose `observe()` answers a new Readable each time is not resubscribed by every render, and the\n * one store holds the demand roots of the committed view — two views over one root hand it over without a release.\n */\nclass ViewDemand {\n readonly store = new ModelSelectionStore();\n private readonly observations = new WeakMap<object, Readable<unknown>>();\n\n observe(view: ResourceView<unknown>): Readable<unknown> {\n let observed = this.observations.get(view);\n\n if (observed === undefined) {\n observed = view.observe();\n this.observations.set(view, observed);\n }\n\n return observed;\n }\n\n /** Demand follows the committed source: a view's roots, or none at all for a plain Readable. */\n commit(source: object): void {\n const observed = this.observations.get(source);\n\n if (observed === undefined) this.store.close();\n else\n this.store.commit(\n new Set([observed]),\n new Set<ResourceDemand>(resourceViewDemands(source as ResourceView<unknown>)),\n );\n }\n}\n\n/**\n * D469: demand follows only the source that committed. A mount may switch between a ResourceView and a plain\n * Readable; the store exists only after it has read a view.\n */\ninterface SelectionInstance {\n views: ViewDemand | undefined;\n}\n\nfunction useSourceValue<Value>(source: Readable<Value> | ResourceView<Value>): Value {\n const instanceRef = useRef<SelectionInstance | undefined>(undefined);\n let instance = instanceRef.current;\n\n if (instance === undefined) {\n instance = { views: undefined };\n instanceRef.current = instance;\n }\n\n // A valid dual-protocol host is a view first, as in the read of a model selection (D466).\n let readable: Readable<Value>;\n let target: Readable<unknown> | ModelSelectionStore;\n\n if (isResourceView(source)) {\n const demand = (instance.views ??= new ViewDemand());\n readable = demand.observe(source) as Readable<Value>;\n target = demand.store;\n } else {\n readable = source;\n target = readable;\n }\n\n const subscribe = useCallback((listener: () => void) => target.subscribe(listener), [target]);\n const getSnapshot = useCallback(() => readable.getSnapshot(), [readable]);\n const selected = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useLayoutEffect(() => {\n // Commit in layout: releasing A can synchronously mutate B. React must see that write before its\n // post-commit snapshot check, or B's displayed value can remain stale.\n // React replays layout setup before restoring passive subscriptions in StrictMode and Activity.\n instance.views?.commit(source);\n }, [instance, source]);\n\n return selected;\n}\n\n/**\n * Subscribe to a Readable or lease a ResourceView for this committed mount.\n */\nexport function useReadable<\n Source extends Readable<unknown> | Resource<unknown, ResourceKey, 'consumers' | 'model'> | ResourceView<unknown>,\n>(\n source: Source extends Readable<unknown> | ResourceView<unknown>\n ? Source\n : 'read resource.state, or select the Resource in useModel',\n): SourceValue<Source> {\n return useSourceValue(source as Readable<SourceValue<Source>> | ResourceView<SourceValue<Source>>);\n}\n","import type { Command } from '@opetope/core';\nimport { isCallTarget } from '@opetope/core/internal';\n\nimport { ContributionError } from './errors';\n\n/**\n * A bound command is the authentic `Command` the model field declares, so the common path adds no wrapper. Observable\n * call state belongs to the model as a `Readable` field (D71), so a binding carries no mode.\n */\ntype CommandBindingIdentity = Command<never, unknown>;\ntype CommandBinding<Input, Output> = Command<Input, Output>;\n\ntype CommandOutcome<Output> =\n | { readonly error: unknown; readonly kind: 'failed' }\n | { readonly reason: unknown; readonly kind: 'cancelled' }\n | { readonly kind: 'ok'; readonly value: Output };\n\ntype AnyCommandBinding = CommandBinding<never, unknown>;\n\ntype CommandBindingDefinition<Input, Output> = {\n readonly target: Command<Input, Output>;\n};\n\nconst bindingDefinitions = new WeakMap<CommandBindingIdentity, CommandBindingDefinition<never, unknown>>();\n\nfunction bindCommand<Input, Output>(target: Command<Input, Output>): CommandBinding<Input, Output> {\n if (arguments.length > 1) {\n throw new ContributionError(\n 'binding-invalid',\n 'Command follows the target it binds; binding options are forbidden.',\n );\n }\n\n if (!isCallTarget(target)) throw new ContributionError('binding-invalid', 'Command target is not authentic.');\n\n bindingDefinitions.set(target, { target });\n\n return target;\n}\n\nfunction getCommandBindingDefinition<Input, Output>(\n binding: Command<Input, Output>,\n): CommandBindingDefinition<Input, Output> {\n const definition = bindingDefinitions.get(binding);\n\n if (definition === undefined) throw new ContributionError('binding-invalid', 'Command binding is not authentic.');\n\n return definition as CommandBindingDefinition<Input, Output>;\n}\n\nfunction isCommandBinding(value: unknown): value is AnyCommandBinding {\n return typeof value === 'object' && value !== null && bindingDefinitions.has(value as CommandBindingIdentity);\n}\n\nexport { bindCommand, getCommandBindingDefinition, isCommandBinding };\nexport type { CommandOutcome };\n","import type { Command, ModelOf } from '@opetope/core';\nimport { isModel, isReadable, isResourceView } from '@opetope/core/internal';\nimport type { ExactKeys, ModelIdentity } from '@opetope/core/internal';\n\nimport { isCommandBinding } from './command';\nimport { ContributionError } from './errors';\nimport { isResource } from './resource-command';\n\nconst modelBindingBrand = Symbol('opetope.model-binding');\nconst modelBindingIdentityBrand = Symbol('opetope.model-binding-identity');\nconst modelBindingMarker = Object.freeze({});\n\ntype AnyModel = ModelIdentity;\ntype AnyCommand = Command<never, unknown>;\n\ninterface ModelBindingIdentity {\n readonly [modelBindingIdentityBrand]: true;\n}\n\ninterface ModelBinding<Declaration extends AnyModel> extends ModelBindingIdentity {\n readonly [modelBindingBrand]: (declaration: Declaration) => Declaration;\n}\n\ntype ModelBindingMetadata = {\n readonly commands: readonly AnyCommand[];\n readonly declaration: AnyModel;\n readonly model: object;\n};\n\nconst registry = new WeakMap<ModelBindingIdentity, ModelBindingMetadata>();\n\n/**\n * The declaration carries the field shape in its type; binding also validates fields supplied by host code.\n * ResourceViews travel unchanged, so observing a model never acquires its dependencies.\n */\nfunction modelFieldValue(declaration: AnyModel, model: object, field: PropertyKey): unknown {\n if (typeof field !== 'string') {\n throw new ContributionError('binding-invalid', `Model ${declaration.id} accepts only string fields.`);\n }\n\n const descriptor = Object.getOwnPropertyDescriptor(model, field);\n\n if (descriptor?.enumerable !== true || !('value' in descriptor)) {\n throw new ContributionError(\n 'binding-invalid',\n `Model ${declaration.id}.${field} requires an enumerable data binding.`,\n );\n }\n\n return descriptor.value;\n}\n\nfunction isObservedField(value: unknown): boolean {\n return isReadable(value) || isResource(value) || isResourceView(value) || typeof value === 'function';\n}\n\nfunction snapshotModelFields(declaration: AnyModel, model: object): readonly AnyCommand[] {\n const commands: AnyCommand[] = [];\n const fields = Reflect.ownKeys(model);\n\n if (fields.length === 0)\n throw new ContributionError('binding-invalid', `Model ${declaration.id} requires at least one field.`);\n\n for (const field of fields) {\n const value = modelFieldValue(declaration, model, field);\n\n // D349: a Resource is a field a model publishes, and it is not a `Readable`, so it is recognised by name.\n if (isObservedField(value)) continue;\n\n if (!isCommandBinding(value)) {\n throw new ContributionError(\n 'binding-invalid',\n `Model ${declaration.id}.${String(field)} requires a Readable, a Resource, a ResourceView or a bound command.`,\n );\n }\n\n commands.push(value);\n }\n\n return Object.freeze(commands);\n}\n\nfunction bindModel<Declaration extends AnyModel, const Keys extends PropertyKey = never>(\n declaration: Declaration,\n model: ExactKeys<Keys, ModelOf<Declaration>> & ModelOf<Declaration>,\n): ModelBinding<Declaration> {\n if (!isModel(declaration)) throw new ContributionError('binding-invalid', 'Model declaration is not authentic.');\n\n if (typeof model !== 'object' || model === null) {\n throw new ContributionError('binding-invalid', `Model ${declaration.id} requires a record binding.`);\n }\n\n const commands = snapshotModelFields(declaration, model);\n const binding = Object.freeze({\n [modelBindingBrand]: modelBindingMarker as unknown as (value: Declaration) => Declaration,\n [modelBindingIdentityBrand]: true as const,\n });\n registry.set(binding, { commands, declaration, model });\n\n return binding;\n}\n\nfunction getModelBindingMetadata(binding: ModelBindingIdentity): ModelBindingMetadata {\n const metadata = registry.get(binding);\n\n if (metadata === undefined) throw new ContributionError('binding-invalid', 'Model binding is not authentic.');\n\n return metadata;\n}\n\nexport { bindModel, getModelBindingMetadata };\nexport type { AnyCommand, AnyModel, ModelBindingIdentity };\n","import type {\n CallAuthority,\n CallController,\n CallDiagnostics,\n CallRunOptions,\n LifetimeLease,\n} from '@opetope/core/internal';\nimport { createCallController, createLifetimeController, reportDetachedError } from '@opetope/core/internal';\n\nimport { getCommandBindingDefinition } from './command';\nimport { ContributionError } from './errors';\nimport { getModelBindingMetadata } from './model-binding';\nimport type { AnyCommand, AnyModel, ModelBindingIdentity } from './model-binding';\n\ntype RuntimeCommandInvoker = {\n readonly run: (input: never, options?: CallRunOptions<unknown>) => Promise<unknown>;\n};\n\ntype CommandRecord = {\n readonly controller: CallController<never, unknown>;\n readonly invoker: RuntimeCommandInvoker;\n};\n\n/** What a mounted contribution grants its components: the models it may read and the commands it may invoke. */\ntype Frame = {\n readonly commandRecords: Map<AnyCommand, CommandRecord>;\n readonly models: Map<AnyModel, unknown>;\n};\n\ntype MountFrameLifecycle = {\n readonly isActive: () => boolean;\n readonly onClose: () => void;\n};\n\ntype MountFrameDiagnostics = {\n readonly active: boolean;\n readonly calls: readonly CallDiagnostics[];\n readonly commandRecords: number;\n readonly models: number;\n};\n\nlet nextMountId = 0;\n\nfunction buildFrame(supplied: readonly ModelBindingIdentity[]): {\n readonly commands: readonly AnyCommand[];\n readonly frame: Frame;\n} {\n const models = new Map<AnyModel, unknown>();\n const commands: AnyCommand[] = [];\n const bound = new Set<AnyCommand>();\n\n for (const candidate of supplied) {\n const binding = getModelBindingMetadata(candidate);\n\n if (models.has(binding.declaration)) {\n throw new ContributionError('duplicate', `Model ${binding.declaration.id} is bound twice in one mount.`);\n }\n\n models.set(binding.declaration, binding.model);\n\n for (const command of binding.commands) {\n // D197: one Command is one command of the mount, however many fields of the models name it. A second name is an\n // alias, not a second command, so it shares the record, the activation and the fence.\n if (bound.has(command)) continue;\n\n bound.add(command);\n commands.push(command);\n }\n }\n\n return { commands: Object.freeze(commands), frame: { commandRecords: new Map(), models } };\n}\n\n/**\n * The lifetime of one mounted contribution. `attach` claims it for the renderer, `detach` schedules the close on the\n * next microtask so a StrictMode remount reuses the same mount, and `close` fences every command it granted (D85).\n */\nclass MountFrameImpl {\n readonly frame: Frame;\n private authority: CallAuthority | undefined;\n private boundCommands: readonly AnyCommand[];\n private closeTicket = 0;\n private readonly isActive: (() => boolean) | undefined;\n private readonly lifetime: ReturnType<typeof createLifetimeController>;\n private onClose: (() => void) | undefined;\n private released = false;\n private rendererAttached = false;\n private readonly renderListeners = new Set<{ readonly listener: () => void }>();\n private state: 'active' | 'closed' | 'closing' | 'detached' = 'detached';\n\n constructor(models: readonly ModelBindingIdentity[], lifecycle?: MountFrameLifecycle) {\n const mountId = ++nextMountId;\n this.lifetime = createLifetimeController({ id: `contribution.${String(mountId)}` });\n this.isActive = lifecycle?.isActive;\n this.onClose = lifecycle?.onClose;\n const { commands, frame } = buildFrame(models);\n this.frame = frame;\n this.boundCommands = commands;\n this.buildCommandRecords(mountId);\n }\n\n attach(): boolean {\n if (this.state === 'closing') {\n this.closeTicket += 1;\n this.state = 'active';\n this.rendererAttached = true;\n\n return true;\n }\n\n if (this.state === 'closed') return false;\n\n if (this.state === 'active') throw new ContributionError('duplicate', 'One contribution mount cannot mount twice.');\n\n const authority = this.createAuthority(this.lifetime.open());\n\n try {\n for (const record of this.frame.commandRecords.values()) record.controller.activate();\n } catch (error) {\n this.authority = authority;\n this.state = 'active';\n this.close();\n\n throw error;\n }\n\n this.authority = authority;\n this.rendererAttached = true;\n this.state = 'active';\n\n return true;\n }\n\n close(): void {\n if (this.state === 'closed') return;\n\n this.state = 'closed';\n this.closeTicket += 1;\n this.lifetime.close();\n this.authority = undefined;\n\n for (const record of this.frame.commandRecords.values()) record.controller.close();\n\n const onClose = this.onClose;\n this.onClose = undefined;\n onClose?.();\n this.publishRenderable();\n\n if (!this.rendererAttached) this.releaseFrame();\n }\n\n detach(): void {\n if (!this.rendererAttached) return;\n\n this.rendererAttached = false;\n\n if (this.state === 'closed') {\n this.releaseFrame();\n\n return;\n }\n\n if (this.state !== 'active') return;\n\n this.state = 'closing';\n const ticket = ++this.closeTicket;\n\n queueMicrotask(() => {\n if (this.state === 'closing' && ticket === this.closeTicket) this.close();\n });\n }\n\n diagnostics(): MountFrameDiagnostics {\n const calls = [...this.frame.commandRecords.values()].map(record => record.controller.diagnostics());\n\n return Object.freeze({\n active: this.state === 'active',\n calls: Object.freeze(calls),\n commandRecords: this.frame.commandRecords.size,\n models: this.frame.models.size,\n });\n }\n\n getRenderableSnapshot = (): boolean => this.state !== 'closed' && (this.isActive === undefined || this.isActive());\n\n releaseClosedFrame(): void {\n if (this.state === 'closed') this.releaseFrame();\n }\n\n subscribeRenderable = (listener: () => void): (() => void) => {\n if (this.state === 'closed') return (): void => undefined;\n\n const registration = { listener };\n this.renderListeners.add(registration);\n let subscribed = true;\n\n return (): void => {\n if (!subscribed) return;\n\n subscribed = false;\n this.renderListeners.delete(registration);\n };\n };\n\n private buildCommandRecords(mountId: number): void {\n let commandIndex = 0;\n\n // `buildFrame` already reduced the models to their distinct Commands, so every command here gets its own record.\n for (const command of this.boundCommands) {\n // Authenticity check only: the binding carries no mode since observe was removed (D71).\n getCommandBindingDefinition(command);\n const controller = createCallController(command, {\n captureAuthority: this.captureAuthority,\n id: `contributionCommand.${String(mountId)}.${String(++commandIndex)}`,\n scheduling: { policy: 'parallel' },\n });\n this.frame.commandRecords.set(command, { controller, invoker: Object.freeze({ run: controller.run }) });\n }\n }\n\n private captureAuthority = (): CallAuthority => {\n const authority = this.authority;\n\n if (this.state !== 'active' || authority === undefined) {\n throw new ContributionError('inactive', 'Contribution mount is not active.');\n }\n\n authority.assertCurrent();\n\n return authority;\n };\n\n private createAuthority(lease: LifetimeLease): CallAuthority {\n return Object.freeze({\n assertCurrent: (): void => {\n if (this.state !== 'active') throw new ContributionError('inactive', 'Contribution mount is not active.');\n\n lease.assertCurrent();\n },\n isCurrent: (): boolean => this.state === 'active' && lease.isCurrent(),\n });\n }\n\n private publishRenderable(): void {\n for (const { listener } of [...this.renderListeners]) {\n try {\n listener();\n } catch (error) {\n reportDetachedError(error);\n }\n }\n }\n\n private releaseFrame(): void {\n if (this.released) return;\n\n this.released = true;\n this.frame.commandRecords.clear();\n this.frame.models.clear();\n this.boundCommands = [];\n this.renderListeners.clear();\n }\n}\n\nexport { MountFrameImpl };\nexport type { Frame };\n","import { useInsertionEffect, useLayoutEffect, useSyncExternalStore } from 'react';\nimport type { PropsWithChildren, ReactElement } from 'react';\n\nimport { FrameContext } from './mount-context';\nimport type { MountFrameImpl } from './mount-frame';\n\nfunction MountProvider({\n children,\n mount,\n}: PropsWithChildren<{ readonly mount: MountFrameImpl }>): ReactElement | null {\n const renderable = useSyncExternalStore(\n mount.subscribeRenderable,\n mount.getRenderableSnapshot,\n mount.getRenderableSnapshot,\n );\n\n useInsertionEffect(() => {\n const attached = mount.attach();\n\n if (!attached) return undefined;\n\n return () => mount.detach();\n }, [mount]);\n\n useLayoutEffect(() => {\n if (!renderable) mount.releaseClosedFrame();\n }, [mount, renderable]);\n\n return renderable ? <FrameContext value={mount.frame}>{children}</FrameContext> : null;\n}\n\nexport { MountProvider };\n","import { memo, useCallback, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport type { ComponentType, ReactElement } from 'react';\n\nimport type { DeclarationId } from '@opetope/core';\nimport {\n closeStateFromOwner,\n createAggregateError,\n createState,\n getContributionOwner,\n isReadable,\n isResourceView,\n reportDetachedError,\n setStateFromOwner,\n} from '@opetope/core/internal';\nimport type { ModelIdentity, State } from '@opetope/core/internal';\nimport { openContributionModels, reportRuntimeFailure, requireContributionModelPlans } from '@opetope/runtime/internal';\nimport type { ContributionModelBundle, RuntimeErrorReporter } from '@opetope/runtime/internal';\n\nimport { bindCommand, isCommandBinding } from './command';\nimport { ContributionIsolation, useContributionErrorContent } from './contribution-isolation';\nimport { bindModel } from './model-binding';\nimport { isResource } from './resource-command';\nimport type { ModelBindingIdentity } from './model-binding';\nimport { MountFrameImpl } from './mount-frame';\nimport { MountProvider } from './mount-provider';\nimport { useReadable } from './readable-hooks';\n\ntype AnyModel = ModelIdentity;\ntype ContributionAuthority = {\n /** The feature whose generation published this contribution (D257). */\n readonly feature?: DeclarationId;\n readonly models: readonly (readonly [AnyModel, unknown])[];\n /** The reporter of the feature that published this contribution: a contained failure is its diagnostic, not ours. */\n readonly reporter?: RuntimeErrorReporter;\n};\ntype ModelFixture = readonly [declaration: AnyModel, model: unknown];\n\ntype ContributionValue = {\n readonly Component: ComponentType<never>;\n readonly models?: readonly object[] | undefined;\n readonly props?: ((slotProps: never) => object) | undefined;\n};\n\ntype ContributionMountProps = {\n readonly authority?: ContributionAuthority | undefined;\n readonly contribution: ContributionValue;\n /** The published entry this mount renders, and the slot it renders in: the identity of a contained failure (D257). */\n readonly contributionId: DeclarationId;\n readonly fixtures?: readonly ModelFixture[];\n readonly slotProps: object;\n readonly targetId: DeclarationId;\n};\n\ntype MountBundle = {\n readonly frame: MountFrameImpl;\n readonly isOpen: () => boolean;\n readonly props: State<object>;\n};\n\ntype MountOwner = {\n readonly authority: ContributionAuthority | undefined;\n bundle: MountBundle | undefined;\n readonly contribution: ContributionValue;\n readonly fixtures: readonly ModelFixture[] | undefined;\n retired: boolean;\n};\n\ntype CommittedMount = {\n readonly bundle: MountBundle;\n readonly owner: MountOwner;\n};\n\nfunction closeOwnedMount(owner: MountOwner): void {\n const bundle = owner.bundle;\n owner.bundle = undefined;\n bundle?.frame.close();\n}\n\n/**\n * Model fields arrive as authentic kernel calls; binding them registers the command records the frame needs. D349: a\n * Resource is none of those and needs none of it — it is a field the selection reads on its own terms, so it travels\n * to the frame unchanged instead of being offered to `bindCommand`, which would refuse it as inauthentic.\n */\nfunction bindFrameModel(declaration: AnyModel, model: unknown): ModelBindingIdentity {\n if (typeof model !== 'object' || model === null) return bindModel(declaration as never, model as never);\n\n const passesThrough = (value: unknown): boolean =>\n isReadable(value) ||\n isResource(value) ||\n isResourceView(value) ||\n typeof value === 'function' ||\n isCommandBinding(value);\n const fields = Object.entries(model).map(([key, value]): readonly [string, unknown] => [\n key,\n passesThrough(value) ? value : bindCommand(value as never),\n ]);\n\n return bindModel(declaration as never, Object.fromEntries(fields) as never);\n}\n\n/**\n * D70: the authority of a contribution belongs to the entry a feature published, not to the value it wrote. One\n * static contribution object may be published by two features, and each mount must read the models of its own.\n */\nfunction contributionAuthority(entry: unknown): ContributionAuthority | undefined {\n return getContributionOwner(entry) as ContributionAuthority | undefined;\n}\n\n/** A mount with no publishing generation behind it: a fixture of a component test grants nothing and reports nowhere. */\nconst unownedContribution: ContributionAuthority = { models: [] };\n\nfunction cleanupFailedMount(close: () => void, cause: unknown): never {\n try {\n close();\n } catch (error) {\n throw createAggregateError([cause, error], 'Contribution mount setup and cleanup failed.', { cause });\n }\n\n throw cause;\n}\n\nfunction contributionModels(\n contribution: ContributionValue,\n slotProps: object,\n fixtures: readonly ModelFixture[],\n owner: ContributionAuthority | undefined,\n): {\n readonly bundle: ContributionModelBundle | undefined;\n readonly models: readonly ModelFixture[];\n readonly props: State<object>;\n} {\n const props = createState(slotProps);\n const { models: granted, reporter } = owner ?? unownedContribution;\n\n try {\n const plans = requireContributionModelPlans(contribution.models);\n const bundle = plans.length === 0 ? undefined : openContributionModels(plans, props, reporter);\n\n return {\n bundle,\n models: [...granted, ...(bundle?.models ?? []), ...fixtures],\n props,\n };\n } catch (error) {\n return cleanupFailedMount(() => closeStateFromOwner(props), error);\n }\n}\n\nfunction createMountBundle(\n contribution: ContributionValue,\n slotProps: object,\n fixtures: readonly ModelFixture[],\n authority: ContributionAuthority | undefined,\n): MountBundle {\n const { bundle, models, props } = contributionModels(contribution, slotProps, fixtures, authority);\n let closed = false;\n const close = (): void => {\n if (closed) return;\n\n closed = true;\n\n try {\n void bundle?.close().catch(reportDetachedError);\n } finally {\n closeStateFromOwner(props);\n }\n };\n try {\n const frame = new MountFrameImpl(\n models.map(([declaration, model]) => bindFrameModel(declaration, model)),\n { isActive: () => !closed, onClose: close },\n );\n\n return { frame, isOpen: () => !closed, props };\n } catch (error) {\n return cleanupFailedMount(close, error);\n }\n}\n\nfunction createComponentElement(Component: ComponentType<never>, props: object): ReactElement {\n const Rendered = Component as ComponentType<object>;\n\n return <Rendered {...props} />;\n}\n\ntype MountedContributionProps = {\n readonly bundle: MountBundle;\n readonly contribution: ContributionValue;\n};\n\n/** Reads the committed props of one live mount: every hook here sees a bundle that already exists. */\nfunction MountedContribution({ bundle, contribution }: MountedContributionProps): ReactElement {\n const committedProps = useReadable(bundle.props);\n const componentProps = useMemo(\n () => (contribution.props === undefined ? committedProps : contribution.props(committedProps as never)),\n [committedProps, contribution],\n );\n\n return (\n <MountProvider mount={bundle.frame}>{createComponentElement(contribution.Component, componentProps)}</MountProvider>\n );\n}\n\n/**\n * D188: a mount is created in commit, never in render. The first pass renders nothing, the layout effect builds the\n * bundle from the props that committed and publishes it, and React flushes that update before paint. A render that\n * is thrown away — StrictMode's double invoke, an abandoned concurrent pass, a suspended sibling — therefore\n * creates no models at all, so there is nothing to sweep, adopt or replace.\n */\nfunction ContributionMount({\n authority,\n contribution,\n fixtures,\n slotProps,\n}: ContributionMountProps): ReactElement | null {\n const owner = useMemo<MountOwner>(\n () => ({ authority, bundle: undefined, contribution, fixtures, retired: false }),\n [authority, contribution, fixtures],\n );\n const [committed, setCommitted] = useState<CommittedMount | undefined>(undefined);\n const bundle = committed?.owner === owner ? committed.bundle : undefined;\n const committedSlotProps = useRef(slotProps);\n\n useLayoutEffect(() => {\n committedSlotProps.current = slotProps;\n });\n\n // Suspense disconnects layout effects while hiding, but insertion cleanup only retires an actual identity.\n // Do not close Readables in insertion: their listeners may update React. A hidden tree has no layout cleanup\n // left to run on unmount, so the microtask also releases a mount that never becomes visible again.\n useInsertionEffect(\n () => () => {\n owner.retired = true;\n queueMicrotask(() => {\n try {\n closeOwnedMount(owner);\n } catch (error) {\n reportDetachedError(error);\n }\n });\n },\n [owner],\n );\n\n // The identity of the contribution owns the mount; a reveal and StrictMode reuse what its first commit created.\n useLayoutEffect(() => {\n const created = (owner.bundle ??= createMountBundle(\n owner.contribution,\n committedSlotProps.current,\n owner.fixtures ?? [],\n owner.authority,\n ));\n setCommitted(current => (current?.owner === owner ? current : { bundle: created, owner }));\n\n return () => {\n if (owner.retired) closeOwnedMount(owner);\n };\n }, [owner]);\n\n // Both the component and its models read the same committed snapshot, published before paint.\n useLayoutEffect(() => {\n if (bundle?.isOpen() === true) setStateFromOwner(bundle.props, slotProps);\n }, [bundle, slotProps]);\n\n if (bundle === undefined) return null;\n\n return <MountedContribution bundle={bundle} contribution={contribution} />;\n}\n\n/**\n * D256: every mount is a boundary. The isolation sits above `ContributionMount`, so it contains the render of the\n * component and the commit that builds the mount alike, and a retry rebuilds the mount instead of reusing the bundle\n * that failed. Containment is unconditional; the content a failure shows is the host policy of `ContributionBoundary`.\n */\nfunction IsolatedContributionMount(props: ContributionMountProps): ReactElement {\n const { authority, contribution, contributionId, fixtures, targetId } = props;\n const content = useContributionErrorContent();\n const identity = useMemo(() => ({ authority, contribution, fixtures }), [authority, contribution, fixtures]);\n const feature = authority?.feature;\n const source = useMemo(\n () => ({ contribution: contributionId, feature, target: targetId }),\n [contributionId, feature, targetId],\n );\n const reporter = authority?.reporter;\n const report = useCallback((error: unknown) => reportRuntimeFailure(error, reporter), [reporter]);\n\n return (\n <ContributionIsolation content={content} identity={identity} report={report} source={source}>\n <ContributionMount {...props} />\n </ContributionIsolation>\n );\n}\n\n/**\n * One mount, one memo: `Slot` recreates its children whenever `entries` changes, so publishing or withholding one\n * contribution used to re-render every other mount of that target. The props are the contribution, the slot props\n * and the fixtures, all of which are stable while nothing about that mount changed.\n */\nconst MemoizedContributionMount = memo(IsolatedContributionMount);\n\nexport { contributionAuthority, MemoizedContributionMount as ContributionMount };\nexport type { ContributionValue, ModelFixture };\n"],"names":["FrameContext","createContext","useFrame","frame","useContext","ContributionError","isResource","value","isResourceValue","paginationOf","resource","capability","createResourceInvokers","options","resourceInvokers","cache","existing","invokers","noLeases","releaseSubscriptions","subscriptions","failures","subscription","dispose","error","createAggregateError","ModelSelectionStore","sources","retained","notify","listener","source","held","removed","lease","release","ViewDemand","view","observed","resourceViewDemands","useSourceValue","instanceRef","useRef","instance","readable","target","isResourceView","demand","subscribe","useCallback","getSnapshot","selected","useSyncExternalStore","useLayoutEffect","_a","useReadable","bindingDefinitions","bindCommand","isCallTarget","getCommandBindingDefinition","binding","definition","isCommandBinding","modelBindingBrand","modelBindingIdentityBrand","modelBindingMarker","registry","modelFieldValue","declaration","model","field","descriptor","isObservedField","isReadable","snapshotModelFields","commands","fields","bindModel","isModel","getModelBindingMetadata","metadata","nextMountId","buildFrame","supplied","models","bound","candidate","command","MountFrameImpl","lifecycle","mountId","createLifetimeController","authority","record","onClose","ticket","calls","registration","subscribed","commandIndex","controller","createCallController","reportDetachedError","MountProvider","children","mount","renderable","useInsertionEffect","_jsx","closeOwnedMount","owner","bundle","bindFrameModel","passesThrough","key","contributionAuthority","entry","getContributionOwner","unownedContribution","cleanupFailedMount","close","cause","contributionModels","contribution","slotProps","fixtures","props","createState","granted","reporter","plans","requireContributionModelPlans","openContributionModels","closeStateFromOwner","createMountBundle","closed","createComponentElement","Component","MountedContribution","committedProps","componentProps","useMemo","ContributionMount","committed","setCommitted","useState","committedSlotProps","created","current","setStateFromOwner","IsolatedContributionMount","contributionId","targetId","content","useContributionErrorContent","identity","feature","report","reportRuntimeFailure","ContributionIsolation","MemoizedContributionMount","memo"],"mappings":"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"}
|