sh3-core 0.21.2 → 0.22.0
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/__test__/reset.js +2 -0
- package/dist/apps/lifecycle.js +49 -2
- package/dist/apps/lifecycle.test.js +234 -0
- package/dist/artifact.d.ts +2 -0
- package/dist/build.js +1 -1
- package/dist/documents/handle.d.ts +1 -1
- package/dist/documents/handle.js +37 -24
- package/dist/documents/handle.test.js +63 -0
- package/dist/documents/types.d.ts +6 -0
- package/dist/layout/LayoutRenderer.svelte +1 -1
- package/dist/layout/SlotContainer.svelte +1 -0
- package/dist/layout/inspection.js +19 -14
- package/dist/layout/inspection.svelte.test.js +136 -1
- package/dist/layout/slotHostPool.svelte.d.ts +2 -1
- package/dist/layout/slotHostPool.svelte.js +6 -3
- package/dist/layout/slotHostPool.test.js +17 -0
- package/dist/layout/store.projectScope.test.d.ts +1 -0
- package/dist/layout/store.projectScope.test.js +76 -0
- package/dist/layout/store.svelte.d.ts +6 -0
- package/dist/layout/store.svelte.js +43 -13
- package/dist/layout/tree-walk.d.ts +8 -1
- package/dist/layout/tree-walk.js +11 -1
- package/dist/layout/tree-walk.test.js +53 -1
- package/dist/layout/types.d.ts +27 -0
- package/dist/layout/types.test.js +28 -0
- package/dist/overlays/FloatFrame.svelte +4 -1
- package/dist/overlays/float.d.ts +7 -1
- package/dist/overlays/float.js +4 -0
- package/dist/projects-shard/ProjectsSection.svelte +1 -5
- package/dist/shards/activate-runtime.test.js +45 -0
- package/dist/shards/activate.svelte.js +5 -1
- package/dist/shards/app-binding.svelte.d.ts +8 -0
- package/dist/shards/app-binding.svelte.js +30 -0
- package/dist/shards/app-binding.test.d.ts +1 -0
- package/dist/shards/app-binding.test.js +25 -0
- package/dist/shards/types.d.ts +77 -10
- package/dist/shell-shard/shellShard.svelte.js +10 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -24,3 +24,31 @@ describe('LAYOUT_SCHEMA_VERSION', () => {
|
|
|
24
24
|
expect(LAYOUT_SCHEMA_VERSION).toBe(7);
|
|
25
25
|
});
|
|
26
26
|
});
|
|
27
|
+
describe('SlotNode props', () => {
|
|
28
|
+
it('accepts optional props', () => {
|
|
29
|
+
var _a;
|
|
30
|
+
const node = {
|
|
31
|
+
type: 'slot',
|
|
32
|
+
slotId: 'slot-1',
|
|
33
|
+
viewId: 'my:view',
|
|
34
|
+
props: { filePath: '/foo.guml', count: 3, flag: true, nul: null },
|
|
35
|
+
};
|
|
36
|
+
expect((_a = node.props) === null || _a === void 0 ? void 0 : _a.filePath).toBe('/foo.guml');
|
|
37
|
+
});
|
|
38
|
+
it('omitting props is valid', () => {
|
|
39
|
+
const node = { type: 'slot', slotId: 's', viewId: null };
|
|
40
|
+
expect(node.props).toBeUndefined();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('TabEntry props', () => {
|
|
44
|
+
it('accepts optional props', () => {
|
|
45
|
+
var _a;
|
|
46
|
+
const entry = {
|
|
47
|
+
slotId: 'slot-1',
|
|
48
|
+
viewId: 'my:view',
|
|
49
|
+
label: 'My View',
|
|
50
|
+
props: { x: 1 },
|
|
51
|
+
};
|
|
52
|
+
expect((_a = entry.props) === null || _a === void 0 ? void 0 : _a.x).toBe(1);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
import { makeSelectionApi } from '../actions/selection.svelte';
|
|
36
36
|
import { spawnSatellite } from '../sh3Api/window';
|
|
37
37
|
import { walkShardsForContent } from '../satellite/walkShards';
|
|
38
|
+
import { getActiveScopeId, getPersonalScopeId } from '../documents/config';
|
|
38
39
|
import { logGesture } from '../gestures';
|
|
39
40
|
|
|
40
41
|
const isTauri =
|
|
@@ -256,13 +257,15 @@
|
|
|
256
257
|
async function onPopOut(e: MouseEvent): Promise<void> {
|
|
257
258
|
e.stopPropagation();
|
|
258
259
|
try {
|
|
260
|
+
const scopeId = getActiveScopeId();
|
|
261
|
+
const personalId = getPersonalScopeId();
|
|
259
262
|
await spawnSatellite({
|
|
260
263
|
kind: 'float',
|
|
261
264
|
content: entry.content,
|
|
262
265
|
title: entry.title,
|
|
263
266
|
size: { w: entry.size.w, h: entry.size.h },
|
|
264
267
|
activateShards: walkShardsForContent(entry.content),
|
|
265
|
-
projectId:
|
|
268
|
+
projectId: scopeId !== personalId ? scopeId : undefined,
|
|
266
269
|
});
|
|
267
270
|
floatManager.close(entry.id);
|
|
268
271
|
} catch (err) {
|
package/dist/overlays/float.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LayoutNode, FloatEntry } from '../layout/types';
|
|
1
|
+
import type { LayoutNode, FloatEntry, JsonValue } from '../layout/types';
|
|
2
2
|
import type { Size } from '../layout/floats';
|
|
3
3
|
export interface FloatOptions {
|
|
4
4
|
title?: string;
|
|
@@ -9,6 +9,12 @@ export interface FloatOptions {
|
|
|
9
9
|
size?: Size;
|
|
10
10
|
/** Instance data threaded to the view factory via `MountContext.meta`. */
|
|
11
11
|
meta?: Record<string, unknown>;
|
|
12
|
+
/**
|
|
13
|
+
* Serializable view props threaded to the factory via `MountContext.props`
|
|
14
|
+
* and persisted with the float entry. Survives `popoutView` → `dockFloat`
|
|
15
|
+
* round-trip. JSON-safe values only.
|
|
16
|
+
*/
|
|
17
|
+
props?: Record<string, JsonValue>;
|
|
12
18
|
/**
|
|
13
19
|
* When true, the float dismisses on any pointerdown outside its frame,
|
|
14
20
|
* is not dockable, and renders without a header when `title` is unset.
|
package/dist/overlays/float.js
CHANGED
|
@@ -150,6 +150,8 @@ function openFloat(viewId, options = {}) {
|
|
|
150
150
|
};
|
|
151
151
|
if (options.meta)
|
|
152
152
|
slot.meta = options.meta;
|
|
153
|
+
if (options.props)
|
|
154
|
+
slot.props = options.props;
|
|
153
155
|
content = slot;
|
|
154
156
|
}
|
|
155
157
|
else {
|
|
@@ -157,6 +159,8 @@ function openFloat(viewId, options = {}) {
|
|
|
157
159
|
const tab = { slotId, viewId, label };
|
|
158
160
|
if (options.meta)
|
|
159
161
|
tab.meta = options.meta;
|
|
162
|
+
if (options.props)
|
|
163
|
+
tab.props = options.props;
|
|
160
164
|
content = {
|
|
161
165
|
type: 'tabs',
|
|
162
166
|
tabs: [tab],
|
|
@@ -90,11 +90,7 @@
|
|
|
90
90
|
border-color: var(--sh3-accent);
|
|
91
91
|
transform: translateY(-1px);
|
|
92
92
|
}
|
|
93
|
-
|
|
94
|
-
border-color: var(--sh3-accent);
|
|
95
|
-
box-shadow: 0 0 0 2px color-mix(in srgb, var(--sh3-accent) 40%, transparent);
|
|
96
|
-
}
|
|
97
|
-
.project-name { font-weight: 600; font-size: 13px; }
|
|
93
|
+
.project-name { font-weight: 600; font-size: 13px; }
|
|
98
94
|
.project-meta { font-size: 11px; color: var(--sh3-fg-muted); }
|
|
99
95
|
.leave-project {
|
|
100
96
|
display: flex;
|
|
@@ -297,3 +297,48 @@ describe('ctx.listVerbs / ctx.runVerb (integration)', () => {
|
|
|
297
297
|
expect(names.find((n) => n.startsWith('ignored:'))).toBeUndefined();
|
|
298
298
|
});
|
|
299
299
|
});
|
|
300
|
+
// ─── registerContributions ────────────────────────────────────────────────────
|
|
301
|
+
describe('registerContributions hook', () => {
|
|
302
|
+
beforeEach(() => {
|
|
303
|
+
__resetShardRegistryForTest();
|
|
304
|
+
__resetViewRegistryForTest();
|
|
305
|
+
__setDocumentBackend(new MemoryDocumentBackend());
|
|
306
|
+
__setActiveScope('tenant-test');
|
|
307
|
+
});
|
|
308
|
+
it('is called after activate() with the same ShardContext', async () => {
|
|
309
|
+
const order = [];
|
|
310
|
+
let activateCtx = null;
|
|
311
|
+
let registerCtx = null;
|
|
312
|
+
registerShard({
|
|
313
|
+
manifest: { id: 'rc-shard', label: 'RC', version: '0.0.0', views: [] },
|
|
314
|
+
activate(ctx) {
|
|
315
|
+
activateCtx = ctx;
|
|
316
|
+
order.push('activate');
|
|
317
|
+
},
|
|
318
|
+
registerContributions(ctx) {
|
|
319
|
+
registerCtx = ctx;
|
|
320
|
+
order.push('registerContributions');
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
await activateShard('rc-shard');
|
|
324
|
+
expect(order).toEqual(['activate', 'registerContributions']);
|
|
325
|
+
expect(registerCtx).toBe(activateCtx);
|
|
326
|
+
});
|
|
327
|
+
it('is not called when the hook is absent', async () => {
|
|
328
|
+
registerShard({
|
|
329
|
+
manifest: { id: 'no-rc', label: 'NoRC', version: '0.0.0', views: [] },
|
|
330
|
+
activate() { },
|
|
331
|
+
});
|
|
332
|
+
await expect(activateShard('no-rc')).resolves.toBeUndefined();
|
|
333
|
+
});
|
|
334
|
+
it('is not called when activate() throws', async () => {
|
|
335
|
+
const registerContributions = vi.fn();
|
|
336
|
+
registerShard({
|
|
337
|
+
manifest: { id: 'fail-rc', label: 'FailRC', version: '0.0.0', views: [] },
|
|
338
|
+
activate() { throw new Error('boom'); },
|
|
339
|
+
registerContributions,
|
|
340
|
+
});
|
|
341
|
+
await expect(activateShard('fail-rc')).rejects.toThrow('boom');
|
|
342
|
+
expect(registerContributions).not.toHaveBeenCalled();
|
|
343
|
+
});
|
|
344
|
+
});
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { sh3 } from '../sh3Runtime.svelte';
|
|
20
20
|
import { registerView, unregisterView, registerVerb as fwRegisterVerb, unregisterVerb as fwUnregisterVerb } from './registry';
|
|
21
|
+
import { getShardBinding } from './app-binding.svelte';
|
|
21
22
|
import { makeSh3Api } from '../sh3Api/headless';
|
|
22
23
|
import { createDocumentHandle, getDocumentBackend, getActiveScopeId } from '../documents';
|
|
23
24
|
import { fetchEnvState, putEnvState } from '../env/client';
|
|
@@ -179,7 +180,7 @@ export async function activateShard(id, opts) {
|
|
|
179
180
|
}
|
|
180
181
|
},
|
|
181
182
|
documents: (options) => {
|
|
182
|
-
const handle = createDocumentHandle(getActiveScopeId()
|
|
183
|
+
const handle = createDocumentHandle(getActiveScopeId, () => { var _a; return (_a = getShardBinding(id)) !== null && _a !== void 0 ? _a : id; }, getDocumentBackend(), options);
|
|
183
184
|
entry.cleanupFns.push(() => handle.dispose());
|
|
184
185
|
return handle;
|
|
185
186
|
},
|
|
@@ -329,6 +330,9 @@ export async function activateShard(id, opts) {
|
|
|
329
330
|
}
|
|
330
331
|
// Activation succeeded — clear any prior error record for this shard.
|
|
331
332
|
erroredShards.delete(id);
|
|
333
|
+
if (shard.registerContributions) {
|
|
334
|
+
shard.registerContributions(ctx);
|
|
335
|
+
}
|
|
332
336
|
void ((_l = shard.autostart) === null || _l === void 0 ? void 0 : _l.call(shard, ctx));
|
|
333
337
|
}
|
|
334
338
|
/**
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Record that `shardId` is currently part of `appId`. Overwrites any prior binding. */
|
|
2
|
+
export declare function bindShardToApp(shardId: string, appId: string): void;
|
|
3
|
+
/** Remove the binding for `shardId`. No-op if not bound. */
|
|
4
|
+
export declare function clearShardBinding(shardId: string): void;
|
|
5
|
+
/** Return the app id this shard is currently bound to, or null. */
|
|
6
|
+
export declare function getShardBinding(shardId: string): string | null;
|
|
7
|
+
/** Test-only reset. */
|
|
8
|
+
export declare function __resetShardBindingsForTest(): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Shard ↔ app binding registry.
|
|
3
|
+
*
|
|
4
|
+
* Records which app (if any) currently owns each active shard. Read by
|
|
5
|
+
* `ctx.documents()` so its handle's namespace can resolve to `{appId}` instead
|
|
6
|
+
* of `{shardId}` when the shard is required by a running app — the framework
|
|
7
|
+
* default for app-shared document namespaces.
|
|
8
|
+
*
|
|
9
|
+
* Set by `launchApp` for non-autostart required shards. Cleared by
|
|
10
|
+
* `unloadApp` (also for non-autostart required shards; autostart shards
|
|
11
|
+
* never get a binding in the first place since they serve multiple apps).
|
|
12
|
+
*/
|
|
13
|
+
const bindings = $state(new Map());
|
|
14
|
+
/** Record that `shardId` is currently part of `appId`. Overwrites any prior binding. */
|
|
15
|
+
export function bindShardToApp(shardId, appId) {
|
|
16
|
+
bindings.set(shardId, appId);
|
|
17
|
+
}
|
|
18
|
+
/** Remove the binding for `shardId`. No-op if not bound. */
|
|
19
|
+
export function clearShardBinding(shardId) {
|
|
20
|
+
bindings.delete(shardId);
|
|
21
|
+
}
|
|
22
|
+
/** Return the app id this shard is currently bound to, or null. */
|
|
23
|
+
export function getShardBinding(shardId) {
|
|
24
|
+
var _a;
|
|
25
|
+
return (_a = bindings.get(shardId)) !== null && _a !== void 0 ? _a : null;
|
|
26
|
+
}
|
|
27
|
+
/** Test-only reset. */
|
|
28
|
+
export function __resetShardBindingsForTest() {
|
|
29
|
+
bindings.clear();
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { bindShardToApp, clearShardBinding, getShardBinding, __resetShardBindingsForTest, } from './app-binding.svelte';
|
|
3
|
+
describe('shardAppBindings', () => {
|
|
4
|
+
beforeEach(__resetShardBindingsForTest);
|
|
5
|
+
it('returns null for an unbound shard', () => {
|
|
6
|
+
expect(getShardBinding('shard-A')).toBeNull();
|
|
7
|
+
});
|
|
8
|
+
it('records and reads a binding', () => {
|
|
9
|
+
bindShardToApp('shard-A', 'app-X');
|
|
10
|
+
expect(getShardBinding('shard-A')).toBe('app-X');
|
|
11
|
+
});
|
|
12
|
+
it('overwrites a prior binding (e.g. shard switching apps)', () => {
|
|
13
|
+
bindShardToApp('shard-A', 'app-X');
|
|
14
|
+
bindShardToApp('shard-A', 'app-Y');
|
|
15
|
+
expect(getShardBinding('shard-A')).toBe('app-Y');
|
|
16
|
+
});
|
|
17
|
+
it('clears a binding back to null', () => {
|
|
18
|
+
bindShardToApp('shard-A', 'app-X');
|
|
19
|
+
clearShardBinding('shard-A');
|
|
20
|
+
expect(getShardBinding('shard-A')).toBeNull();
|
|
21
|
+
});
|
|
22
|
+
it('clearShardBinding on an unbound shard is a no-op', () => {
|
|
23
|
+
expect(() => clearShardBinding('shard-A')).not.toThrow();
|
|
24
|
+
});
|
|
25
|
+
});
|
package/dist/shards/types.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { Sh3Api } from '../verbs/types';
|
|
|
9
9
|
import type { ShardContextKeys } from '../keys/types';
|
|
10
10
|
import type { ContributionsApi } from '../contributions/types';
|
|
11
11
|
import type { ActionsApi } from '../actions/types';
|
|
12
|
-
import type { TreeRootRef, SlotRole } from '../layout/types';
|
|
12
|
+
import type { TreeRootRef, SlotRole, JsonValue, RestoredSlot } from '../layout/types';
|
|
13
13
|
export { PERMISSION_KEYS_MINT, type ShardContextKeys, type ApiKeyPublic, type MintOpts, ScopeEscalationError, ConsentDeniedError } from '../keys/types';
|
|
14
14
|
/**
|
|
15
15
|
* The object returned by `ViewFactory.mount`. The framework calls
|
|
@@ -65,6 +65,13 @@ export interface MountContext {
|
|
|
65
65
|
* Not persisted with the layout — ephemeral per mount.
|
|
66
66
|
*/
|
|
67
67
|
meta?: Record<string, unknown>;
|
|
68
|
+
/**
|
|
69
|
+
* Persistent view-level parameters passed by the caller when opening
|
|
70
|
+
* this view. Serialized with the layout tree — present on every mount
|
|
71
|
+
* including layout restore. Undefined when the slot was opened without
|
|
72
|
+
* props. Values are JSON-safe (`JsonValue`).
|
|
73
|
+
*/
|
|
74
|
+
props?: Record<string, JsonValue>;
|
|
68
75
|
/**
|
|
69
76
|
* Push dirty-state to the tab strip. The framework renders a dirty
|
|
70
77
|
* indicator (filled dot) on the tab when true, clears it when false.
|
|
@@ -84,6 +91,21 @@ export interface MountContext {
|
|
|
84
91
|
*/
|
|
85
92
|
location(): TreeRootRef | null;
|
|
86
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Passed to `Shard.onAppActivate`. The `documents()` factory remains for
|
|
96
|
+
* back-compat (it returns a handle scoped to the app namespace, identical
|
|
97
|
+
* to what `ctx.documents()` now returns by default). Prefer `ctx.documents()`
|
|
98
|
+
* in new code — the framework auto-scopes the shard's existing handle to
|
|
99
|
+
* the active app's namespace via `shardAppBindings`.
|
|
100
|
+
*
|
|
101
|
+
* @deprecated Use `ctx.documents()` — auto-binds to the active app.
|
|
102
|
+
*/
|
|
103
|
+
export interface AppActivateContext {
|
|
104
|
+
/** The id of the app that just became active. */
|
|
105
|
+
readonly appId: string;
|
|
106
|
+
/** @deprecated Use `ctx.documents()`. */
|
|
107
|
+
documents(options?: DocumentHandleOptions): DocumentHandle;
|
|
108
|
+
}
|
|
87
109
|
/**
|
|
88
110
|
* The shard-side adapter that knows how to bring a view to life inside a
|
|
89
111
|
* given HTMLElement. The container is owned by the framework (the slot);
|
|
@@ -350,15 +372,10 @@ export interface Shard {
|
|
|
350
372
|
*/
|
|
351
373
|
activate(ctx: ShardContext): void | Promise<void>;
|
|
352
374
|
/**
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
* action — docking its own views into the active layout, opening a
|
|
358
|
-
* modal, subscribing to framework state, etc. The `__sh3core__` pseudo-
|
|
359
|
-
* shard uses this with a no-op body so its activation path is uniform
|
|
360
|
-
* with other self-starting shards. Diagnostic-style shards use it to
|
|
361
|
-
* do real work.
|
|
375
|
+
* @deprecated Use `registerContributions(ctx)` for static registrations
|
|
376
|
+
* and `activate(ctx)` for imperative setup. `autostart` will be removed
|
|
377
|
+
* in a future ADR — see ADR-026. Existing shards using `autostart` are
|
|
378
|
+
* not broken; this is a migration signal only.
|
|
362
379
|
*/
|
|
363
380
|
autostart?(ctx: ShardContext): void | Promise<void>;
|
|
364
381
|
/** Optional cleanup hook called when the shard is deactivated. Release timers, subscriptions, and external resources here. */
|
|
@@ -376,6 +393,56 @@ export interface Shard {
|
|
|
376
393
|
resume?(ctx: ShardContext): void | Promise<void>;
|
|
377
394
|
/** Fires when a key minted by this shard is revoked from any source. */
|
|
378
395
|
onKeyRevoked?(id: string): void | Promise<void>;
|
|
396
|
+
/**
|
|
397
|
+
* Register views, commands, hotkey bindings, verbs, toolbar items, and
|
|
398
|
+
* menu entries — anything that doesn't depend on session state. Called
|
|
399
|
+
* once after `activate()`. Separating static registrations from ceremony
|
|
400
|
+
* allows the framework to re-call this on hot-reload without re-running
|
|
401
|
+
* the full activation lifecycle. All contributions registered here are
|
|
402
|
+
* auto-unregistered when the shard deactivates.
|
|
403
|
+
*
|
|
404
|
+
* Shards that currently register everything inside `activate()` need not
|
|
405
|
+
* move — `activate()` still works. Use `registerContributions()` for new
|
|
406
|
+
* shards or when you want hot-reload-safe contribution registration.
|
|
407
|
+
*/
|
|
408
|
+
registerContributions?(ctx: ShardContext): void;
|
|
409
|
+
/**
|
|
410
|
+
* Called after all required shards have activated and the app's document
|
|
411
|
+
* namespace binding is established. Use this hook for app-context-aware
|
|
412
|
+
* setup (e.g. preloading docs, registering app-specific contributions).
|
|
413
|
+
* The shard's existing `ctx.documents()` handle is already auto-bound to
|
|
414
|
+
* the app namespace — there is no need to re-mint or swap handles here.
|
|
415
|
+
*
|
|
416
|
+
* The `appCtx.documents()` factory is retained for back-compat but is
|
|
417
|
+
* deprecated; new code should use `ctx.documents()`.
|
|
418
|
+
*/
|
|
419
|
+
onAppActivate?(appId: string, appCtx: AppActivateContext): void | Promise<void>;
|
|
420
|
+
/**
|
|
421
|
+
* Called when the app this shard was part of is unloaded — a different app
|
|
422
|
+
* is launched (the current one is force-unloaded), or `unregisterApp` is
|
|
423
|
+
* called. NOT fired by `returnToHome` — that path keeps the app alive and
|
|
424
|
+
* uses the `suspend`/`resume` hooks instead. The shard remains active; its
|
|
425
|
+
* background services and standalone document handles are still valid.
|
|
426
|
+
* Use this to release app-scoped document handles and revert to standalone
|
|
427
|
+
* state.
|
|
428
|
+
*/
|
|
429
|
+
onAppDeactivate?(appId: string): void | Promise<void>;
|
|
430
|
+
/**
|
|
431
|
+
* Called BEFORE layout slots begin mounting, after all required shards have
|
|
432
|
+
* activated. `slots` contains every slot in the restored layout tree that
|
|
433
|
+
* has a non-null viewId, including their persisted `props`. Register any
|
|
434
|
+
* slot-specific contributions here (e.g. `EDITOR_DOCUMENT_POINT` keyed by
|
|
435
|
+
* `slotId`) so they are in place when the view factory's `mount()` is called.
|
|
436
|
+
*/
|
|
437
|
+
onLayoutWillRestore?(slots: RestoredSlot[]): void | Promise<void>;
|
|
438
|
+
/**
|
|
439
|
+
* Called AFTER the layout has been switched to the app's tree and slots
|
|
440
|
+
* have begun mounting. Use for post-mount wiring and reconciliation.
|
|
441
|
+
* Note: view factories may still be mounting asynchronously (microtask);
|
|
442
|
+
* this hook fires after the layout render, not after all `mount()` calls
|
|
443
|
+
* have returned.
|
|
444
|
+
*/
|
|
445
|
+
onLayoutRestored?(slots: RestoredSlot[]): void;
|
|
379
446
|
}
|
|
380
447
|
/**
|
|
381
448
|
* Source-level shape of a shard as written by external package authors.
|
|
@@ -25,6 +25,7 @@ import { focusView } from '../layout/inspection';
|
|
|
25
25
|
import { floatManager } from '../overlays/float';
|
|
26
26
|
import { getUser, isAdmin } from '../auth/index';
|
|
27
27
|
import { __bindZone, __unbindZone } from './buffer-zone-state.svelte';
|
|
28
|
+
import { getAuthToken } from '../transport/authToken';
|
|
28
29
|
export { makeSh3ApiHeadless, makeSh3ApiForTest } from '../sh3Api/headless';
|
|
29
30
|
export const shellShard = {
|
|
30
31
|
manifest,
|
|
@@ -58,7 +59,15 @@ export const shellShard = {
|
|
|
58
59
|
var _a;
|
|
59
60
|
const proto = typeof location !== 'undefined' && location.protocol === 'https:' ? 'wss' : 'ws';
|
|
60
61
|
const host = typeof location !== 'undefined' ? location.host : 'localhost';
|
|
61
|
-
|
|
62
|
+
let wsUrl = `${proto}://${host}/api/shell/session`;
|
|
63
|
+
// Tauri WebSocket can't set Authorization headers; use the query-param
|
|
64
|
+
// token fallback already supported by extractSessionToken() in auth.ts.
|
|
65
|
+
const isTauri = typeof window !== 'undefined' && ('__TAURI_INTERNALS__' in window || '__TAURI__' in window);
|
|
66
|
+
if (isTauri) {
|
|
67
|
+
const tok = getAuthToken();
|
|
68
|
+
if (tok)
|
|
69
|
+
wsUrl += `?token=${encodeURIComponent(tok)}`;
|
|
70
|
+
}
|
|
62
71
|
const user = getUser();
|
|
63
72
|
const userId = (_a = user === null || user === void 0 ? void 0 : user.id) !== null && _a !== void 0 ? _a : 'guest';
|
|
64
73
|
const role = isAdmin() ? 'admin' : 'user';
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Auto-generated from package.json — do not edit manually. */
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.22.0";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Auto-generated from package.json — do not edit manually. */
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.22.0';
|