@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.
Files changed (93) hide show
  1. package/README.md +84 -4
  2. package/THIRD_PARTY_NOTICES.md +9 -0
  3. package/dist/authentication-lifetime.d.ts +16 -0
  4. package/dist/authentication-lifetime.d.ts.map +1 -0
  5. package/dist/authentication-lifetime.js +1 -0
  6. package/dist/binding-projection.d.ts +47 -0
  7. package/dist/binding-projection.d.ts.map +1 -0
  8. package/dist/binding-projection.js +1 -0
  9. package/dist/canonical.js +1 -100
  10. package/dist/clone.js +1 -4
  11. package/dist/commands.d.ts +1 -1
  12. package/dist/commands.d.ts.map +1 -1
  13. package/dist/commands.js +1 -799
  14. package/dist/contextual-session.d.ts +112 -0
  15. package/dist/contextual-session.d.ts.map +1 -0
  16. package/dist/contextual-session.js +1 -0
  17. package/dist/contributions.d.ts +63 -2
  18. package/dist/contributions.d.ts.map +1 -1
  19. package/dist/contributions.js +1 -302
  20. package/dist/deployment-validation.d.ts +10 -0
  21. package/dist/deployment-validation.d.ts.map +1 -0
  22. package/dist/deployment-validation.js +1 -0
  23. package/dist/entry-commands.js +1 -36
  24. package/dist/extension-sdk.d.ts +12 -6
  25. package/dist/extension-sdk.d.ts.map +1 -1
  26. package/dist/extension-sdk.js +1 -188
  27. package/dist/history.d.ts +12 -2
  28. package/dist/history.d.ts.map +1 -1
  29. package/dist/history.js +1 -63
  30. package/dist/host-session.d.ts +93 -0
  31. package/dist/host-session.d.ts.map +1 -0
  32. package/dist/host-session.js +1 -0
  33. package/dist/http-authoring-contract.d.ts +29 -0
  34. package/dist/http-authoring-contract.d.ts.map +1 -0
  35. package/dist/http-authoring-contract.js +1 -0
  36. package/dist/http-host-adapter.d.ts +173 -0
  37. package/dist/http-host-adapter.d.ts.map +1 -0
  38. package/dist/http-host-adapter.js +1 -0
  39. package/dist/index.d.ts +13 -1
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +1 -18
  42. package/dist/layout.d.ts +66 -0
  43. package/dist/layout.d.ts.map +1 -0
  44. package/dist/layout.js +1 -0
  45. package/dist/migrations.js +1 -83
  46. package/dist/model-commands.js +1 -21
  47. package/dist/modes.js +1 -280
  48. package/dist/negotiation.js +1 -65
  49. package/dist/production-values.d.ts +12 -0
  50. package/dist/production-values.d.ts.map +1 -0
  51. package/dist/production-values.js +1 -0
  52. package/dist/production.d.ts +86 -0
  53. package/dist/production.d.ts.map +1 -0
  54. package/dist/production.js +1 -0
  55. package/dist/profile-validator.d.ts.map +1 -1
  56. package/dist/profile-validator.js +1 -887
  57. package/dist/recipes.js +1 -34
  58. package/dist/registry.js +1 -56
  59. package/dist/schema-profile.js +1 -1015
  60. package/dist/semver.js +1 -128
  61. package/dist/session-policy.d.ts +23 -0
  62. package/dist/session-policy.d.ts.map +1 -0
  63. package/dist/session-policy.js +1 -0
  64. package/dist/session.d.ts +14 -2
  65. package/dist/session.d.ts.map +1 -1
  66. package/dist/session.js +1 -178
  67. package/dist/strict-json.d.ts +7 -0
  68. package/dist/strict-json.d.ts.map +1 -0
  69. package/dist/strict-json.js +2 -0
  70. package/dist/url-policy.js +1 -248
  71. package/dist/validation.d.ts.map +1 -1
  72. package/dist/validation.js +1 -398
  73. package/package.json +5 -3
  74. package/dist/canonical.js.map +0 -1
  75. package/dist/clone.js.map +0 -1
  76. package/dist/commands.js.map +0 -1
  77. package/dist/contributions.js.map +0 -1
  78. package/dist/entry-commands.js.map +0 -1
  79. package/dist/extension-sdk.js.map +0 -1
  80. package/dist/history.js.map +0 -1
  81. package/dist/index.js.map +0 -1
  82. package/dist/migrations.js.map +0 -1
  83. package/dist/model-commands.js.map +0 -1
  84. package/dist/modes.js.map +0 -1
  85. package/dist/negotiation.js.map +0 -1
  86. package/dist/profile-validator.js.map +0 -1
  87. package/dist/recipes.js.map +0 -1
  88. package/dist/registry.js.map +0 -1
  89. package/dist/schema-profile.js.map +0 -1
  90. package/dist/semver.js.map +0 -1
  91. package/dist/session.js.map +0 -1
  92. package/dist/url-policy.js.map +0 -1
  93. package/dist/validation.js.map +0 -1
@@ -0,0 +1 @@
1
+ import{hostOperationsSchema as e,protocolSchemas as t,studioDeploymentSchema as n}from"@kumwe/studio-protocol";import{canonicalStringify as r}from"./canonical.js";import{isStudioTokenLifetimeValid as i}from"./authentication-lifetime.js";import{compileProfileSchema as a}from"./profile-validator.js";const o=a(n,{schemas:t.filter(e=>e.$id!==n.$id)}),s=`studio.operation/`,c=f();export function validateStudioDeploymentConfiguration(e,t=Date.now()){if(!o.validate(e))return!1;let n=e;if(!l(n))return!0;let a=n.transport.authentication;if(a.kind!==`same-origin-session`&&!i(a,t)||r(n.launch.resourceContext)!==r(n.session.resourceContext))return!1;let s=u(n);return s===void 0||!s.has(`authoring/resolve-target`)||!s.has(`authoring/start`)?!1:n.transport.routing.kind===`single-endpoint`||m(new Set(Object.keys(n.transport.routing.endpoints)),s)}export function assertStudioDeploymentConfiguration(e,t=Date.now()){if(validateStudioDeploymentConfiguration(e,t))return;let n=h(o.errors);throw TypeError(n===``?`Studio deployment configuration violates a hosted deployment invariant.`:`Studio deployment configuration is invalid: ${n}`)}function l(e){return e.transport?.kind===`http`}function u(e){let t=new Set;for(let n of e.session.hostCapabilities.ports)for(let e of n.operations){let n=d(e);if(e.startsWith(s)&&n===void 0)return;n!==void 0&&t.add(n)}return t}function d(e){if(!e.startsWith(s))return;let t=e.slice(17),n=t.indexOf(`.`);if(n<=0||n===t.length-1)return;let r=`${t.slice(0,n)}/${t.slice(n+1)}`;return c.has(r)?r:void 0}function f(){let t=e.$defs;if(!p(t))throw TypeError(`Canonical host operation routes are unavailable.`);let n=t.operationRoute;if(!p(n)||!Array.isArray(n.enum))throw TypeError(`Canonical host operation routes are unavailable.`);let r=n.enum;if(!r.every(e=>typeof e==`string`))throw TypeError(`Canonical host operation routes are invalid.`);return new Set(r)}function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function m(e,t){return e.size===t.size&&[...e].every(e=>t.has(e))}function h(e){return e===null||e.length===0?``:e.slice(0,3).map(e=>`${e.instancePath||`/`} ${e.message}`).join(`; `)}
@@ -1,36 +1 @@
1
- import { cloneContractValue } from './clone.js';
2
- import { StudioCommandError } from './commands.js';
3
- export function applyEntryCommand(entry, command) {
4
- if (command.artifactId !== entry.id) {
5
- throw new StudioCommandError('node-not-found', `Command targets ${command.artifactId}, not entry ${entry.id}.`);
6
- }
7
- if (command.payload.locale !== undefined &&
8
- entry.locale !== undefined &&
9
- command.payload.locale !== entry.locale) {
10
- throw new StudioCommandError('locale-mismatch', `Command targets locale ${command.payload.locale}, but the entry stores ${entry.locale}.`);
11
- }
12
- const next = cloneContractValue(entry);
13
- const path = command.payload.fieldPath;
14
- let container = next.values;
15
- for (const [index, segment] of path.entries()) {
16
- if (index === path.length - 1) {
17
- setOwnMember(container, segment, cloneContractValue(command.payload.value));
18
- break;
19
- }
20
- const child = Object.hasOwn(container, segment) ? container[segment] : undefined;
21
- if (child === null || typeof child !== 'object' || Array.isArray(child)) {
22
- throw new StudioCommandError('property-not-found', `Field path segment ${segment} does not resolve to an object value.`);
23
- }
24
- container = child;
25
- }
26
- return next;
27
- }
28
- function setOwnMember(container, member, value) {
29
- Object.defineProperty(container, member, {
30
- configurable: true,
31
- enumerable: true,
32
- value,
33
- writable: true,
34
- });
35
- }
36
- //# sourceMappingURL=entry-commands.js.map
1
+ import{cloneContractValue as e}from"./clone.js";import{StudioCommandError as t}from"./commands.js";export function applyEntryCommand(n,i){if(i.artifactId!==n.id)throw new t(`node-not-found`,`Command targets ${i.artifactId}, not entry ${n.id}.`);if(i.payload.locale!==void 0&&n.locale!==void 0&&i.payload.locale!==n.locale)throw new t(`locale-mismatch`,`Command targets locale ${i.payload.locale}, but the entry stores ${n.locale}.`);let a=e(n),o=i.payload.fieldPath,s=a.values;for(let[n,a]of o.entries()){if(n===o.length-1){r(s,a,e(i.payload.value));break}let c=Object.hasOwn(s,a)?s[a]:void 0;if(typeof c!=`object`||!c||Array.isArray(c))throw new t(`property-not-found`,`Field path segment ${a} does not resolve to an object value.`);s=c}return a}function r(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0})}
@@ -1,14 +1,20 @@
1
- import type { BlockDefinition, PluginManifest, UnresolvedContribution, UnresolvedContributionReference } from '@kumwe/studio-protocol';
1
+ import type { AuthoringTargetDeclaration, BlockDefinition, DesignVocabulary, FieldAdapterContribution, InspectorContribution, MigrationDeclaration, PatternDocument, PluginManifest, UnresolvedContribution, UnresolvedContributionReference } from '@kumwe/studio-protocol';
2
2
  import { ContributionRuntime, type GenerationOptions, type RegistryGeneration } from './contributions.js';
3
3
  /**
4
4
  * One authored Studio plugin: the declarative manifest plus the concrete
5
- * block definitions the manifest declares. Non-block contribution kinds are
6
- * resource-backed declarations; their payloads stay inside the plugin
7
- * package and are validated by the host when the resource is loaded.
5
+ * canonical payloads the manifest declares. Contextual targets and all six
6
+ * composition families are validated and activated transactionally; other
7
+ * manifest kinds remain resource-backed host declarations.
8
8
  */
9
9
  export interface StudioPluginDefinition {
10
+ authoringTargets?: readonly AuthoringTargetDeclaration[];
10
11
  blocks?: readonly BlockDefinition[];
12
+ designVocabularies?: readonly DesignVocabulary[];
13
+ fieldAdapters?: readonly FieldAdapterContribution[];
14
+ inspectors?: readonly InspectorContribution[];
11
15
  manifest: PluginManifest;
16
+ migrations?: readonly MigrationDeclaration[];
17
+ patterns?: readonly PatternDocument[];
12
18
  }
13
19
  /**
14
20
  * The typed authoring entry point for extension developers. At compile time
@@ -33,8 +39,8 @@ export declare function defineStudioPlugin<TDefinition extends StudioPluginDefin
33
39
  export declare function activateStudioPlugin(runtime: ContributionRuntime, definition: StudioPluginDefinition, options: Readonly<GenerationOptions>): RegistryGeneration;
34
40
  /**
35
41
  * The portable unresolved-contribution documents for declared, non-block
36
- * contribution references (field adapters, patterns, transforms, renderer
37
- * capabilities, and the other manifest kinds). This mirrors the reason
42
+ * contribution references (authoring targets, field adapters, patterns,
43
+ * transforms, renderer capabilities, and the other manifest kinds). This mirrors the reason
38
44
  * mapping the runtime applies to Blueprint block nodes, lifted from
39
45
  * registered block versions to manifest declarations: an unknown id is
40
46
  * `not-installed`, an undeclared version is `incompatible`, a trust-revoked
@@ -1 +1 @@
1
- {"version":3,"file":"extension-sdk.d.ts","sourceRoot":"","sources":["../src/extension-sdk.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,eAAe,EAGf,cAAc,EAGd,sBAAsB,EAEtB,+BAA+B,EAChC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,mBAAmB,EAEnB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAG5B;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,SAAS,sBAAsB,EAC3E,UAAU,EAAE,WAAW,GACtB,WAAW,CASb;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,mBAAmB,EAC5B,UAAU,EAAE,sBAAsB,EAClC,OAAO,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GACnC,kBAAkB,CAOpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,SAAS,sBAAsB,EAAE,EAC1C,UAAU,EAAE,SAAS,+BAA+B,EAAE,GACrD,sBAAsB,EAAE,CAoC1B"}
1
+ {"version":3,"file":"extension-sdk.d.ts","sourceRoot":"","sources":["../src/extension-sdk.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,0BAA0B,EAC1B,eAAe,EACf,gBAAgB,EAEhB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EAEpB,eAAe,EAEf,cAAc,EAGd,sBAAsB,EAEtB,+BAA+B,EAChC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,mBAAmB,EAGnB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAG5B;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,CAAC,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACzD,MAAM,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,kBAAkB,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACjD,aAAa,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACpD,UAAU,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC9C,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC7C,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;CACvC;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,SAAS,sBAAsB,EAC3E,UAAU,EAAE,WAAW,GACtB,WAAW,CAOb;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,mBAAmB,EAC5B,UAAU,EAAE,sBAAsB,EAClC,OAAO,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GACnC,kBAAkB,CAGpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,SAAS,sBAAsB,EAAE,EAC1C,UAAU,EAAE,SAAS,+BAA+B,EAAE,GACrD,sBAAsB,EAAE,CAsC1B"}
@@ -1,188 +1 @@
1
- import { commonSchema, pluginManifestSchema, STUDIO_CONTRACT_VERSION, } from '@kumwe/studio-protocol';
2
- import { cloneContractValue } from './clone.js';
3
- import { ContributionRuntime, StudioContributionError, } from './contributions.js';
4
- import { compileProfileSchema } from './profile-validator.js';
5
- const validateManifestSchema = compileProfileSchema(pluginManifestSchema, {
6
- schemas: [commonSchema],
7
- });
8
- /**
9
- * The typed authoring entry point for extension developers. At compile time
10
- * this is an identity function: the argument is checked against the closed
11
- * protocol types, so a typo is an editor error. At runtime it front-loads
12
- * activation: the canonical plugin-manifest schema, the namespace and
13
- * declaration coherence rules of the plugin contract, and the contribution
14
- * runtime's own activation checks (applied through a dry-run activation, not
15
- * a reimplementation). It adds no invariant of its own — everything it
16
- * rejects would be rejected identically at activation. Violations throw the
17
- * runtime's `StudioContributionError` with blocking diagnostics; the
18
- * validated definition is deep-frozen and returned.
19
- */
20
- export function defineStudioPlugin(definition) {
21
- assertCoherentDefinition(definition);
22
- const dryRun = new ContributionRuntime({ generation: 'authoring-mirror-0' });
23
- dryRun.activate(definition.manifest.owner, { blocks: [...(definition.blocks ?? [])] }, { generation: 'authoring-mirror-1' });
24
- return deepFreeze(definition);
25
- }
26
- /**
27
- * Activate an authored plugin definition on a contribution runtime. The
28
- * manifest-level coherence checks run first and fail closed before the
29
- * runtime transaction begins; the runtime then applies its own activation
30
- * rules unchanged, so a rejected definition never disturbs the active
31
- * generation.
32
- */
33
- export function activateStudioPlugin(runtime, definition, options) {
34
- assertCoherentDefinition(definition);
35
- return runtime.activate(definition.manifest.owner, { blocks: [...(definition.blocks ?? [])] }, options);
36
- }
37
- /**
38
- * The portable unresolved-contribution documents for declared, non-block
39
- * contribution references (field adapters, patterns, transforms, renderer
40
- * capabilities, and the other manifest kinds). This mirrors the reason
41
- * mapping the runtime applies to Blueprint block nodes, lifted from
42
- * registered block versions to manifest declarations: an unknown id is
43
- * `not-installed`, an undeclared version is `incompatible`, a trust-revoked
44
- * owner is `owner-revoked`, and any other inactive owner is
45
- * `owner-disabled`. References the current generation resolves produce no
46
- * document.
47
- */
48
- export function unresolvedDeclaredContributions(runtime, plugins, references) {
49
- const states = new Map(runtime.inventory().map((entry) => [entry.owner.id, entry.state]));
50
- const unresolved = [];
51
- const seen = new Set();
52
- for (const reference of references) {
53
- const key = `${reference.contribution}:${reference.id}@${reference.version}`;
54
- if (seen.has(key)) {
55
- continue;
56
- }
57
- seen.add(key);
58
- const resolution = resolveDeclaredReference(states, plugins, reference);
59
- if (resolution === undefined) {
60
- continue;
61
- }
62
- const document = {
63
- contractVersion: STUDIO_CONTRACT_VERSION,
64
- diagnostics: [
65
- {
66
- code: 'studio.validation/contribution-unavailable',
67
- message: {
68
- defaultMessage: `The ${reference.id} ${reference.contribution} contribution is currently unavailable; its content is preserved.`,
69
- key: 'studio.validation/contribution-unavailable',
70
- },
71
- severity: 'warning',
72
- },
73
- ],
74
- kind: 'unresolved-contribution',
75
- reason: resolution.reason,
76
- reference: cloneContractValue(reference),
77
- };
78
- if (resolution.owner !== undefined) {
79
- document.owner = cloneContractValue(resolution.owner);
80
- }
81
- unresolved.push(document);
82
- }
83
- return unresolved;
84
- }
85
- function resolveDeclaredReference(states, plugins, reference) {
86
- for (const plugin of plugins) {
87
- const versions = plugin.manifest.contributions
88
- .filter((contribution) => contribution.id === reference.id)
89
- .map((contribution) => contribution.version);
90
- if (versions.length === 0) {
91
- continue;
92
- }
93
- const owner = plugin.manifest.owner;
94
- const state = states.get(owner.id);
95
- if (state === undefined) {
96
- return { reason: 'not-installed' };
97
- }
98
- if (!versions.includes(reference.version)) {
99
- return { owner, reason: 'incompatible' };
100
- }
101
- if (state === 'trust-revoked') {
102
- return { owner, reason: 'owner-revoked' };
103
- }
104
- if (state === 'active') {
105
- return undefined;
106
- }
107
- return { owner, reason: 'owner-disabled' };
108
- }
109
- return { reason: 'not-installed' };
110
- }
111
- function assertCoherentDefinition(definition) {
112
- const diagnostics = collectDefinitionDiagnostics(definition);
113
- if (diagnostics.length > 0) {
114
- throw new StudioContributionError(`Definition of ${definition.manifest.id} was rejected: ${diagnostics
115
- .map((diagnostic) => diagnostic.code)
116
- .join(', ')}.`, diagnostics);
117
- }
118
- }
119
- function collectDefinitionDiagnostics(definition) {
120
- const diagnostics = [];
121
- const manifest = definition.manifest;
122
- if (!validateManifestSchema.validate(manifest)) {
123
- for (const error of validateManifestSchema.errors ?? []) {
124
- diagnostics.push(coherenceDiagnostic('studio.contribution/invalid-manifest', `Manifest ${error.instancePath === '' ? 'document' : error.instancePath} ${error.message}.`, error.instancePath === '' ? undefined : error.instancePath));
125
- }
126
- return diagnostics;
127
- }
128
- const namespace = namespaceOf(manifest.id);
129
- const declared = new Set();
130
- for (const contribution of manifest.contributions) {
131
- if (!isUnderNamespace(contribution.id, namespace)) {
132
- diagnostics.push(coherenceDiagnostic('studio.contribution/foreign-namespace', `Contribution ${contribution.id} is outside the ${namespace} namespace owned by ${manifest.id}.`));
133
- }
134
- const key = `${contribution.id}@${contribution.version}`;
135
- if (declared.has(key)) {
136
- diagnostics.push(coherenceDiagnostic('studio.contribution/duplicate-contribution', `Contribution ${key} is contributed twice by ${manifest.id}.`));
137
- }
138
- declared.add(key);
139
- if (contribution.executable === true && manifest.activation !== 'executable') {
140
- diagnostics.push(coherenceDiagnostic('studio.contribution/undeclared-executable', `Contribution ${contribution.id} is executable, but ${manifest.id} declares declarative activation.`));
141
- }
142
- }
143
- const declaredBlocks = new Set(manifest.contributions
144
- .filter((contribution) => contribution.kind === 'block')
145
- .map((contribution) => `${contribution.id}@${contribution.version}`));
146
- const declaredCapabilities = new Set([...manifest.requiredCapabilities, ...manifest.optionalCapabilities].map((capability) => capability.id));
147
- for (const block of definition.blocks ?? []) {
148
- if (!declaredBlocks.has(`${block.type}@${block.version}`)) {
149
- diagnostics.push(coherenceDiagnostic('studio.contribution/undeclared-registration', `Block ${block.type}@${block.version} is not declared as a block contribution of ${manifest.id}.`));
150
- }
151
- for (const requirement of block.rendererRequirements) {
152
- if (!declaredCapabilities.has(requirement.capability)) {
153
- diagnostics.push(coherenceDiagnostic('studio.contribution/undeclared-capability', `Block ${block.type} requires the ${requirement.capability} capability, which ${manifest.id} does not declare.`));
154
- }
155
- }
156
- }
157
- return diagnostics;
158
- }
159
- function namespaceOf(id) {
160
- const separator = id.indexOf('/');
161
- return separator === -1 ? id : id.slice(0, separator);
162
- }
163
- function isUnderNamespace(id, namespace) {
164
- const candidate = namespaceOf(id);
165
- return candidate === namespace || candidate.startsWith(`${namespace}.`);
166
- }
167
- function coherenceDiagnostic(code, message, jsonPointer) {
168
- const diagnostic = {
169
- code,
170
- message: { defaultMessage: message, key: 'studio.contribution/activation' },
171
- severity: 'blocking',
172
- };
173
- if (jsonPointer !== undefined) {
174
- diagnostic.location = { jsonPointer };
175
- }
176
- return diagnostic;
177
- }
178
- function deepFreeze(value) {
179
- if (value === null || typeof value !== 'object' || Object.isFrozen(value)) {
180
- return value;
181
- }
182
- Object.freeze(value);
183
- for (const entry of Object.values(value)) {
184
- deepFreeze(entry);
185
- }
186
- return value;
187
- }
188
- //# sourceMappingURL=extension-sdk.js.map
1
+ import{commonSchema as e,pluginManifestSchema as t,STUDIO_CONTRACT_VERSION as n}from"@kumwe/studio-protocol";import{cloneContractValue as r}from"./clone.js";import{ContributionRuntime as i,StudioContributionError as a}from"./contributions.js";import{compileProfileSchema as o}from"./profile-validator.js";const s=o(t,{schemas:[e]}),c=new Set([`authoring-target`,`block`,`design-vocabulary`,`field-adapter`,`inspector`,`migration`,`pattern`]);export function defineStudioPlugin(e){return p(e),new i({generation:`authoring-mirror-0`}).activate(e.manifest.owner,g(e),{generation:`authoring-mirror-1`}),x(e)}export function activateStudioPlugin(e,t,n){return p(t),e.activate(t.manifest.owner,g(t),n)}export function unresolvedDeclaredContributions(e,t,i){let a=new Map(e.inventory().map(e=>[e.owner.id,e.state])),o=[],s=new Set;for(let l of i){let i=`${l.contribution}:${l.id}@${l.version}`;if(s.has(i))continue;s.add(i);let u=c.has(l.contribution)?e.unresolvedReference(l):f(a,t,l);if(u===void 0)continue;let d={contractVersion:n,diagnostics:[{code:`studio.validation/contribution-unavailable`,message:{defaultMessage:`The ${l.id} ${l.contribution} contribution is currently unavailable; its content is preserved.`,key:`studio.validation/contribution-unavailable`},severity:`warning`}],kind:`unresolved-contribution`,reason:u.reason,reference:r(l)};u.owner!==void 0&&(d.owner=r(u.owner)),o.push(d)}return o}function f(e,t,n){for(let r of t){let t=r.manifest.contributions.filter(e=>e.kind===n.contribution&&e.id===n.id).map(e=>e.version);if(t.length===0)continue;let i=r.manifest.owner,a=e.get(i.id);return a===void 0?{reason:`not-installed`}:t.includes(n.version)?a===`trust-revoked`?{owner:i,reason:`owner-revoked`}:a===`active`?void 0:{owner:i,reason:`owner-disabled`}:{owner:i,reason:`incompatible`}}return{reason:`not-installed`}}function p(e){let t=m(e);if(t.length>0)throw new a(`Definition of ${e.manifest.id} was rejected: ${t.map(e=>e.code).join(`, `)}.`,t)}function m(e){let t=[],n=e.manifest;if(!s.validate(n)){for(let e of s.errors??[])t.push(b(`studio.contribution/invalid-manifest`,`Manifest ${e.instancePath===``?`document`:e.instancePath} ${e.message}.`,e.instancePath===``?void 0:e.instancePath));return t}let r=v(n.id),i=new Set;for(let e of n.contributions){y(e.id,r)||t.push(b(`studio.contribution/foreign-namespace`,`Contribution ${e.id} is outside the ${r} namespace owned by ${n.id}.`));let a=_(e.kind,e.id,e.version);i.has(a)&&t.push(b(`studio.contribution/duplicate-contribution`,`${e.kind} contribution ${e.id}@${e.version} is declared twice by ${n.id}.`)),i.add(a),e.executable===!0&&n.activation!==`executable`&&t.push(b(`studio.contribution/undeclared-executable`,`Contribution ${e.id} is executable, but ${n.id} declares declarative activation.`))}let a=new Set([...n.requiredCapabilities,...n.optionalCapabilities].map(e=>e.id)),o=h(e),l=new Set;for(let e of o){let r=_(e.kind,e.id,e.version);l.add(r),i.has(r)||t.push(b(`studio.contribution/undeclared-registration`,`${e.kind} ${e.id}@${e.version} is not declared by ${n.id}.`));for(let r of e.requiredCapabilities)a.has(r)||t.push(b(`studio.contribution/undeclared-capability`,`${e.kind} ${e.id} requires the ${r} capability, which ${n.id} does not declare.`))}for(let e of n.contributions)c.has(e.kind)&&!l.has(_(e.kind,e.id,e.version))&&t.push(b(`studio.contribution/missing-registration`,`${e.kind} ${e.id}@${e.version} has no canonical payload in ${n.id}.`));return t}function h(e){return[...(e.authoringTargets??[]).map(e=>({id:e.id,kind:`authoring-target`,requiredCapabilities:e.requiredCapabilities.map(e=>e.id),version:e.owner.version})),...(e.blocks??[]).map(e=>({id:e.type,kind:`block`,requiredCapabilities:e.rendererRequirements.map(e=>e.capability),version:e.version})),...(e.designVocabularies??[]).map(e=>({id:e.id,kind:`design-vocabulary`,requiredCapabilities:[],version:e.version})),...(e.fieldAdapters??[]).map(e=>({id:e.id,kind:`field-adapter`,requiredCapabilities:e.requiredCapability===void 0?[]:[e.requiredCapability],version:e.version})),...(e.inspectors??[]).map(e=>({id:e.id,kind:`inspector`,requiredCapabilities:e.requiredCapability===void 0?[]:[e.requiredCapability],version:e.version})),...(e.migrations??[]).map(e=>({id:e.id,kind:`migration`,requiredCapabilities:[],version:e.version})),...(e.patterns??[]).map(e=>({id:e.id,kind:`pattern`,requiredCapabilities:[],version:e.version}))]}function g(e){return{authoringTargets:[...e.authoringTargets??[]],blocks:[...e.blocks??[]],designVocabularies:[...e.designVocabularies??[]],fieldAdapters:[...e.fieldAdapters??[]],inspectors:[...e.inspectors??[]],migrations:[...e.migrations??[]],patterns:[...e.patterns??[]]}}function _(e,t,n){return`${e}\u0000${t}\u0000${n}`}function v(e){let t=e.indexOf(`/`);return t===-1?e:e.slice(0,t)}function y(e,t){let n=v(e);return n===t||n.startsWith(`${t}.`)}function b(e,t,n){let r={code:e,message:{defaultMessage:t,key:`studio.contribution/activation`},severity:`blocking`};return n!==void 0&&(r.location={jsonPointer:n}),r}function x(e){if(typeof e!=`object`||!e||Object.isFrozen(e))return e;Object.freeze(e);for(let t of Object.values(e))x(t);return e}
package/dist/history.d.ts CHANGED
@@ -1,11 +1,21 @@
1
- import type { BlueprintCommand, BlueprintDocument } from '@kumwe/studio-protocol';
1
+ import type { BlueprintCommand, BlueprintDocument, Revision } from '@kumwe/studio-protocol';
2
+ import { type ResolvedStudioSessionPolicy } from './session-policy.js';
2
3
  export declare class StudioHistory {
3
4
  #private;
4
- constructor(document: BlueprintDocument, maximumEntries?: number);
5
+ constructor(document: BlueprintDocument, maximumEntries?: number, policy?: Readonly<ResolvedStudioSessionPolicy>);
5
6
  get canRedo(): boolean;
6
7
  get canUndo(): boolean;
7
8
  get current(): BlueprintDocument;
8
9
  get stateVersion(): number;
10
+ /**
11
+ * Advances the host-authored revision carried by every local snapshot.
12
+ *
13
+ * A successful optimistic save establishes one new base revision for the
14
+ * complete local timeline. Rebasing the current, past, and future snapshots
15
+ * keeps later commands and preview staging on that base without fabricating
16
+ * an edit, changing the history topology, or advancing `stateVersion`.
17
+ */
18
+ rebaseRevision(revision: Revision): BlueprintDocument;
9
19
  execute(command: BlueprintCommand): BlueprintDocument;
10
20
  redo(): BlueprintDocument;
11
21
  undo(): BlueprintDocument;
@@ -1 +1 @@
1
- {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIlF,qBAAa,aAAa;;gBAOL,QAAQ,EAAE,iBAAiB,EAAE,cAAc,SAAM;IAQpE,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED,IAAW,OAAO,IAAI,iBAAiB,CAEtC;IAED,IAAW,YAAY,IAAI,MAAM,CAEhC;IAEM,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,iBAAiB;IAkBrD,IAAI,IAAI,iBAAiB;IAWzB,IAAI,IAAI,iBAAiB;CAUjC"}
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAG5F,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,aAAa;;gBAStB,QAAQ,EAAE,iBAAiB,EAC3B,cAAc,SAAM,EACpB,MAAM,CAAC,EAAE,QAAQ,CAAC,2BAA2B,CAAC;IAUhD,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED,IAAW,OAAO,IAAI,iBAAiB,CAEtC;IAED,IAAW,YAAY,IAAI,MAAM,CAEhC;IAED;;;;;;;OAOG;IACI,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,iBAAiB;IAWrD,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,iBAAiB;IAqBrD,IAAI,IAAI,iBAAiB;IAWzB,IAAI,IAAI,iBAAiB;CAUjC"}
package/dist/history.js CHANGED
@@ -1,63 +1 @@
1
- import { applyCommand, StudioCommandError } from './commands.js';
2
- import { cloneContractValue } from './clone.js';
3
- export class StudioHistory {
4
- #maximumEntries;
5
- #current;
6
- #future = [];
7
- #past = [];
8
- #stateVersion = 0;
9
- constructor(document, maximumEntries = 100) {
10
- if (!Number.isInteger(maximumEntries) || maximumEntries < 1) {
11
- throw new RangeError('History maximum must be a positive integer.');
12
- }
13
- this.#current = cloneContractValue(document);
14
- this.#maximumEntries = maximumEntries;
15
- }
16
- get canRedo() {
17
- return this.#future.length > 0;
18
- }
19
- get canUndo() {
20
- return this.#past.length > 0;
21
- }
22
- get current() {
23
- return cloneContractValue(this.#current);
24
- }
25
- get stateVersion() {
26
- return this.#stateVersion;
27
- }
28
- execute(command) {
29
- if (command.baseStateVersion !== this.#stateVersion) {
30
- throw new StudioCommandError('stale-state', `Command state ${command.baseStateVersion} does not match ${this.#stateVersion}.`);
31
- }
32
- const next = applyCommand(this.#current, command);
33
- this.#past.push(this.#current);
34
- if (this.#past.length > this.#maximumEntries) {
35
- this.#past.shift();
36
- }
37
- this.#current = next;
38
- this.#future = [];
39
- this.#stateVersion += 1;
40
- return this.current;
41
- }
42
- redo() {
43
- const next = this.#future.pop();
44
- if (next === undefined) {
45
- return this.current;
46
- }
47
- this.#past.push(this.#current);
48
- this.#current = next;
49
- this.#stateVersion += 1;
50
- return this.current;
51
- }
52
- undo() {
53
- const previous = this.#past.pop();
54
- if (previous === undefined) {
55
- return this.current;
56
- }
57
- this.#future.push(this.#current);
58
- this.#current = previous;
59
- this.#stateVersion += 1;
60
- return this.current;
61
- }
62
- }
63
- //# sourceMappingURL=history.js.map
1
+ import{applyCommand as e,StudioCommandError as t}from"./commands.js";import{cloneContractValue as n}from"./clone.js";import{assertBlueprintCommandPolicy as r}from"./session-policy.js";export class StudioHistory{#maximumEntries;#policy;#current;#future=[];#past=[];#stateVersion=0;constructor(e,t=100,r){if(!Number.isInteger(t)||t<1)throw RangeError(`History maximum must be a positive integer.`);this.#current=n(e),this.#maximumEntries=t,this.#policy=r}get canRedo(){return this.#future.length>0}get canUndo(){return this.#past.length>0}get current(){return n(this.#current)}get stateVersion(){return this.#stateVersion}rebaseRevision(e){let t=t=>({...t,revision:e});return this.#current=t(this.#current),this.#past=this.#past.map(t),this.#future=this.#future.map(t),this.current}execute(n){if(n.baseStateVersion!==this.#stateVersion)throw new t(`stale-state`,`Command state ${n.baseStateVersion} does not match ${this.#stateVersion}.`);let i=e(this.#current,n);return this.#policy!==void 0&&r(this.#current,n,i,this.#policy),this.#past.push(this.#current),this.#past.length>this.#maximumEntries&&this.#past.shift(),this.#current=i,this.#future=[],this.#stateVersion+=1,this.current}redo(){let e=this.#future.pop();return e===void 0?this.current:(this.#past.push(this.#current),this.#current=e,this.#stateVersion+=1,this.current)}undo(){let e=this.#past.pop();return e===void 0?this.current:(this.#future.push(this.#current),this.#current=e,this.#stateVersion+=1,this.current)}}
@@ -0,0 +1,93 @@
1
+ import { HostPortFailure, type ArtifactReference, type ContentModelDocument, type HostAdapter, type HostPortResult, type HostRequestContext, type JsonObject, type JsonPrimitive, type JsonValue, type QualifiedName, type ResourceSearchPage, type ResourceSearchQuery, type Revision, type StableId, type StudioConfiguration, type StudioDiagnostic } from '@kumwe/studio-protocol';
2
+ import { type CapabilityNegotiationResult } from './negotiation.js';
3
+ import { StudioSession } from './session.js';
4
+ /** Public bounds enforced before a composed session invokes resource search. */
5
+ export declare const STUDIO_RESOURCE_SEARCH_LIMITS: Readonly<{
6
+ maximumCursorLength: number;
7
+ maximumLimit: number;
8
+ maximumSearchLength: number;
9
+ minimumLimit: number;
10
+ }>;
11
+ export interface StudioHostSessionIdentifierFactories {
12
+ /** Allocates a session-unique request identifier for one host attempt. */
13
+ requestId(operationId: QualifiedName): StableId;
14
+ /** Allocates a mutation identifier; exact failed-intent retries reuse it. */
15
+ idempotencyKey(operationId: QualifiedName): StableId;
16
+ }
17
+ export interface OpenStudioSessionOptions {
18
+ /** A schema-valid, resolved, immutable configuration supplied by the host. */
19
+ configuration: StudioConfiguration;
20
+ /** Injected so core never depends on clocks, randomness, DOM, or Node APIs. */
21
+ identifiers: StudioHostSessionIdentifierFactories;
22
+ /** Additional port capabilities whose absence should be diagnosed as degradation. */
23
+ optionalPorts?: readonly QualifiedName[];
24
+ }
25
+ export interface StudioHostSessionRecovery {
26
+ discard(): Promise<HostPortResult<null>>;
27
+ load(): Promise<HostPortResult<JsonObject | null>>;
28
+ store(envelope: JsonObject): Promise<HostPortResult<null>>;
29
+ }
30
+ /** Read-only access to the authorized model projection behind this session. */
31
+ export interface StudioHostSessionModels {
32
+ get(reference: ArtifactReference): Promise<HostPortResult<ContentModelDocument>>;
33
+ list(): Promise<HostPortResult<ContentModelDocument[]>>;
34
+ }
35
+ /** Read-only discovery of host-authorized resources behind this session. */
36
+ export interface StudioHostSessionResources {
37
+ search(query: ResourceSearchQuery): Promise<HostPortResult<ResourceSearchPage>>;
38
+ }
39
+ export interface StudioHostSessionHandle {
40
+ /** The complete open-time negotiation and profile diagnostics. */
41
+ readonly diagnostics: readonly StudioDiagnostic[];
42
+ readonly disposed: boolean;
43
+ readonly invalidated: boolean;
44
+ readonly negotiation: CapabilityNegotiationResult;
45
+ /** Present only when the model port advertises and implements both read operations. */
46
+ readonly models: StudioHostSessionModels | undefined;
47
+ /** Present only when feature policy, advertised operations, and adapter agree. */
48
+ readonly recovery: StudioHostSessionRecovery | undefined;
49
+ /** Present only when the resource port advertises and implements search. */
50
+ readonly resources: StudioHostSessionResources | undefined;
51
+ /** The most recent host-accepted Blueprint revision. */
52
+ readonly revision: Revision;
53
+ readonly session: StudioSession;
54
+ /** Local, idempotent teardown. It never invents a host teardown operation. */
55
+ dispose(): void;
56
+ save(): Promise<HostPortResult<null>>;
57
+ }
58
+ export type StudioHostSessionErrorCode = 'configuration-blocked' | 'disposed' | 'invalid-authoring-request' | 'invalid-identifier' | 'invalid-model-reference' | 'invalid-resource-query' | 'read-only-session' | 'save-plan-mismatch' | 'unexpected-authoring-result' | 'unexpected-artifact';
59
+ /** A local composition/state failure, distinct from a host-port rejection. */
60
+ export declare class StudioHostSessionError extends Error {
61
+ readonly code: StudioHostSessionErrorCode;
62
+ readonly diagnostics: readonly StudioDiagnostic[];
63
+ constructor(code: StudioHostSessionErrorCode, message: string, diagnostics?: readonly StudioDiagnostic[]);
64
+ }
65
+ /**
66
+ * Composes the DOM-free editing engine with one resolved host configuration.
67
+ *
68
+ * The current contract-safe profile opens a single Blueprint only. It does
69
+ * not fabricate entry/model state, infer a transport, stage preview drafts,
70
+ * or reconcile recovery data. Those capabilities require their own explicit
71
+ * contracts.
72
+ */
73
+ export declare function openStudioSession(adapter: HostAdapter, options: Readonly<OpenStudioSessionOptions>): Promise<StudioHostSessionHandle>;
74
+ interface ContextOptions {
75
+ expectedRevision?: Revision;
76
+ idempotencyKey?: StableId;
77
+ operationId: QualifiedName;
78
+ }
79
+ export declare class SessionIdentifierAllocator {
80
+ #private;
81
+ constructor(factories: StudioHostSessionIdentifierFactories);
82
+ dispose(): void;
83
+ idempotencyKey(operationId: QualifiedName, fingerprint: string): StableId;
84
+ requestId(operationId: QualifiedName): StableId;
85
+ }
86
+ export declare function createContext(configuration: StudioConfiguration, requestId: StableId, options: ContextOptions): HostRequestContext;
87
+ export declare function createDiagnostic(code: QualifiedName, defaultMessage: string, severity: StudioDiagnostic['severity'], parameters?: Record<string, JsonPrimitive>): StudioDiagnostic;
88
+ export declare function mutationFingerprint(argument: JsonValue, configuration: StudioConfiguration, expectedRevision?: Revision): string;
89
+ export declare function normalizeHostRejection(error: unknown): HostPortFailure;
90
+ export declare function adapterContractFailure(code: QualifiedName, defaultMessage: string): HostPortFailure;
91
+ export declare function isStaleGenerationFailure(failure: HostPortFailure): boolean;
92
+ export {};
93
+ //# sourceMappingURL=host-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-session.d.ts","sourceRoot":"","sources":["../src/host-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{HostPortFailure as e,STUDIO_CONTRACT_VERSION as t,STUDIO_STALE_SESSION_GENERATION_DIAGNOSTIC_CODE as n,commonSchema as r,contentModelSchema as i,isHostPortFailure as a}from"@kumwe/studio-protocol";import{canonicalStringify as o}from"./canonical.js";import{cloneContractValue as s}from"./clone.js";import{negotiateCapabilities as c}from"./negotiation.js";import{resolveSessionMode as l}from"./modes.js";import{compileProfileSchema as u}from"./profile-validator.js";import{StudioSession as d}from"./session.js";import{assertBlueprintWithinSessionPolicy as f}from"./session-policy.js";const p=`studio.port/artifact`,m=`studio.port/model`,h=`studio.port/recovery`,g=`studio.port/resource`,_=`studio.operation/artifact.load`,v=`studio.operation/artifact.save`,y=`studio.operation/model.get`,b=`studio.operation/model.list`,x=`studio.operation/recovery.store`,S=`studio.operation/recovery.load`,C=`studio.operation/recovery.discard`,w=`studio.operation/resource.search`,T=/^[A-Za-z0-9][A-Za-z0-9._:/-]*$/u,E=/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*\/[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/u,D=new Set([`__proto__`,`prototype`,`constructor`]);export const STUDIO_RESOURCE_SEARCH_LIMITS=Object.freeze({maximumCursorLength:500,maximumLimit:100,maximumSearchLength:500,minimumLimit:1});const O=u(i,{schemas:[r]}),k=u({$ref:`https://schemas.kumwe.org/studio/v1/common.schema.json#/$defs/artifactReference`,$schema:`https://json-schema.org/draft/2020-12/schema`},{schemas:[r]});export class StudioHostSessionError extends Error{code;diagnostics;constructor(e,t,n=[]){super(t),this.name=`StudioHostSessionError`,this.code=e,this.diagnostics=s(n)}}export async function openStudioSession(e,t){let n=s(t.configuration),r=N(n,t.optionalPorts),i=c(n.hostCapabilities,{optionalPorts:r,requiredPorts:[p],supportedProtocolVersions:[n.protocolVersion]});n.sessionState===`read-only`&&(i.sessionState=`read-only`),M(n,i);let a=ee(e,n,i),o=te(e,n,i),u=ne(e,n,i);if(i.diagnostics.some(e=>e.severity===`blocking`))throw new StudioHostSessionError(`configuration-blocked`,`The resolved Studio configuration cannot open a Blueprint host session.`,i.diagnostics);let m=n.artifacts.blueprint;if(m===void 0)throw new StudioHostSessionError(`configuration-blocked`,`A Blueprint host session requires an explicit locked Blueprint reference.`,i.diagnostics);let h=new SessionIdentifierAllocator(t.identifiers),g=createContext(n,h.requestId(_),{operationId:_}),v=await ie(()=>e.artifact.load(m,g));if(!F(v,m.id)){let e=createDiagnostic(`studio.host/unexpected-artifact`,`The artifact port did not return the configured Blueprint.`,`blocking`,{artifactId:m.id});throw new StudioHostSessionError(`unexpected-artifact`,`The host returned an artifact outside the Blueprint session profile.`,[e])}let y=P(v.value,v.revision);f(y,n.limits);let b=new d({document:y,limits:n.limits,maximumHistoryEntries:n.limits.maxHistoryEntries,mode:l(n),permissions:n.permissions,sessionGeneration:n.sessionGeneration});return b.markSaved(y.revision),new A(e,n,h,i,a,o,u,b,y.revision)}class A{diagnostics;negotiation;models;recovery;resources;session;#adapter;#configuration;#identifiers;#retryIntents=new Map;#disposed=!1;#invalidationFailure;#lastScheduledSave;#revision;#saveTail=Promise.resolve();constructor(e,t,n,r,i,a,o,c,l){this.#adapter=e,this.#configuration=t,this.#identifiers=n,this.negotiation=ae(r),this.diagnostics=s(r.diagnostics),this.session=c,this.#revision=l,this.recovery=i?Object.freeze({discard:()=>this.#discardRecovery(),load:()=>this.#loadRecovery(),store:e=>this.#storeRecovery(e)}):void 0,this.models=a?Object.freeze({get:e=>this.#getModel(e),list:()=>this.#listModels()}):void 0,this.resources=o?Object.freeze({search:e=>this.#searchResources(e)}):void 0}get disposed(){return this.#disposed}get invalidated(){return this.#invalidationFailure!==void 0}get revision(){return this.#revision}dispose(){this.#disposed||(this.#disposed=!0,this.#retryIntents.clear(),this.#identifiers.dispose())}save(){try{if(this.#assertActive(),this.session.mode===`read-only`)throw new StudioHostSessionError(`read-only-session`,`A read-only Studio host session cannot save.`);let e=this.session.document,t=o(e),n=this.#lastScheduledSave;if(n?.snapshotFingerprint===t)return n.promise;if(!this.session.dirty)return Promise.resolve({revision:this.#revision,value:null});let r=this.session.stateVersion,i=this.#saveTail.then(()=>this.#saveSnapshot(e,r));this.#saveTail=i.then(()=>void 0,()=>void 0),this.#lastScheduledSave={promise:i,snapshotFingerprint:t};let a=()=>{this.#lastScheduledSave?.promise===i&&(this.#lastScheduledSave=void 0)};return i.then(a,a),i}catch(e){return Promise.reject(e instanceof Error?e:Error(`The Studio host session failed with a non-Error rejection.`))}}async#discardRecovery(){this.#assertActive();let e=this.#adapter.recovery;if(e===void 0)throw adapterContractFailure(`studio.host/adapter-port-unavailable`,`The negotiated recovery adapter is unavailable.`);let t=mutationFingerprint(null,this.#configuration),n=this.#mutationKey(C,t),r=createContext(this.#configuration,this.#identifiers.requestId(C),{idempotencyKey:n,operationId:C}),i=await this.#invoke(()=>e.discard(r));return this.#clearMutationKey(C,t),i}async#loadRecovery(){this.#assertActive();let e=this.#adapter.recovery;if(e===void 0)throw adapterContractFailure(`studio.host/adapter-port-unavailable`,`The negotiated recovery adapter is unavailable.`);let t=createContext(this.#configuration,this.#identifiers.requestId(S),{operationId:S}),n=await this.#invoke(()=>e.load(t));return{...n.revision===void 0?{}:{revision:n.revision},value:n.value===null?null:s(n.value)}}async#getModel(e){if(this.#assertActive(),!Y(e))throw new StudioHostSessionError(`invalid-model-reference`,`A model read requires a canonical artifact identifier and semantic version.`);let t=this.#adapter.model;if(t===void 0)throw adapterContractFailure(`studio.host/adapter-port-unavailable`,`The negotiated model adapter is unavailable.`);let n=s(e),r=createContext(this.#configuration,this.#identifiers.requestId(y),{operationId:y}),i=await this.#invoke(()=>t.get(n,r));if(!I(i,n))throw adapterContractFailure(`studio.host/unexpected-model-result`,`The model port returned a document outside the requested model coordinate.`);return{...i.revision===void 0?{}:{revision:i.revision},value:s(i.value)}}async#listModels(){this.#assertActive();let e=this.#adapter.model;if(e===void 0)throw adapterContractFailure(`studio.host/adapter-port-unavailable`,`The negotiated model adapter is unavailable.`);let t=createContext(this.#configuration,this.#identifiers.requestId(b),{operationId:b}),n=await this.#invoke(()=>e.list(t));if(!L(n))throw adapterContractFailure(`studio.host/unexpected-model-result`,`The model port returned a malformed or duplicate model collection.`);return{...n.revision===void 0?{}:{revision:n.revision},value:s(n.value).sort(re)}}async#saveSnapshot(e,t){this.#assertActive();let n=this.#revision,r={...e,revision:n},i=mutationFingerprint(r,this.#configuration,n),a=this.#mutationKey(v,i),o=createContext(this.#configuration,this.#identifiers.requestId(v),{expectedRevision:n,idempotencyKey:a,operationId:v}),s=await this.#invoke(()=>this.#adapter.artifact.save(r,o));if(s.value!==null||!$(s.revision))throw adapterContractFailure(`studio.host/missing-accepted-revision`,`The artifact save did not return its accepted revision.`);return this.#revision=s.revision,this.session.markSaved(s.revision,t),this.#clearMutationKey(v,i),{revision:s.revision,value:null}}async#searchResources(e){if(this.#assertActive(),!R(e))throw new StudioHostSessionError(`invalid-resource-query`,`A resource search requires a canonical resource type, bounded limit, cursor, and search text.`);let t=this.#adapter.resource;if(t===void 0)throw adapterContractFailure(`studio.host/adapter-port-unavailable`,`The negotiated resource adapter is unavailable.`);let n=s(e),r=createContext(this.#configuration,this.#identifiers.requestId(w),{operationId:w}),i=await this.#invoke(()=>t.search(n,r));if(!z(i,n))throw adapterContractFailure(`studio.host/unexpected-resource-result`,`The resource port returned a malformed, mismatched, duplicate, or oversized search page.`);return{...i.revision===void 0?{}:{revision:i.revision},value:s(i.value)}}async#storeRecovery(e){this.#assertActive();let t=this.#adapter.recovery;if(t===void 0)throw adapterContractFailure(`studio.host/adapter-port-unavailable`,`The negotiated recovery adapter is unavailable.`);let n=s(e),r=mutationFingerprint(n,this.#configuration),i=this.#mutationKey(x,r),a=createContext(this.#configuration,this.#identifiers.requestId(x),{idempotencyKey:i,operationId:x}),o=await this.#invoke(()=>t.store(n,a));return this.#clearMutationKey(x,r),o}#assertActive(){if(this.#invalidationFailure!==void 0)throw this.#invalidationFailure;if(this.#disposed)throw new StudioHostSessionError(`disposed`,`The Studio host 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=normalizeHostRejection(e);throw isStaleGenerationFailure(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}}export class SessionIdentifierAllocator{#factories;#idempotencyIntents=new Map;#requestIds=new Set;constructor(e){this.#factories=e}dispose(){this.#idempotencyIntents.clear(),this.#requestIds.clear()}idempotencyKey(e,t){let n=j(e=>this.#factories.idempotencyKey(e),e,`idempotency`),r=`${e}\u0000${n}`,i=this.#idempotencyIntents.get(r);if(i!==void 0&&i!==t)throw new StudioHostSessionError(`invalid-identifier`,`The idempotency-key factory reused a key for another mutation intent.`);return this.#idempotencyIntents.set(r,t),n}requestId(e){let t=j(e=>this.#factories.requestId(e),e,`request`);if(this.#requestIds.has(t))throw new StudioHostSessionError(`invalid-identifier`,`The request-ID factory returned an identifier already used by this session.`);return this.#requestIds.add(t),t}}function j(e,t,n){let r;try{r=e(t)}catch{throw new StudioHostSessionError(`invalid-identifier`,`The ${n}-ID factory failed to allocate an identifier.`)}if(!Q(r))throw new StudioHostSessionError(`invalid-identifier`,`The ${n}-ID factory returned a non-canonical stable identifier.`);return r}function ee(e,t,n){let r=t.hostCapabilities.ports.find(e=>e.id===p);if(r!==void 0){let e=[_];t.sessionState===`editable`&&e.push(v);for(let t of e)r.operations.includes(t)||n.diagnostics.push(createDiagnostic(`studio.host/missing-required-operation`,`The host does not advertise the required ${t} operation.`,`blocking`,{operationId:t}))}if(!t.features.offlineRecovery)return!1;let i=t.hostCapabilities.ports.find(e=>e.id===h);if(i===void 0)return!1;let a=!0;for(let e of[x,S,C])i.operations.includes(e)||(a=!1,n.diagnostics.push(createDiagnostic(`studio.host/missing-optional-operation`,`The optional recovery port omits ${e}; recovery is disabled.`,`information`,{operationId:e})));return e.recovery===void 0&&(a=!1,n.diagnostics.push(createDiagnostic(`studio.host/adapter-port-unavailable`,`The capability document advertises recovery but the adapter does not implement it.`,`information`,{port:h}))),a}function te(e,t,n){let r=t.hostCapabilities.ports.find(e=>e.id===m);if(r===void 0)return!1;let i=!0;for(let e of[b,y])r.operations.includes(e)||(i=!1,n.diagnostics.push(createDiagnostic(`studio.host/missing-optional-operation`,`The model port omits ${e}; model binding is disabled.`,`information`,{operationId:e})));return e.model===void 0&&(i=!1,n.diagnostics.push(createDiagnostic(`studio.host/adapter-port-unavailable`,`The capability document advertises model reads but the adapter does not implement them.`,`information`,{port:m}))),i}function ne(e,t,n){let r=t.hostCapabilities.ports.find(e=>e.id===g);if(r===void 0)return!1;let i=!0;return r.operations.includes(w)||(i=!1,n.diagnostics.push(createDiagnostic(`studio.host/missing-optional-operation`,`The resource port omits ${w}; resource discovery is disabled.`,`information`,{operationId:w}))),e.resource===void 0&&(i=!1,n.diagnostics.push(createDiagnostic(`studio.host/adapter-port-unavailable`,`The capability document advertises resource discovery but the adapter does not implement it.`,`information`,{port:g}))),i}function M(e,t){e.artifacts.blueprint===void 0&&t.diagnostics.push(createDiagnostic(`studio.host/missing-blueprint-artifact`,`A Blueprint session requires a locked Blueprint artifact reference.`,`blocking`)),(e.mode!==`blueprint`||e.composite!==`single`)&&t.diagnostics.push(createDiagnostic(`studio.host/unsupported-session-profile`,`This host-session profile opens only single Blueprint configurations.`,`blocking`,{composite:e.composite,mode:e.mode}))}function N(e,t){let n=new Set(t??[]);return n.delete(p),e.features.offlineRecovery&&n.add(h),e.hostCapabilities.ports.some(e=>e.id===m)&&n.add(m),e.hostCapabilities.ports.some(e=>e.id===g)&&n.add(g),[...n]}export function createContext(e,t,n){return{...n.expectedRevision===void 0?{}:{expectedRevision:n.expectedRevision},...n.idempotencyKey===void 0?{}:{idempotencyKey:n.idempotencyKey},locale:e.locale.resolved,operationId:n.operationId,protocolVersion:e.protocolVersion,requestId:t,resourceContextKey:e.resourceContext.key,sessionGeneration:e.sessionGeneration}}export function createDiagnostic(e,t,n,r){return{code:e,message:{defaultMessage:t,key:e},...r===void 0?{}:{parameters:r},severity:n}}function P(e,t){let n=t??e.revision;if(!$(n))throw new StudioHostSessionError(`unexpected-artifact`,`The loaded Blueprint does not carry a valid accepted revision.`,[createDiagnostic(`studio.host/missing-accepted-revision`,`The loaded Blueprint does not carry a valid accepted revision.`,`blocking`)]);return s({...e,revision:n})}function F(e,t){if(typeof e!=`object`||!e||Array.isArray(e)||!(`value`in e))return!1;let n=e.value;return typeof n==`object`&&!!n&&!Array.isArray(n)&&`kind`in n&&n.kind===`blueprint`&&`id`in n&&n.id===t}function I(e,t){if(!q(e)||!J(e.value))return!1;let n=X(t);return e.value.id===t.id&&e.value.version===t.version&&(n===void 0||e.value.revision===n)&&(e.revision===void 0||e.revision===e.value.revision)}function L(e){if(!q(e)||!Array.isArray(e.value))return!1;let t=new Set;for(let n of e.value){if(!J(n))return!1;let e=`${n.id}\u0000${n.version}\u0000${n.revision}`;if(t.has(e))return!1;t.add(e)}return!0}function R(e){return!G(e)||!K(e,[`limit`,`resourceType`],[`cursor`,`search`])?!1:typeof e.limit==`number`&&Number.isSafeInteger(e.limit)&&e.limit>=STUDIO_RESOURCE_SEARCH_LIMITS.minimumLimit&&e.limit<=STUDIO_RESOURCE_SEARCH_LIMITS.maximumLimit&&U(e.resourceType)&&W(e.cursor,STUDIO_RESOURCE_SEARCH_LIMITS.maximumCursorLength,!1)&&W(e.search,STUDIO_RESOURCE_SEARCH_LIMITS.maximumSearchLength,!0)}function z(e,t){return!(!q(e)||!B(e.value,t))}function B(e,t){if(!G(e)||!K(e,[`items`],[`nextCursor`])||!Array.isArray(e.items)||e.items.length>t.limit||!W(e.nextCursor,STUDIO_RESOURCE_SEARCH_LIMITS.maximumCursorLength,!1))return!1;let n=new Set;for(let r of e.items){if(!V(r,t.resourceType)||n.has(r.id))return!1;n.add(r.id)}return!0}function V(e,t){return G(e)&&K(e,[`id`,`label`,`resourceType`])&&Q(e.id)&&e.resourceType===t&&H(e.label)}function H(e){return G(e)&&K(e,[`key`],[`defaultMessage`])&&U(e.key)&&(e.defaultMessage===void 0||typeof e.defaultMessage==`string`&&e.defaultMessage.length>=1&&e.defaultMessage.length<=500)}function U(e){return typeof e==`string`&&e.length<=160&&E.test(e)}function W(e,t,n){return e===void 0||typeof e==`string`&&e.length<=t&&(n||e.length>=1)}function G(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function K(e,t,n=[]){let r=new Set([...t,...n]);return t.every(t=>Object.hasOwn(e,t))&&Object.keys(e).every(e=>r.has(e))}function q(e){return typeof e!=`object`||!e||Array.isArray(e)||!(`value`in e)?!1:!(`revision`in e)||$(e.revision)}function J(e){return O.validate(e)}function Y(e){return k.validate(e)}function X(e){let t=e;return $(t.revision)?t.revision:void 0}function re(e,t){return Z(e.id,t.id)||Z(e.version,t.version)||Z(e.revision,t.revision)}function Z(e,t){return e<t?-1:+(e>t)}export function mutationFingerprint(e,t,n){return o({argument:e,context:{...n===void 0?{}:{expectedRevision:n},locale:t.locale.resolved,protocolVersion:t.protocolVersion}})}async function ie(e){try{return await e()}catch(e){throw normalizeHostRejection(e)}}export function normalizeHostRejection(e){return a(e)?e:adapterContractFailure(`studio.host/invalid-failure-wrapper`,`The host adapter rejected without a canonical HostPortFailure.`)}export function adapterContractFailure(n,r){let i={category:`internal`,contractVersion:t,diagnostics:[createDiagnostic(n,r,`error`)],kind:`host-error`,message:{defaultMessage:r,key:n},retryable:!1};return new e(i)}export function isStaleGenerationFailure(e){return e.error.category===`invalid-request`&&(e.error.diagnostics?.some(e=>e.code===n)??!1)}function ae(e){return{availablePorts:[...e.availablePorts],diagnostics:s(e.diagnostics),missingOptionalPorts:[...e.missingOptionalPorts],missingRequiredPorts:[...e.missingRequiredPorts],...e.protocolVersion===void 0?{}:{protocolVersion:e.protocolVersion},sessionState:e.sessionState}}function Q(e){return typeof e==`string`&&e.length>=1&&e.length<=240&&!D.has(e)&&T.test(e)}function $(e){return typeof e==`string`&&e.length>=1&&e.length<=200}
@@ -0,0 +1,29 @@
1
+ import type { QualifiedName } from '@kumwe/studio-protocol';
2
+ export declare const AUTHORING_HTTP_SCHEMA_ID: "https://schemas.kumwe.org/studio/v1/authoring-http.schema.json";
3
+ export type AuthoringHttpRoute = 'authoring/list-types' | 'authoring/plan-save' | 'authoring/resolve-target' | 'authoring/save-as-new-type' | 'authoring/save-item' | 'authoring/save-new-type-version' | 'authoring/start';
4
+ export interface AuthoringHttpOperationContract {
5
+ capability: QualifiedName;
6
+ mutating: boolean;
7
+ requestSchema: string;
8
+ responseSchema: string;
9
+ route: AuthoringHttpRoute;
10
+ }
11
+ export interface AuthoringHttpOperationRegistry {
12
+ listTypes: AuthoringHttpOperationContract;
13
+ planSave: AuthoringHttpOperationContract;
14
+ resolveTarget: AuthoringHttpOperationContract;
15
+ saveAsNewType: AuthoringHttpOperationContract;
16
+ saveItem: AuthoringHttpOperationContract;
17
+ saveNewTypeVersion: AuthoringHttpOperationContract;
18
+ start: AuthoringHttpOperationContract;
19
+ }
20
+ /** Validates one value against an exact canonical schema reference. */
21
+ export type HttpSchemaValidator = (schemaReference: string, value: unknown) => boolean;
22
+ /**
23
+ * Exact public route/capability/schema binding for contextual authoring.
24
+ * The JSON Schema remains the language-neutral source of serialized shape;
25
+ * this table prevents the TypeScript reference transport from drifting from it.
26
+ */
27
+ export declare const AUTHORING_HTTP_OPERATIONS: Readonly<AuthoringHttpOperationRegistry>;
28
+ export declare const AUTHORING_HTTP_OPERATIONS_BY_ROUTE: ReadonlyMap<AuthoringHttpRoute, AuthoringHttpOperationContract>;
29
+ //# sourceMappingURL=http-authoring-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-authoring-contract.d.ts","sourceRoot":"","sources":["../src/http-authoring-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,eAAO,MAAM,wBAAwB,EACnC,gEAAyE,CAAC;AAE5E,MAAM,MAAM,kBAAkB,GAC1B,sBAAsB,GACtB,qBAAqB,GACrB,0BAA0B,GAC1B,4BAA4B,GAC5B,qBAAqB,GACrB,iCAAiC,GACjC,iBAAiB,CAAC;AAEtB,MAAM,WAAW,8BAA8B;IAC7C,UAAU,EAAE,aAAa,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,kBAAkB,CAAC;CAC3B;AAED,MAAM,WAAW,8BAA8B;IAC7C,SAAS,EAAE,8BAA8B,CAAC;IAC1C,QAAQ,EAAE,8BAA8B,CAAC;IACzC,aAAa,EAAE,8BAA8B,CAAC;IAC9C,aAAa,EAAE,8BAA8B,CAAC;IAC9C,QAAQ,EAAE,8BAA8B,CAAC;IACzC,kBAAkB,EAAE,8BAA8B,CAAC;IACnD,KAAK,EAAE,8BAA8B,CAAC;CACvC;AAED,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;AAiBvF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,8BAA8B,CAsC7E,CAAC;AAEH,eAAO,MAAM,kCAAkC,EAAE,WAAW,CAC1D,kBAAkB,EAClB,8BAA8B,CACmE,CAAC"}
@@ -0,0 +1 @@
1
+ export const AUTHORING_HTTP_SCHEMA_ID=`https://schemas.kumwe.org/studio/v1/authoring-http.schema.json`;function t(t,n,r,i){return Object.freeze({capability:n,mutating:i,requestSchema:`${AUTHORING_HTTP_SCHEMA_ID}#/$defs/${r}Request`,responseSchema:`${AUTHORING_HTTP_SCHEMA_ID}#/$defs/${r}Result`,route:t})}export const AUTHORING_HTTP_OPERATIONS=Object.freeze({listTypes:t(`authoring/list-types`,`studio.operation/authoring.list-types`,`listTypes`,!1),planSave:t(`authoring/plan-save`,`studio.operation/authoring.plan-save`,`planSave`,!1),resolveTarget:t(`authoring/resolve-target`,`studio.operation/authoring.resolve-target`,`resolveTarget`,!1),saveAsNewType:t(`authoring/save-as-new-type`,`studio.operation/authoring.save-as-new-type`,`saveAsNewType`,!0),saveItem:t(`authoring/save-item`,`studio.operation/authoring.save-item`,`saveItem`,!0),saveNewTypeVersion:t(`authoring/save-new-type-version`,`studio.operation/authoring.save-new-type-version`,`saveNewTypeVersion`,!0),start:t(`authoring/start`,`studio.operation/authoring.start`,`start`,!0)});export const AUTHORING_HTTP_OPERATIONS_BY_ROUTE=new Map(Object.values(AUTHORING_HTTP_OPERATIONS).map(e=>[e.route,e]));