devframe 0.1.20 → 0.1.21

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.
Files changed (61) hide show
  1. package/dist/{_shared-S-Ujqz_L.mjs → _shared-iZy45oG3.mjs} +2 -2
  2. package/dist/adapters/build.d.mts +3 -3
  3. package/dist/adapters/build.mjs +7 -7
  4. package/dist/adapters/cli.d.mts +1 -1
  5. package/dist/adapters/cli.mjs +2 -2
  6. package/dist/adapters/dev.d.mts +2 -2
  7. package/dist/adapters/dev.mjs +1 -1
  8. package/dist/adapters/embedded.d.mts +2 -2
  9. package/dist/adapters/embedded.mjs +1 -1
  10. package/dist/adapters/mcp.d.mts +1 -1
  11. package/dist/adapters/mcp.mjs +4 -3
  12. package/dist/adapters/vite.d.mts +5 -4
  13. package/dist/adapters/vite.mjs +4 -3
  14. package/dist/client/index.d.mts +15 -145
  15. package/dist/client/index.mjs +3 -12
  16. package/dist/constants.d.mts +12 -15
  17. package/dist/constants.mjs +12 -29
  18. package/dist/context-BJ4r2SmR.mjs +1051 -0
  19. package/dist/context-internal-Dx_NoSv1.mjs +199 -0
  20. package/dist/context-internal-saIAfNVw.d.mts +51 -0
  21. package/dist/{dev-B8i_CBlQ.mjs → dev-CdAy400a.mjs} +6 -6
  22. package/dist/{devtool-Bm6zZAw5.d.mts → devtool-CNvLs2_Y.d.mts} +37 -538
  23. package/dist/diagnostics-DxPnRoXO.mjs +51 -0
  24. package/dist/{human-id-CHS0s28X.mjs → human-id-BLoGo_e5.mjs} +0 -1
  25. package/dist/{index-BCo03GEF.d.mts → index-CuLRIMto.d.mts} +1 -1
  26. package/dist/index.d.mts +4 -5
  27. package/dist/index.mjs +1 -4
  28. package/dist/internal/index.d.mts +16 -0
  29. package/dist/internal/index.mjs +3 -0
  30. package/dist/node/index.d.mts +14 -146
  31. package/dist/node/index.mjs +7 -6
  32. package/dist/recipes/open-helpers.d.mts +1 -1
  33. package/dist/recipes/open-helpers.mjs +1 -1
  34. package/dist/rpc/index.d.mts +2 -2
  35. package/dist/rpc/transports/ws-client.d.mts +1 -1
  36. package/dist/rpc/transports/ws-server.d.mts +1 -1
  37. package/dist/{server-DksyT-um.d.mts → server-BAqOajx_.d.mts} +1 -1
  38. package/dist/types/index.d.mts +4 -4
  39. package/dist/utils/events.d.mts +1 -1
  40. package/dist/utils/human-id.mjs +1 -1
  41. package/dist/utils/shared-state.d.mts +1 -1
  42. package/dist/utils/state.d.mts +1 -1
  43. package/dist/utils/streaming-channel.d.mts +1 -1
  44. package/dist/utils/when.d.mts +401 -2
  45. package/dist/{ws-client-DQySVfF_.d.mts → ws-client-CjPuPFbA.d.mts} +1 -1
  46. package/dist/{ws-server-VQqESKAs.d.mts → ws-server-C7LnhOHi.d.mts} +1 -1
  47. package/package.json +2 -5
  48. package/skills/devframe/SKILL.md +54 -100
  49. package/skills/devframe/templates/counter-devtool.ts +3 -8
  50. package/skills/devframe/templates/spa-devtool.ts +2 -7
  51. package/dist/adapters/kit.d.mts +0 -23
  52. package/dist/adapters/kit.mjs +0 -16
  53. package/dist/context-BfvbAyGk.mjs +0 -7215
  54. package/dist/main-DpINGndA.mjs +0 -601
  55. package/dist/when-aBBXAEh5.d.mts +0 -401
  56. package/dist/{host-h3-BMvrFzIJ.mjs → host-h3-9jeHcltx.mjs} +1 -1
  57. package/dist/{open-BtOOEldu.mjs → open-Dede_w9r.mjs} +4 -4
  58. /package/dist/{server-qRRM8t3v.mjs → server-CBsxXIH5.mjs} +0 -0
  59. /package/dist/{static-dump-C1aVSwxY.mjs → static-dump-D5VH8Iqk.mjs} +0 -0
  60. /package/dist/{transports-BPUzHhI2.mjs → transports-DSV5_5QM.mjs} +0 -0
  61. /package/dist/{types-ag029cAe.d.mts → types-C5OVe4AC.d.mts} +0 -0
@@ -0,0 +1,199 @@
1
+ import { t as import_dist } from "./human-id-BLoGo_e5.mjs";
2
+ import { n as logger } from "./diagnostics-DxPnRoXO.mjs";
3
+ import { createSharedState } from "./utils/shared-state.mjs";
4
+ import fs from "node:fs";
5
+ import { dirname, join } from "pathe";
6
+ //#region src/node/auth-revoke.ts
7
+ /**
8
+ * Flip `isTrusted` to false on any live WS clients connected with `token`
9
+ * and broadcast the `auth:revoked` event so they can react.
10
+ *
11
+ * Shared between persisted-auth revocation and remote-dock token revocation.
12
+ */
13
+ async function revokeActiveConnectionsForToken(context, token) {
14
+ const rpcHost = context.rpc;
15
+ if (!rpcHost?._rpcGroup) return;
16
+ const affectedSessionIds = /* @__PURE__ */ new Set();
17
+ for (const client of rpcHost._rpcGroup.clients) if (client.$meta.clientAuthToken === token) {
18
+ affectedSessionIds.add(client.$meta.id);
19
+ client.$meta.isTrusted = false;
20
+ client.$meta.clientAuthToken = void 0;
21
+ }
22
+ if (affectedSessionIds.size === 0) return;
23
+ await rpcHost.broadcast({
24
+ method: "devframe:auth:revoked",
25
+ args: [],
26
+ filter: (client) => affectedSessionIds.has(client.$meta.id)
27
+ });
28
+ }
29
+ /**
30
+ * Revoke an auth token: remove from storage and notify all connected clients
31
+ * using this token that they are no longer trusted.
32
+ */
33
+ async function revokeAuthToken(context, storage, token) {
34
+ storage.mutate((state) => {
35
+ delete state.trusted[token];
36
+ });
37
+ await revokeActiveConnectionsForToken(context, token);
38
+ }
39
+ //#endregion
40
+ //#region ../../../node_modules/.pnpm/perfect-debounce@2.1.0/node_modules/perfect-debounce/dist/index.mjs
41
+ const DEBOUNCE_DEFAULTS = { trailing: true };
42
+ /**
43
+ Debounce functions
44
+ @param fn - Promise-returning/async function to debounce.
45
+ @param wait - Milliseconds to wait before calling `fn`. Default value is 25ms
46
+ @returns A function that delays calling `fn` until after `wait` milliseconds have elapsed since the last time it was called.
47
+ @example
48
+ ```
49
+ import { debounce } from 'perfect-debounce';
50
+ const expensiveCall = async input => input;
51
+ const debouncedFn = debounce(expensiveCall, 200);
52
+ for (const number of [1, 2, 3]) {
53
+ console.log(await debouncedFn(number));
54
+ }
55
+ //=> 1
56
+ //=> 2
57
+ //=> 3
58
+ ```
59
+ */
60
+ function debounce(fn, wait = 25, options = {}) {
61
+ options = {
62
+ ...DEBOUNCE_DEFAULTS,
63
+ ...options
64
+ };
65
+ if (!Number.isFinite(wait)) throw new TypeError("Expected `wait` to be a finite number");
66
+ let leadingValue;
67
+ let timeout;
68
+ let resolveList = [];
69
+ let currentPromise;
70
+ let trailingArgs;
71
+ const applyFn = (_this, args) => {
72
+ currentPromise = _applyPromised(fn, _this, args);
73
+ currentPromise.finally(() => {
74
+ currentPromise = null;
75
+ if (options.trailing && trailingArgs && !timeout) {
76
+ const promise = applyFn(_this, trailingArgs);
77
+ trailingArgs = null;
78
+ return promise;
79
+ }
80
+ });
81
+ return currentPromise;
82
+ };
83
+ const debounced = function(...args) {
84
+ if (options.trailing) trailingArgs = args;
85
+ if (currentPromise) return currentPromise;
86
+ return new Promise((resolve) => {
87
+ const shouldCallNow = !timeout && options.leading;
88
+ clearTimeout(timeout);
89
+ timeout = setTimeout(() => {
90
+ timeout = null;
91
+ const promise = options.leading ? leadingValue : applyFn(this, args);
92
+ trailingArgs = null;
93
+ for (const _resolve of resolveList) _resolve(promise);
94
+ resolveList = [];
95
+ }, wait);
96
+ if (shouldCallNow) {
97
+ leadingValue = applyFn(this, args);
98
+ resolve(leadingValue);
99
+ } else resolveList.push(resolve);
100
+ });
101
+ };
102
+ const _clearTimeout = (timer) => {
103
+ if (timer) {
104
+ clearTimeout(timer);
105
+ timeout = null;
106
+ }
107
+ };
108
+ debounced.isPending = () => !!timeout;
109
+ debounced.cancel = () => {
110
+ _clearTimeout(timeout);
111
+ resolveList = [];
112
+ trailingArgs = null;
113
+ };
114
+ debounced.flush = () => {
115
+ _clearTimeout(timeout);
116
+ if (!trailingArgs || currentPromise) return;
117
+ const args = trailingArgs;
118
+ trailingArgs = null;
119
+ return applyFn(this, args);
120
+ };
121
+ return debounced;
122
+ }
123
+ async function _applyPromised(fn, _this, args) {
124
+ return await fn.apply(_this, args);
125
+ }
126
+ //#endregion
127
+ //#region src/node/storage.ts
128
+ function createStorage(options) {
129
+ const { mergeInitialValue = (initialValue, savedValue) => ({
130
+ ...initialValue,
131
+ ...savedValue
132
+ }), debounce: debounceTime = 100 } = options;
133
+ let initialValue = options.initialValue;
134
+ if (fs.existsSync(options.filepath)) try {
135
+ const savedValue = JSON.parse(fs.readFileSync(options.filepath, "utf-8"));
136
+ initialValue = mergeInitialValue ? mergeInitialValue(options.initialValue, savedValue) : savedValue;
137
+ } catch (error) {
138
+ logger.DF0012({ filepath: options.filepath }, { cause: error }).log();
139
+ initialValue = options.initialValue;
140
+ }
141
+ const state = createSharedState({
142
+ initialValue,
143
+ enablePatches: false
144
+ });
145
+ state.on("updated", debounce((newState) => {
146
+ fs.mkdirSync(dirname(options.filepath), { recursive: true });
147
+ fs.writeFileSync(options.filepath, `${JSON.stringify(newState, null, 2)}\n`);
148
+ }, debounceTime));
149
+ return state;
150
+ }
151
+ //#endregion
152
+ //#region src/node/context-internal.ts
153
+ const internalContextMap = /* @__PURE__ */ new WeakMap();
154
+ function getInternalContext(context) {
155
+ if (!internalContextMap.has(context)) {
156
+ const storage = createStorage({
157
+ filepath: join(context.host.getStorageDir("global"), "auth.json"),
158
+ initialValue: { trusted: {} }
159
+ });
160
+ const remoteTokens = /* @__PURE__ */ new Map();
161
+ function revokeRemoteToken(token) {
162
+ if (!remoteTokens.delete(token)) return;
163
+ revokeActiveConnectionsForToken(context, token);
164
+ }
165
+ const internalContext = {
166
+ storage: { auth: storage },
167
+ revokeAuthToken: (token) => revokeAuthToken(context, storage, token),
168
+ remoteTokens,
169
+ allocateRemoteToken(dockId, origin, originLock) {
170
+ const token = (0, import_dist.humanId)({
171
+ separator: "-",
172
+ capitalize: false
173
+ });
174
+ remoteTokens.set(token, {
175
+ dockId,
176
+ origin,
177
+ originLock
178
+ });
179
+ return token;
180
+ },
181
+ revokeRemoteToken,
182
+ revokeRemoteTokensForDock(dockId) {
183
+ const tokensToRevoke = [];
184
+ for (const [token, record] of remoteTokens) if (record.dockId === dockId) tokensToRevoke.push(token);
185
+ for (const token of tokensToRevoke) revokeRemoteToken(token);
186
+ },
187
+ isRemoteTokenTrusted(token, requestOrigin) {
188
+ const record = remoteTokens.get(token);
189
+ if (!record) return false;
190
+ if (!record.originLock) return true;
191
+ return !!requestOrigin && record.origin === requestOrigin;
192
+ }
193
+ };
194
+ internalContextMap.set(context, internalContext);
195
+ }
196
+ return internalContextMap.get(context);
197
+ }
198
+ //#endregion
199
+ export { revokeAuthToken as a, revokeActiveConnectionsForToken as i, internalContextMap as n, createStorage as r, getInternalContext as t };
@@ -0,0 +1,51 @@
1
+ import { P as SharedState, d as DevToolsNodeContext } from "./devtool-CNvLs2_Y.mjs";
2
+
3
+ //#region src/node/context-internal.d.ts
4
+ interface InternalAnonymousAuthStorage {
5
+ trusted: Record<string, {
6
+ authToken: string;
7
+ ua: string;
8
+ origin: string;
9
+ timestamp: number;
10
+ } | undefined>;
11
+ }
12
+ interface RemoteTokenRecord {
13
+ dockId: string;
14
+ /** Dock URL origin — matched against WS handshake `Origin` header when `originLock` is on. */
15
+ origin: string;
16
+ originLock: boolean;
17
+ }
18
+ interface DevToolsInternalContext {
19
+ storage: {
20
+ auth: SharedState<InternalAnonymousAuthStorage>;
21
+ };
22
+ /**
23
+ * Revoke an auth token: remove from storage and notify all connected clients
24
+ * using this token that they are no longer trusted.
25
+ */
26
+ revokeAuthToken: (token: string) => Promise<void>;
27
+ /**
28
+ * Session-only tokens issued to remote-UI iframe docks. Not persisted —
29
+ * regenerated on every dev-server restart.
30
+ */
31
+ remoteTokens: Map<string, RemoteTokenRecord>;
32
+ allocateRemoteToken: (dockId: string, origin: string, originLock: boolean) => string;
33
+ revokeRemoteToken: (token: string) => void;
34
+ revokeRemoteTokensForDock: (dockId: string) => void;
35
+ /**
36
+ * Returns true if `token` is a valid remote token and, when `originLock` is
37
+ * on, `requestOrigin` matches the recorded dock origin.
38
+ */
39
+ isRemoteTokenTrusted: (token: string, requestOrigin?: string) => boolean;
40
+ /**
41
+ * Populated by `createWsServer` once the WS port is bound. Consumed by the
42
+ * docks host when enriching remote iframe URLs with a connection descriptor.
43
+ */
44
+ wsEndpoint?: {
45
+ /** Full `ws://` or `wss://` URL with host and port. */url: string;
46
+ };
47
+ }
48
+ declare const internalContextMap: WeakMap<DevToolsNodeContext, DevToolsInternalContext>;
49
+ declare function getInternalContext(context: DevToolsNodeContext): DevToolsInternalContext;
50
+ //#endregion
51
+ export { internalContextMap as a, getInternalContext as i, InternalAnonymousAuthStorage as n, RemoteTokenRecord as r, DevToolsInternalContext as t };
@@ -1,11 +1,11 @@
1
- import { t as createHostContext } from "./context-BfvbAyGk.mjs";
1
+ import { t as createHostContext } from "./context-BJ4r2SmR.mjs";
2
+ import { t as createH3DevToolsHost } from "./host-h3-9jeHcltx.mjs";
3
+ import { t as startHttpAndWs } from "./server-CBsxXIH5.mjs";
2
4
  import { DEVTOOLS_CONNECTION_META_FILENAME } from "./constants.mjs";
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";
5
+ import { n as resolveBasePath, t as normalizeBasePath } from "./_shared-iZy45oG3.mjs";
6
6
  import { resolve } from "pathe";
7
- import process$1 from "node:process";
8
7
  import { networkInterfaces } from "node:os";
8
+ import process$1 from "node:process";
9
9
  import { createApp, eventHandler, fromNodeMiddleware } from "h3";
10
10
  import { createServer } from "node:net";
11
11
  import sirv from "sirv";
@@ -312,7 +312,7 @@ async function maybeOpenBrowser(def, flags, origin, override) {
312
312
  if (resolved === void 0 || resolved === false) return;
313
313
  const target = typeof resolved === "string" ? resolveOpenTarget(origin, resolved) : origin;
314
314
  try {
315
- const { default: open } = await import("./open-BtOOEldu.mjs");
315
+ const { default: open } = await import("./open-Dede_w9r.mjs");
316
316
  await open(target);
317
317
  } catch {}
318
318
  }