@openfairygui/backend 0.2.0 → 0.3.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.cjs CHANGED
@@ -28,6 +28,7 @@ node_path = __toESM(node_path);
28
28
  let _openfairygui_core_uam = require("@openfairygui/core/uam");
29
29
  let _openfairygui_functions_uam = require("@openfairygui/functions/uam");
30
30
  let _openfairygui_core_project_io = require("@openfairygui/core/project-io");
31
+ let _openfairygui_functions = require("@openfairygui/functions");
31
32
  //#region src/path-policy.ts
32
33
  function normalizeComparablePath(value) {
33
34
  const normalized = value.replace(/[/\\]+$/, "").replace(/\\/g, "/");
@@ -122,7 +123,7 @@ function createMeta(stage, startedAt, options) {
122
123
  diagnostics: options?.diagnostics ?? [],
123
124
  stage,
124
125
  contractVersion: BACKEND_CONTRACT_VERSION,
125
- capabilitySchemaVersion: 2
126
+ capabilitySchemaVersion: 3
126
127
  };
127
128
  }
128
129
  function success(stage, startedAt, data, options) {
@@ -1076,6 +1077,48 @@ var JobService = class {
1076
1077
  };
1077
1078
  //#endregion
1078
1079
  //#region src/services/read-service.ts
1080
+ function toProjectOutline(session) {
1081
+ const project = session.project;
1082
+ return {
1083
+ sessionId: session.sessionId,
1084
+ revision: session.revision,
1085
+ projectId: project.projectId,
1086
+ projectType: project.projectType,
1087
+ version: project.version,
1088
+ branches: [...project.branches],
1089
+ packages: project.packages.map((pkg) => ({
1090
+ id: pkg.id,
1091
+ name: pkg.name,
1092
+ branchNames: [...pkg.branchNames],
1093
+ folders: pkg.folders.map((folder) => ({
1094
+ branch: folder.branch,
1095
+ path: folder.path
1096
+ })),
1097
+ resources: pkg.resources.map((resource) => ({
1098
+ id: resource.id,
1099
+ name: resource.name,
1100
+ path: resource.path,
1101
+ kind: resource.kind,
1102
+ branch: resource.branch,
1103
+ ...resource.kind === "component" ? { component: {
1104
+ displayList: resource.component.displayList.map((node) => ({
1105
+ id: node.id,
1106
+ name: node.name,
1107
+ kind: node.kind
1108
+ })),
1109
+ controllers: resource.component.controllers.map((controller) => ({
1110
+ name: controller.name,
1111
+ pages: controller.pages.map((page) => ({
1112
+ id: page.id,
1113
+ name: page.name
1114
+ }))
1115
+ })),
1116
+ transitions: resource.component.transitions.map((transition) => ({ name: transition.name }))
1117
+ } } : {}
1118
+ }))
1119
+ }))
1120
+ };
1121
+ }
1079
1122
  var ReadService = class {
1080
1123
  constructor(context) {
1081
1124
  this.context = context;
@@ -1092,6 +1135,35 @@ var ReadService = class {
1092
1135
  revision: session.revision
1093
1136
  });
1094
1137
  }
1138
+ getProjectOutline(input) {
1139
+ const startedAt = Date.now();
1140
+ const session = this.context.sessions.get(input.sessionId);
1141
+ if (!session || session.closed) return failure("read", startedAt, createSessionNotFoundError(input.sessionId));
1142
+ return success("read", startedAt, toProjectOutline(session), {
1143
+ sessionId: session.sessionId,
1144
+ revision: session.revision
1145
+ });
1146
+ }
1147
+ validateSession(input) {
1148
+ const startedAt = Date.now();
1149
+ const session = this.context.sessions.get(input.sessionId);
1150
+ if (!session || session.closed) return failure("read", startedAt, createSessionNotFoundError(input.sessionId));
1151
+ const report = (0, _openfairygui_functions.validateProject)(session.project, {
1152
+ readDiagnostics: session.readDiagnostics,
1153
+ complete: session.readComplete,
1154
+ validateSources: true
1155
+ });
1156
+ return success("read", startedAt, report, {
1157
+ sessionId: session.sessionId,
1158
+ revision: session.revision,
1159
+ diagnostics: report.diagnostics.map(({ code, message, severity, path }) => ({
1160
+ code,
1161
+ message,
1162
+ severity,
1163
+ path
1164
+ }))
1165
+ });
1166
+ }
1095
1167
  };
1096
1168
  //#endregion
1097
1169
  //#region src/services/runtime-service.ts
@@ -1247,7 +1319,9 @@ var RuntimeService = class {
1247
1319
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1248
1320
  canonicalPathKey
1249
1321
  }));
1250
- const document = await new _openfairygui_core_project_io.ProjectReader(createProjectReaderFileSystem(fileSystem)).read(fairyPath, { hydrateResourceBytes: true });
1322
+ const read = await new _openfairygui_core_project_io.ProjectReader(createProjectReaderFileSystem(fileSystem)).readDetailed(fairyPath, { hydrateResourceBytes: true });
1323
+ if (!read.document) throw new Error(read.diagnostics[0]?.message ?? `Unable to read project: ${fairyPath}`);
1324
+ const document = read.document;
1251
1325
  const project = (0, _openfairygui_core_uam.liftDocumentToUamProject)(document);
1252
1326
  const sessionId = randomId();
1253
1327
  const session = {
@@ -1259,6 +1333,8 @@ var RuntimeService = class {
1259
1333
  sessionLock,
1260
1334
  fileSystem,
1261
1335
  project,
1336
+ readDiagnostics: read.diagnostics,
1337
+ readComplete: read.complete,
1262
1338
  uamFidelity: await hasFullUamFidelity(document, project) ? "full" : "unsupported",
1263
1339
  revision: 0,
1264
1340
  lastSavedRevision: 0,
@@ -1322,6 +1398,8 @@ var RuntimeService = class {
1322
1398
  sessionLock: null,
1323
1399
  fileSystem: storage?.fileSystem,
1324
1400
  project: (0, _openfairygui_core_uam.normalizeUamProject)(input.project),
1401
+ readDiagnostics: [],
1402
+ readComplete: true,
1325
1403
  uamFidelity: "full",
1326
1404
  revision: 0,
1327
1405
  lastSavedRevision: 0,
@@ -1405,6 +1483,8 @@ const BACKEND_METHODS = [
1405
1483
  "openSession",
1406
1484
  "openProjectSession",
1407
1485
  "getSession",
1486
+ "getProjectOutline",
1487
+ "validateSession",
1408
1488
  "applyTransaction",
1409
1489
  "saveSession",
1410
1490
  "materializeSession",
@@ -1426,14 +1506,16 @@ const ARTIFACT_BRIDGE_CAPABILITY = {
1426
1506
  function createCapabilities() {
1427
1507
  return {
1428
1508
  contractVersion: BACKEND_CONTRACT_VERSION,
1429
- capabilitySchemaVersion: 2,
1509
+ capabilitySchemaVersion: 3,
1430
1510
  transactionKernelOwner: "@openfairygui/core",
1431
1511
  appSeamOwner: "@openfairygui/functions",
1432
1512
  runtimeOwner: "@openfairygui/backend",
1433
1513
  methods: BACKEND_METHODS,
1434
1514
  read: {
1435
1515
  capabilitySnapshot: true,
1436
- sessionSnapshot: true
1516
+ sessionSnapshot: true,
1517
+ projectOutline: true,
1518
+ projectValidation: true
1437
1519
  },
1438
1520
  authoring: {
1439
1521
  applyTransaction: true,
@@ -1573,6 +1655,12 @@ var BackendRuntime = class {
1573
1655
  getSession(input) {
1574
1656
  return this.readService.getSession(input);
1575
1657
  }
1658
+ getProjectOutline(input) {
1659
+ return this.readService.getProjectOutline(input);
1660
+ }
1661
+ validateSession(input) {
1662
+ return this.readService.validateSession(input);
1663
+ }
1576
1664
  async applyTransaction(input) {
1577
1665
  return this.authoringService.applyTransaction(input);
1578
1666
  }
package/dist/node.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { ApplyUamTransactionAppError } from "@openfairygui/functions/uam";
2
- import { UamProject, UamTransactionOperation } from "@openfairygui/core/uam";
2
+ import { ProjectValidationReport } from "@openfairygui/core";
3
+ import { UamDisplayNodeKind, UamProject, UamResource, UamTransactionOperation } from "@openfairygui/core/uam";
3
4
 
4
5
  //#region src/path-policy.d.ts
5
6
  interface PathPolicyViolationError {
@@ -12,7 +13,7 @@ interface PathPolicyViolationError {
12
13
  //#endregion
13
14
  //#region src/contracts.d.ts
14
15
  declare const BACKEND_CONTRACT_VERSION: "1.1.0-p2";
15
- declare const BACKEND_CAPABILITY_SCHEMA_VERSION: 2;
16
+ declare const BACKEND_CAPABILITY_SCHEMA_VERSION: 3;
16
17
  declare const BACKEND_COMPATIBILITY_POLICY: {
17
18
  readonly incompatibleChange: "requires contractVersion bump";
18
19
  readonly capabilitySchemaChange: "requires capabilitySchemaVersion bump";
@@ -129,10 +130,12 @@ interface BackendCapabilities {
129
130
  transactionKernelOwner: '@openfairygui/core';
130
131
  appSeamOwner: '@openfairygui/functions';
131
132
  runtimeOwner: '@openfairygui/backend';
132
- methods: readonly ['getCapabilities', 'openSession', 'openProjectSession', 'getSession', 'applyTransaction', 'saveSession', 'materializeSession', 'closeSession', 'getEvents', 'getJob', 'listJobs', 'cancelJob', 'getCacheSnapshot', 'refreshCache'];
133
+ methods: readonly ['getCapabilities', 'openSession', 'openProjectSession', 'getSession', 'getProjectOutline', 'validateSession', 'applyTransaction', 'saveSession', 'materializeSession', 'closeSession', 'getEvents', 'getJob', 'listJobs', 'cancelJob', 'getCacheSnapshot', 'refreshCache'];
133
134
  read: {
134
135
  capabilitySnapshot: true;
135
136
  sessionSnapshot: true;
137
+ projectOutline: true;
138
+ projectValidation: true;
136
139
  };
137
140
  authoring: {
138
141
  applyTransaction: true;
@@ -201,6 +204,49 @@ interface BackendSessionSnapshot {
201
204
  lockHeld: boolean;
202
205
  capabilities: BackendCapabilities;
203
206
  }
207
+ interface BackendProjectOutline {
208
+ sessionId: string;
209
+ revision: number;
210
+ projectId: string;
211
+ projectType: number;
212
+ version: string;
213
+ branches: string[];
214
+ packages: BackendProjectOutlinePackage[];
215
+ }
216
+ interface BackendProjectOutlinePackage {
217
+ id: string;
218
+ name: string;
219
+ branchNames: string[];
220
+ folders: Array<{
221
+ branch: string;
222
+ path: string;
223
+ }>;
224
+ resources: BackendProjectOutlineResource[];
225
+ }
226
+ interface BackendProjectOutlineResource {
227
+ id: string;
228
+ name: string;
229
+ path: string;
230
+ kind: UamResource['kind'];
231
+ branch: string;
232
+ component?: {
233
+ displayList: Array<{
234
+ id: string;
235
+ name: string;
236
+ kind: UamDisplayNodeKind;
237
+ }>;
238
+ controllers: Array<{
239
+ name: string;
240
+ pages: Array<{
241
+ id: string;
242
+ name: string;
243
+ }>;
244
+ }>;
245
+ transitions: Array<{
246
+ name: string;
247
+ }>;
248
+ };
249
+ }
204
250
  interface MaterializeSessionSnapshot extends BackendSessionSnapshot {
205
251
  mode: 'fullProject';
206
252
  reason?: string;
@@ -425,6 +471,12 @@ interface ApplySessionTransactionInput {
425
471
  expectedRevision: number;
426
472
  operations: UamTransactionOperation[];
427
473
  }
474
+ interface GetProjectOutlineInput {
475
+ sessionId: string;
476
+ }
477
+ interface ValidateSessionInput {
478
+ sessionId: string;
479
+ }
428
480
  interface OpenProjectSessionInput {
429
481
  /** Authoritative UAM project. Use BackendRuntime.openSession() when importing an existing project from storage. */
430
482
  project: UamProject;
@@ -488,6 +540,8 @@ declare class BackendRuntime {
488
540
  getSession(input: {
489
541
  sessionId: string;
490
542
  }): BackendResult<BackendSessionSnapshot, SessionNotFoundError>;
543
+ getProjectOutline(input: GetProjectOutlineInput): BackendResult<BackendProjectOutline, SessionNotFoundError>;
544
+ validateSession(input: ValidateSessionInput): BackendResult<ProjectValidationReport, SessionNotFoundError>;
491
545
  applyTransaction(input: ApplySessionTransactionInput): Promise<BackendResult<BackendSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | ApplyUamTransactionAppError>>;
492
546
  saveSession(input: SaveSessionInput): Promise<BackendResult<BackendSessionSnapshot | MaterializeSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | SavePartialFailureError | UamFidelityUnsupportedError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | InProcessLockConflictError | BackendCapabilityUnavailableError>>;
493
547
  materializeSession(input: MaterializeSessionInput): Promise<BackendResult<MaterializeSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | UamFidelityUnsupportedError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | InProcessLockConflictError | BackendCapabilityUnavailableError>>;
package/dist/node.d.mts CHANGED
@@ -1,5 +1,6 @@
1
- import { UamProject, UamTransactionOperation } from "@openfairygui/core/uam";
1
+ import { UamDisplayNodeKind, UamProject, UamResource, UamTransactionOperation } from "@openfairygui/core/uam";
2
2
  import { ApplyUamTransactionAppError } from "@openfairygui/functions/uam";
3
+ import { ProjectValidationReport } from "@openfairygui/core";
3
4
 
4
5
  //#region src/path-policy.d.ts
5
6
  interface PathPolicyViolationError {
@@ -12,7 +13,7 @@ interface PathPolicyViolationError {
12
13
  //#endregion
13
14
  //#region src/contracts.d.ts
14
15
  declare const BACKEND_CONTRACT_VERSION: "1.1.0-p2";
15
- declare const BACKEND_CAPABILITY_SCHEMA_VERSION: 2;
16
+ declare const BACKEND_CAPABILITY_SCHEMA_VERSION: 3;
16
17
  declare const BACKEND_COMPATIBILITY_POLICY: {
17
18
  readonly incompatibleChange: "requires contractVersion bump";
18
19
  readonly capabilitySchemaChange: "requires capabilitySchemaVersion bump";
@@ -129,10 +130,12 @@ interface BackendCapabilities {
129
130
  transactionKernelOwner: '@openfairygui/core';
130
131
  appSeamOwner: '@openfairygui/functions';
131
132
  runtimeOwner: '@openfairygui/backend';
132
- methods: readonly ['getCapabilities', 'openSession', 'openProjectSession', 'getSession', 'applyTransaction', 'saveSession', 'materializeSession', 'closeSession', 'getEvents', 'getJob', 'listJobs', 'cancelJob', 'getCacheSnapshot', 'refreshCache'];
133
+ methods: readonly ['getCapabilities', 'openSession', 'openProjectSession', 'getSession', 'getProjectOutline', 'validateSession', 'applyTransaction', 'saveSession', 'materializeSession', 'closeSession', 'getEvents', 'getJob', 'listJobs', 'cancelJob', 'getCacheSnapshot', 'refreshCache'];
133
134
  read: {
134
135
  capabilitySnapshot: true;
135
136
  sessionSnapshot: true;
137
+ projectOutline: true;
138
+ projectValidation: true;
136
139
  };
137
140
  authoring: {
138
141
  applyTransaction: true;
@@ -201,6 +204,49 @@ interface BackendSessionSnapshot {
201
204
  lockHeld: boolean;
202
205
  capabilities: BackendCapabilities;
203
206
  }
207
+ interface BackendProjectOutline {
208
+ sessionId: string;
209
+ revision: number;
210
+ projectId: string;
211
+ projectType: number;
212
+ version: string;
213
+ branches: string[];
214
+ packages: BackendProjectOutlinePackage[];
215
+ }
216
+ interface BackendProjectOutlinePackage {
217
+ id: string;
218
+ name: string;
219
+ branchNames: string[];
220
+ folders: Array<{
221
+ branch: string;
222
+ path: string;
223
+ }>;
224
+ resources: BackendProjectOutlineResource[];
225
+ }
226
+ interface BackendProjectOutlineResource {
227
+ id: string;
228
+ name: string;
229
+ path: string;
230
+ kind: UamResource['kind'];
231
+ branch: string;
232
+ component?: {
233
+ displayList: Array<{
234
+ id: string;
235
+ name: string;
236
+ kind: UamDisplayNodeKind;
237
+ }>;
238
+ controllers: Array<{
239
+ name: string;
240
+ pages: Array<{
241
+ id: string;
242
+ name: string;
243
+ }>;
244
+ }>;
245
+ transitions: Array<{
246
+ name: string;
247
+ }>;
248
+ };
249
+ }
204
250
  interface MaterializeSessionSnapshot extends BackendSessionSnapshot {
205
251
  mode: 'fullProject';
206
252
  reason?: string;
@@ -425,6 +471,12 @@ interface ApplySessionTransactionInput {
425
471
  expectedRevision: number;
426
472
  operations: UamTransactionOperation[];
427
473
  }
474
+ interface GetProjectOutlineInput {
475
+ sessionId: string;
476
+ }
477
+ interface ValidateSessionInput {
478
+ sessionId: string;
479
+ }
428
480
  interface OpenProjectSessionInput {
429
481
  /** Authoritative UAM project. Use BackendRuntime.openSession() when importing an existing project from storage. */
430
482
  project: UamProject;
@@ -488,6 +540,8 @@ declare class BackendRuntime {
488
540
  getSession(input: {
489
541
  sessionId: string;
490
542
  }): BackendResult<BackendSessionSnapshot, SessionNotFoundError>;
543
+ getProjectOutline(input: GetProjectOutlineInput): BackendResult<BackendProjectOutline, SessionNotFoundError>;
544
+ validateSession(input: ValidateSessionInput): BackendResult<ProjectValidationReport, SessionNotFoundError>;
491
545
  applyTransaction(input: ApplySessionTransactionInput): Promise<BackendResult<BackendSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | ApplyUamTransactionAppError>>;
492
546
  saveSession(input: SaveSessionInput): Promise<BackendResult<BackendSessionSnapshot | MaterializeSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | SavePartialFailureError | UamFidelityUnsupportedError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | InProcessLockConflictError | BackendCapabilityUnavailableError>>;
493
547
  materializeSession(input: MaterializeSessionInput): Promise<BackendResult<MaterializeSessionSnapshot, SessionNotFoundError | SessionStaleWriteError | UamFidelityUnsupportedError | MaterializeValidationFailedError | MaterializeWriteFailedError | PathPolicyViolationError | InProcessLockConflictError | BackendCapabilityUnavailableError>>;
package/dist/node.mjs CHANGED
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import { UAM_SUPPORTED_MATERIALIZATION_SCOPE, UAM_SUPPORTED_TRANSACTION_SCOPE, commitUamProjectSourcePaths, liftDocumentToUamProject, materializeUamProject, normalizeUamProject, staleBranchDirectories, staleResourceFolders, staleSourceFiles, validateUamProject } from "@openfairygui/core/uam";
4
4
  import { applyUamTransactionAppAsync } from "@openfairygui/functions/uam";
5
5
  import { ProjectReader, ProjectWriter } from "@openfairygui/core/project-io";
6
+ import { validateProject } from "@openfairygui/functions";
6
7
  //#region src/path-policy.ts
7
8
  function normalizeComparablePath(value) {
8
9
  const normalized = value.replace(/[/\\]+$/, "").replace(/\\/g, "/");
@@ -97,7 +98,7 @@ function createMeta(stage, startedAt, options) {
97
98
  diagnostics: options?.diagnostics ?? [],
98
99
  stage,
99
100
  contractVersion: BACKEND_CONTRACT_VERSION,
100
- capabilitySchemaVersion: 2
101
+ capabilitySchemaVersion: 3
101
102
  };
102
103
  }
103
104
  function success(stage, startedAt, data, options) {
@@ -1051,6 +1052,48 @@ var JobService = class {
1051
1052
  };
1052
1053
  //#endregion
1053
1054
  //#region src/services/read-service.ts
1055
+ function toProjectOutline(session) {
1056
+ const project = session.project;
1057
+ return {
1058
+ sessionId: session.sessionId,
1059
+ revision: session.revision,
1060
+ projectId: project.projectId,
1061
+ projectType: project.projectType,
1062
+ version: project.version,
1063
+ branches: [...project.branches],
1064
+ packages: project.packages.map((pkg) => ({
1065
+ id: pkg.id,
1066
+ name: pkg.name,
1067
+ branchNames: [...pkg.branchNames],
1068
+ folders: pkg.folders.map((folder) => ({
1069
+ branch: folder.branch,
1070
+ path: folder.path
1071
+ })),
1072
+ resources: pkg.resources.map((resource) => ({
1073
+ id: resource.id,
1074
+ name: resource.name,
1075
+ path: resource.path,
1076
+ kind: resource.kind,
1077
+ branch: resource.branch,
1078
+ ...resource.kind === "component" ? { component: {
1079
+ displayList: resource.component.displayList.map((node) => ({
1080
+ id: node.id,
1081
+ name: node.name,
1082
+ kind: node.kind
1083
+ })),
1084
+ controllers: resource.component.controllers.map((controller) => ({
1085
+ name: controller.name,
1086
+ pages: controller.pages.map((page) => ({
1087
+ id: page.id,
1088
+ name: page.name
1089
+ }))
1090
+ })),
1091
+ transitions: resource.component.transitions.map((transition) => ({ name: transition.name }))
1092
+ } } : {}
1093
+ }))
1094
+ }))
1095
+ };
1096
+ }
1054
1097
  var ReadService = class {
1055
1098
  constructor(context) {
1056
1099
  this.context = context;
@@ -1067,6 +1110,35 @@ var ReadService = class {
1067
1110
  revision: session.revision
1068
1111
  });
1069
1112
  }
1113
+ getProjectOutline(input) {
1114
+ const startedAt = Date.now();
1115
+ const session = this.context.sessions.get(input.sessionId);
1116
+ if (!session || session.closed) return failure("read", startedAt, createSessionNotFoundError(input.sessionId));
1117
+ return success("read", startedAt, toProjectOutline(session), {
1118
+ sessionId: session.sessionId,
1119
+ revision: session.revision
1120
+ });
1121
+ }
1122
+ validateSession(input) {
1123
+ const startedAt = Date.now();
1124
+ const session = this.context.sessions.get(input.sessionId);
1125
+ if (!session || session.closed) return failure("read", startedAt, createSessionNotFoundError(input.sessionId));
1126
+ const report = validateProject(session.project, {
1127
+ readDiagnostics: session.readDiagnostics,
1128
+ complete: session.readComplete,
1129
+ validateSources: true
1130
+ });
1131
+ return success("read", startedAt, report, {
1132
+ sessionId: session.sessionId,
1133
+ revision: session.revision,
1134
+ diagnostics: report.diagnostics.map(({ code, message, severity, path }) => ({
1135
+ code,
1136
+ message,
1137
+ severity,
1138
+ path
1139
+ }))
1140
+ });
1141
+ }
1070
1142
  };
1071
1143
  //#endregion
1072
1144
  //#region src/services/runtime-service.ts
@@ -1222,7 +1294,9 @@ var RuntimeService = class {
1222
1294
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1223
1295
  canonicalPathKey
1224
1296
  }));
1225
- const document = await new ProjectReader(createProjectReaderFileSystem(fileSystem)).read(fairyPath, { hydrateResourceBytes: true });
1297
+ const read = await new ProjectReader(createProjectReaderFileSystem(fileSystem)).readDetailed(fairyPath, { hydrateResourceBytes: true });
1298
+ if (!read.document) throw new Error(read.diagnostics[0]?.message ?? `Unable to read project: ${fairyPath}`);
1299
+ const document = read.document;
1226
1300
  const project = liftDocumentToUamProject(document);
1227
1301
  const sessionId = randomId();
1228
1302
  const session = {
@@ -1234,6 +1308,8 @@ var RuntimeService = class {
1234
1308
  sessionLock,
1235
1309
  fileSystem,
1236
1310
  project,
1311
+ readDiagnostics: read.diagnostics,
1312
+ readComplete: read.complete,
1237
1313
  uamFidelity: await hasFullUamFidelity(document, project) ? "full" : "unsupported",
1238
1314
  revision: 0,
1239
1315
  lastSavedRevision: 0,
@@ -1297,6 +1373,8 @@ var RuntimeService = class {
1297
1373
  sessionLock: null,
1298
1374
  fileSystem: storage?.fileSystem,
1299
1375
  project: normalizeUamProject(input.project),
1376
+ readDiagnostics: [],
1377
+ readComplete: true,
1300
1378
  uamFidelity: "full",
1301
1379
  revision: 0,
1302
1380
  lastSavedRevision: 0,
@@ -1380,6 +1458,8 @@ const BACKEND_METHODS = [
1380
1458
  "openSession",
1381
1459
  "openProjectSession",
1382
1460
  "getSession",
1461
+ "getProjectOutline",
1462
+ "validateSession",
1383
1463
  "applyTransaction",
1384
1464
  "saveSession",
1385
1465
  "materializeSession",
@@ -1401,14 +1481,16 @@ const ARTIFACT_BRIDGE_CAPABILITY = {
1401
1481
  function createCapabilities() {
1402
1482
  return {
1403
1483
  contractVersion: BACKEND_CONTRACT_VERSION,
1404
- capabilitySchemaVersion: 2,
1484
+ capabilitySchemaVersion: 3,
1405
1485
  transactionKernelOwner: "@openfairygui/core",
1406
1486
  appSeamOwner: "@openfairygui/functions",
1407
1487
  runtimeOwner: "@openfairygui/backend",
1408
1488
  methods: BACKEND_METHODS,
1409
1489
  read: {
1410
1490
  capabilitySnapshot: true,
1411
- sessionSnapshot: true
1491
+ sessionSnapshot: true,
1492
+ projectOutline: true,
1493
+ projectValidation: true
1412
1494
  },
1413
1495
  authoring: {
1414
1496
  applyTransaction: true,
@@ -1548,6 +1630,12 @@ var BackendRuntime = class {
1548
1630
  getSession(input) {
1549
1631
  return this.readService.getSession(input);
1550
1632
  }
1633
+ getProjectOutline(input) {
1634
+ return this.readService.getProjectOutline(input);
1635
+ }
1636
+ validateSession(input) {
1637
+ return this.readService.validateSession(input);
1638
+ }
1551
1639
  async applyTransaction(input) {
1552
1640
  return this.authoringService.applyTransaction(input);
1553
1641
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfairygui/backend",
3
- "version": "0.2.0",
3
+ "version": "0.3.0-alpha.2",
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",
56
- "@openfairygui/functions": "0.2.0"
55
+ "@openfairygui/core": "0.3.0-alpha.2",
56
+ "@openfairygui/functions": "0.3.0-alpha.2"
57
57
  },
58
58
  "devDependencies": {
59
59
  "ava": "^7.0.0",
package/src/contracts.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export const BACKEND_CONTRACT_VERSION = '1.1.0-p2' as const;
2
- export const BACKEND_CAPABILITY_SCHEMA_VERSION = 2 as const;
2
+ export const BACKEND_CAPABILITY_SCHEMA_VERSION = 3 as const;
3
3
  export const BACKEND_COMPATIBILITY_POLICY = {
4
4
  incompatibleChange: 'requires contractVersion bump',
5
5
  capabilitySchemaChange: 'requires capabilitySchemaVersion bump',
package/src/index.ts CHANGED
@@ -32,6 +32,9 @@ export {
32
32
  type BackendJobProgress,
33
33
  type BackendJobSnapshot,
34
34
  type BackendJobStatus,
35
+ type BackendProjectOutline,
36
+ type BackendProjectOutlinePackage,
37
+ type BackendProjectOutlineResource,
35
38
  type BackendProjectSessionStorage,
36
39
  type BackendResult,
37
40
  BackendRuntime,
@@ -46,6 +49,7 @@ export {
46
49
  type GetEventsInput,
47
50
  type GetEventsSnapshot,
48
51
  type GetJobInput,
52
+ type GetProjectOutlineInput,
49
53
  type InProcessLockConflictError,
50
54
  type ListJobsInput,
51
55
  type MaterializeSessionInput,
@@ -59,6 +63,7 @@ export {
59
63
  type SessionNotFoundError,
60
64
  type SessionStaleWriteError,
61
65
  type UamFidelityUnsupportedError,
66
+ type ValidateSessionInput,
62
67
  } from './runtime.js';
63
68
  export {
64
69
  type BackendAsyncStorageAdapter,
@@ -16,6 +16,8 @@ const BACKEND_METHODS = [
16
16
  'openSession',
17
17
  'openProjectSession',
18
18
  'getSession',
19
+ 'getProjectOutline',
20
+ 'validateSession',
19
21
  'applyTransaction',
20
22
  'saveSession',
21
23
  'materializeSession',
@@ -47,6 +49,8 @@ export function createCapabilities(): BackendCapabilities {
47
49
  read: {
48
50
  capabilitySnapshot: true,
49
51
  sessionSnapshot: true,
52
+ projectOutline: true,
53
+ projectValidation: true,
50
54
  },
51
55
  authoring: {
52
56
  applyTransaction: true,
@@ -1,4 +1,9 @@
1
- import type { UamProject, UamTransactionOperation } from '@openfairygui/core/uam';
1
+ import type {
2
+ UamDisplayNodeKind,
3
+ UamProject,
4
+ UamResource,
5
+ UamTransactionOperation,
6
+ } from '@openfairygui/core/uam';
2
7
  import type { ApplyUamTransactionAppError } from '@openfairygui/functions/uam';
3
8
  import type {
4
9
  BACKEND_CAPABILITY_SCHEMA_VERSION,
@@ -94,6 +99,8 @@ export interface BackendCapabilities {
94
99
  'openSession',
95
100
  'openProjectSession',
96
101
  'getSession',
102
+ 'getProjectOutline',
103
+ 'validateSession',
97
104
  'applyTransaction',
98
105
  'saveSession',
99
106
  'materializeSession',
@@ -108,6 +115,8 @@ export interface BackendCapabilities {
108
115
  read: {
109
116
  capabilitySnapshot: true;
110
117
  sessionSnapshot: true;
118
+ projectOutline: true;
119
+ projectValidation: true;
111
120
  };
112
121
  authoring: {
113
122
  applyTransaction: true;
@@ -178,6 +187,37 @@ export interface BackendSessionSnapshot {
178
187
  capabilities: BackendCapabilities;
179
188
  }
180
189
 
190
+ export interface BackendProjectOutline {
191
+ sessionId: string;
192
+ revision: number;
193
+ projectId: string;
194
+ projectType: number;
195
+ version: string;
196
+ branches: string[];
197
+ packages: BackendProjectOutlinePackage[];
198
+ }
199
+
200
+ export interface BackendProjectOutlinePackage {
201
+ id: string;
202
+ name: string;
203
+ branchNames: string[];
204
+ folders: Array<{ branch: string; path: string }>;
205
+ resources: BackendProjectOutlineResource[];
206
+ }
207
+
208
+ export interface BackendProjectOutlineResource {
209
+ id: string;
210
+ name: string;
211
+ path: string;
212
+ kind: UamResource['kind'];
213
+ branch: string;
214
+ component?: {
215
+ displayList: Array<{ id: string; name: string; kind: UamDisplayNodeKind }>;
216
+ controllers: Array<{ name: string; pages: Array<{ id: string; name: string }> }>;
217
+ transitions: Array<{ name: string }>;
218
+ };
219
+ }
220
+
181
221
  export interface MaterializeSessionSnapshot extends BackendSessionSnapshot {
182
222
  mode: 'fullProject';
183
223
  reason?: string;
@@ -476,6 +516,14 @@ export interface ApplySessionTransactionInput {
476
516
  operations: UamTransactionOperation[];
477
517
  }
478
518
 
519
+ export interface GetProjectOutlineInput {
520
+ sessionId: string;
521
+ }
522
+
523
+ export interface ValidateSessionInput {
524
+ sessionId: string;
525
+ }
526
+
479
527
  export interface OpenProjectSessionInput {
480
528
  /** Authoritative UAM project. Use BackendRuntime.openSession() when importing an existing project from storage. */
481
529
  project: UamProject;