devframe 0.5.4 → 0.6.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{_shared-CUFqO4kJ.mjs → _shared-bWRzeSa0.mjs} +2 -3
- package/dist/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +7 -7
- package/dist/adapters/cli.d.mts +1 -1
- package/dist/adapters/cli.mjs +2 -2
- package/dist/adapters/dev.d.mts +8 -2
- package/dist/adapters/dev.mjs +1 -1
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.mjs +4 -4
- package/dist/client/index.d.mts +148 -6
- package/dist/client/index.mjs +257 -44
- package/dist/constants.d.mts +17 -1
- package/dist/constants.mjs +17 -1
- package/dist/context-3x_bgBgZ.mjs +48 -0
- package/dist/{context-DTRcO_UH.d.mts → context-BEVByy_Z.d.mts} +1 -1
- package/dist/{dev-Cv43GfqM.mjs → dev-BaX8fLH2.mjs} +39 -13
- package/dist/{devframe-BuR6n9ZD.d.mts → devframe-D-gr9sBx.d.mts} +365 -15
- package/dist/{diagnostics-GitRGKbr.mjs → diagnostics-BXwBQmoN.mjs} +1 -1
- package/dist/{dump-9lKIJTLh.mjs → dump-DoXkj4ku.mjs} +1 -1
- package/dist/helpers/vite.d.mts +1 -1
- package/dist/helpers/vite.mjs +11 -11
- package/dist/{host-h3-Dgpgr1Ul.mjs → host-h3-C5SZlk03.mjs} +134 -6
- package/dist/{index-C7M1hnvL.d.mts → index-CxaPKDXX.d.mts} +2 -2
- package/dist/{index-DH2sBIwd.d.mts → index-DXHWuwJk.d.mts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +1 -1
- package/dist/{launch-editor-BbNhtg7b.mjs → launch-editor-DPfltGA4.mjs} +88 -13
- package/dist/node/auth.d.mts +43 -23
- package/dist/node/auth.mjs +84 -37
- package/dist/node/hub-internals.d.mts +2 -2
- package/dist/node/hub-internals.mjs +2 -2
- package/dist/node/index.d.mts +22 -6
- package/dist/node/index.mjs +4 -4
- package/dist/recipes/open-helpers.d.mts +1 -1
- package/dist/recipes/open-helpers.mjs +3 -3
- package/dist/revoke-ENfxWkFK.mjs +79 -0
- package/dist/rpc/dump.d.mts +1 -1
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +3 -3
- package/dist/rpc/index.mjs +4 -4
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +2 -2
- package/dist/rpc/transports/ws-server.d.mts +2 -2
- package/dist/rpc/transports/ws-server.mjs +154 -61
- package/dist/{serialization-BD_qXGjd.mjs → serialization-DpLXCy13.mjs} +1 -1
- package/dist/{server-BBaBJaUL.mjs → server-Dl6TU5LE.mjs} +19 -14
- package/dist/server-rX781kz-.d.mts +90 -0
- package/dist/{shared-state-u0y123fi.mjs → shared-state-D4PPieA0.mjs} +4 -4
- package/dist/{shared-state-BlBNYziY.mjs → storage-l2ezeend.mjs} +128 -6
- package/dist/types/index.d.mts +4 -4
- package/dist/{types-BkkQ0Txg.d.mts → types-DZEx4ffs.d.mts} +9 -1
- package/dist/utils/crypto-token.d.mts +24 -0
- package/dist/utils/crypto-token.mjs +45 -0
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/hash.mjs +1 -1
- package/dist/utils/launch-editor.mjs +1 -1
- package/dist/utils/open.mjs +1 -1
- package/dist/utils/scope.d.mts +11 -0
- package/dist/utils/scope.mjs +15 -0
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/utils/structured-clone.mjs +1 -1
- package/dist/{ws-client-CVYX9niP.d.mts → ws-client-D0z0pOhn.d.mts} +1 -1
- package/dist/ws-server-Bc2wBHl-.d.mts +119 -0
- package/package.json +12 -7
- package/skills/devframe/SKILL.md +123 -23
- package/skills/devframe/templates/counter-devframe.ts +14 -4
- package/skills/devframe/templates/spa-devframe.ts +13 -3
- package/skills/devframe/templates/vite-client.ts +3 -2
- package/dist/context-DaKmhhHY.mjs +0 -164
- package/dist/revoke-CL0LSAN9.mjs +0 -803
- package/dist/server-wHlpcdZ9.d.mts +0 -55
- package/dist/utils/human-id.d.mts +0 -8
- package/dist/utils/human-id.mjs +0 -769
- package/dist/ws-server-C1LjmRnp.d.mts +0 -61
- /package/dist/{define-CW9gLnyG.mjs → define-BLWPsH6y.mjs} +0 -0
- /package/dist/{diagnostics-reporter-CBBZwoMv.mjs → diagnostics-reporter-CsIG85Q5.mjs} +0 -0
- /package/dist/{hash-bwOD8RgU.mjs → hash-DFc5WwhO.mjs} +0 -0
- /package/dist/{open-DiQn6zCH.mjs → open-Dusa2Zzd.mjs} +0 -0
- /package/dist/{structured-clone-PdCZwt7F.mjs → structured-clone-CeZOHvkd.mjs} +0 -0
- /package/dist/{structured-clone-jegjz0hM.mjs → structured-clone-XpHLZ8nr.mjs} +0 -0
- /package/dist/{transports-DTFoMUbE.mjs → transports-BmDVn4SF.mjs} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { _ as RpcFunctionDefinition } from "./types-DZEx4ffs.mjs";
|
|
2
|
+
import { S as RpcFunctionsCollectorBase } from "./index-CxaPKDXX.mjs";
|
|
3
|
+
import { t as DevframeNodeRpcSessionMeta } from "./ws-server-Bc2wBHl-.mjs";
|
|
3
4
|
import { CAC } from "cac";
|
|
4
5
|
import { GenericSchema, InferOutput } from "valibot";
|
|
5
6
|
import { BirpcReturn } from "birpc";
|
|
@@ -368,6 +369,19 @@ interface DevframeHost {
|
|
|
368
369
|
* for build snapshots).
|
|
369
370
|
*/
|
|
370
371
|
mountStatic: (base: string, distDir: string) => void | Promise<void>;
|
|
372
|
+
/**
|
|
373
|
+
* Serve the host's connection meta (`__connection.json`) at the given URL
|
|
374
|
+
* base, so a devframe SPA mounted there can discover the RPC/WS endpoint
|
|
375
|
+
* via `connectDevframe()`'s relative `./__connection.json` fetch.
|
|
376
|
+
*
|
|
377
|
+
* Called by `mountDevframe` for each mounted devframe (alongside
|
|
378
|
+
* `mountStatic`). Without it, an embedded SPA can only discover the
|
|
379
|
+
* endpoint by inheriting it from a same-origin parent window — which fails
|
|
380
|
+
* for cross-origin or sandboxed iframes. Implementations serve the same
|
|
381
|
+
* meta they expose at the hub's own base. Optional: hosts that can't serve
|
|
382
|
+
* a dynamic route (e.g. static-snapshot builds) may omit it.
|
|
383
|
+
*/
|
|
384
|
+
mountConnectionMeta?: (base: string) => void | Promise<void>;
|
|
371
385
|
/**
|
|
372
386
|
* Return the public origin the host is reachable at, e.g.
|
|
373
387
|
* `http://localhost:5173`. Used by the dock host to enrich remote
|
|
@@ -400,6 +414,14 @@ interface DevframeHost {
|
|
|
400
414
|
* To be extended
|
|
401
415
|
*/
|
|
402
416
|
interface DevframeRpcClientFunctions {
|
|
417
|
+
/**
|
|
418
|
+
* Server→client notification that this connection's auth token has been
|
|
419
|
+
* revoked. The client drops to untrusted on receipt. Broadcast by
|
|
420
|
+
* `revokeActiveConnectionsForToken`.
|
|
421
|
+
*
|
|
422
|
+
* @internal
|
|
423
|
+
*/
|
|
424
|
+
'devframe:auth:revoked': () => Promise<void>;
|
|
403
425
|
/**
|
|
404
426
|
* Streaming chunk pushed from server to subscribed clients. Wired by
|
|
405
427
|
* `RpcStreamingHost`; do not register manually.
|
|
@@ -424,11 +446,54 @@ interface DevframeRpcClientFunctions {
|
|
|
424
446
|
* @internal
|
|
425
447
|
*/
|
|
426
448
|
'devframe:streaming:upload-cancel': (channel: string, id: string) => Promise<void>;
|
|
449
|
+
/**
|
|
450
|
+
* Full shared-state snapshot pushed from server to subscribed clients.
|
|
451
|
+
* Wired by `RpcSharedStateHost`; do not register manually.
|
|
452
|
+
*
|
|
453
|
+
* @internal
|
|
454
|
+
*/
|
|
455
|
+
'devframe:rpc:client-state:updated': (key: string, fullState: any, syncId: string) => Promise<void>;
|
|
456
|
+
/**
|
|
457
|
+
* Incremental shared-state patch pushed from server to subscribed clients.
|
|
458
|
+
* Wired by `RpcSharedStateHost`; do not register manually.
|
|
459
|
+
*
|
|
460
|
+
* @internal
|
|
461
|
+
*/
|
|
462
|
+
'devframe:rpc:client-state:patch': (key: string, patches: any[], syncId: string) => Promise<void>;
|
|
427
463
|
}
|
|
428
464
|
/**
|
|
429
465
|
* To be extended
|
|
430
466
|
*/
|
|
431
467
|
interface DevframeRpcServerFunctions {
|
|
468
|
+
/**
|
|
469
|
+
* Authenticate a connection with a previously-issued bearer token; resolves
|
|
470
|
+
* whether the connection is now trusted. The interactive handler is provided
|
|
471
|
+
* by the host adapter (e.g. Vite DevTools); the standalone server registers
|
|
472
|
+
* an auto-trust noop when `auth: false`.
|
|
473
|
+
*
|
|
474
|
+
* @internal
|
|
475
|
+
*/
|
|
476
|
+
'devframe:anonymous:auth': (params: {
|
|
477
|
+
authToken: string;
|
|
478
|
+
ua: string;
|
|
479
|
+
origin: string;
|
|
480
|
+
}) => Promise<{
|
|
481
|
+
isTrusted: boolean;
|
|
482
|
+
}>;
|
|
483
|
+
/**
|
|
484
|
+
* Exchange a one-time authentication code (shown by the dev server) for a fresh,
|
|
485
|
+
* node-issued bearer token, returning the token on success or `null`. The
|
|
486
|
+
* handler is provided by the host adapter on top of `exchangeTempAuthCode`.
|
|
487
|
+
*
|
|
488
|
+
* @internal
|
|
489
|
+
*/
|
|
490
|
+
'devframe:auth:exchange': (params: {
|
|
491
|
+
code: string;
|
|
492
|
+
ua: string;
|
|
493
|
+
origin: string;
|
|
494
|
+
}) => Promise<{
|
|
495
|
+
authToken: string | null;
|
|
496
|
+
}>;
|
|
432
497
|
/**
|
|
433
498
|
* Subscribe a client to a shared-state key. Wired by
|
|
434
499
|
* `RpcSharedStateHost`; do not register manually.
|
|
@@ -503,15 +568,6 @@ interface DevframeRpcServerFunctions {
|
|
|
503
568
|
*/
|
|
504
569
|
interface DevframeRpcSharedStates {}
|
|
505
570
|
//#endregion
|
|
506
|
-
//#region src/types/utils.d.ts
|
|
507
|
-
type Thenable<T> = T | Promise<T>;
|
|
508
|
-
type EntriesToObject<T extends readonly [string, any][]> = { [K in T[number] as K[0]]: K[1] };
|
|
509
|
-
type PartialWithoutId<T extends {
|
|
510
|
-
id: string;
|
|
511
|
-
}> = Partial<Omit<T, 'id'>> & {
|
|
512
|
-
id: string;
|
|
513
|
-
};
|
|
514
|
-
//#endregion
|
|
515
571
|
//#region src/types/views.d.ts
|
|
516
572
|
interface DevframeViewHost {
|
|
517
573
|
/**
|
|
@@ -529,6 +585,188 @@ interface DevframeViewHost {
|
|
|
529
585
|
hostStatic: (baseUrl: string, distDir: string) => void;
|
|
530
586
|
}
|
|
531
587
|
//#endregion
|
|
588
|
+
//#region src/types/scope.d.ts
|
|
589
|
+
type AnyRpcFn = (...args: any[]) => any;
|
|
590
|
+
/**
|
|
591
|
+
* Augmentable registry mapping a scope namespace to the shape of its
|
|
592
|
+
* persisted settings. Tools augment it so `ctx.scope('my-plugin')`
|
|
593
|
+
* gets a fully-typed `settings.global` / `settings.project`:
|
|
594
|
+
*
|
|
595
|
+
* ```ts
|
|
596
|
+
* declare module 'devframe' {
|
|
597
|
+
* interface DevframeSettingsRegistry {
|
|
598
|
+
* 'my-plugin': { theme: 'light' | 'dark', recentFiles: string[] }
|
|
599
|
+
* }
|
|
600
|
+
* }
|
|
601
|
+
* ```
|
|
602
|
+
*/
|
|
603
|
+
interface DevframeSettingsRegistry {}
|
|
604
|
+
/**
|
|
605
|
+
* Resolve the settings shape for a namespace from
|
|
606
|
+
* {@link DevframeSettingsRegistry}, falling back to an open record when
|
|
607
|
+
* the namespace hasn't been augmented.
|
|
608
|
+
*/
|
|
609
|
+
type SettingsForNamespace<NS extends string> = NS extends keyof DevframeSettingsRegistry ? DevframeSettingsRegistry[NS] extends Record<string, any> ? DevframeSettingsRegistry[NS] : Record<string, any> : Record<string, any>;
|
|
610
|
+
/**
|
|
611
|
+
* A persisted key-value settings store for one scope (`global` or
|
|
612
|
+
* `project`). Backed by a file on the node side and by the shared-state
|
|
613
|
+
* sync protocol on the client, so a `set` on either side propagates to
|
|
614
|
+
* every connected peer and survives restarts.
|
|
615
|
+
*
|
|
616
|
+
* Every method is async because the underlying shared state is resolved
|
|
617
|
+
* lazily on first access.
|
|
618
|
+
*/
|
|
619
|
+
interface DevframeSettingsStore<T extends Record<string, any> = Record<string, any>> {
|
|
620
|
+
/** Read a single setting. Resolves to `undefined` when unset. */
|
|
621
|
+
get: <K extends keyof T>(key: K) => Promise<T[K] | undefined>;
|
|
622
|
+
/** Write a single setting. */
|
|
623
|
+
set: <K extends keyof T>(key: K, value: T[K]) => Promise<void>;
|
|
624
|
+
/** Remove a single setting. */
|
|
625
|
+
delete: <K extends keyof T>(key: K) => Promise<void>;
|
|
626
|
+
/** Read the whole settings object (immutable snapshot). */
|
|
627
|
+
all: () => Promise<Readonly<T>>;
|
|
628
|
+
/**
|
|
629
|
+
* Subscribe to settings changes. Resolves to an unsubscribe function.
|
|
630
|
+
* Fires on every local or remote mutation with the full snapshot.
|
|
631
|
+
*/
|
|
632
|
+
onChange: (fn: (value: Readonly<T>) => void) => Promise<() => void>;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* The two settings scopes available on a scoped context.
|
|
636
|
+
*
|
|
637
|
+
* - `project` — per-workspace state, persisted under the host's
|
|
638
|
+
* `workspace` storage dir. Project-local settings.
|
|
639
|
+
* - `global` — per-user state, persisted under the host's `global`
|
|
640
|
+
* storage dir. Machine-wide preferences.
|
|
641
|
+
*/
|
|
642
|
+
interface DevframeSettings<T extends Record<string, any> = Record<string, any>> {
|
|
643
|
+
global: DevframeSettingsStore<T>;
|
|
644
|
+
project: DevframeSettingsStore<T>;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Map the server-side RPC registry down to the bare names owned by a
|
|
648
|
+
* namespace, so a scoped `call('get-cwd')` is typed without the
|
|
649
|
+
* `my-plugin:` prefix.
|
|
650
|
+
*/
|
|
651
|
+
type ScopedServerFunctions<NS extends string> = { [K in keyof DevframeRpcServerFunctions as K extends `${NS}:${infer R}` ? R : never]: DevframeRpcServerFunctions[K] };
|
|
652
|
+
/**
|
|
653
|
+
* Map the client-side RPC registry down to the bare names owned by a
|
|
654
|
+
* namespace, used by scoped `broadcast`.
|
|
655
|
+
*/
|
|
656
|
+
type ScopedClientFunctions<NS extends string> = { [K in keyof DevframeRpcClientFunctions as K extends `${NS}:${infer R}` ? R : never]: DevframeRpcClientFunctions[K] };
|
|
657
|
+
/**
|
|
658
|
+
* Map the shared-state registry down to the bare keys owned by a
|
|
659
|
+
* namespace, so scoped `sharedState('messages')` is typed without the
|
|
660
|
+
* `my-plugin:` prefix.
|
|
661
|
+
*/
|
|
662
|
+
type ScopedSharedStates<NS extends string> = { [K in keyof DevframeRpcSharedStates as K extends `${NS}:${infer R}` ? R : never]: DevframeRpcSharedStates[K] };
|
|
663
|
+
/**
|
|
664
|
+
* Broadcast options for a scoped client method (bare name).
|
|
665
|
+
*/
|
|
666
|
+
interface ScopedBroadcastOptions<METHOD, Args extends any[]> {
|
|
667
|
+
method: METHOD;
|
|
668
|
+
args: Args;
|
|
669
|
+
optional?: boolean;
|
|
670
|
+
event?: boolean;
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Node-side streaming host scoped to a namespace. Channel names are
|
|
674
|
+
* auto-prefixed with `<namespace>:`.
|
|
675
|
+
*/
|
|
676
|
+
interface DevframeScopedStreamingHost {
|
|
677
|
+
/**
|
|
678
|
+
* Register a streaming channel. The bare `name` is auto-prefixed with
|
|
679
|
+
* the scope namespace (`<namespace>:<name>`); pass an already-qualified
|
|
680
|
+
* name (containing `:`) to opt out.
|
|
681
|
+
*/
|
|
682
|
+
create: <T = unknown>(name: string, opts?: RpcStreamingChannelOptions) => RpcStreamingChannel<T>;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* The scoped node RPC surface exposed on `ctx.scope('my-plugin').rpc`.
|
|
686
|
+
* IDs and keys you pass are auto-namespaced with `my-plugin:`.
|
|
687
|
+
*/
|
|
688
|
+
interface DevframeScopedNodeRpc<NS extends string = string> {
|
|
689
|
+
/** The namespace this surface is scoped to. */
|
|
690
|
+
readonly namespace: NS;
|
|
691
|
+
/**
|
|
692
|
+
* Register a server RPC function. The definition's `name` must be bare
|
|
693
|
+
* (no `:`); it is stored as `<namespace>:<name>`. Throws `DF0034` if an
|
|
694
|
+
* already-namespaced name is passed.
|
|
695
|
+
*/
|
|
696
|
+
register: (fn: RpcFunctionDefinition<string, any, any, any, any, any, DevframeNodeContext>, force?: boolean) => void;
|
|
697
|
+
/**
|
|
698
|
+
* Update a previously registered server RPC function. Same naming rules
|
|
699
|
+
* as {@link DevframeScopedNodeRpc.register}.
|
|
700
|
+
*/
|
|
701
|
+
update: (fn: RpcFunctionDefinition<string, any, any, any, any, any, DevframeNodeContext>, force?: boolean) => void;
|
|
702
|
+
/**
|
|
703
|
+
* Invoke a locally registered server RPC function. Bare names are
|
|
704
|
+
* resolved within this namespace; pass a fully-qualified name
|
|
705
|
+
* (containing `:`) to call another scope's function.
|
|
706
|
+
*/
|
|
707
|
+
call: {
|
|
708
|
+
<T extends keyof ScopedServerFunctions<NS> & string>(method: T, ...args: Parameters<Extract<ScopedServerFunctions<NS>[T], AnyRpcFn>>): Promise<Awaited<ReturnType<Extract<ScopedServerFunctions<NS>[T], AnyRpcFn>>>>;
|
|
709
|
+
<T extends keyof DevframeRpcServerFunctions & string>(method: T, ...args: Parameters<Extract<DevframeRpcServerFunctions[T], AnyRpcFn>>): Promise<Awaited<ReturnType<Extract<DevframeRpcServerFunctions[T], AnyRpcFn>>>>;
|
|
710
|
+
(method: string, ...args: any[]): Promise<any>;
|
|
711
|
+
};
|
|
712
|
+
/**
|
|
713
|
+
* Broadcast a client RPC event to every connected client. Bare method
|
|
714
|
+
* names are resolved within this namespace.
|
|
715
|
+
*/
|
|
716
|
+
broadcast: {
|
|
717
|
+
<T extends keyof ScopedClientFunctions<NS> & string>(options: ScopedBroadcastOptions<T, Parameters<Extract<ScopedClientFunctions<NS>[T], AnyRpcFn>>>): Promise<void>;
|
|
718
|
+
(options: ScopedBroadcastOptions<string, any[]>): Promise<void>;
|
|
719
|
+
};
|
|
720
|
+
/**
|
|
721
|
+
* Resolve a namespaced shared state. Bare keys are resolved within this
|
|
722
|
+
* namespace; pass a fully-qualified key (containing `:`) to opt out.
|
|
723
|
+
*/
|
|
724
|
+
sharedState: {
|
|
725
|
+
<T extends keyof ScopedSharedStates<NS> & string>(key: T, options?: RpcSharedStateGetOptions<ScopedSharedStates<NS>[T]>): Promise<SharedState<ScopedSharedStates<NS>[T]>>;
|
|
726
|
+
<T extends Record<string, any> = Record<string, any>>(key: string, options?: RpcSharedStateGetOptions<T>): Promise<SharedState<T>>;
|
|
727
|
+
};
|
|
728
|
+
/** Streaming host scoped to this namespace. */
|
|
729
|
+
streaming: DevframeScopedStreamingHost;
|
|
730
|
+
/** Pass-through to the current RPC session, when called inside a handler. */
|
|
731
|
+
getCurrentRpcSession: () => DevframeNodeRpcSession | undefined;
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* A namespace-scoped view of {@link DevframeNodeContext}. Returned by
|
|
735
|
+
* `ctx.scope('my-plugin')`. Re-exposes the unscoped surfaces (`views`,
|
|
736
|
+
* `diagnostics`, `agent`, …), replaces `rpc` with the auto-namespaced
|
|
737
|
+
* {@link DevframeScopedNodeRpc}, and adds a top-level `settings` store.
|
|
738
|
+
*/
|
|
739
|
+
interface DevframeScopedNodeContext<NS extends string = string, Settings extends Record<string, any> = Record<string, any>> {
|
|
740
|
+
/** The namespace this context is scoped to. */
|
|
741
|
+
readonly namespace: NS;
|
|
742
|
+
/** The underlying unscoped context. */
|
|
743
|
+
readonly base: DevframeNodeContext;
|
|
744
|
+
readonly workspaceRoot: string;
|
|
745
|
+
readonly cwd: string;
|
|
746
|
+
readonly mode: 'dev' | 'build';
|
|
747
|
+
host: DevframeHost;
|
|
748
|
+
rpc: DevframeScopedNodeRpc<NS>;
|
|
749
|
+
/** Persisted settings for this namespace (`global` + `project`). */
|
|
750
|
+
settings: DevframeSettings<Settings>;
|
|
751
|
+
views: DevframeViewHost;
|
|
752
|
+
diagnostics: DevframeDiagnosticsHost;
|
|
753
|
+
agent: DevframeAgentHost;
|
|
754
|
+
/**
|
|
755
|
+
* Return a new scoped context, replacing the current scope. Pass `null`
|
|
756
|
+
* or `''` to un-scope and get the base context.
|
|
757
|
+
*/
|
|
758
|
+
scope: DevframeNodeContext['scope'];
|
|
759
|
+
}
|
|
760
|
+
//#endregion
|
|
761
|
+
//#region src/types/utils.d.ts
|
|
762
|
+
type Thenable<T> = T | Promise<T>;
|
|
763
|
+
type EntriesToObject<T extends readonly [string, any][]> = { [K in T[number] as K[0]]: K[1] };
|
|
764
|
+
type PartialWithoutId<T extends {
|
|
765
|
+
id: string;
|
|
766
|
+
}> = Partial<Omit<T, 'id'>> & {
|
|
767
|
+
id: string;
|
|
768
|
+
};
|
|
769
|
+
//#endregion
|
|
532
770
|
//#region src/utils/shared-state.d.ts
|
|
533
771
|
type ImmutablePrimitive = undefined | null | boolean | string | number | Function;
|
|
534
772
|
type Immutable<T> = T extends ImmutablePrimitive ? T : T extends Array<infer U> ? ImmutableArray<U> : T extends Map<infer K, infer V> ? ImmutableMap<K, V> : T extends Set<infer M> ? ImmutableSet<M> : ImmutableObject<T>;
|
|
@@ -755,7 +993,7 @@ interface RpcSharedStateGetOptions<T> {
|
|
|
755
993
|
initialValue?: T;
|
|
756
994
|
}
|
|
757
995
|
interface RpcSharedStateHost {
|
|
758
|
-
get: <T extends
|
|
996
|
+
get: <T extends object = any>(key: string, options?: RpcSharedStateGetOptions<T>) => Promise<SharedState<T>>;
|
|
759
997
|
keys: () => string[];
|
|
760
998
|
/**
|
|
761
999
|
* Subscribe to new shared-state keys becoming available. Fires when
|
|
@@ -917,10 +1155,55 @@ interface DevframeNodeContext {
|
|
|
917
1155
|
* @experimental
|
|
918
1156
|
*/
|
|
919
1157
|
agent: DevframeAgentHost;
|
|
1158
|
+
/**
|
|
1159
|
+
* Create a namespace-scoped view of this context. The returned
|
|
1160
|
+
* `ctx.scope('my-plugin')` auto-namespaces every RPC id, shared-state
|
|
1161
|
+
* key, and streaming channel with `my-plugin:`, and exposes a typed
|
|
1162
|
+
* top-level `settings` store. This is the preferred way to consume the
|
|
1163
|
+
* context from a single tool's setup code.
|
|
1164
|
+
*
|
|
1165
|
+
* Pass `null` or `''` to un-scope and get the base context.
|
|
1166
|
+
*/
|
|
1167
|
+
scope: {
|
|
1168
|
+
<NS extends string>(namespace: NS): DevframeScopedNodeContext<NS, SettingsForNamespace<NS>>;
|
|
1169
|
+
(namespace?: null | ''): DevframeNodeContext;
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Describes where the browser client should open its RPC WebSocket. The
|
|
1174
|
+
* object form is the proxy-flexible default: `path` is resolved relative to
|
|
1175
|
+
* where `__connection.json` was loaded, and the connection is made to the
|
|
1176
|
+
* page's own origin (only the `http`→`ws` / `https`→`wss` protocol swap is
|
|
1177
|
+
* applied). This survives reverse proxies that change the host/port, because
|
|
1178
|
+
* the client never trusts a server-baked hostname — it reuses its own.
|
|
1179
|
+
*
|
|
1180
|
+
* Set `port` (and/or `host`) only when the WS endpoint genuinely lives on a
|
|
1181
|
+
* different origin than the page, e.g. a side-car server on its own port.
|
|
1182
|
+
*/
|
|
1183
|
+
interface ConnectionMetaWebsocket {
|
|
1184
|
+
/**
|
|
1185
|
+
* Path to the WS endpoint. Relative paths (the default, e.g. `__devframe_ws`) are
|
|
1186
|
+
* resolved against `__connection.json`'s location; absolute paths (`/__devframe_ws`)
|
|
1187
|
+
* resolve against the page origin.
|
|
1188
|
+
*/
|
|
1189
|
+
path?: string;
|
|
1190
|
+
/** Override the port. Combined with the page hostname unless `host` is set. */
|
|
1191
|
+
port?: number;
|
|
1192
|
+
/** Override the host (`hostname[:port]`). Use for a fully cross-origin endpoint. */
|
|
1193
|
+
host?: string;
|
|
920
1194
|
}
|
|
921
1195
|
interface ConnectionMeta {
|
|
922
1196
|
backend: 'websocket' | 'static';
|
|
923
|
-
|
|
1197
|
+
/**
|
|
1198
|
+
* WebSocket endpoint, resolved by the client into a `ws(s)://` URL:
|
|
1199
|
+
*
|
|
1200
|
+
* - {@link ConnectionMetaWebsocket} — the proxy-flexible default; a
|
|
1201
|
+
* same-origin path relative to `__connection.json`.
|
|
1202
|
+
* - `number` — a port on the page's hostname (`ws(s)://<host>:<port>`).
|
|
1203
|
+
* - `string` — a full `ws://`/`wss://` URL used verbatim, an `http(s)://`
|
|
1204
|
+
* URL with its protocol swapped, or a path resolved same-origin.
|
|
1205
|
+
*/
|
|
1206
|
+
websocket?: number | string | ConnectionMetaWebsocket;
|
|
924
1207
|
/**
|
|
925
1208
|
* Names of RPC functions that have declared `jsonSerializable: true`.
|
|
926
1209
|
* Used by the WS / static client to dispatch the per-call wire
|
|
@@ -941,6 +1224,51 @@ type DevframeRuntime = 'cli' | 'build' | 'spa' | 'vite' | 'embedded';
|
|
|
941
1224
|
* (`cli`, `spa`, `build`) own the origin and default to `/`.
|
|
942
1225
|
*/
|
|
943
1226
|
type DevframeDeploymentKind = 'standalone' | 'hosted';
|
|
1227
|
+
/**
|
|
1228
|
+
* How a hub deduplicates devframes that share an `id` when more than one
|
|
1229
|
+
* is mounted onto the same hub. See {@link DevframeDefinition.duplicationStrategy}.
|
|
1230
|
+
*
|
|
1231
|
+
* - `'warn'` (default) — keep the first registration, drop later
|
|
1232
|
+
* duplicates, and emit a warning diagnostic (`DF8105`).
|
|
1233
|
+
* - `'silent'` — drop later duplicates without warning.
|
|
1234
|
+
* - `'throw'` — throw when a duplicate is mounted.
|
|
1235
|
+
* - `'duplicate'` — let every instance coexist under a disambiguated
|
|
1236
|
+
* dock id.
|
|
1237
|
+
*/
|
|
1238
|
+
type DevframeDuplicationStrategy = 'warn' | 'silent' | 'throw' | 'duplicate';
|
|
1239
|
+
/**
|
|
1240
|
+
* Controls where the browser opens the RPC WebSocket — advertised in
|
|
1241
|
+
* `__connection.json` and used to bind the dev server. The three shapes map
|
|
1242
|
+
* to the three connection scenarios; precedence is `url` > `port` > `route`:
|
|
1243
|
+
*
|
|
1244
|
+
* 1. **Same server, different route** (default) — leave `port`/`url` unset.
|
|
1245
|
+
* The socket shares the HTTP server's port and binds to `route`
|
|
1246
|
+
* (`__devframe_ws`). The client connects to its own origin, so the link
|
|
1247
|
+
* survives a reverse proxy that rewrites the host/port/subpath.
|
|
1248
|
+
*
|
|
1249
|
+
* 2. **Different port** — set `port`. The socket binds on its own port on the
|
|
1250
|
+
* same host; the client targets `ws(s)://<page-host>:<port>/<route>`.
|
|
1251
|
+
*
|
|
1252
|
+
* 3. **Remote, different origin** — set `url` to a full `ws://`/`wss://`
|
|
1253
|
+
* endpoint (e.g. a public tunnel or relay). The client uses it verbatim.
|
|
1254
|
+
*/
|
|
1255
|
+
interface DevframeWsOptions {
|
|
1256
|
+
/**
|
|
1257
|
+
* Upgrade route segment the socket binds to and is advertised at, relative
|
|
1258
|
+
* to the SPA base. Default: `__devframe_ws`.
|
|
1259
|
+
*/
|
|
1260
|
+
route?: string;
|
|
1261
|
+
/**
|
|
1262
|
+
* Bind the socket on its own port instead of sharing the HTTP port. The
|
|
1263
|
+
* browser connects to this port on the page's hostname.
|
|
1264
|
+
*/
|
|
1265
|
+
port?: number;
|
|
1266
|
+
/**
|
|
1267
|
+
* Advertise a fixed, fully-qualified endpoint on another origin (a full
|
|
1268
|
+
* `ws://`/`wss://` URL). Takes precedence over `port`/`route` in the meta.
|
|
1269
|
+
*/
|
|
1270
|
+
url?: string;
|
|
1271
|
+
}
|
|
944
1272
|
interface DevframeCliOptions {
|
|
945
1273
|
/** Binary name; default: the devframe's `id`. */
|
|
946
1274
|
command?: string;
|
|
@@ -969,6 +1297,12 @@ interface DevframeCliOptions {
|
|
|
969
1297
|
auth?: boolean;
|
|
970
1298
|
/** Author's SPA dist directory (served as the devframe's UI). */
|
|
971
1299
|
distDir?: string;
|
|
1300
|
+
/**
|
|
1301
|
+
* How the browser reaches the RPC WebSocket. Defaults to sharing the HTTP
|
|
1302
|
+
* port on the `__devframe_ws` route. See {@link DevframeWsOptions} for the
|
|
1303
|
+
* different-port and remote-origin variants.
|
|
1304
|
+
*/
|
|
1305
|
+
ws?: DevframeWsOptions;
|
|
972
1306
|
/**
|
|
973
1307
|
* Capability-side CAC hook. Called with the CAC instance after the
|
|
974
1308
|
* adapter registers its built-in commands (`build` / `spa` / `mcp`)
|
|
@@ -1031,17 +1365,33 @@ interface DevframeSetupInfo {
|
|
|
1031
1365
|
interface DevframeDefinition {
|
|
1032
1366
|
id: string;
|
|
1033
1367
|
name: string;
|
|
1368
|
+
/** Semver of the tool, surfaced in hub UIs and diagnostics. */
|
|
1369
|
+
version: string;
|
|
1370
|
+
/** npm package name the devframe ships in (e.g. `@scope/my-tool`). */
|
|
1371
|
+
packageName: string;
|
|
1372
|
+
/** Project homepage or documentation URL. */
|
|
1373
|
+
homepage: string;
|
|
1374
|
+
/** One-line summary of what the tool does. */
|
|
1375
|
+
description: string;
|
|
1034
1376
|
icon?: string | {
|
|
1035
1377
|
light: string;
|
|
1036
1378
|
dark: string;
|
|
1037
1379
|
};
|
|
1038
|
-
version?: string;
|
|
1039
1380
|
/**
|
|
1040
1381
|
* Mount path override. Defaults depend on the adapter:
|
|
1041
1382
|
* `/` for standalone (`cli` / `spa` / `build`), `/__<id>/` for hosted
|
|
1042
1383
|
* (`vite` / `embedded`).
|
|
1043
1384
|
*/
|
|
1044
1385
|
basePath?: string;
|
|
1386
|
+
/**
|
|
1387
|
+
* How a hub reacts when another devframe sharing this one's `id` is
|
|
1388
|
+
* mounted onto the same hub. Consulted only by hub adapters
|
|
1389
|
+
* (`mountDevframe`); standalone adapters (`cli` / `spa` / `build`)
|
|
1390
|
+
* ignore it.
|
|
1391
|
+
*
|
|
1392
|
+
* @default 'warn'
|
|
1393
|
+
*/
|
|
1394
|
+
duplicationStrategy?: DevframeDuplicationStrategy;
|
|
1045
1395
|
capabilities?: {
|
|
1046
1396
|
dev?: boolean | Record<string, boolean>;
|
|
1047
1397
|
build?: boolean | Record<string, boolean>;
|
|
@@ -1056,4 +1406,4 @@ interface DevframeDefinition {
|
|
|
1056
1406
|
}
|
|
1057
1407
|
declare function defineDevframe(d: DevframeDefinition): DevframeDefinition;
|
|
1058
1408
|
//#endregion
|
|
1059
|
-
export {
|
|
1409
|
+
export { ScopedServerFunctions as $, createStreamReader as A, SharedStatePatch as B, BufferedChunk as C, CliFlagsSchema as Ct, StreamReader as D, StreamErrorPayload as E, parseCliFlags as Et, ImmutableObject as F, DevframeScopedNodeContext as G, EntriesToObject as H, ImmutableSet as I, DevframeSettings as J, DevframeScopedNodeRpc as K, SharedState as L, Immutable as M, ImmutableArray as N, StreamSink as O, ImmutableMap as P, ScopedClientFunctions as Q, SharedStateEvents as R, RpcStreamingHost as S, EventsMap as St, CreateStreamSinkOptions as T, defineCliFlags as Tt, PartialWithoutId as U, createSharedState as V, Thenable as W, DevframeSettingsStore as X, DevframeSettingsRegistry as Y, ScopedBroadcastOptions as Z, RpcFunctionsHost as _, AgentToolInput as _t, DevframeDuplicationStrategy as a, DevframeRpcSharedStates as at, RpcStreamingChannel as b, EventEmitter as bt, DevframeSpaOptions as c, DevframeDiagnosticsDefinition as ct, ConnectionMeta as d, AgentHandle as dt, ScopedSharedStates as et, ConnectionMetaWebsocket as f, AgentManifest as ft, RpcBroadcastOptions as g, AgentTool as gt, DevframeNodeRpcSession as h, AgentResourceInput as ht, DevframeDeploymentKind as i, DevframeRpcServerFunctions as it, createStreamSink as j, StreamSinkEvents as k, DevframeWsOptions as l, DevframeDiagnosticsHost as lt, DevframeNodeContext as m, AgentResourceContent as mt, DevframeCliOptions as n, DevframeViewHost as nt, DevframeRuntime as o, DevframeHost as ot, DevframeCapabilities as p, AgentResource as pt, DevframeScopedStreamingHost as q, DevframeDefinition as r, DevframeRpcClientFunctions as rt, DevframeSetupInfo as s, DevframeDefineDiagnosticsOptions as st, DevframeBrowserContext as t, SettingsForNamespace as tt, defineDevframe as u, DevframeDiagnosticsLogger as ut, RpcSharedStateGetOptions as v, DevframeAgentHost as vt, CreateStreamReaderOptions as w, InferCliFlags as wt, RpcStreamingChannelOptions as x, EventUnsubscribe as xt, RpcSharedStateHost as y, DevframeAgentHostEvents as yt, SharedStateOptions as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as devframeReporter } from "./diagnostics-reporter-
|
|
1
|
+
import { t as devframeReporter } from "./diagnostics-reporter-CsIG85Q5.mjs";
|
|
2
2
|
import { defineDiagnostics } from "nostics";
|
|
3
3
|
//#region src/rpc/diagnostics.ts
|
|
4
4
|
const diagnostics = defineDiagnostics({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as diagnostics } from "./diagnostics-
|
|
1
|
+
import { t as diagnostics } from "./diagnostics-BXwBQmoN.mjs";
|
|
2
2
|
import { DEVFRAME_RPC_DUMP_DIRNAME } from "./constants.mjs";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
//#region ../../node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/shared/ohash.D__AXeF1.mjs
|
package/dist/helpers/vite.d.mts
CHANGED
package/dist/helpers/vite.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { DEVFRAME_CONNECTION_META_FILENAME } from "../constants.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { n as resolveBasePath } from "../_shared-
|
|
1
|
+
import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_WS_ROUTE } from "../constants.mjs";
|
|
2
|
+
import { a as diagnostics } from "../storage-l2ezeend.mjs";
|
|
3
|
+
import { n as resolveBasePath, t as normalizeBasePath } from "../_shared-bWRzeSa0.mjs";
|
|
4
4
|
import { serveStaticNodeMiddleware } from "../utils/serve-static.mjs";
|
|
5
|
-
import { n as resolveDevServerPort, t as createDevServer } from "../dev-
|
|
5
|
+
import { n as resolveDevServerPort, t as createDevServer } from "../dev-BaX8fLH2.mjs";
|
|
6
6
|
import { resolve } from "pathe";
|
|
7
7
|
//#region src/helpers/vite.ts
|
|
8
8
|
/**
|
|
@@ -66,7 +66,10 @@ function viteDevBridge(d, options = {}) {
|
|
|
66
66
|
res.setHeader("Content-Type", "application/json");
|
|
67
67
|
res.end(JSON.stringify({
|
|
68
68
|
backend: "websocket",
|
|
69
|
-
websocket:
|
|
69
|
+
websocket: {
|
|
70
|
+
port,
|
|
71
|
+
path: `/${DEVFRAME_WS_ROUTE}`
|
|
72
|
+
}
|
|
70
73
|
}));
|
|
71
74
|
});
|
|
72
75
|
server.httpServer?.once("close", () => {
|
|
@@ -82,14 +85,11 @@ function viteDevBridge(d, options = {}) {
|
|
|
82
85
|
/**
|
|
83
86
|
* Make `base` safe for `server.middlewares.use(path, …)`. Vite's connect
|
|
84
87
|
* router matches by absolute URL prefix, so relative spellings like
|
|
85
|
-
* `'./'` (commonly used for base-agnostic Nuxt builds)
|
|
86
|
-
*
|
|
88
|
+
* `'./'` (commonly used for base-agnostic Nuxt builds) collapse to the
|
|
89
|
+
* origin root before the shared leading/trailing-slash normalization.
|
|
87
90
|
*/
|
|
88
91
|
function normalizeMountBase(base) {
|
|
89
|
-
|
|
90
|
-
if (!out.startsWith("/")) out = `/${out}`;
|
|
91
|
-
if (!out.endsWith("/")) out = `${out}/`;
|
|
92
|
-
return out.replace(/\/+/g, "/");
|
|
92
|
+
return normalizeBasePath(base.replace(/^\.\/?/, "/"));
|
|
93
93
|
}
|
|
94
94
|
//#endregion
|
|
95
95
|
export { viteDevBridge };
|