devframe 0.0.0 → 0.1.16

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 (73) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +62 -0
  3. package/dist/_shared-CU6dE-VX.mjs +20 -0
  4. package/dist/adapters/build.d.mts +37 -0
  5. package/dist/adapters/build.mjs +61 -0
  6. package/dist/adapters/cli.d.mts +35 -0
  7. package/dist/adapters/cli.mjs +357 -0
  8. package/dist/adapters/embedded.d.mts +19 -0
  9. package/dist/adapters/embedded.mjs +15 -0
  10. package/dist/adapters/kit.d.mts +23 -0
  11. package/dist/adapters/kit.mjs +16 -0
  12. package/dist/adapters/mcp.d.mts +39 -0
  13. package/dist/adapters/mcp.mjs +278 -0
  14. package/dist/adapters/vite.d.mts +32 -0
  15. package/dist/adapters/vite.mjs +31 -0
  16. package/dist/client/index.d.mts +227 -0
  17. package/dist/client/index.mjs +2 -0
  18. package/dist/client-4WrEozlH.mjs +1561 -0
  19. package/dist/constants.d.mts +20 -0
  20. package/dist/constants.mjs +34 -0
  21. package/dist/context-BrePWeyd.mjs +6776 -0
  22. package/dist/define-Bb4zh-Dc.mjs +11 -0
  23. package/dist/devtool-OJ3QW0ns.d.mts +1125 -0
  24. package/dist/helpers/nuxt/index.d.mts +46 -0
  25. package/dist/helpers/nuxt/index.mjs +58 -0
  26. package/dist/helpers/nuxt/runtime/plugin.client.d.mts +8 -0
  27. package/dist/helpers/nuxt/runtime/plugin.client.mjs +12 -0
  28. package/dist/human-id-CHS0s28X.mjs +844 -0
  29. package/dist/immer-HjMAm3b6.mjs +894 -0
  30. package/dist/index-DvKDO5H8.d.mts +333 -0
  31. package/dist/index.d.mts +10 -0
  32. package/dist/index.mjs +2 -0
  33. package/dist/main-DpINGndA.mjs +601 -0
  34. package/dist/node/index.d.mts +365 -0
  35. package/dist/node/index.mjs +69 -0
  36. package/dist/open-BtOOEldu.mjs +533 -0
  37. package/dist/recipes/open-helpers.d.mts +104 -0
  38. package/dist/recipes/open-helpers.mjs +69 -0
  39. package/dist/rpc/client.d.mts +9 -0
  40. package/dist/rpc/client.mjs +13 -0
  41. package/dist/rpc/index.d.mts +2 -0
  42. package/dist/rpc/index.mjs +3 -0
  43. package/dist/rpc/server.d.mts +8 -0
  44. package/dist/rpc/server.mjs +10 -0
  45. package/dist/rpc/transports/ws-client.d.mts +2 -0
  46. package/dist/rpc/transports/ws-client.mjs +43 -0
  47. package/dist/rpc/transports/ws-server.d.mts +2 -0
  48. package/dist/rpc/transports/ws-server.mjs +58 -0
  49. package/dist/rpc-9FNa3Inb.mjs +474 -0
  50. package/dist/server-DrBxa6ZV.mjs +49 -0
  51. package/dist/src-BoIqXRc9.mjs +85 -0
  52. package/dist/static-dump-CQUC1aIW.mjs +82 -0
  53. package/dist/transports-BPUzHhI2.mjs +15 -0
  54. package/dist/types/index.d.mts +4 -0
  55. package/dist/types/index.mjs +6 -0
  56. package/dist/utils/events.d.mts +9 -0
  57. package/dist/utils/events.mjs +40 -0
  58. package/dist/utils/human-id.d.mts +10 -0
  59. package/dist/utils/human-id.mjs +3 -0
  60. package/dist/utils/nanoid.d.mts +4 -0
  61. package/dist/utils/nanoid.mjs +10 -0
  62. package/dist/utils/promise.d.mts +8 -0
  63. package/dist/utils/promise.mjs +15 -0
  64. package/dist/utils/shared-state.d.mts +2 -0
  65. package/dist/utils/shared-state.mjs +36 -0
  66. package/dist/utils/state.d.mts +49 -0
  67. package/dist/utils/state.mjs +26 -0
  68. package/dist/utils/when.d.mts +2 -0
  69. package/dist/utils/when.mjs +424 -0
  70. package/dist/when-CGLewRtm.d.mts +401 -0
  71. package/dist/ws-client-CklfxUHE.d.mts +17 -0
  72. package/dist/ws-server--IuUAaGi.d.mts +37 -0
  73. package/package.json +116 -8
@@ -0,0 +1,4 @@
1
+ import { $ as DevToolsLogsHost, A as DevToolsViewHost, At as AgentHandle, B as DevToolsTerminalStatus, Bt as EventUnsubscribe, Ct as DevToolsCommandHandle, Dt as DevToolsCommandsHostEvents, Et as DevToolsCommandsHost, F as DevToolsChildProcessTerminalSession, Ft as AgentTool, G as DevToolsLogElementPosition, H as DevToolsRpcClientFunctions, I as DevToolsTerminalHost, It as AgentToolInput, J as DevToolsLogEntryInput, K as DevToolsLogEntry, L as DevToolsTerminalSession, Lt as DevToolsAgentHost, M as PartialWithoutId, Mt as AgentResource, N as Thenable, Nt as AgentResourceContent, Ot as DevToolsServerCommandEntry, P as DevToolsChildProcessExecuteOptions, Pt as AgentResourceInput, Q as DevToolsLogsClient, R as DevToolsTerminalSessionBase, Rt as DevToolsAgentHostEvents, St as DevToolsCommandEntry, Tt as DevToolsCommandShortcutOverrides, U as DevToolsRpcServerFunctions, V as DevToolsDocksUserSettings, Vt as EventsMap, W as DevToolsRpcSharedStates, X as DevToolsLogHandle, Y as DevToolsLogFilePosition, Z as DevToolsLogLevel, _ as RpcSharedStateGetOptions, _t as JsonRenderSpec, a as DevtoolRuntime, at as DevToolsDockEntryCategory, bt as DevToolsClientCommand, c as defineDevtool, ct as DevToolsDockUserEntry, d as DevToolsNodeContext, dt as DevToolsViewCustomRender, et as DevToolsHost, f as DevToolsNodeUtils, ft as DevToolsViewIframe, g as RpcFunctionsHost, gt as JsonRenderElement, h as RpcBroadcastOptions, ht as DevToolsViewLauncherStatus, i as DevtoolDeploymentKind, it as DevToolsDockEntryBase, j as EntriesToObject, jt as AgentManifest, kt as DevToolsServerCommandInput, l as ConnectionMeta, lt as DevToolsViewAction, m as DevToolsNodeRpcSession, mt as DevToolsViewLauncher, n as DevtoolCliOptions, nt as DevToolsDockEntriesGrouped, o as DevtoolSetupInfo, ot as DevToolsDockEntryIcon, p as RemoteConnectionInfo, pt as DevToolsViewJsonRender, q as DevToolsLogEntryFrom, r as DevtoolDefinition, rt as DevToolsDockEntry, s as DevtoolSpaOptions, st as DevToolsDockHost, t as DevtoolBrowserContext, tt as ClientScriptEntry, u as DevToolsCapabilities, ut as DevToolsViewBuiltin, v as RpcSharedStateHost, vt as JsonRenderer, wt as DevToolsCommandKeybinding, xt as DevToolsCommandBase, yt as RemoteDockOptions, z as DevToolsTerminalSessionStreamChunkEvent, zt as EventEmitter } from "../devtool-OJ3QW0ns.mjs";
2
+ import { w as RpcFunctionAgentOptions } from "../index-DvKDO5H8.mjs";
3
+ import { t as DevToolsNodeRpcSessionMeta } from "../ws-server--IuUAaGi.mjs";
4
+ export { AgentHandle, AgentManifest, AgentResource, AgentResourceContent, AgentResourceInput, AgentTool, AgentToolInput, ClientScriptEntry, ConnectionMeta, DevToolsAgentHost, DevToolsAgentHostEvents, DevToolsCapabilities, DevToolsChildProcessExecuteOptions, DevToolsChildProcessTerminalSession, DevToolsClientCommand, DevToolsCommandBase, DevToolsCommandEntry, DevToolsCommandHandle, DevToolsCommandKeybinding, DevToolsCommandShortcutOverrides, DevToolsCommandsHost, DevToolsCommandsHostEvents, DevToolsDockEntriesGrouped, DevToolsDockEntry, DevToolsDockEntryBase, DevToolsDockEntryCategory, DevToolsDockEntryIcon, DevToolsDockHost, DevToolsDockUserEntry, DevToolsDocksUserSettings, DevToolsHost, DevToolsLogElementPosition, DevToolsLogEntry, DevToolsLogEntryFrom, DevToolsLogEntryInput, DevToolsLogFilePosition, DevToolsLogHandle, DevToolsLogLevel, DevToolsLogsClient, DevToolsLogsHost, DevToolsNodeContext, DevToolsNodeRpcSession, DevToolsNodeRpcSessionMeta, DevToolsNodeUtils, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions, DevToolsRpcSharedStates, DevToolsServerCommandEntry, DevToolsServerCommandInput, DevToolsTerminalHost, DevToolsTerminalSession, DevToolsTerminalSessionBase, DevToolsTerminalSessionStreamChunkEvent, DevToolsTerminalStatus, DevToolsViewAction, DevToolsViewBuiltin, DevToolsViewCustomRender, DevToolsViewHost, DevToolsViewIframe, DevToolsViewJsonRender, DevToolsViewLauncher, DevToolsViewLauncherStatus, DevtoolBrowserContext, DevtoolCliOptions, DevtoolDefinition, DevtoolDeploymentKind, DevtoolRuntime, DevtoolSetupInfo, DevtoolSpaOptions, EntriesToObject, EventEmitter, EventUnsubscribe, EventsMap, JsonRenderElement, JsonRenderSpec, JsonRenderer, PartialWithoutId, RemoteConnectionInfo, RemoteDockOptions, RpcBroadcastOptions, RpcFunctionAgentOptions, RpcFunctionsHost, RpcSharedStateGetOptions, RpcSharedStateHost, Thenable, defineDevtool };
@@ -0,0 +1,6 @@
1
+ //#region src/types/devtool.ts
2
+ function defineDevtool(d) {
3
+ return d;
4
+ }
5
+ //#endregion
6
+ export { defineDevtool };
@@ -0,0 +1,9 @@
1
+ import { Vt as EventsMap, zt as EventEmitter } from "../devtool-OJ3QW0ns.mjs";
2
+
3
+ //#region src/utils/events.d.ts
4
+ /**
5
+ * Create event emitter.
6
+ */
7
+ declare function createEventEmitter<Events extends EventsMap>(): EventEmitter<Events>;
8
+ //#endregion
9
+ export { createEventEmitter };
@@ -0,0 +1,40 @@
1
+ //#region src/utils/events.ts
2
+ /**
3
+ * Create event emitter.
4
+ */
5
+ function createEventEmitter() {
6
+ const _listeners = {};
7
+ function emit(event, ...args) {
8
+ const callbacks = _listeners[event] || [];
9
+ for (let i = 0, length = callbacks.length; i < length; i++) {
10
+ const callback = callbacks[i];
11
+ if (callback) callback(...args);
12
+ }
13
+ }
14
+ function emitOnce(event, ...args) {
15
+ emit(event, ...args);
16
+ delete _listeners[event];
17
+ }
18
+ function on(event, cb) {
19
+ (_listeners[event] ||= []).push(cb);
20
+ return () => {
21
+ _listeners[event] = _listeners[event]?.filter((i) => cb !== i);
22
+ };
23
+ }
24
+ function once(event, cb) {
25
+ const unsubscribe = on(event, ((...args) => {
26
+ unsubscribe();
27
+ return cb(...args);
28
+ }));
29
+ return unsubscribe;
30
+ }
31
+ return {
32
+ _listeners,
33
+ emit,
34
+ emitOnce,
35
+ on,
36
+ once
37
+ };
38
+ }
39
+ //#endregion
40
+ export { createEventEmitter };
@@ -0,0 +1,10 @@
1
+ //#region ../../../node_modules/.pnpm/human-id@4.1.3/node_modules/human-id/dist/index.d.ts
2
+ interface Options {
3
+ separator?: string;
4
+ capitalize?: boolean;
5
+ adjectiveCount?: number;
6
+ addAdverb?: boolean;
7
+ }
8
+ declare function humanId(options?: Options | string | boolean): string;
9
+ //#endregion
10
+ export { humanId };
@@ -0,0 +1,3 @@
1
+ import { t as import_dist } from "../human-id-CHS0s28X.mjs";
2
+ var humanId = import_dist.humanId;
3
+ export { humanId };
@@ -0,0 +1,4 @@
1
+ //#region src/utils/nanoid.d.ts
2
+ declare function nanoid(size?: number): string;
3
+ //#endregion
4
+ export { nanoid };
@@ -0,0 +1,10 @@
1
+ //#region src/utils/nanoid.ts
2
+ const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
3
+ function nanoid(size = 21) {
4
+ let id = "";
5
+ let i = size;
6
+ while (i--) id += urlAlphabet[Math.random() * 64 | 0];
7
+ return id;
8
+ }
9
+ //#endregion
10
+ export { nanoid };
@@ -0,0 +1,8 @@
1
+ //#region src/utils/promise.d.ts
2
+ declare function promiseWithResolver<T>(): {
3
+ promise: Promise<T>;
4
+ resolve: (value: T) => void;
5
+ reject: (error: Error) => void;
6
+ };
7
+ //#endregion
8
+ export { promiseWithResolver };
@@ -0,0 +1,15 @@
1
+ //#region src/utils/promise.ts
2
+ function promiseWithResolver() {
3
+ let resolve;
4
+ let reject;
5
+ return {
6
+ promise: new Promise((_resolve, _reject) => {
7
+ resolve = _resolve;
8
+ reject = _reject;
9
+ }),
10
+ resolve,
11
+ reject
12
+ };
13
+ }
14
+ //#endregion
15
+ export { promiseWithResolver };
@@ -0,0 +1,2 @@
1
+ import { C as ImmutableSet, D as createSharedState, E as SharedStateOptions, S as ImmutableObject, T as SharedStateEvents, b as ImmutableArray, k as Patch, w as SharedState, x as ImmutableMap, y as Immutable } from "../devtool-OJ3QW0ns.mjs";
2
+ export { Immutable, ImmutableArray, ImmutableMap, ImmutableObject, ImmutableSet, SharedState, SharedStateEvents, SharedStateOptions, Patch as SharedStatePatch, createSharedState };
@@ -0,0 +1,36 @@
1
+ import { createEventEmitter } from "./events.mjs";
2
+ import { i as produceWithPatches, n as enablePatches, r as produce, t as applyPatches } from "../immer-HjMAm3b6.mjs";
3
+ import { nanoid } from "./nanoid.mjs";
4
+ //#region src/utils/shared-state.ts
5
+ function createSharedState(options) {
6
+ const { enablePatches: enablePatches$1 = false } = options;
7
+ const events = createEventEmitter();
8
+ let state = options.initialValue;
9
+ const syncIds = /* @__PURE__ */ new Set();
10
+ return {
11
+ on: events.on,
12
+ value: () => state,
13
+ patch: (patches, syncId = nanoid()) => {
14
+ if (syncIds.has(syncId)) return;
15
+ enablePatches();
16
+ state = applyPatches(state, patches);
17
+ syncIds.add(syncId);
18
+ events.emit("updated", state, void 0, syncId);
19
+ },
20
+ mutate: (fn, syncId = nanoid()) => {
21
+ if (syncIds.has(syncId)) return;
22
+ syncIds.add(syncId);
23
+ if (enablePatches$1) {
24
+ const [newState, patches] = produceWithPatches(state, fn);
25
+ state = newState;
26
+ events.emit("updated", state, patches, syncId);
27
+ } else {
28
+ state = produce(state, fn);
29
+ events.emit("updated", state, void 0, syncId);
30
+ }
31
+ },
32
+ syncIds
33
+ };
34
+ }
35
+ //#endregion
36
+ export { createSharedState };
@@ -0,0 +1,49 @@
1
+ import { O as Objectish, k as Patch, zt as EventEmitter } from "../devtool-OJ3QW0ns.mjs";
2
+
3
+ //#region src/utils/state.d.ts
4
+ type ImmutablePrimitive = undefined | null | boolean | string | number | Function;
5
+ 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>;
6
+ type ImmutableArray<T> = ReadonlyArray<Immutable<T>>;
7
+ type ImmutableMap<K, V> = ReadonlyMap<Immutable<K>, Immutable<V>>;
8
+ type ImmutableSet<T> = ReadonlySet<Immutable<T>>;
9
+ type ImmutableObject<T> = { readonly [K in keyof T]: Immutable<T[K]> };
10
+ /**
11
+ * State host that is immutable by default with explicit mutate.
12
+ */
13
+ interface SharedState<T> {
14
+ /**
15
+ * Get the current state. Immutable.
16
+ */
17
+ get: () => Immutable<T>;
18
+ /**
19
+ * Subscribe to state changes.
20
+ */
21
+ on: EventEmitter<SharedStateEvents<T>>['on'];
22
+ /**
23
+ * Mutate the state.
24
+ */
25
+ mutate: (fn: (state: T) => void) => void;
26
+ /**
27
+ * Apply patches to the state.
28
+ */
29
+ patch: (patches: Patch[]) => void;
30
+ }
31
+ interface SharedStateEvents<T> {
32
+ updated: (state: T) => void;
33
+ patches: (patches: Patch[]) => void;
34
+ }
35
+ interface SharedStateOptions<T> {
36
+ /**
37
+ * Initial state.
38
+ */
39
+ initialState: T;
40
+ /**
41
+ * Enable patches.
42
+ *
43
+ * @default false
44
+ */
45
+ enablePatches?: boolean;
46
+ }
47
+ declare function createSharedState<T extends Objectish>(options: SharedStateOptions<T>): SharedState<T>;
48
+ //#endregion
49
+ export { Immutable, ImmutableArray, ImmutableMap, ImmutableObject, ImmutableSet, SharedState, SharedStateEvents, SharedStateOptions, createSharedState };
@@ -0,0 +1,26 @@
1
+ import { createEventEmitter } from "./events.mjs";
2
+ import { i as produceWithPatches, r as produce, t as applyPatches } from "../immer-HjMAm3b6.mjs";
3
+ //#region src/utils/state.ts
4
+ function createSharedState(options) {
5
+ const { enablePatches = false } = options;
6
+ const events = createEventEmitter();
7
+ let state = options.initialState;
8
+ return {
9
+ on: events.on,
10
+ get: () => state,
11
+ patch: (patches) => {
12
+ state = applyPatches(state, patches);
13
+ events.emit("updated", state);
14
+ },
15
+ mutate: (fn) => {
16
+ if (enablePatches) {
17
+ const [newState, patches] = produceWithPatches(state, fn);
18
+ state = newState;
19
+ events.emit("patches", patches);
20
+ } else state = produce(state, fn);
21
+ events.emit("updated", state);
22
+ }
23
+ };
24
+ }
25
+ //#endregion
26
+ export { createSharedState };
@@ -0,0 +1,2 @@
1
+ import { i as resolveContextValue, n as WhenExpression, r as evaluateWhen, t as WhenContext } from "../when-CGLewRtm.mjs";
2
+ export { WhenContext, WhenExpression, evaluateWhen, resolveContextValue };
@@ -0,0 +1,424 @@
1
+ //#region ../../../node_modules/.pnpm/whenexpr@0.1.2/node_modules/whenexpr/dist/index.mjs
2
+ const OPS = [
3
+ "===",
4
+ "!==",
5
+ "==",
6
+ "!=",
7
+ "<=",
8
+ ">=",
9
+ "&&",
10
+ "||",
11
+ "<",
12
+ ">",
13
+ "+",
14
+ "-",
15
+ "*",
16
+ "/",
17
+ "%",
18
+ "!"
19
+ ];
20
+ const IDENT_START = /[a-z_$]/i;
21
+ const IDENT_CONT = /[\w$.:]/;
22
+ const DIGIT = /\d/;
23
+ const WHITESPACE = /\s/;
24
+ function tokenize(input) {
25
+ const tokens = [];
26
+ let i = 0;
27
+ while (i < input.length) {
28
+ const c = input[i];
29
+ if (WHITESPACE.test(c)) {
30
+ i++;
31
+ continue;
32
+ }
33
+ if (c === "(") {
34
+ tokens.push({ type: "lparen" });
35
+ i++;
36
+ continue;
37
+ }
38
+ if (c === ")") {
39
+ tokens.push({ type: "rparen" });
40
+ i++;
41
+ continue;
42
+ }
43
+ let matched = false;
44
+ for (const op of OPS) if (input.startsWith(op, i)) {
45
+ tokens.push({
46
+ type: "op",
47
+ value: op
48
+ });
49
+ i += op.length;
50
+ matched = true;
51
+ break;
52
+ }
53
+ if (matched) continue;
54
+ if (DIGIT.test(c)) {
55
+ let j = i;
56
+ while (j < input.length && DIGIT.test(input[j])) j++;
57
+ if (input[j] === "." && j + 1 < input.length && DIGIT.test(input[j + 1])) {
58
+ j++;
59
+ while (j < input.length && DIGIT.test(input[j])) j++;
60
+ }
61
+ tokens.push({
62
+ type: "number",
63
+ value: Number(input.slice(i, j))
64
+ });
65
+ i = j;
66
+ continue;
67
+ }
68
+ if (c === "\"" || c === "'") {
69
+ const quote = c;
70
+ let j = i + 1;
71
+ let value = "";
72
+ while (j < input.length && input[j] !== quote) if (input[j] === "\\" && j + 1 < input.length) {
73
+ const nx = input[j + 1];
74
+ value += nx === "n" ? "\n" : nx === "t" ? " " : nx;
75
+ j += 2;
76
+ } else {
77
+ value += input[j];
78
+ j++;
79
+ }
80
+ if (j >= input.length) throw new Error(`Unterminated string literal at position ${i}`);
81
+ j++;
82
+ tokens.push({
83
+ type: "string",
84
+ value
85
+ });
86
+ i = j;
87
+ continue;
88
+ }
89
+ if (IDENT_START.test(c)) {
90
+ let j = i;
91
+ while (j < input.length && IDENT_CONT.test(input[j])) j++;
92
+ const name = input.slice(i, j);
93
+ if (name === "true") tokens.push({
94
+ type: "bool",
95
+ value: true
96
+ });
97
+ else if (name === "false") tokens.push({
98
+ type: "bool",
99
+ value: false
100
+ });
101
+ else tokens.push({
102
+ type: "ident",
103
+ value: name
104
+ });
105
+ i = j;
106
+ continue;
107
+ }
108
+ throw new Error(`Unexpected character "${c}" at position ${i}`);
109
+ }
110
+ tokens.push({ type: "eof" });
111
+ return tokens;
112
+ }
113
+ /**
114
+ * Parse a when-clause expression string into an AST.
115
+ *
116
+ * Grammar (lowest to highest precedence):
117
+ * - `||` — logical OR
118
+ * - `&&` — logical AND
119
+ * - `==`, `!=`, `===`, `!==` — equality
120
+ * - `<`, `>`, `<=`, `>=` — relational
121
+ * - `+`, `-` — additive
122
+ * - `*`, `/`, `%` — multiplicative
123
+ * - `!`, `-`, `+` — unary
124
+ * - primary: literals (number, string, boolean), identifiers, `( … )`
125
+ *
126
+ * `==` and `!=` follow VS Code-style semantics: the right-hand side is a
127
+ * simple value literal or bare identifier (treated as an implicit string),
128
+ * not a full expression. Use `===` / `!==` for JS-style strict equality with
129
+ * full expressions on both sides.
130
+ */
131
+ function parse(expression) {
132
+ const tokens = tokenize(expression);
133
+ let pos = 0;
134
+ const peek = () => tokens[pos];
135
+ const consume = () => tokens[pos++];
136
+ const isOp = (op) => {
137
+ const t = peek();
138
+ return t.type === "op" && t.value === op;
139
+ };
140
+ const consumeOp = () => {
141
+ const t = consume();
142
+ if (t.type !== "op") throw new Error(`internal: expected operator token, got ${tokenLabel(t)}`);
143
+ return t.value;
144
+ };
145
+ function parseOr() {
146
+ let left = parseAnd();
147
+ while (isOp("||")) {
148
+ consume();
149
+ left = {
150
+ type: "binary",
151
+ op: "||",
152
+ left,
153
+ right: parseAnd()
154
+ };
155
+ }
156
+ return left;
157
+ }
158
+ function parseAnd() {
159
+ let left = parseEquality();
160
+ while (isOp("&&")) {
161
+ consume();
162
+ left = {
163
+ type: "binary",
164
+ op: "&&",
165
+ left,
166
+ right: parseEquality()
167
+ };
168
+ }
169
+ return left;
170
+ }
171
+ function parseEquality() {
172
+ let left = parseRelational();
173
+ while (isOp("===") || isOp("!==") || isOp("==") || isOp("!=")) {
174
+ const op = consumeOp();
175
+ const right = op === "==" || op === "!=" ? parseValueRhs() : parseRelational();
176
+ left = {
177
+ type: "binary",
178
+ op,
179
+ left,
180
+ right
181
+ };
182
+ }
183
+ return left;
184
+ }
185
+ function parseRelational() {
186
+ let left = parseAdditive();
187
+ while (isOp("<=") || isOp(">=") || isOp("<") || isOp(">")) left = {
188
+ type: "binary",
189
+ op: consumeOp(),
190
+ left,
191
+ right: parseAdditive()
192
+ };
193
+ return left;
194
+ }
195
+ function parseAdditive() {
196
+ let left = parseMultiplicative();
197
+ while (isOp("+") || isOp("-")) left = {
198
+ type: "binary",
199
+ op: consumeOp(),
200
+ left,
201
+ right: parseMultiplicative()
202
+ };
203
+ return left;
204
+ }
205
+ function parseMultiplicative() {
206
+ let left = parseUnary();
207
+ while (isOp("*") || isOp("/") || isOp("%")) left = {
208
+ type: "binary",
209
+ op: consumeOp(),
210
+ left,
211
+ right: parseUnary()
212
+ };
213
+ return left;
214
+ }
215
+ function parseUnary() {
216
+ if (isOp("!") || isOp("-") || isOp("+")) return {
217
+ type: "unary",
218
+ op: consumeOp(),
219
+ operand: parseUnary()
220
+ };
221
+ return parsePrimary();
222
+ }
223
+ function parsePrimary() {
224
+ const t = peek();
225
+ if (t.type === "number" || t.type === "string" || t.type === "bool") {
226
+ consume();
227
+ return {
228
+ type: "literal",
229
+ value: t.value
230
+ };
231
+ }
232
+ if (t.type === "ident") {
233
+ consume();
234
+ return {
235
+ type: "key",
236
+ key: t.value
237
+ };
238
+ }
239
+ if (t.type === "lparen") {
240
+ consume();
241
+ const node = parseOr();
242
+ const close = peek();
243
+ if (close.type !== "rparen") throw new Error(`Expected ")" but got ${tokenLabel(close)}`);
244
+ consume();
245
+ return node;
246
+ }
247
+ throw new Error(`Unexpected token: ${tokenLabel(t)}`);
248
+ }
249
+ function parseValueRhs() {
250
+ const t = peek();
251
+ if (t.type === "string") {
252
+ consume();
253
+ return {
254
+ type: "literal",
255
+ value: t.value
256
+ };
257
+ }
258
+ if (t.type === "number") {
259
+ consume();
260
+ return {
261
+ type: "literal",
262
+ value: String(t.value)
263
+ };
264
+ }
265
+ if (t.type === "bool") {
266
+ consume();
267
+ return {
268
+ type: "literal",
269
+ value: String(t.value)
270
+ };
271
+ }
272
+ if (t.type === "ident") {
273
+ consume();
274
+ return {
275
+ type: "literal",
276
+ value: t.value
277
+ };
278
+ }
279
+ throw new Error(`Expected value literal or identifier on right side of equality, got ${tokenLabel(t)}`);
280
+ }
281
+ const node = parseOr();
282
+ const end = peek();
283
+ if (end.type !== "eof") throw new Error(`Unexpected token: ${tokenLabel(end)}`);
284
+ return node;
285
+ }
286
+ function tokenLabel(t) {
287
+ switch (t.type) {
288
+ case "eof": return "end of expression";
289
+ case "lparen": return "\"(\"";
290
+ case "rparen": return "\")\"";
291
+ case "op":
292
+ case "ident":
293
+ case "string": return `"${t.value}"`;
294
+ case "number":
295
+ case "bool": return `"${String(t.value)}"`;
296
+ }
297
+ }
298
+ /**
299
+ * Evaluate a parsed when-clause AST against a context object.
300
+ *
301
+ * With `{ strict: true }`, referencing an unknown context key throws.
302
+ * Short-circuit evaluation still applies — keys not reached are not checked.
303
+ */
304
+ function evaluate(node, ctx, options = {}) {
305
+ const { strict = false } = options;
306
+ return !!run(node, ctx, strict);
307
+ }
308
+ function run(node, ctx, strict) {
309
+ switch (node.type) {
310
+ case "literal": return node.value;
311
+ case "key": return lookup(node.key, ctx, strict);
312
+ case "unary": return runUnary(node.op, run(node.operand, ctx, strict));
313
+ case "binary": return runBinary(node, ctx, strict);
314
+ }
315
+ }
316
+ function runUnary(op, v) {
317
+ switch (op) {
318
+ case "!": return !v;
319
+ case "-": return -v;
320
+ case "+": return +v;
321
+ }
322
+ }
323
+ function runBinary(node, ctx, strict) {
324
+ const { op } = node;
325
+ if (op === "&&") {
326
+ const l = run(node.left, ctx, strict);
327
+ return l ? run(node.right, ctx, strict) : l;
328
+ }
329
+ if (op === "||") return run(node.left, ctx, strict) || run(node.right, ctx, strict);
330
+ const l = run(node.left, ctx, strict);
331
+ const r = run(node.right, ctx, strict);
332
+ switch (op) {
333
+ case "==": return String(l) === String(r);
334
+ case "!=": return String(l) !== String(r);
335
+ case "===": return l === r;
336
+ case "!==": return l !== r;
337
+ case "<": return l < r;
338
+ case ">": return l > r;
339
+ case "<=": return l <= r;
340
+ case ">=": return l >= r;
341
+ case "+": return l + r;
342
+ case "-": return l - r;
343
+ case "*": return l * r;
344
+ case "/": return l / r;
345
+ case "%": return l % r;
346
+ }
347
+ }
348
+ /**
349
+ * Evaluate a when-clause expression string against a context object.
350
+ * Equivalent to `evaluate(parse(expression), ctx, options)`.
351
+ *
352
+ * Supports a JS-expression subset:
353
+ * - Literals: booleans, numbers, strings (quoted with `"` or `'`)
354
+ * - Identifiers: bare keys, including namespaced (`vite.mode`, `vite:buildMode`)
355
+ * - Logical: `&&`, `||`, `!`
356
+ * - Equality: `==`, `!=` (string comparison, bare identifier RHS treated as string),
357
+ * `===`, `!==` (JS strict equality with full expression RHS)
358
+ * - Relational: `<`, `<=`, `>`, `>=`
359
+ * - Arithmetic: `+`, `-`, `*`, `/`, `%`, unary `-` / `+`
360
+ * - Grouping: `(` … `)`
361
+ *
362
+ * When `ctx` has a specific type with known keys, the expression string is
363
+ * **statically validated** — unknown context keys and syntax errors surface
364
+ * as TypeScript errors at the call site. Pass `ctx` typed as
365
+ * `Record<string, unknown>`, or the expression as `string`, to opt out of
366
+ * static checking (e.g. for dynamic expressions).
367
+ *
368
+ * With `{ strict: true }`, referencing an unknown context key at runtime
369
+ * throws. Short-circuit evaluation still applies — keys not reached are not
370
+ * checked.
371
+ */
372
+ function evaluateWhen(expression, ctx, options) {
373
+ return evaluate(parse(expression), ctx, options);
374
+ }
375
+ /**
376
+ * Resolve a context value by key. Supports namespaced keys with `.` or `:` separators.
377
+ *
378
+ * Lookup order:
379
+ * 1. Exact match — `ctx['plugin.mode']` or `ctx['plugin:mode']`
380
+ * 2. Nested path — e.g. `plugin.mode` falls back to `ctx.plugin?.mode`
381
+ *
382
+ * Returns `undefined` for unknown keys.
383
+ */
384
+ function resolveContextValue(key, ctx) {
385
+ return resolve(key, ctx).value;
386
+ }
387
+ function lookup(key, ctx, strict) {
388
+ const { found, value } = resolve(key, ctx);
389
+ if (!found && strict) throw new Error(`Unknown context key: "${key}"`);
390
+ return value;
391
+ }
392
+ function resolve(key, ctx) {
393
+ if (key in ctx) return {
394
+ found: true,
395
+ value: ctx[key]
396
+ };
397
+ const separator = key.includes(".") ? "." : key.includes(":") ? ":" : null;
398
+ if (separator) {
399
+ const segments = key.split(separator);
400
+ let current = ctx;
401
+ for (const segment of segments) {
402
+ if (current == null || typeof current !== "object") return {
403
+ found: false,
404
+ value: void 0
405
+ };
406
+ const obj = current;
407
+ if (!(segment in obj)) return {
408
+ found: false,
409
+ value: void 0
410
+ };
411
+ current = obj[segment];
412
+ }
413
+ return {
414
+ found: true,
415
+ value: current
416
+ };
417
+ }
418
+ return {
419
+ found: false,
420
+ value: void 0
421
+ };
422
+ }
423
+ //#endregion
424
+ export { evaluateWhen, resolveContextValue };