@kumwe/studio-core 0.1.0-alpha.8 → 0.1.0-beta.2
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/README.md +84 -4
- package/THIRD_PARTY_NOTICES.md +9 -0
- package/dist/authentication-lifetime.d.ts +16 -0
- package/dist/authentication-lifetime.d.ts.map +1 -0
- package/dist/authentication-lifetime.js +1 -0
- package/dist/binding-projection.d.ts +47 -0
- package/dist/binding-projection.d.ts.map +1 -0
- package/dist/binding-projection.js +1 -0
- package/dist/canonical.js +1 -100
- package/dist/clone.js +1 -4
- package/dist/commands.d.ts +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +1 -799
- package/dist/contextual-session.d.ts +112 -0
- package/dist/contextual-session.d.ts.map +1 -0
- package/dist/contextual-session.js +1 -0
- package/dist/contributions.d.ts +63 -2
- package/dist/contributions.d.ts.map +1 -1
- package/dist/contributions.js +1 -302
- package/dist/deployment-validation.d.ts +10 -0
- package/dist/deployment-validation.d.ts.map +1 -0
- package/dist/deployment-validation.js +1 -0
- package/dist/entry-commands.js +1 -36
- package/dist/extension-sdk.d.ts +12 -6
- package/dist/extension-sdk.d.ts.map +1 -1
- package/dist/extension-sdk.js +1 -188
- package/dist/history.d.ts +12 -2
- package/dist/history.d.ts.map +1 -1
- package/dist/history.js +1 -63
- package/dist/host-session.d.ts +93 -0
- package/dist/host-session.d.ts.map +1 -0
- package/dist/host-session.js +1 -0
- package/dist/http-authoring-contract.d.ts +29 -0
- package/dist/http-authoring-contract.d.ts.map +1 -0
- package/dist/http-authoring-contract.js +1 -0
- package/dist/http-host-adapter.d.ts +173 -0
- package/dist/http-host-adapter.d.ts.map +1 -0
- package/dist/http-host-adapter.js +1 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -18
- package/dist/layout.d.ts +66 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +1 -0
- package/dist/migrations.js +1 -83
- package/dist/model-commands.js +1 -21
- package/dist/modes.js +1 -280
- package/dist/negotiation.js +1 -65
- package/dist/production-values.d.ts +12 -0
- package/dist/production-values.d.ts.map +1 -0
- package/dist/production-values.js +1 -0
- package/dist/production.d.ts +86 -0
- package/dist/production.d.ts.map +1 -0
- package/dist/production.js +1 -0
- package/dist/profile-validator.d.ts.map +1 -1
- package/dist/profile-validator.js +1 -887
- package/dist/recipes.js +1 -34
- package/dist/registry.js +1 -56
- package/dist/schema-profile.js +1 -1015
- package/dist/semver.js +1 -128
- package/dist/session-policy.d.ts +23 -0
- package/dist/session-policy.d.ts.map +1 -0
- package/dist/session-policy.js +1 -0
- package/dist/session.d.ts +14 -2
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +1 -178
- package/dist/strict-json.d.ts +7 -0
- package/dist/strict-json.d.ts.map +1 -0
- package/dist/strict-json.js +2 -0
- package/dist/url-policy.js +1 -248
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +1 -398
- package/package.json +5 -3
- package/dist/canonical.js.map +0 -1
- package/dist/clone.js.map +0 -1
- package/dist/commands.js.map +0 -1
- package/dist/contributions.js.map +0 -1
- package/dist/entry-commands.js.map +0 -1
- package/dist/extension-sdk.js.map +0 -1
- package/dist/history.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/migrations.js.map +0 -1
- package/dist/model-commands.js.map +0 -1
- package/dist/modes.js.map +0 -1
- package/dist/negotiation.js.map +0 -1
- package/dist/profile-validator.js.map +0 -1
- package/dist/recipes.js.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/schema-profile.js.map +0 -1
- package/dist/semver.js.map +0 -1
- package/dist/session.js.map +0 -1
- package/dist/url-policy.js.map +0 -1
- package/dist/validation.js.map +0 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { type AddModelFieldCommand, type AuthoringArtifactCoordinates, type AuthoringPresentationState, type AuthoringSaveIntent, type AuthoringSavePlan, type AuthoringSaveResult, type AuthoringSessionSnapshot, type AuthoringStartRequest, type AuthoringTargetResolution, type AuthoringTargetResolveRequest, type AuthoringTypeListPage, type AuthoringTypeListQuery, type BlueprintCommand, type BlueprintDocument, type ContentModelDocument, type EntryDocument, type HostAdapter, type HostPortResult, type MessageReference, type QualifiedName, type ReusableContentTypeDefinition, type SetFieldValueCommand, type StudioConfiguration, type StudioDiagnostic } from '@kumwe/studio-protocol';
|
|
2
|
+
import { type StudioHostSessionIdentifierFactories } from './host-session.js';
|
|
3
|
+
import { type CapabilityNegotiationResult } from './negotiation.js';
|
|
4
|
+
import { StudioSession } from './session.js';
|
|
5
|
+
/**
|
|
6
|
+
* Check an untrusted value against the complete canonical contextual-project
|
|
7
|
+
* schema. The guard performs no authorization and returns no host authority;
|
|
8
|
+
* callers still decide whether the referenced blocks and capabilities are
|
|
9
|
+
* available in their runtime.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isAuthoringSessionSnapshot(value: unknown): value is AuthoringSessionSnapshot;
|
|
12
|
+
/** Check an untrusted value against the canonical host save-intent shape. */
|
|
13
|
+
export declare function isAuthoringSaveIntent(value: unknown): value is AuthoringSaveIntent;
|
|
14
|
+
export interface OpenContextualStudioSessionOptions {
|
|
15
|
+
/** The same resolved configuration that binds locale, actor, context and generation. */
|
|
16
|
+
configuration: StudioConfiguration;
|
|
17
|
+
/** Injected deterministic identifiers; core reads no clock or random source. */
|
|
18
|
+
identifiers: StudioHostSessionIdentifierFactories;
|
|
19
|
+
/** The exact target/resource request resolved before any artifacts are started. */
|
|
20
|
+
target: AuthoringTargetResolveRequest;
|
|
21
|
+
/** Blank, reusable-type, or existing-item start for that same target and resource. */
|
|
22
|
+
start: AuthoringStartRequest;
|
|
23
|
+
}
|
|
24
|
+
export interface PreflightContextualStudioSessionOptions {
|
|
25
|
+
/** The same resolved configuration that binds locale, actor, context and generation. */
|
|
26
|
+
configuration: StudioConfiguration;
|
|
27
|
+
/** Injected deterministic identifiers; core reads no clock or random source. */
|
|
28
|
+
identifiers: StudioHostSessionIdentifierFactories;
|
|
29
|
+
/** The exact target/resource request authorized before a start is selected. */
|
|
30
|
+
target: AuthoringTargetResolveRequest;
|
|
31
|
+
}
|
|
32
|
+
export interface StudioContextualArtifactStateVersions {
|
|
33
|
+
readonly blueprint: number;
|
|
34
|
+
readonly entry: number;
|
|
35
|
+
readonly model: number;
|
|
36
|
+
}
|
|
37
|
+
export interface StudioContextualDirtyArtifacts {
|
|
38
|
+
readonly blueprint: boolean;
|
|
39
|
+
readonly entry: boolean;
|
|
40
|
+
readonly model: boolean;
|
|
41
|
+
}
|
|
42
|
+
export type StudioContextualSaveIntentOptions = {
|
|
43
|
+
/** Include a separately authorized item-local Blueprint, never a reusable-type mutation. */
|
|
44
|
+
readonly includeItemBlueprint?: boolean;
|
|
45
|
+
readonly outcome: 'save-item';
|
|
46
|
+
} | {
|
|
47
|
+
readonly outcome: 'save-new-type-version';
|
|
48
|
+
} | {
|
|
49
|
+
readonly authoringPolicy: ReusableContentTypeDefinition['authoringPolicy'];
|
|
50
|
+
readonly label: MessageReference;
|
|
51
|
+
readonly outcome: 'save-as-new-type';
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* One DOM-free, resource-bound editing state. The three drafts stay separate,
|
|
55
|
+
* carry independent state versions, and accept only commands for the modes the
|
|
56
|
+
* host resolved. Durable effects remain on the host-session handle.
|
|
57
|
+
*/
|
|
58
|
+
export interface StudioContextualSession {
|
|
59
|
+
readonly blueprint: BlueprintDocument;
|
|
60
|
+
readonly blueprintSession: StudioSession;
|
|
61
|
+
readonly coordinates: AuthoringArtifactCoordinates;
|
|
62
|
+
readonly dirty: StudioContextualDirtyArtifacts;
|
|
63
|
+
readonly entry: EntryDocument;
|
|
64
|
+
readonly model: ContentModelDocument;
|
|
65
|
+
readonly snapshot: AuthoringSessionSnapshot;
|
|
66
|
+
readonly stateVersions: StudioContextualArtifactStateVersions;
|
|
67
|
+
createSaveIntent(options: StudioContextualSaveIntentOptions): AuthoringSaveIntent;
|
|
68
|
+
executeBlueprint(command: BlueprintCommand): BlueprintDocument;
|
|
69
|
+
executeEntry(command: SetFieldValueCommand): EntryDocument;
|
|
70
|
+
executeModel(command: AddModelFieldCommand): ContentModelDocument;
|
|
71
|
+
setPresentation(presentation: AuthoringPresentationState): AuthoringPresentationState;
|
|
72
|
+
}
|
|
73
|
+
export interface StudioContextualTypeCatalog {
|
|
74
|
+
list(query: AuthoringTypeListQuery): Promise<HostPortResult<AuthoringTypeListPage>>;
|
|
75
|
+
}
|
|
76
|
+
/** A resolved target that has not yet hydrated blank, reusable-type, or existing drafts. */
|
|
77
|
+
export interface StudioContextualPreflightHandle {
|
|
78
|
+
readonly diagnostics: readonly StudioDiagnostic[];
|
|
79
|
+
readonly disposed: boolean;
|
|
80
|
+
readonly invalidated: boolean;
|
|
81
|
+
readonly negotiation: CapabilityNegotiationResult;
|
|
82
|
+
readonly resolution: AuthoringTargetResolution;
|
|
83
|
+
readonly started: boolean;
|
|
84
|
+
readonly types: StudioContextualTypeCatalog | undefined;
|
|
85
|
+
dispose(): void;
|
|
86
|
+
start(request: AuthoringStartRequest): Promise<StudioContextualHostSessionHandle>;
|
|
87
|
+
}
|
|
88
|
+
export interface StudioContextualHostSessionHandle {
|
|
89
|
+
readonly diagnostics: readonly StudioDiagnostic[];
|
|
90
|
+
readonly disposed: boolean;
|
|
91
|
+
readonly invalidated: boolean;
|
|
92
|
+
readonly negotiation: CapabilityNegotiationResult;
|
|
93
|
+
readonly resolution: AuthoringTargetResolution;
|
|
94
|
+
readonly session: StudioContextualSession;
|
|
95
|
+
readonly types: StudioContextualTypeCatalog | undefined;
|
|
96
|
+
dispose(): void;
|
|
97
|
+
planSave(intent: AuthoringSaveIntent): Promise<HostPortResult<AuthoringSavePlan>>;
|
|
98
|
+
save(intent: AuthoringSaveIntent, plan: AuthoringSavePlan, acceptedConsequences?: readonly QualifiedName[]): Promise<HostPortResult<AuthoringSaveResult>>;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Opens the additive coordinated profile without changing the legacy
|
|
102
|
+
* Blueprint-only `openStudioSession` contract. Target resolution and start are
|
|
103
|
+
* explicit host calls; core never guesses an artifact or creates persistence.
|
|
104
|
+
*/
|
|
105
|
+
export declare function openContextualStudioSession(adapter: HostAdapter, options: Readonly<OpenContextualStudioSessionOptions>): Promise<StudioContextualHostSessionHandle>;
|
|
106
|
+
/**
|
|
107
|
+
* Resolve one target without prematurely choosing a create source. Interactive
|
|
108
|
+
* shells use this to present only the host-authorized blank/from-type choices;
|
|
109
|
+
* the convenience opener above uses the same path and immediately starts.
|
|
110
|
+
*/
|
|
111
|
+
export declare function preflightContextualStudioSession(adapter: HostAdapter, options: Readonly<PreflightContextualStudioSessionOptions>): Promise<StudioContextualPreflightHandle>;
|
|
112
|
+
//# sourceMappingURL=contextual-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextual-session.d.ts","sourceRoot":"","sources":["../src/contextual-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{authoringSaveSchema as e,authoringSessionSchema as t,authoringTargetSchema as n,blueprintSchema as r,commonSchema as i,contentModelSchema as a,entrySchema as o,reusableContentTypeSchema as s}from"@kumwe/studio-protocol";import{canonicalStringify as c}from"./canonical.js";import{cloneContractValue as l}from"./clone.js";import{StudioCommandError as u}from"./commands.js";import{applyEntryCommand as d}from"./entry-commands.js";import{SessionIdentifierAllocator as f,StudioHostSessionError as p,adapterContractFailure as m,createContext as h,createDiagnostic as g,isStaleGenerationFailure as _,mutationFingerprint as v,normalizeHostRejection as y}from"./host-session.js";import{applyModelCommand as ee}from"./model-commands.js";import{negotiateCapabilities as te}from"./negotiation.js";import{compileProfileSchema as ne}from"./profile-validator.js";import{StudioSession as re}from"./session.js";import{assertBlueprintWithinSessionPolicy as b,assertEntryWithinSessionPolicy as x,assertModelWithinSessionPolicy as S}from"./session-policy.js";const C=`studio.port/authoring`,w=`studio.operation/authoring.resolve-target`,T=`studio.operation/authoring.list-types`,E=`studio.operation/authoring.start`,D=`studio.operation/authoring.plan-save`,ie=[i,n,s,a,r,o,t,e],ae=M(`https://schemas.kumwe.org/studio/v1/authoring-target.schema.json#/$defs/resolveRequest`),oe=M(`https://schemas.kumwe.org/studio/v1/authoring-target.schema.json#/$defs/resolution`),O=M(`https://schemas.kumwe.org/studio/v1/reusable-content-type.schema.json#/$defs/listQuery`),se=M(`https://schemas.kumwe.org/studio/v1/reusable-content-type.schema.json#/$defs/listPage`),ce=M(`https://schemas.kumwe.org/studio/v1/authoring-session.schema.json#/$defs/startRequest`),k=M(`https://schemas.kumwe.org/studio/v1/authoring-session.schema.json#/$defs/snapshot`),A=M(`https://schemas.kumwe.org/studio/v1/authoring-save.schema.json#/$defs/saveIntent`),le=M(`https://schemas.kumwe.org/studio/v1/authoring-save.schema.json#/$defs/savePlan`),ue=M(`https://schemas.kumwe.org/studio/v1/authoring-save.schema.json#/$defs/saveResult`);export function isAuthoringSessionSnapshot(e){return k.validate(e)}export function isAuthoringSaveIntent(e){return A.validate(e)}export async function openContextualStudioSession(e,t){N(t.configuration,t.target,t.start);let n=await preflightContextualStudioSession(e,{configuration:t.configuration,identifiers:t.identifiers,target:t.target});try{return await n.start(t.start)}catch(e){throw n.dispose(),e}}export async function preflightContextualStudioSession(e,t){let n=l(t.configuration),r=l(t.target);P(n,r);let i=te(n.hostCapabilities,{requiredPorts:[C],supportedProtocolVersions:[n.protocolVersion]});n.sessionState===`read-only`&&(i.sessionState=`read-only`);let a=me(e,n,i);if(L(i,`The resolved configuration cannot open contextual authoring.`),a===void 0)throw new p(`configuration-blocked`,`The resolved configuration has no contextual authoring adapter.`,i.diagnostics);let o=new f(t.identifiers);try{let e=H(await Te(()=>a.resolveTarget(r,h(n,o.requestId(w),{operationId:w}))),oe,`studio.host/unexpected-authoring-target`,`The authoring port returned a malformed target resolution.`);return ge(n,r,e),he(n,i,e),L(i,`The resolved target cannot provide its declared authoring profile.`),new de(a,n,o,i,r,e)}catch(e){throw o.dispose(),e}}class de{diagnostics;negotiation;resolution;types;#authoring;#configuration;#identifiers;#targetRequest;#disposed=!1;#invalidationFailure;#startIdempotencyKeys=new Map;#startActive=!1;#started=!1;constructor(e,t,n,r,i,a){this.#authoring=e,this.#configuration=t,this.#identifiers=n,this.#targetRequest=l(i),this.negotiation=Y(r),this.diagnostics=l(r.diagnostics),this.resolution=l(a),this.types=I(t,T)?Object.freeze({list:e=>this.#listTypes(e)}):void 0}get disposed(){return this.#disposed}get invalidated(){return this.#invalidationFailure!==void 0}get started(){return this.#started}dispose(){this.#disposed||this.#started||(this.#disposed=!0,this.#startIdempotencyKeys.clear(),this.#identifiers.dispose())}async start(e){if(this.#assertActive(),this.#startActive)throw new p(`invalid-authoring-request`,`A contextual Studio start is already active for this resolved target.`);let t=l(e);N(this.#configuration,this.#targetRequest,t),_e(this.resolution,t);let n=v(t,this.#configuration),r=this.#startIdempotencyKeys.get(n);r===void 0&&(r=this.#identifiers.idempotencyKey(E,n),this.#startIdempotencyKeys.set(n,r)),this.#startActive=!0;try{let e=H(await this.#invoke(()=>this.#authoring.start(t,h(this.#configuration,this.#identifiers.requestId(E),{idempotencyKey:r,operationId:E}))),k,`studio.host/unexpected-authoring-session`,`The authoring port returned a malformed contextual session.`);return ve(this.#configuration,this.resolution,t,e),this.#started=!0,this.#startIdempotencyKeys.clear(),new pe(this.#authoring,this.#configuration,this.#identifiers,this.negotiation,this.resolution,e)}finally{this.#startActive=!1}}async#listTypes(e){return this.#assertActive(),j(this.#authoring,this.#configuration,this.#identifiers,this.resolution,e=>this.#invoke(e),e)}#assertActive(){if(this.#invalidationFailure!==void 0)throw this.#invalidationFailure;if(this.#started)throw new p(`disposed`,`The contextual Studio preflight has already transferred ownership to a session.`);if(this.#disposed)throw new p(`disposed`,`The contextual Studio preflight is disposed.`)}async#invoke(e){this.#assertActive();try{return await e()}catch(e){let t=y(e);throw _(t)&&(this.#invalidationFailure=t),t}}}class fe{#limits;#maximumHistoryEntries;#permissions;#readOnly;#blueprintSession;#entry;#entryStateVersion=0;#initialDirty=new Set;#model;#modelStateVersion=0;#presentation;#snapshot;constructor(e,t){this.#limits=l(t.limits),this.#maximumHistoryEntries=t.limits.maxHistoryEntries,this.#permissions=l(t.permissions),this.#readOnly=t.sessionState===`read-only`,this.acceptHostSnapshot(e)}get blueprint(){return l(this.#blueprintSession.document)}get blueprintSession(){return this.#blueprintSession}get coordinates(){return l(this.#snapshot.state.coordinates)}get dirty(){return Object.freeze({blueprint:this.#initialDirty.has(`blueprint`)||this.#blueprintSession.dirty,entry:this.#initialDirty.has(`entry`)||this.#entryStateVersion>0,model:this.#initialDirty.has(`model`)||this.#modelStateVersion>0})}get entry(){return l(this.#entry)}get model(){return l(this.#model)}get snapshot(){let e=this.dirty;return l({...this.#snapshot,presentation:{...this.#snapshot.presentation,current:this.#presentation},state:{...this.#snapshot.state,blueprint:this.#blueprintSession.document,dirty:[`model`,`blueprint`,`entry`].filter(t=>e[t]),entry:this.#entry,model:this.#model}})}get stateVersions(){return Object.freeze({blueprint:this.#blueprintSession.stateVersion,entry:this.#entryStateVersion,model:this.#modelStateVersion})}get acceptedSnapshot(){return l(this.#snapshot)}createSaveIntent(e){this.#assertSaveOutcome(e.outcome);let t={contractVersion:this.#snapshot.contractVersion,expected:this.coordinates,kind:`authoring-save-intent`,sessionId:this.#snapshot.sessionId},n;switch(e.outcome){case`save-item`:{let r=e.includeItemBlueprint??!1;if(r&&!this.#allowsItemComposition())throw new p(`invalid-authoring-request`,`This session does not authorize item-local Blueprint composition.`);n={...t,draft:{outcome:`save-item`,entry:this.entry,...r?{itemBlueprint:this.blueprint}:{}}};break}case`save-new-type-version`:if(this.#snapshot.type===void 0)throw new p(`invalid-authoring-request`,`Saving a new type version requires an existing reusable content type.`);n={...t,draft:{blueprint:this.blueprint,model:this.model,outcome:`save-new-type-version`}};break;case`save-as-new-type`:n={...t,draft:{authoringPolicy:l(e.authoringPolicy),blueprint:this.blueprint,label:l(e.label),model:this.model,outcome:`save-as-new-type`}}}if(!A.validate(n))throw new p(`invalid-authoring-request`,`The requested save intent is outside the canonical authoring-save contract.`);return l(n)}executeBlueprint(e){return this.#assertWritableMode(`blueprint`),l(this.#blueprintSession.execute(l(e)))}executeEntry(e){this.#assertWritableMode(`content`),this.#assertCommandFence(e,this.#entry.id,this.#entry.revision,this.#entryStateVersion);let t=d(this.#entry,l(e));return x(t,this.#limits),this.#entry=t,this.#entryStateVersion+=1,this.entry}executeModel(e){this.#assertWritableMode(`model`),this.#assertCommandFence(e,this.#model.id,this.#model.revision,this.#modelStateVersion);let t=ee(this.#model,l(e));return S(t,this.#limits),this.#model=t,this.#modelStateVersion+=1,this.model}setPresentation(e){if(!this.#snapshot.capabilities.presentationStates.includes(e))throw new p(`invalid-authoring-request`,`The resolved contextual session does not support the ${e} presentation.`);return this.#presentation=e,this.#presentation}acceptHostSnapshot(e){b(e.state.blueprint,this.#limits),x(e.state.entry,this.#limits),S(e.state.model,this.#limits);let t=this.#blueprintSession?.selection??[];this.#snapshot=l(e),this.#model=l(e.state.model),this.#entry=l(e.state.entry),this.#presentation=e.presentation.current,this.#modelStateVersion=0,this.#entryStateVersion=0,this.#initialDirty=new Set(e.state.dirty),this.#blueprintSession=new re({document:l(e.state.blueprint),limits:this.#limits,maximumHistoryEntries:this.#maximumHistoryEntries,mode:we(e,this.#readOnly),permissions:this.#permissions,sessionGeneration:e.sessionGeneration}),this.#blueprintSession.markSaved(e.state.blueprint.revision);let n=t.filter(e=>$(this.#blueprintSession.document.roots,e));n.length>0&&this.#blueprintSession.select(n)}#allowsItemComposition(){return this.#snapshot.type===void 0?this.#snapshot.start.kind===`blank`:this.#snapshot.type.authoringPolicy.itemComposition===`overrides`}#assertCommandFence(e,t,n,r){if(e.sessionGeneration!==this.#snapshot.sessionGeneration)throw new u(`stale-generation`,`The command generation does not match the contextual session generation.`);if(e.artifactId!==t)throw new u(`node-not-found`,`Command targets ${e.artifactId}, not ${t}.`);if(e.baseStateVersion!==r)throw new u(`stale-state`,`Command state ${String(e.baseStateVersion)} does not match ${String(r)}.`);if(e.expectedRevision!==void 0&&e.expectedRevision!==n)throw new u(`stale-state`,`Command expects revision ${e.expectedRevision}, but the session holds ${n}.`)}#assertSaveOutcome(e){if(this.#readOnly)throw new p(`read-only-session`,`A read-only contextual session cannot create a save intent.`);if(!this.#snapshot.capabilities.saveOutcomes.includes(e))throw new p(`invalid-authoring-request`,`The resolved contextual session does not support ${e}.`)}#assertWritableMode(e){if(this.#readOnly)throw new u(`read-only-session`,`A read-only contextual session never applies a persistent command.`);if(!this.#snapshot.capabilities.modes.includes(e))throw new u(`mode-forbidden`,`The resolved contextual session does not permit ${e} commands.`)}}class pe{diagnostics;negotiation;resolution;session;types;#authoring;#configuration;#draftSession;#identifiers;#plannedIntents=new Map;#retryIntents=new Map;#disposed=!1;#invalidationFailure;#saveTail=Promise.resolve();constructor(e,t,n,r,i,a){this.#authoring=e,this.#configuration=t,this.#identifiers=n,this.negotiation=Y(r),this.diagnostics=l(r.diagnostics),this.resolution=l(i),this.#draftSession=new fe(a,t),this.session=this.#draftSession,this.types=I(t,T)?Object.freeze({list:e=>this.#listTypes(e)}):void 0}get disposed(){return this.#disposed}get invalidated(){return this.#invalidationFailure!==void 0}dispose(){this.#disposed||(this.#disposed=!0,this.#plannedIntents.clear(),this.#retryIntents.clear(),this.#identifiers.dispose())}async planSave(e){this.#assertActive(),this.#assertCurrentIntent(e);let t=l(e),n=h(this.#configuration,this.#identifiers.requestId(D),{operationId:D}),r=await this.#invoke(()=>this.#authoring.planSave(t,n)),i=H(r,le,`studio.host/unexpected-authoring-save-plan`,`The authoring port returned a malformed save plan.`);return z(i,t),this.#plannedIntents.set(q(i),X(t)),{...U(r)?{revision:r.revision}:{},value:l(i)}}save(e,t,n=[]){try{if(this.#assertActive(),this.#assertCurrentIntent(e),z(t,e),this.#plannedIntents.get(q(t))!==X(e))throw new p(`save-plan-mismatch`,`The save plan was not produced for this exact current intent.`);ye(t,n);let r=l(e),i=l(t),a=be(r,i,n),o=V(r.draft.outcome),s=this.#saveTail.then(()=>this.#commit(o,r,a,i));return this.#saveTail=s.then(()=>void 0,()=>void 0),s}catch(e){return Promise.reject(e instanceof Error?e:Error(`The contextual Studio session failed with a non-Error rejection.`))}}async#commit(e,t,n,r){if(this.#assertActive(),this.#assertCurrentIntent(t),z(r,t),this.#plannedIntents.get(q(r))!==X(t))throw new p(`save-plan-mismatch`,`The save plan is no longer valid for the current contextual draft.`);let i=v(n,this.#configuration),a=this.#mutationKey(e,i),o=h(this.#configuration,this.#identifiers.requestId(e),{idempotencyKey:a,operationId:e}),s=await this.#invoke(()=>{switch(n.kind){case`authoring-save-item-request`:return this.#authoring.saveItem(n,o);case`authoring-save-new-type-version-request`:return this.#authoring.saveNewTypeVersion(n,o);case`authoring-save-as-new-type-request`:return this.#authoring.saveAsNewType(n,o)}}),c=H(s,ue,`studio.host/unexpected-authoring-save-result`,`The authoring port returned a malformed save result.`),u=this.#draftSession.snapshot,d=this.#draftSession.acceptedSnapshot;xe(r,n,c,u,d);let f=Se(c,n,u);return this.#draftSession.acceptHostSnapshot(f.session),this.#plannedIntents.clear(),this.#clearMutationKey(e,i),{...U(s)?{revision:s.revision}:{},value:l(f)}}async#listTypes(e){return this.#assertActive(),j(this.#authoring,this.#configuration,this.#identifiers,this.resolution,e=>this.#invoke(e),e)}#assertCurrentIntent(e){if(!A.validate(e))throw new p(`invalid-authoring-request`,`The save intent is outside the canonical authoring-save contract.`);let t=this.#draftSession.createSaveIntent(Ce(e));if(X(e)!==X(t))throw new p(`save-plan-mismatch`,`The save intent no longer matches the current resource-bound drafts and revisions.`)}#assertActive(){if(this.#invalidationFailure!==void 0)throw this.#invalidationFailure;if(this.#disposed)throw new p(`disposed`,`The contextual Studio session is disposed.`)}#clearMutationKey(e,t){this.#retryIntents.get(e)?.fingerprint===t&&this.#retryIntents.delete(e)}async#invoke(e){this.#assertActive();try{return await e()}catch(e){let t=y(e);throw _(t)&&(this.#invalidationFailure=t),t}}#mutationKey(e,t){let n=this.#retryIntents.get(e);if(n?.fingerprint===t)return n.idempotencyKey;let r=this.#identifiers.idempotencyKey(e,t);return this.#retryIntents.set(e,{fingerprint:t,idempotencyKey:r}),r}}async function j(e,t,n,r,i,a){if(!O.validate(a)||a.targetId!==r.target.id||!Z(a.resourceContext,r.resourceContext))throw new p(`invalid-authoring-request`,`A type query must be canonical and target this exact contextual resource.`);let o=l(a),s=await i(()=>e.listTypes(o,h(t,n.requestId(T),{operationId:T}))),c=H(s,se,`studio.host/unexpected-authoring-type-page`,`The authoring port returned a malformed reusable-type page.`);if(c.items.length>a.limit||Ee(c))throw m(`studio.host/unexpected-authoring-type-page`,`The authoring port returned an oversized or duplicate reusable-type page.`);return{...U(s)?{revision:s.revision}:{},value:l(c)}}function M(e){return ne({$ref:e,$schema:`https://json-schema.org/draft/2020-12/schema`},{schemas:[...ie]})}function N(e,t,n){if(P(e,t),!ce.validate(n))throw new p(`invalid-authoring-request`,`Contextual opening requires a canonical start request.`);if(t.targetId!==n.targetId||!Z(t.resourceContext,n.resourceContext))throw new p(`invalid-authoring-request`,`Target resolution, start, and configuration must bind the same exact resource context.`);let r=n.source.kind===`existing`?`edit`:`create`;if(t.intent!==r)throw new p(`invalid-authoring-request`,`The ${n.source.kind} start requires the ${r} target intent.`);if(t.requestedPresentation!==void 0&&n.presentation!==void 0&&t.requestedPresentation!==n.presentation)throw new p(`invalid-authoring-request`,`The target and start requests name different presentation states.`)}function P(e,t){if(!ae.validate(t)||!Z(t.resourceContext,e.resourceContext))throw new p(`invalid-authoring-request`,`Contextual preflight requires one canonical target bound to the configured resource context.`)}function me(e,t,n){for(let e of[w,E])I(t,e)||n.diagnostics.push(g(`studio.host/missing-required-operation`,`The authoring port does not advertise ${e}.`,`blocking`,{operationId:e}));return e.authoring===void 0&&n.diagnostics.push(g(`studio.host/adapter-port-unavailable`,`The host advertises contextual authoring but the adapter does not implement it.`,`blocking`,{port:C})),e.authoring}function he(e,t,n){if(n.availableStarts.includes(`from-type`)&&F(e,t,T),e.sessionState!==`read-only`){n.target.saveOutcomes.length>0&&F(e,t,D);for(let r of n.target.saveOutcomes)F(e,t,V(r))}}function F(e,t,n){I(e,n)||t.diagnostics.push(g(`studio.host/missing-required-operation`,`The resolved authoring target requires ${n}.`,`blocking`,{operationId:n}))}function I(e,t){return e.hostCapabilities.ports.find(e=>e.id===C)?.operations.includes(t)??!1}function L(e,t){if(e.diagnostics.some(e=>e.severity===`blocking`))throw new p(`configuration-blocked`,t,e.diagnostics)}function ge(e,t,n){let r=n.resourceContext.resource?.type;if(n.target.id!==t.targetId||n.target.surface!==n.resourceContext.surface||!Z(n.resourceContext,t.resourceContext)||!Z(n.resourceContext,e.resourceContext)||!n.target.eligibility.includes(t.intent)||!n.target.presentationStates.includes(n.initialPresentation)||r!==void 0&&!n.target.resourceTypes.includes(r)||t.requestedPresentation!==void 0&&n.initialPresentation!==t.requestedPresentation)throw W(`studio.host/authoring-target-mismatch`,`The resolved target does not match the requested resource, intent, or presentation.`);if(n.availableStarts.some(e=>!n.target.startKinds.includes(e)))throw W(`studio.host/authoring-target-mismatch`,`The target resolution offers a start kind the declaration does not authorize.`)}function _e(e,t){if(!e.availableStarts.includes(t.source.kind)||!e.target.startKinds.includes(t.source.kind)||t.presentation!==void 0&&!e.target.presentationStates.includes(t.presentation))throw new p(`invalid-authoring-request`,`The resolved target does not authorize the requested ${t.source.kind} start and presentation.`)}function ve(e,t,n,r){b(r.state.blueprint,e.limits),x(r.state.entry,e.limits),S(r.state.model,e.limits);let i=n.presentation??t.initialPresentation;if(r.sessionId!==e.sessionId||r.sessionGeneration!==e.sessionGeneration||!Z(r.target,t.target)||!Z(r.resourceContext,t.resourceContext)||!Z(r.start,n.source)||r.presentation.current!==i||!Z(r.presentation.returnContext,t.returnContext)||!Q(r.capabilities.modes,t.target.modes)||!Q(r.capabilities.presentationStates,t.target.presentationStates)||!Q(r.capabilities.saveOutcomes,t.target.saveOutcomes))throw W(`studio.host/authoring-session-mismatch`,`The started session does not preserve its requested target, resource, generation, or capabilities.`);switch(R(r),n.source.kind){case`blank`:if(r.type!==void 0||r.state.coordinates.type!==void 0)throw W(`studio.host/authoring-start-mismatch`,`A blank start cannot silently bind an existing reusable content type.`);break;case`from-type`:if(r.type===void 0||!Z(K(r.type),n.source.type)||!Z(r.state.coordinates.type,n.source.type))throw W(`studio.host/authoring-start-mismatch`,`A from-type start must hydrate the exact requested reusable content type.`);break;case`existing`:if(t.resourceContext.resource===void 0||r.type===void 0||r.state.coordinates.type===void 0)throw W(`studio.host/authoring-start-mismatch`,`An existing-item start requires an exact resource and reusable content type.`)}}function R(e){let{coordinates:t,model:n,blueprint:r,entry:i}=e.state;if(!G(t.model,n)||!G(t.blueprint,r)||t.entry.id!==i.id||t.entry.revision!==i.revision||!Z(r.model,t.model)||!Z(i.model,t.model))throw W(`studio.host/authoring-artifact-coordinate-mismatch`,`The Model, Blueprint, and Entry documents do not match their accepted coordinates.`);if(e.type===void 0?t.type!==void 0:!Z(K(e.type),t.type)||!Z(e.type.model,t.model)||e.type.authoringPolicy.itemComposition===`denied`&&!Z(e.type.blueprint,t.blueprint))throw W(`studio.host/authoring-type-coordinate-mismatch`,`The reusable content type does not match the coordinated artifact coordinates.`)}function z(e,t){if(e.contractVersion!==t.contractVersion||e.sessionId!==t.sessionId||e.outcome!==t.draft.outcome||!Z(e.expected,t.expected))throw new p(`save-plan-mismatch`,`The host save plan does not match the current save intent.`);let n=new Set(e.affectedArtifacts);if(t.draft.outcome===`save-item`){if(!n.has(`entry`)||n.has(`model`)||n.has(`reusable-content-type`)||(t.draft.itemBlueprint===void 0?n.has(`blueprint`):!n.has(`blueprint`)))throw new p(`save-plan-mismatch`,`A save-item plan may affect only the Entry and an explicitly supplied item Blueprint.`)}else if(n.has(`entry`)||!n.has(`model`)||!n.has(`blueprint`)||!n.has(`reusable-content-type`))throw new p(`save-plan-mismatch`,`A reusable-type plan must affect Model, Blueprint, and type, but never Entry values.`)}function ye(e,t){if(new Set(t).size!==t.length)throw new p(`invalid-authoring-request`,`Accepted save consequences must be unique.`);let n=new Set(e.consequences.map(e=>e.code));if(t.some(e=>!n.has(e)))throw new p(`invalid-authoring-request`,`A save request cannot accept a consequence absent from its plan.`);if(e.confirmationRequired&&[...n].some(e=>!t.includes(e)))throw new p(`invalid-authoring-request`,`Every consequence in a confirmation-required plan must be accepted explicitly.`)}function be(e,t,n){let r={acceptedConsequences:[...n],contractVersion:e.contractVersion,plan:J(t)};switch(e.draft.outcome){case`save-item`:return{...r,draft:l(e.draft),kind:`authoring-save-item-request`};case`save-new-type-version`:return{...r,draft:l(e.draft),kind:`authoring-save-new-type-version-request`};case`save-as-new-type`:return{...r,draft:l(e.draft),kind:`authoring-save-as-new-type-request`}}}function xe(e,t,n,r,i){if(n.contractVersion!==r.contractVersion||n.outcome!==e.outcome||!Z(n.plan,J(e))||n.session.sessionId!==r.sessionId||n.session.sessionGeneration!==r.sessionGeneration||n.session.contractVersion!==r.contractVersion||!Z(n.session.target,r.target)||!Z(n.session.resourceContext,r.resourceContext)||!Z(n.session.start,r.start)||!Z(n.session.capabilities,r.capabilities)||n.session.presentation.current!==i.presentation.current&&n.session.presentation.current!==r.presentation.current||!Z(n.session.presentation.returnContext,e.successorContext)||n.session.contributionGeneration!==r.contributionGeneration)throw m(`studio.host/unexpected-authoring-save-result`,`The save result does not reconcile the planned resource-bound session.`);if(R(n.session),t.kind===`authoring-save-item-request`){if(!Z(n.session.state.coordinates.model,i.state.coordinates.model)||!Z(n.session.state.model,i.state.model)&&!Z(n.session.state.model,r.state.model)||t.draft.itemBlueprint===void 0&&(!Z(n.session.state.coordinates.blueprint,i.state.coordinates.blueprint)||!Z(n.session.state.blueprint,i.state.blueprint)&&!Z(n.session.state.blueprint,r.state.blueprint)))throw m(`studio.host/unexpected-unaffected-artifact-mutation`,`A save-item result changed a Model or reusable Blueprint excluded from the request.`);if(!Z(n.session.type,r.type))throw m(`studio.host/unexpected-type-mutation`,`A save-item result changed the reusable content type excluded from the request.`)}else{let e=B(n.session.state.entry);if(!Z(e,B(i.state.entry))&&!Z(e,B(r.state.entry)))throw m(`studio.host/unexpected-entry-mutation`,`A reusable-type save result changed Entry values or item-only state excluded from the request.`);let a=n.session.type;if(a===void 0)throw m(`studio.host/missing-accepted-content-type`,`A reusable-type save result did not return its accepted content type.`);if(t.kind===`authoring-save-new-type-version-request`){let e=r.type;if(a.id!==e?.id||a.version===e?.version||a.revision===e?.revision||a.model.id!==e?.model.id||a.model.revision===e?.model.revision||a.blueprint.id!==e?.blueprint.id||a.blueprint.revision===e?.blueprint.revision)throw m(`studio.host/invalid-type-successor`,`A save-new-type-version result must return immutable successor type, Model, and Blueprint coordinates.`)}else if(a.id===r.type?.id)throw m(`studio.host/invalid-new-type-identity`,`A save-as-new-type result must return a distinct reusable content type identity.`)}}function B(e){return{...e.compositionOverrides===void 0?{}:{compositionOverrides:e.compositionOverrides},...e.extensions===void 0?{}:{extensions:e.extensions},id:e.id,...e.locale===void 0?{}:{locale:e.locale},status:e.status,...e.translationOf===void 0?{}:{translationOf:e.translationOf},values:e.values,...e.workflowState===void 0?{}:{workflowState:e.workflowState}}}function Se(e,t,n){let r=l(e);r.session.presentation.current=n.presentation.current;let i=new Set(r.session.state.dirty);if(t.kind===`authoring-save-item-request`)r.session.state.model=l(n.state.model),n.state.dirty.includes(`model`)&&i.add(`model`),t.draft.itemBlueprint===void 0&&(r.session.state.blueprint=l(n.state.blueprint),n.state.dirty.includes(`blueprint`)&&i.add(`blueprint`));else{let e=r.session.state.entry,t=n.state.entry,a={...t.compositionOverrides===void 0?{}:{compositionOverrides:l(t.compositionOverrides)},contractVersion:e.contractVersion,...t.extensions===void 0?{}:{extensions:l(t.extensions)},id:t.id,kind:`entry`,...t.locale===void 0?{}:{locale:t.locale},model:l(e.model),revision:e.revision,status:t.status,...t.translationOf===void 0?{}:{translationOf:t.translationOf},values:l(t.values),...t.workflowState===void 0?{}:{workflowState:t.workflowState}};r.session.state.entry=a,n.state.dirty.includes(`entry`)&&i.add(`entry`)}return r.session.state.dirty=[`model`,`blueprint`,`entry`].filter(e=>i.has(e)),r}function Ce(e){switch(e.draft.outcome){case`save-item`:return{includeItemBlueprint:e.draft.itemBlueprint!==void 0,outcome:`save-item`};case`save-new-type-version`:return{outcome:`save-new-type-version`};case`save-as-new-type`:return{authoringPolicy:l(e.draft.authoringPolicy),label:l(e.draft.label),outcome:`save-as-new-type`}}}function V(e){switch(e){case`save-item`:return`studio.operation/authoring.save-item`;case`save-new-type-version`:return`studio.operation/authoring.save-new-type-version`;case`save-as-new-type`:return`studio.operation/authoring.save-as-new-type`}}function we(e,t){return t?`read-only`:e.capabilities.modes.includes(`blueprint`)?`blueprint`:e.capabilities.modes.includes(`content`)?`hybrid`:`read-only`}function H(e,t,n,r){if(typeof e!=`object`||!e||Array.isArray(e)||!Object.hasOwn(e,`value`)||!t.validate(e.value))throw m(n,r);return l(e.value)}function U(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&`revision`in e&&typeof e.revision==`string`&&e.revision.length>=1&&e.revision.length<=200}async function Te(e){try{return await e()}catch(e){throw y(e)}}function W(e,t){return m(e,t)}function G(e,t){return e.id===t.id&&e.version===t.version&&e.revision===t.revision}function K(e){return{id:e.id,revision:e.revision,version:e.version}}function q(e){return X(J(e))}function J(e){return{id:e.id,revision:e.revision,successorContext:l(e.successorContext)}}function Ee(e){let t=new Set;for(let n of e.items){let e=`${n.reference.id}\u0000${n.reference.version}\u0000${n.reference.revision}`;if(t.has(e))return!0;t.add(e)}return!1}function Y(e){return{availablePorts:[...e.availablePorts],diagnostics:l(e.diagnostics),missingOptionalPorts:[...e.missingOptionalPorts],missingRequiredPorts:[...e.missingRequiredPorts],...e.protocolVersion===void 0?{}:{protocolVersion:e.protocolVersion},sessionState:e.sessionState}}function X(e){return c(e)}function Z(e,t){return X(e)===X(t)}function Q(e,t){return e.every(e=>t.includes(e))}function $(e,t){for(let n of e){if(n.id===t)return!0;for(let e of Object.values(n.slots))if($(e,t))return!0}return!1}
|
package/dist/contributions.d.ts
CHANGED
|
@@ -1,7 +1,31 @@
|
|
|
1
|
-
import type { BlockDefinition, BlockType, BlueprintDocument, ExtensionLifecycleState, NodeId, OwnerReference, Revision, StudioDiagnostic, UnresolvedContribution, UnresolvedContributionReason } from '@kumwe/studio-protocol';
|
|
1
|
+
import type { AuthoringTargetDeclaration, AuthoringTargetResolveRequest, BlockDefinition, BlockType, BlueprintDocument, DesignVocabulary, ExtensionLifecycleState, FieldAdapterContribution, HostFeatureCapability, InspectorContribution, MigrationDeclaration, NodeId, OwnerReference, PatternDocument, Revision, StudioDiagnostic, UnresolvedContribution, UnresolvedContributionReference, UnresolvedContributionReason } from '@kumwe/studio-protocol';
|
|
2
2
|
import { BlockRegistry } from './registry.js';
|
|
3
3
|
export interface ExtensionContributions {
|
|
4
|
+
authoringTargets?: AuthoringTargetDeclaration[];
|
|
4
5
|
blocks: BlockDefinition[];
|
|
6
|
+
designVocabularies?: DesignVocabulary[];
|
|
7
|
+
fieldAdapters?: FieldAdapterContribution[];
|
|
8
|
+
inspectors?: InspectorContribution[];
|
|
9
|
+
migrations?: MigrationDeclaration[];
|
|
10
|
+
patterns?: PatternDocument[];
|
|
11
|
+
}
|
|
12
|
+
export type StudioCompositionContributionKind = 'block' | 'design-vocabulary' | 'field-adapter' | 'inspector' | 'migration' | 'pattern';
|
|
13
|
+
/**
|
|
14
|
+
* Every canonical payload admitted to an immutable contribution generation.
|
|
15
|
+
* Authoring targets are discovery declarations rather than page composition,
|
|
16
|
+
* so they intentionally remain outside `StudioCompositionContributionKind`.
|
|
17
|
+
*/
|
|
18
|
+
export type StudioLifecycleContributionKind = 'authoring-target' | StudioCompositionContributionKind;
|
|
19
|
+
export type StudioCompositionContribution = BlockDefinition | DesignVocabulary | FieldAdapterContribution | InspectorContribution | MigrationDeclaration | PatternDocument;
|
|
20
|
+
export type StudioLifecycleContribution = AuthoringTargetDeclaration | StudioCompositionContribution;
|
|
21
|
+
export interface AuthoringTargetRuntimeOptions {
|
|
22
|
+
capabilities: readonly HostFeatureCapability[];
|
|
23
|
+
mode?: 'blueprint' | 'content' | 'model';
|
|
24
|
+
}
|
|
25
|
+
export interface ResolvedAuthoringTarget {
|
|
26
|
+
/** Only dependencies explicitly admitted by this target are returned. */
|
|
27
|
+
contributions: readonly StudioCompositionContribution[];
|
|
28
|
+
target: AuthoringTargetDeclaration;
|
|
5
29
|
}
|
|
6
30
|
export interface ExtensionInventory {
|
|
7
31
|
diagnostics: StudioDiagnostic[];
|
|
@@ -22,18 +46,39 @@ export declare class StudioContributionError extends Error {
|
|
|
22
46
|
readonly diagnostics: StudioDiagnostic[];
|
|
23
47
|
constructor(message: string, diagnostics: StudioDiagnostic[]);
|
|
24
48
|
}
|
|
49
|
+
interface ContributionEntry {
|
|
50
|
+
id: string;
|
|
51
|
+
kind: StudioLifecycleContributionKind;
|
|
52
|
+
owner: OwnerReference;
|
|
53
|
+
payload: StudioLifecycleContribution;
|
|
54
|
+
version: string;
|
|
55
|
+
}
|
|
25
56
|
/**
|
|
26
57
|
* One immutable, resolvable registry generation. A generation never changes
|
|
27
58
|
* after publication; lifecycle transitions publish a successor instead.
|
|
28
59
|
*/
|
|
29
60
|
export declare class RegistryGeneration {
|
|
30
61
|
#private;
|
|
31
|
-
constructor(generation: Revision, owners: readonly OwnerReference[], registry: BlockRegistry);
|
|
62
|
+
constructor(generation: Revision, owners: readonly OwnerReference[], registry: BlockRegistry, contributions?: readonly ContributionEntry[]);
|
|
32
63
|
get generation(): Revision;
|
|
33
64
|
get registry(): BlockRegistry;
|
|
34
65
|
blocks(): BlockDefinition[];
|
|
35
66
|
owners(): OwnerReference[];
|
|
36
67
|
resolveBlock(type: BlockType, version: string): BlockDefinition | undefined;
|
|
68
|
+
/** Resolve a canonical lifecycle payload by exact kind, identity, and version. */
|
|
69
|
+
resolveContribution(kind: StudioLifecycleContributionKind, id: string, version: string): StudioLifecycleContribution | undefined;
|
|
70
|
+
/** Enumerate one canonical kind in deterministic identity/version order. */
|
|
71
|
+
contributions(kind: StudioCompositionContributionKind): StudioCompositionContribution[];
|
|
72
|
+
/** Enumerate active core and extension targets in deterministic identity order. */
|
|
73
|
+
authoringTargets(): AuthoringTargetDeclaration[];
|
|
74
|
+
/**
|
|
75
|
+
* Resolve one contextual target against the same immutable generation used
|
|
76
|
+
* for all six composition families. This is deterministic discovery only:
|
|
77
|
+
* a successful result neither authorizes the actor nor mints a resource
|
|
78
|
+
* context. The host must still perform both duties through its authoring
|
|
79
|
+
* port before a session can open.
|
|
80
|
+
*/
|
|
81
|
+
resolveAuthoringTarget(request: Readonly<AuthoringTargetResolveRequest>, options: Readonly<AuthoringTargetRuntimeOptions>): ResolvedAuthoringTarget | undefined;
|
|
37
82
|
}
|
|
38
83
|
/**
|
|
39
84
|
* The owner-aware contribution runtime. Activation is transactional: a
|
|
@@ -51,6 +96,12 @@ export declare class ContributionRuntime {
|
|
|
51
96
|
disable(ownerId: string, options: Readonly<GenerationOptions>): RegistryGeneration;
|
|
52
97
|
reactivate(ownerId: string, options: Readonly<GenerationOptions>): RegistryGeneration;
|
|
53
98
|
revokeTrust(ownerId: string, options: Readonly<GenerationOptions>): RegistryGeneration;
|
|
99
|
+
/**
|
|
100
|
+
* Remove all executable resolution for an extension while retaining its
|
|
101
|
+
* owned payload inventory for unresolved diagnostics and later migration.
|
|
102
|
+
* A fresh verified activation is required before it can contribute again.
|
|
103
|
+
*/
|
|
104
|
+
uninstall(ownerId: string, options: Readonly<GenerationOptions>): RegistryGeneration;
|
|
54
105
|
assertCurrent(generation: Revision): RegistryGeneration;
|
|
55
106
|
inventory(): ExtensionInventory[];
|
|
56
107
|
unresolvedNodes(document: BlueprintDocument): UnresolvedNodeReport[];
|
|
@@ -61,5 +112,15 @@ export declare class ContributionRuntime {
|
|
|
61
112
|
* owner.
|
|
62
113
|
*/
|
|
63
114
|
unresolvedContributions(document: BlueprintDocument): UnresolvedContribution[];
|
|
115
|
+
/**
|
|
116
|
+
* Resolve the lifecycle reason for any canonical contribution reference.
|
|
117
|
+
* Identity is kind-scoped, so a pattern can never satisfy a field-adapter
|
|
118
|
+
* reference merely because their IDs and versions match.
|
|
119
|
+
*/
|
|
120
|
+
unresolvedReference(reference: UnresolvedContributionReference): {
|
|
121
|
+
owner?: OwnerReference;
|
|
122
|
+
reason: UnresolvedContributionReason;
|
|
123
|
+
} | undefined;
|
|
64
124
|
}
|
|
125
|
+
export {};
|
|
65
126
|
//# sourceMappingURL=contributions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contributions.d.ts","sourceRoot":"","sources":["../src/contributions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"contributions.d.ts","sourceRoot":"","sources":["../src/contributions.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,6BAA6B,EAC7B,eAAe,EACf,SAAS,EACT,iBAAiB,EAEjB,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,MAAM,EACN,cAAc,EACd,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,sBAAsB,EACtB,+BAA+B,EAC/B,4BAA4B,EAC7B,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAK9C,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,CAAC,EAAE,0BAA0B,EAAE,CAAC;IAChD,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACxC,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;IAC3C,UAAU,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACrC,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAC9B;AAYD,MAAM,MAAM,iCAAiC,GAC3C,OAAO,GAAG,mBAAmB,GAAG,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,SAAS,CAAC;AAE1F;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GACzC,kBAAkB,GAAG,iCAAiC,CAAC;AAEzD,MAAM,MAAM,6BAA6B,GACrC,eAAe,GACf,gBAAgB,GAChB,wBAAwB,GACxB,qBAAqB,GACrB,oBAAoB,GACpB,eAAe,CAAC;AAEpB,MAAM,MAAM,2BAA2B,GACrC,0BAA0B,GAAG,6BAA6B,CAAC;AAE7D,MAAM,WAAW,6BAA6B;IAC5C,YAAY,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC/C,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;CAC1C;AAED,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,aAAa,EAAE,SAAS,6BAA6B,EAAE,CAAC;IACxD,MAAM,EAAE,0BAA0B,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,uBAAuB,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,QAAQ,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,4BAA4B,CAAC;IACrC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAgB,WAAW,EAAE,gBAAgB,EAAE,CAAC;gBAE7B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE;CAKpE;AASD,UAAU,iBAAiB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,+BAA+B,CAAC;IACtC,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,2BAA2B,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAgBD;;;GAGG;AACH,qBAAa,kBAAkB;;gBAO3B,UAAU,EAAE,QAAQ,EACpB,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,QAAQ,EAAE,aAAa,EACvB,aAAa,GAAE,SAAS,iBAAiB,EAAO;IAalD,IAAW,UAAU,IAAI,QAAQ,CAEhC;IAED,IAAW,QAAQ,IAAI,aAAa,CAEnC;IAEM,MAAM,IAAI,eAAe,EAAE;IAI3B,MAAM,IAAI,cAAc,EAAE;IAI1B,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIlF,kFAAkF;IAC3E,mBAAmB,CACxB,IAAI,EAAE,+BAA+B,EACrC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,2BAA2B,GAAG,SAAS;IAQ1C,4EAA4E;IACrE,aAAa,CAAC,IAAI,EAAE,iCAAiC,GAAG,6BAA6B,EAAE;IAW9F,mFAAmF;IAC5E,gBAAgB,IAAI,0BAA0B,EAAE;IAQvD;;;;;;OAMG;IACI,sBAAsB,CAC3B,OAAO,EAAE,QAAQ,CAAC,6BAA6B,CAAC,EAChD,OAAO,EAAE,QAAQ,CAAC,6BAA6B,CAAC,GAC/C,uBAAuB,GAAG,SAAS;CAgCvC;AAiBD;;;;;;;GAOG;AACH,qBAAa,mBAAmB;;gBAIX,OAAO,EAAE,QAAQ,CAAC,iBAAiB,CAAC;IAIvD,IAAW,OAAO,IAAI,kBAAkB,CAEvC;IAEM,QAAQ,CACb,KAAK,EAAE,cAAc,EACrB,aAAa,EAAE,QAAQ,CAAC,sBAAsB,CAAC,EAC/C,OAAO,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GACnC,kBAAkB;IA8Bd,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,kBAAkB;IAalF,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,kBAAkB;IAarF,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,kBAAkB;IAU7F;;;;OAIG;IACI,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,kBAAkB;IAOpF,aAAa,CAAC,UAAU,EAAE,QAAQ,GAAG,kBAAkB;IAUvD,SAAS,IAAI,kBAAkB,EAAE;IAUjC,eAAe,CAAC,QAAQ,EAAE,iBAAiB,GAAG,oBAAoB,EAAE;IA4B3E;;;;;OAKG;IACI,uBAAuB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,sBAAsB,EAAE;IAiCrF;;;;OAIG;IACI,mBAAmB,CACxB,SAAS,EAAE,+BAA+B,GACzC;QAAE,KAAK,CAAC,EAAE,cAAc,CAAC;QAAC,MAAM,EAAE,4BAA4B,CAAA;KAAE,GAAG,SAAS;CAoLhF"}
|
package/dist/contributions.js
CHANGED
|
@@ -1,302 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { cloneContractValue } from './clone.js';
|
|
3
|
-
import { StudioCommandError } from './commands.js';
|
|
4
|
-
import { BlockRegistry } from './registry.js';
|
|
5
|
-
export class StudioContributionError extends Error {
|
|
6
|
-
diagnostics;
|
|
7
|
-
constructor(message, diagnostics) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = 'StudioContributionError';
|
|
10
|
-
this.diagnostics = diagnostics;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* One immutable, resolvable registry generation. A generation never changes
|
|
15
|
-
* after publication; lifecycle transitions publish a successor instead.
|
|
16
|
-
*/
|
|
17
|
-
export class RegistryGeneration {
|
|
18
|
-
#generation;
|
|
19
|
-
#owners;
|
|
20
|
-
#registry;
|
|
21
|
-
constructor(generation, owners, registry) {
|
|
22
|
-
this.#generation = generation;
|
|
23
|
-
this.#owners = owners;
|
|
24
|
-
this.#registry = registry;
|
|
25
|
-
}
|
|
26
|
-
get generation() {
|
|
27
|
-
return this.#generation;
|
|
28
|
-
}
|
|
29
|
-
get registry() {
|
|
30
|
-
return this.#registry;
|
|
31
|
-
}
|
|
32
|
-
blocks() {
|
|
33
|
-
return this.#registry.definitions();
|
|
34
|
-
}
|
|
35
|
-
owners() {
|
|
36
|
-
return this.#owners.map((owner) => cloneContractValue(owner));
|
|
37
|
-
}
|
|
38
|
-
resolveBlock(type, version) {
|
|
39
|
-
return this.#registry.resolve(type, version);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
class SealedBlockRegistry extends BlockRegistry {
|
|
43
|
-
#sealed = false;
|
|
44
|
-
seal() {
|
|
45
|
-
this.#sealed = true;
|
|
46
|
-
}
|
|
47
|
-
register(...parameters) {
|
|
48
|
-
if (this.#sealed) {
|
|
49
|
-
throw new Error('A published registry generation is immutable.');
|
|
50
|
-
}
|
|
51
|
-
super.register(...parameters);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* The owner-aware contribution runtime. Activation is transactional: a
|
|
56
|
-
* rejected activation publishes no partial generation and never disturbs a
|
|
57
|
-
* previously active extension. Every successful transition publishes a new
|
|
58
|
-
* immutable generation; disabling an owner removes its executable
|
|
59
|
-
* contributions from resolution without touching stored documents, and a
|
|
60
|
-
* stale generation cannot be used for execution.
|
|
61
|
-
*/
|
|
62
|
-
export class ContributionRuntime {
|
|
63
|
-
#extensions = new Map();
|
|
64
|
-
#current;
|
|
65
|
-
constructor(options) {
|
|
66
|
-
this.#current = this.#publish(options.generation);
|
|
67
|
-
}
|
|
68
|
-
get current() {
|
|
69
|
-
return this.#current;
|
|
70
|
-
}
|
|
71
|
-
activate(owner, contributions, options) {
|
|
72
|
-
const candidate = cloneContractValue(contributions);
|
|
73
|
-
const diagnostics = this.#collectActivationDiagnostics(owner, candidate);
|
|
74
|
-
if (diagnostics.length > 0) {
|
|
75
|
-
if (!this.#extensions.has(owner.id)) {
|
|
76
|
-
this.#extensions.set(owner.id, {
|
|
77
|
-
contributions: { blocks: [] },
|
|
78
|
-
diagnostics,
|
|
79
|
-
owner: cloneContractValue(owner),
|
|
80
|
-
state: 'rejected',
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
throw new StudioContributionError(`Activation of ${owner.id} was rejected: ${diagnostics
|
|
84
|
-
.map((diagnostic) => diagnostic.code)
|
|
85
|
-
.join(', ')}.`, diagnostics);
|
|
86
|
-
}
|
|
87
|
-
this.#extensions.set(owner.id, {
|
|
88
|
-
contributions: candidate,
|
|
89
|
-
diagnostics: [],
|
|
90
|
-
owner: cloneContractValue(owner),
|
|
91
|
-
state: 'active',
|
|
92
|
-
});
|
|
93
|
-
this.#current = this.#publish(options.generation);
|
|
94
|
-
return this.#current;
|
|
95
|
-
}
|
|
96
|
-
disable(ownerId, options) {
|
|
97
|
-
const record = this.#requireExtension(ownerId);
|
|
98
|
-
record.state = 'disabled';
|
|
99
|
-
this.#current = this.#publish(options.generation);
|
|
100
|
-
return this.#current;
|
|
101
|
-
}
|
|
102
|
-
reactivate(ownerId, options) {
|
|
103
|
-
const record = this.#requireExtension(ownerId);
|
|
104
|
-
if (record.state === 'trust-revoked') {
|
|
105
|
-
throw new StudioContributionError(`Extension ${ownerId} is trust-revoked and requires a fresh verified activation.`, record.diagnostics);
|
|
106
|
-
}
|
|
107
|
-
record.state = 'active';
|
|
108
|
-
this.#current = this.#publish(options.generation);
|
|
109
|
-
return this.#current;
|
|
110
|
-
}
|
|
111
|
-
revokeTrust(ownerId, options) {
|
|
112
|
-
const record = this.#requireExtension(ownerId);
|
|
113
|
-
record.state = 'trust-revoked';
|
|
114
|
-
// Contribution DATA is retained for the diagnostics inventory the
|
|
115
|
-
// lifecycle contract requires; only resolution excludes it, because a
|
|
116
|
-
// published generation includes active extensions exclusively.
|
|
117
|
-
this.#current = this.#publish(options.generation);
|
|
118
|
-
return this.#current;
|
|
119
|
-
}
|
|
120
|
-
assertCurrent(generation) {
|
|
121
|
-
if (this.#current.generation !== generation) {
|
|
122
|
-
throw new StudioCommandError('stale-generation', `Registry generation ${generation} is stale; the active generation is ${this.#current.generation}.`);
|
|
123
|
-
}
|
|
124
|
-
return this.#current;
|
|
125
|
-
}
|
|
126
|
-
inventory() {
|
|
127
|
-
return [...this.#extensions.values()]
|
|
128
|
-
.map((record) => ({
|
|
129
|
-
diagnostics: cloneContractValue(record.diagnostics),
|
|
130
|
-
owner: cloneContractValue(record.owner),
|
|
131
|
-
state: record.state,
|
|
132
|
-
}))
|
|
133
|
-
.sort((left, right) => (left.owner.id < right.owner.id ? -1 : 1));
|
|
134
|
-
}
|
|
135
|
-
unresolvedNodes(document) {
|
|
136
|
-
const unresolved = [];
|
|
137
|
-
const stack = [...document.roots].reverse();
|
|
138
|
-
while (stack.length > 0) {
|
|
139
|
-
const node = stack.pop();
|
|
140
|
-
if (node === undefined) {
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
if (this.#current.resolveBlock(node.type, node.version) === undefined) {
|
|
144
|
-
const { owner, reason } = this.#unresolvedReason(node.type, node.version);
|
|
145
|
-
const report = {
|
|
146
|
-
nodeId: node.id,
|
|
147
|
-
reason,
|
|
148
|
-
type: node.type,
|
|
149
|
-
version: node.version,
|
|
150
|
-
};
|
|
151
|
-
if (owner !== undefined) {
|
|
152
|
-
report.owner = cloneContractValue(owner);
|
|
153
|
-
}
|
|
154
|
-
unresolved.push(report);
|
|
155
|
-
}
|
|
156
|
-
for (const children of Object.values(node.slots)) {
|
|
157
|
-
stack.push(...[...children].reverse());
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return unresolved;
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* The portable unresolved-contribution documents for a Blueprint: one per
|
|
164
|
-
* unresolved block type and version, carrying the affected nodes and a
|
|
165
|
-
* localizable diagnostic, without interpreting node data through another
|
|
166
|
-
* owner.
|
|
167
|
-
*/
|
|
168
|
-
unresolvedContributions(document) {
|
|
169
|
-
const grouped = new Map();
|
|
170
|
-
for (const report of this.unresolvedNodes(document)) {
|
|
171
|
-
const key = `${report.type}@${report.version}`;
|
|
172
|
-
let entry = grouped.get(key);
|
|
173
|
-
if (entry === undefined) {
|
|
174
|
-
entry = {
|
|
175
|
-
affectedNodes: [],
|
|
176
|
-
contractVersion: STUDIO_CONTRACT_VERSION,
|
|
177
|
-
diagnostics: [
|
|
178
|
-
{
|
|
179
|
-
code: 'studio.validation/block-unavailable',
|
|
180
|
-
message: {
|
|
181
|
-
defaultMessage: `The ${report.type} block is currently unavailable; its content is preserved.`,
|
|
182
|
-
key: 'studio.validation/block-unavailable',
|
|
183
|
-
},
|
|
184
|
-
severity: 'warning',
|
|
185
|
-
},
|
|
186
|
-
],
|
|
187
|
-
kind: 'unresolved-contribution',
|
|
188
|
-
reason: report.reason,
|
|
189
|
-
reference: { contribution: 'block', id: report.type, version: report.version },
|
|
190
|
-
};
|
|
191
|
-
if (report.owner !== undefined) {
|
|
192
|
-
entry.owner = report.owner;
|
|
193
|
-
}
|
|
194
|
-
grouped.set(key, entry);
|
|
195
|
-
}
|
|
196
|
-
entry.affectedNodes?.push(report.nodeId);
|
|
197
|
-
}
|
|
198
|
-
return [...grouped.values()];
|
|
199
|
-
}
|
|
200
|
-
#unresolvedReason(type, version) {
|
|
201
|
-
for (const record of this.#extensions.values()) {
|
|
202
|
-
const versions = record.contributions.blocks
|
|
203
|
-
.filter((block) => block.type === type)
|
|
204
|
-
.map((block) => block.version);
|
|
205
|
-
if (versions.length === 0) {
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
if (!versions.includes(version)) {
|
|
209
|
-
return { owner: record.owner, reason: 'incompatible' };
|
|
210
|
-
}
|
|
211
|
-
if (record.state === 'trust-revoked') {
|
|
212
|
-
return { owner: record.owner, reason: 'owner-revoked' };
|
|
213
|
-
}
|
|
214
|
-
return { owner: record.owner, reason: 'owner-disabled' };
|
|
215
|
-
}
|
|
216
|
-
return { reason: 'not-installed' };
|
|
217
|
-
}
|
|
218
|
-
#collectActivationDiagnostics(owner, candidate) {
|
|
219
|
-
const diagnostics = [];
|
|
220
|
-
const seen = new Set();
|
|
221
|
-
for (const block of candidate.blocks) {
|
|
222
|
-
if (block.owner.id !== owner.id || block.owner.version !== owner.version) {
|
|
223
|
-
diagnostics.push(activationDiagnostic('studio.contribution/owner-mismatch', `Block ${block.type} declares owner ${block.owner.id}@${block.owner.version}.`));
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
const key = `${block.type}@${block.version}`;
|
|
227
|
-
if (seen.has(key)) {
|
|
228
|
-
diagnostics.push(activationDiagnostic('studio.contribution/duplicate-contribution', `Block ${key} is contributed twice by ${owner.id}.`));
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
seen.add(key);
|
|
232
|
-
const conflictingOwner = this.#ownerOfBlockType(block.type, owner.id);
|
|
233
|
-
if (conflictingOwner !== undefined) {
|
|
234
|
-
diagnostics.push(activationDiagnostic('studio.contribution/cross-owner-collision', `Block type ${block.type} is owned by ${conflictingOwner}.`));
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
if (diagnostics.length === 0) {
|
|
238
|
-
try {
|
|
239
|
-
const dryRun = new SealedBlockRegistry();
|
|
240
|
-
for (const record of this.#extensions.values()) {
|
|
241
|
-
if (record.state !== 'active' || record.owner.id === owner.id) {
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
for (const block of record.contributions.blocks) {
|
|
245
|
-
dryRun.register(cloneContractValue(block));
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
for (const block of candidate.blocks) {
|
|
249
|
-
dryRun.register(cloneContractValue(block));
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
catch (error) {
|
|
253
|
-
diagnostics.push(activationDiagnostic('studio.contribution/invalid-definition', error instanceof Error ? error.message : 'A contributed definition is invalid.'));
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return diagnostics;
|
|
257
|
-
}
|
|
258
|
-
#ownerOfBlockType(type, exceptOwnerId) {
|
|
259
|
-
for (const record of this.#extensions.values()) {
|
|
260
|
-
if (record.owner.id === exceptOwnerId) {
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
if (record.state === 'purged' || record.state === 'uninstalled-data-preserved') {
|
|
264
|
-
continue;
|
|
265
|
-
}
|
|
266
|
-
if (record.contributions.blocks.some((block) => block.type === type)) {
|
|
267
|
-
return record.owner.id;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return undefined;
|
|
271
|
-
}
|
|
272
|
-
#publish(generation) {
|
|
273
|
-
const registry = new SealedBlockRegistry();
|
|
274
|
-
const owners = [];
|
|
275
|
-
for (const record of this.#extensions.values()) {
|
|
276
|
-
if (record.state !== 'active') {
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
279
|
-
owners.push(cloneContractValue(record.owner));
|
|
280
|
-
for (const block of record.contributions.blocks) {
|
|
281
|
-
registry.register(cloneContractValue(block));
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
registry.seal();
|
|
285
|
-
return new RegistryGeneration(generation, owners, registry);
|
|
286
|
-
}
|
|
287
|
-
#requireExtension(ownerId) {
|
|
288
|
-
const record = this.#extensions.get(ownerId);
|
|
289
|
-
if (record === undefined) {
|
|
290
|
-
throw new StudioContributionError(`Extension ${ownerId} is not known to the contribution runtime.`, []);
|
|
291
|
-
}
|
|
292
|
-
return record;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
function activationDiagnostic(code, message) {
|
|
296
|
-
return {
|
|
297
|
-
code,
|
|
298
|
-
message: { defaultMessage: message, key: 'studio.contribution/activation' },
|
|
299
|
-
severity: 'blocking',
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
//# sourceMappingURL=contributions.js.map
|
|
1
|
+
import{authoringTargetSchema as e,blockDefinitionSchema as t,blueprintSchema as n,commonSchema as r,designVocabularySchema as i,fieldAdapterSchema as a,inspectorSchema as o,migrationSchema as s,patternSchema as c,STUDIO_CONTRACT_VERSION as l}from"@kumwe/studio-protocol";import{cloneContractValue as u}from"./clone.js";import{StudioCommandError as d}from"./commands.js";import{BlockRegistry as f}from"./registry.js";import{compileProfileSchema as p}from"./profile-validator.js";import{assertStudioPropertySchema as m}from"./schema-profile.js";import{compareSemanticVersions as h,satisfiesVersionRange as g}from"./semver.js";export class StudioContributionError extends Error{diagnostics;constructor(e,t){super(e),this.name=`StudioContributionError`,this.diagnostics=t}}const _={"authoring-target":p(e,{schemas:[r]}),block:p(t,{schemas:[r]}),"design-vocabulary":p(i,{schemas:[r]}),"field-adapter":p(a,{schemas:[r]}),inspector:p(o,{schemas:[r]}),migration:p(s,{schemas:[r]}),pattern:p(c,{schemas:[r,n]})};export class RegistryGeneration{#contributions;#generation;#owners;#registry;constructor(e,t,n,r=[]){this.#contributions=new Map(r.map(e=>[x(e.kind,e.id,e.version),u(e.payload)])),this.#generation=e,this.#owners=t,this.#registry=n}get generation(){return this.#generation}get registry(){return this.#registry}blocks(){return this.#registry.definitions()}owners(){return this.#owners.map(e=>u(e))}resolveBlock(e,t){return this.#registry.resolve(e,t)}resolveContribution(e,t,n){if(e===`block`)return this.resolveBlock(t,n);let r=this.#contributions.get(x(e,t,n));return r===void 0?void 0:u(r)}contributions(e){if(e===`block`)return this.blocks();let t=`${e}\u0000`;return[...this.#contributions.entries()].filter(([e])=>e.startsWith(t)).sort(([e],[t])=>e.localeCompare(t)).map(([,e])=>u(e))}authoringTargets(){return[...this.#contributions.entries()].filter(([e])=>e.startsWith(`authoring-target\0`)).sort(([e],[t])=>e.localeCompare(t)).map(([,e])=>u(e))}resolveAuthoringTarget(e,t){let n=this.authoringTargets().find(t=>t.id===e.targetId);if(n===void 0||!T(n,e,t))return;let r=[];for(let e of n.contributionDependencies){let t=this.#resolveDependency(e);if(t===void 0){if(e.required)return;continue}r.push(t)}return{contributions:u(r),target:u(n)}}#resolveDependency(e){let t=C(e.kind);return w(this.#contributions,t,e.id).filter(t=>g(t.version,e.versions)).sort((e,t)=>h(t.version,e.version))[0]?.payload}}class v extends f{#sealed=!1;seal(){this.#sealed=!0}register(...e){if(this.#sealed)throw Error(`A published registry generation is immutable.`);super.register(...e)}}export class ContributionRuntime{#extensions=new Map;#current;constructor(e){this.#current=this.#publish(e.generation)}get current(){return this.#current}activate(e,t,n){let r=y(t),i=this.#collectActivationDiagnostics(e,r);if(i.length>0)throw this.#extensions.has(e.id)||this.#extensions.set(e.id,{contributions:y({blocks:[]}),diagnostics:i,owner:u(e),state:`rejected`}),new StudioContributionError(`Activation of ${e.id} was rejected: ${i.map(e=>e.code).join(`, `)}.`,i);return this.#extensions.set(e.id,{contributions:r,diagnostics:[],owner:u(e),state:`active`}),this.#current=this.#publish(n.generation),this.#current}disable(e,t){let n=this.#requireExtension(e);if(n.state!==`active`&&n.state!==`disabled`)throw new StudioContributionError(`Extension ${e} cannot be disabled from lifecycle state ${n.state}.`,n.diagnostics);return n.state=`disabled`,this.#current=this.#publish(t.generation),this.#current}reactivate(e,t){let n=this.#requireExtension(e);if(n.state!==`disabled`)throw new StudioContributionError(`Extension ${e} cannot be reactivated from lifecycle state ${n.state}; a fresh verified activation is required.`,n.diagnostics);return n.state=`active`,this.#current=this.#publish(t.generation),this.#current}revokeTrust(e,t){let n=this.#requireExtension(e);return n.state=`trust-revoked`,this.#current=this.#publish(t.generation),this.#current}uninstall(e,t){let n=this.#requireExtension(e);return n.state=`uninstalled-data-preserved`,this.#current=this.#publish(t.generation),this.#current}assertCurrent(e){if(this.#current.generation!==e)throw new d(`stale-generation`,`Registry generation ${e} is stale; the active generation is ${this.#current.generation}.`);return this.#current}inventory(){return[...this.#extensions.values()].map(e=>({diagnostics:u(e.diagnostics),owner:u(e.owner),state:e.state})).sort((e,t)=>e.owner.id<t.owner.id?-1:1)}unresolvedNodes(e){let t=[],n=[...e.roots].reverse();for(;n.length>0;){let e=n.pop();if(e===void 0)break;if(this.#current.resolveBlock(e.type,e.version)===void 0){let{owner:n,reason:r}=this.#unresolvedReason(e.type,e.version),i={nodeId:e.id,reason:r,type:e.type,version:e.version};n!==void 0&&(i.owner=u(n)),t.push(i)}for(let t of Object.values(e.slots))n.push(...[...t].reverse())}return t}unresolvedContributions(e){let t=new Map;for(let n of this.unresolvedNodes(e)){let e=`${n.type}@${n.version}`,r=t.get(e);r===void 0&&(r={affectedNodes:[],contractVersion:l,diagnostics:[{code:`studio.validation/block-unavailable`,message:{defaultMessage:`The ${n.type} block is currently unavailable; its content is preserved.`,key:`studio.validation/block-unavailable`},severity:`warning`}],kind:`unresolved-contribution`,reason:n.reason,reference:{contribution:`block`,id:n.type,version:n.version}},n.owner!==void 0&&(r.owner=n.owner),t.set(e,r)),r.affectedNodes?.push(n.nodeId)}return[...t.values()]}unresolvedReference(e){if(!S(e.contribution))return{reason:`not-installed`};if(this.#current.resolveContribution(e.contribution,e.id,e.version)===void 0)return this.#unresolvedContributionReason(e.contribution,e.id,e.version)}#unresolvedReason(e,t){return this.#unresolvedContributionReason(`block`,e,t)}#unresolvedContributionReason(e,t,n){for(let r of this.#extensions.values()){let i=b(r.contributions).filter(n=>n.kind===e&&n.id===t).map(e=>e.version);if(i.length!==0)return i.includes(n)?r.state===`trust-revoked`?{owner:r.owner,reason:`owner-revoked`}:{owner:r.owner,reason:`owner-disabled`}:{owner:r.owner,reason:`incompatible`}}return{reason:`not-installed`}}#collectActivationDiagnostics(e,t){let n=[],r=new Set;for(let i of b(t)){if(i.owner.id!==e.id||i.owner.version!==e.version){n.push(E(`studio.contribution/owner-mismatch`,`${i.kind} ${i.id} declares owner ${i.owner.id}@${i.owner.version}.`));continue}let t=x(i.kind,i.id,i.version);if(r.has(t)){n.push(E(`studio.contribution/duplicate-contribution`,`${i.kind} ${i.id}@${i.version} is contributed twice by ${e.id}.`));continue}r.add(t);let a=this.#ownerOfContribution(i.kind,i.id,e.id);a!==void 0&&n.push(E(`studio.contribution/cross-owner-collision`,`${i.kind} ${i.id} is owned by ${a}.`));let o=_[i.kind];if(!o.validate(i.payload)){let e=o.errors?.[0];n.push(E(`studio.contribution/invalid-definition`,`${i.kind} ${i.id}@${i.version} ${e?.instancePath??`document`} ${e?.message??`violates its canonical schema`}.`))}}if(n.length===0)try{let n=new v;for(let t of this.#extensions.values())if(t.state===`active`&&t.owner.id!==e.id)for(let e of t.contributions.blocks)n.register(u(e));for(let e of t.blocks)n.register(u(e));for(let e of t.fieldAdapters)e.optionSchema!==void 0&&m(e.optionSchema)}catch(e){n.push(E(`studio.contribution/invalid-definition`,e instanceof Error?e.message:`A contributed definition is invalid.`))}return n}#ownerOfContribution(e,t,n){for(let r of this.#extensions.values())if(r.owner.id!==n&&r.state!==`purged`&&b(r.contributions).some(n=>n.kind===e&&n.id===t))return r.owner.id}#publish(e){let t=new v,n=[],r=[];for(let e of this.#extensions.values())if(e.state===`active`){n.push(u(e.owner));for(let n of e.contributions.blocks)t.register(u(n));r.push(...b(e.contributions))}return t.seal(),new RegistryGeneration(e,n,t,r)}#requireExtension(e){let t=this.#extensions.get(e);if(t===void 0)throw new StudioContributionError(`Extension ${e} is not known to the contribution runtime.`,[]);return t}}function y(e){return{authoringTargets:u(e.authoringTargets??[]),blocks:u(e.blocks),designVocabularies:u(e.designVocabularies??[]),fieldAdapters:u(e.fieldAdapters??[]),inspectors:u(e.inspectors??[]),migrations:u(e.migrations??[]),patterns:u(e.patterns??[])}}function b(e){return[...e.authoringTargets.map(e=>({id:e.id,kind:`authoring-target`,owner:e.owner,payload:e,version:e.owner.version})),...e.blocks.map(e=>({id:e.type,kind:`block`,owner:e.owner,payload:e,version:e.version})),...e.designVocabularies.map(e=>({id:e.id,kind:`design-vocabulary`,owner:e.owner,payload:e,version:e.version})),...e.fieldAdapters.map(e=>({id:e.id,kind:`field-adapter`,owner:e.owner,payload:e,version:e.version})),...e.inspectors.map(e=>({id:e.id,kind:`inspector`,owner:e.owner,payload:e,version:e.version})),...e.migrations.map(e=>({id:e.id,kind:`migration`,owner:e.owner,payload:e,version:e.version})),...e.patterns.map(e=>({id:e.id,kind:`pattern`,owner:e.owner,payload:e,version:e.version}))]}function x(e,t,n){return`${e}\u0000${t}\u0000${n}`}function S(e){return e===`authoring-target`||e===`block`||e===`design-vocabulary`||e===`field-adapter`||e===`inspector`||e===`migration`||e===`pattern`}function C(e){return e===`block-definition`?`block`:e}function w(e,t,n){let r=`${t}\u0000${n}\u0000`;return[...e.entries()].filter(([e])=>e.startsWith(r)).map(([e,t])=>({payload:u(t),version:e.slice(r.length)}))}function T(e,t,n){return e.surface!==t.resourceContext.surface||t.resourceContext.resource===void 0||!e.resourceTypes.includes(t.resourceContext.resource.type)||!e.eligibility.includes(t.intent)||t.requestedPresentation!==void 0&&!e.presentationStates.includes(t.requestedPresentation)||n.mode!==void 0&&!e.modes.includes(n.mode)?!1:e.requiredCapabilities.every(e=>n.capabilities.some(t=>t.id===e.id&&g(t.version,e.versions)))}function E(e,t){return{code:e,message:{defaultMessage:t,key:`studio.contribution/activation`},severity:`blocking`}}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type StudioDeploymentConfiguration } from '@kumwe/studio-protocol';
|
|
2
|
+
/**
|
|
3
|
+
* Full CSP-safe validation for the canonical deployment document. Validation
|
|
4
|
+
* includes every referenced session and contribution schema plus the
|
|
5
|
+
* cross-document hosted invariants that JSON Schema cannot express.
|
|
6
|
+
*/
|
|
7
|
+
export declare function validateStudioDeploymentConfiguration(value: unknown, currentTimeMilliseconds?: number): value is StudioDeploymentConfiguration;
|
|
8
|
+
/** Throws a value-free, bounded initialization error when validation fails. */
|
|
9
|
+
export declare function assertStudioDeploymentConfiguration(value: unknown, currentTimeMilliseconds?: number): asserts value is StudioDeploymentConfiguration;
|
|
10
|
+
//# sourceMappingURL=deployment-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-validation.d.ts","sourceRoot":"","sources":["../src/deployment-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,6BAA6B,EAGnC,MAAM,wBAAwB,CAAC;AAgBhC;;;;GAIG;AACH,wBAAgB,qCAAqC,CACnD,KAAK,EAAE,OAAO,EACd,uBAAuB,GAAE,MAAmB,GAC3C,KAAK,IAAI,6BAA6B,CAsCxC;AAED,+EAA+E;AAC/E,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,OAAO,EACd,uBAAuB,GAAE,MAAmB,GAC3C,OAAO,CAAC,KAAK,IAAI,6BAA6B,CAUhD"}
|