@tutti-os/workspace-app-center 0.0.12 → 0.0.14
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/{chunk-PD2WLRHE.js → chunk-7BJAJ7F3.js} +1 -1
- package/dist/chunk-7BJAJ7F3.js.map +1 -0
- package/dist/{chunk-Y63TZ5JT.js → chunk-AWA3NSBR.js} +1 -1
- package/dist/chunk-AWA3NSBR.js.map +1 -0
- package/dist/{chunk-O3XCZVHE.js → chunk-F76FG674.js} +217 -33
- package/dist/chunk-F76FG674.js.map +1 -0
- package/dist/contracts/index.d.ts +7 -3
- package/dist/contracts/index.js +2 -2
- package/dist/core/index.d.ts +8 -3
- package/dist/core/index.js +2 -2
- package/dist/i18n/index.js +115 -147
- package/dist/i18n/index.js.map +1 -1
- package/dist/{index-DT5o9P2u.d.ts → index-Cy1APjhZ.d.ts} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/ui/index.d.ts +3 -2
- package/dist/ui/index.js +228 -109
- package/dist/ui/index.js.map +1 -1
- package/dist/{viewModel-BpgU7_M1.d.ts → viewModel-CfNTZHZw.d.ts} +14 -1
- package/package.json +3 -3
- package/dist/chunk-O3XCZVHE.js.map +0 -1
- package/dist/chunk-PD2WLRHE.js.map +0 -1
- package/dist/chunk-Y63TZ5JT.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contracts/runtime.ts"],"sourcesContent":["export const workspaceAppRuntimeStatuses = [\n \"idle\",\n \"installing\",\n \"preparing\",\n \"starting\",\n \"running\",\n \"failed\",\n \"stopping\",\n \"unavailable\"\n] as const;\n\nexport type WorkspaceAppRuntimeStatus =\n (typeof workspaceAppRuntimeStatuses)[number];\n\nexport interface WorkspaceAppRuntimeError {\n readonly code?: string;\n readonly message: string;\n}\n\nexport type WorkspaceAppInstallUserPhase =\n | \"downloading\"\n | \"installing\"\n | \"starting\";\n\nexport interface WorkspaceAppInstallProgress {\n readonly userPhase: WorkspaceAppInstallUserPhase;\n readonly overallPercent: number;\n readonly downloadedBytes?: number | null;\n readonly totalBytes?: number | null;\n readonly indeterminate: boolean;\n}\n\nexport interface WorkspaceAppRuntimeState {\n readonly runtimeId?: string;\n readonly installationId?: string;\n readonly appId: string;\n readonly status: WorkspaceAppRuntimeStatus;\n readonly launchUrl?: string | null;\n readonly installProgress?: WorkspaceAppInstallProgress | null;\n readonly error?: WorkspaceAppRuntimeError | null;\n readonly startedAt?: string | null;\n readonly updatedAt?: string | null;\n}\n"],"mappings":";AAAO,IAAM,8BAA8B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contracts/manifest.ts"],"sourcesContent":["export const workspaceAppManifestSchemaVersion = \"tutti.app.manifest.v1\";\n\nexport type WorkspaceAppManifestSchemaVersion =\n typeof workspaceAppManifestSchemaVersion;\n\nexport interface WorkspaceAppManifestIcon {\n readonly type: \"asset\";\n readonly src: string;\n}\n\nexport interface WorkspaceAppManifestRuntime {\n readonly bootstrap: string;\n readonly healthcheckPath: string;\n}\n\nexport interface WorkspaceAppManifestReferences {\n readonly listEndpoint: string;\n readonly searchEndpoint?: string;\n}\n\nexport type WorkspaceAppManifestWindowMinimizeBehavior =\n | \"hibernate\"\n | \"keep-mounted\";\n\nexport interface WorkspaceAppManifestWindow {\n readonly minimizeBehavior?: WorkspaceAppManifestWindowMinimizeBehavior;\n readonly minHeight?: number;\n readonly minWidth?: number;\n}\n\nexport interface WorkspaceAppManifestAuthor {\n readonly name: string;\n readonly url?: string;\n}\n\nexport interface WorkspaceAppManifestLocalizationInfo {\n readonly defaultLocale: string;\n readonly additionalLocales?: readonly WorkspaceAppManifestLocalizationFile[];\n}\n\nexport interface WorkspaceAppManifestLocalizationFile {\n readonly locale: string;\n readonly file: string;\n}\n\nexport interface WorkspaceAppManifest {\n readonly schemaVersion: WorkspaceAppManifestSchemaVersion;\n readonly appId: string;\n readonly name: string;\n readonly version: string;\n readonly description: string;\n readonly icon?: WorkspaceAppManifestIcon;\n readonly runtime: WorkspaceAppManifestRuntime;\n readonly references?: WorkspaceAppManifestReferences;\n readonly window?: WorkspaceAppManifestWindow;\n readonly author?: WorkspaceAppManifestAuthor;\n readonly tags?: readonly string[];\n readonly localizationInfo?: WorkspaceAppManifestLocalizationInfo;\n}\n"],"mappings":";AAAO,IAAM,oCAAoC;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
workspaceAppManifestSchemaVersion
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AWA3NSBR.js";
|
|
4
4
|
|
|
5
5
|
// src/core/appCenterControllerHelpers.ts
|
|
6
6
|
function resolveAppRunDurationMs(startedAtUnixMs, now) {
|
|
@@ -30,13 +30,25 @@ function mergeWorkspaceAppCatalogFields(currentApp, snapshotApp) {
|
|
|
30
30
|
updateAvailable: snapshotApp.updateAvailable
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
+
function areWorkspaceAppInstallProgressEqual(left, right) {
|
|
34
|
+
if (left == null && right == null) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
if (left == null || right == null) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return left.userPhase === right.userPhase && left.overallPercent === right.overallPercent && left.downloadedBytes === right.downloadedBytes && left.totalBytes === right.totalBytes && left.indeterminate === right.indeterminate;
|
|
41
|
+
}
|
|
33
42
|
function areWorkspaceAppCenterAppsEqual(left, right) {
|
|
34
43
|
if (left.length !== right.length) {
|
|
35
44
|
return false;
|
|
36
45
|
}
|
|
37
46
|
return left.every((leftApp, index) => {
|
|
38
47
|
const rightApp = right[index];
|
|
39
|
-
return rightApp !== void 0 && leftApp.appId === rightApp.appId && leftApp.availableIconUrl === rightApp.availableIconUrl && leftApp.availableVersion === rightApp.availableVersion && leftApp.createdAtUnixMs === rightApp.createdAtUnixMs && leftApp.description === rightApp.description && leftApp.enabled === rightApp.enabled && leftApp.exportable === rightApp.exportable && leftApp.iconUrl === rightApp.iconUrl && leftApp.installed === rightApp.installed &&
|
|
48
|
+
return rightApp !== void 0 && leftApp.appId === rightApp.appId && leftApp.availableIconUrl === rightApp.availableIconUrl && leftApp.availableVersion === rightApp.availableVersion && leftApp.createdAtUnixMs === rightApp.createdAtUnixMs && leftApp.description === rightApp.description && leftApp.enabled === rightApp.enabled && leftApp.exportable === rightApp.exportable && leftApp.iconUrl === rightApp.iconUrl && leftApp.installed === rightApp.installed && areWorkspaceAppInstallProgressEqual(
|
|
49
|
+
leftApp.installProgress,
|
|
50
|
+
rightApp.installProgress
|
|
51
|
+
) && leftApp.installationId === rightApp.installationId && areWorkspaceAppCenterLocalizationsEqual(
|
|
40
52
|
leftApp.localizations ?? [],
|
|
41
53
|
rightApp.localizations ?? []
|
|
42
54
|
) && leftApp.minimizeBehavior === rightApp.minimizeBehavior && leftApp.name === rightApp.name && leftApp.references.listSupported === rightApp.references.listSupported && leftApp.runtimeId === rightApp.runtimeId && leftApp.runtimeStatus === rightApp.runtimeStatus && leftApp.source === rightApp.source && leftApp.stateRevision === rightApp.stateRevision && areStringArraysEqual(leftApp.tags ?? [], rightApp.tags ?? []) && (leftApp.updateAvailable ?? false) === (rightApp.updateAvailable ?? false) && leftApp.launchUrl === rightApp.launchUrl && leftApp.version === rightApp.version && leftApp.windowMinHeight === rightApp.windowMinHeight && leftApp.windowMinWidth === rightApp.windowMinWidth;
|
|
@@ -276,6 +288,85 @@ var WorkspaceAppCenterControllerBase = class {
|
|
|
276
288
|
}
|
|
277
289
|
};
|
|
278
290
|
|
|
291
|
+
// src/core/installProgressMerge.ts
|
|
292
|
+
var installUserPhaseOrder = {
|
|
293
|
+
downloading: 0,
|
|
294
|
+
installing: 1,
|
|
295
|
+
starting: 2
|
|
296
|
+
};
|
|
297
|
+
var defaultDownloadCompletePercent = 70;
|
|
298
|
+
var defaultInstallingPartialPercent = 79;
|
|
299
|
+
var defaultStartingPartialPercent = 96;
|
|
300
|
+
function reconcilePendingInstallProgress(input) {
|
|
301
|
+
const runtimePhase = runtimeStatusToInstallUserPhase(input.runtimeStatus);
|
|
302
|
+
const progress = input.incoming ?? input.previous ?? (runtimePhase == null ? null : createProgressForRuntimePhase(runtimePhase));
|
|
303
|
+
if (progress == null) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
if (runtimePhase == null) {
|
|
307
|
+
return clearDownloadBytesUnlessDownloading(progress);
|
|
308
|
+
}
|
|
309
|
+
if (compareInstallUserPhase(progress.userPhase, runtimePhase) >= 0) {
|
|
310
|
+
return clearDownloadBytesUnlessDownloading(progress);
|
|
311
|
+
}
|
|
312
|
+
return advanceInstallProgressToPhase(progress, runtimePhase);
|
|
313
|
+
}
|
|
314
|
+
function runtimeStatusToInstallUserPhase(runtimeStatus) {
|
|
315
|
+
switch (runtimeStatus) {
|
|
316
|
+
case "preparing":
|
|
317
|
+
return "installing";
|
|
318
|
+
case "starting":
|
|
319
|
+
return "starting";
|
|
320
|
+
default:
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function compareInstallUserPhase(left, right) {
|
|
325
|
+
return installUserPhaseOrder[left] - installUserPhaseOrder[right];
|
|
326
|
+
}
|
|
327
|
+
function advanceInstallProgressToPhase(progress, targetPhase) {
|
|
328
|
+
let overallPercent = progress.overallPercent;
|
|
329
|
+
let userPhase = progress.userPhase;
|
|
330
|
+
if (targetPhase === "installing" || targetPhase === "starting") {
|
|
331
|
+
overallPercent = Math.max(overallPercent, defaultDownloadCompletePercent);
|
|
332
|
+
userPhase = "installing";
|
|
333
|
+
}
|
|
334
|
+
if (targetPhase === "starting") {
|
|
335
|
+
overallPercent = Math.max(overallPercent, defaultStartingPartialPercent);
|
|
336
|
+
userPhase = "starting";
|
|
337
|
+
} else if (targetPhase === "installing") {
|
|
338
|
+
overallPercent = Math.max(overallPercent, defaultInstallingPartialPercent);
|
|
339
|
+
}
|
|
340
|
+
return clearDownloadBytesUnlessDownloading({
|
|
341
|
+
...progress,
|
|
342
|
+
indeterminate: false,
|
|
343
|
+
overallPercent,
|
|
344
|
+
userPhase
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
function createProgressForRuntimePhase(userPhase) {
|
|
348
|
+
return advanceInstallProgressToPhase(
|
|
349
|
+
{
|
|
350
|
+
downloadedBytes: null,
|
|
351
|
+
indeterminate: false,
|
|
352
|
+
overallPercent: 0,
|
|
353
|
+
totalBytes: null,
|
|
354
|
+
userPhase: "downloading"
|
|
355
|
+
},
|
|
356
|
+
userPhase
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
function clearDownloadBytesUnlessDownloading(progress) {
|
|
360
|
+
if (progress.userPhase === "downloading") {
|
|
361
|
+
return progress;
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
...progress,
|
|
365
|
+
downloadedBytes: null,
|
|
366
|
+
totalBytes: null
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
|
|
279
370
|
// src/core/appCenterControllerState.ts
|
|
280
371
|
var WorkspaceAppCenterControllerState = class extends WorkspaceAppCenterControllerBase {
|
|
281
372
|
applySnapshot(workspaceId, snapshot) {
|
|
@@ -371,11 +462,16 @@ var WorkspaceAppCenterControllerState = class extends WorkspaceAppCenterControll
|
|
|
371
462
|
return;
|
|
372
463
|
}
|
|
373
464
|
const appIdsToClose = currentApp?.installed === true && !nextApp.installed ? [nextApp.appId] : [];
|
|
465
|
+
const mergedApp = this.mergeActiveInstallAppState(
|
|
466
|
+
workspaceId,
|
|
467
|
+
nextApp,
|
|
468
|
+
currentApp
|
|
469
|
+
);
|
|
374
470
|
const nextApps = sortWorkspaceAppCenterApps([
|
|
375
471
|
...this.store.apps.filter(
|
|
376
472
|
(candidate) => candidate.appId !== nextApp.appId
|
|
377
473
|
),
|
|
378
|
-
|
|
474
|
+
mergedApp
|
|
379
475
|
]);
|
|
380
476
|
if (areWorkspaceAppCenterAppsEqual(this.store.apps, nextApps)) {
|
|
381
477
|
return;
|
|
@@ -385,8 +481,8 @@ var WorkspaceAppCenterControllerState = class extends WorkspaceAppCenterControll
|
|
|
385
481
|
this.store.loadStatus = "ready";
|
|
386
482
|
this.bumpRevision();
|
|
387
483
|
this.settlePendingInstallReport({
|
|
388
|
-
app:
|
|
389
|
-
failureReason: options.installFailureReason ??
|
|
484
|
+
app: mergedApp,
|
|
485
|
+
failureReason: options.installFailureReason ?? mergedApp.failureReason ?? mergedApp.lastError ?? null,
|
|
390
486
|
workspaceId
|
|
391
487
|
});
|
|
392
488
|
this.closeWorkspaceAppViews(workspaceId, appIdsToClose);
|
|
@@ -495,15 +591,24 @@ var WorkspaceAppCenterControllerState = class extends WorkspaceAppCenterControll
|
|
|
495
591
|
this.bumpRevision();
|
|
496
592
|
}
|
|
497
593
|
}
|
|
498
|
-
isPendingInstallSettled(installKey, app) {
|
|
594
|
+
isPendingInstallSettled(installKey, app, previousApp) {
|
|
595
|
+
if (this.isPendingInstallAbandoned(installKey, app, previousApp)) {
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
499
598
|
if (app.runtimeStatus === "failed") {
|
|
500
599
|
return true;
|
|
501
600
|
}
|
|
601
|
+
if (this.isRuntimeInstallBusy(app.runtimeStatus)) {
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
502
604
|
if (this.pendingInstallReportKeys.has(installKey)) {
|
|
503
605
|
return app.installed;
|
|
504
606
|
}
|
|
505
607
|
return app.installed && !app.updateAvailable && !app.availableVersion;
|
|
506
608
|
}
|
|
609
|
+
isRuntimeInstallBusy(runtimeStatus) {
|
|
610
|
+
return runtimeStatus === "installing" || runtimeStatus === "preparing" || runtimeStatus === "starting";
|
|
611
|
+
}
|
|
507
612
|
mergeSnapshotAppsByStateRevision(workspaceId, snapshotApps) {
|
|
508
613
|
if (this.store.workspaceId !== workspaceId) {
|
|
509
614
|
return [...snapshotApps];
|
|
@@ -520,7 +625,8 @@ var WorkspaceAppCenterControllerState = class extends WorkspaceAppCenterControll
|
|
|
520
625
|
if (this.pendingInstallKeys.has(installKey)) {
|
|
521
626
|
const pendingSettled = this.isPendingInstallSettled(
|
|
522
627
|
installKey,
|
|
523
|
-
snapshotApp
|
|
628
|
+
snapshotApp,
|
|
629
|
+
currentApp
|
|
524
630
|
);
|
|
525
631
|
if (pendingSettled && currentApp.stateRevision <= snapshotApp.stateRevision) {
|
|
526
632
|
return snapshotApp;
|
|
@@ -545,22 +651,50 @@ var WorkspaceAppCenterControllerState = class extends WorkspaceAppCenterControll
|
|
|
545
651
|
void this.refresh(workspaceId);
|
|
546
652
|
}, this.dependencies.catalogLoadingRefreshDelayMs ?? defaultCatalogLoadingRefreshDelayMs);
|
|
547
653
|
}
|
|
654
|
+
mergeActiveInstallAppState(workspaceId, app, previousApp) {
|
|
655
|
+
const installKey = appRuntimeKey(workspaceId, app.appId);
|
|
656
|
+
if (!this.pendingInstallKeys.has(installKey)) {
|
|
657
|
+
return app;
|
|
658
|
+
}
|
|
659
|
+
if (this.isPendingInstallSettled(installKey, app, previousApp)) {
|
|
660
|
+
return app;
|
|
661
|
+
}
|
|
662
|
+
const incomingRuntimeStatus = app.runtimeStatus;
|
|
663
|
+
const runtimeStatus = this.isRuntimeInstallLifecycleStatus(
|
|
664
|
+
incomingRuntimeStatus
|
|
665
|
+
) ? incomingRuntimeStatus : "installing";
|
|
666
|
+
return {
|
|
667
|
+
...app,
|
|
668
|
+
enabled: true,
|
|
669
|
+
installed: this.pendingInstallReportKeys.has(installKey) ? false : app.installed,
|
|
670
|
+
installProgress: reconcilePendingInstallProgress({
|
|
671
|
+
incoming: app.installProgress,
|
|
672
|
+
previous: previousApp?.installProgress ?? null,
|
|
673
|
+
runtimeStatus: incomingRuntimeStatus
|
|
674
|
+
}),
|
|
675
|
+
runtimeStatus
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
isRuntimeInstallLifecycleStatus(runtimeStatus) {
|
|
679
|
+
return runtimeStatus === "installing" || runtimeStatus === "preparing" || runtimeStatus === "starting";
|
|
680
|
+
}
|
|
681
|
+
isPendingInstallAbandoned(installKey, app, previousApp) {
|
|
682
|
+
return this.pendingInstallReportKeys.has(installKey) && !app.installed && app.runtimeStatus === "idle" && app.installProgress == null && this.hasObservedInstallActivity(previousApp);
|
|
683
|
+
}
|
|
684
|
+
hasObservedInstallActivity(app) {
|
|
685
|
+
return app?.installProgress != null || app?.runtimeStatus === "preparing" || app?.runtimeStatus === "starting";
|
|
686
|
+
}
|
|
548
687
|
withPendingInstallState(workspaceId, apps) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
enabled: true,
|
|
560
|
-
installed: this.pendingInstallReportKeys.has(installKey) ? false : app.installed,
|
|
561
|
-
runtimeStatus: "installing"
|
|
562
|
-
};
|
|
563
|
-
});
|
|
688
|
+
const previousAppsById = new Map(
|
|
689
|
+
this.store.apps.map((app) => [app.appId, app])
|
|
690
|
+
);
|
|
691
|
+
return apps.map(
|
|
692
|
+
(app) => this.mergeActiveInstallAppState(
|
|
693
|
+
workspaceId,
|
|
694
|
+
app,
|
|
695
|
+
previousAppsById.get(app.appId)
|
|
696
|
+
)
|
|
697
|
+
);
|
|
564
698
|
}
|
|
565
699
|
async refreshInstallState(workspaceId, appId) {
|
|
566
700
|
try {
|
|
@@ -595,6 +729,9 @@ var WorkspaceAppCenterControllerState = class extends WorkspaceAppCenterControll
|
|
|
595
729
|
this.dependencies.hooks?.onAppInstalled?.(input.app);
|
|
596
730
|
return;
|
|
597
731
|
}
|
|
732
|
+
if (input.app.runtimeStatus === "idle" && input.app.installProgress == null && input.failureReason == null && input.app.failureReason == null && input.app.lastError == null) {
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
598
735
|
this.dependencies.hooks?.onAppInstallFailed?.({
|
|
599
736
|
app: input.app,
|
|
600
737
|
appId: input.app.appId,
|
|
@@ -954,11 +1091,16 @@ var WorkspaceAppCenterController = class extends WorkspaceAppCenterControllerSta
|
|
|
954
1091
|
this.pendingInstallKeys.add(installKey);
|
|
955
1092
|
this.markAppInstalling(input.appId, { preserveInstalled: true });
|
|
956
1093
|
try {
|
|
1094
|
+
const restartRunning = app?.installed === true && app.runtimeStatus === "running";
|
|
957
1095
|
const snapshot = await this.dependencies.gateway.installWorkspaceApp(
|
|
958
1096
|
input.workspaceId,
|
|
959
|
-
input.appId
|
|
1097
|
+
input.appId,
|
|
1098
|
+
restartRunning ? { restartRunning: true } : void 0
|
|
960
1099
|
);
|
|
961
1100
|
this.applySnapshot(input.workspaceId, snapshot);
|
|
1101
|
+
if (restartRunning) {
|
|
1102
|
+
this.closeWorkspaceAppViews(input.workspaceId, [input.appId]);
|
|
1103
|
+
}
|
|
962
1104
|
this.dependencies.hooks?.onAppUpdated?.({
|
|
963
1105
|
app,
|
|
964
1106
|
trigger: input.trigger
|
|
@@ -1252,7 +1394,7 @@ function validateReferences(value, issues) {
|
|
|
1252
1394
|
return void 0;
|
|
1253
1395
|
}
|
|
1254
1396
|
const unsupportedKey = Object.keys(value).find(
|
|
1255
|
-
(key) => key !== "listEndpoint"
|
|
1397
|
+
(key) => key !== "listEndpoint" && key !== "searchEndpoint"
|
|
1256
1398
|
);
|
|
1257
1399
|
if (unsupportedKey) {
|
|
1258
1400
|
issues.push({
|
|
@@ -1271,6 +1413,18 @@ function validateReferences(value, issues) {
|
|
|
1271
1413
|
});
|
|
1272
1414
|
return void 0;
|
|
1273
1415
|
}
|
|
1416
|
+
if (value.searchEndpoint !== void 0) {
|
|
1417
|
+
const searchEndpoint = readOptionalString(value.searchEndpoint);
|
|
1418
|
+
if (!searchEndpoint || !isRelativeUrlPath(searchEndpoint)) {
|
|
1419
|
+
issues.push({
|
|
1420
|
+
code: "manifest.references",
|
|
1421
|
+
message: "references.searchEndpoint must be a relative URL path without query or fragment.",
|
|
1422
|
+
path: "$.references.searchEndpoint"
|
|
1423
|
+
});
|
|
1424
|
+
return void 0;
|
|
1425
|
+
}
|
|
1426
|
+
return { listEndpoint, searchEndpoint };
|
|
1427
|
+
}
|
|
1274
1428
|
return { listEndpoint };
|
|
1275
1429
|
}
|
|
1276
1430
|
function validateWindow(value, issues) {
|
|
@@ -1600,9 +1754,11 @@ function createAppCenterViewModel({
|
|
|
1600
1754
|
manifest: app.manifest
|
|
1601
1755
|
});
|
|
1602
1756
|
const factoryAgentSessionId = factoryJob?.agentSessionId?.trim() || null;
|
|
1603
|
-
const
|
|
1757
|
+
const factoryEditAction = factoryJob && factoryAgentSessionId ? factoryJob.status === "published" ? "prepare_modification" : "open_session" : null;
|
|
1758
|
+
const status = resolveRuntimeStatusForViewModel(runtime);
|
|
1604
1759
|
const presentation = resolveWorkspaceAppStatusPresentation(status);
|
|
1605
1760
|
const installed = Boolean(app.install);
|
|
1761
|
+
const installBusy = runtime?.installProgress != null || status === "installing";
|
|
1606
1762
|
const sourceKind = resolveCatalogSourceKind(app.catalog);
|
|
1607
1763
|
const localApp = sourceKind === "local";
|
|
1608
1764
|
const runtimeId = normalizeOptionalString(runtime?.runtimeId);
|
|
@@ -1624,6 +1780,7 @@ function createAppCenterViewModel({
|
|
|
1624
1780
|
installed,
|
|
1625
1781
|
status
|
|
1626
1782
|
});
|
|
1783
|
+
const iconUrl = resolveWorkspaceAppIconUrl(app);
|
|
1627
1784
|
return {
|
|
1628
1785
|
id: app.manifest.appId,
|
|
1629
1786
|
installationId,
|
|
@@ -1636,30 +1793,37 @@ function createAppCenterViewModel({
|
|
|
1636
1793
|
...app.availableVersion && !comingSoon ? { availableVersion: app.availableVersion } : {},
|
|
1637
1794
|
...app.category?.trim() ? { category: app.category.trim() } : {},
|
|
1638
1795
|
updateAvailable: app.updateAvailable ?? false,
|
|
1639
|
-
...
|
|
1796
|
+
...iconUrl ? {
|
|
1797
|
+
icon: {
|
|
1798
|
+
type: "asset",
|
|
1799
|
+
src: iconUrl
|
|
1800
|
+
}
|
|
1801
|
+
} : {},
|
|
1640
1802
|
tags: metadata.tags,
|
|
1641
1803
|
installed,
|
|
1642
1804
|
status,
|
|
1643
1805
|
statusLabelKey: comingSoon ? "status.comingSoon" : resolvePrimaryActionLabelKey(primaryAction, presentation.labelKey),
|
|
1644
1806
|
statusTone: presentation.tone,
|
|
1645
|
-
statusPulse: presentation.pulse,
|
|
1807
|
+
statusPulse: runtime?.installProgress ? false : presentation.pulse,
|
|
1646
1808
|
primaryAction,
|
|
1647
1809
|
sourceKind,
|
|
1648
1810
|
canOpen,
|
|
1649
1811
|
canExport: localApp,
|
|
1650
1812
|
canDelete: localApp,
|
|
1651
1813
|
canReplaceIcon: replaceableIconAppIdSet.has(app.manifest.appId),
|
|
1652
|
-
canOpenFolder: installed,
|
|
1653
|
-
canOpenPackageFolder: installed && localApp && Boolean(displayVersion),
|
|
1814
|
+
canOpenFolder: installed && !installBusy,
|
|
1815
|
+
canOpenPackageFolder: installed && localApp && Boolean(displayVersion) && !installBusy,
|
|
1654
1816
|
canOpenFactorySession: Boolean(factoryAgentSessionId),
|
|
1655
1817
|
canPublishFactoryUpdate: installed && factoryJob?.status === "ready" && Boolean(factoryJob.publishedVersion?.trim()),
|
|
1656
|
-
canUninstall: installed,
|
|
1818
|
+
canUninstall: installed && !installBusy,
|
|
1657
1819
|
canRetry,
|
|
1658
1820
|
canUpdate,
|
|
1659
1821
|
...factoryAgentSessionId ? { factoryAgentSessionId } : {},
|
|
1822
|
+
...factoryEditAction ? { factoryEditAction } : {},
|
|
1660
1823
|
...factoryJob?.jobId ? { factoryJobId: factoryJob.jobId } : {},
|
|
1661
1824
|
...factoryJob?.provider ? { factoryProvider: factoryJob.provider } : {},
|
|
1662
|
-
...runtime?.error?.message ? { errorMessage: runtime.error.message } : {}
|
|
1825
|
+
...runtime?.error?.message ? { errorMessage: runtime.error.message } : {},
|
|
1826
|
+
...runtime?.installProgress ? { installProgress: runtime.installProgress } : {}
|
|
1663
1827
|
};
|
|
1664
1828
|
}).sort((left, right) => left.name.localeCompare(right.name));
|
|
1665
1829
|
return {
|
|
@@ -1677,7 +1841,8 @@ function createRuntimeStateMaps(runtimeStates) {
|
|
|
1677
1841
|
for (const state of runtimeStates) {
|
|
1678
1842
|
const runtime = {
|
|
1679
1843
|
...state,
|
|
1680
|
-
status: mapWorkspaceAppRuntimeStatus(state.status)
|
|
1844
|
+
status: mapWorkspaceAppRuntimeStatus(state.status),
|
|
1845
|
+
installProgress: state.installProgress ?? null
|
|
1681
1846
|
};
|
|
1682
1847
|
const installationId = normalizeOptionalString(runtime.installationId);
|
|
1683
1848
|
if (installationId) {
|
|
@@ -1703,6 +1868,15 @@ function findRuntimeStateForApp(maps, appId, installationId) {
|
|
|
1703
1868
|
}
|
|
1704
1869
|
return maps.fallbackByAppId.get(appId);
|
|
1705
1870
|
}
|
|
1871
|
+
function resolveRuntimeStatusForViewModel(runtime) {
|
|
1872
|
+
if (!runtime) {
|
|
1873
|
+
return "idle";
|
|
1874
|
+
}
|
|
1875
|
+
if (runtime.installProgress != null && runtime.status === "idle") {
|
|
1876
|
+
return "installing";
|
|
1877
|
+
}
|
|
1878
|
+
return runtime.status;
|
|
1879
|
+
}
|
|
1706
1880
|
function resolveCatalogSourceKind(catalog) {
|
|
1707
1881
|
return catalog?.source?.kind ?? "bundled";
|
|
1708
1882
|
}
|
|
@@ -1749,6 +1923,16 @@ function normalizeOptionalString(value) {
|
|
|
1749
1923
|
const normalized = value?.trim() ?? "";
|
|
1750
1924
|
return normalized.length > 0 ? normalized : null;
|
|
1751
1925
|
}
|
|
1926
|
+
function resolveWorkspaceAppIconUrl(app) {
|
|
1927
|
+
const manifestIconUrl = normalizeOptionalString(app.manifest.icon?.src);
|
|
1928
|
+
if (manifestIconUrl && isResolvedIconUrl(manifestIconUrl)) {
|
|
1929
|
+
return manifestIconUrl;
|
|
1930
|
+
}
|
|
1931
|
+
return normalizeOptionalString(app.availableIconUrl) ?? manifestIconUrl;
|
|
1932
|
+
}
|
|
1933
|
+
function isResolvedIconUrl(value) {
|
|
1934
|
+
return /^[a-z][a-z0-9+.-]*:/iu.test(value) || value.startsWith("/");
|
|
1935
|
+
}
|
|
1752
1936
|
function resolvePrimaryAction(input) {
|
|
1753
1937
|
if (input.comingSoon) {
|
|
1754
1938
|
return "none";
|
|
@@ -1869,4 +2053,4 @@ export {
|
|
|
1869
2053
|
resolveWorkspaceAppCatalogMetadata,
|
|
1870
2054
|
createWorkspaceAppRecord
|
|
1871
2055
|
};
|
|
1872
|
-
//# sourceMappingURL=chunk-
|
|
2056
|
+
//# sourceMappingURL=chunk-F76FG674.js.map
|