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.
- package/LICENSE.md +21 -0
- package/README.md +62 -0
- package/dist/_shared-CU6dE-VX.mjs +20 -0
- package/dist/adapters/build.d.mts +37 -0
- package/dist/adapters/build.mjs +61 -0
- package/dist/adapters/cli.d.mts +35 -0
- package/dist/adapters/cli.mjs +357 -0
- package/dist/adapters/embedded.d.mts +19 -0
- package/dist/adapters/embedded.mjs +15 -0
- package/dist/adapters/kit.d.mts +23 -0
- package/dist/adapters/kit.mjs +16 -0
- package/dist/adapters/mcp.d.mts +39 -0
- package/dist/adapters/mcp.mjs +278 -0
- package/dist/adapters/vite.d.mts +32 -0
- package/dist/adapters/vite.mjs +31 -0
- package/dist/client/index.d.mts +227 -0
- package/dist/client/index.mjs +2 -0
- package/dist/client-4WrEozlH.mjs +1561 -0
- package/dist/constants.d.mts +20 -0
- package/dist/constants.mjs +34 -0
- package/dist/context-BrePWeyd.mjs +6776 -0
- package/dist/define-Bb4zh-Dc.mjs +11 -0
- package/dist/devtool-OJ3QW0ns.d.mts +1125 -0
- package/dist/helpers/nuxt/index.d.mts +46 -0
- package/dist/helpers/nuxt/index.mjs +58 -0
- package/dist/helpers/nuxt/runtime/plugin.client.d.mts +8 -0
- package/dist/helpers/nuxt/runtime/plugin.client.mjs +12 -0
- package/dist/human-id-CHS0s28X.mjs +844 -0
- package/dist/immer-HjMAm3b6.mjs +894 -0
- package/dist/index-DvKDO5H8.d.mts +333 -0
- package/dist/index.d.mts +10 -0
- package/dist/index.mjs +2 -0
- package/dist/main-DpINGndA.mjs +601 -0
- package/dist/node/index.d.mts +365 -0
- package/dist/node/index.mjs +69 -0
- package/dist/open-BtOOEldu.mjs +533 -0
- package/dist/recipes/open-helpers.d.mts +104 -0
- package/dist/recipes/open-helpers.mjs +69 -0
- package/dist/rpc/client.d.mts +9 -0
- package/dist/rpc/client.mjs +13 -0
- package/dist/rpc/index.d.mts +2 -0
- package/dist/rpc/index.mjs +3 -0
- package/dist/rpc/server.d.mts +8 -0
- package/dist/rpc/server.mjs +10 -0
- package/dist/rpc/transports/ws-client.d.mts +2 -0
- package/dist/rpc/transports/ws-client.mjs +43 -0
- package/dist/rpc/transports/ws-server.d.mts +2 -0
- package/dist/rpc/transports/ws-server.mjs +58 -0
- package/dist/rpc-9FNa3Inb.mjs +474 -0
- package/dist/server-DrBxa6ZV.mjs +49 -0
- package/dist/src-BoIqXRc9.mjs +85 -0
- package/dist/static-dump-CQUC1aIW.mjs +82 -0
- package/dist/transports-BPUzHhI2.mjs +15 -0
- package/dist/types/index.d.mts +4 -0
- package/dist/types/index.mjs +6 -0
- package/dist/utils/events.d.mts +9 -0
- package/dist/utils/events.mjs +40 -0
- package/dist/utils/human-id.d.mts +10 -0
- package/dist/utils/human-id.mjs +3 -0
- package/dist/utils/nanoid.d.mts +4 -0
- package/dist/utils/nanoid.mjs +10 -0
- package/dist/utils/promise.d.mts +8 -0
- package/dist/utils/promise.mjs +15 -0
- package/dist/utils/shared-state.d.mts +2 -0
- package/dist/utils/shared-state.mjs +36 -0
- package/dist/utils/state.d.mts +49 -0
- package/dist/utils/state.mjs +26 -0
- package/dist/utils/when.d.mts +2 -0
- package/dist/utils/when.mjs +424 -0
- package/dist/when-CGLewRtm.d.mts +401 -0
- package/dist/ws-client-CklfxUHE.d.mts +17 -0
- package/dist/ws-server--IuUAaGi.d.mts +37 -0
- 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,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,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,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,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 };
|