@powerhousedao/connect 6.2.2-dev.9 → 6.2.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/assets/document-icon-192x192.png +0 -0
- package/assets/document-icon-512x512.png +0 -0
- package/assets/pwa-192x192.png +0 -0
- package/assets/pwa-512x512-maskable.png +0 -0
- package/assets/pwa-512x512.png +0 -0
- package/dist/{AddDriveModal-MMHlkJBJ.js → AddDriveModal-Q-Ffh5XA.js} +5 -5
- package/dist/AddDriveModal-Q-Ffh5XA.js.map +1 -0
- package/dist/{ClearStorageModal-BrqS8I-J.js → ClearStorageModal-Fmh5kOVI.js} +4 -4
- package/dist/{ClearStorageModal-BrqS8I-J.js.map → ClearStorageModal-Fmh5kOVI.js.map} +1 -1
- package/dist/ConfirmDocumentUpgradeModal-FUOhZsk7.js +114 -0
- package/dist/ConfirmDocumentUpgradeModal-FUOhZsk7.js.map +1 -0
- package/dist/{CookiesPolicyModal-CkcUKPLb.js → CookiesPolicyModal-BpyPPyxS.js} +3 -3
- package/dist/{CookiesPolicyModal-CkcUKPLb.js.map → CookiesPolicyModal-BpyPPyxS.js.map} +1 -1
- package/dist/{CreateDocumentModal-CvsTh0HM.js → CreateDocumentModal-C45W8J0V.js} +7 -5
- package/dist/CreateDocumentModal-C45W8J0V.js.map +1 -0
- package/dist/{DebugSettingsModal-CCZi5Gmx.js → DebugSettingsModal-CpGjPPjw.js} +6 -6
- package/dist/{DebugSettingsModal-CCZi5Gmx.js.map → DebugSettingsModal-CpGjPPjw.js.map} +1 -1
- package/dist/{DeleteDriveModal-DSTK8FYk.js → DeleteDriveModal-Dug84t1j.js} +4 -4
- package/dist/{DeleteDriveModal-DSTK8FYk.js.map → DeleteDriveModal-Dug84t1j.js.map} +1 -1
- package/dist/{DeleteItemModal-B2nJmjsP.js → DeleteItemModal-mMzy3V8o.js} +4 -4
- package/dist/{DeleteItemModal-B2nJmjsP.js.map → DeleteItemModal-mMzy3V8o.js.map} +1 -1
- package/dist/{DisclaimerModal-D5FO34u9.js → DisclaimerModal-DvpD5dPM.js} +3 -3
- package/dist/{DisclaimerModal-D5FO34u9.js.map → DisclaimerModal-DvpD5dPM.js.map} +1 -1
- package/dist/DocumentVersionUnsupportedModal-C3Q0V75l.js +32 -0
- package/dist/DocumentVersionUnsupportedModal-C3Q0V75l.js.map +1 -0
- package/dist/{DownloadDocumentWithErrorsModal-tEr3bbtN.js → DownloadDocumentWithErrorsModal-IKl0ljQb.js} +3 -3
- package/dist/{DownloadDocumentWithErrorsModal-tEr3bbtN.js.map → DownloadDocumentWithErrorsModal-IKl0ljQb.js.map} +1 -1
- package/dist/DriveAuthRequiredModal-Cw9eCAQ_.js +36 -0
- package/dist/DriveAuthRequiredModal-Cw9eCAQ_.js.map +1 -0
- package/dist/{DriveSettingsModal-kR3hQnh4.js → DriveSettingsModal-C6-mRQiv.js} +3 -3
- package/dist/{DriveSettingsModal-kR3hQnh4.js.map → DriveSettingsModal-C6-mRQiv.js.map} +1 -1
- package/dist/{InspectorModal-BfwRytsl.js → InspectorModal-CiFokzb8.js} +6 -6
- package/dist/{InspectorModal-BfwRytsl.js.map → InspectorModal-CiFokzb8.js.map} +1 -1
- package/dist/LoginModal-CybbOm3N.js +75 -0
- package/dist/LoginModal-CybbOm3N.js.map +1 -0
- package/dist/{MissingPackageModal-BQcCQbOn.js → MissingPackageModal-C7usWVHQ.js} +18 -6
- package/dist/MissingPackageModal-C7usWVHQ.js.map +1 -0
- package/dist/OpenFileDocumentsModal-TskJgkzl.js +311 -0
- package/dist/OpenFileDocumentsModal-TskJgkzl.js.map +1 -0
- package/dist/SettingsModal-Chptr_NH.js +568 -0
- package/dist/SettingsModal-Chptr_NH.js.map +1 -0
- package/dist/{UpgradeDriveModal-BZGSE9_r.js → UpgradeDriveModal-_8t9slxQ.js} +3 -3
- package/dist/{UpgradeDriveModal-BZGSE9_r.js.map → UpgradeDriveModal-_8t9slxQ.js.map} +1 -1
- package/dist/{app-loader-BqH5S4gP.js → app-loader-CoxjGoau.js} +839 -560
- package/dist/app-loader-CoxjGoau.js.map +1 -0
- package/dist/app-loader-D7RV-yqv.js +4 -0
- package/dist/build-info-D8VekPcJ.js +28 -0
- package/dist/build-info-D8VekPcJ.js.map +1 -0
- package/dist/components-qFeURFYe.js +4 -0
- package/dist/{connect.config-vgUeFoNp.js → connect.config-DaHDEUrw.js} +13 -7
- package/dist/connect.config-DaHDEUrw.js.map +1 -0
- package/dist/{connection-state-DO_2lAEJ.js → connection-state-3w4liC1X.js} +4 -4
- package/dist/{connection-state-DO_2lAEJ.js.map → connection-state-3w4liC1X.js.map} +1 -1
- package/dist/cookie-banner-BH6bIq24.js +70 -0
- package/dist/cookie-banner-BH6bIq24.js.map +1 -0
- package/dist/{reload-connect-toast-D1Iqw9E_.js → i18n-CWO0vYVd.js} +23 -30
- package/dist/i18n-CWO0vYVd.js.map +1 -0
- package/dist/load-D_BC1JxM.js +131 -0
- package/dist/load-D_BC1JxM.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/{pglite-seed-z3B1JA38.js → pglite-seed-BqAUvNFw.js} +4 -4
- package/dist/{pglite-seed-z3B1JA38.js.map → pglite-seed-BqAUvNFw.js.map} +1 -1
- package/dist/preferences-store-_5Cw4_YV.js +104 -0
- package/dist/preferences-store-_5Cw4_YV.js.map +1 -0
- package/dist/pwa-manifest-link-DIgOSo2Q.js +34 -0
- package/dist/pwa-manifest-link-DIgOSo2Q.js.map +1 -0
- package/dist/{reactor-ynguOpe7.js → reactor-DBCWJdBA.js} +240 -67
- package/dist/reactor-DBCWJdBA.js.map +1 -0
- package/dist/reactor.worker.js +11 -6
- package/dist/reactor.worker.js.map +1 -1
- package/dist/{registerServiceWorker-nJIc0yEY.js → registerServiceWorker-BSzbNfvz.js} +6 -4
- package/dist/registerServiceWorker-BSzbNfvz.js.map +1 -0
- package/dist/sentry-QXKgQmr2.js +15 -0
- package/dist/sentry-QXKgQmr2.js.map +1 -0
- package/dist/start-connect.js +1 -1
- package/dist/style.css +243 -7
- package/dist/{toast-4t-VimvD.js → toast-BXIGd4Eb.js} +8 -5
- package/dist/toast-BXIGd4Eb.js.map +1 -0
- package/dist/use-renown-login-Cf3va6u_.js +52 -0
- package/dist/use-renown-login-Cf3va6u_.js.map +1 -0
- package/dist/useRegistryPackages-DMhCvTWq.js +314 -0
- package/dist/useRegistryPackages-DMhCvTWq.js.map +1 -0
- package/package.json +19 -13
- package/public/powerhouse.config.json +3 -0
- package/style.css +1 -0
- package/dist/AddDriveModal-MMHlkJBJ.js.map +0 -1
- package/dist/CreateDocumentModal-CvsTh0HM.js.map +0 -1
- package/dist/DriveAuthRequiredModal-BA2vS3oF.js +0 -40
- package/dist/DriveAuthRequiredModal-BA2vS3oF.js.map +0 -1
- package/dist/MissingPackageModal-BQcCQbOn.js.map +0 -1
- package/dist/SettingsModal-CdoFxyJJ.js +0 -289
- package/dist/SettingsModal-CdoFxyJJ.js.map +0 -1
- package/dist/app-loader-BqH5S4gP.js.map +0 -1
- package/dist/app-loader-J8Z4QAD5.js +0 -4
- package/dist/build-info-AUWI7jOw.js +0 -18
- package/dist/build-info-AUWI7jOw.js.map +0 -1
- package/dist/components-B6-PFL8z.js +0 -5
- package/dist/connect.config-vgUeFoNp.js.map +0 -1
- package/dist/load-BucYuvxH.js +0 -100
- package/dist/load-BucYuvxH.js.map +0 -1
- package/dist/package-BcKQ9BGX.js +0 -127
- package/dist/package-BcKQ9BGX.js.map +0 -1
- package/dist/reactor-ynguOpe7.js.map +0 -1
- package/dist/registerServiceWorker-nJIc0yEY.js.map +0 -1
- package/dist/reload-connect-toast-D1Iqw9E_.js.map +0 -1
- package/dist/toast-4t-VimvD.js.map +0 -1
- package/dist/useRegistryPackages-BaYtekjQ.js +0 -179
- package/dist/useRegistryPackages-BaYtekjQ.js.map +0 -1
|
@@ -1,24 +1,104 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="139fd9bf-816c-554d-8fe6-a26d88299956")}catch(e){}}();
|
|
3
3
|
import { n as getRuntimeConfig } from "./runtime-config-DL3QjcfM.js";
|
|
4
4
|
import { a as resolvePgMajorForRuntime, r as loadPGliteModule } from "./pglite-major-B39aOEiE.js";
|
|
5
|
-
import {
|
|
6
|
-
import { n as buildPHGlobalConfig, o as phGlobalConfig } from "./connect.config-
|
|
7
|
-
import {
|
|
8
|
-
import { n as
|
|
5
|
+
import { i as getVersion, n as getGitSha } from "./build-info-D8VekPcJ.js";
|
|
6
|
+
import { n as buildPHGlobalConfig, o as phGlobalConfig } from "./connect.config-DaHDEUrw.js";
|
|
7
|
+
import { t as refreshPwaManifestLink } from "./pwa-manifest-link-DIgOSo2Q.js";
|
|
8
|
+
import { a as detectReactorPgMajor, h as RELATIONAL_PGLITE_NAME, m as REACTOR_PGLITE_NAME, n as setWorkerConnectionStatus, o as detectRelationalPgMajor, p as REACTOR_INSTANCE_NAMESPACE } from "./connection-state-3w4liC1X.js";
|
|
9
|
+
import { r as toast } from "./toast-BXIGd4Eb.js";
|
|
10
|
+
import { PWA_IDB_KEY, PWA_IDB_NAME, PWA_IDB_STORE, PWA_IDB_VERSION, mergePwaConfig, withInferredCategory } from "@powerhousedao/shared/connect";
|
|
9
11
|
import { createRelationalDb } from "@powerhousedao/shared/processors";
|
|
10
|
-
import { DocumentModelRegistry, DocumentModelResolver, ReactorEventTypes } from "@powerhousedao/reactor";
|
|
12
|
+
import { DocumentModelRegistry, DocumentModelResolver, ReactorEventTypes, createReactorHostModuleBase } from "@powerhousedao/reactor";
|
|
11
13
|
import { MessageRouter, RPC_PROTOCOL_VERSION, SyncManagerProxy, connectReactorClient, createInspectorProxy, createPortTransport, createReactorEventBusProxy, createRelationalPgliteProxy, createWorkerAdminClient, postReactorIdentity } from "@powerhousedao/reactor-browser/rpc";
|
|
12
14
|
import { Kysely } from "kysely";
|
|
13
15
|
import { PGliteDialect } from "kysely-pglite-dialect";
|
|
14
|
-
import { BrowserLocalStorage, ChannelScheme as ChannelScheme$1, DRIVE_DOCUMENT_TYPES, DocumentCache, DocumentChangeType, ReactorBuilder as ReactorBuilder$1, ReactorClientBuilder as ReactorClientBuilder$1, RegistryClient, addPHEventHandlers, addRemoteDrive, createAnalyticsStore, extractDriveSlugFromPath, extractNodeSlugFromPath, getDrives, isDriveAuthError, login, refreshReactorDataClient, setAttachmentService, setDefaultPHGlobalConfig, setDocumentCache, setDriveMetadata, setDrives, setFeatures, setPGliteDB, setPHToast, setPackageDiscoveryService, setReactorClient, setReactorClientModule, setRenown, setSelectedDrive, setSelectedNode, setVetraPackageManager, waitForDocumentReady } from "@powerhousedao/reactor-browser";
|
|
16
|
+
import { BrowserLocalStorage, ChannelScheme as ChannelScheme$1, DRIVE_DOCUMENT_TYPES, DocumentCache, DocumentChangeType, ReactorBuilder as ReactorBuilder$1, ReactorClientBuilder as ReactorClientBuilder$1, RegistryClient, addDrive, addPHEventHandlers, addRemoteDrive, createAnalyticsStore, extractDriveSlugFromPath, extractNodeSlugFromPath, getDrives, isDriveAuthError, login, refreshReactorDataClient, setAttachmentService, setDefaultPHGlobalConfig, setDocumentCache, setDriveMetadata, setDrives, setFeatures, setPGliteDB, setPHToast, setPackageDiscoveryService, setReactorClient, setReactorClientModule, setRenown, setSelectedDrive, setSelectedNode, setVetraPackageManager, waitForDocumentReady } from "@powerhousedao/reactor-browser";
|
|
15
17
|
import { ConsoleLogger, logger, setLogLevel as setLogLevel$1 } from "document-model";
|
|
16
18
|
import { BrowserKeyStorage, RenownBuilder, RenownCryptoBuilder, createSignatureVerifier } from "@renown/sdk";
|
|
17
|
-
import {
|
|
19
|
+
import { PwaConfigSchema } from "@powerhousedao/shared/document-model";
|
|
20
|
+
import { createAttachmentClient, createRemoteAttachmentService, createXhrUploadTransport } from "@powerhousedao/reactor-attachments/client";
|
|
18
21
|
import { OpenFeature } from "@openfeature/web-sdk";
|
|
19
22
|
import * as common from "@powerhousedao/powerhouse-vetra-packages";
|
|
20
23
|
import commonPkg from "@powerhousedao/powerhouse-vetra-packages/package.json" with { type: "json" };
|
|
24
|
+
import { toCdnUrl } from "@powerhousedao/shared/registry/urls";
|
|
21
25
|
import vetraPkg from "@powerhousedao/vetra/package.json" with { type: "json" };
|
|
26
|
+
//#region src/utils/pwa-idb.ts
|
|
27
|
+
function openPwaIdb() {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const req = indexedDB.open(PWA_IDB_NAME, PWA_IDB_VERSION);
|
|
30
|
+
req.onupgradeneeded = () => {
|
|
31
|
+
if (!req.result.objectStoreNames.contains(PWA_IDB_STORE)) req.result.createObjectStore(PWA_IDB_STORE);
|
|
32
|
+
};
|
|
33
|
+
req.onerror = () => reject(req.error ?? /* @__PURE__ */ new Error("ph-pwa open failed"));
|
|
34
|
+
req.onblocked = () => reject(/* @__PURE__ */ new Error("ph-pwa open blocked"));
|
|
35
|
+
req.onsuccess = () => resolve(req.result);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** Write (replace) the single merged fragment record. Best-effort: a failure to
|
|
39
|
+
* mirror the manifest must never break package installation, so callers ignore
|
|
40
|
+
* rejections. No-op when IndexedDB is unavailable (SSR/tests). */
|
|
41
|
+
async function writeMergedPwaFragment(fragment) {
|
|
42
|
+
if (typeof indexedDB === "undefined") return;
|
|
43
|
+
const db = await openPwaIdb();
|
|
44
|
+
try {
|
|
45
|
+
await new Promise((resolve, reject) => {
|
|
46
|
+
const tx = db.transaction(PWA_IDB_STORE, "readwrite");
|
|
47
|
+
tx.oncomplete = () => resolve();
|
|
48
|
+
tx.onerror = () => reject(tx.error ?? /* @__PURE__ */ new Error("PWA fragment write failed"));
|
|
49
|
+
tx.objectStore(PWA_IDB_STORE).put({
|
|
50
|
+
version: 1,
|
|
51
|
+
fragment,
|
|
52
|
+
updatedAt: Date.now()
|
|
53
|
+
}, PWA_IDB_KEY);
|
|
54
|
+
});
|
|
55
|
+
} finally {
|
|
56
|
+
db.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Resolve `src` against the package `baseUrl`, absolute srcs passing through.
|
|
60
|
+
* `baseUrl` may itself be relative (e.g. a same-origin-proxied registry, or the
|
|
61
|
+
* dev `/node_modules/…` path), so it is first made absolute against the app
|
|
62
|
+
* origin — `new URL(src, relativeBase)` would otherwise throw and silently
|
|
63
|
+
* leave the src unresolved. A malformed src is left untouched. */
|
|
64
|
+
function toAbsoluteAssetUrl(src, baseUrl) {
|
|
65
|
+
try {
|
|
66
|
+
const origin = typeof location !== "undefined" ? location.href : "http://localhost/";
|
|
67
|
+
return new URL(src, new URL(baseUrl, origin)).toString();
|
|
68
|
+
} catch {
|
|
69
|
+
return src;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function resolveIconSrc(icon, baseUrl) {
|
|
73
|
+
return {
|
|
74
|
+
...icon,
|
|
75
|
+
src: toAbsoluteAssetUrl(icon.src, baseUrl)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Rewrite a package fragment's relative asset srcs (manifest icons and
|
|
80
|
+
* file-handler icons) to absolute URLs against the package's base — a runtime
|
|
81
|
+
* package's assets live on the registry CDN, not the app origin, so the served
|
|
82
|
+
* manifest must point there. `baseUrl` null (a local/bundled package whose
|
|
83
|
+
* assets are app-origin-relative) leaves srcs untouched.
|
|
84
|
+
*/
|
|
85
|
+
function resolveFragmentAssetUrls(config, baseUrl) {
|
|
86
|
+
if (!baseUrl || !config.manifest) return config;
|
|
87
|
+
const m = config.manifest;
|
|
88
|
+
const resolveIcons = (icons) => icons?.map((icon) => resolveIconSrc(icon, baseUrl));
|
|
89
|
+
return {
|
|
90
|
+
...config,
|
|
91
|
+
manifest: {
|
|
92
|
+
...m,
|
|
93
|
+
icons: resolveIcons(m.icons),
|
|
94
|
+
file_handlers: m.file_handlers?.map((handler) => ({
|
|
95
|
+
...handler,
|
|
96
|
+
icons: resolveIcons(handler.icons)
|
|
97
|
+
}))
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
22
102
|
//#region src/pglite.db.ts
|
|
23
103
|
async function createMainThreadPGlite(major, dbName) {
|
|
24
104
|
const { PGlite } = await loadPGliteModule(major);
|
|
@@ -73,7 +153,7 @@ async function getDb() {
|
|
|
73
153
|
* Creates a Reactor that plugs into legacy storage but syncs through the new
|
|
74
154
|
* Reactor GQL API.
|
|
75
155
|
*/
|
|
76
|
-
async function createBrowserReactor(documentModelModules, upgradeManifests, renown, documentModelLoader) {
|
|
156
|
+
async function createBrowserReactor(documentModelModules, upgradeManifests, renown, featureFlags, documentModelLoader) {
|
|
77
157
|
const signerConfig = {
|
|
78
158
|
signer: renown.signer,
|
|
79
159
|
verifier: createSignatureVerifier()
|
|
@@ -84,7 +164,7 @@ async function createBrowserReactor(documentModelModules, upgradeManifests, reno
|
|
|
84
164
|
};
|
|
85
165
|
const pg = await getReactorPGlite();
|
|
86
166
|
const logger = new ConsoleLogger(["reactor-client"]);
|
|
87
|
-
const builder = new ReactorClientBuilder$1().withLogger(logger).withSigner(signerConfig).withReactorBuilder(new ReactorBuilder$1().withDocumentModelSources(documentModelModules).withUpgradeManifests(upgradeManifests).withChannelScheme(ChannelScheme$1.CONNECT).withJwtHandler(jwtHandler).withKysely(new Kysely({ dialect: new PGliteDialect(pg) })));
|
|
167
|
+
const builder = new ReactorClientBuilder$1().withLogger(logger).withSigner(signerConfig).withReactorBuilder(new ReactorBuilder$1().withDocumentModelSources(documentModelModules).withUpgradeManifests(upgradeManifests).withChannelScheme(ChannelScheme$1.CONNECT).withExecutorConfig({ featureFlags }).withJwtHandler(jwtHandler).withKysely(new Kysely({ dialect: new PGliteDialect(pg) })));
|
|
88
168
|
if (documentModelLoader) builder.withDocumentModelLoader(documentModelLoader);
|
|
89
169
|
const module = await builder.buildModule();
|
|
90
170
|
return {
|
|
@@ -103,40 +183,74 @@ function getDefaultDrives(runtimeConfig) {
|
|
|
103
183
|
* Add default drives for the new reactor via sync manager.
|
|
104
184
|
*
|
|
105
185
|
* Drives register concurrently so a slow or unreachable drive can't delay the
|
|
106
|
-
* others — in particular the one the URL slug resolves to.
|
|
107
|
-
* backoff to handle the common race where Connect's dev
|
|
108
|
-
* the switchboard has finished binding its port.
|
|
186
|
+
* others — in particular the one the URL slug resolves to. Remote drives
|
|
187
|
+
* retry with linear backoff to handle the common race where Connect's dev
|
|
188
|
+
* server is ready before the switchboard has finished binding its port.
|
|
109
189
|
*
|
|
110
|
-
*
|
|
190
|
+
* Each entry is either a remote drive (a URL registered with the sync
|
|
191
|
+
* manager, waited on for initial backfill) or a local drive (created once in
|
|
192
|
+
* this browser's local reactor; its fixed id makes later boots skip it).
|
|
193
|
+
*
|
|
194
|
+
* @param drives - Array of default-drive entries
|
|
111
195
|
*/
|
|
112
196
|
async function addDefaultDrivesForNewReactor(drives) {
|
|
197
|
+
await Promise.all(drives.map((drive) => "url" in drive ? addRemoteDefaultDrive(drive) : addLocalDefaultDrive(drive)));
|
|
198
|
+
}
|
|
199
|
+
async function addRemoteDefaultDrive(drive) {
|
|
113
200
|
const MAX_ATTEMPTS = 3;
|
|
114
201
|
const BACKOFF_MS = 2e3;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
127
|
-
}
|
|
202
|
+
let driveId;
|
|
203
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) try {
|
|
204
|
+
driveId = await addRemoteDrive(drive.url);
|
|
205
|
+
break;
|
|
206
|
+
} catch (error) {
|
|
207
|
+
if (isDriveAuthError(error)) break;
|
|
208
|
+
if (attempt === MAX_ATTEMPTS) console.error(`Failed to add default drive ${drive.url} after ${MAX_ATTEMPTS} attempts:`, error);
|
|
209
|
+
else {
|
|
210
|
+
const delay = BACKOFF_MS * attempt;
|
|
211
|
+
console.warn(`Default drive ${drive.url} not reachable (attempt ${attempt}/${MAX_ATTEMPTS}), retrying in ${delay}ms...`);
|
|
212
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
128
213
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
214
|
+
}
|
|
215
|
+
if (driveId && (drive.name || drive.icon)) try {
|
|
216
|
+
const reactorClient = window.ph?.reactorClientModule?.client;
|
|
217
|
+
if (reactorClient) await waitForDocumentReady(reactorClient, driveId, { timeoutMs: 15e3 });
|
|
218
|
+
await setDriveMetadata(driveId, {
|
|
219
|
+
name: drive.name,
|
|
220
|
+
icon: drive.icon
|
|
221
|
+
});
|
|
222
|
+
} catch (error) {
|
|
223
|
+
console.warn(`Default drive ${drive.url} was added but metadata update failed:`, error);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Create a configured local default drive in this browser's local reactor.
|
|
228
|
+
* The drive is only created when the configured id is not already taken, so
|
|
229
|
+
* repeated boots are idempotent and a drive the user deleted stays deleted.
|
|
230
|
+
* Name and icon are written straight into the created document's global state
|
|
231
|
+
* (no setDriveMetadata round-trip), and `app` maps to the drive's preferred
|
|
232
|
+
* editor.
|
|
233
|
+
*/
|
|
234
|
+
async function addLocalDefaultDrive(drive) {
|
|
235
|
+
if (!drive.id) {
|
|
236
|
+
console.error("Ignoring local default drive with no id:", JSON.stringify(drive));
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
const reactorClient = window.ph?.reactorClientModule?.client;
|
|
241
|
+
if (reactorClient) {
|
|
242
|
+
if (await reactorClient.isDocumentIdTaken(drive.id)) return;
|
|
138
243
|
}
|
|
139
|
-
|
|
244
|
+
await addDrive({
|
|
245
|
+
id: drive.id,
|
|
246
|
+
global: {
|
|
247
|
+
name: drive.name ?? "",
|
|
248
|
+
icon: drive.icon ?? null
|
|
249
|
+
}
|
|
250
|
+
}, drive.app);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.error(`Failed to create local default drive ${drive.id}:`, error);
|
|
253
|
+
}
|
|
140
254
|
}
|
|
141
255
|
//#endregion
|
|
142
256
|
//#region src/feature-flags.ts
|
|
@@ -601,14 +715,14 @@ var BrowserPackageManager = class {
|
|
|
601
715
|
#cdnUrl;
|
|
602
716
|
#localPackageVersion;
|
|
603
717
|
#localPackageNames = new Set([LOCAL_PACKAGE_NAME]);
|
|
718
|
+
#pwaSyncTimer;
|
|
719
|
+
/** Serialized last-mirrored PWA fragment; lets a sync skip the IndexedDB
|
|
720
|
+
* write + manifest re-attach when nothing PWA-relevant changed. */
|
|
721
|
+
#lastSyncedFragmentJson;
|
|
604
722
|
constructor(namespace, registryUrl) {
|
|
605
723
|
this.#storage = new BrowserLocalStorage(namespace + ":PH_PACKAGES");
|
|
606
724
|
this.registryUrl = registryUrl;
|
|
607
|
-
this.#cdnUrl = registryUrl !== null ?
|
|
608
|
-
}
|
|
609
|
-
#toCdnUrl(baseUrl) {
|
|
610
|
-
if (baseUrl.includes("/-/cdn")) return baseUrl;
|
|
611
|
-
return `${baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl}/-/cdn`;
|
|
725
|
+
this.#cdnUrl = registryUrl !== null ? toCdnUrl(registryUrl) : null;
|
|
612
726
|
}
|
|
613
727
|
async init(localPackage, localPackageVersion, studioMode) {
|
|
614
728
|
this.addLocalPackage(common.manifest.name, common, commonPkg.version);
|
|
@@ -829,6 +943,53 @@ var BrowserPackageManager = class {
|
|
|
829
943
|
this.#subscribers.forEach((handler) => {
|
|
830
944
|
handler({ packages });
|
|
831
945
|
});
|
|
946
|
+
this.#schedulePwaSync();
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Debounced mirror of every loaded package's PWA fragment into IndexedDB, so
|
|
950
|
+
* the service worker can serve a web-app manifest that reflects packages
|
|
951
|
+
* installed AT RUNTIME (a SW can't read localStorage, where the package list
|
|
952
|
+
* lives). Debounced because `init()` rehydrates many packages in a burst;
|
|
953
|
+
* coalescing collapses that into a single write.
|
|
954
|
+
*/
|
|
955
|
+
#schedulePwaSync() {
|
|
956
|
+
if (typeof indexedDB === "undefined") return;
|
|
957
|
+
clearTimeout(this.#pwaSyncTimer);
|
|
958
|
+
this.#pwaSyncTimer = setTimeout(() => {
|
|
959
|
+
this.#syncPwaFragments();
|
|
960
|
+
}, 50);
|
|
961
|
+
}
|
|
962
|
+
async #syncPwaFragments() {
|
|
963
|
+
const contributions = [];
|
|
964
|
+
for (const [name, loadedPackage] of this.#packages) {
|
|
965
|
+
const manifest = loadedPackage.manifest;
|
|
966
|
+
let config = {};
|
|
967
|
+
if (manifest.pwa) {
|
|
968
|
+
const parsed = PwaConfigSchema.safeParse(manifest.pwa);
|
|
969
|
+
if (parsed.success) {
|
|
970
|
+
const importUrl = this.#storage.get(name)?.importUrl ?? null;
|
|
971
|
+
const baseUrl = importUrl ? importUrl.replace(/browser\/index\.js$/, "") : null;
|
|
972
|
+
config = resolveFragmentAssetUrls(parsed.data, baseUrl);
|
|
973
|
+
} else console.warn(`[Connect][PWA] "${name}" ships an invalid pwa fragment; skipped.`, parsed.error);
|
|
974
|
+
}
|
|
975
|
+
config = withInferredCategory(config, manifest.category);
|
|
976
|
+
if (Object.keys(config).length === 0) continue;
|
|
977
|
+
contributions.push({
|
|
978
|
+
source: name,
|
|
979
|
+
config
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
const merged = mergePwaConfig(contributions);
|
|
983
|
+
const mergedJson = JSON.stringify(merged);
|
|
984
|
+
if (mergedJson === this.#lastSyncedFragmentJson) return;
|
|
985
|
+
try {
|
|
986
|
+
await writeMergedPwaFragment(merged);
|
|
987
|
+
} catch (error) {
|
|
988
|
+
console.debug("[Connect][PWA] fragment mirror to IndexedDB failed:", error);
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
this.#lastSyncedFragmentJson = mergedJson;
|
|
992
|
+
refreshPwaManifestLink();
|
|
832
993
|
}
|
|
833
994
|
};
|
|
834
995
|
//#endregion
|
|
@@ -855,6 +1016,10 @@ function bumpWorkerGen(namespace, gen) {
|
|
|
855
1016
|
const PING_INTERVAL_MS = 2e3;
|
|
856
1017
|
const PING_DEADLINE_MS = 3e3;
|
|
857
1018
|
const MAX_MISSED_PINGS = 2;
|
|
1019
|
+
/** Sorted so the same set always produces the same fingerprint. */
|
|
1020
|
+
function enabledFlagList(flags) {
|
|
1021
|
+
return Object.entries(flags).filter(([, enabled]) => enabled).map(([name]) => name).sort().join(",");
|
|
1022
|
+
}
|
|
858
1023
|
function toReactorIdentity(user) {
|
|
859
1024
|
if (!user) return null;
|
|
860
1025
|
return {
|
|
@@ -890,14 +1055,17 @@ function createWorkerReactorClientModule(args) {
|
|
|
890
1055
|
models: args.documentModelModules.map((m) => ({
|
|
891
1056
|
id: m.documentModel.global.id,
|
|
892
1057
|
version: m.version ?? 1
|
|
893
|
-
}))
|
|
1058
|
+
})),
|
|
1059
|
+
featureFlags: enabledFlagList(args.featureFlags)
|
|
894
1060
|
},
|
|
895
1061
|
construct: {
|
|
896
1062
|
namespace: args.namespace,
|
|
897
1063
|
relationalNamespace: args.relationalNamespace,
|
|
898
1064
|
cdnUrl: args.cdnUrl,
|
|
899
1065
|
packageSpecs: args.packageSpecs,
|
|
900
|
-
studioMode: args.studioMode
|
|
1066
|
+
studioMode: args.studioMode,
|
|
1067
|
+
renownChainId: args.renownChainId,
|
|
1068
|
+
featureFlags: args.featureFlags
|
|
901
1069
|
},
|
|
902
1070
|
packages: args.packageSpecs
|
|
903
1071
|
}, args.onReload, documentModelRegistry);
|
|
@@ -1004,29 +1172,23 @@ var NullAttachmentService = class {
|
|
|
1004
1172
|
get() {
|
|
1005
1173
|
return Promise.reject(/* @__PURE__ */ new Error("NullAttachmentService: no attachment service configured"));
|
|
1006
1174
|
}
|
|
1175
|
+
getDownloadTarget() {
|
|
1176
|
+
return Promise.reject(/* @__PURE__ */ new Error("NullAttachmentService: no attachment service configured"));
|
|
1177
|
+
}
|
|
1007
1178
|
};
|
|
1008
1179
|
async function createProcessorHostModule(reactorClient, readModels, attachmentService) {
|
|
1009
1180
|
try {
|
|
1010
1181
|
const { pgLite, relationalDb } = await getDb();
|
|
1011
1182
|
const { store: analyticsStore } = await createAnalyticsStore({ pgLite });
|
|
1012
1183
|
return {
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
id: jobInfo.id,
|
|
1022
|
-
status: jobInfo.status
|
|
1023
|
-
};
|
|
1024
|
-
} },
|
|
1025
|
-
getReadModel(name) {
|
|
1026
|
-
const model = readModels.find((m) => m.name === name);
|
|
1027
|
-
if (!model) throw new Error(`Read model "${name}" not found`);
|
|
1028
|
-
return model;
|
|
1029
|
-
}
|
|
1184
|
+
...createReactorHostModuleBase({
|
|
1185
|
+
client: reactorClient,
|
|
1186
|
+
readModels,
|
|
1187
|
+
relationalDb,
|
|
1188
|
+
analyticsStore,
|
|
1189
|
+
processorApp: "connect"
|
|
1190
|
+
}),
|
|
1191
|
+
attachments: createAttachmentClient(attachmentService ?? new NullAttachmentService())
|
|
1030
1192
|
};
|
|
1031
1193
|
} catch (error) {
|
|
1032
1194
|
console.error(`Failed to initialize processor host module:`);
|
|
@@ -1120,11 +1282,16 @@ async function createReactor(localPackage) {
|
|
|
1120
1282
|
setPHToast(toast);
|
|
1121
1283
|
const features = await initFeatureFlags();
|
|
1122
1284
|
logger.info("Features: @features", JSON.stringify(Object.fromEntries(features), null, 2));
|
|
1285
|
+
const renownChainId = getRuntimeConfig().connect.renown?.chainId;
|
|
1123
1286
|
const keyPairStorage = await BrowserKeyStorage.create();
|
|
1124
|
-
const
|
|
1287
|
+
const cryptoBuilder = new RenownCryptoBuilder().withKeyPairStorage(keyPairStorage);
|
|
1288
|
+
if (renownChainId !== void 0) cryptoBuilder.withChainId(renownChainId);
|
|
1289
|
+
const renownCrypto = await cryptoBuilder.build();
|
|
1125
1290
|
const renown = await new RenownBuilder("connect", {
|
|
1126
1291
|
basename: getRuntimeConfig().connect.renown?.namespace ?? phGlobalConfig.routerBasename,
|
|
1127
|
-
baseUrl: phGlobalConfig.renownUrl
|
|
1292
|
+
baseUrl: phGlobalConfig.renownUrl,
|
|
1293
|
+
switchboardUrl: phGlobalConfig.switchboardUrl,
|
|
1294
|
+
chainId: renownChainId
|
|
1128
1295
|
}).withCrypto(renownCrypto).build();
|
|
1129
1296
|
const runtimeConfig = getRuntimeConfig();
|
|
1130
1297
|
const packageManager = new BrowserPackageManager(phGlobalConfig.routerBasename ?? "", runtimeConfig.packageRegistryUrl ?? null);
|
|
@@ -1146,6 +1313,9 @@ async function createReactor(localPackage) {
|
|
|
1146
1313
|
storageKey: phGlobalConfig.routerBasename ?? ""
|
|
1147
1314
|
}) : new NoRegistryDiscoveryService(packageManager);
|
|
1148
1315
|
setPackageDiscoveryService(discoveryService);
|
|
1316
|
+
const reactorFeatureFlags = runtimeConfig.connect?.reactor?.featureFlags ?? {};
|
|
1317
|
+
const enabledReactorFlags = Object.entries(reactorFeatureFlags).filter(([, enabled]) => enabled).map(([name]) => name);
|
|
1318
|
+
if (enabledReactorFlags.length > 0) logger.info(`Reactor feature flags: ${enabledReactorFlags.join(", ")}`);
|
|
1149
1319
|
let reactorClientModule;
|
|
1150
1320
|
if (isReactorWorkerEnabled()) {
|
|
1151
1321
|
const packageSpecs = packageManager.getRegistryPackages().map((p) => p.version ? `${p.name}@${p.version}` : p.name);
|
|
@@ -1156,6 +1326,8 @@ async function createReactor(localPackage) {
|
|
|
1156
1326
|
cdnUrl: packageManager.cdnUrl ?? "",
|
|
1157
1327
|
packageSpecs,
|
|
1158
1328
|
studioMode: phGlobalConfig.studioMode,
|
|
1329
|
+
renownChainId,
|
|
1330
|
+
featureFlags: reactorFeatureFlags,
|
|
1159
1331
|
documentModelModules,
|
|
1160
1332
|
upgradeManifests,
|
|
1161
1333
|
documentModelLoader: { async load(documentType) {
|
|
@@ -1183,7 +1355,7 @@ async function createReactor(localPackage) {
|
|
|
1183
1355
|
logger.error("Reactor worker failed to start: @error", error);
|
|
1184
1356
|
throw error;
|
|
1185
1357
|
}
|
|
1186
|
-
} else reactorClientModule = await createBrowserReactor(documentModelModules, upgradeManifests, renown, discoveryService);
|
|
1358
|
+
} else reactorClientModule = await createBrowserReactor(documentModelModules, upgradeManifests, renown, reactorFeatureFlags, discoveryService);
|
|
1187
1359
|
const drives = await getDrives(reactorClientModule.client);
|
|
1188
1360
|
await login(getDidFromUrl(), renown);
|
|
1189
1361
|
const documentCache = new DocumentCache(reactorClientModule.client);
|
|
@@ -1206,7 +1378,8 @@ async function createReactor(localPackage) {
|
|
|
1206
1378
|
};
|
|
1207
1379
|
setAttachmentService(createRemoteAttachmentService({
|
|
1208
1380
|
remoteUrl: switchboardOrigin,
|
|
1209
|
-
jwtHandler: attachmentJwtHandler
|
|
1381
|
+
jwtHandler: attachmentJwtHandler,
|
|
1382
|
+
uploadTransport: createXhrUploadTransport()
|
|
1210
1383
|
}));
|
|
1211
1384
|
}
|
|
1212
1385
|
}
|
|
@@ -1278,5 +1451,5 @@ function getDriveUrl() {
|
|
|
1278
1451
|
//#endregion
|
|
1279
1452
|
export { createReactor as n, clearReactorStorage as t };
|
|
1280
1453
|
|
|
1281
|
-
//# sourceMappingURL=reactor-
|
|
1282
|
-
//# debugId=
|
|
1454
|
+
//# sourceMappingURL=reactor-DBCWJdBA.js.map
|
|
1455
|
+
//# debugId=139fd9bf-816c-554d-8fe6-a26d88299956
|