devframe 0.1.19 → 0.1.20
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/README.md +2 -2
- package/dist/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +9 -6
- package/dist/adapters/cli.d.mts +1 -1
- package/dist/adapters/cli.mjs +1 -1
- package/dist/adapters/dev.d.mts +2 -2
- package/dist/adapters/dev.mjs +1 -1
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/kit.d.mts +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.mjs +6 -3
- package/dist/adapters/vite.d.mts +1 -1
- package/dist/adapters/vite.mjs +1 -1
- package/dist/client/index.d.mts +42 -6
- package/dist/client/index.mjs +1673 -2
- package/dist/constants.d.mts +1 -1
- package/dist/{context-BsNZMCnr.mjs → context-BfvbAyGk.mjs} +428 -40
- package/dist/{dev-Djy5hbgs.mjs → dev-B8i_CBlQ.mjs} +6 -5
- package/dist/{devtool-CIqONpYU.d.mts → devtool-Bm6zZAw5.d.mts} +365 -27
- package/dist/host-h3-BMvrFzIJ.mjs +24 -0
- package/dist/{index-BwrLhNmz.d.mts → index-BCo03GEF.d.mts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/node/index.d.mts +44 -7
- package/dist/node/index.mjs +5 -5
- package/dist/recipes/open-helpers.d.mts +1 -1
- package/dist/recipes/open-helpers.mjs +3 -1
- package/dist/rpc/index.d.mts +2 -2
- package/dist/rpc/index.mjs +2 -2
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +1 -1
- package/dist/rpc/transports/ws-server.d.mts +1 -1
- package/dist/rpc/transports/ws-server.mjs +1 -1
- package/dist/{rpc-D7LxIh8t.mjs → rpc-INbWfHoX.mjs} +1 -1
- package/dist/{serialization-BN2ZQEE9.mjs → serialization-DwKi05Pn.mjs} +1 -1
- package/dist/{server-CaUeMcAh.d.mts → server-DksyT-um.d.mts} +1 -1
- package/dist/{server-DrBxa6ZV.mjs → server-qRRM8t3v.mjs} +27 -2
- package/dist/{static-dump-cyGfMmRf.mjs → static-dump-C1aVSwxY.mjs} +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/shared-state.d.mts +2 -2
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/state.d.mts +2 -1
- package/dist/utils/state.mjs +1 -1
- package/dist/utils/streaming-channel.d.mts +2 -0
- package/dist/utils/streaming-channel.mjs +255 -0
- package/dist/utils/when.d.mts +1 -1
- package/dist/{ws-client-DOYwYluO.d.mts → ws-client-DQySVfF_.d.mts} +1 -1
- package/dist/{ws-server-DHMeNOY_.d.mts → ws-server-VQqESKAs.d.mts} +13 -1
- package/package.json +9 -17
- package/skills/devframe/README.md +13 -0
- package/skills/devframe/SKILL.md +452 -0
- package/skills/devframe/templates/counter-devtool.ts +29 -0
- package/skills/devframe/templates/spa-devtool.ts +33 -0
- package/skills/devframe/templates/vite-client.ts +11 -0
- package/dist/client-C6w_NshP.mjs +0 -1569
- package/dist/helpers/nuxt/index.d.mts +0 -46
- package/dist/helpers/nuxt/index.mjs +0 -58
- package/dist/helpers/nuxt/runtime/plugin.client.d.mts +0 -8
- package/dist/helpers/nuxt/runtime/plugin.client.mjs +0 -12
- package/dist/host-h3-w3c0t8ZO.mjs +0 -18
- package/dist/immer-HjMAm3b6.mjs +0 -894
- /package/dist/{_shared-BcPXmcjq.mjs → _shared-S-Ujqz_L.mjs} +0 -0
- /package/dist/{main-CuGOfqoX.mjs → main-DpINGndA.mjs} +0 -0
- /package/dist/{open-JfacLHs0.mjs → open-BtOOEldu.mjs} +0 -0
- /package/dist/{transports-DSV5_5QM.mjs → transports-BPUzHhI2.mjs} +0 -0
- /package/dist/{types-gWbe-b2R.d.mts → types-ag029cAe.d.mts} +0 -0
- /package/dist/{when-BAE663Hv.d.mts → when-aBBXAEh5.d.mts} +0 -0
package/dist/constants.d.mts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { t as import_dist } from "./human-id-CHS0s28X.mjs";
|
|
2
|
-
import { o as RpcFunctionsCollectorBase } from "./rpc-
|
|
3
|
-
import { s as diagnostics$1 } from "./serialization-
|
|
2
|
+
import { o as RpcFunctionsCollectorBase } from "./rpc-INbWfHoX.mjs";
|
|
3
|
+
import { s as diagnostics$1 } from "./serialization-DwKi05Pn.mjs";
|
|
4
4
|
import { defineRpcFunction } from "./index.mjs";
|
|
5
5
|
import { createEventEmitter } from "./utils/events.mjs";
|
|
6
6
|
import { DEFAULT_STATE_USER_SETTINGS, REMOTE_CONNECTION_KEY } from "./constants.mjs";
|
|
7
7
|
import { nanoid } from "./utils/nanoid.mjs";
|
|
8
8
|
import { createSharedState } from "./utils/shared-state.mjs";
|
|
9
|
+
import { createStreamReader, createStreamSink } from "./utils/streaming-channel.mjs";
|
|
9
10
|
import { builtinModules } from "node:module";
|
|
10
11
|
import { consoleReporter, createLogger, defineDiagnostics } from "logs-sdk";
|
|
11
12
|
import fs, { existsSync } from "node:fs";
|
|
@@ -18,7 +19,6 @@ import v8 from "node:v8";
|
|
|
18
19
|
import { format, formatWithOptions, inspect } from "node:util";
|
|
19
20
|
import c from "ansis";
|
|
20
21
|
import { ansiFormatter } from "logs-sdk/formatters/ansi";
|
|
21
|
-
import { homedir } from "node:os";
|
|
22
22
|
import { isatty } from "node:tty";
|
|
23
23
|
//#region src/node/auth-revoke.ts
|
|
24
24
|
/**
|
|
@@ -38,7 +38,7 @@ async function revokeActiveConnectionsForToken(context, token) {
|
|
|
38
38
|
}
|
|
39
39
|
if (affectedSessionIds.size === 0) return;
|
|
40
40
|
await rpcHost.broadcast({
|
|
41
|
-
method: "
|
|
41
|
+
method: "devframe:auth:revoked",
|
|
42
42
|
args: [],
|
|
43
43
|
filter: (client) => affectedSessionIds.has(client.$meta.id)
|
|
44
44
|
});
|
|
@@ -5575,7 +5575,7 @@ const ContextUtils = { createSimpleClientScript(fn) {
|
|
|
5575
5575
|
//#endregion
|
|
5576
5576
|
//#region src/node/diagnostics.ts
|
|
5577
5577
|
const diagnostics = defineDiagnostics({
|
|
5578
|
-
docsBase: "https://
|
|
5578
|
+
docsBase: "https://devfra.me/errors",
|
|
5579
5579
|
codes: {
|
|
5580
5580
|
DF0001: {
|
|
5581
5581
|
message: (p) => `Dock with id "${p.id}" is already registered`,
|
|
@@ -5610,6 +5610,23 @@ const diagnostics = defineDiagnostics({
|
|
|
5610
5610
|
message: "`ctx.logs` is deprecated and will be removed in a future release. Use `ctx.messages` instead.",
|
|
5611
5611
|
hint: "Replace any access to `ctx.logs` (or `context.logs`) with `ctx.messages`. The runtime behavior is identical.",
|
|
5612
5612
|
level: "warn"
|
|
5613
|
+
},
|
|
5614
|
+
DF0029: {
|
|
5615
|
+
message: (p) => `Stream "${p.channel}#${p.id}" dropped ${p.dropped} chunk(s) after exceeding the client high-water mark.`,
|
|
5616
|
+
hint: "The consumer is too slow for the producer. Raise `highWaterMark` on the subscription, slow the producer, or batch chunks.",
|
|
5617
|
+
level: "warn"
|
|
5618
|
+
},
|
|
5619
|
+
DF0030: {
|
|
5620
|
+
message: (p) => `Stream "${p.channel}#${p.id}" is unknown — no producer has called \`channel.start({ id: "${p.id}" })\`.`,
|
|
5621
|
+
hint: "Ensure the server-side producer is running before clients subscribe, or check for typos in the stream id."
|
|
5622
|
+
},
|
|
5623
|
+
DF0031: {
|
|
5624
|
+
message: (p) => `Cannot write to closed stream "${p.channel}#${p.id}".`,
|
|
5625
|
+
hint: "Track the producer lifecycle — guard writes with the `stream.signal.aborted` flag."
|
|
5626
|
+
},
|
|
5627
|
+
DF0032: {
|
|
5628
|
+
message: (p) => `Streaming channel "${p.channel}" is already registered.`,
|
|
5629
|
+
hint: "Each channel name must be unique within a context. Pick a different name or reuse the existing channel handle."
|
|
5613
5630
|
}
|
|
5614
5631
|
}
|
|
5615
5632
|
});
|
|
@@ -5903,7 +5920,7 @@ const internalContextMap = /* @__PURE__ */ new WeakMap();
|
|
|
5903
5920
|
function getInternalContext(context) {
|
|
5904
5921
|
if (!internalContextMap.has(context)) {
|
|
5905
5922
|
const storage = createStorage({
|
|
5906
|
-
filepath: join(
|
|
5923
|
+
filepath: join(context.host.getStorageDir("global"), "auth.json"),
|
|
5907
5924
|
initialValue: { trusted: {} }
|
|
5908
5925
|
});
|
|
5909
5926
|
const remoteTokens = /* @__PURE__ */ new Map();
|
|
@@ -5982,8 +5999,8 @@ var DevToolsDockHost = class {
|
|
|
5982
5999
|
this.context = context;
|
|
5983
6000
|
}
|
|
5984
6001
|
async init() {
|
|
5985
|
-
this.userSettings = await this.context.rpc.sharedState.get("
|
|
5986
|
-
filepath: join(this.context.
|
|
6002
|
+
this.userSettings = await this.context.rpc.sharedState.get("devframe:user-settings", { sharedState: createStorage({
|
|
6003
|
+
filepath: join(this.context.host.getStorageDir("workspace"), "settings.json"),
|
|
5987
6004
|
initialValue: DEFAULT_STATE_USER_SETTINGS()
|
|
5988
6005
|
}) });
|
|
5989
6006
|
}
|
|
@@ -6074,7 +6091,6 @@ var DevToolsDockHost = class {
|
|
|
6074
6091
|
token,
|
|
6075
6092
|
options
|
|
6076
6093
|
});
|
|
6077
|
-
if (view.when === void 0) view.when = "mode != build";
|
|
6078
6094
|
}
|
|
6079
6095
|
};
|
|
6080
6096
|
//#endregion
|
|
@@ -6333,7 +6349,8 @@ function createDebug(namespace, options) {
|
|
|
6333
6349
|
enable(process.env.DEBUG || "");
|
|
6334
6350
|
//#endregion
|
|
6335
6351
|
//#region src/node/rpc-shared-state.ts
|
|
6336
|
-
const debug = createDebug("vite:devtools:rpc:state:changed");
|
|
6352
|
+
const debug$1 = createDebug("vite:devtools:rpc:state:changed");
|
|
6353
|
+
const debugSubscribe = createDebug("vite:devtools:rpc:state:subscribe");
|
|
6337
6354
|
function createRpcSharedStateServerHost(rpc) {
|
|
6338
6355
|
const sharedState = /* @__PURE__ */ new Map();
|
|
6339
6356
|
const keyAddedListeners = /* @__PURE__ */ new Set();
|
|
@@ -6341,12 +6358,12 @@ function createRpcSharedStateServerHost(rpc) {
|
|
|
6341
6358
|
const offs = [];
|
|
6342
6359
|
offs.push(state.on("updated", (fullState, patches, syncId) => {
|
|
6343
6360
|
if (patches) {
|
|
6344
|
-
debug("patch", {
|
|
6361
|
+
debug$1("patch", {
|
|
6345
6362
|
key,
|
|
6346
6363
|
syncId
|
|
6347
6364
|
});
|
|
6348
6365
|
rpc.broadcast({
|
|
6349
|
-
method: "
|
|
6366
|
+
method: "devframe:rpc:client-state:patch",
|
|
6350
6367
|
args: [
|
|
6351
6368
|
key,
|
|
6352
6369
|
patches,
|
|
@@ -6355,12 +6372,12 @@ function createRpcSharedStateServerHost(rpc) {
|
|
|
6355
6372
|
filter: (client) => client.$meta.subscribedStates.has(key)
|
|
6356
6373
|
});
|
|
6357
6374
|
} else {
|
|
6358
|
-
debug("updated", {
|
|
6375
|
+
debug$1("updated", {
|
|
6359
6376
|
key,
|
|
6360
6377
|
syncId
|
|
6361
6378
|
});
|
|
6362
6379
|
rpc.broadcast({
|
|
6363
|
-
method: "
|
|
6380
|
+
method: "devframe:rpc:client-state:updated",
|
|
6364
6381
|
args: [
|
|
6365
6382
|
key,
|
|
6366
6383
|
fullState,
|
|
@@ -6374,11 +6391,11 @@ function createRpcSharedStateServerHost(rpc) {
|
|
|
6374
6391
|
for (const off of offs) off();
|
|
6375
6392
|
};
|
|
6376
6393
|
}
|
|
6377
|
-
|
|
6394
|
+
const host = {
|
|
6378
6395
|
get: async (key, options) => {
|
|
6379
6396
|
if (sharedState.has(key)) return sharedState.get(key);
|
|
6380
6397
|
if (options?.initialValue === void 0 && options?.sharedState === void 0) throw logger.DF0013({ key }).throw();
|
|
6381
|
-
debug("new-state", key);
|
|
6398
|
+
debug$1("new-state", key);
|
|
6382
6399
|
const state = options.sharedState ?? createSharedState({
|
|
6383
6400
|
initialValue: options.initialValue,
|
|
6384
6401
|
enablePatches: false
|
|
@@ -6398,6 +6415,344 @@ function createRpcSharedStateServerHost(rpc) {
|
|
|
6398
6415
|
};
|
|
6399
6416
|
}
|
|
6400
6417
|
};
|
|
6418
|
+
rpc.register({
|
|
6419
|
+
name: "devframe:rpc:server-state:subscribe",
|
|
6420
|
+
type: "event",
|
|
6421
|
+
handler(key) {
|
|
6422
|
+
const session = rpc.getCurrentRpcSession();
|
|
6423
|
+
if (!session) return;
|
|
6424
|
+
debugSubscribe("subscribe", {
|
|
6425
|
+
key,
|
|
6426
|
+
session: session.meta.id
|
|
6427
|
+
});
|
|
6428
|
+
session.meta.subscribedStates.add(key);
|
|
6429
|
+
}
|
|
6430
|
+
});
|
|
6431
|
+
rpc.register({
|
|
6432
|
+
name: "devframe:rpc:server-state:get",
|
|
6433
|
+
type: "query",
|
|
6434
|
+
handler: async (key) => {
|
|
6435
|
+
if (!sharedState.has(key)) return void 0;
|
|
6436
|
+
return (await host.get(key)).value();
|
|
6437
|
+
},
|
|
6438
|
+
dump: () => ({ inputs: host.keys().map((key) => [key]) })
|
|
6439
|
+
});
|
|
6440
|
+
rpc.register({
|
|
6441
|
+
name: "devframe:rpc:server-state:set",
|
|
6442
|
+
type: "query",
|
|
6443
|
+
handler: async (key, value, syncId) => {
|
|
6444
|
+
(await host.get(key, { initialValue: value })).mutate(() => value, syncId);
|
|
6445
|
+
}
|
|
6446
|
+
});
|
|
6447
|
+
rpc.register({
|
|
6448
|
+
name: "devframe:rpc:server-state:patch",
|
|
6449
|
+
type: "query",
|
|
6450
|
+
handler: async (key, patches, syncId) => {
|
|
6451
|
+
if (!sharedState.has(key)) return;
|
|
6452
|
+
(await host.get(key)).patch(patches, syncId);
|
|
6453
|
+
}
|
|
6454
|
+
});
|
|
6455
|
+
return host;
|
|
6456
|
+
}
|
|
6457
|
+
//#endregion
|
|
6458
|
+
//#region src/node/rpc-streaming.ts
|
|
6459
|
+
const debug = createDebug("vite:devtools:rpc:streaming");
|
|
6460
|
+
const STREAM_KEY_SEPARATOR = "";
|
|
6461
|
+
function streamKey(channel, id) {
|
|
6462
|
+
return `${channel}${STREAM_KEY_SEPARATOR}${id}`;
|
|
6463
|
+
}
|
|
6464
|
+
/**
|
|
6465
|
+
* Build the server-side streaming host. Mirrors the layout of
|
|
6466
|
+
* `createRpcSharedStateServerHost` — registers a fixed set of internal
|
|
6467
|
+
* RPC methods (`subscribe` / `unsubscribe` / `cancel`) once, then per-channel
|
|
6468
|
+
* state lives in a `Map<channelName, ChannelState>`.
|
|
6469
|
+
*/
|
|
6470
|
+
function createRpcStreamingServerHost(rpc) {
|
|
6471
|
+
const channels = /* @__PURE__ */ new Map();
|
|
6472
|
+
function findStream(channelName, id) {
|
|
6473
|
+
return channels.get(channelName)?.streams.get(id);
|
|
6474
|
+
}
|
|
6475
|
+
function freeStreamNow(state, id) {
|
|
6476
|
+
const record = state.streams.get(id);
|
|
6477
|
+
if (!record) return;
|
|
6478
|
+
if (record.retentionTimer) {
|
|
6479
|
+
clearTimeout(record.retentionTimer);
|
|
6480
|
+
record.retentionTimer = void 0;
|
|
6481
|
+
}
|
|
6482
|
+
for (const off of record.unbinders) off();
|
|
6483
|
+
state.streams.delete(id);
|
|
6484
|
+
debug("freed", state.name, id);
|
|
6485
|
+
}
|
|
6486
|
+
function maybeFreeStream(state, id) {
|
|
6487
|
+
const record = state.streams.get(id);
|
|
6488
|
+
if (!record) return;
|
|
6489
|
+
if (!record.sink.closed || record.subscribers.size > 0) return;
|
|
6490
|
+
const retention = state.options.closedStreamRetention;
|
|
6491
|
+
if (retention <= 0) {
|
|
6492
|
+
freeStreamNow(state, id);
|
|
6493
|
+
return;
|
|
6494
|
+
}
|
|
6495
|
+
if (record.retentionTimer) return;
|
|
6496
|
+
record.retentionTimer = setTimeout(freeStreamNow, retention, state, id);
|
|
6497
|
+
}
|
|
6498
|
+
function cancelRetention(record) {
|
|
6499
|
+
if (record.retentionTimer) {
|
|
6500
|
+
clearTimeout(record.retentionTimer);
|
|
6501
|
+
record.retentionTimer = void 0;
|
|
6502
|
+
}
|
|
6503
|
+
}
|
|
6504
|
+
rpc.register({
|
|
6505
|
+
name: "devframe:streaming:subscribe",
|
|
6506
|
+
type: "event",
|
|
6507
|
+
handler(channelName, id, opts) {
|
|
6508
|
+
const state = channels.get(channelName);
|
|
6509
|
+
if (!state) {
|
|
6510
|
+
logger.DF0030({
|
|
6511
|
+
channel: channelName,
|
|
6512
|
+
id
|
|
6513
|
+
}).log();
|
|
6514
|
+
return;
|
|
6515
|
+
}
|
|
6516
|
+
const record = state.streams.get(id);
|
|
6517
|
+
if (!record) {
|
|
6518
|
+
logger.DF0030({
|
|
6519
|
+
channel: channelName,
|
|
6520
|
+
id
|
|
6521
|
+
}).log();
|
|
6522
|
+
return;
|
|
6523
|
+
}
|
|
6524
|
+
const session = rpc.getCurrentRpcSession();
|
|
6525
|
+
if (!session) return;
|
|
6526
|
+
const key = streamKey(channelName, id);
|
|
6527
|
+
session.meta.subscribedStreams ??= /* @__PURE__ */ new Set();
|
|
6528
|
+
session.meta.subscribedStreams.add(key);
|
|
6529
|
+
record.subscribers.add(session.meta);
|
|
6530
|
+
cancelRetention(record);
|
|
6531
|
+
const afterSeq = opts?.afterSeq ?? 0;
|
|
6532
|
+
for (const buffered of record.sink.buffer) if (buffered.seq > afterSeq) rpc.broadcast({
|
|
6533
|
+
method: "devframe:streaming:chunk",
|
|
6534
|
+
args: [
|
|
6535
|
+
channelName,
|
|
6536
|
+
id,
|
|
6537
|
+
buffered.seq,
|
|
6538
|
+
buffered.chunk
|
|
6539
|
+
],
|
|
6540
|
+
event: true,
|
|
6541
|
+
optional: true,
|
|
6542
|
+
filter: (client) => client.$meta === session.meta
|
|
6543
|
+
});
|
|
6544
|
+
if (record.sink.closed) rpc.broadcast({
|
|
6545
|
+
method: "devframe:streaming:end",
|
|
6546
|
+
args: [
|
|
6547
|
+
channelName,
|
|
6548
|
+
id,
|
|
6549
|
+
void 0
|
|
6550
|
+
],
|
|
6551
|
+
event: true,
|
|
6552
|
+
optional: true,
|
|
6553
|
+
filter: (client) => client.$meta === session.meta
|
|
6554
|
+
});
|
|
6555
|
+
}
|
|
6556
|
+
});
|
|
6557
|
+
rpc.register({
|
|
6558
|
+
name: "devframe:streaming:unsubscribe",
|
|
6559
|
+
type: "event",
|
|
6560
|
+
handler(channelName, id) {
|
|
6561
|
+
const state = channels.get(channelName);
|
|
6562
|
+
const record = state?.streams.get(id);
|
|
6563
|
+
const session = rpc.getCurrentRpcSession();
|
|
6564
|
+
if (!session) return;
|
|
6565
|
+
session.meta.subscribedStreams?.delete(streamKey(channelName, id));
|
|
6566
|
+
if (state && record) {
|
|
6567
|
+
record.subscribers.delete(session.meta);
|
|
6568
|
+
maybeFreeStream(state, id);
|
|
6569
|
+
}
|
|
6570
|
+
}
|
|
6571
|
+
});
|
|
6572
|
+
rpc.register({
|
|
6573
|
+
name: "devframe:streaming:cancel",
|
|
6574
|
+
type: "event",
|
|
6575
|
+
handler(channelName, id) {
|
|
6576
|
+
const record = findStream(channelName, id);
|
|
6577
|
+
if (!record) return;
|
|
6578
|
+
const session = rpc.getCurrentRpcSession();
|
|
6579
|
+
if (!session) return;
|
|
6580
|
+
record.subscribers.delete(session.meta);
|
|
6581
|
+
session.meta.subscribedStreams?.delete(streamKey(channelName, id));
|
|
6582
|
+
if (record.subscribers.size === 0) record.sink.abort("cancelled by client");
|
|
6583
|
+
}
|
|
6584
|
+
});
|
|
6585
|
+
rpc.register({
|
|
6586
|
+
name: "devframe:streaming:upload-chunk",
|
|
6587
|
+
type: "event",
|
|
6588
|
+
handler(channelName, id, seq, chunk) {
|
|
6589
|
+
const record = channels.get(channelName)?.inbound.get(id);
|
|
6590
|
+
if (!record) {
|
|
6591
|
+
logger.DF0030({
|
|
6592
|
+
channel: channelName,
|
|
6593
|
+
id
|
|
6594
|
+
}).log();
|
|
6595
|
+
return;
|
|
6596
|
+
}
|
|
6597
|
+
if (!record.uploaderMeta) {
|
|
6598
|
+
const session = rpc.getCurrentRpcSession();
|
|
6599
|
+
if (session) {
|
|
6600
|
+
record.uploaderMeta = session.meta;
|
|
6601
|
+
session.meta.uploadingStreams ??= /* @__PURE__ */ new Set();
|
|
6602
|
+
session.meta.uploadingStreams.add(streamKey(channelName, id));
|
|
6603
|
+
}
|
|
6604
|
+
}
|
|
6605
|
+
record.reader._push(seq, chunk);
|
|
6606
|
+
}
|
|
6607
|
+
});
|
|
6608
|
+
rpc.register({
|
|
6609
|
+
name: "devframe:streaming:upload-end",
|
|
6610
|
+
type: "event",
|
|
6611
|
+
handler(channelName, id, error) {
|
|
6612
|
+
const state = channels.get(channelName);
|
|
6613
|
+
const record = state?.inbound.get(id);
|
|
6614
|
+
if (!record) return;
|
|
6615
|
+
record.reader._end(error);
|
|
6616
|
+
if (record.uploaderMeta) record.uploaderMeta.uploadingStreams?.delete(streamKey(channelName, id));
|
|
6617
|
+
state?.inbound.delete(id);
|
|
6618
|
+
}
|
|
6619
|
+
});
|
|
6620
|
+
function createChannel(name, opts = {}) {
|
|
6621
|
+
if (channels.has(name)) throw logger.DF0032({ channel: name }).throw();
|
|
6622
|
+
const replayWindow = opts.replayWindow ?? 0;
|
|
6623
|
+
const state = {
|
|
6624
|
+
name,
|
|
6625
|
+
options: {
|
|
6626
|
+
replayWindow,
|
|
6627
|
+
closedStreamRetention: opts.closedStreamRetention ?? (replayWindow > 0 ? 3e4 : 0)
|
|
6628
|
+
},
|
|
6629
|
+
streams: /* @__PURE__ */ new Map(),
|
|
6630
|
+
inbound: /* @__PURE__ */ new Map()
|
|
6631
|
+
};
|
|
6632
|
+
channels.set(name, state);
|
|
6633
|
+
function start(startOpts = {}) {
|
|
6634
|
+
const sink = createStreamSink({
|
|
6635
|
+
id: startOpts.id,
|
|
6636
|
+
replayWindow: state.options.replayWindow
|
|
6637
|
+
});
|
|
6638
|
+
const record = {
|
|
6639
|
+
sink,
|
|
6640
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
6641
|
+
unbinders: []
|
|
6642
|
+
};
|
|
6643
|
+
state.streams.set(sink.id, record);
|
|
6644
|
+
record.unbinders.push(sink.events.on("chunk", (seq, chunk) => {
|
|
6645
|
+
rpc.broadcast({
|
|
6646
|
+
method: "devframe:streaming:chunk",
|
|
6647
|
+
args: [
|
|
6648
|
+
name,
|
|
6649
|
+
sink.id,
|
|
6650
|
+
seq,
|
|
6651
|
+
chunk
|
|
6652
|
+
],
|
|
6653
|
+
event: true,
|
|
6654
|
+
optional: true,
|
|
6655
|
+
filter: (client) => record.subscribers.has(client.$meta)
|
|
6656
|
+
});
|
|
6657
|
+
}));
|
|
6658
|
+
record.unbinders.push(sink.events.on("end", (error) => {
|
|
6659
|
+
rpc.broadcast({
|
|
6660
|
+
method: "devframe:streaming:end",
|
|
6661
|
+
args: [
|
|
6662
|
+
name,
|
|
6663
|
+
sink.id,
|
|
6664
|
+
error
|
|
6665
|
+
],
|
|
6666
|
+
event: true,
|
|
6667
|
+
optional: true,
|
|
6668
|
+
filter: (client) => record.subscribers.has(client.$meta)
|
|
6669
|
+
});
|
|
6670
|
+
maybeFreeStream(state, sink.id);
|
|
6671
|
+
}));
|
|
6672
|
+
return sink;
|
|
6673
|
+
}
|
|
6674
|
+
async function pipeFrom(readable, startOpts = {}) {
|
|
6675
|
+
const sink = start(startOpts);
|
|
6676
|
+
readable.pipeTo(sink.writable, { signal: sink.signal }).catch(() => {});
|
|
6677
|
+
return sink;
|
|
6678
|
+
}
|
|
6679
|
+
function get(id) {
|
|
6680
|
+
return state.streams.get(id)?.sink;
|
|
6681
|
+
}
|
|
6682
|
+
function ids() {
|
|
6683
|
+
return Array.from(state.streams.keys());
|
|
6684
|
+
}
|
|
6685
|
+
function openInbound(inboundOpts = {}) {
|
|
6686
|
+
let inboundRecord;
|
|
6687
|
+
const reader = createStreamReader({
|
|
6688
|
+
id: inboundOpts.id,
|
|
6689
|
+
onCancel() {
|
|
6690
|
+
const targetMeta = inboundRecord?.uploaderMeta;
|
|
6691
|
+
if (!targetMeta) return;
|
|
6692
|
+
rpc.broadcast({
|
|
6693
|
+
method: "devframe:streaming:upload-cancel",
|
|
6694
|
+
args: [name, reader.id],
|
|
6695
|
+
event: true,
|
|
6696
|
+
optional: true,
|
|
6697
|
+
filter: (client) => client.$meta === targetMeta
|
|
6698
|
+
});
|
|
6699
|
+
}
|
|
6700
|
+
});
|
|
6701
|
+
inboundRecord = { reader };
|
|
6702
|
+
state.inbound.set(reader.id, inboundRecord);
|
|
6703
|
+
debug("opened-inbound", name, reader.id);
|
|
6704
|
+
return reader;
|
|
6705
|
+
}
|
|
6706
|
+
return {
|
|
6707
|
+
name,
|
|
6708
|
+
start,
|
|
6709
|
+
pipeFrom,
|
|
6710
|
+
get,
|
|
6711
|
+
ids,
|
|
6712
|
+
openInbound
|
|
6713
|
+
};
|
|
6714
|
+
}
|
|
6715
|
+
function parseKey(key) {
|
|
6716
|
+
const sepIdx = key.indexOf(STREAM_KEY_SEPARATOR);
|
|
6717
|
+
if (sepIdx < 0) return void 0;
|
|
6718
|
+
return {
|
|
6719
|
+
channelName: key.slice(0, sepIdx),
|
|
6720
|
+
id: key.slice(sepIdx + 1)
|
|
6721
|
+
};
|
|
6722
|
+
}
|
|
6723
|
+
return {
|
|
6724
|
+
create: createChannel,
|
|
6725
|
+
_onSessionDisconnected(meta) {
|
|
6726
|
+
if (meta.subscribedStreams) {
|
|
6727
|
+
for (const key of meta.subscribedStreams) {
|
|
6728
|
+
const parsed = parseKey(key);
|
|
6729
|
+
if (!parsed) continue;
|
|
6730
|
+
const state = channels.get(parsed.channelName);
|
|
6731
|
+
const record = state?.streams.get(parsed.id);
|
|
6732
|
+
if (!state || !record) continue;
|
|
6733
|
+
record.subscribers.delete(meta);
|
|
6734
|
+
if (record.subscribers.size === 0 && !record.sink.closed) record.sink.abort("all subscribers disconnected");
|
|
6735
|
+
maybeFreeStream(state, parsed.id);
|
|
6736
|
+
}
|
|
6737
|
+
meta.subscribedStreams.clear();
|
|
6738
|
+
}
|
|
6739
|
+
if (meta.uploadingStreams) {
|
|
6740
|
+
for (const key of meta.uploadingStreams) {
|
|
6741
|
+
const parsed = parseKey(key);
|
|
6742
|
+
if (!parsed) continue;
|
|
6743
|
+
const state = channels.get(parsed.channelName);
|
|
6744
|
+
const record = state?.inbound.get(parsed.id);
|
|
6745
|
+
if (!state || !record) continue;
|
|
6746
|
+
record.reader._end({
|
|
6747
|
+
name: "UploadDisconnected",
|
|
6748
|
+
message: "Uploader disconnected before completing the stream"
|
|
6749
|
+
});
|
|
6750
|
+
state.inbound.delete(parsed.id);
|
|
6751
|
+
}
|
|
6752
|
+
meta.uploadingStreams.clear();
|
|
6753
|
+
}
|
|
6754
|
+
}
|
|
6755
|
+
};
|
|
6401
6756
|
}
|
|
6402
6757
|
//#endregion
|
|
6403
6758
|
//#region src/node/host-functions.ts
|
|
@@ -6411,8 +6766,20 @@ var RpcFunctionsHost = class extends RpcFunctionsCollectorBase {
|
|
|
6411
6766
|
constructor(context) {
|
|
6412
6767
|
super(context);
|
|
6413
6768
|
this.sharedState = createRpcSharedStateServerHost(this);
|
|
6769
|
+
this.streaming = createRpcStreamingServerHost(this);
|
|
6414
6770
|
}
|
|
6415
6771
|
sharedState;
|
|
6772
|
+
streaming;
|
|
6773
|
+
/**
|
|
6774
|
+
* Adapters call this from their WS `onDisconnected` hook so downstream
|
|
6775
|
+
* hosts (streaming, …) can free per-session state. Public-ish because
|
|
6776
|
+
* tests / custom adapters may want to mirror it.
|
|
6777
|
+
*
|
|
6778
|
+
* @internal
|
|
6779
|
+
*/
|
|
6780
|
+
_emitSessionDisconnected(meta) {
|
|
6781
|
+
this.streaming._onSessionDisconnected(meta);
|
|
6782
|
+
}
|
|
6416
6783
|
async invokeLocal(method, ...args) {
|
|
6417
6784
|
if (!this.definitions.has(method)) throw logger.DF0006({ name: String(method) }).throw();
|
|
6418
6785
|
const handler = await this.getHandler(method);
|
|
@@ -6543,13 +6910,32 @@ var DevToolsMessagesHost = class {
|
|
|
6543
6910
|
};
|
|
6544
6911
|
//#endregion
|
|
6545
6912
|
//#region src/node/host-terminals.ts
|
|
6913
|
+
/**
|
|
6914
|
+
* Channel name used for terminal stream output. Built into devframe so the
|
|
6915
|
+
* standalone client (`packages/core/src/client/webcomponents/state/terminals.ts`)
|
|
6916
|
+
* can subscribe by a stable, well-known name.
|
|
6917
|
+
*/
|
|
6918
|
+
const TERMINAL_STREAM_CHANNEL = "devframe:terminals";
|
|
6919
|
+
const TERMINAL_REPLAY_WINDOW = 1e3;
|
|
6546
6920
|
var DevToolsTerminalHost = class {
|
|
6547
6921
|
sessions = /* @__PURE__ */ new Map();
|
|
6548
6922
|
events = createEventEmitter();
|
|
6549
6923
|
_boundStreams = /* @__PURE__ */ new Map();
|
|
6924
|
+
_channel;
|
|
6550
6925
|
constructor(context) {
|
|
6551
6926
|
this.context = context;
|
|
6552
6927
|
}
|
|
6928
|
+
/**
|
|
6929
|
+
* Lazily acquire the streaming channel — `context.rpc` isn't assigned
|
|
6930
|
+
* until after every host is constructed, so we can't grab it in the
|
|
6931
|
+
* constructor.
|
|
6932
|
+
*/
|
|
6933
|
+
getStreamingChannel() {
|
|
6934
|
+
if (this._channel) return this._channel;
|
|
6935
|
+
if (!this.context.rpc?.streaming) return void 0;
|
|
6936
|
+
this._channel = this.context.rpc.streaming.create(TERMINAL_STREAM_CHANNEL, { replayWindow: TERMINAL_REPLAY_WINDOW });
|
|
6937
|
+
return this._channel;
|
|
6938
|
+
}
|
|
6553
6939
|
register(session) {
|
|
6554
6940
|
if (this.sessions.has(session.id)) throw logger.DF0004({ id: session.id }).throw();
|
|
6555
6941
|
this.sessions.set(session.id, session);
|
|
@@ -6577,26 +6963,31 @@ var DevToolsTerminalHost = class {
|
|
|
6577
6963
|
this._boundStreams.delete(session.id);
|
|
6578
6964
|
if (!session.stream) return;
|
|
6579
6965
|
session.buffer ||= [];
|
|
6580
|
-
const
|
|
6581
|
-
const
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6966
|
+
const sessionBuffer = session.buffer;
|
|
6967
|
+
const sink = this.getStreamingChannel()?.start({ id: session.id });
|
|
6968
|
+
const writer = new WritableStream({
|
|
6969
|
+
write(chunk) {
|
|
6970
|
+
sessionBuffer.push(chunk);
|
|
6971
|
+
sink?.write(chunk);
|
|
6972
|
+
},
|
|
6973
|
+
close() {
|
|
6974
|
+
sink?.close();
|
|
6975
|
+
},
|
|
6976
|
+
abort(reason) {
|
|
6977
|
+
sink?.error(reason);
|
|
6978
|
+
}
|
|
6979
|
+
});
|
|
6980
|
+
session.stream.pipeTo(writer).catch(() => {});
|
|
6590
6981
|
this._boundStreams.set(session.id, {
|
|
6591
6982
|
dispose: () => {
|
|
6592
|
-
|
|
6983
|
+
if (sink && !sink.closed) sink.close();
|
|
6593
6984
|
},
|
|
6594
6985
|
stream: session.stream
|
|
6595
6986
|
});
|
|
6596
6987
|
}
|
|
6597
6988
|
async startChildProcess(executeOptions, terminal) {
|
|
6598
6989
|
if (this.sessions.has(terminal.id)) throw logger.DF0004({ id: terminal.id }).throw();
|
|
6599
|
-
const { exec } = await import("./main-
|
|
6990
|
+
const { exec } = await import("./main-DpINGndA.mjs");
|
|
6600
6991
|
let controller;
|
|
6601
6992
|
const stream = new ReadableStream({ start(_controller) {
|
|
6602
6993
|
controller = _controller;
|
|
@@ -6674,6 +7065,7 @@ const agentInvokeTool = defineRpcFunction({
|
|
|
6674
7065
|
const agentListResources = defineRpcFunction({
|
|
6675
7066
|
name: "devframe:agent:list-resources",
|
|
6676
7067
|
type: "query",
|
|
7068
|
+
jsonSerializable: true,
|
|
6677
7069
|
setup: (ctx) => {
|
|
6678
7070
|
return { async handler() {
|
|
6679
7071
|
return ctx.agent.list().resources;
|
|
@@ -6693,6 +7085,7 @@ const BUILTIN_AGENT_RPC = [
|
|
|
6693
7085
|
defineRpcFunction({
|
|
6694
7086
|
name: "devframe:agent:list-tools",
|
|
6695
7087
|
type: "query",
|
|
7088
|
+
jsonSerializable: true,
|
|
6696
7089
|
setup: (ctx) => {
|
|
6697
7090
|
return { async handler() {
|
|
6698
7091
|
return ctx.agent.list().tools;
|
|
@@ -6704,6 +7097,7 @@ const BUILTIN_AGENT_RPC = [
|
|
|
6704
7097
|
defineRpcFunction({
|
|
6705
7098
|
name: "devframe:agent:read-resource",
|
|
6706
7099
|
type: "query",
|
|
7100
|
+
jsonSerializable: true,
|
|
6707
7101
|
setup: (ctx) => {
|
|
6708
7102
|
return { async handler(id) {
|
|
6709
7103
|
return await ctx.agent.read(id);
|
|
@@ -6767,7 +7161,7 @@ async function createHostContext(options) {
|
|
|
6767
7161
|
context.agent = new DevToolsAgentHost(context);
|
|
6768
7162
|
let jrCounter = 0;
|
|
6769
7163
|
context.createJsonRenderer = (initialSpec) => {
|
|
6770
|
-
const stateKey = `
|
|
7164
|
+
const stateKey = `devframe:json-render:${jrCounter++}`;
|
|
6771
7165
|
const statePromise = rpcHost.sharedState.get(stateKey, { initialValue: initialSpec });
|
|
6772
7166
|
return {
|
|
6773
7167
|
_stateKey: stateKey,
|
|
@@ -6787,26 +7181,20 @@ async function createHostContext(options) {
|
|
|
6787
7181
|
for (const fn of BUILTIN_AGENT_RPC) rpcHost.register(fn);
|
|
6788
7182
|
for (const fn of builtinRpcDeclarations) rpcHost.register(fn);
|
|
6789
7183
|
await docksHost.init();
|
|
6790
|
-
const docksSharedState = await rpcHost.sharedState.get("
|
|
7184
|
+
const docksSharedState = await rpcHost.sharedState.get("devframe:docks", { initialValue: [] });
|
|
6791
7185
|
docksHost.events.on("dock:entry:updated", debounce(() => {
|
|
6792
7186
|
docksSharedState.mutate(() => context.docks.values());
|
|
6793
7187
|
}, mode === "build" ? 0 : 10));
|
|
6794
7188
|
terminalsHost.events.on("terminal:session:updated", debounce(() => {
|
|
6795
7189
|
rpcHost.broadcast({
|
|
6796
|
-
method: "
|
|
7190
|
+
method: "devframe:terminals:updated",
|
|
6797
7191
|
args: []
|
|
6798
7192
|
});
|
|
6799
7193
|
docksSharedState.mutate(() => context.docks.values());
|
|
6800
7194
|
}, mode === "build" ? 0 : 10));
|
|
6801
|
-
terminalsHost.events.on("terminal:session:stream-chunk", (data) => {
|
|
6802
|
-
rpcHost.broadcast({
|
|
6803
|
-
method: "devtoolskit:internal:terminals:stream-chunk",
|
|
6804
|
-
args: [data]
|
|
6805
|
-
});
|
|
6806
|
-
});
|
|
6807
7195
|
const debouncedMessagesUpdate = debounce(() => {
|
|
6808
7196
|
rpcHost.broadcast({
|
|
6809
|
-
method: "
|
|
7197
|
+
method: "devframe:messages:updated",
|
|
6810
7198
|
args: []
|
|
6811
7199
|
});
|
|
6812
7200
|
docksSharedState.mutate(() => context.docks.values());
|
|
@@ -6815,7 +7203,7 @@ async function createHostContext(options) {
|
|
|
6815
7203
|
messagesHost.events.on("message:updated", () => debouncedMessagesUpdate());
|
|
6816
7204
|
messagesHost.events.on("message:removed", () => debouncedMessagesUpdate());
|
|
6817
7205
|
messagesHost.events.on("message:cleared", () => debouncedMessagesUpdate());
|
|
6818
|
-
const commandsSharedState = await rpcHost.sharedState.get("
|
|
7206
|
+
const commandsSharedState = await rpcHost.sharedState.get("devframe:commands", { initialValue: [] });
|
|
6819
7207
|
const debouncedCommandsSync = debounce(() => {
|
|
6820
7208
|
commandsSharedState.mutate(() => commandsHost.list());
|
|
6821
7209
|
}, mode === "build" ? 0 : 10);
|
|
@@ -6824,4 +7212,4 @@ async function createHostContext(options) {
|
|
|
6824
7212
|
return context;
|
|
6825
7213
|
}
|
|
6826
7214
|
//#endregion
|
|
6827
|
-
export {
|
|
7215
|
+
export { revokeActiveConnectionsForToken as _, RpcFunctionsHost as a, DevToolsDockHost as c, createStorage as d, DevToolsDiagnosticsHost as f, ContextUtils as g, logger as h, DevToolsMessagesHost as i, getInternalContext as l, DevToolsAgentHost as m, DevToolsViewHost as n, createRpcStreamingServerHost as o, DevToolsCommandsHost as p, DevToolsTerminalHost as r, createRpcSharedStateServerHost as s, createHostContext as t, internalContextMap as u, revokeAuthToken as v };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as createHostContext } from "./context-
|
|
1
|
+
import { t as createHostContext } from "./context-BfvbAyGk.mjs";
|
|
2
2
|
import { DEVTOOLS_CONNECTION_META_FILENAME } from "./constants.mjs";
|
|
3
|
-
import { t as createH3DevToolsHost } from "./host-h3-
|
|
4
|
-
import { t as startHttpAndWs } from "./server-
|
|
5
|
-
import { n as resolveBasePath, t as normalizeBasePath } from "./_shared-
|
|
3
|
+
import { t as createH3DevToolsHost } from "./host-h3-BMvrFzIJ.mjs";
|
|
4
|
+
import { t as startHttpAndWs } from "./server-qRRM8t3v.mjs";
|
|
5
|
+
import { n as resolveBasePath, t as normalizeBasePath } from "./_shared-S-Ujqz_L.mjs";
|
|
6
6
|
import { resolve } from "pathe";
|
|
7
7
|
import process$1 from "node:process";
|
|
8
8
|
import { networkInterfaces } from "node:os";
|
|
@@ -266,6 +266,7 @@ async function createDevServer(def, options = {}) {
|
|
|
266
266
|
const app = options.app ?? createApp();
|
|
267
267
|
const h3Host = createH3DevToolsHost({
|
|
268
268
|
origin: `http://${host}:${port}`,
|
|
269
|
+
appName: def.id,
|
|
269
270
|
mount: (base, dir) => {
|
|
270
271
|
app.use(base, fromNodeMiddleware(sirv(dir, {
|
|
271
272
|
dev: true,
|
|
@@ -311,7 +312,7 @@ async function maybeOpenBrowser(def, flags, origin, override) {
|
|
|
311
312
|
if (resolved === void 0 || resolved === false) return;
|
|
312
313
|
const target = typeof resolved === "string" ? resolveOpenTarget(origin, resolved) : origin;
|
|
313
314
|
try {
|
|
314
|
-
const { default: open } = await import("./open-
|
|
315
|
+
const { default: open } = await import("./open-BtOOEldu.mjs");
|
|
315
316
|
await open(target);
|
|
316
317
|
} catch {}
|
|
317
318
|
}
|