@openfairygui/backend 0.2.0-alpha.1 → 0.2.0-alpha.13
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/LICENSE +21 -0
- package/README.md +40 -2
- package/dist/index.cjs +146 -1
- package/dist/index.d.cts +33 -2
- package/dist/index.d.mts +33 -2
- package/dist/index.mjs +146 -2
- package/dist/node.cjs +1 -1
- package/dist/node.d.cts +1 -1
- package/dist/node.d.mts +1 -1
- package/dist/node.mjs +1 -1
- package/dist/{runtime-DLWLghmH.mjs → runtime-DFatY9W0.mjs} +244 -19
- package/dist/{runtime-BXbt135W.cjs → runtime-GKzsXJdO.cjs} +251 -26
- package/dist/{runtime-C5JY_kRI.d.cts → runtime-GyNVxAQ0.d.mts} +81 -11
- package/dist/{runtime-C5ZsWMnH.d.mts → runtime-Jec6FcF5.d.cts} +81 -11
- package/package.json +65 -65
- package/src/contracts.ts +8 -0
- package/src/index.ts +12 -0
- package/src/runtime.ts +156 -29
- package/src/services/authoring-service.ts +462 -46
- package/src/services/context.ts +2 -1
- package/src/services/runtime-service.ts +62 -25
- package/src/storage.ts +192 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require("./node.cjs");
|
|
2
|
-
let
|
|
3
|
-
let
|
|
2
|
+
let _openfairygui_core_uam = require("@openfairygui/core/uam");
|
|
3
|
+
let _openfairygui_core_project_io = require("@openfairygui/core/project-io");
|
|
4
|
+
let _openfairygui_functions_uam = require("@openfairygui/functions/uam");
|
|
4
5
|
//#region src/contracts.ts
|
|
5
6
|
const BACKEND_CONTRACT_VERSION = "1.1.0-p2";
|
|
6
7
|
const BACKEND_CAPABILITY_SCHEMA_VERSION = 2;
|
|
@@ -254,6 +255,54 @@ function createWriterFileSystem(fileSystem, committedPaths, failedPaths) {
|
|
|
254
255
|
}
|
|
255
256
|
};
|
|
256
257
|
}
|
|
258
|
+
function toBackendDiagnostics(error) {
|
|
259
|
+
return error.diagnostics.length > 0 ? error.diagnostics.map((diagnostic) => ({ ...diagnostic })) : [{
|
|
260
|
+
code: error.code,
|
|
261
|
+
message: error.message,
|
|
262
|
+
severity: "error",
|
|
263
|
+
operationKind: error.operationKind,
|
|
264
|
+
opIndex: error.opIndex,
|
|
265
|
+
opId: error.opId
|
|
266
|
+
}];
|
|
267
|
+
}
|
|
268
|
+
function createCapabilityUnavailableError$1(message) {
|
|
269
|
+
return {
|
|
270
|
+
code: "capability_unavailable",
|
|
271
|
+
message,
|
|
272
|
+
capability: "fileSystem",
|
|
273
|
+
requiredAdapter: "BackendFileSystem"
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function validationDiagnostics(sessionProject) {
|
|
277
|
+
return (0, _openfairygui_core_uam.validateUamProject)(sessionProject).map((issue) => ({
|
|
278
|
+
code: "materialize_validation_failed",
|
|
279
|
+
message: issue.message,
|
|
280
|
+
severity: "error",
|
|
281
|
+
path: issue.path,
|
|
282
|
+
operationKind: "materializeSession"
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
function toMaterializeSnapshot(session, capabilities, input) {
|
|
286
|
+
return {
|
|
287
|
+
...toSessionSnapshot(session, capabilities),
|
|
288
|
+
mode: "fullProject",
|
|
289
|
+
reason: input.reason,
|
|
290
|
+
materializeRevision: session.revision,
|
|
291
|
+
saveRevision: session.lastSavedRevision,
|
|
292
|
+
writtenPaths: [...input.writtenPaths],
|
|
293
|
+
skippedPaths: [...input.skippedPaths],
|
|
294
|
+
diagnostics: input.diagnostics.map((diagnostic) => ({ ...diagnostic }))
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function storageCanonicalTarget(input) {
|
|
298
|
+
const canonicalProjectPath = input.canonicalProjectPath ?? (input.fileSystem.dirname(input.fairyPath) || ".");
|
|
299
|
+
return {
|
|
300
|
+
fileSystem: input.fileSystem,
|
|
301
|
+
fairyPath: input.fairyPath,
|
|
302
|
+
canonicalProjectPath,
|
|
303
|
+
canonicalPathKey: input.canonicalPathKey ?? normalizeComparablePath(canonicalProjectPath)
|
|
304
|
+
};
|
|
305
|
+
}
|
|
257
306
|
var AuthoringService = class {
|
|
258
307
|
constructor(context, cacheService, eventService) {
|
|
259
308
|
this.context = context;
|
|
@@ -276,25 +325,23 @@ var AuthoringService = class {
|
|
|
276
325
|
revision: session.revision
|
|
277
326
|
});
|
|
278
327
|
}
|
|
279
|
-
const result = (0,
|
|
328
|
+
const result = (0, _openfairygui_functions_uam.applyUamTransactionApp)({
|
|
280
329
|
project: session.project,
|
|
281
330
|
operations: input.operations
|
|
282
331
|
});
|
|
283
332
|
if (result.ok === false) {
|
|
333
|
+
const diagnostics = toBackendDiagnostics(result.error);
|
|
284
334
|
this.eventService.emit({
|
|
285
335
|
kind: "transaction.rejected",
|
|
286
336
|
sessionId: session.sessionId,
|
|
287
337
|
canonicalPathKey: session.canonicalPathKey,
|
|
288
338
|
revision: session.revision,
|
|
289
|
-
diagnostics
|
|
290
|
-
code: result.error.code,
|
|
291
|
-
message: issue.message,
|
|
292
|
-
severity: "error"
|
|
293
|
-
})) ?? []
|
|
339
|
+
diagnostics
|
|
294
340
|
});
|
|
295
341
|
return failure("authoring", startedAt, result.error, toSessionSnapshot(session, this.context.capabilities), {
|
|
296
342
|
sessionId: session.sessionId,
|
|
297
|
-
revision: session.revision
|
|
343
|
+
revision: session.revision,
|
|
344
|
+
diagnostics
|
|
298
345
|
});
|
|
299
346
|
}
|
|
300
347
|
session.project = result.project;
|
|
@@ -320,15 +367,19 @@ var AuthoringService = class {
|
|
|
320
367
|
});
|
|
321
368
|
}
|
|
322
369
|
async saveSession(input) {
|
|
370
|
+
if (input.force === true || input.mode === "materializeCleanSession") return this.materializeSession({
|
|
371
|
+
sessionId: input.sessionId,
|
|
372
|
+
expectedRevision: input.expectedRevision,
|
|
373
|
+
targetPath: input.targetPath,
|
|
374
|
+
fileSystem: input.fileSystem,
|
|
375
|
+
mode: "fullProject",
|
|
376
|
+
reason: "force_save"
|
|
377
|
+
});
|
|
323
378
|
const startedAt = Date.now();
|
|
324
379
|
const session = this.context.sessions.get(input.sessionId);
|
|
325
380
|
if (!session || session.closed) return failure("authoring", startedAt, createSessionNotFoundError(input.sessionId));
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
message: "saveSession requires an injected BackendFileSystem adapter.",
|
|
329
|
-
capability: "fileSystem",
|
|
330
|
-
requiredAdapter: "BackendFileSystem"
|
|
331
|
-
}, toSessionSnapshot(session, this.context.capabilities), {
|
|
381
|
+
const fileSystem = input.fileSystem ?? session.fileSystem ?? this.context.fileSystem;
|
|
382
|
+
if (!fileSystem) return failure("authoring", startedAt, createCapabilityUnavailableError$1("saveSession requires an injected BackendFileSystem adapter."), toSessionSnapshot(session, this.context.capabilities), {
|
|
332
383
|
sessionId: session.sessionId,
|
|
333
384
|
revision: session.revision
|
|
334
385
|
});
|
|
@@ -336,7 +387,6 @@ var AuthoringService = class {
|
|
|
336
387
|
sessionId: session.sessionId,
|
|
337
388
|
revision: session.revision
|
|
338
389
|
});
|
|
339
|
-
const fileSystem = this.context.fileSystem;
|
|
340
390
|
const targetViolation = await validateSaveTarget(fileSystem, session.fairyPath, input.targetPath);
|
|
341
391
|
if (targetViolation) return failure("authoring", startedAt, targetViolation, toSessionSnapshot(session, this.context.capabilities), {
|
|
342
392
|
sessionId: session.sessionId,
|
|
@@ -355,7 +405,7 @@ var AuthoringService = class {
|
|
|
355
405
|
revision: session.revision
|
|
356
406
|
});
|
|
357
407
|
try {
|
|
358
|
-
await new
|
|
408
|
+
await new _openfairygui_core_project_io.ProjectWriter(createWriterFileSystem(fileSystem, committedPaths, failedPaths)).write((0, _openfairygui_core_uam.materializeUamProject)(session.project), session.fairyPath);
|
|
359
409
|
session.lastSavedRevision = session.revision;
|
|
360
410
|
session.dirty = false;
|
|
361
411
|
const cacheEntry = this.cacheService.refreshSession(session);
|
|
@@ -400,6 +450,154 @@ var AuthoringService = class {
|
|
|
400
450
|
});
|
|
401
451
|
}
|
|
402
452
|
}
|
|
453
|
+
async materializeSession(input) {
|
|
454
|
+
const startedAt = Date.now();
|
|
455
|
+
const session = this.context.sessions.get(input.sessionId);
|
|
456
|
+
if (!session || session.closed) return failure("authoring", startedAt, createSessionNotFoundError(input.sessionId));
|
|
457
|
+
if (input.expectedRevision !== void 0 && input.expectedRevision !== session.revision) return failure("authoring", startedAt, createStaleWriteError(session, input.expectedRevision), toSessionSnapshot(session, this.context.capabilities), {
|
|
458
|
+
sessionId: session.sessionId,
|
|
459
|
+
revision: session.revision
|
|
460
|
+
});
|
|
461
|
+
const storageTarget = input.storage ? storageCanonicalTarget(input.storage) : null;
|
|
462
|
+
const fileSystem = storageTarget?.fileSystem ?? input.fileSystem ?? session.fileSystem ?? this.context.fileSystem;
|
|
463
|
+
if (!fileSystem) return failure("authoring", startedAt, createCapabilityUnavailableError$1("materializeSession requires an injected BackendFileSystem adapter."), toSessionSnapshot(session, this.context.capabilities), {
|
|
464
|
+
sessionId: session.sessionId,
|
|
465
|
+
revision: session.revision
|
|
466
|
+
});
|
|
467
|
+
const fairyPath = storageTarget?.fairyPath ?? session.fairyPath;
|
|
468
|
+
const targetViolation = await validateSaveTarget(fileSystem, fairyPath, input.targetPath);
|
|
469
|
+
if (targetViolation) return failure("authoring", startedAt, targetViolation, toSessionSnapshot(session, this.context.capabilities), {
|
|
470
|
+
sessionId: session.sessionId,
|
|
471
|
+
revision: session.revision
|
|
472
|
+
});
|
|
473
|
+
if (storageTarget) {
|
|
474
|
+
const holderSessionId = this.context.sessionsByPath.get(storageTarget.canonicalPathKey);
|
|
475
|
+
if (holderSessionId && holderSessionId !== session.sessionId) return failure("authoring", startedAt, {
|
|
476
|
+
code: "lock_conflict",
|
|
477
|
+
kind: "in_process_session_exists",
|
|
478
|
+
message: `Project is already open in this backend runtime: ${storageTarget.canonicalProjectPath}`,
|
|
479
|
+
canonicalPathKey: storageTarget.canonicalPathKey,
|
|
480
|
+
holderSessionId
|
|
481
|
+
}, toSessionSnapshot(session, this.context.capabilities), {
|
|
482
|
+
sessionId: session.sessionId,
|
|
483
|
+
revision: session.revision
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
const diagnostics = validationDiagnostics(session.project);
|
|
487
|
+
if (diagnostics.length > 0) return failure("authoring", startedAt, {
|
|
488
|
+
code: "materialize_validation_failed",
|
|
489
|
+
message: `UAM materialize validation failed with ${diagnostics.length} issue(s).`,
|
|
490
|
+
sessionId: session.sessionId,
|
|
491
|
+
canonicalPathKey: session.canonicalPathKey,
|
|
492
|
+
issueCount: diagnostics.length,
|
|
493
|
+
diagnostics
|
|
494
|
+
}, toSessionSnapshot(session, this.context.capabilities), {
|
|
495
|
+
sessionId: session.sessionId,
|
|
496
|
+
revision: session.revision,
|
|
497
|
+
diagnostics
|
|
498
|
+
});
|
|
499
|
+
let document;
|
|
500
|
+
try {
|
|
501
|
+
document = (0, _openfairygui_core_uam.materializeUamProject)(session.project);
|
|
502
|
+
} catch (error) {
|
|
503
|
+
const diagnosticsFromError = [{
|
|
504
|
+
code: "materialize_validation_failed",
|
|
505
|
+
message: error instanceof Error ? error.message : String(error),
|
|
506
|
+
severity: "error",
|
|
507
|
+
operationKind: "materializeSession"
|
|
508
|
+
}];
|
|
509
|
+
return failure("authoring", startedAt, {
|
|
510
|
+
code: "materialize_validation_failed",
|
|
511
|
+
message: error instanceof Error ? error.message : String(error),
|
|
512
|
+
sessionId: session.sessionId,
|
|
513
|
+
canonicalPathKey: session.canonicalPathKey,
|
|
514
|
+
issueCount: diagnosticsFromError.length,
|
|
515
|
+
diagnostics: diagnosticsFromError
|
|
516
|
+
}, toSessionSnapshot(session, this.context.capabilities), {
|
|
517
|
+
sessionId: session.sessionId,
|
|
518
|
+
revision: session.revision,
|
|
519
|
+
diagnostics: diagnosticsFromError
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
const writtenPaths = [];
|
|
523
|
+
const failedPaths = [];
|
|
524
|
+
const skippedPaths = [];
|
|
525
|
+
this.eventService.emit({
|
|
526
|
+
kind: "save.started",
|
|
527
|
+
sessionId: session.sessionId,
|
|
528
|
+
canonicalPathKey: storageTarget?.canonicalPathKey ?? session.canonicalPathKey,
|
|
529
|
+
revision: session.revision
|
|
530
|
+
});
|
|
531
|
+
try {
|
|
532
|
+
await new _openfairygui_core_project_io.ProjectWriter(createWriterFileSystem(fileSystem, writtenPaths, failedPaths)).write(document, fairyPath);
|
|
533
|
+
if (storageTarget) {
|
|
534
|
+
this.context.sessionsByPath.delete(session.canonicalPathKey);
|
|
535
|
+
session.fileSystem = storageTarget.fileSystem;
|
|
536
|
+
session.fairyPath = storageTarget.fairyPath;
|
|
537
|
+
session.canonicalProjectPath = storageTarget.canonicalProjectPath;
|
|
538
|
+
session.canonicalPathKey = storageTarget.canonicalPathKey;
|
|
539
|
+
this.context.sessionsByPath.set(session.canonicalPathKey, session.sessionId);
|
|
540
|
+
}
|
|
541
|
+
session.lastSavedRevision = session.revision;
|
|
542
|
+
session.dirty = false;
|
|
543
|
+
const cacheEntry = this.cacheService.refreshSession(session);
|
|
544
|
+
this.eventService.emit({
|
|
545
|
+
kind: "save.completed",
|
|
546
|
+
sessionId: session.sessionId,
|
|
547
|
+
canonicalPathKey: session.canonicalPathKey,
|
|
548
|
+
revision: session.revision
|
|
549
|
+
});
|
|
550
|
+
this.eventService.emit({
|
|
551
|
+
kind: "cache.updated",
|
|
552
|
+
sessionId: session.sessionId,
|
|
553
|
+
canonicalPathKey: session.canonicalPathKey,
|
|
554
|
+
revision: session.revision,
|
|
555
|
+
cacheRevision: cacheEntry.revision
|
|
556
|
+
});
|
|
557
|
+
return success("authoring", startedAt, toMaterializeSnapshot(session, this.context.capabilities, {
|
|
558
|
+
reason: input.reason,
|
|
559
|
+
writtenPaths,
|
|
560
|
+
skippedPaths,
|
|
561
|
+
diagnostics: []
|
|
562
|
+
}), {
|
|
563
|
+
sessionId: session.sessionId,
|
|
564
|
+
revision: session.revision
|
|
565
|
+
});
|
|
566
|
+
} catch (error) {
|
|
567
|
+
const diagnosticsFromError = [{
|
|
568
|
+
code: "write_failed",
|
|
569
|
+
message: error instanceof Error ? error.message : String(error),
|
|
570
|
+
severity: "error",
|
|
571
|
+
path: failedPaths[0],
|
|
572
|
+
operationKind: "materializeSession"
|
|
573
|
+
}];
|
|
574
|
+
this.cacheService.invalidateSession(session);
|
|
575
|
+
this.eventService.emit({
|
|
576
|
+
kind: "save.failed",
|
|
577
|
+
sessionId: session.sessionId,
|
|
578
|
+
canonicalPathKey: session.canonicalPathKey,
|
|
579
|
+
revision: session.revision,
|
|
580
|
+
diagnostics: diagnosticsFromError
|
|
581
|
+
});
|
|
582
|
+
return failure("authoring", startedAt, {
|
|
583
|
+
code: "write_failed",
|
|
584
|
+
message: error instanceof Error ? error.message : String(error),
|
|
585
|
+
sessionId: session.sessionId,
|
|
586
|
+
canonicalPathKey: session.canonicalPathKey,
|
|
587
|
+
attemptedRevision: session.revision,
|
|
588
|
+
lastSavedRevision: session.lastSavedRevision,
|
|
589
|
+
writtenPaths,
|
|
590
|
+
failedPaths,
|
|
591
|
+
skippedPaths,
|
|
592
|
+
diagnostics: diagnosticsFromError,
|
|
593
|
+
diskMayBePartiallyUpdated: true
|
|
594
|
+
}, toSessionSnapshot(session, this.context.capabilities), {
|
|
595
|
+
sessionId: session.sessionId,
|
|
596
|
+
revision: session.revision,
|
|
597
|
+
diagnostics: diagnosticsFromError
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
}
|
|
403
601
|
};
|
|
404
602
|
//#endregion
|
|
405
603
|
//#region src/services/cache-service.ts
|
|
@@ -892,7 +1090,7 @@ var RuntimeService = class {
|
|
|
892
1090
|
canonicalPathKey
|
|
893
1091
|
}));
|
|
894
1092
|
await advisoryLock.close();
|
|
895
|
-
const project = (0,
|
|
1093
|
+
const project = (0, _openfairygui_core_uam.liftDocumentToUamProject)(await new _openfairygui_core_project_io.ProjectReader(createProjectReaderFileSystem(fileSystem)).read(fairyPath));
|
|
896
1094
|
const sessionId = randomId();
|
|
897
1095
|
const session = {
|
|
898
1096
|
sessionId,
|
|
@@ -900,6 +1098,7 @@ var RuntimeService = class {
|
|
|
900
1098
|
canonicalProjectPath,
|
|
901
1099
|
canonicalPathKey,
|
|
902
1100
|
lockFilePath,
|
|
1101
|
+
fileSystem,
|
|
903
1102
|
project,
|
|
904
1103
|
revision: 0,
|
|
905
1104
|
lastSavedRevision: 0,
|
|
@@ -938,8 +1137,10 @@ var RuntimeService = class {
|
|
|
938
1137
|
openProjectSession(input) {
|
|
939
1138
|
const startedAt = Date.now();
|
|
940
1139
|
const sessionId = input.sessionId ?? randomId();
|
|
941
|
-
const
|
|
942
|
-
const
|
|
1140
|
+
const storage = input.storage;
|
|
1141
|
+
const memoryProjectPath = `memory://${sessionId}`;
|
|
1142
|
+
const canonicalProjectPath = storage?.canonicalProjectPath ?? input.canonicalProjectPath ?? (storage ? storage.fileSystem.dirname(storage.fairyPath) || "." : memoryProjectPath);
|
|
1143
|
+
const canonicalPathKey = storage?.canonicalPathKey ?? input.canonicalPathKey ?? (storage ? normalizeComparablePath(canonicalProjectPath) : canonicalProjectPath.toLowerCase());
|
|
943
1144
|
const existingSessionId = this.context.sessionsByPath.get(canonicalPathKey);
|
|
944
1145
|
if (existingSessionId) return failure("runtime", startedAt, {
|
|
945
1146
|
code: "lock_conflict",
|
|
@@ -950,11 +1151,12 @@ var RuntimeService = class {
|
|
|
950
1151
|
});
|
|
951
1152
|
const session = {
|
|
952
1153
|
sessionId,
|
|
953
|
-
fairyPath: canonicalProjectPath,
|
|
1154
|
+
fairyPath: storage?.fairyPath ?? canonicalProjectPath,
|
|
954
1155
|
canonicalProjectPath,
|
|
955
1156
|
canonicalPathKey,
|
|
956
1157
|
lockFilePath: "",
|
|
957
|
-
|
|
1158
|
+
fileSystem: storage?.fileSystem,
|
|
1159
|
+
project: (0, _openfairygui_core_uam.normalizeUamProject)(input.project),
|
|
958
1160
|
revision: 0,
|
|
959
1161
|
lastSavedRevision: 0,
|
|
960
1162
|
dirty: false,
|
|
@@ -1017,6 +1219,7 @@ const BACKEND_METHODS = [
|
|
|
1017
1219
|
"getSession",
|
|
1018
1220
|
"applyTransaction",
|
|
1019
1221
|
"saveSession",
|
|
1222
|
+
"materializeSession",
|
|
1020
1223
|
"closeSession",
|
|
1021
1224
|
"getEvents",
|
|
1022
1225
|
"getJob",
|
|
@@ -1047,9 +1250,14 @@ function createCapabilities() {
|
|
|
1047
1250
|
authoring: {
|
|
1048
1251
|
applyTransaction: true,
|
|
1049
1252
|
saveSession: true,
|
|
1050
|
-
resourceKinds: [...
|
|
1051
|
-
nodeKinds: [...
|
|
1052
|
-
gearKinds: [...
|
|
1253
|
+
resourceKinds: [..._openfairygui_core_uam.UAM_SUPPORTED_MATERIALIZATION_SCOPE.resourceKinds],
|
|
1254
|
+
nodeKinds: [..._openfairygui_core_uam.UAM_SUPPORTED_MATERIALIZATION_SCOPE.nodeKinds],
|
|
1255
|
+
gearKinds: [..._openfairygui_core_uam.UAM_SUPPORTED_MATERIALIZATION_SCOPE.gearKinds],
|
|
1256
|
+
transactionScope: {
|
|
1257
|
+
resourceKinds: [..._openfairygui_core_uam.UAM_SUPPORTED_TRANSACTION_SCOPE.resourceKinds],
|
|
1258
|
+
nodeKinds: [..._openfairygui_core_uam.UAM_SUPPORTED_TRANSACTION_SCOPE.nodeKinds],
|
|
1259
|
+
gearKinds: [..._openfairygui_core_uam.UAM_SUPPORTED_TRANSACTION_SCOPE.gearKinds]
|
|
1260
|
+
},
|
|
1053
1261
|
unsupported: ["artifact.publish", "artifact.restore"]
|
|
1054
1262
|
},
|
|
1055
1263
|
artifact: createArtifactCapabilities(),
|
|
@@ -1060,7 +1268,21 @@ function createCapabilities() {
|
|
|
1060
1268
|
adapters: {
|
|
1061
1269
|
fileSystem: {
|
|
1062
1270
|
injected: true,
|
|
1063
|
-
requiredFor: [
|
|
1271
|
+
requiredFor: [
|
|
1272
|
+
"openSession",
|
|
1273
|
+
"saveSession",
|
|
1274
|
+
"materializeSession"
|
|
1275
|
+
]
|
|
1276
|
+
},
|
|
1277
|
+
projectStorage: {
|
|
1278
|
+
injected: true,
|
|
1279
|
+
browserSafe: true,
|
|
1280
|
+
requiredFor: [
|
|
1281
|
+
"openProjectSession.writeback",
|
|
1282
|
+
"saveSession",
|
|
1283
|
+
"materializeSession"
|
|
1284
|
+
],
|
|
1285
|
+
adapterFactory: "createBackendStorageFileSystem"
|
|
1064
1286
|
},
|
|
1065
1287
|
host: {
|
|
1066
1288
|
injected: true,
|
|
@@ -1167,6 +1389,9 @@ var BackendRuntime = class {
|
|
|
1167
1389
|
async saveSession(input) {
|
|
1168
1390
|
return this.authoringService.saveSession(input);
|
|
1169
1391
|
}
|
|
1392
|
+
async materializeSession(input) {
|
|
1393
|
+
return this.authoringService.materializeSession(input);
|
|
1394
|
+
}
|
|
1170
1395
|
async closeSession(input) {
|
|
1171
1396
|
return this.runtimeService.closeSession(input);
|
|
1172
1397
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { UamProject, UamTransactionOperation } from "@openfairygui/core";
|
|
2
|
-
import { ApplyUamTransactionAppError } from "@openfairygui/functions";
|
|
1
|
+
import { UamProject, UamTransactionOperation } from "@openfairygui/core/uam";
|
|
2
|
+
import { ApplyUamTransactionAppError } from "@openfairygui/functions/uam";
|
|
3
3
|
|
|
4
4
|
//#region src/contracts.d.ts
|
|
5
5
|
declare const BACKEND_CONTRACT_VERSION: "1.1.0-p2";
|
|
@@ -18,6 +18,14 @@ interface BackendDiagnostic {
|
|
|
18
18
|
code: string;
|
|
19
19
|
message: string;
|
|
20
20
|
severity: 'info' | 'warning' | 'error';
|
|
21
|
+
path?: string;
|
|
22
|
+
nodeKind?: string;
|
|
23
|
+
resourceKind?: string;
|
|
24
|
+
gearKind?: string;
|
|
25
|
+
field?: string;
|
|
26
|
+
operationKind?: string;
|
|
27
|
+
opIndex?: number;
|
|
28
|
+
opId?: string;
|
|
21
29
|
}
|
|
22
30
|
interface BackendResponseMeta {
|
|
23
31
|
requestId: string;
|
|
@@ -87,7 +95,13 @@ interface BackendCapabilityManifest {
|
|
|
87
95
|
adapters: {
|
|
88
96
|
fileSystem: {
|
|
89
97
|
injected: true;
|
|
90
|
-
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';
|
|
91
105
|
};
|
|
92
106
|
host: {
|
|
93
107
|
injected: true;
|
|
@@ -111,7 +125,7 @@ interface BackendCapabilities {
|
|
|
111
125
|
transactionKernelOwner: '@openfairygui/core';
|
|
112
126
|
appSeamOwner: '@openfairygui/functions';
|
|
113
127
|
runtimeOwner: '@openfairygui/backend';
|
|
114
|
-
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'];
|
|
115
129
|
read: {
|
|
116
130
|
capabilitySnapshot: true;
|
|
117
131
|
sessionSnapshot: true;
|
|
@@ -122,6 +136,11 @@ interface BackendCapabilities {
|
|
|
122
136
|
resourceKinds: readonly string[];
|
|
123
137
|
nodeKinds: readonly string[];
|
|
124
138
|
gearKinds: readonly string[];
|
|
139
|
+
transactionScope: {
|
|
140
|
+
resourceKinds: readonly string[];
|
|
141
|
+
nodeKinds: readonly string[];
|
|
142
|
+
gearKinds: readonly string[];
|
|
143
|
+
};
|
|
125
144
|
unsupported: readonly ['artifact.publish', 'artifact.restore'];
|
|
126
145
|
};
|
|
127
146
|
artifact: {
|
|
@@ -177,6 +196,15 @@ interface BackendSessionSnapshot {
|
|
|
177
196
|
lockHeld: boolean;
|
|
178
197
|
capabilities: BackendCapabilities;
|
|
179
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
|
+
}
|
|
180
208
|
interface BackendSuccess<T> {
|
|
181
209
|
ok: true;
|
|
182
210
|
meta: BackendResponseMeta;
|
|
@@ -229,6 +257,27 @@ interface SavePartialFailureError {
|
|
|
229
257
|
failedPaths: string[];
|
|
230
258
|
diskMayBePartiallyUpdated: true;
|
|
231
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
|
+
}
|
|
232
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';
|
|
233
282
|
interface BackendEvent {
|
|
234
283
|
sequence: number;
|
|
@@ -360,7 +409,7 @@ interface RefreshCacheInput {
|
|
|
360
409
|
sessionId: string;
|
|
361
410
|
reason?: 'manual' | 'session_open' | 'after_save';
|
|
362
411
|
}
|
|
363
|
-
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;
|
|
364
413
|
interface ApplySessionTransactionInput {
|
|
365
414
|
sessionId: string;
|
|
366
415
|
expectedRevision: number;
|
|
@@ -371,6 +420,30 @@ interface OpenProjectSessionInput {
|
|
|
371
420
|
sessionId?: string;
|
|
372
421
|
canonicalProjectPath?: string;
|
|
373
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;
|
|
374
447
|
}
|
|
375
448
|
interface BackendRuntimeOptions {
|
|
376
449
|
fileSystem?: BackendFileSystem;
|
|
@@ -402,11 +475,8 @@ declare class BackendRuntime {
|
|
|
402
475
|
sessionId: string;
|
|
403
476
|
}): BackendResult<BackendSessionSnapshot, SessionNotFoundError>;
|
|
404
477
|
applyTransaction(input: ApplySessionTransactionInput): Promise<BackendResult<BackendSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | ApplyUamTransactionAppError>>;
|
|
405
|
-
saveSession(input:
|
|
406
|
-
|
|
407
|
-
expectedRevision?: number;
|
|
408
|
-
targetPath?: string;
|
|
409
|
-
}): 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>>;
|
|
410
480
|
closeSession(input: {
|
|
411
481
|
sessionId: string;
|
|
412
482
|
}): Promise<BackendResult<{
|
|
@@ -421,4 +491,4 @@ declare class BackendRuntime {
|
|
|
421
491
|
refreshCache(input: RefreshCacheInput): BackendResult<BackendJobSnapshot, SessionNotFoundError>;
|
|
422
492
|
}
|
|
423
493
|
//#endregion
|
|
424
|
-
export {
|
|
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 };
|