sh3-core 0.20.1 → 0.20.3
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/BrandSlot.svelte +2 -2
- package/dist/actions/ctx-actions.svelte.test.js +2 -2
- package/dist/artifact.d.ts +2 -0
- package/dist/boot/satellitePayload.d.ts +2 -0
- package/dist/boot/satellitePayload.test.js +19 -0
- package/dist/build.d.ts +7 -1
- package/dist/build.js +22 -3
- package/dist/build.test.js +27 -1
- package/dist/createShell.js +34 -9
- package/dist/documents/backends.d.ts +12 -0
- package/dist/documents/backends.js +230 -3
- package/dist/documents/backends.test.js +147 -1
- package/dist/documents/browse.d.ts +20 -0
- package/dist/documents/browse.js +35 -0
- package/dist/documents/browse.test.js +125 -0
- package/dist/documents/config.d.ts +2 -4
- package/dist/documents/config.js +3 -7
- package/dist/documents/handle.js +40 -0
- package/dist/documents/handle.test.js +88 -1
- package/dist/documents/http-backend.d.ts +11 -0
- package/dist/documents/http-backend.js +86 -0
- package/dist/documents/http-backend.test.js +117 -1
- package/dist/documents/index.d.ts +1 -1
- package/dist/documents/index.js +1 -1
- package/dist/documents/picker-api.test.js +2 -2
- package/dist/documents/types.d.ts +87 -14
- package/dist/documents/types.js +4 -0
- package/dist/host-entry.d.ts +1 -1
- package/dist/host-entry.js +1 -1
- package/dist/host.d.ts +1 -1
- package/dist/host.js +1 -1
- package/dist/layout/slotHostPool.svelte.js +2 -2
- package/dist/overlays/FloatFrame.svelte +1 -0
- package/dist/primitives/widgets/DocumentFilePicker.d.ts +6 -2
- package/dist/primitives/widgets/DocumentFilePicker.js +12 -5
- package/dist/primitives/widgets/DocumentFilePicker.svelte +23 -1
- package/dist/primitives/widgets/DocumentFilePicker.svelte.d.ts +14 -0
- package/dist/primitives/widgets/DocumentFilePicker.test.d.ts +1 -0
- package/dist/primitives/widgets/DocumentFilePicker.test.js +33 -0
- package/dist/primitives/widgets/DocumentOpener.svelte +20 -0
- package/dist/primitives/widgets/DocumentOpener.svelte.d.ts +14 -0
- package/dist/primitives/widgets/DocumentSaver.svelte +17 -0
- package/dist/primitives/widgets/DocumentSaver.svelte.d.ts +13 -0
- package/dist/primitives/widgets/_DocumentBrowser.svelte +414 -27
- package/dist/primitives/widgets/_DocumentBrowser.svelte.d.ts +12 -0
- package/dist/primitives/widgets/_DocumentBrowser.svelte.test.d.ts +1 -0
- package/dist/primitives/widgets/_DocumentBrowser.svelte.test.js +277 -0
- package/dist/primitives/widgets/_FolderConfirmDelete.svelte +57 -0
- package/dist/primitives/widgets/_FolderConfirmDelete.svelte.d.ts +12 -0
- package/dist/projects/session-state.svelte.d.ts +3 -0
- package/dist/projects/session-state.svelte.js +25 -0
- package/dist/projects/session-state.test.js +43 -2
- package/dist/projects-shard/ProjectsSection.svelte +14 -18
- package/dist/runtime/runVerb-shell.test.js +2 -2
- package/dist/runtime/runVerb.test.js +2 -2
- package/dist/sh3Api/headless.js +10 -0
- package/dist/sh3core-shard/appActions.js +5 -2
- package/dist/shards/activate-browse.test.js +2 -2
- package/dist/shards/activate-contributions.test.js +2 -2
- package/dist/shards/activate-error-isolation.test.js +3 -3
- package/dist/shards/activate-on-key-revoked.test.js +2 -2
- package/dist/shards/activate-runtime.test.js +2 -2
- package/dist/shards/activate.svelte.js +5 -5
- package/dist/shards/ctx-fetch.test.js +4 -4
- package/dist/shell-shard/Terminal.svelte +4 -1
- package/dist/shell-shard/Terminal.svelte.d.ts +2 -0
- package/dist/shell-shard/dispatch.d.ts +2 -0
- package/dist/shell-shard/dispatch.js +2 -0
- package/dist/shell-shard/manifest.js +7 -1
- package/dist/shell-shard/shellShard.svelte.js +1 -1
- package/dist/shell-shard/verbs/cat.d.ts +2 -0
- package/dist/shell-shard/verbs/cat.js +35 -0
- package/dist/shell-shard/verbs/cat.test.d.ts +1 -0
- package/dist/shell-shard/verbs/cat.test.js +49 -0
- package/dist/shell-shard/verbs/index.js +12 -0
- package/dist/shell-shard/verbs/ls.d.ts +2 -0
- package/dist/shell-shard/verbs/ls.js +48 -0
- package/dist/shell-shard/verbs/ls.test.d.ts +1 -0
- package/dist/shell-shard/verbs/ls.test.js +64 -0
- package/dist/shell-shard/verbs/mkdir.d.ts +2 -0
- package/dist/shell-shard/verbs/mkdir.js +30 -0
- package/dist/shell-shard/verbs/mkdir.test.d.ts +1 -0
- package/dist/shell-shard/verbs/mkdir.test.js +48 -0
- package/dist/shell-shard/verbs/mv.d.ts +2 -0
- package/dist/shell-shard/verbs/mv.js +33 -0
- package/dist/shell-shard/verbs/mv.test.d.ts +1 -0
- package/dist/shell-shard/verbs/mv.test.js +55 -0
- package/dist/shell-shard/verbs/rm.d.ts +2 -0
- package/dist/shell-shard/verbs/rm.js +28 -0
- package/dist/shell-shard/verbs/rm.test.d.ts +1 -0
- package/dist/shell-shard/verbs/rm.test.js +47 -0
- package/dist/shell-shard/verbs/scope-parse.d.ts +7 -0
- package/dist/shell-shard/verbs/scope-parse.js +33 -0
- package/dist/shell-shard/verbs/scope-parse.test.d.ts +1 -0
- package/dist/shell-shard/verbs/scope-parse.test.js +76 -0
- package/dist/shell-shard/verbs/xfer.d.ts +2 -0
- package/dist/shell-shard/verbs/xfer.js +87 -0
- package/dist/shell-shard/verbs/xfer.test.d.ts +1 -0
- package/dist/shell-shard/verbs/xfer.test.js +107 -0
- package/dist/verbs/types.d.ts +18 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/BrandSlot.svelte
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { getLiveDispatcherState } from './actions/state.svelte';
|
|
14
14
|
import { launchApp, returnToHome } from './apps/lifecycle';
|
|
15
15
|
import { getBreadcrumbAppId, getRegisteredApp } from './apps/registry.svelte';
|
|
16
|
-
import { sessionState,
|
|
16
|
+
import { sessionState, switchProjectScope } from './projects/session-state.svelte';
|
|
17
17
|
import { projectsState } from './projects-shard/projectsShard.svelte';
|
|
18
18
|
|
|
19
19
|
const activeAppId = $derived(getLiveDispatcherState().activeAppId);
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
function exitProject() {
|
|
51
|
-
|
|
51
|
+
switchProjectScope(null);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
function reenterProjectHome() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
2
|
import { MemoryDocumentBackend } from '../documents/backends';
|
|
3
|
-
import { __setDocumentBackend,
|
|
3
|
+
import { __setDocumentBackend, __setActiveScope } from '../documents/config';
|
|
4
4
|
import { registerShard, activateShard, __resetShardRegistryForTest, } from '../shards/activate.svelte';
|
|
5
5
|
import { __resetViewRegistryForTest } from '../shards/registry';
|
|
6
6
|
import { __resetActionsRegistryForTest } from './registry';
|
|
@@ -14,7 +14,7 @@ describe('ShardContext.listActions / runAction (integration)', () => {
|
|
|
14
14
|
__resetActionsRegistryForTest();
|
|
15
15
|
__resetDispatcherStateForTest();
|
|
16
16
|
__setDocumentBackend(new MemoryDocumentBackend());
|
|
17
|
-
|
|
17
|
+
__setActiveScope('tenant-test');
|
|
18
18
|
});
|
|
19
19
|
it('listActions enumerates actions registered by other shards', async () => {
|
|
20
20
|
registerShard({
|
package/dist/artifact.d.ts
CHANGED
|
@@ -8,10 +8,12 @@ export type SatellitePayload = {
|
|
|
8
8
|
h: number;
|
|
9
9
|
};
|
|
10
10
|
activateShards: string[];
|
|
11
|
+
projectId?: string;
|
|
11
12
|
} | {
|
|
12
13
|
kind: 'app';
|
|
13
14
|
appId: string;
|
|
14
15
|
activateShards: string[];
|
|
16
|
+
projectId?: string;
|
|
15
17
|
};
|
|
16
18
|
export declare function encodePayload(payload: SatellitePayload): string;
|
|
17
19
|
export declare function decodePayload(encoded: string): SatellitePayload;
|
|
@@ -36,6 +36,25 @@ describe('satellite payload encode/decode', () => {
|
|
|
36
36
|
const bad = btoa(JSON.stringify({ kind: 'mystery' }));
|
|
37
37
|
expect(() => decodePayload(bad)).toThrow();
|
|
38
38
|
});
|
|
39
|
+
it('round-trips a float payload with projectId', () => {
|
|
40
|
+
const payload = {
|
|
41
|
+
kind: 'float',
|
|
42
|
+
content: { type: 'slot', slotId: 's:1', viewId: 'foo:bar' },
|
|
43
|
+
size: { w: 800, h: 600 },
|
|
44
|
+
activateShards: ['foo'],
|
|
45
|
+
projectId: 'proj-abc',
|
|
46
|
+
};
|
|
47
|
+
expect(decodePayload(encodePayload(payload))).toEqual(payload);
|
|
48
|
+
});
|
|
49
|
+
it('round-trips an app payload with projectId', () => {
|
|
50
|
+
const payload = {
|
|
51
|
+
kind: 'app',
|
|
52
|
+
appId: 'sh3-store',
|
|
53
|
+
activateShards: ['sh3-core'],
|
|
54
|
+
projectId: 'proj-xyz',
|
|
55
|
+
};
|
|
56
|
+
expect(decodePayload(encodePayload(payload))).toEqual(payload);
|
|
57
|
+
});
|
|
39
58
|
it('produces a URL-safe encoding (no + / =)', () => {
|
|
40
59
|
// A long-ish payload increases the chance the underlying base64
|
|
41
60
|
// would contain non-URL-safe characters from the standard alphabet.
|
package/dist/build.d.ts
CHANGED
|
@@ -70,10 +70,16 @@ export declare function composeArtifactVersion(pkgVersion: string, suffix: strin
|
|
|
70
70
|
* After Vite's lib build completes, this plugin:
|
|
71
71
|
* 1. Finds the entry chunk and renames it to client.js
|
|
72
72
|
* 2. Optionally copies a pre-built server bundle as server.js
|
|
73
|
-
* 3. Extracts manifest fields (id, label, type) from the source
|
|
73
|
+
* 3. Extracts manifest fields (id, label, type, requiredShards) from the source
|
|
74
74
|
* 4. Reads `version` from `package.json.version` — the authoritative
|
|
75
75
|
* source per ADR-013. A literal `version:` in a source manifest is
|
|
76
76
|
* ignored; only `package.json.version` matters for the artifact.
|
|
77
77
|
* 5. Writes manifest.json alongside the bundles
|
|
78
78
|
*/
|
|
79
|
+
/**
|
|
80
|
+
* Extract the requiredShards array from a bundled source string.
|
|
81
|
+
* Finds the first `requiredShards: [...]` array literal and parses its string IDs.
|
|
82
|
+
* Exported for testing; used internally by sh3Artifact.
|
|
83
|
+
*/
|
|
84
|
+
export declare function extractRequiredShardsFromBundle(bundleSource: string): string[];
|
|
79
85
|
export declare function sh3Artifact(options?: Sh3ArtifactOptions): Plugin;
|
package/dist/build.js
CHANGED
|
@@ -136,12 +136,28 @@ function resolveAutoBuildSuffix() {
|
|
|
136
136
|
* After Vite's lib build completes, this plugin:
|
|
137
137
|
* 1. Finds the entry chunk and renames it to client.js
|
|
138
138
|
* 2. Optionally copies a pre-built server bundle as server.js
|
|
139
|
-
* 3. Extracts manifest fields (id, label, type) from the source
|
|
139
|
+
* 3. Extracts manifest fields (id, label, type, requiredShards) from the source
|
|
140
140
|
* 4. Reads `version` from `package.json.version` — the authoritative
|
|
141
141
|
* source per ADR-013. A literal `version:` in a source manifest is
|
|
142
142
|
* ignored; only `package.json.version` matters for the artifact.
|
|
143
143
|
* 5. Writes manifest.json alongside the bundles
|
|
144
144
|
*/
|
|
145
|
+
/**
|
|
146
|
+
* Extract the requiredShards array from a bundled source string.
|
|
147
|
+
* Finds the first `requiredShards: [...]` array literal and parses its string IDs.
|
|
148
|
+
* Exported for testing; used internally by sh3Artifact.
|
|
149
|
+
*/
|
|
150
|
+
export function extractRequiredShardsFromBundle(bundleSource) {
|
|
151
|
+
const arrayMatch = bundleSource.match(/\brequiredShards\s*:\s*\[([^\]]*)\]/);
|
|
152
|
+
if (!arrayMatch)
|
|
153
|
+
return [];
|
|
154
|
+
const ids = [];
|
|
155
|
+
const idRe = /["']([^"']+)["']/g;
|
|
156
|
+
let m;
|
|
157
|
+
while ((m = idRe.exec(arrayMatch[1])) !== null)
|
|
158
|
+
ids.push(m[1]);
|
|
159
|
+
return ids;
|
|
160
|
+
}
|
|
145
161
|
export function sh3Artifact(options = {}) {
|
|
146
162
|
let outDir = '';
|
|
147
163
|
let entryFileName = '';
|
|
@@ -238,14 +254,17 @@ export function sh3Artifact(options = {}) {
|
|
|
238
254
|
const m = block.match(pattern);
|
|
239
255
|
return m ? m[1] : '';
|
|
240
256
|
};
|
|
257
|
+
// Extract the requiredShards string-id array from the app manifest block.
|
|
258
|
+
const requiredShards = extractRequiredShardsFromBundle(block);
|
|
241
259
|
return {
|
|
242
260
|
id: get(/\bid\s*:\s*["']([^"']+)["']/),
|
|
243
261
|
label: get(/\blabel\s*:\s*["']([^"']+)["']/),
|
|
262
|
+
requiredShards,
|
|
244
263
|
};
|
|
245
264
|
}
|
|
246
265
|
// App first, then Shard.
|
|
247
266
|
const extracted = (_a = extractFromBlock(/\brequiredShards\s*:\s*\[/)) !== null && _a !== void 0 ? _a : extractFromBlock(/\bviews\s*:\s*\[/);
|
|
248
|
-
const { id, label } = extracted;
|
|
267
|
+
const { id, label, requiredShards } = extracted;
|
|
249
268
|
// --- Optional server bundle ---
|
|
250
269
|
let hasServer = false;
|
|
251
270
|
if (options.serverEntry && existsSync(options.serverEntry)) {
|
|
@@ -292,7 +311,7 @@ export function sh3Artifact(options = {}) {
|
|
|
292
311
|
if (!finalAuthor) {
|
|
293
312
|
throw new Error('[sh3-artifact] Missing "author". Add it to package.json or pass it via sh3Artifact({ manifest: { author } }).');
|
|
294
313
|
}
|
|
295
|
-
const manifest = Object.assign(Object.assign(Object.assign({ id: id || 'unknown', type, label: label || id || 'unknown', version: artifactVersion, contractVersion: 1, client: 'client.js' }, (hasServer ? { server: 'server.js' } : {})), { description: finalDescription, author: finalAuthor }), overrides);
|
|
314
|
+
const manifest = Object.assign(Object.assign(Object.assign(Object.assign({ id: id || 'unknown', type, label: label || id || 'unknown', version: artifactVersion, contractVersion: 1, client: 'client.js' }, (hasServer ? { server: 'server.js' } : {})), { description: finalDescription, author: finalAuthor }), ((type === 'app' || type === 'combo') ? { requiredShards } : {})), overrides);
|
|
296
315
|
writeFileSync(join(outDir, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\n');
|
|
297
316
|
// --- Log summary ---
|
|
298
317
|
const files = ['manifest.json', 'client.js'];
|
package/dist/build.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { composeArtifactVersion } from './build';
|
|
2
|
+
import { composeArtifactVersion, extractRequiredShardsFromBundle } from './build';
|
|
3
3
|
describe('composeArtifactVersion', () => {
|
|
4
4
|
it('returns pkgVersion unchanged when suffix is undefined', () => {
|
|
5
5
|
expect(composeArtifactVersion('1.2.3', undefined)).toBe('1.2.3');
|
|
@@ -29,3 +29,29 @@ describe('composeArtifactVersion', () => {
|
|
|
29
29
|
expect(() => composeArtifactVersion('1.2.3', '+42')).toThrow(/not a valid semver build-metadata identifier/);
|
|
30
30
|
});
|
|
31
31
|
});
|
|
32
|
+
describe('extractRequiredShardsFromBundle', () => {
|
|
33
|
+
it('extracts a single shard id', () => {
|
|
34
|
+
const src = `const App = { manifest: { id: "my-app", requiredShards: ["guml.core"] } };`;
|
|
35
|
+
expect(extractRequiredShardsFromBundle(src)).toEqual(['guml.core']);
|
|
36
|
+
});
|
|
37
|
+
it('extracts multiple shard ids', () => {
|
|
38
|
+
const src = `requiredShards: ["guml.core", "sh3-file-explorer", "some-other"]`;
|
|
39
|
+
expect(extractRequiredShardsFromBundle(src)).toEqual(['guml.core', 'sh3-file-explorer', 'some-other']);
|
|
40
|
+
});
|
|
41
|
+
it('handles single-quoted ids', () => {
|
|
42
|
+
const src = `requiredShards: ['guml.core', 'sh3-files']`;
|
|
43
|
+
expect(extractRequiredShardsFromBundle(src)).toEqual(['guml.core', 'sh3-files']);
|
|
44
|
+
});
|
|
45
|
+
it('returns empty array when requiredShards is not present', () => {
|
|
46
|
+
const src = `const Shard = { manifest: { id: "my-shard", views: [] } };`;
|
|
47
|
+
expect(extractRequiredShardsFromBundle(src)).toEqual([]);
|
|
48
|
+
});
|
|
49
|
+
it('returns empty array when requiredShards is empty', () => {
|
|
50
|
+
const src = `requiredShards: []`;
|
|
51
|
+
expect(extractRequiredShardsFromBundle(src)).toEqual([]);
|
|
52
|
+
});
|
|
53
|
+
it('handles minified format without spaces', () => {
|
|
54
|
+
const src = `{id:"my-app",requiredShards:["guml.core","other-shard"]}`;
|
|
55
|
+
expect(extractRequiredShardsFromBundle(src)).toEqual(['guml.core', 'other-shard']);
|
|
56
|
+
});
|
|
57
|
+
});
|
package/dist/createShell.js
CHANGED
|
@@ -22,11 +22,33 @@ import { registerLoadedBundle } from './registry/register';
|
|
|
22
22
|
import { attachGlobalListeners } from './actions/listeners';
|
|
23
23
|
import { detectSatelliteMode } from './boot/satelliteMode';
|
|
24
24
|
import { MemoryBackend } from './state/backends';
|
|
25
|
-
import { sessionState } from './projects/session-state.svelte';
|
|
25
|
+
import { sessionState, readPendingScope, PENDING_SCOPE_KEY } from './projects/session-state.svelte';
|
|
26
26
|
import SatelliteShell from './satellite/SatelliteShell.svelte';
|
|
27
27
|
export async function createShell(config) {
|
|
28
28
|
var _a, _b;
|
|
29
29
|
const sUrl = (_a = config === null || config === void 0 ? void 0 : config.serverUrl) !== null && _a !== void 0 ? _a : '';
|
|
30
|
+
// 0. Restore pending project scope from a reload-triggered scope switch.
|
|
31
|
+
// Written before the previous page reload by switchProjectScope(); must
|
|
32
|
+
// be set before bootstrap() so shards activate with the correct scope.
|
|
33
|
+
const pendingProjectId = readPendingScope();
|
|
34
|
+
if (pendingProjectId !== null) {
|
|
35
|
+
sessionState.activeProjectId = pendingProjectId;
|
|
36
|
+
}
|
|
37
|
+
// Read ?project= injected by Tauri's --project CLI arg (or any deep-link URL).
|
|
38
|
+
// Guard against overriding an in-session scope switch that wrote to sessionStorage.
|
|
39
|
+
if (typeof window !== 'undefined' && pendingProjectId === null) {
|
|
40
|
+
const urlProject = new URLSearchParams(window.location.search).get('project');
|
|
41
|
+
if (urlProject) {
|
|
42
|
+
// Mirror switchProjectScope's sessionStorage write so subsequent reloads
|
|
43
|
+
// within this tab re-enter the same project (readPendingScope will pick it up).
|
|
44
|
+
sessionStorage.setItem(PENDING_SCOPE_KEY, JSON.stringify({ projectId: urlProject }));
|
|
45
|
+
sessionState.activeProjectId = urlProject;
|
|
46
|
+
// Strip the param so it doesn't linger in bookmarks or history.
|
|
47
|
+
const cleanUrl = new URL(window.location.href);
|
|
48
|
+
cleanUrl.searchParams.delete('project');
|
|
49
|
+
history.replaceState(null, '', cleanUrl.toString());
|
|
50
|
+
}
|
|
51
|
+
}
|
|
30
52
|
// 1. Platform detection
|
|
31
53
|
const platform = await resolvePlatform();
|
|
32
54
|
if (platform.backends) {
|
|
@@ -60,6 +82,11 @@ export async function createShell(config) {
|
|
|
60
82
|
// but pop-out is currently a Tauri-only POC so we don't fetch it.
|
|
61
83
|
if (platform.localOwner)
|
|
62
84
|
__setActiveScope('local');
|
|
85
|
+
// Inherit the host's active project scope so shard activation lands in the
|
|
86
|
+
// correct tenant (satellite opens in the same project context as the host).
|
|
87
|
+
if (satellite.payload.projectId) {
|
|
88
|
+
sessionState.activeProjectId = satellite.payload.projectId;
|
|
89
|
+
}
|
|
63
90
|
__setScopeResolver(() => sessionState.activeProjectId);
|
|
64
91
|
__setShardScopeResolver(() => sessionState.activeProjectId ? 'project' : 'tenant');
|
|
65
92
|
if (config === null || config === void 0 ? void 0 : config.shards)
|
|
@@ -138,19 +165,17 @@ export async function createShell(config) {
|
|
|
138
165
|
for (const app of config.apps)
|
|
139
166
|
registerApp(app);
|
|
140
167
|
}
|
|
141
|
-
// 7.
|
|
168
|
+
// 7. Wire scope resolvers before bootstrap so shards activate in the correct scope.
|
|
169
|
+
__setScopeResolver(() => sessionState.activeProjectId);
|
|
170
|
+
__setShardScopeResolver(() => sessionState.activeProjectId ? 'project' : 'tenant');
|
|
171
|
+
// 8. Bootstrap
|
|
142
172
|
const bootstrapConfig = {};
|
|
143
173
|
if (config === null || config === void 0 ? void 0 : config.excludeShards)
|
|
144
174
|
bootstrapConfig.excludeShards = config.excludeShards;
|
|
145
175
|
await bootstrap(bootstrapConfig);
|
|
146
|
-
//
|
|
147
|
-
// When the user enters a project, getActiveScopeId() returns the project
|
|
148
|
-
// id so all document operations use the project's virtual tenant.
|
|
149
|
-
__setScopeResolver(() => sessionState.activeProjectId);
|
|
150
|
-
__setShardScopeResolver(() => sessionState.activeProjectId ? 'project' : 'tenant');
|
|
151
|
-
// 8. Attach document-level keyboard / focus listeners
|
|
176
|
+
// 9. Attach document-level keyboard / focus listeners
|
|
152
177
|
attachGlobalListeners();
|
|
153
|
-
//
|
|
178
|
+
// 10. Mount the sh3
|
|
154
179
|
mount(Sh3, { target });
|
|
155
180
|
}
|
|
156
181
|
/**
|
|
@@ -13,6 +13,12 @@ export declare class MemoryDocumentBackend implements DocumentBackend {
|
|
|
13
13
|
shardId: string;
|
|
14
14
|
}>>;
|
|
15
15
|
readMeta(tenantId: string, shardId: string, path: string): Promise<DocStatus | null>;
|
|
16
|
+
mkdir(tenantId: string, shardId: string, path: string): Promise<void>;
|
|
17
|
+
rmdir(tenantId: string, shardId: string, path: string, opts: {
|
|
18
|
+
recursive: boolean;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
renameFolder(tenantId: string, shardId: string, oldPath: string, newPath: string): Promise<void>;
|
|
21
|
+
listFolders(tenantId: string, shardId: string, prefix: string): Promise<string[]>;
|
|
16
22
|
}
|
|
17
23
|
export declare class IndexedDBDocumentBackend implements DocumentBackend {
|
|
18
24
|
#private;
|
|
@@ -26,4 +32,10 @@ export declare class IndexedDBDocumentBackend implements DocumentBackend {
|
|
|
26
32
|
listAllDocuments(tenantId: string): Promise<Array<DocumentMeta & {
|
|
27
33
|
shardId: string;
|
|
28
34
|
}>>;
|
|
35
|
+
mkdir(tenantId: string, shardId: string, path: string): Promise<void>;
|
|
36
|
+
rmdir(tenantId: string, shardId: string, path: string, opts: {
|
|
37
|
+
recursive: boolean;
|
|
38
|
+
}): Promise<void>;
|
|
39
|
+
renameFolder(tenantId: string, shardId: string, oldPath: string, newPath: string): Promise<void>;
|
|
40
|
+
listFolders(tenantId: string, shardId: string, prefix: string): Promise<string[]>;
|
|
29
41
|
}
|
|
@@ -16,7 +16,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
16
16
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
17
17
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
18
18
|
};
|
|
19
|
-
var _MemoryDocumentBackend_store, _IndexedDBDocumentBackend_instances, _IndexedDBDocumentBackend_dbPromise, _IndexedDBDocumentBackend_db, _IndexedDBDocumentBackend_tx;
|
|
19
|
+
var _MemoryDocumentBackend_store, _MemoryDocumentBackend_folders, _IndexedDBDocumentBackend_instances, _IndexedDBDocumentBackend_dbPromise, _IndexedDBDocumentBackend_db, _IndexedDBDocumentBackend_tx, _IndexedDBDocumentBackend_txOn;
|
|
20
20
|
// ---------------------------------------------------------------------------
|
|
21
21
|
// Helpers
|
|
22
22
|
// ---------------------------------------------------------------------------
|
|
@@ -29,6 +29,7 @@ function keyPrefix(tenantId, shardId) {
|
|
|
29
29
|
export class MemoryDocumentBackend {
|
|
30
30
|
constructor() {
|
|
31
31
|
_MemoryDocumentBackend_store.set(this, new Map());
|
|
32
|
+
_MemoryDocumentBackend_folders.set(this, new Set()); // composite keys: `${tenant}/${shard}/${path}`
|
|
32
33
|
}
|
|
33
34
|
async read(tenantId, shardId, path) {
|
|
34
35
|
const entry = __classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f").get(compositeKey(tenantId, shardId, path));
|
|
@@ -111,14 +112,111 @@ export class MemoryDocumentBackend {
|
|
|
111
112
|
return null;
|
|
112
113
|
return { exists: true, version: 1, syncMode: 'sync', syncState: 'synced' };
|
|
113
114
|
}
|
|
115
|
+
async mkdir(tenantId, shardId, path) {
|
|
116
|
+
if (__classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f").has(compositeKey(tenantId, shardId, path))) {
|
|
117
|
+
throw new Error(`Cannot mkdir ${path}: a document occupies this path`);
|
|
118
|
+
}
|
|
119
|
+
__classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f").add(compositeKey(tenantId, shardId, path));
|
|
120
|
+
}
|
|
121
|
+
async rmdir(tenantId, shardId, path, opts) {
|
|
122
|
+
const folderKey = compositeKey(tenantId, shardId, path);
|
|
123
|
+
const docPrefix = folderKey + '/';
|
|
124
|
+
const docDescendants = [];
|
|
125
|
+
const folderDescendants = [];
|
|
126
|
+
for (const key of __classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f").keys()) {
|
|
127
|
+
if (key.startsWith(docPrefix))
|
|
128
|
+
docDescendants.push(key);
|
|
129
|
+
}
|
|
130
|
+
for (const key of __classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f")) {
|
|
131
|
+
if (key === folderKey)
|
|
132
|
+
continue;
|
|
133
|
+
if (key.startsWith(docPrefix))
|
|
134
|
+
folderDescendants.push(key);
|
|
135
|
+
}
|
|
136
|
+
if (!opts.recursive && (docDescendants.length > 0 || folderDescendants.length > 0)) {
|
|
137
|
+
throw new Error(`Cannot rmdir ${path}: folder is not empty`);
|
|
138
|
+
}
|
|
139
|
+
for (const k of docDescendants)
|
|
140
|
+
__classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f").delete(k);
|
|
141
|
+
for (const k of folderDescendants)
|
|
142
|
+
__classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f").delete(k);
|
|
143
|
+
__classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f").delete(folderKey);
|
|
144
|
+
}
|
|
145
|
+
async renameFolder(tenantId, shardId, oldPath, newPath) {
|
|
146
|
+
const oldFolderKey = compositeKey(tenantId, shardId, oldPath);
|
|
147
|
+
const newFolderKey = compositeKey(tenantId, shardId, newPath);
|
|
148
|
+
const oldDocPrefix = oldFolderKey + '/';
|
|
149
|
+
const oldHasExplicit = __classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f").has(oldFolderKey);
|
|
150
|
+
const oldHasImplicit = [...__classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f").keys()].some((k) => k.startsWith(oldDocPrefix)) ||
|
|
151
|
+
[...__classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f")].some((k) => k.startsWith(oldDocPrefix));
|
|
152
|
+
if (!oldHasExplicit && !oldHasImplicit) {
|
|
153
|
+
throw new Error(`Cannot rename folder ${oldPath}: does not exist`);
|
|
154
|
+
}
|
|
155
|
+
const newDocPrefix = newFolderKey + '/';
|
|
156
|
+
const newHasExplicit = __classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f").has(newFolderKey);
|
|
157
|
+
const newHasImplicit = [...__classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f").keys()].some((k) => k.startsWith(newDocPrefix)) ||
|
|
158
|
+
[...__classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f")].some((k) => k.startsWith(newDocPrefix));
|
|
159
|
+
if (newHasExplicit || newHasImplicit) {
|
|
160
|
+
throw new Error(`Cannot rename folder to ${newPath}: already exists`);
|
|
161
|
+
}
|
|
162
|
+
// Rewrite docs
|
|
163
|
+
const docMoves = [];
|
|
164
|
+
for (const [key, entry] of __classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f")) {
|
|
165
|
+
if (key.startsWith(oldDocPrefix)) {
|
|
166
|
+
const rewritten = newFolderKey + '/' + key.slice(oldDocPrefix.length);
|
|
167
|
+
docMoves.push([key, rewritten, entry]);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for (const [oldKey, newKey, entry] of docMoves) {
|
|
171
|
+
__classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f").delete(oldKey);
|
|
172
|
+
__classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f").set(newKey, Object.assign(Object.assign({}, entry), { lastModified: Date.now() }));
|
|
173
|
+
}
|
|
174
|
+
// Rewrite folders
|
|
175
|
+
const folderMoves = [];
|
|
176
|
+
for (const key of __classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f")) {
|
|
177
|
+
if (key === oldFolderKey) {
|
|
178
|
+
folderMoves.push([key, newFolderKey]);
|
|
179
|
+
}
|
|
180
|
+
else if (key.startsWith(oldDocPrefix)) {
|
|
181
|
+
folderMoves.push([key, newFolderKey + '/' + key.slice(oldDocPrefix.length)]);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
for (const [oldKey, newKey] of folderMoves) {
|
|
185
|
+
__classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f").delete(oldKey);
|
|
186
|
+
__classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f").add(newKey);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async listFolders(tenantId, shardId, prefix) {
|
|
190
|
+
const basePrefix = prefix
|
|
191
|
+
? compositeKey(tenantId, shardId, prefix) + '/'
|
|
192
|
+
: keyPrefix(tenantId, shardId);
|
|
193
|
+
const out = new Set();
|
|
194
|
+
for (const key of __classPrivateFieldGet(this, _MemoryDocumentBackend_folders, "f")) {
|
|
195
|
+
if (!key.startsWith(basePrefix))
|
|
196
|
+
continue;
|
|
197
|
+
const rest = key.slice(basePrefix.length);
|
|
198
|
+
const slash = rest.indexOf('/');
|
|
199
|
+
out.add(slash >= 0 ? rest.slice(0, slash) : rest);
|
|
200
|
+
}
|
|
201
|
+
for (const key of __classPrivateFieldGet(this, _MemoryDocumentBackend_store, "f").keys()) {
|
|
202
|
+
if (!key.startsWith(basePrefix))
|
|
203
|
+
continue;
|
|
204
|
+
const rest = key.slice(basePrefix.length);
|
|
205
|
+
const slash = rest.indexOf('/');
|
|
206
|
+
if (slash >= 0)
|
|
207
|
+
out.add(rest.slice(0, slash));
|
|
208
|
+
}
|
|
209
|
+
return [...out].sort();
|
|
210
|
+
}
|
|
114
211
|
}
|
|
115
|
-
_MemoryDocumentBackend_store = new WeakMap();
|
|
212
|
+
_MemoryDocumentBackend_store = new WeakMap(), _MemoryDocumentBackend_folders = new WeakMap();
|
|
116
213
|
// ---------------------------------------------------------------------------
|
|
117
214
|
// IndexedDBDocumentBackend
|
|
118
215
|
// ---------------------------------------------------------------------------
|
|
119
216
|
const IDB_NAME = 'sh3-documents';
|
|
120
217
|
const IDB_STORE = 'docs';
|
|
121
|
-
const
|
|
218
|
+
const IDB_FOLDERS = 'folders';
|
|
219
|
+
const IDB_VERSION = 3;
|
|
122
220
|
export class IndexedDBDocumentBackend {
|
|
123
221
|
constructor() {
|
|
124
222
|
_IndexedDBDocumentBackend_instances.add(this);
|
|
@@ -274,6 +372,123 @@ export class IndexedDBDocumentBackend {
|
|
|
274
372
|
req.onerror = () => reject(req.error);
|
|
275
373
|
});
|
|
276
374
|
}
|
|
375
|
+
async mkdir(tenantId, shardId, path) {
|
|
376
|
+
const docKey = compositeKey(tenantId, shardId, path);
|
|
377
|
+
const exists = await __classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_tx).call(this, 'readonly', (s) => s.getKey(docKey));
|
|
378
|
+
if (exists !== undefined) {
|
|
379
|
+
throw new Error(`Cannot mkdir ${path}: a document occupies this path`);
|
|
380
|
+
}
|
|
381
|
+
await __classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_txOn).call(this, IDB_FOLDERS, 'readwrite', (s) => s.put(1, docKey));
|
|
382
|
+
}
|
|
383
|
+
async rmdir(tenantId, shardId, path, opts) {
|
|
384
|
+
const folderKey = compositeKey(tenantId, shardId, path);
|
|
385
|
+
const docPrefix = folderKey + '/';
|
|
386
|
+
const upper = docPrefix + '';
|
|
387
|
+
const docKeys = await __classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_tx).call(this, 'readonly', (s) => s.getAllKeys(IDBKeyRange.bound(docPrefix, upper, false, false)));
|
|
388
|
+
const folderKeys = await __classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_txOn).call(this, IDB_FOLDERS, 'readonly', (s) => s.getAllKeys(IDBKeyRange.bound(docPrefix, upper, false, false)));
|
|
389
|
+
if (!opts.recursive && (docKeys.length > 0 || folderKeys.length > 0)) {
|
|
390
|
+
throw new Error(`Cannot rmdir ${path}: folder is not empty`);
|
|
391
|
+
}
|
|
392
|
+
const db = await __classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_db).call(this);
|
|
393
|
+
await new Promise((resolve, reject) => {
|
|
394
|
+
const tx = db.transaction([IDB_STORE, IDB_FOLDERS], 'readwrite');
|
|
395
|
+
const docStore = tx.objectStore(IDB_STORE);
|
|
396
|
+
const folderStore = tx.objectStore(IDB_FOLDERS);
|
|
397
|
+
for (const k of docKeys)
|
|
398
|
+
docStore.delete(k);
|
|
399
|
+
for (const k of folderKeys)
|
|
400
|
+
folderStore.delete(k);
|
|
401
|
+
folderStore.delete(folderKey);
|
|
402
|
+
tx.oncomplete = () => resolve();
|
|
403
|
+
tx.onerror = () => reject(tx.error);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
async renameFolder(tenantId, shardId, oldPath, newPath) {
|
|
407
|
+
const oldFolderKey = compositeKey(tenantId, shardId, oldPath);
|
|
408
|
+
const newFolderKey = compositeKey(tenantId, shardId, newPath);
|
|
409
|
+
const oldPrefix = oldFolderKey + '/';
|
|
410
|
+
const newPrefix = newFolderKey + '/';
|
|
411
|
+
const upperOld = oldPrefix + '';
|
|
412
|
+
const upperNew = newPrefix + '';
|
|
413
|
+
const [oldDocs, oldFolders, oldExplicit, newDocs, newFolders, newExplicit] = await Promise.all([
|
|
414
|
+
__classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_tx).call(this, 'readonly', (s) => s.getAllKeys(IDBKeyRange.bound(oldPrefix, upperOld, false, false))),
|
|
415
|
+
__classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_txOn).call(this, IDB_FOLDERS, 'readonly', (s) => s.getAllKeys(IDBKeyRange.bound(oldPrefix, upperOld, false, false))),
|
|
416
|
+
__classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_txOn).call(this, IDB_FOLDERS, 'readonly', (s) => s.getKey(oldFolderKey)),
|
|
417
|
+
__classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_tx).call(this, 'readonly', (s) => s.getAllKeys(IDBKeyRange.bound(newPrefix, upperNew, false, false))),
|
|
418
|
+
__classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_txOn).call(this, IDB_FOLDERS, 'readonly', (s) => s.getAllKeys(IDBKeyRange.bound(newPrefix, upperNew, false, false))),
|
|
419
|
+
__classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_txOn).call(this, IDB_FOLDERS, 'readonly', (s) => s.getKey(newFolderKey)),
|
|
420
|
+
]);
|
|
421
|
+
if (oldDocs.length === 0 && oldFolders.length === 0 && oldExplicit === undefined) {
|
|
422
|
+
throw new Error(`Cannot rename folder ${oldPath}: does not exist`);
|
|
423
|
+
}
|
|
424
|
+
if (newDocs.length > 0 || newFolders.length > 0 || newExplicit !== undefined) {
|
|
425
|
+
throw new Error(`Cannot rename folder to ${newPath}: already exists`);
|
|
426
|
+
}
|
|
427
|
+
// Read doc entries with values via cursor
|
|
428
|
+
const docEntries = await new Promise((resolve, reject) => {
|
|
429
|
+
__classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_db).call(this).then((db) => {
|
|
430
|
+
const tx = db.transaction(IDB_STORE, 'readonly');
|
|
431
|
+
const store = tx.objectStore(IDB_STORE);
|
|
432
|
+
const req = store.openCursor(IDBKeyRange.bound(oldPrefix, upperOld, false, false));
|
|
433
|
+
const acc = [];
|
|
434
|
+
req.onsuccess = () => {
|
|
435
|
+
const cursor = req.result;
|
|
436
|
+
if (cursor) {
|
|
437
|
+
acc.push({ key: cursor.key, value: cursor.value });
|
|
438
|
+
cursor.continue();
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
resolve(acc);
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
req.onerror = () => reject(req.error);
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
const db = await __classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_db).call(this);
|
|
448
|
+
await new Promise((resolve, reject) => {
|
|
449
|
+
const tx = db.transaction([IDB_STORE, IDB_FOLDERS], 'readwrite');
|
|
450
|
+
const docStore = tx.objectStore(IDB_STORE);
|
|
451
|
+
const folderStore = tx.objectStore(IDB_FOLDERS);
|
|
452
|
+
for (const { key, value } of docEntries) {
|
|
453
|
+
const rewritten = newFolderKey + '/' + key.slice(oldPrefix.length);
|
|
454
|
+
docStore.delete(key);
|
|
455
|
+
docStore.put(Object.assign(Object.assign({}, value), { lastModified: Date.now() }), rewritten);
|
|
456
|
+
}
|
|
457
|
+
if (oldExplicit !== undefined) {
|
|
458
|
+
folderStore.delete(oldFolderKey);
|
|
459
|
+
}
|
|
460
|
+
folderStore.put(1, newFolderKey);
|
|
461
|
+
for (const k of oldFolders) {
|
|
462
|
+
const oldKeyStr = k;
|
|
463
|
+
const rewritten = newFolderKey + '/' + oldKeyStr.slice(oldPrefix.length);
|
|
464
|
+
folderStore.delete(k);
|
|
465
|
+
folderStore.put(1, rewritten);
|
|
466
|
+
}
|
|
467
|
+
tx.oncomplete = () => resolve();
|
|
468
|
+
tx.onerror = () => reject(tx.error);
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
async listFolders(tenantId, shardId, prefix) {
|
|
472
|
+
const basePrefix = prefix
|
|
473
|
+
? compositeKey(tenantId, shardId, prefix) + '/'
|
|
474
|
+
: keyPrefix(tenantId, shardId);
|
|
475
|
+
const upper = basePrefix + '';
|
|
476
|
+
const out = new Set();
|
|
477
|
+
const folderKeys = await __classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_txOn).call(this, IDB_FOLDERS, 'readonly', (s) => s.getAllKeys(IDBKeyRange.bound(basePrefix, upper, false, false)));
|
|
478
|
+
for (const k of folderKeys) {
|
|
479
|
+
const rest = k.slice(basePrefix.length);
|
|
480
|
+
const slash = rest.indexOf('/');
|
|
481
|
+
out.add(slash >= 0 ? rest.slice(0, slash) : rest);
|
|
482
|
+
}
|
|
483
|
+
const docKeys = await __classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_tx).call(this, 'readonly', (s) => s.getAllKeys(IDBKeyRange.bound(basePrefix, upper, false, false)));
|
|
484
|
+
for (const k of docKeys) {
|
|
485
|
+
const rest = k.slice(basePrefix.length);
|
|
486
|
+
const slash = rest.indexOf('/');
|
|
487
|
+
if (slash >= 0)
|
|
488
|
+
out.add(rest.slice(0, slash));
|
|
489
|
+
}
|
|
490
|
+
return [...out].sort();
|
|
491
|
+
}
|
|
277
492
|
}
|
|
278
493
|
_IndexedDBDocumentBackend_dbPromise = new WeakMap(), _IndexedDBDocumentBackend_instances = new WeakSet(), _IndexedDBDocumentBackend_db = function _IndexedDBDocumentBackend_db() {
|
|
279
494
|
if (!__classPrivateFieldGet(this, _IndexedDBDocumentBackend_dbPromise, "f")) {
|
|
@@ -284,6 +499,9 @@ _IndexedDBDocumentBackend_dbPromise = new WeakMap(), _IndexedDBDocumentBackend_i
|
|
|
284
499
|
if (!db.objectStoreNames.contains(IDB_STORE)) {
|
|
285
500
|
db.createObjectStore(IDB_STORE);
|
|
286
501
|
}
|
|
502
|
+
if (!db.objectStoreNames.contains(IDB_FOLDERS)) {
|
|
503
|
+
db.createObjectStore(IDB_FOLDERS);
|
|
504
|
+
}
|
|
287
505
|
};
|
|
288
506
|
req.onsuccess = () => resolve(req.result);
|
|
289
507
|
req.onerror = () => reject(req.error);
|
|
@@ -301,4 +519,13 @@ async function _IndexedDBDocumentBackend_tx(mode, fn) {
|
|
|
301
519
|
req.onsuccess = () => resolve(req.result);
|
|
302
520
|
req.onerror = () => reject(req.error);
|
|
303
521
|
});
|
|
522
|
+
}, _IndexedDBDocumentBackend_txOn = async function _IndexedDBDocumentBackend_txOn(storeName, mode, fn) {
|
|
523
|
+
const db = await __classPrivateFieldGet(this, _IndexedDBDocumentBackend_instances, "m", _IndexedDBDocumentBackend_db).call(this);
|
|
524
|
+
return new Promise((resolve, reject) => {
|
|
525
|
+
const tx = db.transaction(storeName, mode);
|
|
526
|
+
const store = tx.objectStore(storeName);
|
|
527
|
+
const req = fn(store);
|
|
528
|
+
req.onsuccess = () => resolve(req.result);
|
|
529
|
+
req.onerror = () => reject(req.error);
|
|
530
|
+
});
|
|
304
531
|
};
|