alinea 2.0.0-preview.12 → 2.0.0-preview.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.init/content/pages/welcome.json +1 -1
- package/dist/.mcp/later/dev.json +1 -1
- package/dist/.mcp/online/dev.json +1 -1
- package/dist/adapter/next/cms.js +16 -8
- package/dist/adapter/next/dashboardUrl.d.ts +6 -0
- package/dist/adapter/next/dashboardUrl.js +13 -0
- package/dist/adapter/next/syncCheck.d.ts +15 -2
- package/dist/adapter/next/syncCheck.js +26 -9
- package/dist/backend/Handler.js +5 -1
- package/dist/backend/api/BlobStore.d.ts +21 -0
- package/dist/backend/api/BlobStore.js +63 -0
- package/dist/backend/api/CreateBackend.js +10 -8
- package/dist/backend/api/DatabaseApi.d.ts +4 -1
- package/dist/backend/api/DatabaseApi.js +88 -4
- package/dist/backend/api/GithubApi.js +47 -24
- package/dist/backend/api/database.js +6 -6
- package/dist/bundled.d.ts +676 -280
- package/dist/chunks/{bun-sqlite-5SHXN3AT.js → bun-sqlite-RI6BYU5S.js} +3 -3
- package/dist/chunks/{chunk-OHGAVV4G.js → chunk-3QFSGTGF.js} +2 -3
- package/dist/chunks/{chunk-QJGGYF6E.js → chunk-4ZA6KZHS.js} +5 -5
- package/dist/chunks/{chunk-ASYKC6IE.js → chunk-5H4D5JQL.js} +1 -1
- package/dist/chunks/{chunk-ETWOY4AL.js → chunk-A2I6MCCS.js} +1 -1
- package/dist/chunks/{chunk-W5AXN7GH.js → chunk-CYVOGRSD.js} +1 -2
- package/dist/chunks/{chunk-TIJTT5ZI.js → chunk-G43W7AME.js} +1 -0
- package/dist/chunks/{chunk-RE523BQ7.js → chunk-HOETF6HN.js} +5829 -5830
- package/dist/chunks/{chunk-AIU6CMVT.js → chunk-PTYZMV5G.js} +1 -1
- package/dist/chunks/{chunk-JOF663EG.js → chunk-QHHMKJUO.js} +1 -1
- package/dist/chunks/{chunk-66YZ47TY.js → chunk-RAR44T5O.js} +1 -1
- package/dist/chunks/{chunk-QSN6RH6X.js → chunk-VA6NC3MI.js} +1 -1
- package/dist/chunks/{node-sqlite-XVNTNMCY.js → node-sqlite-C7VJ2NSN.js} +3 -3
- package/dist/cli/Mcp.js +1 -1
- package/dist/cli/Serve.js +1 -1
- package/dist/cli/bin.js +2 -3
- package/dist/cli/serve/mcp/DevMcp.js +1 -1
- package/dist/cli/serve/mcp/McpTools.js +29 -1
- package/dist/cloud/CloudRemote.js +1 -1
- package/dist/components/Alert.js +2 -2
- package/dist/components/AppShell.js +2 -2
- package/dist/components/Badge.d.ts +3 -1
- package/dist/components/Badge.js +5 -3
- package/dist/components/Breadcrumbs.js +7 -7
- package/dist/components/Button.d.ts +6 -1
- package/dist/components/Button.js +16 -7
- package/dist/components/Calendar.js +20 -20
- package/dist/components/Checkbox.js +7 -7
- package/dist/components/CheckboxGroup.js +4 -4
- package/dist/components/Code.js +2 -2
- package/dist/components/Collapsible.js +3 -3
- package/dist/components/ColorSwatch.js +2 -2
- package/dist/components/ColorSwatchPicker.js +2 -2
- package/dist/components/ComboBox.js +7 -7
- package/dist/components/Command.js +14 -13
- package/dist/components/ContentCard.d.ts +3 -1
- package/dist/components/ContentCard.js +46 -24
- package/dist/components/ContentGrid.js +17 -17
- package/dist/components/DataList.js +2 -2
- package/dist/components/DateField.js +2 -2
- package/dist/components/DatePicker.js +2 -2
- package/dist/components/DateRangePicker.js +2 -2
- package/dist/components/Dialog.js +7 -7
- package/dist/components/DropZone.js +6 -6
- package/dist/components/DropdownMenu.js +9 -9
- package/dist/components/Empty.js +5 -5
- package/dist/components/Field.js +8 -8
- package/dist/components/List.js +27 -27
- package/dist/components/MediaPreview.js +5 -5
- package/dist/components/MultipleSelect.js +22 -22
- package/dist/components/NavRail.js +4 -4
- package/dist/components/NumberField.js +4 -4
- package/dist/components/Page.js +3 -3
- package/dist/components/Popover.js +2 -2
- package/dist/components/PreviewFrame.js +9 -9
- package/dist/components/RadioGroup.js +9 -9
- package/dist/components/Resizable.js +4 -4
- package/dist/components/SearchField.d.ts +6 -1
- package/dist/components/SearchField.js +5 -3
- package/dist/components/Select.js +13 -13
- package/dist/components/Sheet.d.ts +50 -0
- package/dist/components/Sheet.js +202 -0
- package/dist/components/Sidebar.js +4 -4
- package/dist/components/SortableList.d.ts +34 -30
- package/dist/components/SortableList.js +161 -264
- package/dist/components/Spinner.js +2 -2
- package/dist/components/Surface.js +2 -2
- package/dist/components/Switch.js +8 -8
- package/dist/components/Table.d.ts +3 -1
- package/dist/components/Table.js +57 -46
- package/dist/components/Tabs.js +5 -5
- package/dist/components/TagGroup.js +8 -8
- package/dist/components/TextField.js +10 -10
- package/dist/components/TimeField.js +6 -6
- package/dist/components/Timestamp.js +1 -1
- package/dist/components/ToggleGroup.js +2 -2
- package/dist/components/Toolbar.js +2 -2
- package/dist/components/Tooltip.js +5 -5
- package/dist/components/Tree.js +24 -24
- package/dist/components/internal/DateControl.js +12 -12
- package/dist/components/internal/ListBoxOption.js +6 -6
- package/dist/components/internal/Locale.js +2 -2
- package/dist/components/internal/PopoverSurface.js +4 -4
- package/dist/components/internal/SelectionCheckbox.js +5 -5
- package/dist/components/internal/Slot.js +1 -1
- package/dist/components/internal/ToggleButton.js +3 -3
- package/dist/components/internal/Trigger.js +2 -2
- package/dist/components/internal/sortableDrag.d.ts +19 -0
- package/dist/components/internal/sortableDrag.js +175 -0
- package/dist/components/internal/useDragDrop.js +2 -2
- package/dist/components.d.ts +1 -0
- package/dist/components.js +1 -0
- package/dist/core/Config.d.ts +6 -1
- package/dist/core/Document.d.ts +9 -1
- package/dist/core/Document.js +31 -6
- package/dist/core/Overview.d.ts +2 -4
- package/dist/core/TextDoc.d.ts +4 -0
- package/dist/core/Validation.d.ts +0 -1
- package/dist/core/Validation.js +0 -6
- package/dist/core/field/RichTextField.js +23 -4
- package/dist/core/media/MediaTypes.js +1 -1
- package/dist/core/source/GithubSource.d.ts +4 -0
- package/dist/core/source/GithubSource.js +127 -25
- package/dist/core/source/GithubUsage.d.ts +21 -0
- package/dist/core/source/GithubUsage.js +47 -0
- package/dist/dashboard/App.d.ts +2 -2
- package/dist/dashboard/App.js +5 -3
- package/dist/dashboard/ViewKeys.d.ts +1 -0
- package/dist/dashboard/ViewKeys.js +1 -0
- package/dist/dashboard/app/ActivityStatus.js +7 -7
- package/dist/dashboard/app/AuthView.js +5 -5
- package/dist/dashboard/app/BlockSheet.d.ts +50 -0
- package/dist/dashboard/app/BlockSheet.js +207 -0
- package/dist/dashboard/app/BlockSheetStoryFrame.d.ts +6 -0
- package/dist/dashboard/app/BlockSheetStoryFrame.js +29 -0
- package/dist/dashboard/app/CompactField.js +16 -16
- package/dist/dashboard/app/DashboardLayout.js +3 -1
- package/dist/dashboard/app/EntryFields.js +2 -2
- package/dist/dashboard/app/EntryHeader.js +33 -34
- package/dist/dashboard/app/EntryReferences.js +7 -7
- package/dist/dashboard/app/EntrySidebar.js +15 -15
- package/dist/dashboard/app/EntrySidebarPreview.js +3 -3
- package/dist/dashboard/app/EntryStatusIcon.d.ts +23 -0
- package/dist/dashboard/app/EntryStatusIcon.js +58 -0
- package/dist/dashboard/app/EntryValidationModal.d.ts +6 -5
- package/dist/dashboard/app/EntryValidationModal.js +20 -20
- package/dist/dashboard/app/Explorer.d.ts +3 -1
- package/dist/dashboard/app/Explorer.js +48 -44
- package/dist/dashboard/app/ExplorerBatchActions.d.ts +3 -1
- package/dist/dashboard/app/ExplorerBatchActions.js +68 -43
- package/dist/dashboard/app/ExplorerCards.js +7 -1
- package/dist/dashboard/app/ExplorerControls.js +6 -6
- package/dist/dashboard/app/ExplorerList.js +5 -5
- package/dist/dashboard/app/ExplorerModal.js +2 -2
- package/dist/dashboard/app/ExplorerTable.js +11 -8
- package/dist/dashboard/app/ImageEditor.js +28 -28
- package/dist/dashboard/app/ImagePicker.js +3 -13
- package/dist/dashboard/app/LinkPicker.js +28 -26
- package/dist/dashboard/app/LocaleMenu.js +4 -4
- package/dist/dashboard/app/MediaPreviewCell.js +1 -1
- package/dist/dashboard/app/MoveConfirmDialog.d.ts +5 -0
- package/dist/dashboard/app/MoveConfirmDialog.js +79 -0
- package/dist/dashboard/app/OverviewCell.js +8 -13
- package/dist/dashboard/app/PendingUploadsView.js +3 -3
- package/dist/dashboard/app/ReadOnlyBadge.d.ts +1 -1
- package/dist/dashboard/app/RemoveDialog.d.ts +17 -0
- package/dist/dashboard/app/{DeleteDialog.js → RemoveDialog.js} +67 -27
- package/dist/dashboard/app/RemoveRedirect.d.ts +7 -0
- package/dist/dashboard/app/RemoveRedirect.js +123 -0
- package/dist/dashboard/app/SearchBar.d.ts +9 -0
- package/dist/dashboard/app/SearchBar.js +31 -0
- package/dist/dashboard/app/SidebarTree.js +27 -72
- package/dist/dashboard/app/WorkspaceMenu.js +7 -7
- package/dist/dashboard/app/WorkspaceRoots.js +12 -12
- package/dist/dashboard/app/editor/FileEditor.js +14 -14
- package/dist/dashboard/app/modals/CreateEntry.js +3 -3
- package/dist/dashboard/app/pages/EntryPage.d.ts +2 -1
- package/dist/dashboard/app/pages/EntryPage.js +34 -15
- package/dist/dashboard/app/pages/SplashPage.js +37 -37
- package/dist/dashboard/app/pages/UsersPage.js +12 -12
- package/dist/dashboard/app/ui/DashboardModal.js +15 -14
- package/dist/dashboard/atoms/dashboard.js +1 -1
- package/dist/dashboard/atoms/entry.js +1 -14
- package/dist/dashboard/atoms/entryTable.js +1 -0
- package/dist/dashboard/atoms/explorer.d.ts +4 -0
- package/dist/dashboard/atoms/explorer.js +19 -7
- package/dist/dashboard/atoms/graph.js +1 -1
- package/dist/dashboard/atoms/link.js +5 -2
- package/dist/dashboard/atoms/move.d.ts +5 -0
- package/dist/dashboard/atoms/move.js +29 -3
- package/dist/dashboard/atoms/moveConfirmation.d.ts +34 -0
- package/dist/dashboard/atoms/moveConfirmation.js +95 -0
- package/dist/dashboard/atoms/nav.d.ts +9 -5
- package/dist/dashboard/atoms/nav.js +120 -45
- package/dist/dashboard/atoms/overview.d.ts +6 -5
- package/dist/dashboard/atoms/overview.js +2 -16
- package/dist/dashboard/atoms/remove.d.ts +112 -0
- package/dist/dashboard/atoms/remove.js +268 -0
- package/dist/dashboard/atoms/root.d.ts +2 -2
- package/dist/dashboard/atoms/root.js +41 -26
- package/dist/dashboard/atoms/user.js +1 -1
- package/dist/dashboard/atoms/utils.js +1 -1
- package/dist/dashboard/boot/Boot.js +25 -17
- package/dist/dashboard/boot/DashboardWorker.d.ts +1 -0
- package/dist/dashboard/boot/DashboardWorker.js +10 -46
- package/dist/dashboard/boot/LoadWorker.js +17 -10
- package/dist/dashboard/cms/EntryTable.js +8 -5
- package/dist/database/BrowserEntryStore.d.ts +12 -62
- package/dist/database/BrowserEntryStore.js +97 -196
- package/dist/database/DatabaseTables.js +2 -2
- package/dist/database/EntryDatabase.js +21 -1
- package/dist/database/EntryTransaction.js +0 -35
- package/dist/database/EntryUrlAliases.d.ts +4 -0
- package/dist/database/EntryUrlAliases.js +16 -10
- package/dist/database/driver/RuntimeDatabase.js +3 -3
- package/dist/database/driver/WasmDatabase.d.ts +5 -18
- package/dist/database/driver/WasmDatabase.js +15 -16
- package/dist/database/entry/EntryTable.js +2 -2
- package/dist/database/query/EntryQuery.js +1 -1
- package/dist/database/query/Relation.js +1 -1
- package/dist/database/query/Search.js +2 -2
- package/dist/field/code/CodeField.view.js +16 -16
- package/dist/field/link/EntryLink.d.ts +4 -4
- package/dist/field/link/FileLink.d.ts +4 -4
- package/dist/field/link/ImageLink.d.ts +4 -4
- package/dist/field/link/Link.d.ts +1 -1
- package/dist/field/link/LinkField.d.ts +5 -0
- package/dist/field/link/LinkField.view.js +244 -370
- package/dist/field/link/UrlLink.d.ts +4 -4
- package/dist/field/list/ListField.d.ts +2 -0
- package/dist/field/list/ListField.view.d.ts +15 -0
- package/dist/field/list/ListField.view.js +343 -301
- package/dist/field/metadata/MetadataField.d.ts +17 -7
- package/dist/field/metadata/MetadataField.js +14 -3
- package/dist/field/metadata/MetadataField.view.d.ts +1 -0
- package/dist/field/metadata/MetadataField.view.js +25 -21
- package/dist/field/richtext/RichTextBlock.d.ts +3 -1
- package/dist/field/richtext/RichTextBlock.js +177 -74
- package/dist/field/richtext/RichTextBlockHost.js +1 -1
- package/dist/field/richtext/RichTextExtensions.js +31 -31
- package/dist/field/richtext/RichTextField.view.js +14 -8
- package/dist/field/richtext/RichTextInsertMenu.js +43 -27
- package/dist/field/views.js +2 -0
- package/dist/index.css +490 -309
- package/dist/picker/url/UrlPicker.js +1 -0
- package/docs/components/badge.md +1 -0
- package/docs/components/button.md +1 -0
- package/docs/components/content-card.md +1 -0
- package/docs/components/search-field.md +1 -0
- package/docs/components/sortable-list.md +5 -20
- package/docs/components/table.md +1 -0
- package/docs/configuration.md +1 -1
- package/docs/deploy/self-host.md +1 -1
- package/docs/deploy.md +5 -4
- package/docs/fields.md +1 -1
- package/docs/index.md +1 -1
- package/docs/instant-publishing.md +7 -22
- package/docs/overviews.md +3 -4
- package/docs/upgrading.md +3 -2
- package/llms-full.txt +31 -55
- package/package.json +2 -3
- package/dist/core/db/EntryValidationError.d.ts +0 -13
- package/dist/core/db/EntryValidationError.js +0 -23
- package/dist/dashboard/app/DeleteDialog.d.ts +0 -11
- package/dist/dashboard/atoms/delete.d.ts +0 -68
- package/dist/dashboard/atoms/delete.js +0 -143
- package/dist/chunks/{chunk-MOWR65LM.js → chunk-PYDOMKJZ.js} +71 -71
|
@@ -9,10 +9,8 @@ import { getScope } from "alinea/core/Scope";
|
|
|
9
9
|
import { trigger } from "alinea/core/Trigger";
|
|
10
10
|
import { IndexEvent } from "alinea/core/db/IndexEvent";
|
|
11
11
|
import { EntryUrlConflictError } from "alinea/core/db/EntryUrlConflictError";
|
|
12
|
-
import { EntryValidationError } from "alinea/core/db/EntryValidationError";
|
|
13
12
|
import {
|
|
14
13
|
BrowserEntryStore,
|
|
15
|
-
holdCache,
|
|
16
14
|
isCorruptDatabaseError
|
|
17
15
|
} from "alinea/database/BrowserEntryStore";
|
|
18
16
|
import { EntryStore } from "alinea/database/EntryStore";
|
|
@@ -21,7 +19,6 @@ import {
|
|
|
21
19
|
} from "./ActivityEvent.js";
|
|
22
20
|
var remote = pLimit(1);
|
|
23
21
|
var cacheName = "alinea-entry-database";
|
|
24
|
-
var cacheWait = 1e3;
|
|
25
22
|
var syncInterval = 12e4;
|
|
26
23
|
var activityHistoryLimit = 100;
|
|
27
24
|
var DashboardWorker = class extends EventTarget {
|
|
@@ -30,14 +27,13 @@ var DashboardWorker = class extends EventTarget {
|
|
|
30
27
|
#localClient;
|
|
31
28
|
#nextLoad = trigger();
|
|
32
29
|
#defer;
|
|
33
|
-
/** Whether this worker holds the cache, see #holdsCache. */
|
|
34
|
-
#cacheHeld;
|
|
35
30
|
#currentRevision;
|
|
36
31
|
#mutations = [];
|
|
37
32
|
#activities = [];
|
|
38
33
|
#local = pLimit(1);
|
|
39
34
|
#blocked = false;
|
|
40
35
|
#syncInterval;
|
|
36
|
+
/** Keep the content in memory with `source`, instead of in the browser. */
|
|
41
37
|
constructor(source) {
|
|
42
38
|
super();
|
|
43
39
|
this.#source = source;
|
|
@@ -120,7 +116,7 @@ Remote updates: ${remote2}`
|
|
|
120
116
|
void this.#flush(item);
|
|
121
117
|
return item.sha;
|
|
122
118
|
} catch (error) {
|
|
123
|
-
if (error instanceof EntryUrlConflictError
|
|
119
|
+
if (error instanceof EntryUrlConflictError) {
|
|
124
120
|
this.#cancelMutation(item, error);
|
|
125
121
|
throw error;
|
|
126
122
|
}
|
|
@@ -284,9 +280,11 @@ Remote updates: ${remote2}`
|
|
|
284
280
|
this.#localDB = void 0;
|
|
285
281
|
this.#localClient = void 0;
|
|
286
282
|
try {
|
|
287
|
-
await this.#defer?.();
|
|
288
|
-
this.#defer = void 0;
|
|
289
283
|
let db = await this.#open(config, revision, false);
|
|
284
|
+
if (this.#defer)
|
|
285
|
+
void this.#defer().catch(() => {
|
|
286
|
+
});
|
|
287
|
+
this.#defer = void 0;
|
|
290
288
|
let cacheFailure = await this.#syncLocalIndex(db);
|
|
291
289
|
if (cacheFailure && isCorruptDatabaseError(cacheFailure.error)) {
|
|
292
290
|
await db.close();
|
|
@@ -310,9 +308,7 @@ Remote updates: ${remote2}`
|
|
|
310
308
|
});
|
|
311
309
|
this.#defer = async () => {
|
|
312
310
|
unsubscribe();
|
|
313
|
-
|
|
314
|
-
void db.close().catch(() => {
|
|
315
|
-
});
|
|
311
|
+
await db.close();
|
|
316
312
|
};
|
|
317
313
|
} catch (cause) {
|
|
318
314
|
this.#currentRevision = void 0;
|
|
@@ -321,41 +317,9 @@ Remote updates: ${remote2}`
|
|
|
321
317
|
throw cause;
|
|
322
318
|
}
|
|
323
319
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
* and else, or if the cache fails, keep the content in memory only.
|
|
328
|
-
*/
|
|
329
|
-
async #open(config, revision, reset) {
|
|
330
|
-
if (globalThis.indexedDB) {
|
|
331
|
-
const options = { name: cacheName, revision };
|
|
332
|
-
if (await this.#holdsCache()) {
|
|
333
|
-
try {
|
|
334
|
-
return await BrowserEntryStore.open(config, { ...options, reset });
|
|
335
|
-
} catch (error) {
|
|
336
|
-
console.warn("Failed to open the content cache", error);
|
|
337
|
-
}
|
|
338
|
-
} else if (!reset) {
|
|
339
|
-
const snapshot = await BrowserEntryStore.snapshot(config, options);
|
|
340
|
-
if (snapshot) return snapshot;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
return EntryStore.memory(config, this.#fallbackSource());
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Whether this worker holds the cache, which it then keeps for as long as
|
|
347
|
-
* it runs: no other worker writes the cache meanwhile, such as one of
|
|
348
|
-
* another dashboard build. A worker that does not hold it stores nothing
|
|
349
|
-
* until the dashboard loads again.
|
|
350
|
-
*/
|
|
351
|
-
#holdsCache() {
|
|
352
|
-
this.#cacheHeld ??= holdCache(cacheName, { wait: cacheWait });
|
|
353
|
-
return this.#cacheHeld;
|
|
354
|
-
}
|
|
355
|
-
#fallbackSource() {
|
|
356
|
-
if (!this.#source)
|
|
357
|
-
throw new Error("A source is required when IndexedDB is unavailable");
|
|
358
|
-
return this.#source;
|
|
320
|
+
#open(config, fingerprint, reset) {
|
|
321
|
+
if (this.#source) return EntryStore.memory(config, this.#source);
|
|
322
|
+
return BrowserEntryStore.open(config, { name: cacheName, fingerprint, reset });
|
|
359
323
|
}
|
|
360
324
|
async #syncLocalIndex(db) {
|
|
361
325
|
const sourceTree = await db.source.getTree();
|
|
@@ -5,19 +5,14 @@ import "../../chunks/chunk-CQ52GEHY.js";
|
|
|
5
5
|
|
|
6
6
|
// src/dashboard/boot/LoadWorker.ts
|
|
7
7
|
import { IndexEvent } from "alinea/core/db/IndexEvent";
|
|
8
|
-
import { MemorySource } from "alinea/core/source/MemorySource";
|
|
9
8
|
import { ActivityEvent } from "./ActivityEvent.js";
|
|
10
9
|
import { DashboardWorker } from "./DashboardWorker.js";
|
|
11
10
|
async function loadWorker(gen) {
|
|
12
|
-
const worker = new DashboardWorker(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
console.info("Worker connected");
|
|
16
|
-
const port = event.ports[0];
|
|
17
|
-
expose(worker, port);
|
|
18
|
-
const listen = (event2) => {
|
|
11
|
+
const worker = new DashboardWorker();
|
|
12
|
+
function forward(target) {
|
|
13
|
+
const listen = (event) => {
|
|
19
14
|
try {
|
|
20
|
-
|
|
15
|
+
target.postMessage({ ...event, type: event.type });
|
|
21
16
|
} catch {
|
|
22
17
|
worker.removeEventListener(IndexEvent.type, listen);
|
|
23
18
|
worker.removeEventListener(ActivityEvent.type, listen);
|
|
@@ -25,7 +20,19 @@ async function loadWorker(gen) {
|
|
|
25
20
|
};
|
|
26
21
|
worker.addEventListener(IndexEvent.type, listen);
|
|
27
22
|
worker.addEventListener(ActivityEvent.type, listen);
|
|
28
|
-
}
|
|
23
|
+
}
|
|
24
|
+
if ("onconnect" in globalThis) {
|
|
25
|
+
addEventListener("connect", (event) => {
|
|
26
|
+
if (!(event instanceof MessageEvent)) return;
|
|
27
|
+
console.info("Worker connected");
|
|
28
|
+
const port = event.ports[0];
|
|
29
|
+
expose(worker, port);
|
|
30
|
+
forward(port);
|
|
31
|
+
});
|
|
32
|
+
} else {
|
|
33
|
+
expose(worker, globalThis);
|
|
34
|
+
forward(globalThis);
|
|
35
|
+
}
|
|
29
36
|
for await (const batch of gen) {
|
|
30
37
|
await worker.load(batch.configFingerprint, batch.config, batch.client);
|
|
31
38
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
unwrap
|
|
3
|
-
} from "../../chunks/chunk-
|
|
3
|
+
} from "../../chunks/chunk-G43W7AME.js";
|
|
4
4
|
import {
|
|
5
5
|
useAtomValueRaw,
|
|
6
6
|
useAtomValueRawSync,
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
import { Schema } from "alinea/core/Schema";
|
|
38
38
|
import { getScope } from "alinea/core/Scope";
|
|
39
39
|
import { Type } from "alinea/core/Type";
|
|
40
|
+
import { EntryStatusIcon, entryStatus } from "../app/EntryStatusIcon.js";
|
|
40
41
|
import {
|
|
41
42
|
OverviewCell,
|
|
42
43
|
overviewCellText,
|
|
@@ -65,9 +66,9 @@ import {
|
|
|
65
66
|
var EntryTable_default = {
|
|
66
67
|
"EntryTable-loading": "alinea-EntryTable-loading",
|
|
67
68
|
"EntryTableLoading": "alinea-EntryTable-loading",
|
|
69
|
+
"EntryTable": "alinea-EntryTable",
|
|
68
70
|
"EntryTable-table": "alinea-EntryTable-table",
|
|
69
|
-
"EntryTableTable": "alinea-EntryTable-table"
|
|
70
|
-
"EntryTable": "alinea-EntryTable"
|
|
71
|
+
"EntryTableTable": "alinea-EntryTable-table"
|
|
71
72
|
};
|
|
72
73
|
|
|
73
74
|
// src/dashboard/cms/EntryTable.tsx
|
|
@@ -234,17 +235,19 @@ function EntryTableRow({ config, overview, row }) {
|
|
|
234
235
|
const texts = overview.columns.map(
|
|
235
236
|
(column) => overviewCellText(config, column, row, links)
|
|
236
237
|
);
|
|
238
|
+
const status = entryStatus(row);
|
|
237
239
|
return /* @__PURE__ */ jsxs(
|
|
238
240
|
TableRow,
|
|
239
241
|
{
|
|
240
242
|
id: row.id,
|
|
241
|
-
textValue: [row.title, ...texts].filter(Boolean).join(" "),
|
|
243
|
+
textValue: [row.title, status?.label, ...texts].filter(Boolean).join(" "),
|
|
242
244
|
children: [
|
|
243
245
|
/* @__PURE__ */ jsx(
|
|
244
246
|
TableTitle,
|
|
245
247
|
{
|
|
246
248
|
icon: type && getType(type).icon || LucideFile,
|
|
247
|
-
title: row.title
|
|
249
|
+
title: row.title,
|
|
250
|
+
suffix: status && /* @__PURE__ */ jsx(EntryStatusIcon, { status })
|
|
248
251
|
}
|
|
249
252
|
),
|
|
250
253
|
overview.columns.map((column, index) => /* @__PURE__ */ jsx(
|
|
@@ -1,84 +1,34 @@
|
|
|
1
1
|
import type { Config } from 'alinea/core/Config';
|
|
2
|
-
import type { Mutation } from 'alinea/core/db/Mutation';
|
|
3
|
-
import type { CommitRequest } from 'alinea/core/db/CommitRequest';
|
|
4
2
|
import type { SyncOptions } from 'alinea/core/db/LocalStore';
|
|
5
3
|
import type { RemoteSource } from 'alinea/core/source/Source';
|
|
4
|
+
import { type SnapshotStorage } from '@alinea/sqlite-wasm/snapshots';
|
|
6
5
|
import { EntryStore } from './EntryStore.js';
|
|
7
6
|
export interface BrowserEntryStoreOptions {
|
|
8
7
|
name: string;
|
|
9
|
-
|
|
8
|
+
/** Stores of one config fingerprint open the bases it wrote. */
|
|
9
|
+
fingerprint: string;
|
|
10
|
+
/** Where bases are kept, Blobs in IndexedDB by default. */
|
|
11
|
+
storage?: SnapshotStorage;
|
|
10
12
|
/**
|
|
11
|
-
* Start over from an empty database instead of
|
|
13
|
+
* Start over from an empty database instead of a stored base, such as
|
|
12
14
|
* when it turned out to be corrupt.
|
|
13
15
|
*/
|
|
14
16
|
reset?: boolean;
|
|
15
|
-
/** The IndexedDB implementation, the global one by default. */
|
|
16
|
-
indexedDB?: IDBFactory;
|
|
17
|
-
IDBKeyRange?: typeof IDBKeyRange;
|
|
18
|
-
/** The Web Locks implementation, the global one by default. */
|
|
19
|
-
locks?: CacheLocks;
|
|
20
|
-
}
|
|
21
|
-
/** The part of the Web Locks API that keeps a cache to one worker. */
|
|
22
|
-
export interface CacheLocks {
|
|
23
|
-
request(name: string, options: {
|
|
24
|
-
ifAvailable?: boolean;
|
|
25
|
-
signal?: AbortSignal;
|
|
26
|
-
}, callback: (lock: Lock | null) => Promise<void> | void): Promise<unknown>;
|
|
27
|
-
}
|
|
28
|
-
export interface HoldCacheOptions {
|
|
29
|
-
/**
|
|
30
|
-
* How long to wait, in milliseconds, for another worker that holds the
|
|
31
|
-
* cache to end: none by default, Infinity until it does.
|
|
32
|
-
*/
|
|
33
|
-
wait?: number;
|
|
34
|
-
/** The Web Locks implementation, the global one by default. */
|
|
35
|
-
locks?: CacheLocks;
|
|
36
17
|
}
|
|
37
18
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*/
|
|
44
|
-
export declare function holdCache(name: string, options?: HoldCacheOptions): Promise<boolean>;
|
|
45
|
-
/**
|
|
46
|
-
* WASM entry store kept in IndexedDB: every commit stores the pages it
|
|
47
|
-
* changed.
|
|
19
|
+
* WASM entry store on a copy-on-write overlay over the newest stored base:
|
|
20
|
+
* it reads pages from the base as queries need them, and keeps its changes
|
|
21
|
+
* in memory. Every sync stores them as a new base in the background, which
|
|
22
|
+
* the next store opens; the stored bases never change, so stores of any
|
|
23
|
+
* number of workers and dashboard builds can use them at once.
|
|
48
24
|
*/
|
|
49
25
|
export declare class BrowserEntryStore extends EntryStore {
|
|
50
26
|
#private;
|
|
51
|
-
/**
|
|
52
|
-
* Open the store kept in IndexedDB. Only the worker that holds the cache
|
|
53
|
-
* opens it (see `holdCache`), and deletes the caches of other versions.
|
|
54
|
-
*/
|
|
55
27
|
static open(config: Config, options: BrowserEntryStoreOptions): Promise<BrowserEntryStore>;
|
|
56
|
-
/**
|
|
57
|
-
* A copy in memory of the stored content, for a worker that cannot store
|
|
58
|
-
* it while another one does: it loads the last committed state and never
|
|
59
|
-
* writes. Resolves with undefined if that state cannot be read.
|
|
60
|
-
*/
|
|
61
|
-
static snapshot(config: Config, options: BrowserEntryStoreOptions): Promise<EntryStore | undefined>;
|
|
62
28
|
private constructor();
|
|
63
|
-
/**
|
|
64
|
-
* Opening, and syncing, resolve once the content is in memory: storing it
|
|
65
|
-
* is a cache that finishes in the background, which takes seconds for a
|
|
66
|
-
* first sync or a rebuild of a large project.
|
|
67
|
-
*/
|
|
68
29
|
sync(): Promise<string>;
|
|
69
30
|
syncWith(remote: RemoteSource, options?: SyncOptions): Promise<string>;
|
|
70
|
-
|
|
71
|
-
sha: string;
|
|
72
|
-
}>;
|
|
73
|
-
write(request: CommitRequest): Promise<{
|
|
74
|
-
sha: string;
|
|
75
|
-
}>;
|
|
76
|
-
/**
|
|
77
|
-
* Stop storing, and resolve once the commits so far are stored, for a
|
|
78
|
-
* replacement to open the cache. Work in flight then changes only this
|
|
79
|
-
* store's memory, so the replacement need not wait for it.
|
|
80
|
-
*/
|
|
81
|
-
release(): Promise<void>;
|
|
31
|
+
/** Close once the last checkpoint is stored. */
|
|
82
32
|
close(): Promise<void>;
|
|
83
33
|
}
|
|
84
34
|
/** Whether an error, or one it holds, reports a damaged SQLite database. */
|
|
@@ -5,196 +5,105 @@ import "../chunks/chunk-CQ52GEHY.js";
|
|
|
5
5
|
|
|
6
6
|
// src/database/BrowserEntryStore.ts
|
|
7
7
|
import { ReadonlyTree } from "alinea/core/source/Tree";
|
|
8
|
-
import { TaskQueue } from "alinea/core/util/Async";
|
|
9
8
|
import { isRecord } from "alinea/core/util/Objects";
|
|
10
9
|
import {
|
|
11
|
-
|
|
12
|
-
} from "@alinea/sqlite-wasm/
|
|
13
|
-
import { versionedCacheName } from "./Version.js";
|
|
10
|
+
indexedDBSnapshots
|
|
11
|
+
} from "@alinea/sqlite-wasm/snapshots";
|
|
12
|
+
import { databaseVersion, versionedCacheName } from "./Version.js";
|
|
14
13
|
import { EntryDatabase } from "./EntryDatabase.js";
|
|
15
14
|
import { EntryStore } from "./EntryStore.js";
|
|
16
15
|
import { DatabaseSource } from "./DatabaseSource.js";
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
var buildTable = sql.identifier("alinea_dashboard_build");
|
|
21
|
-
function holdCache(name, options = {}) {
|
|
22
|
-
const locks = options.locks ?? globalThis.navigator?.locks;
|
|
23
|
-
if (!locks) return Promise.resolve(false);
|
|
24
|
-
const { wait = 0 } = options;
|
|
25
|
-
const timeout = wait > 0 && wait < Infinity ? new AbortController() : void 0;
|
|
26
|
-
const timer = timeout && setTimeout(() => timeout.abort(), wait);
|
|
27
|
-
const request = wait === 0 ? { ifAvailable: true } : timeout ? { signal: timeout.signal } : {};
|
|
28
|
-
return new Promise((resolve) => {
|
|
29
|
-
try {
|
|
30
|
-
locks.request(storageNameOf(name), request, (lock) => {
|
|
31
|
-
clearTimeout(timer);
|
|
32
|
-
resolve(Boolean(lock));
|
|
33
|
-
if (lock) return new Promise(() => {
|
|
34
|
-
});
|
|
35
|
-
}).catch(() => resolve(false));
|
|
36
|
-
} catch {
|
|
37
|
-
resolve(false);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
16
|
+
import { wasmHandle, wasmSqlite } from "./driver/WasmDatabase.js";
|
|
17
|
+
var cacheSize = -65536;
|
|
18
|
+
var keepBranches = 2;
|
|
41
19
|
var BrowserEntryStore = class _BrowserEntryStore extends EntryStore {
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
|
|
47
|
-
* Open the store kept in IndexedDB. Only the worker that holds the cache
|
|
48
|
-
* opens it (see `holdCache`), and deletes the caches of other versions.
|
|
49
|
-
*/
|
|
20
|
+
#session;
|
|
21
|
+
#storage;
|
|
22
|
+
#stored;
|
|
23
|
+
#written = Promise.resolve();
|
|
24
|
+
#cleanup = Promise.resolve();
|
|
50
25
|
static async open(config, options) {
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
currentName: storageName
|
|
26
|
+
const { name, fingerprint } = options;
|
|
27
|
+
const storage = options.storage ?? indexedDBSnapshots(`${versionedCacheName(name)}-snapshots`);
|
|
28
|
+
const cleanup = !options.storage && globalThis.indexedDB ? cleanupOldCaches(indexedDB, name).catch(() => {
|
|
29
|
+
}) : Promise.resolve();
|
|
30
|
+
const Database = await wasmSqlite();
|
|
31
|
+
const session = options.reset ? storage.session(new Database(), { branch: fingerprint }) : await openBase(storage, Database, fingerprint);
|
|
32
|
+
const store = await _BrowserEntryStore.#on(
|
|
33
|
+
config,
|
|
34
|
+
session,
|
|
35
|
+
storage,
|
|
36
|
+
fingerprint
|
|
37
|
+
).catch((error) => {
|
|
38
|
+
if (!session.snapshot) throw error;
|
|
39
|
+
return _BrowserEntryStore.#on(
|
|
40
|
+
config,
|
|
41
|
+
storage.session(new Database(), { branch: fingerprint }),
|
|
42
|
+
storage,
|
|
43
|
+
fingerprint
|
|
44
|
+
);
|
|
71
45
|
});
|
|
46
|
+
store.#cleanup = cleanup;
|
|
72
47
|
return store;
|
|
73
48
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
});
|
|
84
|
-
let handle;
|
|
85
|
-
try {
|
|
86
|
-
handle = await syncWasmDatabase(storage);
|
|
87
|
-
handle.detach();
|
|
88
|
-
const db = handle.database;
|
|
89
|
-
const stored = await storedBuild(db);
|
|
90
|
-
if (stored === void 0) {
|
|
91
|
-
await db.close();
|
|
92
|
-
return void 0;
|
|
93
|
-
}
|
|
94
|
-
await EntryDatabase.createSchema(db, config, ReadonlyTree.EMPTY.sha);
|
|
95
|
-
const database = new EntryDatabase(config, db, { fork: handle.fork });
|
|
96
|
-
if (stored !== options.revision) await database.reindex(config);
|
|
97
|
-
return new EntryStore(config, database, new DatabaseSource(database), {
|
|
98
|
-
ownsDatabase: true,
|
|
99
|
-
sourceFollowsDatabase: true
|
|
100
|
-
});
|
|
101
|
-
} catch (error) {
|
|
102
|
-
if (handle) await handle.database.close();
|
|
103
|
-
console.warn("Failed to read the content cache", error);
|
|
104
|
-
return void 0;
|
|
49
|
+
static async #on(config, session, storage, fingerprint) {
|
|
50
|
+
const sqlite = session.db;
|
|
51
|
+
const branch = session.snapshot?.branch;
|
|
52
|
+
sqlite.run(`pragma cache_size = ${cacheSize}`);
|
|
53
|
+
const { database: db, fork } = wasmHandle(sqlite);
|
|
54
|
+
async function preview() {
|
|
55
|
+
const copy = await fork();
|
|
56
|
+
await copy.database.run(sql`pragma cache_size = -8192`);
|
|
57
|
+
return copy;
|
|
105
58
|
}
|
|
106
|
-
}
|
|
107
|
-
static async #openStorage(config, options, storage) {
|
|
108
|
-
const handle = await syncWasmDatabase(storage);
|
|
109
59
|
try {
|
|
110
|
-
|
|
111
|
-
await db.run(sql`pragma page_size = 65536`);
|
|
112
|
-
const stored = await storedBuild(db);
|
|
60
|
+
await db.run(sql`pragma page_size = 16384`);
|
|
113
61
|
await EntryDatabase.createSchema(db, config, ReadonlyTree.EMPTY.sha);
|
|
114
|
-
const database = new EntryDatabase(config, db, { fork:
|
|
115
|
-
if (
|
|
116
|
-
await database.reindex(config);
|
|
117
|
-
|
|
118
|
-
await db.run(
|
|
119
|
-
sql`insert or replace into ${buildTable} (id, revision)
|
|
120
|
-
values (1, ${options.revision})`
|
|
121
|
-
);
|
|
122
|
-
return new _BrowserEntryStore(config, database, handle);
|
|
62
|
+
const database = new EntryDatabase(config, db, { fork: preview });
|
|
63
|
+
if (branch !== void 0 && branch !== fingerprint)
|
|
64
|
+
await withoutJournal(sqlite, () => database.reindex(config));
|
|
65
|
+
return new _BrowserEntryStore(config, database, session, storage);
|
|
123
66
|
} catch (error) {
|
|
124
|
-
await
|
|
67
|
+
await db.close();
|
|
125
68
|
throw error;
|
|
126
69
|
}
|
|
127
70
|
}
|
|
128
|
-
|
|
129
|
-
if (this.#detached) return;
|
|
130
|
-
this.#detached = true;
|
|
131
|
-
this.#handle.detach();
|
|
132
|
-
}
|
|
133
|
-
constructor(config, database, handle) {
|
|
71
|
+
constructor(config, database, session, storage) {
|
|
134
72
|
super(config, database, new DatabaseSource(database), {
|
|
135
73
|
ownsDatabase: true,
|
|
136
74
|
sourceFollowsDatabase: true
|
|
137
75
|
});
|
|
138
|
-
this.#
|
|
76
|
+
this.#session = session;
|
|
77
|
+
this.#storage = storage;
|
|
139
78
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
* is a cache that finishes in the background, which takes seconds for a
|
|
143
|
-
* first sync or a rebuild of a large project.
|
|
144
|
-
*/
|
|
145
|
-
sync() {
|
|
146
|
-
return this.#run(() => super.sync());
|
|
79
|
+
async sync() {
|
|
80
|
+
return this.#checkpoint(await super.sync());
|
|
147
81
|
}
|
|
148
|
-
syncWith(remote, options) {
|
|
149
|
-
return this.#
|
|
82
|
+
async syncWith(remote, options) {
|
|
83
|
+
return this.#checkpoint(await super.syncWith(remote, options));
|
|
150
84
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Wait for the commits so far to be stored. The cache only saves loading
|
|
167
|
-
* time: if storing fails, such as over quota, it stops instead of failing
|
|
168
|
-
* the commit, and keeps the last committed state it stored.
|
|
169
|
-
*/
|
|
170
|
-
async #store() {
|
|
171
|
-
if (this.#detached) return;
|
|
172
|
-
try {
|
|
173
|
-
await this.#handle.flush();
|
|
174
|
-
} catch (error) {
|
|
175
|
-
console.warn("Stopped caching content in IndexedDB", error);
|
|
176
|
-
this.#detach();
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Stop storing, and resolve once the commits so far are stored, for a
|
|
181
|
-
* replacement to open the cache. Work in flight then changes only this
|
|
182
|
-
* store's memory, so the replacement need not wait for it.
|
|
183
|
-
*/
|
|
184
|
-
async release() {
|
|
185
|
-
this.#detach();
|
|
186
|
-
await this.#handle.flush().catch(() => {
|
|
85
|
+
/** Store the content at `revision` as a base, in the background. */
|
|
86
|
+
#checkpoint(revision) {
|
|
87
|
+
if (!this.#storage.supported() || this.#stored === revision) return revision;
|
|
88
|
+
this.#stored = revision;
|
|
89
|
+
const session = this.#session;
|
|
90
|
+
const storage = this.#storage;
|
|
91
|
+
const key = `${revision}-${session.branch}`;
|
|
92
|
+
const save = (key2) => this.database.whileIdle(async () => ({
|
|
93
|
+
saved: session.held ? session.save({ key: key2, meta: { tree: revision } }) : void 0
|
|
94
|
+
})).then(({ saved }) => saved);
|
|
95
|
+
const written = save(key).then(
|
|
96
|
+
(result) => result?.status === "mismatch" ? save(`${key}-${crypto.randomUUID()}`) : result
|
|
97
|
+
).then(() => storage.retain({ branches: keepBranches })).catch(() => {
|
|
98
|
+
if (this.#stored === revision) this.#stored = void 0;
|
|
187
99
|
});
|
|
100
|
+
this.#written = Promise.all([this.#written, written]);
|
|
101
|
+
return revision;
|
|
188
102
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
close() {
|
|
195
|
-
if (this.#closed) return this.#persistQueue.drain();
|
|
196
|
-
this.#closed = true;
|
|
197
|
-
return this.#persistQueue.run(() => super.close());
|
|
103
|
+
/** Close once the last checkpoint is stored. */
|
|
104
|
+
async close() {
|
|
105
|
+
await Promise.all([this.#cleanup, this.#written]);
|
|
106
|
+
await super.close();
|
|
198
107
|
}
|
|
199
108
|
};
|
|
200
109
|
var corruptCodes = /* @__PURE__ */ new Set(["SQLITE_CORRUPT", "SQLITE_NOTADB"]);
|
|
@@ -208,43 +117,36 @@ function isCorruptDatabaseError(error) {
|
|
|
208
117
|
const errors = Array.isArray(error.errors) ? error.errors : [];
|
|
209
118
|
return isCorruptDatabaseError(error.cause) || errors.some(isCorruptDatabaseError);
|
|
210
119
|
}
|
|
211
|
-
function
|
|
212
|
-
|
|
120
|
+
async function withoutJournal(sqlite, task) {
|
|
121
|
+
const [[mode]] = sqlite.exec("pragma journal_mode")[0].values;
|
|
122
|
+
sqlite.run("pragma journal_mode = off");
|
|
123
|
+
try {
|
|
124
|
+
return await task();
|
|
125
|
+
} finally {
|
|
126
|
+
sqlite.run(`pragma journal_mode = ${mode}`);
|
|
127
|
+
}
|
|
213
128
|
}
|
|
214
|
-
async function
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
);
|
|
222
|
-
if (row) return row.revision;
|
|
223
|
-
const entries = await db.get(
|
|
224
|
-
sql`select count(*) as count from sqlite_master
|
|
225
|
-
where type = 'table' and name = 'alinea_entry_index'`
|
|
226
|
-
);
|
|
227
|
-
return entries?.count ? "" : void 0;
|
|
129
|
+
async function openBase(storage, Database, fingerprint) {
|
|
130
|
+
const empty = () => storage.session(new Database(), { branch: fingerprint });
|
|
131
|
+
if (!storage.supported()) return empty();
|
|
132
|
+
return storage.open(Database, {
|
|
133
|
+
branch: fingerprint,
|
|
134
|
+
choose: (bases) => bases.find((base) => base.branch === fingerprint) ?? bases[0]
|
|
135
|
+
}).catch(empty);
|
|
228
136
|
}
|
|
229
|
-
async function cleanupOldCaches({
|
|
230
|
-
factory,
|
|
231
|
-
locks,
|
|
232
|
-
baseName,
|
|
233
|
-
currentName
|
|
234
|
-
}) {
|
|
137
|
+
async function cleanupOldCaches(factory, name) {
|
|
235
138
|
if (!factory.databases) return;
|
|
236
139
|
const databases = await factory.databases().catch(() => []);
|
|
237
|
-
const
|
|
238
|
-
(database) => database.name &&
|
|
140
|
+
const stale = databases.flatMap(
|
|
141
|
+
(database) => database.name && isStale(database.name, name) ? [database.name] : []
|
|
239
142
|
);
|
|
240
|
-
await Promise.all(
|
|
143
|
+
await Promise.all(stale.map((cache) => deleteCache(factory, cache)));
|
|
241
144
|
}
|
|
242
|
-
|
|
243
|
-
if (
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
});
|
|
145
|
+
function isStale(cache, name) {
|
|
146
|
+
if (cache === name || cache === `${versionedCacheName(name)}-pages`)
|
|
147
|
+
return true;
|
|
148
|
+
if (!cache.startsWith(`${name}-v`)) return false;
|
|
149
|
+
return Number.parseInt(cache.slice(name.length + 2)) < databaseVersion;
|
|
248
150
|
}
|
|
249
151
|
function deleteCache(factory, name) {
|
|
250
152
|
return new Promise((resolve) => {
|
|
@@ -256,6 +158,5 @@ function deleteCache(factory, name) {
|
|
|
256
158
|
}
|
|
257
159
|
export {
|
|
258
160
|
BrowserEntryStore,
|
|
259
|
-
holdCache,
|
|
260
161
|
isCorruptDatabaseError
|
|
261
162
|
};
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
number,
|
|
5
5
|
text,
|
|
6
6
|
varchar
|
|
7
|
-
} from "../chunks/chunk-
|
|
7
|
+
} from "../chunks/chunk-5H4D5JQL.js";
|
|
8
8
|
import {
|
|
9
9
|
table
|
|
10
|
-
} from "../chunks/chunk-
|
|
10
|
+
} from "../chunks/chunk-PYDOMKJZ.js";
|
|
11
11
|
import "../chunks/chunk-76VMZTLN.js";
|
|
12
12
|
import "../chunks/chunk-2PIFHEYR.js";
|
|
13
13
|
import "../chunks/chunk-K62JP6HR.js";
|