@powerhousedao/connect 6.0.0-dev.188 → 6.0.0-dev.189
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/{AddDriveModal-CBK9gEWg.js → AddDriveModal-DSl4aUG4.js} +1 -1
- package/dist/{AddDriveModal-CBK9gEWg.js.map → AddDriveModal-DSl4aUG4.js.map} +1 -1
- package/dist/{ClearStorageModal-BPNxgYAt.js → ClearStorageModal-D5GnV_KP.js} +2 -2
- package/dist/{ClearStorageModal-BPNxgYAt.js.map → ClearStorageModal-D5GnV_KP.js.map} +1 -1
- package/dist/{CookiesPolicyModal-Gae1QuhA.js → CookiesPolicyModal-CJ8eVy5s.js} +1 -1
- package/dist/{CookiesPolicyModal-Gae1QuhA.js.map → CookiesPolicyModal-CJ8eVy5s.js.map} +1 -1
- package/dist/{CreateDocumentModal-5i6rmv3C.js → CreateDocumentModal-Dn6aS43b.js} +1 -1
- package/dist/{CreateDocumentModal-5i6rmv3C.js.map → CreateDocumentModal-Dn6aS43b.js.map} +1 -1
- package/dist/{DebugSettingsModal-BgGapwSF.js → DebugSettingsModal-BKzA1RHD.js} +2 -2
- package/dist/{DebugSettingsModal-BgGapwSF.js.map → DebugSettingsModal-BKzA1RHD.js.map} +1 -1
- package/dist/{DeleteDriveModal-BbAx_yXt.js → DeleteDriveModal-CGYHSOaD.js} +1 -1
- package/dist/{DeleteDriveModal-BbAx_yXt.js.map → DeleteDriveModal-CGYHSOaD.js.map} +1 -1
- package/dist/{DeleteItemModal-CkWegLlh.js → DeleteItemModal-B5s1N_pu.js} +1 -1
- package/dist/{DeleteItemModal-CkWegLlh.js.map → DeleteItemModal-B5s1N_pu.js.map} +1 -1
- package/dist/{DisclaimerModal-CCnvwoB5.js → DisclaimerModal-H-yj2hgE.js} +1 -1
- package/dist/{DisclaimerModal-CCnvwoB5.js.map → DisclaimerModal-H-yj2hgE.js.map} +1 -1
- package/dist/{DriveSettingsModal-DxMjOsLg.js → DriveSettingsModal-BNo0P8gj.js} +1 -1
- package/dist/{DriveSettingsModal-DxMjOsLg.js.map → DriveSettingsModal-BNo0P8gj.js.map} +1 -1
- package/dist/{ExportDocumentWithErrorsModal-hgliF8Gy.js → ExportDocumentWithErrorsModal-0qO7mQpW.js} +1 -1
- package/dist/{ExportDocumentWithErrorsModal-hgliF8Gy.js.map → ExportDocumentWithErrorsModal-0qO7mQpW.js.map} +1 -1
- package/dist/{InspectorModal-C4rE0Y5E.js → InspectorModal-DmKsFb2H.js} +80 -16
- package/dist/InspectorModal-DmKsFb2H.js.map +1 -0
- package/dist/{MissingPackageModal-7VpP86dg.js → MissingPackageModal-Ct_ZNExZ.js} +1 -1
- package/dist/{MissingPackageModal-7VpP86dg.js.map → MissingPackageModal-Ct_ZNExZ.js.map} +1 -1
- package/dist/{SettingsModal-Dz__q4t4.js → SettingsModal-VOiLShDP.js} +2 -2
- package/dist/{SettingsModal-Dz__q4t4.js.map → SettingsModal-VOiLShDP.js.map} +1 -1
- package/dist/{UpgradeDriveModal-DldcNCaT.js → UpgradeDriveModal-DnDjNlz6.js} +1 -1
- package/dist/{UpgradeDriveModal-DldcNCaT.js.map → UpgradeDriveModal-DnDjNlz6.js.map} +1 -1
- package/dist/{migration-status-B9oFtMAT.js → i18n-Ch408v5-.js} +2 -19
- package/dist/i18n-Ch408v5-.js.map +1 -0
- package/dist/load-DqQfTsU4.js +109 -0
- package/dist/load-DqQfTsU4.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/{package-DOkPWVM4.js → package-Dhk9woN2.js} +2 -2
- package/dist/package-Dhk9woN2.js.map +1 -0
- package/dist/pglite-runtime-BS9wpAs9.js +132 -0
- package/dist/pglite-runtime-BS9wpAs9.js.map +1 -0
- package/dist/pglite-seed-VlhY0n-A.js +46 -0
- package/dist/pglite-seed-VlhY0n-A.js.map +1 -0
- package/dist/pglite.worker.legacy.d.ts +1 -0
- package/dist/pglite.worker.legacy.js +15 -0
- package/dist/pglite.worker.legacy.js.map +1 -0
- package/dist/{reactor-f19C1Zwk.js → reactor-CPD8Z_UP.js} +22 -8
- package/dist/reactor-CPD8Z_UP.js.map +1 -0
- package/dist/{registerServiceWorker-BzzFXdLM.js → registerServiceWorker-1maoTQNT.js} +1 -1
- package/dist/{registerServiceWorker-BzzFXdLM.js.map → registerServiceWorker-1maoTQNT.js.map} +1 -1
- package/dist/{sidebar-D5BFqQP5.js → sidebar-Bfqk_9jd.js} +362 -26
- package/dist/sidebar-Bfqk_9jd.js.map +1 -0
- package/dist/start-connect.js +1 -1
- package/dist/style.css +53 -0
- package/package.json +9 -9
- package/dist/InspectorModal-C4rE0Y5E.js.map +0 -1
- package/dist/load-D33GBKWy.js +0 -354
- package/dist/load-D33GBKWy.js.map +0 -1
- package/dist/migration-status-B9oFtMAT.js.map +0 -1
- package/dist/package-DOkPWVM4.js.map +0 -1
- package/dist/reactor-f19C1Zwk.js.map +0 -1
- package/dist/sidebar-D5BFqQP5.js.map +0 -1
package/dist/load-D33GBKWy.js
DELETED
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
import { t as connectConfig } from "./connect.config-Cuh0hj_Q.js";
|
|
2
|
-
import { t as toast } from "./toast-iD-70hL8.js";
|
|
3
|
-
import { t as package_default } from "./package-DOkPWVM4.js";
|
|
4
|
-
import { n as setMigrationStatus } from "./migration-status-B9oFtMAT.js";
|
|
5
|
-
import { n as createReactor } from "./reactor-f19C1Zwk.js";
|
|
6
|
-
import { useUser } from "@powerhousedao/reactor-browser";
|
|
7
|
-
import { logger } from "document-model";
|
|
8
|
-
import { createElement, useEffect } from "react";
|
|
9
|
-
import { setUser } from "@sentry/react";
|
|
10
|
-
import { useTranslation } from "react-i18next";
|
|
11
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
-
import { PGlite } from "@electric-sql/pglite";
|
|
13
|
-
import { DEFAULT_RELATIONAL_PROCESSOR_DB_NAME } from "@powerhousedao/shared/processors";
|
|
14
|
-
//#region src/components/reload-connect-toast.tsx
|
|
15
|
-
const ReloadConnectToast = () => {
|
|
16
|
-
const { t } = useTranslation();
|
|
17
|
-
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
|
|
18
|
-
className: "font-medium",
|
|
19
|
-
children: t("notifications.reloadApp")
|
|
20
|
-
}), /* @__PURE__ */ jsxs("button", {
|
|
21
|
-
onClick: () => location.reload(),
|
|
22
|
-
className: "underline decoration-solid underline-offset-2",
|
|
23
|
-
children: [t("common.reloadConnect"), " 🔄"]
|
|
24
|
-
})] });
|
|
25
|
-
};
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/hooks/useCheckLatestVersion.ts
|
|
28
|
-
const useCheckLatestVersion = () => {
|
|
29
|
-
async function checkLatestVersion() {
|
|
30
|
-
const result = await isLatestVersion();
|
|
31
|
-
if (result === null) return;
|
|
32
|
-
if (result.isLatest || result.currentVersion.includes("-")) return true;
|
|
33
|
-
if (import.meta.env.MODE === "development" || connectConfig.studioMode || !connectConfig.warnOutdatedApp) logger.warn("Connect is outdated: \nCurrent: @currentVersion\nLatest: @latestVersion", result.currentVersion, result.latestVersion);
|
|
34
|
-
else toast(createElement(ReloadConnectToast), {
|
|
35
|
-
type: "connect-warning",
|
|
36
|
-
toastId: "outdated-app",
|
|
37
|
-
autoClose: false
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
checkLatestVersion().catch(console.error);
|
|
42
|
-
}, []);
|
|
43
|
-
};
|
|
44
|
-
window.navigator.appVersion.includes("Mac");
|
|
45
|
-
const urlBranchMap = {
|
|
46
|
-
"staging/makerdao": "deployments/staging/makerdao",
|
|
47
|
-
"staging/arbitrum": "arb-ltip",
|
|
48
|
-
"staging/powerhouse": "staging",
|
|
49
|
-
makerdao: "deployments/makerdao",
|
|
50
|
-
arbitrum: "deployments/arbitrum",
|
|
51
|
-
arbgrants: "deployments/arbitrum",
|
|
52
|
-
localhost: "develop"
|
|
53
|
-
};
|
|
54
|
-
const getGithubLinkFromUrl = () => {
|
|
55
|
-
const githubLink = "https://raw.githubusercontent.com/powerhouse-inc/connect";
|
|
56
|
-
const url = window.location.href;
|
|
57
|
-
const env = Object.keys(urlBranchMap).find((env) => url.includes(env));
|
|
58
|
-
const value = env ? urlBranchMap[env] : void 0;
|
|
59
|
-
if (!value) return;
|
|
60
|
-
else return `${githubLink}/${value}/package.json`;
|
|
61
|
-
};
|
|
62
|
-
const fetchLatestVersion = async () => {
|
|
63
|
-
const link = getGithubLinkFromUrl();
|
|
64
|
-
if (!link) return;
|
|
65
|
-
const { version } = await (await fetch(link)).json();
|
|
66
|
-
return version;
|
|
67
|
-
};
|
|
68
|
-
const isLatestVersion = async () => {
|
|
69
|
-
const currentVersion = package_default.version;
|
|
70
|
-
const deployed = await fetchLatestVersion();
|
|
71
|
-
if (deployed) return {
|
|
72
|
-
isLatest: deployed === currentVersion,
|
|
73
|
-
currentVersion,
|
|
74
|
-
latestVersion: deployed
|
|
75
|
-
};
|
|
76
|
-
return null;
|
|
77
|
-
};
|
|
78
|
-
const IDB_STORE_NAME = "FILE_DATA";
|
|
79
|
-
const IDB_DB_VERSION = 21;
|
|
80
|
-
const BACKUP_PREFIX = "ph-pglite-backup::";
|
|
81
|
-
const BACKUP_INDEX_KEY = "ph:pglite-backups";
|
|
82
|
-
const BACKUP_RETENTION_MS = 720 * 60 * 60 * 1e3;
|
|
83
|
-
const PRIMARY_IDB_NAMES = [`/pglite/reactor`, `/pglite/${DEFAULT_RELATIONAL_PROCESSOR_DB_NAME}`];
|
|
84
|
-
function idbError(req, context) {
|
|
85
|
-
const cause = req.error ?? /* @__PURE__ */ new Error("unknown IDB error");
|
|
86
|
-
return new Error(`${context}: ${cause.message}`, { cause });
|
|
87
|
-
}
|
|
88
|
-
const LEGACY_DUMPERS = { 16: async () => {
|
|
89
|
-
const [{ PGlite: LegacyPGlite }, { pgDump }] = await Promise.all([import("pglite-legacy-02"), import("pglite-tools-legacy-02/pg_dump")]);
|
|
90
|
-
return async (idbName) => {
|
|
91
|
-
const pg = new LegacyPGlite(`idb://${idbName.replace(/^\/pglite\//, "")}`);
|
|
92
|
-
try {
|
|
93
|
-
await pg.waitReady;
|
|
94
|
-
return await (await pgDump({ pg })).text();
|
|
95
|
-
} finally {
|
|
96
|
-
await pg.close();
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
} };
|
|
100
|
-
function indexedDbExists(name) {
|
|
101
|
-
if (typeof indexedDB.databases === "function") return indexedDB.databases().then((dbs) => dbs.some((d) => d.name === name)).catch(() => true);
|
|
102
|
-
return Promise.resolve(true);
|
|
103
|
-
}
|
|
104
|
-
function openIdb(name, version, upgrade) {
|
|
105
|
-
return new Promise((resolve, reject) => {
|
|
106
|
-
const req = indexedDB.open(name, version);
|
|
107
|
-
req.onerror = () => reject(idbError(req, `IDB open failed for ${name}`));
|
|
108
|
-
req.onblocked = () => reject(/* @__PURE__ */ new Error(`IDB open blocked for ${name}`));
|
|
109
|
-
req.onupgradeneeded = () => upgrade?.(req.result);
|
|
110
|
-
req.onsuccess = () => resolve(req.result);
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
function deleteIdb(name, timeoutMs = 15e3) {
|
|
114
|
-
return new Promise((resolve, reject) => {
|
|
115
|
-
const req = indexedDB.deleteDatabase(name);
|
|
116
|
-
let settled = false;
|
|
117
|
-
const done = (fn) => {
|
|
118
|
-
if (settled) return;
|
|
119
|
-
settled = true;
|
|
120
|
-
fn();
|
|
121
|
-
};
|
|
122
|
-
const timer = setTimeout(() => done(() => reject(/* @__PURE__ */ new Error(`IDB delete timed out for ${name} after ${timeoutMs}ms`))), timeoutMs);
|
|
123
|
-
req.onsuccess = () => done(() => {
|
|
124
|
-
clearTimeout(timer);
|
|
125
|
-
resolve();
|
|
126
|
-
});
|
|
127
|
-
req.onerror = () => done(() => {
|
|
128
|
-
clearTimeout(timer);
|
|
129
|
-
reject(idbError(req, `IDB delete failed for ${name}`));
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
function createFileDataStore(db) {
|
|
134
|
-
if (!db.objectStoreNames.contains(IDB_STORE_NAME)) db.createObjectStore(IDB_STORE_NAME).createIndex("timestamp", "timestamp", { unique: false });
|
|
135
|
-
}
|
|
136
|
-
async function readPgVersionFile(idbName) {
|
|
137
|
-
if (!await indexedDbExists(idbName)) return null;
|
|
138
|
-
let db;
|
|
139
|
-
try {
|
|
140
|
-
db = await openIdb(idbName, IDB_DB_VERSION, createFileDataStore);
|
|
141
|
-
} catch {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
try {
|
|
145
|
-
if (!db.objectStoreNames.contains(IDB_STORE_NAME)) return null;
|
|
146
|
-
const store = db.transaction(IDB_STORE_NAME, "readonly").objectStore(IDB_STORE_NAME);
|
|
147
|
-
const value = await new Promise((resolve, reject) => {
|
|
148
|
-
const req = store.openCursor();
|
|
149
|
-
req.onerror = () => reject(idbError(req, `FILE_DATA cursor failed for ${idbName}`));
|
|
150
|
-
req.onsuccess = () => {
|
|
151
|
-
const cursor = req.result;
|
|
152
|
-
if (!cursor) return resolve(null);
|
|
153
|
-
if ((typeof cursor.key === "string" ? cursor.key : "").endsWith("/PG_VERSION")) resolve(cursor.value);
|
|
154
|
-
else cursor.continue();
|
|
155
|
-
};
|
|
156
|
-
});
|
|
157
|
-
if (!value) return null;
|
|
158
|
-
const bytes = value.contents instanceof Uint8Array ? value.contents : new Uint8Array(value.contents);
|
|
159
|
-
const text = new TextDecoder().decode(bytes).trim();
|
|
160
|
-
const major = parseInt(text, 10);
|
|
161
|
-
return Number.isFinite(major) ? major : null;
|
|
162
|
-
} finally {
|
|
163
|
-
db.close();
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
async function clearFileData(name) {
|
|
167
|
-
const db = await openIdb(name, IDB_DB_VERSION, createFileDataStore);
|
|
168
|
-
try {
|
|
169
|
-
await new Promise((resolve, reject) => {
|
|
170
|
-
const tx = db.transaction(IDB_STORE_NAME, "readwrite");
|
|
171
|
-
tx.oncomplete = () => resolve();
|
|
172
|
-
tx.onerror = () => reject(idbError(tx, `FILE_DATA clear failed for ${name}`));
|
|
173
|
-
tx.onabort = () => reject(idbError(tx, `FILE_DATA clear aborted for ${name}`));
|
|
174
|
-
tx.objectStore(IDB_STORE_NAME).clear();
|
|
175
|
-
});
|
|
176
|
-
} finally {
|
|
177
|
-
db.close();
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
async function cloneFileData(sourceName, destName) {
|
|
181
|
-
const source = await openIdb(sourceName, IDB_DB_VERSION, createFileDataStore);
|
|
182
|
-
try {
|
|
183
|
-
const dest = await openIdb(destName, IDB_DB_VERSION, createFileDataStore);
|
|
184
|
-
try {
|
|
185
|
-
const readStore = source.transaction(IDB_STORE_NAME, "readonly").objectStore(IDB_STORE_NAME);
|
|
186
|
-
const entries = await new Promise((resolve, reject) => {
|
|
187
|
-
const out = [];
|
|
188
|
-
const req = readStore.openCursor();
|
|
189
|
-
req.onerror = () => reject(idbError(req, `FILE_DATA read cursor failed for ${sourceName}`));
|
|
190
|
-
req.onsuccess = () => {
|
|
191
|
-
const cursor = req.result;
|
|
192
|
-
if (!cursor) return resolve(out);
|
|
193
|
-
out.push({
|
|
194
|
-
key: cursor.key,
|
|
195
|
-
value: cursor.value
|
|
196
|
-
});
|
|
197
|
-
cursor.continue();
|
|
198
|
-
};
|
|
199
|
-
});
|
|
200
|
-
await new Promise((resolve, reject) => {
|
|
201
|
-
const writeTx = dest.transaction(IDB_STORE_NAME, "readwrite");
|
|
202
|
-
writeTx.oncomplete = () => resolve();
|
|
203
|
-
writeTx.onerror = () => reject(idbError(writeTx, `FILE_DATA write failed for ${destName}`));
|
|
204
|
-
writeTx.onabort = () => reject(idbError(writeTx, `FILE_DATA write aborted for ${destName}`));
|
|
205
|
-
const writeStore = writeTx.objectStore(IDB_STORE_NAME);
|
|
206
|
-
writeStore.clear();
|
|
207
|
-
for (const { key, value } of entries) writeStore.put(value, key);
|
|
208
|
-
});
|
|
209
|
-
} finally {
|
|
210
|
-
dest.close();
|
|
211
|
-
}
|
|
212
|
-
} finally {
|
|
213
|
-
source.close();
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
function readBackupIndex() {
|
|
217
|
-
try {
|
|
218
|
-
const raw = localStorage.getItem(BACKUP_INDEX_KEY);
|
|
219
|
-
if (!raw) return [];
|
|
220
|
-
const parsed = JSON.parse(raw);
|
|
221
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
222
|
-
} catch {
|
|
223
|
-
return [];
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
function writeBackupIndex(records) {
|
|
227
|
-
try {
|
|
228
|
-
localStorage.setItem(BACKUP_INDEX_KEY, JSON.stringify(records));
|
|
229
|
-
} catch {}
|
|
230
|
-
}
|
|
231
|
-
function registerBackup(rec) {
|
|
232
|
-
writeBackupIndex([...readBackupIndex(), rec]);
|
|
233
|
-
}
|
|
234
|
-
function forgetBackup(name) {
|
|
235
|
-
writeBackupIndex(readBackupIndex().filter((r) => r.name !== name));
|
|
236
|
-
}
|
|
237
|
-
async function janitor() {
|
|
238
|
-
const cutoff = Date.now() - BACKUP_RETENTION_MS;
|
|
239
|
-
const keep = [];
|
|
240
|
-
for (const rec of readBackupIndex()) {
|
|
241
|
-
if (rec.createdAt >= cutoff) {
|
|
242
|
-
keep.push(rec);
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
245
|
-
try {
|
|
246
|
-
await deleteIdb(rec.name);
|
|
247
|
-
} catch (err) {
|
|
248
|
-
console.warn(`Failed to delete expired pglite backup ${rec.name}`, err);
|
|
249
|
-
keep.push(rec);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
writeBackupIndex(keep);
|
|
253
|
-
}
|
|
254
|
-
function publishPhase(idbName, phase) {
|
|
255
|
-
setMigrationStatus({
|
|
256
|
-
idbName,
|
|
257
|
-
phase
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
async function migrateIdbIfNeeded(idbName) {
|
|
261
|
-
const major = await readPgVersionFile(idbName);
|
|
262
|
-
if (major === null || major === 17) return;
|
|
263
|
-
const loader = LEGACY_DUMPERS[major];
|
|
264
|
-
if (!loader) throw new Error(`Unsupported legacy PGlite data dir: PG_VERSION=${major} for ${idbName}`);
|
|
265
|
-
const backupName = `${BACKUP_PREFIX}${idbName}::${(/* @__PURE__ */ new Date()).toISOString()}`;
|
|
266
|
-
const backupRec = {
|
|
267
|
-
name: backupName,
|
|
268
|
-
idbName,
|
|
269
|
-
createdAt: Date.now()
|
|
270
|
-
};
|
|
271
|
-
publishPhase(idbName, "clone");
|
|
272
|
-
await cloneFileData(idbName, backupName);
|
|
273
|
-
registerBackup(backupRec);
|
|
274
|
-
let sql;
|
|
275
|
-
try {
|
|
276
|
-
publishPhase(idbName, "dump");
|
|
277
|
-
sql = await (await loader())(idbName);
|
|
278
|
-
} catch (err) {
|
|
279
|
-
await deleteIdb(backupName).catch(() => {});
|
|
280
|
-
forgetBackup(backupName);
|
|
281
|
-
throw err;
|
|
282
|
-
}
|
|
283
|
-
try {
|
|
284
|
-
await clearFileData(idbName);
|
|
285
|
-
publishPhase(idbName, "restore");
|
|
286
|
-
const pg = new PGlite(`idb://${idbName.replace(/^\/pglite\//, "")}`, { relaxedDurability: false });
|
|
287
|
-
try {
|
|
288
|
-
await pg.waitReady;
|
|
289
|
-
await pg.exec(sql);
|
|
290
|
-
} finally {
|
|
291
|
-
await pg.close();
|
|
292
|
-
}
|
|
293
|
-
} catch (err) {
|
|
294
|
-
await rollbackFromBackup(idbName, backupName, err);
|
|
295
|
-
throw err;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
async function rollbackFromBackup(idbName, backupName, originalError) {
|
|
299
|
-
try {
|
|
300
|
-
await clearFileData(idbName).catch(() => {});
|
|
301
|
-
await cloneFileData(backupName, idbName);
|
|
302
|
-
} catch (rollbackErr) {
|
|
303
|
-
console.error(`PGlite migration failed AND rollback failed for ${idbName}. Primary error:`, originalError, "Rollback error:", rollbackErr);
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
await deleteIdb(backupName).catch(() => {});
|
|
307
|
-
forgetBackup(backupName);
|
|
308
|
-
}
|
|
309
|
-
async function migrateAllLocked() {
|
|
310
|
-
for (const idbName of PRIMARY_IDB_NAMES) await migrateIdbIfNeeded(idbName);
|
|
311
|
-
setMigrationStatus(null);
|
|
312
|
-
}
|
|
313
|
-
async function migrateAllIfNeeded() {
|
|
314
|
-
janitor().catch((err) => console.warn("PGlite backup janitor failed", err));
|
|
315
|
-
if (!(typeof navigator !== "undefined" && "locks" in navigator && typeof navigator.locks.request === "function")) {
|
|
316
|
-
await migrateAllLocked();
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
await navigator.locks.request("ph-pglite-migration", { mode: "exclusive" }, async () => {
|
|
320
|
-
await migrateAllLocked();
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
//#endregion
|
|
324
|
-
//#region src/store/user.ts
|
|
325
|
-
function useSetSentryUser() {
|
|
326
|
-
const user = useUser();
|
|
327
|
-
useEffect(() => {
|
|
328
|
-
let sentryUser = null;
|
|
329
|
-
if (user) {
|
|
330
|
-
const { credential, ...rest } = user;
|
|
331
|
-
sentryUser = {
|
|
332
|
-
id: rest.did,
|
|
333
|
-
username: rest.ens?.name,
|
|
334
|
-
...rest
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
setUser(sentryUser);
|
|
338
|
-
}, [user]);
|
|
339
|
-
}
|
|
340
|
-
//#endregion
|
|
341
|
-
//#region src/components/load.tsx
|
|
342
|
-
async function loadComponent(localPackage) {
|
|
343
|
-
await migrateAllIfNeeded();
|
|
344
|
-
await createReactor(localPackage);
|
|
345
|
-
return { default: ({ children }) => {
|
|
346
|
-
useSetSentryUser();
|
|
347
|
-
useCheckLatestVersion();
|
|
348
|
-
return children;
|
|
349
|
-
} };
|
|
350
|
-
}
|
|
351
|
-
//#endregion
|
|
352
|
-
export { loadComponent };
|
|
353
|
-
|
|
354
|
-
//# sourceMappingURL=load-D33GBKWy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"load-D33GBKWy.js","names":["packageJson"],"sources":["../src/components/reload-connect-toast.tsx","../src/hooks/useCheckLatestVersion.ts","../src/hooks/utils.ts","../src/utils/pglite-migration.ts","../src/store/user.ts","../src/components/load.tsx"],"sourcesContent":["import { useTranslation } from \"react-i18next\";\n\nexport const ReloadConnectToast = () => {\n const { t } = useTranslation();\n\n return (\n <div>\n <p className=\"font-medium\">{t(\"notifications.reloadApp\")}</p>\n <button\n onClick={() => location.reload()}\n className=\"underline decoration-solid underline-offset-2\"\n >\n {t(\"common.reloadConnect\")} 🔄\n </button>\n </div>\n );\n};\n","import { connectConfig } from \"@powerhousedao/connect/config\";\nimport { isLatestVersion } from \"@powerhousedao/connect/hooks\";\nimport { toast } from \"@powerhousedao/connect/services\";\nimport { logger } from \"document-model\";\nimport { createElement, useEffect } from \"react\";\nimport { ReloadConnectToast } from \"../components/reload-connect-toast.js\";\n\nexport const useCheckLatestVersion = () => {\n async function checkLatestVersion() {\n const result = await isLatestVersion();\n if (result === null) return;\n // ignore dev/staging versions\n if (result.isLatest || result.currentVersion.includes(\"-\")) {\n return true;\n }\n\n if (\n import.meta.env.MODE === \"development\" ||\n connectConfig.studioMode ||\n !connectConfig.warnOutdatedApp\n ) {\n logger.warn(\n \"Connect is outdated: \\nCurrent: @currentVersion\\nLatest: @latestVersion\",\n result.currentVersion,\n result.latestVersion,\n );\n } else {\n toast(createElement(ReloadConnectToast), {\n type: \"connect-warning\",\n toastId: \"outdated-app\",\n autoClose: false,\n });\n }\n }\n\n useEffect(() => {\n checkLatestVersion().catch(console.error);\n }, []);\n};\n","import { packageJson } from \"../utils/package-json.js\";\n\nexport const isMac = window.navigator.appVersion.includes(\"Mac\");\n\nconst urlBranchMap: Record<string, string> = {\n \"staging/makerdao\": \"deployments/staging/makerdao\",\n \"staging/arbitrum\": \"arb-ltip\",\n \"staging/powerhouse\": \"staging\",\n makerdao: \"deployments/makerdao\",\n arbitrum: \"deployments/arbitrum\",\n arbgrants: \"deployments/arbitrum\",\n localhost: \"develop\",\n};\n\nconst getGithubLinkFromUrl = () => {\n const githubLink = \"https://raw.githubusercontent.com/powerhouse-inc/connect\";\n const url = window.location.href;\n\n const env = Object.keys(urlBranchMap).find((env) => url.includes(env));\n const value = env ? urlBranchMap[env] : undefined;\n if (!value) {\n return undefined;\n } else {\n return `${githubLink}/${value}/package.json`;\n }\n};\n\nconst fetchLatestVersion = async () => {\n const link = getGithubLinkFromUrl();\n if (!link) {\n return undefined;\n }\n const result = await fetch(link);\n const data = (await result.json()) as { version: string };\n const { version } = data;\n return version;\n};\n\nexport const isLatestVersion = async () => {\n const currentVersion = packageJson.version;\n const deployed = await fetchLatestVersion();\n\n if (deployed) {\n return {\n isLatest: deployed === currentVersion,\n currentVersion,\n latestVersion: deployed,\n };\n }\n\n return null;\n};\n","import { PGlite } from \"@electric-sql/pglite\";\nimport { DEFAULT_RELATIONAL_PROCESSOR_DB_NAME } from \"@powerhousedao/shared/processors\";\nimport {\n setMigrationStatus,\n type MigrationPhase,\n} from \"../components/migration-status.js\";\n\nexport const CURRENT_PG_MAJOR = 17;\n\nconst IDB_STORE_NAME = \"FILE_DATA\";\nconst IDB_DB_VERSION = 21;\nconst BACKUP_PREFIX = \"ph-pglite-backup::\";\nconst BACKUP_INDEX_KEY = \"ph:pglite-backups\";\nconst BACKUP_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;\n\nconst PRIMARY_IDB_NAMES = [\n `/pglite/reactor`,\n `/pglite/${DEFAULT_RELATIONAL_PROCESSOR_DB_NAME}`,\n] as const;\n\ntype FileDataValue = {\n contents: Uint8Array | number[];\n mode: number;\n timestamp: Date | number;\n};\n\ntype LegacyDumper = (idbName: string) => Promise<string>;\n\nfunction idbError(req: IDBRequest | IDBTransaction, context: string): Error {\n const cause = req.error ?? new Error(\"unknown IDB error\");\n return new Error(`${context}: ${cause.message}`, { cause });\n}\n\nconst LEGACY_DUMPERS: Partial<Record<number, () => Promise<LegacyDumper>>> = {\n 16: async () => {\n const [{ PGlite: LegacyPGlite }, { pgDump }] = await Promise.all([\n import(\"pglite-legacy-02\"),\n import(\"pglite-tools-legacy-02/pg_dump\"),\n ]);\n return async (idbName: string) => {\n const stripped = idbName.replace(/^\\/pglite\\//, \"\");\n const pg = new LegacyPGlite(`idb://${stripped}`);\n try {\n await pg.waitReady;\n const file = await pgDump({ pg });\n return await file.text();\n } finally {\n await pg.close();\n }\n };\n },\n};\n\nfunction indexedDbExists(name: string): Promise<boolean> {\n if (typeof indexedDB.databases === \"function\") {\n return indexedDB\n .databases()\n .then((dbs) => dbs.some((d) => d.name === name))\n .catch(() => true);\n }\n return Promise.resolve(true);\n}\n\nfunction openIdb(\n name: string,\n version: number,\n upgrade?: (db: IDBDatabase) => void,\n): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open(name, version);\n req.onerror = () => reject(idbError(req, `IDB open failed for ${name}`));\n req.onblocked = () => reject(new Error(`IDB open blocked for ${name}`));\n req.onupgradeneeded = () => upgrade?.(req.result);\n req.onsuccess = () => resolve(req.result);\n });\n}\n\n// Emscripten IDBFS holds the IDB connection open past pglite's pg.close(),\n// so deleteDatabase can be blocked indefinitely. Callers on the hot path\n// should prefer clearFileData() instead; deleteIdb is only used by the\n// janitor for expired backups, which tolerates the 15s timeout.\nfunction deleteIdb(name: string, timeoutMs = 15_000): Promise<void> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.deleteDatabase(name);\n let settled = false;\n const done = (fn: () => void) => {\n if (settled) return;\n settled = true;\n fn();\n };\n const timer = setTimeout(\n () =>\n done(() =>\n reject(\n new Error(`IDB delete timed out for ${name} after ${timeoutMs}ms`),\n ),\n ),\n timeoutMs,\n );\n req.onsuccess = () =>\n done(() => {\n clearTimeout(timer);\n resolve();\n });\n req.onerror = () =>\n done(() => {\n clearTimeout(timer);\n reject(idbError(req, `IDB delete failed for ${name}`));\n });\n });\n}\n\nfunction createFileDataStore(db: IDBDatabase): void {\n if (!db.objectStoreNames.contains(IDB_STORE_NAME)) {\n const store = db.createObjectStore(IDB_STORE_NAME);\n store.createIndex(\"timestamp\", \"timestamp\", { unique: false });\n }\n}\n\nasync function readPgVersionFile(idbName: string): Promise<number | null> {\n if (!(await indexedDbExists(idbName))) return null;\n let db: IDBDatabase;\n try {\n db = await openIdb(idbName, IDB_DB_VERSION, createFileDataStore);\n } catch {\n return null;\n }\n try {\n if (!db.objectStoreNames.contains(IDB_STORE_NAME)) return null;\n const tx = db.transaction(IDB_STORE_NAME, \"readonly\");\n const store = tx.objectStore(IDB_STORE_NAME);\n const value = await new Promise<FileDataValue | null>((resolve, reject) => {\n const req = store.openCursor();\n req.onerror = () =>\n reject(idbError(req, `FILE_DATA cursor failed for ${idbName}`));\n req.onsuccess = () => {\n const cursor = req.result;\n if (!cursor) return resolve(null);\n const key = typeof cursor.key === \"string\" ? cursor.key : \"\";\n if (key.endsWith(\"/PG_VERSION\")) {\n resolve(cursor.value as FileDataValue);\n } else {\n cursor.continue();\n }\n };\n });\n if (!value) return null;\n const bytes =\n value.contents instanceof Uint8Array\n ? value.contents\n : new Uint8Array(value.contents);\n const text = new TextDecoder().decode(bytes).trim();\n const major = parseInt(text, 10);\n return Number.isFinite(major) ? major : null;\n } finally {\n db.close();\n }\n}\n\nasync function clearFileData(name: string): Promise<void> {\n const db = await openIdb(name, IDB_DB_VERSION, createFileDataStore);\n try {\n await new Promise<void>((resolve, reject) => {\n const tx = db.transaction(IDB_STORE_NAME, \"readwrite\");\n tx.oncomplete = () => resolve();\n tx.onerror = () =>\n reject(idbError(tx, `FILE_DATA clear failed for ${name}`));\n tx.onabort = () =>\n reject(idbError(tx, `FILE_DATA clear aborted for ${name}`));\n tx.objectStore(IDB_STORE_NAME).clear();\n });\n } finally {\n db.close();\n }\n}\n\nasync function cloneFileData(\n sourceName: string,\n destName: string,\n): Promise<void> {\n const source = await openIdb(sourceName, IDB_DB_VERSION, createFileDataStore);\n try {\n const dest = await openIdb(destName, IDB_DB_VERSION, createFileDataStore);\n try {\n const readTx = source.transaction(IDB_STORE_NAME, \"readonly\");\n const readStore = readTx.objectStore(IDB_STORE_NAME);\n const entries = await new Promise<\n Array<{ key: IDBValidKey; value: FileDataValue }>\n >((resolve, reject) => {\n const out: Array<{ key: IDBValidKey; value: FileDataValue }> = [];\n const req = readStore.openCursor();\n req.onerror = () =>\n reject(\n idbError(req, `FILE_DATA read cursor failed for ${sourceName}`),\n );\n req.onsuccess = () => {\n const cursor = req.result;\n if (!cursor) return resolve(out);\n out.push({ key: cursor.key, value: cursor.value as FileDataValue });\n cursor.continue();\n };\n });\n\n await new Promise<void>((resolve, reject) => {\n const writeTx = dest.transaction(IDB_STORE_NAME, \"readwrite\");\n writeTx.oncomplete = () => resolve();\n writeTx.onerror = () =>\n reject(idbError(writeTx, `FILE_DATA write failed for ${destName}`));\n writeTx.onabort = () =>\n reject(idbError(writeTx, `FILE_DATA write aborted for ${destName}`));\n const writeStore = writeTx.objectStore(IDB_STORE_NAME);\n writeStore.clear();\n for (const { key, value } of entries) {\n writeStore.put(value, key);\n }\n });\n } finally {\n dest.close();\n }\n } finally {\n source.close();\n }\n}\n\ntype BackupRecord = { name: string; idbName: string; createdAt: number };\n\nfunction readBackupIndex(): BackupRecord[] {\n try {\n const raw = localStorage.getItem(BACKUP_INDEX_KEY);\n if (!raw) return [];\n const parsed: unknown = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as BackupRecord[]) : [];\n } catch {\n return [];\n }\n}\n\nfunction writeBackupIndex(records: BackupRecord[]): void {\n try {\n localStorage.setItem(BACKUP_INDEX_KEY, JSON.stringify(records));\n } catch {\n // ignore quota errors — janitor is best-effort\n }\n}\n\nfunction registerBackup(rec: BackupRecord): void {\n writeBackupIndex([...readBackupIndex(), rec]);\n}\n\nfunction forgetBackup(name: string): void {\n writeBackupIndex(readBackupIndex().filter((r) => r.name !== name));\n}\n\nasync function janitor(): Promise<void> {\n const cutoff = Date.now() - BACKUP_RETENTION_MS;\n const keep: BackupRecord[] = [];\n for (const rec of readBackupIndex()) {\n if (rec.createdAt >= cutoff) {\n keep.push(rec);\n continue;\n }\n try {\n await deleteIdb(rec.name);\n } catch (err) {\n console.warn(`Failed to delete expired pglite backup ${rec.name}`, err);\n keep.push(rec);\n }\n }\n writeBackupIndex(keep);\n}\n\nfunction publishPhase(idbName: string, phase: MigrationPhase): void {\n setMigrationStatus({ idbName, phase });\n}\n\nasync function migrateIdbIfNeeded(idbName: string): Promise<void> {\n const major = await readPgVersionFile(idbName);\n if (major === null || major === CURRENT_PG_MAJOR) return;\n\n const loader = LEGACY_DUMPERS[major];\n if (!loader) {\n throw new Error(\n `Unsupported legacy PGlite data dir: PG_VERSION=${major} for ${idbName}`,\n );\n }\n\n const backupName = `${BACKUP_PREFIX}${idbName}::${new Date().toISOString()}`;\n const backupRec: BackupRecord = {\n name: backupName,\n idbName,\n createdAt: Date.now(),\n };\n\n publishPhase(idbName, \"clone\");\n await cloneFileData(idbName, backupName);\n registerBackup(backupRec);\n\n let sql: string;\n try {\n publishPhase(idbName, \"dump\");\n const dump = await loader();\n sql = await dump(idbName);\n } catch (err) {\n await deleteIdb(backupName).catch(() => {});\n forgetBackup(backupName);\n throw err;\n }\n\n try {\n // Can't deleteDatabase here: Emscripten IDBFS from the legacy PGlite\n // keeps its IDB connection open past pg.close(). Clearing the store\n // in-place leaves the IDB handle alone, and the fresh PGlite will\n // initdb into the empty VFS.\n await clearFileData(idbName);\n publishPhase(idbName, \"restore\");\n const stripped = idbName.replace(/^\\/pglite\\//, \"\");\n const pg = new PGlite(`idb://${stripped}`, { relaxedDurability: false });\n try {\n await pg.waitReady;\n await pg.exec(sql);\n } finally {\n await pg.close();\n }\n } catch (err) {\n await rollbackFromBackup(idbName, backupName, err);\n throw err;\n }\n}\n\nasync function rollbackFromBackup(\n idbName: string,\n backupName: string,\n originalError: unknown,\n): Promise<void> {\n try {\n await clearFileData(idbName).catch(() => {});\n await cloneFileData(backupName, idbName);\n } catch (rollbackErr) {\n console.error(\n `PGlite migration failed AND rollback failed for ${idbName}. Primary error:`,\n originalError,\n \"Rollback error:\",\n rollbackErr,\n );\n return;\n }\n await deleteIdb(backupName).catch(() => {});\n forgetBackup(backupName);\n}\n\nasync function migrateAllLocked(): Promise<void> {\n for (const idbName of PRIMARY_IDB_NAMES) {\n await migrateIdbIfNeeded(idbName);\n }\n setMigrationStatus(null);\n}\n\nexport async function migrateAllIfNeeded(): Promise<void> {\n janitor().catch((err) => console.warn(\"PGlite backup janitor failed\", err));\n\n const hasLocks =\n typeof navigator !== \"undefined\" &&\n \"locks\" in navigator &&\n typeof navigator.locks.request === \"function\";\n\n if (!hasLocks) {\n await migrateAllLocked();\n return;\n }\n\n await navigator.locks.request(\n \"ph-pglite-migration\",\n { mode: \"exclusive\" },\n async () => {\n await migrateAllLocked();\n },\n );\n}\n","import { useUser } from \"@powerhousedao/reactor-browser\";\nimport type { User as SentryUser } from \"@sentry/react\";\nimport { setUser as setSentryUser } from \"@sentry/react\";\nimport { useEffect } from \"react\";\n\nexport function useSetSentryUser() {\n const user = useUser();\n useEffect(() => {\n let sentryUser: SentryUser | null = null;\n if (user) {\n // saves the user info except the credential\n const { credential, ...rest } = user;\n sentryUser = { id: rest.did, username: rest.ens?.name, ...rest };\n }\n setSentryUser(sentryUser);\n }, [user]);\n}\n","import { useCheckLatestVersion } from \"@powerhousedao/connect/hooks\";\nimport \"@powerhousedao/connect/i18n\";\nimport { createReactor, useSetSentryUser } from \"@powerhousedao/connect/store\";\nimport { migrateAllIfNeeded } from \"@powerhousedao/connect/utils\";\nimport type { DocumentModelLib } from \"document-model\";\nimport { type ReactNode } from \"react\";\n\nexport async function loadComponent(localPackage?: DocumentModelLib) {\n await migrateAllIfNeeded();\n await createReactor(localPackage);\n return {\n default: ({ children }: { children?: ReactNode }) => {\n useSetSentryUser();\n useCheckLatestVersion();\n return children;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migration-status-B9oFtMAT.js","names":["translationEN"],"sources":["../src/i18n/locales/en.json","../src/i18n/index.ts","../src/components/migration-status.ts"],"sourcesContent":["","import type { Resource } from \"i18next\";\nimport i18n from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\n\nimport translationEN from \"./locales/en.json\" with { type: \"json\" };\n\nconst resources: Resource = {\n en: {\n code: \"en\",\n name: \"English\",\n translation: translationEN,\n },\n};\n\ni18n\n .use(initReactI18next)\n .init({\n resources,\n fallbackLng: \"en\",\n debug: false,\n interpolation: {\n escapeValue: false,\n },\n })\n .catch((e: unknown) => {\n console.error(e);\n });\n\nexport { i18n };\nexport default i18n;\n","export type MigrationPhase = \"clone\" | \"dump\" | \"restore\";\n\nexport type MigrationStatus = {\n idbName: string;\n phase: MigrationPhase;\n};\n\nlet current: MigrationStatus | null = null;\nconst listeners = new Set<() => void>();\n\nexport function setMigrationStatus(status: MigrationStatus | null): void {\n current = status;\n for (const l of listeners) l();\n}\n\nexport function getMigrationStatus(): MigrationStatus | null {\n return current;\n}\n\nexport function subscribeMigrationStatus(cb: () => void): () => void {\n listeners.add(cb);\n return () => {\n listeners.delete(cb);\n };\n}\n"],"mappings":";;ACcA,KACG,IAAI,iBAAiB,CACrB,KAAK;CACJ,WAXwB,EAC1B,IAAI;EACF,MAAM;EACN,MAAM;EACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EACD,EACF;CAMG,aAAa;CACb,OAAO;CACP,eAAe,EACb,aAAa,OACd;CACF,CAAC,CACD,OAAO,MAAe;AACrB,SAAQ,MAAM,EAAE;EAChB;;;ACnBJ,IAAI,UAAkC;AACtC,MAAM,4BAAY,IAAI,KAAiB;AAEvC,SAAgB,mBAAmB,QAAsC;AACvE,WAAU;AACV,MAAK,MAAM,KAAK,UAAW,IAAG;;AAGhC,SAAgB,qBAA6C;AAC3D,QAAO;;AAGT,SAAgB,yBAAyB,IAA4B;AACnE,WAAU,IAAI,GAAG;AACjB,cAAa;AACX,YAAU,OAAO,GAAG"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"package-DOkPWVM4.js","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reactor-f19C1Zwk.js","names":["#packageManager","#registryClient","#mode","#dismissedStorage","#findModuleInLoadedPackages","#deferred","#discover","#discoveredTypes","#pending","#addToPending","#findTypesByPackage","#emitEvent","#notifyPendingChanged","#pendingMemo","#pendingSubscribers","#eventSubscribers","#createDeferredEntry","#storage","#cdnUrl","#toCdnUrl","#localPackageNames","#registerPackage","#localPackage","#localPackageVersion","#notifyPackagesChanged","#packagesMemo","#packages","#loadPackage","#unmountStylesheet","#subscribers","#loadPackageFromNodeModules","#importPackage","#loadPackageFromRegistry","#mountStylesheet","#stylesheets"],"sources":["../src/utils/reactor.ts","../src/feature-flags.ts","../src/package-discovery.ts","../src/package-manager.ts","../src/packages.config.ts","../src/pglite.db.ts","../src/store/processor-host-module.ts","../src/store/reactor.ts"],"sourcesContent":["import { PGlite } from \"@electric-sql/pglite\";\nimport {\n addRemoteDrive,\n ChannelScheme,\n ReactorBuilder,\n ReactorClientBuilder,\n type BrowserReactorClientModule,\n type Database,\n type IDocumentModelLoader,\n type JwtHandler,\n type SignerConfig,\n} from \"@powerhousedao/reactor-browser\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { createSignatureVerifier, type IRenown } from \"@renown/sdk\";\nimport { ConsoleLogger } from \"document-model\";\nimport { Kysely } from \"kysely\";\nimport { PGliteDialect } from \"kysely-pglite-dialect\";\n\n/**\n * Creates a Reactor that plugs into legacy storage but syncs through the new\n * Reactor GQL API.\n */\nexport async function createBrowserReactor(\n documentModelModules: DocumentModelModule[],\n upgradeManifests: UpgradeManifest<readonly number[]>[],\n renown: IRenown,\n documentModelLoader?: IDocumentModelLoader,\n): Promise<BrowserReactorClientModule> {\n const signerConfig: SignerConfig = {\n signer: renown.signer,\n verifier: createSignatureVerifier(),\n };\n\n const jwtHandler: JwtHandler = async (url: string) => {\n if (!renown.user) {\n return undefined;\n }\n return renown.getBearerToken({ expiresIn: 10, aud: url });\n };\n\n const pg = new PGlite(\"idb://reactor\", {\n relaxedDurability: true,\n });\n const logger = new ConsoleLogger([\"reactor-client\"]);\n const builder = new ReactorClientBuilder()\n .withLogger(logger)\n .withSigner(signerConfig)\n .withReactorBuilder(\n new ReactorBuilder()\n .withDocumentModels(documentModelModules)\n .withUpgradeManifests(upgradeManifests)\n .withChannelScheme(ChannelScheme.CONNECT)\n .withJwtHandler(jwtHandler)\n .withKysely(\n new Kysely<Database>({\n dialect: new PGliteDialect(pg),\n }),\n ),\n );\n\n if (documentModelLoader) {\n builder.withDocumentModelLoader(documentModelLoader);\n }\n\n const module = await builder.buildModule();\n return {\n ...module,\n pg,\n } as BrowserReactorClientModule;\n}\n\n/**\n * Parse default drives from environment variable.\n * Returns an array of drive REST endpoint URLs (e.g., \"https://example.com/d/powerhouse\").\n */\nexport function getDefaultDrivesFromEnv(): string[] {\n const envValue = import.meta.env.PH_CONNECT_DEFAULT_DRIVES_URL as\n | string\n | undefined;\n if (!envValue) return [];\n return envValue.split(\",\").filter((url) => url.trim().length > 0);\n}\n\n/**\n * Add default drives for the new reactor via sync manager.\n *\n * Retries with linear backoff to handle the common race where Connect's\n * dev server is ready before the switchboard has finished binding its port.\n *\n * @param defaultDriveUrls - Array of drive REST endpoint URLs (e.g., \"https://example.com/d/powerhouse\")\n */\nexport async function addDefaultDrivesForNewReactor(\n defaultDriveUrls: string[],\n): Promise<void> {\n const MAX_ATTEMPTS = 3;\n const BACKOFF_MS = 2000;\n\n for (const url of defaultDriveUrls) {\n for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {\n try {\n await addRemoteDrive(url);\n break;\n } catch (error) {\n if (attempt === MAX_ATTEMPTS) {\n console.error(\n `Failed to add default drive ${url} after ${MAX_ATTEMPTS} attempts:`,\n error,\n );\n } else {\n const delay = BACKOFF_MS * attempt;\n console.warn(\n `Default drive ${url} not reachable (attempt ${attempt}/${MAX_ATTEMPTS}), retrying in ${delay}ms...`,\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n }\n}\n","import {\n OpenFeature,\n type ErrorCode,\n type JsonValue,\n type Provider,\n type ResolutionDetails,\n} from \"@openfeature/web-sdk\";\nimport { logger, setLogLevel, type ILogger } from \"document-model\";\n\n/**\n * QueryParamProvider reads feature flags from URL query parameters.\n *\n * Usage:\n * const params = new URLSearchParams(window.location.search);\n * const provider = new QueryParamProvider(params);\n * await OpenFeature.setProviderAndWait(provider);\n *\n * Query parameter format:\n * ?FEATURE_DUAL_ACTION_CREATE_ENABLED=true&FEATURE_FOO=false\n */\nexport class QueryParamProvider implements Provider {\n public readonly runsOn = \"client\" as const;\n\n readonly metadata = {\n name: \"QueryParamProvider\",\n } as const;\n\n private flags: Map<string, string>;\n\n constructor(searchParams: URLSearchParams) {\n this.flags = new Map();\n\n // Extract all query parameters that look like feature flags\n for (const [key, value] of searchParams.entries()) {\n this.flags.set(key, value);\n }\n }\n\n resolveBooleanEvaluation(\n flagKey: string,\n defaultValue: boolean,\n ): ResolutionDetails<boolean> {\n const value = this.flags.get(flagKey);\n\n if (value === undefined) {\n return {\n value: defaultValue,\n reason: \"DEFAULT\",\n };\n }\n\n // Parse boolean from string\n const boolValue = value.toLowerCase() === \"true\" || value === \"1\";\n\n return {\n value: boolValue,\n reason: \"STATIC\",\n variant: value,\n };\n }\n\n resolveStringEvaluation(\n flagKey: string,\n defaultValue: string,\n ): ResolutionDetails<string> {\n const value = this.flags.get(flagKey);\n\n if (value === undefined) {\n return {\n value: defaultValue,\n reason: \"DEFAULT\",\n };\n }\n\n return {\n value,\n reason: \"STATIC\",\n variant: value,\n };\n }\n\n resolveNumberEvaluation(\n flagKey: string,\n defaultValue: number,\n ): ResolutionDetails<number> {\n const value = this.flags.get(flagKey);\n\n if (value === undefined) {\n return {\n value: defaultValue,\n reason: \"DEFAULT\",\n };\n }\n\n const numValue = Number(value);\n\n if (isNaN(numValue)) {\n return {\n value: defaultValue,\n reason: \"ERROR\",\n errorCode: \"PARSE_ERROR\" as ErrorCode,\n errorMessage: `Failed to parse \"${value}\" as a number`,\n };\n }\n\n return {\n value: numValue,\n reason: \"STATIC\",\n variant: value,\n };\n }\n\n resolveObjectEvaluation<T extends JsonValue>(\n flagKey: string,\n defaultValue: T,\n ): ResolutionDetails<T> {\n const value = this.flags.get(flagKey);\n\n if (value === undefined) {\n return {\n value: defaultValue,\n reason: \"DEFAULT\",\n };\n }\n\n try {\n const objValue = JSON.parse(value) as T;\n return {\n value: objValue,\n reason: \"STATIC\",\n variant: value,\n };\n } catch (error) {\n return {\n value: defaultValue,\n reason: \"ERROR\",\n errorCode: \"PARSE_ERROR\" as ErrorCode,\n errorMessage: `Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n }\n}\n\n/**\n * Initialize OpenFeature with the QueryParamProvider.\n * Reads feature flags from query parameters.\n */\nexport async function initFeatureFlags(\n searchParams?: URLSearchParams,\n): Promise<Map<string, boolean>> {\n const params =\n searchParams ??\n (typeof window !== \"undefined\"\n ? new URLSearchParams(window.location.search)\n : new URLSearchParams());\n const provider = new QueryParamProvider(params);\n await OpenFeature.setProviderAndWait(provider);\n\n const features = new Map<string, boolean>();\n\n // Handle LOG_LEVEL query param override\n const logLevelParam = params.get(\"LOG_LEVEL\");\n if (logLevelParam) {\n const validLogLevels = [\"verbose\", \"debug\", \"info\", \"warn\", \"error\"];\n if (validLogLevels.includes(logLevelParam.toLowerCase())) {\n setLogLevel(logLevelParam.toLowerCase() as ILogger[\"level\"]);\n logger.info(\n \"Log level set to @level via query param\",\n logLevelParam.toLowerCase(),\n );\n } else {\n logger.warn(\n \"Invalid LOG_LEVEL query param: @param. Valid values: @validLevels\",\n logLevelParam,\n validLogLevels.join(\", \"),\n );\n }\n }\n\n return features;\n}\n","import {\n BrowserLocalStorage,\n type IDocumentModelLoader,\n type IPackageDiscoveryService,\n type DiscoveryEvent,\n type DiscoveryEventListener,\n type PendingInstallation,\n} from \"@powerhousedao/reactor-browser\";\nimport type { RegistryClient } from \"@powerhousedao/reactor-browser\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport type { BrowserPackageManager } from \"./package-manager.js\";\n\nexport type DiscoveryMode = \"immediate\" | \"manual\";\n\ntype DeferredEntry = {\n packageNames: string[];\n resolve: (module: DocumentModelModule<any>) => void;\n reject: (reason: unknown) => void;\n promise: Promise<DocumentModelModule<any>>;\n};\n\nexport class PackageDiscoveryService\n implements IDocumentModelLoader, IPackageDiscoveryService\n{\n #packageManager: BrowserPackageManager;\n #registryClient: RegistryClient;\n #mode: DiscoveryMode;\n\n #deferred = new Map<string, DeferredEntry>();\n #pending = new Map<string, PendingInstallation>();\n #pendingMemo: PendingInstallation[] = [];\n #pendingSubscribers = new Set<() => void>();\n #eventSubscribers = new Set<DiscoveryEventListener>();\n #dismissedStorage: BrowserLocalStorage<boolean>;\n #discoveredTypes = new Map<string, string[]>();\n\n constructor(\n packageManager: BrowserPackageManager,\n registryClient: RegistryClient,\n options: { mode: DiscoveryMode; storageKey: string },\n ) {\n this.#packageManager = packageManager;\n this.#registryClient = registryClient;\n this.#mode = options.mode;\n this.#dismissedStorage = new BrowserLocalStorage<boolean>(\n options.storageKey + \":PH_DISMISSED_TYPES\",\n );\n }\n\n load(documentType: string): Promise<DocumentModelModule<any>> {\n const existing = this.#findModuleInLoadedPackages(documentType);\n if (existing) {\n return Promise.resolve(existing);\n }\n\n if (this.#dismissedStorage.has(documentType)) {\n return Promise.reject(\n new Error(`Document type \"${documentType}\" was dismissed`),\n );\n }\n\n const tracked = this.#deferred.get(documentType);\n if (tracked) {\n return tracked.promise;\n }\n\n return this.#discover(documentType);\n }\n\n promptInstallation(documentType: string): void {\n const packageNames = this.#discoveredTypes.get(documentType);\n if (!packageNames) return;\n if (this.#pending.has(documentType)) return;\n\n this.#discoveredTypes.delete(documentType);\n this.#addToPending(documentType, packageNames);\n }\n\n async approveInstallation(packageName: string): Promise<void> {\n const affectedTypes = this.#findTypesByPackage(packageName);\n if (affectedTypes.length === 0) return;\n\n const result = await this.#packageManager.addPackage(packageName);\n if (result.type === \"error\") {\n this.#emitEvent({\n type: \"installation-failed\",\n packageName,\n error: result.error,\n });\n for (const documentType of affectedTypes) {\n const entry = this.#deferred.get(documentType);\n if (entry) {\n entry.reject(result.error);\n this.#deferred.delete(documentType);\n this.#pending.delete(documentType);\n }\n }\n this.#notifyPendingChanged();\n return;\n }\n\n this.#emitEvent({\n type: \"installation-approved\",\n packageName,\n documentTypes: affectedTypes,\n });\n\n for (const documentType of affectedTypes) {\n const entry = this.#deferred.get(documentType);\n if (!entry) continue;\n\n const module = this.#findModuleInLoadedPackages(documentType);\n if (module) {\n entry.resolve(module);\n } else {\n entry.reject(\n new Error(\n `Package \"${packageName}\" installed but module for \"${documentType}\" not found`,\n ),\n );\n }\n this.#deferred.delete(documentType);\n this.#pending.delete(documentType);\n }\n this.#notifyPendingChanged();\n }\n\n dismissInstallation(packageName: string): void {\n const affectedTypes = this.#findTypesByPackage(packageName);\n if (affectedTypes.length === 0) return;\n\n for (const documentType of affectedTypes) {\n this.#dismissedStorage.set(documentType, true);\n const entry = this.#deferred.get(documentType);\n if (entry) {\n entry.reject(\n new Error(`Document type \"${documentType}\" was dismissed`),\n );\n }\n this.#deferred.delete(documentType);\n this.#pending.delete(documentType);\n this.#discoveredTypes.delete(documentType);\n }\n\n this.#emitEvent({\n type: \"installation-dismissed\",\n packageName,\n documentTypes: affectedTypes,\n });\n this.#notifyPendingChanged();\n }\n\n getPendingInstallations(): PendingInstallation[] {\n return this.#pendingMemo;\n }\n\n subscribePending(listener: () => void): () => void {\n this.#pendingSubscribers.add(listener);\n return () => {\n this.#pendingSubscribers.delete(listener);\n };\n }\n\n subscribeEvents(listener: DiscoveryEventListener): () => void {\n this.#eventSubscribers.add(listener);\n return () => {\n this.#eventSubscribers.delete(listener);\n };\n }\n\n async #discover(documentType: string): Promise<DocumentModelModule<any>> {\n let packageNames: string[];\n try {\n packageNames =\n await this.#registryClient.getPackagesByDocumentType(documentType);\n } catch (error) {\n this.#emitEvent({\n type: \"registry-query-failed\",\n documentType,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n return Promise.reject(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n\n if (packageNames.length === 0) {\n return Promise.reject(\n new Error(`No packages found for document type \"${documentType}\"`),\n );\n }\n\n const entry = this.#createDeferredEntry(documentType, packageNames);\n\n this.#emitEvent({\n type: \"type-discovered\",\n documentType,\n packageNames,\n });\n\n if (this.#mode === \"immediate\") {\n this.#addToPending(documentType, packageNames);\n } else {\n this.#discoveredTypes.set(documentType, packageNames);\n }\n\n return entry.promise;\n }\n\n #createDeferredEntry(\n documentType: string,\n packageNames: string[],\n ): DeferredEntry {\n let resolve!: (module: DocumentModelModule<any>) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<DocumentModelModule<any>>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const entry: DeferredEntry = { packageNames, resolve, reject, promise };\n this.#deferred.set(documentType, entry);\n return entry;\n }\n\n #addToPending(documentType: string, packageNames: string[]): void {\n const installation: PendingInstallation = { documentType, packageNames };\n this.#pending.set(documentType, installation);\n this.#emitEvent({\n type: \"installation-prompted\",\n documentType,\n packageNames,\n });\n this.#notifyPendingChanged();\n }\n\n #findModuleInLoadedPackages(\n documentType: string,\n ): DocumentModelModule<any> | undefined {\n return this.#packageManager.packages\n .flatMap((p) => p.documentModels)\n .find((m) => m.documentModel.global.id === documentType);\n }\n\n #findTypesByPackage(packageName: string): string[] {\n const types: string[] = [];\n for (const [documentType, entry] of this.#deferred) {\n if (entry.packageNames.includes(packageName)) {\n types.push(documentType);\n }\n }\n return types;\n }\n\n #notifyPendingChanged(): void {\n this.#pendingMemo = Array.from(this.#pending.values());\n for (const listener of this.#pendingSubscribers) {\n listener();\n }\n }\n\n #emitEvent(event: DiscoveryEvent): void {\n for (const listener of this.#eventSubscribers) {\n listener(event);\n }\n }\n}\n","import * as common from \"@powerhousedao/powerhouse-vetra-packages\";\nimport commonPkg from \"@powerhousedao/powerhouse-vetra-packages/package.json\" with { type: \"json\" };\nimport type {\n IPackagesListener,\n PackageManagerInstallResult,\n} from \"@powerhousedao/reactor-browser\";\nimport {\n BrowserLocalStorage,\n type IPackageListerUnsubscribe,\n type IPackageManager,\n} from \"@powerhousedao/reactor-browser\";\nimport {\n type DocumentModelLib,\n type DocumentModelModule,\n} from \"@powerhousedao/shared/document-model\";\nimport * as vetra from \"@powerhousedao/vetra\";\nimport vetraPkg from \"@powerhousedao/vetra/package.json\" with { type: \"json\" };\n\ntype PackageMeta = {\n name: string;\n importUrl: string | null;\n stylesheetUrl: string | null;\n version?: string;\n};\n\ntype PackageWithMeta = PackageMeta & {\n loadedPackage: DocumentModelLib;\n};\n\nasync function fetchPackageJsonVersion(\n baseUrl: string,\n): Promise<string | undefined> {\n try {\n const res = await fetch(baseUrl);\n if (!res.ok) return undefined;\n const pkg = (await res.json()) as { version?: unknown };\n return typeof pkg.version === \"string\" ? pkg.version : undefined;\n } catch {\n return undefined;\n }\n}\n\nconst LOCAL_PACKAGE_NAME = \"Local\" as const;\n\nexport class BrowserPackageManager implements IPackageManager {\n registryUrl: string | null;\n #storage: BrowserLocalStorage<PackageMeta>;\n #packages: Map<string, DocumentModelLib> = new Map();\n #subscribers = new Set<IPackagesListener>();\n #packagesMemo: DocumentModelLib[] = [];\n #stylesheets: Map<string, HTMLLinkElement> = new Map();\n #localPackage: DocumentModelLib | undefined;\n\n #cdnUrl: string | null;\n #localPackageVersion: string | undefined;\n #localPackageNames: Set<string> = new Set([LOCAL_PACKAGE_NAME]);\n\n constructor(namespace: string, registryUrl: string | null) {\n this.#storage = new BrowserLocalStorage<PackageMeta>(\n namespace + \":PH_PACKAGES\",\n );\n this.registryUrl = registryUrl;\n this.#cdnUrl = registryUrl !== null ? this.#toCdnUrl(registryUrl) : null;\n }\n\n #toCdnUrl(baseUrl: string): string {\n if (baseUrl.includes(\"/-/cdn\")) return baseUrl;\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n return `${base}/-/cdn`;\n }\n\n async init(localPackage?: DocumentModelLib, localPackageVersion?: string) {\n this.addLocalPackage(common.manifest.name, common, commonPkg.version);\n this.addLocalPackage(vetra.manifest.name, vetra, vetraPkg.version);\n if (localPackage) {\n this.updateLocalPackage(localPackage, localPackageVersion);\n }\n for (const packageName of this.#storage.keys()) {\n await this.addPackage(packageName);\n }\n }\n\n addLocalPackage(\n name: string,\n loadedPackage: DocumentModelLib,\n version?: string,\n ) {\n this.#localPackageNames.add(name);\n this.#registerPackage({\n name,\n importUrl: null,\n stylesheetUrl: null,\n loadedPackage,\n version,\n });\n }\n\n updateLocalPackage(pkg: DocumentModelLib, version?: string) {\n console.debug(\"Updating local package:\", pkg);\n this.#localPackage = pkg;\n this.#registerPackage({\n name: LOCAL_PACKAGE_NAME,\n stylesheetUrl: null,\n importUrl: null,\n loadedPackage: pkg,\n });\n if (version) {\n this.#localPackageVersion = version;\n this.#notifyPackagesChanged();\n return;\n }\n fetchPackageJsonVersion(\"/package.json\")\n .then((fetchedVersion) => {\n this.#localPackageVersion = fetchedVersion;\n if (fetchedVersion) this.#notifyPackagesChanged();\n })\n .catch(() => {});\n }\n\n get packages() {\n return this.#packagesMemo;\n }\n\n get cdnUrl(): string | null {\n return this.#cdnUrl;\n }\n\n getPackageSource(packageName: string) {\n // check vs packages registered as local (Common, Vetra, bundled packages...)\n if (this.#localPackageNames.has(packageName)) {\n return \"common\";\n }\n // check if the package has the same name as the local project\n if (packageName === this.#localPackage?.manifest.name) return \"project\";\n const packageMeta = this.#storage.get(packageName);\n // if meta does not exist the package is not installed\n if (!packageMeta) return null;\n // if imported from node_modules then the package is installed locally\n if (packageMeta.importUrl === `/node_modules/${packageName}`)\n return \"local-install\";\n // all other import urls point to a registry\n return \"registry-install\";\n }\n\n getPackageVersion(packageName: string): string | undefined {\n if (packageName === this.#localPackage?.manifest.name) {\n return this.#localPackageVersion;\n }\n return this.#storage.get(packageName)?.version;\n }\n\n async addPackage(packageName: string): Promise<PackageManagerInstallResult> {\n const existingPackage = this.#packages.get(packageName);\n if (existingPackage) {\n return {\n type: \"success\",\n package: existingPackage,\n };\n }\n try {\n const packageWithMeta = await this.#loadPackage(packageName);\n this.#registerPackage(packageWithMeta);\n\n return {\n type: \"success\",\n package: packageWithMeta.loadedPackage,\n };\n } catch (error) {\n const normalized =\n error instanceof Error ? error : new Error(String(error));\n console.error(\n `[Connect][PackageManager] Failed to install package \"${packageName}\": ${normalized.message}`,\n normalized,\n );\n return {\n type: \"error\",\n error: normalized,\n };\n }\n }\n\n async addPackages(packageNames: string[]) {\n const results: PackageManagerInstallResult[] = [];\n for (const packageName of packageNames) {\n const result = await this.addPackage(packageName);\n results.push(result);\n }\n return results;\n }\n\n removePackage(name: string) {\n this.#packages.delete(name);\n this.#storage.delete(name);\n this.#unmountStylesheet(name);\n this.#notifyPackagesChanged();\n }\n\n subscribe(handler: IPackagesListener): IPackageListerUnsubscribe {\n this.#subscribers.add(handler);\n return () => {\n this.#subscribers.delete(handler);\n };\n }\n\n load(documentType: string): Promise<DocumentModelModule<any>> {\n const documentModelModule = Array.from(\n this.#packages.values().flatMap((p) => p.documentModels),\n ).find((m) => m.documentModel.global.id === documentType);\n\n if (documentModelModule) return Promise.resolve(documentModelModule);\n return Promise.reject(new Error(\"Model not available\"));\n }\n\n async #loadPackageFromNodeModules(name: string): Promise<PackageWithMeta> {\n const importUrl = `/node_modules/${name}/browser/index.js`;\n const stylesheetUrl = `/node_modules/${name}/style.css`;\n\n const packageWithMeta = await this.#importPackage({\n name,\n importUrl,\n stylesheetUrl,\n });\n packageWithMeta.version = await fetchPackageJsonVersion(\n `/node_modules/${name}/package.json`,\n );\n\n return packageWithMeta;\n }\n\n async #loadPackageFromRegistry(name: string): Promise<PackageWithMeta> {\n const importUrl = `${this.#cdnUrl}/${name}/browser/index.js`;\n const stylesheetUrl = `${this.#cdnUrl}/${name}/style.css`;\n const packageWithMeta = await this.#importPackage({\n name,\n importUrl,\n stylesheetUrl,\n });\n packageWithMeta.version = await fetchPackageJsonVersion(\n `${this.#cdnUrl}/${name}/package.json`,\n );\n\n return packageWithMeta;\n }\n\n async #importPackage(packageMeta: PackageMeta): Promise<PackageWithMeta> {\n const { name, importUrl, stylesheetUrl } = packageMeta;\n if (!importUrl) {\n throw new Error(`Import url not defined for package \"${name}\".`);\n }\n\n const loadedPackage = (await import(\n /* @vite-ignore */ importUrl\n )) as DocumentModelLib;\n\n return {\n name,\n loadedPackage,\n importUrl,\n stylesheetUrl,\n };\n }\n\n async #loadPackage(packageName: string): Promise<PackageWithMeta> {\n if (this.#localPackageNames.has(packageName)) {\n throw new Error(\n `Package \"${packageName}\" is a local package and cannot be loaded dynamically.`,\n );\n }\n\n // only attemp to load from node_modules in dev mode\n if (!import.meta.env.PROD) {\n try {\n const packageWithMeta =\n await this.#loadPackageFromNodeModules(packageName);\n return packageWithMeta;\n } catch (error) {\n console.warn(\n `Failed to load package \"${packageName}\" from node_modules:`,\n error,\n );\n }\n }\n\n if (!this.registryUrl) {\n throw new Error(\"Registry url not defined.\");\n }\n\n return await this.#loadPackageFromRegistry(packageName);\n }\n\n #registerPackage(packageWithMeta: PackageWithMeta) {\n const { name, loadedPackage, importUrl, stylesheetUrl, version } =\n packageWithMeta;\n\n if (stylesheetUrl !== null) {\n this.#mountStylesheet(name, stylesheetUrl);\n }\n this.#packages.set(name, loadedPackage);\n this.#storage.set(name, {\n name,\n importUrl,\n stylesheetUrl,\n version,\n });\n\n this.#notifyPackagesChanged();\n }\n\n #mountStylesheet(name: string, href: string) {\n const existing = this.#stylesheets.get(name);\n\n if (existing) return existing;\n\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = href;\n document.head.appendChild(link);\n\n this.#stylesheets.set(name, link);\n }\n\n #unmountStylesheet(name: string): void {\n const link = this.#stylesheets.get(name);\n if (!link) return;\n\n link.remove();\n this.#stylesheets.delete(name);\n }\n\n #notifyPackagesChanged() {\n this.#packagesMemo = Array.from(this.#packages.values());\n const packages = this.packages;\n this.#subscribers.forEach((handler) => {\n handler({ packages });\n });\n }\n}\n","export type PackagesConfig = {\n packages: string[];\n localPackage?: { name: string; version: string } | null;\n};\n\nfunction assertPackagesConfig(value: unknown): asserts value is PackagesConfig {\n if (typeof value !== \"object\" || value === null) {\n throw new Error(\"ph-packages.json must be a JSON object\");\n }\n\n const obj = value as Record<string, unknown>;\n\n if (!Array.isArray(obj.packages)) {\n throw new Error(\"ph-packages.json: 'packages' must be an array\");\n }\n\n if (!obj.packages.every((item) => typeof item === \"string\")) {\n throw new Error(\"ph-packages.json: 'packages' must be an array of strings\");\n }\n}\n\nlet cached: PackagesConfig | undefined;\n\nexport async function loadPackagesConfig(): Promise<PackagesConfig> {\n if (cached) return cached;\n\n const basePath = import.meta.env.BASE_URL ?? \"/\";\n const url = `${basePath}ph-packages.json`;\n const res = await fetch(url);\n const json: unknown = await res.json();\n assertPackagesConfig(json);\n cached = json;\n return cached;\n}\n\n/**\n * Returns the cached config synchronously.\n * Must be called after `loadPackagesConfig()` has resolved.\n */\nexport function getPackagesConfig(): PackagesConfig {\n if (!cached) {\n throw new Error(\n \"Packages config not loaded yet. Call loadPackagesConfig() first.\",\n );\n }\n return cached;\n}\n","import { live } from \"@electric-sql/pglite/live\";\nimport { PGliteWorker } from \"@electric-sql/pglite/worker\";\nimport { createRelationalDb } from \"@powerhousedao/shared/processors\";\nimport { Kysely } from \"kysely\";\nimport { PGliteDialect } from \"kysely-pglite-dialect\";\n\nexport async function getDb() {\n const worker = new Worker(new URL(\"./pglite.worker.js\", import.meta.url), {\n type: \"module\",\n });\n\n const pgLite = await PGliteWorker.create(worker, {\n extensions: { live },\n });\n\n const kysely = new Kysely({\n dialect: new PGliteDialect(pgLite),\n });\n\n const relationalDb = createRelationalDb(kysely);\n\n return { pgLite, relationalDb };\n}\n","import { createAnalyticsStore } from \"@powerhousedao/reactor-browser\";\nimport type { Action } from \"@powerhousedao/shared/document-model\";\nimport { type IProcessorHostModule } from \"@powerhousedao/shared/processors\";\nimport { getDb } from \"../pglite.db.js\";\n\nexport interface IReactorDispatch {\n executeAsync(\n documentIdentifier: string,\n branch: string,\n actions: Action[],\n signal?: AbortSignal,\n ): Promise<{ id: string; status: string }>;\n}\n\ninterface INamedReadModel {\n readonly name: string;\n}\n\nexport async function createProcessorHostModule(\n reactorClient: IReactorDispatch,\n readModels: INamedReadModel[],\n): Promise<IProcessorHostModule | undefined> {\n try {\n const { pgLite, relationalDb } = await getDb();\n const { store: analyticsStore } = await createAnalyticsStore({\n pgLite,\n });\n const processorApp = \"connect\" as const;\n return {\n relationalDb,\n analyticsStore,\n processorApp,\n dispatch: {\n async execute(docId, branch, actions, signal) {\n const jobInfo = await reactorClient.executeAsync(\n docId,\n branch,\n actions,\n signal,\n );\n return { id: jobInfo.id, status: jobInfo.status };\n },\n },\n getReadModel<T>(name: string): T {\n const model = readModels.find((m) => m.name === name);\n if (!model) {\n throw new Error(`Read model \"${name}\" not found`);\n }\n return model as unknown as T;\n },\n };\n } catch (error) {\n console.error(`Failed to initialize processor host module:`);\n console.error(error);\n }\n}\n","import { phGlobalConfigFromEnv } from \"@powerhousedao/connect/config\";\nimport { toast } from \"@powerhousedao/connect/services\";\nimport {\n addDefaultDrivesForNewReactor,\n createBrowserReactor,\n getDefaultDrivesFromEnv,\n} from \"@powerhousedao/connect/utils\";\nimport {\n addPHEventHandlers,\n addRemoteDrive,\n DocumentCache,\n DocumentChangeType,\n extractDriveSlugFromPath,\n extractNodeSlugFromPath,\n getDrives,\n login,\n refreshReactorDataClient,\n RegistryClient,\n setDefaultPHGlobalConfig,\n setDocumentCache,\n setDrives,\n setFeatures,\n setPackageDiscoveryService,\n setPHToast,\n setReactorClient,\n setReactorClientModule,\n setRenown,\n setSelectedDrive,\n setSelectedNode,\n setVetraPackageManager,\n type PHToastFn,\n} from \"@powerhousedao/reactor-browser\";\nimport {\n BrowserKeyStorage,\n RenownBuilder,\n RenownCryptoBuilder,\n} from \"@renown/sdk\";\nimport {\n logger,\n type DocumentModelLib,\n type UpgradeManifest,\n} from \"document-model\";\nimport { initFeatureFlags } from \"../feature-flags.js\";\nimport { PackageDiscoveryService } from \"../package-discovery.js\";\nimport { BrowserPackageManager } from \"../package-manager.js\";\nimport { loadPackagesConfig } from \"../packages.config.js\";\nimport { createProcessorHostModule } from \"./processor-host-module.js\";\n\nexport async function clearReactorStorage() {\n await window.ph?.reactorClientModule?.pg?.close();\n\n // Dropping tables inside an existing PGlite instance is unreliable with\n // `relaxedDurability: true` followed by an immediate page reload — pending\n // IDB writes can be lost. Deleting the underlying database outright sidesteps\n // flush-timing; the next startup re-creates and re-migrates from scratch.\n const dbs = await indexedDB.databases();\n const targets = dbs\n .map((d) => d.name)\n .filter(\n (n): n is string =>\n !!n && !n.startsWith(\"ph-pglite-backup::\") && /pglite|reactor/i.test(n),\n );\n\n await Promise.all(\n targets.map(\n (name) =>\n new Promise<void>((resolve) => {\n const req = indexedDB.deleteDatabase(name);\n req.onsuccess = req.onerror = req.onblocked = () => resolve();\n }),\n ),\n );\n}\n\nexport async function createReactor(localPackage?: DocumentModelLib) {\n if (!window.ph) {\n window.ph = {};\n }\n if (window.ph.loading) return;\n\n window.ph.loading = true;\n\n // add window event handlers for updates\n addPHEventHandlers();\n\n // register toast function for use in editor components\n setPHToast(toast as PHToastFn);\n\n // initialize feature flags\n const features = await initFeatureFlags();\n\n logger.info(\n \"Features: @features\",\n JSON.stringify(Object.fromEntries(features), null, 2),\n );\n\n // initialize renown crypto\n const keyPairStorage = await BrowserKeyStorage.create();\n const renownCrypto = await new RenownCryptoBuilder()\n .withKeyPairStorage(keyPairStorage)\n .build();\n\n // initialize Renown\n const renown = await new RenownBuilder(\"connect\", {\n basename: phGlobalConfigFromEnv.routerBasename,\n baseUrl: phGlobalConfigFromEnv.renownUrl,\n })\n .withCrypto(renownCrypto)\n .build();\n\n // load packages list from ph-packages.json (replaceable post-build)\n const packagesConfig = await loadPackagesConfig();\n\n // initialize package manager\n const packageManager = new BrowserPackageManager(\n phGlobalConfigFromEnv.routerBasename ?? \"\",\n PH_PACKAGE_REGISTRY_URL,\n );\n setVetraPackageManager(packageManager);\n await packageManager.init(localPackage, packagesConfig.localPackage?.version);\n // Register any packages marked as provider: \"local\" in powerhouse.config.json\n // that the vite plugin bundled into this build. No-op when none were bundled.\n const { default: registerBundledPackages } =\n await import(\"ph-bundled-packages-virtual\");\n registerBundledPackages(packageManager);\n const packagesResult = await packageManager.addPackages(\n packagesConfig.packages,\n );\n packagesResult.map((r) => {\n if (r.type === \"error\") console.error(r.error);\n });\n\n // get document models to set in the reactor (all versions)\n const documentModelModules = packageManager.packages\n .flatMap((pkg) => pkg.documentModels)\n .filter(\n (module, index, modules) =>\n // deduplicate by documentType and version\n modules.findIndex(\n (m) =>\n m.documentModel.global.id === module.documentModel.global.id &&\n m.version === module.version,\n ) === index,\n );\n\n // get upgrade manifests from packages\n const upgradeManifests = packageManager.packages\n .flatMap((pkg) => pkg.upgradeManifests)\n .filter(\n (manifest, index, manifests) =>\n // deduplicate by documentType and version\n manifest !== undefined &&\n manifests.findIndex(\n (m) => m && m.documentType === manifest.documentType,\n ) === index,\n ) as UpgradeManifest<readonly number[]>[];\n\n // initialize package discovery service for auto-installing unknown document types\n const discoveryService =\n packageManager.cdnUrl !== null\n ? new PackageDiscoveryService(\n packageManager,\n new RegistryClient(packageManager.cdnUrl),\n {\n mode: \"immediate\",\n storageKey: phGlobalConfigFromEnv.routerBasename ?? \"\",\n },\n )\n : undefined;\n\n if (discoveryService) {\n setPackageDiscoveryService(discoveryService);\n }\n\n // create reactor v2 with all versions and upgrade manifests\n const reactorClientModule = await createBrowserReactor(\n documentModelModules,\n upgradeManifests,\n renown,\n discoveryService,\n );\n\n // get the drives from the reactor\n const drives = await getDrives(reactorClientModule.client);\n\n // set the selected drive and node from the path\n const path = window.location.pathname;\n const driveSlug = extractDriveSlugFromPath(path);\n const nodeSlug = extractNodeSlugFromPath(path);\n\n // initialize user from URL parameter\n const didFromUrl = getDidFromUrl();\n await login(didFromUrl, renown);\n\n const documentCache = new DocumentCache(reactorClientModule.client);\n\n // dispatch the events to set the values in the window object\n setDefaultPHGlobalConfig(phGlobalConfigFromEnv);\n setReactorClientModule(reactorClientModule);\n setReactorClient(reactorClientModule.client);\n setDocumentCache(documentCache);\n setRenown(renown);\n setDrives(drives);\n setSelectedDrive(driveSlug);\n setSelectedNode(nodeSlug);\n setFeatures(features);\n\n // Add default drives for new reactor (after window.ph is set up)\n const defaultDrivesConfig = getDefaultDrivesFromEnv();\n if (defaultDrivesConfig.length > 0) {\n await addDefaultDrivesForNewReactor(defaultDrivesConfig);\n }\n\n // if remoteUrl is set and drive not already existing add remote drive and open it\n const remoteUrl = getDriveUrl();\n if (remoteUrl) {\n try {\n await addRemoteDrive(remoteUrl);\n } catch (error) {\n console.error(`Failed to add remote drive from ${remoteUrl}:`, error);\n }\n }\n\n // Subscribe via ReactorClient interface\n const reactorClient = reactorClientModule.client;\n reactorClient.subscribe({ type: \"powerhouse/document-drive\" }, (event) => {\n logger.verbose(\"ReactorClient subscription event: @event\", event);\n refreshReactorDataClient(reactorClientModule.client).catch((e) =>\n logger.error(\"@error\", e),\n );\n });\n\n // Redirect when a currently-viewed document or drive is deleted remotely\n reactorClient.subscribe({}, (event) => {\n if (event.type !== DocumentChangeType.Deleted) return;\n const deletedId = event.context?.childId;\n if (!deletedId) return;\n\n const selectedDriveId = window.ph?.selectedDriveId;\n const selectedNodeId = window.ph?.selectedNodeId;\n\n if (selectedDriveId && deletedId === selectedDriveId) {\n setSelectedDrive(undefined);\n toast(\"The drive you were viewing has been deleted\");\n return;\n }\n\n if (selectedNodeId && deletedId === selectedNodeId) {\n setSelectedNode(undefined);\n toast(\"The document you were editing has been deleted\");\n }\n });\n\n // Refresh from ReactorClient to pick up any synced drives\n await refreshReactorDataClient(reactorClientModule.client);\n\n // Setup processor factories for packages that have them\n const packagesWithProcessorFactories = packageManager.packages.filter(\n (pkg) => pkg.processorFactory !== undefined,\n );\n\n if (packagesWithProcessorFactories.length > 0) {\n const readModels =\n reactorClientModule.reactorModule?.readModelCoordinator?.readModels ?? [];\n const processorHostModule = await createProcessorHostModule(\n reactorClientModule.client,\n readModels,\n );\n if (processorHostModule !== undefined) {\n await Promise.all(\n packagesWithProcessorFactories.map(async (pkg) => {\n const { manifest, processorFactory } = pkg;\n const name = manifest.name;\n const id = manifest.name;\n logger.info(\"Loading processor factory: @name\", name);\n try {\n const factory = await processorFactory?.(processorHostModule);\n if (!factory) return;\n await reactorClientModule.reactorModule?.processorManager.registerFactory(\n id,\n factory,\n );\n } catch (error) {\n logger.error(`Error registering processor: @name`, name);\n logger.error(\"@error\", error);\n }\n }),\n );\n }\n }\n\n window.ph.loading = false;\n}\n\nfunction getDidFromUrl() {\n const searchParams = new URLSearchParams(window.location.search);\n const didComponent = searchParams.get(\"user\");\n const did = didComponent ? decodeURIComponent(didComponent) : undefined;\n return did;\n}\n\nfunction getDriveUrl() {\n const searchParams = new URLSearchParams(window.location.search);\n const driveUrl = searchParams.get(\"driveUrl\");\n const url = driveUrl ? decodeURIComponent(driveUrl) : undefined;\n return url;\n}\n"],"mappings":"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"}
|