@openfairygui/backend 0.2.0-alpha.6 → 0.2.0-alpha.8

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.
@@ -95,7 +95,13 @@ interface BackendCapabilityManifest {
95
95
  adapters: {
96
96
  fileSystem: {
97
97
  injected: true;
98
- requiredFor: readonly ['openSession', 'saveSession'];
98
+ requiredFor: readonly ['openSession', 'saveSession', 'materializeSession'];
99
+ };
100
+ projectStorage: {
101
+ injected: true;
102
+ browserSafe: true;
103
+ requiredFor: readonly ['openProjectSession.writeback', 'saveSession', 'materializeSession'];
104
+ adapterFactory: 'createBackendStorageFileSystem';
99
105
  };
100
106
  host: {
101
107
  injected: true;
@@ -119,7 +125,7 @@ interface BackendCapabilities {
119
125
  transactionKernelOwner: '@openfairygui/core';
120
126
  appSeamOwner: '@openfairygui/functions';
121
127
  runtimeOwner: '@openfairygui/backend';
122
- methods: readonly ['getCapabilities', 'openSession', 'openProjectSession', 'getSession', 'applyTransaction', 'saveSession', 'closeSession', 'getEvents', 'getJob', 'listJobs', 'cancelJob', 'getCacheSnapshot', 'refreshCache'];
128
+ methods: readonly ['getCapabilities', 'openSession', 'openProjectSession', 'getSession', 'applyTransaction', 'saveSession', 'materializeSession', 'closeSession', 'getEvents', 'getJob', 'listJobs', 'cancelJob', 'getCacheSnapshot', 'refreshCache'];
123
129
  read: {
124
130
  capabilitySnapshot: true;
125
131
  sessionSnapshot: true;
@@ -190,6 +196,15 @@ interface BackendSessionSnapshot {
190
196
  lockHeld: boolean;
191
197
  capabilities: BackendCapabilities;
192
198
  }
199
+ interface MaterializeSessionSnapshot extends BackendSessionSnapshot {
200
+ mode: 'fullProject';
201
+ reason?: string;
202
+ materializeRevision: number;
203
+ saveRevision: number;
204
+ writtenPaths: string[];
205
+ skippedPaths: string[];
206
+ diagnostics: BackendDiagnostic[];
207
+ }
193
208
  interface BackendSuccess<T> {
194
209
  ok: true;
195
210
  meta: BackendResponseMeta;
@@ -242,6 +257,27 @@ interface SavePartialFailureError {
242
257
  failedPaths: string[];
243
258
  diskMayBePartiallyUpdated: true;
244
259
  }
260
+ interface MaterializeValidationFailedError {
261
+ code: 'materialize_validation_failed';
262
+ message: string;
263
+ sessionId: string;
264
+ canonicalPathKey: string;
265
+ issueCount: number;
266
+ diagnostics: BackendDiagnostic[];
267
+ }
268
+ interface MaterializeWriteFailedError {
269
+ code: 'write_failed';
270
+ message: string;
271
+ sessionId: string;
272
+ canonicalPathKey: string;
273
+ attemptedRevision: number;
274
+ lastSavedRevision: number;
275
+ writtenPaths: string[];
276
+ failedPaths: string[];
277
+ skippedPaths: string[];
278
+ diagnostics: BackendDiagnostic[];
279
+ diskMayBePartiallyUpdated: true;
280
+ }
245
281
  type BackendEventKind = 'session.opened' | 'transaction.applied' | 'transaction.rejected' | 'save.started' | 'save.completed' | 'save.failed' | 'session.closeRequested' | 'session.closed' | 'cache.invalidated' | 'cache.updated' | 'job.created' | 'job.started' | 'job.progress' | 'job.cancelRequested' | 'job.cancelled' | 'job.completed' | 'job.failed';
246
282
  interface BackendEvent {
247
283
  sequence: number;
@@ -373,7 +409,7 @@ interface RefreshCacheInput {
373
409
  sessionId: string;
374
410
  reason?: 'manual' | 'session_open' | 'after_save';
375
411
  }
376
- type BackendError = SessionNotFoundError | SessionStaleWriteError | InProcessLockConflictError | AdvisoryLockConflictError | SavePartialFailureError | PathPolicyViolationError | EventCursorInvalidError | BackendJobNotFoundError | BackendJobNotCancellableError | BackendJobCancelledError | CacheRefreshFailedError | BackendCapabilityUnavailableError | ApplyUamTransactionAppError;
412
+ type BackendError = SessionNotFoundError | SessionStaleWriteError | InProcessLockConflictError | AdvisoryLockConflictError | SavePartialFailureError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | EventCursorInvalidError | BackendJobNotFoundError | BackendJobNotCancellableError | BackendJobCancelledError | CacheRefreshFailedError | BackendCapabilityUnavailableError | ApplyUamTransactionAppError;
377
413
  interface ApplySessionTransactionInput {
378
414
  sessionId: string;
379
415
  expectedRevision: number;
@@ -384,6 +420,30 @@ interface OpenProjectSessionInput {
384
420
  sessionId?: string;
385
421
  canonicalProjectPath?: string;
386
422
  canonicalPathKey?: string;
423
+ storage?: BackendProjectSessionStorage;
424
+ }
425
+ interface BackendProjectSessionStorage {
426
+ fileSystem: BackendFileSystem;
427
+ fairyPath: string;
428
+ canonicalProjectPath?: string;
429
+ canonicalPathKey?: string;
430
+ }
431
+ interface SaveSessionInput {
432
+ sessionId: string;
433
+ expectedRevision?: number;
434
+ targetPath?: string;
435
+ fileSystem?: BackendFileSystem;
436
+ force?: boolean;
437
+ mode?: 'materializeCleanSession';
438
+ }
439
+ interface MaterializeSessionInput {
440
+ sessionId: string;
441
+ expectedRevision?: number;
442
+ storage?: BackendProjectSessionStorage;
443
+ targetPath?: string;
444
+ fileSystem?: BackendFileSystem;
445
+ mode?: 'fullProject';
446
+ reason?: string;
387
447
  }
388
448
  interface BackendRuntimeOptions {
389
449
  fileSystem?: BackendFileSystem;
@@ -415,11 +475,8 @@ declare class BackendRuntime {
415
475
  sessionId: string;
416
476
  }): BackendResult<BackendSessionSnapshot, SessionNotFoundError>;
417
477
  applyTransaction(input: ApplySessionTransactionInput): Promise<BackendResult<BackendSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | ApplyUamTransactionAppError>>;
418
- saveSession(input: {
419
- sessionId: string;
420
- expectedRevision?: number;
421
- targetPath?: string;
422
- }): Promise<BackendResult<BackendSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | SavePartialFailureError | PathPolicyViolationError | BackendCapabilityUnavailableError>>;
478
+ saveSession(input: SaveSessionInput): Promise<BackendResult<BackendSessionSnapshot | MaterializeSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | SavePartialFailureError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | InProcessLockConflictError | BackendCapabilityUnavailableError>>;
479
+ materializeSession(input: MaterializeSessionInput): Promise<BackendResult<MaterializeSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | InProcessLockConflictError | BackendCapabilityUnavailableError>>;
423
480
  closeSession(input: {
424
481
  sessionId: string;
425
482
  }): Promise<BackendResult<{
@@ -434,4 +491,4 @@ declare class BackendRuntime {
434
491
  refreshCache(input: RefreshCacheInput): BackendResult<BackendJobSnapshot, SessionNotFoundError>;
435
492
  }
436
493
  //#endregion
437
- export { BackendSuccess as A, OpenProjectSessionInput as B, BackendJobProgress as C, BackendRuntime as D, BackendResult as E, GetEventsInput as F, BACKEND_CAPABILITY_SCHEMA_VERSION as G, SavePartialFailureError as H, GetEventsSnapshot as I, BackendDiagnostic as J, BACKEND_COMPATIBILITY_POLICY as K, GetJobInput as L, CancelJobInput as M, EventCursorInvalidError as N, BackendRuntimeOptions as O, GetCacheSnapshotInput as P, InProcessLockConflictError as R, BackendJobNotFoundError as S, BackendJobStatus as T, SessionNotFoundError as U, RefreshCacheInput as V, SessionStaleWriteError as W, BackendResponseMeta as X, BackendMessage as Y, BackendStage as Z, BackendJobErrors as _, BackendCacheSnapshot as a, BackendJobListStatusFilter as b, BackendCapabilityUnavailableError as c, BackendEventKind as d, BackendFailure as f, BackendHostAdapter as g, BackendFileSystem as h, BackendCacheEntry as i, CacheRefreshFailedError as j, BackendSessionSnapshot as k, BackendError as l, BackendFileStat as m, ApplySessionTransactionInput as n, BackendCapabilities as o, BackendFileHandle as p, BACKEND_CONTRACT_VERSION as q, BackendArtifactBridgeCapability as r, BackendCapabilityManifest as s, AdvisoryLockConflictError as t, BackendEvent as u, BackendJobKind as v, BackendJobSnapshot as w, BackendJobNotCancellableError as x, BackendJobListSnapshot as y, ListJobsInput as z };
494
+ export { BACKEND_CONTRACT_VERSION as $, BackendSessionSnapshot as A, ListJobsInput as B, BackendJobProgress as C, BackendResult as D, BackendProjectSessionStorage as E, GetCacheSnapshotInput as F, OpenProjectSessionInput as G, MaterializeSessionSnapshot as H, GetEventsInput as I, SaveSessionInput as J, RefreshCacheInput as K, GetEventsSnapshot as L, CacheRefreshFailedError as M, CancelJobInput as N, BackendRuntime as O, EventCursorInvalidError as P, BACKEND_COMPATIBILITY_POLICY as Q, GetJobInput as R, BackendJobNotFoundError as S, BackendJobStatus as T, MaterializeValidationFailedError as U, MaterializeSessionInput as V, MaterializeWriteFailedError as W, SessionStaleWriteError as X, SessionNotFoundError as Y, BACKEND_CAPABILITY_SCHEMA_VERSION as Z, BackendJobErrors as _, BackendCacheSnapshot as a, BackendJobListStatusFilter as b, BackendCapabilityUnavailableError as c, BackendEventKind as d, BackendDiagnostic as et, BackendFailure as f, BackendHostAdapter as g, BackendFileSystem as h, BackendCacheEntry as i, BackendSuccess as j, BackendRuntimeOptions as k, BackendError as l, BackendFileStat as m, ApplySessionTransactionInput as n, BackendResponseMeta as nt, BackendCapabilities as o, BackendFileHandle as p, SavePartialFailureError as q, BackendArtifactBridgeCapability as r, BackendStage as rt, BackendCapabilityManifest as s, AdvisoryLockConflictError as t, BackendMessage as tt, BackendEvent as u, BackendJobKind as v, BackendJobSnapshot as w, BackendJobNotCancellableError as x, BackendJobListSnapshot as y, InProcessLockConflictError as z };
@@ -95,7 +95,13 @@ interface BackendCapabilityManifest {
95
95
  adapters: {
96
96
  fileSystem: {
97
97
  injected: true;
98
- requiredFor: readonly ['openSession', 'saveSession'];
98
+ requiredFor: readonly ['openSession', 'saveSession', 'materializeSession'];
99
+ };
100
+ projectStorage: {
101
+ injected: true;
102
+ browserSafe: true;
103
+ requiredFor: readonly ['openProjectSession.writeback', 'saveSession', 'materializeSession'];
104
+ adapterFactory: 'createBackendStorageFileSystem';
99
105
  };
100
106
  host: {
101
107
  injected: true;
@@ -119,7 +125,7 @@ interface BackendCapabilities {
119
125
  transactionKernelOwner: '@openfairygui/core';
120
126
  appSeamOwner: '@openfairygui/functions';
121
127
  runtimeOwner: '@openfairygui/backend';
122
- methods: readonly ['getCapabilities', 'openSession', 'openProjectSession', 'getSession', 'applyTransaction', 'saveSession', 'closeSession', 'getEvents', 'getJob', 'listJobs', 'cancelJob', 'getCacheSnapshot', 'refreshCache'];
128
+ methods: readonly ['getCapabilities', 'openSession', 'openProjectSession', 'getSession', 'applyTransaction', 'saveSession', 'materializeSession', 'closeSession', 'getEvents', 'getJob', 'listJobs', 'cancelJob', 'getCacheSnapshot', 'refreshCache'];
123
129
  read: {
124
130
  capabilitySnapshot: true;
125
131
  sessionSnapshot: true;
@@ -190,6 +196,15 @@ interface BackendSessionSnapshot {
190
196
  lockHeld: boolean;
191
197
  capabilities: BackendCapabilities;
192
198
  }
199
+ interface MaterializeSessionSnapshot extends BackendSessionSnapshot {
200
+ mode: 'fullProject';
201
+ reason?: string;
202
+ materializeRevision: number;
203
+ saveRevision: number;
204
+ writtenPaths: string[];
205
+ skippedPaths: string[];
206
+ diagnostics: BackendDiagnostic[];
207
+ }
193
208
  interface BackendSuccess<T> {
194
209
  ok: true;
195
210
  meta: BackendResponseMeta;
@@ -242,6 +257,27 @@ interface SavePartialFailureError {
242
257
  failedPaths: string[];
243
258
  diskMayBePartiallyUpdated: true;
244
259
  }
260
+ interface MaterializeValidationFailedError {
261
+ code: 'materialize_validation_failed';
262
+ message: string;
263
+ sessionId: string;
264
+ canonicalPathKey: string;
265
+ issueCount: number;
266
+ diagnostics: BackendDiagnostic[];
267
+ }
268
+ interface MaterializeWriteFailedError {
269
+ code: 'write_failed';
270
+ message: string;
271
+ sessionId: string;
272
+ canonicalPathKey: string;
273
+ attemptedRevision: number;
274
+ lastSavedRevision: number;
275
+ writtenPaths: string[];
276
+ failedPaths: string[];
277
+ skippedPaths: string[];
278
+ diagnostics: BackendDiagnostic[];
279
+ diskMayBePartiallyUpdated: true;
280
+ }
245
281
  type BackendEventKind = 'session.opened' | 'transaction.applied' | 'transaction.rejected' | 'save.started' | 'save.completed' | 'save.failed' | 'session.closeRequested' | 'session.closed' | 'cache.invalidated' | 'cache.updated' | 'job.created' | 'job.started' | 'job.progress' | 'job.cancelRequested' | 'job.cancelled' | 'job.completed' | 'job.failed';
246
282
  interface BackendEvent {
247
283
  sequence: number;
@@ -373,7 +409,7 @@ interface RefreshCacheInput {
373
409
  sessionId: string;
374
410
  reason?: 'manual' | 'session_open' | 'after_save';
375
411
  }
376
- type BackendError = SessionNotFoundError | SessionStaleWriteError | InProcessLockConflictError | AdvisoryLockConflictError | SavePartialFailureError | PathPolicyViolationError | EventCursorInvalidError | BackendJobNotFoundError | BackendJobNotCancellableError | BackendJobCancelledError | CacheRefreshFailedError | BackendCapabilityUnavailableError | ApplyUamTransactionAppError;
412
+ type BackendError = SessionNotFoundError | SessionStaleWriteError | InProcessLockConflictError | AdvisoryLockConflictError | SavePartialFailureError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | EventCursorInvalidError | BackendJobNotFoundError | BackendJobNotCancellableError | BackendJobCancelledError | CacheRefreshFailedError | BackendCapabilityUnavailableError | ApplyUamTransactionAppError;
377
413
  interface ApplySessionTransactionInput {
378
414
  sessionId: string;
379
415
  expectedRevision: number;
@@ -384,6 +420,30 @@ interface OpenProjectSessionInput {
384
420
  sessionId?: string;
385
421
  canonicalProjectPath?: string;
386
422
  canonicalPathKey?: string;
423
+ storage?: BackendProjectSessionStorage;
424
+ }
425
+ interface BackendProjectSessionStorage {
426
+ fileSystem: BackendFileSystem;
427
+ fairyPath: string;
428
+ canonicalProjectPath?: string;
429
+ canonicalPathKey?: string;
430
+ }
431
+ interface SaveSessionInput {
432
+ sessionId: string;
433
+ expectedRevision?: number;
434
+ targetPath?: string;
435
+ fileSystem?: BackendFileSystem;
436
+ force?: boolean;
437
+ mode?: 'materializeCleanSession';
438
+ }
439
+ interface MaterializeSessionInput {
440
+ sessionId: string;
441
+ expectedRevision?: number;
442
+ storage?: BackendProjectSessionStorage;
443
+ targetPath?: string;
444
+ fileSystem?: BackendFileSystem;
445
+ mode?: 'fullProject';
446
+ reason?: string;
387
447
  }
388
448
  interface BackendRuntimeOptions {
389
449
  fileSystem?: BackendFileSystem;
@@ -415,11 +475,8 @@ declare class BackendRuntime {
415
475
  sessionId: string;
416
476
  }): BackendResult<BackendSessionSnapshot, SessionNotFoundError>;
417
477
  applyTransaction(input: ApplySessionTransactionInput): Promise<BackendResult<BackendSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | ApplyUamTransactionAppError>>;
418
- saveSession(input: {
419
- sessionId: string;
420
- expectedRevision?: number;
421
- targetPath?: string;
422
- }): Promise<BackendResult<BackendSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | SavePartialFailureError | PathPolicyViolationError | BackendCapabilityUnavailableError>>;
478
+ saveSession(input: SaveSessionInput): Promise<BackendResult<BackendSessionSnapshot | MaterializeSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | SavePartialFailureError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | InProcessLockConflictError | BackendCapabilityUnavailableError>>;
479
+ materializeSession(input: MaterializeSessionInput): Promise<BackendResult<MaterializeSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | InProcessLockConflictError | BackendCapabilityUnavailableError>>;
423
480
  closeSession(input: {
424
481
  sessionId: string;
425
482
  }): Promise<BackendResult<{
@@ -434,4 +491,4 @@ declare class BackendRuntime {
434
491
  refreshCache(input: RefreshCacheInput): BackendResult<BackendJobSnapshot, SessionNotFoundError>;
435
492
  }
436
493
  //#endregion
437
- export { BackendSuccess as A, OpenProjectSessionInput as B, BackendJobProgress as C, BackendRuntime as D, BackendResult as E, GetEventsInput as F, BACKEND_CAPABILITY_SCHEMA_VERSION as G, SavePartialFailureError as H, GetEventsSnapshot as I, BackendDiagnostic as J, BACKEND_COMPATIBILITY_POLICY as K, GetJobInput as L, CancelJobInput as M, EventCursorInvalidError as N, BackendRuntimeOptions as O, GetCacheSnapshotInput as P, InProcessLockConflictError as R, BackendJobNotFoundError as S, BackendJobStatus as T, SessionNotFoundError as U, RefreshCacheInput as V, SessionStaleWriteError as W, BackendResponseMeta as X, BackendMessage as Y, BackendStage as Z, BackendJobErrors as _, BackendCacheSnapshot as a, BackendJobListStatusFilter as b, BackendCapabilityUnavailableError as c, BackendEventKind as d, BackendFailure as f, BackendHostAdapter as g, BackendFileSystem as h, BackendCacheEntry as i, CacheRefreshFailedError as j, BackendSessionSnapshot as k, BackendError as l, BackendFileStat as m, ApplySessionTransactionInput as n, BackendCapabilities as o, BackendFileHandle as p, BACKEND_CONTRACT_VERSION as q, BackendArtifactBridgeCapability as r, BackendCapabilityManifest as s, AdvisoryLockConflictError as t, BackendEvent as u, BackendJobKind as v, BackendJobSnapshot as w, BackendJobNotCancellableError as x, BackendJobListSnapshot as y, ListJobsInput as z };
494
+ export { BACKEND_CONTRACT_VERSION as $, BackendSessionSnapshot as A, ListJobsInput as B, BackendJobProgress as C, BackendResult as D, BackendProjectSessionStorage as E, GetCacheSnapshotInput as F, OpenProjectSessionInput as G, MaterializeSessionSnapshot as H, GetEventsInput as I, SaveSessionInput as J, RefreshCacheInput as K, GetEventsSnapshot as L, CacheRefreshFailedError as M, CancelJobInput as N, BackendRuntime as O, EventCursorInvalidError as P, BACKEND_COMPATIBILITY_POLICY as Q, GetJobInput as R, BackendJobNotFoundError as S, BackendJobStatus as T, MaterializeValidationFailedError as U, MaterializeSessionInput as V, MaterializeWriteFailedError as W, SessionStaleWriteError as X, SessionNotFoundError as Y, BACKEND_CAPABILITY_SCHEMA_VERSION as Z, BackendJobErrors as _, BackendCacheSnapshot as a, BackendJobListStatusFilter as b, BackendCapabilityUnavailableError as c, BackendEventKind as d, BackendDiagnostic as et, BackendFailure as f, BackendHostAdapter as g, BackendFileSystem as h, BackendCacheEntry as i, BackendSuccess as j, BackendRuntimeOptions as k, BackendError as l, BackendFileStat as m, ApplySessionTransactionInput as n, BackendResponseMeta as nt, BackendCapabilities as o, BackendFileHandle as p, SavePartialFailureError as q, BackendArtifactBridgeCapability as r, BackendStage as rt, BackendCapabilityManifest as s, AdvisoryLockConflictError as t, BackendMessage as tt, BackendEvent as u, BackendJobKind as v, BackendJobSnapshot as w, BackendJobNotCancellableError as x, BackendJobListSnapshot as y, InProcessLockConflictError as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfairygui/backend",
3
- "version": "0.2.0-alpha.6",
3
+ "version": "0.2.0-alpha.8",
4
4
  "description": "FairyGUI Headless Authoring SDK — stateful backend runtime and session services.",
5
5
  "author": "OpenFairyGUI Contributors",
6
6
  "license": "MIT",
@@ -52,8 +52,8 @@
52
52
  "runtime"
53
53
  ],
54
54
  "dependencies": {
55
- "@openfairygui/core": "0.2.0-alpha.6",
56
- "@openfairygui/functions": "0.2.0-alpha.6"
55
+ "@openfairygui/core": "0.2.0-alpha.8",
56
+ "@openfairygui/functions": "0.2.0-alpha.8"
57
57
  },
58
58
  "devDependencies": {
59
59
  "ava": "^7.0.0",
package/src/index.ts CHANGED
@@ -38,12 +38,24 @@ export {
38
38
  type GetJobInput,
39
39
  type InProcessLockConflictError,
40
40
  type ListJobsInput,
41
+ type MaterializeSessionInput,
42
+ type MaterializeSessionSnapshot,
43
+ type MaterializeValidationFailedError,
44
+ type MaterializeWriteFailedError,
41
45
  type OpenProjectSessionInput,
46
+ type BackendProjectSessionStorage,
42
47
  type RefreshCacheInput,
48
+ type SaveSessionInput,
43
49
  type SavePartialFailureError,
44
50
  type SessionNotFoundError,
45
51
  type SessionStaleWriteError,
46
52
  } from './runtime.js';
53
+ export {
54
+ createBackendStorageFileSystem,
55
+ type BackendAsyncStorageAdapter,
56
+ type BackendStorageFileSystem,
57
+ type BackendStorageStatLike,
58
+ } from './storage.js';
47
59
  export {
48
60
  type BackendDiagnostic,
49
61
  type BackendMessage,
package/src/runtime.ts CHANGED
@@ -66,7 +66,13 @@ export interface BackendCapabilityManifest {
66
66
  adapters: {
67
67
  fileSystem: {
68
68
  injected: true;
69
- requiredFor: readonly ['openSession', 'saveSession'];
69
+ requiredFor: readonly ['openSession', 'saveSession', 'materializeSession'];
70
+ };
71
+ projectStorage: {
72
+ injected: true;
73
+ browserSafe: true;
74
+ requiredFor: readonly ['openProjectSession.writeback', 'saveSession', 'materializeSession'];
75
+ adapterFactory: 'createBackendStorageFileSystem';
70
76
  };
71
77
  host: {
72
78
  injected: true;
@@ -98,6 +104,7 @@ export interface BackendCapabilities {
98
104
  'getSession',
99
105
  'applyTransaction',
100
106
  'saveSession',
107
+ 'materializeSession',
101
108
  'closeSession',
102
109
  'getEvents',
103
110
  'getJob',
@@ -178,6 +185,16 @@ export interface BackendSessionSnapshot {
178
185
  capabilities: BackendCapabilities;
179
186
  }
180
187
 
188
+ export interface MaterializeSessionSnapshot extends BackendSessionSnapshot {
189
+ mode: 'fullProject';
190
+ reason?: string;
191
+ materializeRevision: number;
192
+ saveRevision: number;
193
+ writtenPaths: string[];
194
+ skippedPaths: string[];
195
+ diagnostics: import('./contracts.js').BackendDiagnostic[];
196
+ }
197
+
181
198
  export interface BackendSuccess<T> {
182
199
  ok: true;
183
200
  meta: BackendResponseMeta;
@@ -238,6 +255,29 @@ export interface SavePartialFailureError {
238
255
  diskMayBePartiallyUpdated: true;
239
256
  }
240
257
 
258
+ export interface MaterializeValidationFailedError {
259
+ code: 'materialize_validation_failed';
260
+ message: string;
261
+ sessionId: string;
262
+ canonicalPathKey: string;
263
+ issueCount: number;
264
+ diagnostics: import('./contracts.js').BackendDiagnostic[];
265
+ }
266
+
267
+ export interface MaterializeWriteFailedError {
268
+ code: 'write_failed';
269
+ message: string;
270
+ sessionId: string;
271
+ canonicalPathKey: string;
272
+ attemptedRevision: number;
273
+ lastSavedRevision: number;
274
+ writtenPaths: string[];
275
+ failedPaths: string[];
276
+ skippedPaths: string[];
277
+ diagnostics: import('./contracts.js').BackendDiagnostic[];
278
+ diskMayBePartiallyUpdated: true;
279
+ }
280
+
241
281
  export type BackendEventKind =
242
282
  | 'session.opened'
243
283
  | 'transaction.applied'
@@ -418,6 +458,8 @@ export type BackendError =
418
458
  | InProcessLockConflictError
419
459
  | AdvisoryLockConflictError
420
460
  | SavePartialFailureError
461
+ | MaterializeValidationFailedError
462
+ | MaterializeWriteFailedError
421
463
  | PathPolicyViolationError
422
464
  | EventCursorInvalidError
423
465
  | BackendJobNotFoundError
@@ -438,6 +480,33 @@ export interface OpenProjectSessionInput {
438
480
  sessionId?: string;
439
481
  canonicalProjectPath?: string;
440
482
  canonicalPathKey?: string;
483
+ storage?: BackendProjectSessionStorage;
484
+ }
485
+
486
+ export interface BackendProjectSessionStorage {
487
+ fileSystem: BackendFileSystem;
488
+ fairyPath: string;
489
+ canonicalProjectPath?: string;
490
+ canonicalPathKey?: string;
491
+ }
492
+
493
+ export interface SaveSessionInput {
494
+ sessionId: string;
495
+ expectedRevision?: number;
496
+ targetPath?: string;
497
+ fileSystem?: BackendFileSystem;
498
+ force?: boolean;
499
+ mode?: 'materializeCleanSession';
500
+ }
501
+
502
+ export interface MaterializeSessionInput {
503
+ sessionId: string;
504
+ expectedRevision?: number;
505
+ storage?: BackendProjectSessionStorage;
506
+ targetPath?: string;
507
+ fileSystem?: BackendFileSystem;
508
+ mode?: 'fullProject';
509
+ reason?: string;
441
510
  }
442
511
 
443
512
  export interface BackendRuntimeOptions {
@@ -452,6 +521,7 @@ const BACKEND_METHODS = [
452
521
  'getSession',
453
522
  'applyTransaction',
454
523
  'saveSession',
524
+ 'materializeSession',
455
525
  'closeSession',
456
526
  'getEvents',
457
527
  'getJob',
@@ -502,7 +572,13 @@ function createCapabilities(): BackendCapabilities {
502
572
  adapters: {
503
573
  fileSystem: {
504
574
  injected: true,
505
- requiredFor: ['openSession', 'saveSession'],
575
+ requiredFor: ['openSession', 'saveSession', 'materializeSession'],
576
+ },
577
+ projectStorage: {
578
+ injected: true,
579
+ browserSafe: true,
580
+ requiredFor: ['openProjectSession.writeback', 'saveSession', 'materializeSession'],
581
+ adapterFactory: 'createBackendStorageFileSystem',
506
582
  },
507
583
  host: {
508
584
  injected: true,
@@ -628,23 +704,37 @@ export class BackendRuntime {
628
704
  return this.authoringService.applyTransaction(input);
629
705
  }
630
706
 
631
- public async saveSession(input: {
632
- sessionId: string;
633
- expectedRevision?: number;
634
- targetPath?: string;
635
- }): Promise<
707
+ public async saveSession(input: SaveSessionInput): Promise<
636
708
  BackendResult<
637
- BackendSessionSnapshot,
709
+ BackendSessionSnapshot | MaterializeSessionSnapshot,
638
710
  | SessionNotFoundError
639
711
  | SessionStaleWriteError
640
712
  | SavePartialFailureError
713
+ | MaterializeValidationFailedError
714
+ | MaterializeWriteFailedError
641
715
  | PathPolicyViolationError
716
+ | InProcessLockConflictError
642
717
  | BackendCapabilityUnavailableError
643
718
  >
644
719
  > {
645
720
  return this.authoringService.saveSession(input);
646
721
  }
647
722
 
723
+ public async materializeSession(input: MaterializeSessionInput): Promise<
724
+ BackendResult<
725
+ MaterializeSessionSnapshot,
726
+ | SessionNotFoundError
727
+ | SessionStaleWriteError
728
+ | MaterializeValidationFailedError
729
+ | MaterializeWriteFailedError
730
+ | PathPolicyViolationError
731
+ | InProcessLockConflictError
732
+ | BackendCapabilityUnavailableError
733
+ >
734
+ > {
735
+ return this.authoringService.materializeSession(input);
736
+ }
737
+
648
738
  public async closeSession(input: {
649
739
  sessionId: string;
650
740
  }): Promise<BackendResult<{ sessionId: string; closed: true }, SessionNotFoundError>> {