devframe 0.9.11 → 0.9.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/build.mjs +1 -1
- package/dist/adapters/cac.mjs +1 -1
- package/dist/adapters/dev.d.mts +1 -1
- package/dist/adapters/dev.mjs +1 -1
- package/dist/adapters/initiate.d.mts +1 -1
- package/dist/adapters/initiate.mjs +1 -1
- package/dist/adapters/mcp.mjs +9 -15
- package/dist/client/index.mjs +20 -23
- package/dist/{context-Bq27SDK-.mjs → context-DwGevWqT.mjs} +30 -19
- package/dist/{dev-B32EVw5w.mjs → dev-CZ1fu4J1.mjs} +2 -2
- package/dist/{instance-shell-BWh0JQuo.d.mts → instance-shell-BUyYrKlu.d.mts} +9 -2
- package/dist/{instance-shell-DvYCwrDy.mjs → instance-shell-xuu6jg51.mjs} +7 -2
- package/dist/internal/index.d.mts +1 -1
- package/dist/internal/index.mjs +1 -1
- package/dist/node/index.mjs +1 -1
- package/dist/recipes/interactive-auth.d.mts +34 -8
- package/dist/recipes/interactive-auth.mjs +47 -4
- package/package.json +1 -1
package/dist/adapters/build.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { t as resolveClientAssets } from "../client-assets-DNdhagGm.mjs";
|
|
|
3
3
|
import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME } from "../constants.mjs";
|
|
4
4
|
import { n as collectStaticRpcDump, t as writeStaticRpcDump } from "../write-BuLCrn9h.mjs";
|
|
5
5
|
import { t as diagnostics } from "../diagnostics-DZA6KQ_Z.mjs";
|
|
6
|
-
import { t as createHostContext } from "../context-
|
|
6
|
+
import { t as createHostContext } from "../context-DwGevWqT.mjs";
|
|
7
7
|
import { t as resolveStaticAssetsSource } from "../remote-assets-DMFzLSoH.mjs";
|
|
8
8
|
import { t as createH3DevframeHost } from "../host-h3-BROI6SQ4.mjs";
|
|
9
9
|
import fs from "node:fs/promises";
|
package/dist/adapters/cac.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { s as colors } from "../nostics-D0PvLZsn.mjs";
|
|
2
2
|
import { i as resolveDevServerPort, s as importRuntimeModule } from "../_shared-U8D-xzrp.mjs";
|
|
3
3
|
import { createBuild } from "./build.mjs";
|
|
4
|
-
import { t as createDevServer } from "../dev-
|
|
4
|
+
import { t as createDevServer } from "../dev-CZ1fu4J1.mjs";
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
import cac$1 from "cac";
|
|
7
7
|
//#region src/adapters/flags.ts
|
package/dist/adapters/dev.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection, n as WsOriginRegistry } from "../ws-server-D2nv68Hg.mjs";
|
|
2
2
|
import { F as DevframeDefinition, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, q as McpSetting, s as DevframeNodeRpcSession } from "../context-BBWPLDHh.mjs";
|
|
3
3
|
import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
|
|
4
|
-
import { c as StartedServer } from "../instance-shell-
|
|
4
|
+
import { c as StartedServer } from "../instance-shell-BUyYrKlu.mjs";
|
|
5
5
|
import { c as resolveMcpConnectionMeta, o as resolveDevServerPort, t as ResolveDevServerPortOptions } from "../_shared-DEAMiPfH.mjs";
|
|
6
6
|
import { H3 } from "h3";
|
|
7
7
|
//#region src/adapters/dev.d.ts
|
package/dist/adapters/dev.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { i as resolveDevServerPort, o as resolveMcpConnectionMeta } from "../_shared-U8D-xzrp.mjs";
|
|
2
|
-
import { t as createDevServer } from "../dev-
|
|
2
|
+
import { t as createDevServer } from "../dev-CZ1fu4J1.mjs";
|
|
3
3
|
export { createDevServer, resolveDevServerPort, resolveMcpConnectionMeta };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection, n as WsOriginRegistry } from "../ws-server-D2nv68Hg.mjs";
|
|
2
2
|
import { F as DevframeDefinition, St as DevframeStorageScope, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, o as DevframeNodeContext, q as McpSetting, s as DevframeNodeRpcSession, t as ConnectionMeta } from "../context-BBWPLDHh.mjs";
|
|
3
3
|
import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
|
|
4
|
-
import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-
|
|
4
|
+
import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-BUyYrKlu.mjs";
|
|
5
5
|
import { Buffer } from "node:buffer";
|
|
6
6
|
import { IncomingMessage, Server, ServerResponse } from "node:http";
|
|
7
7
|
import { Duplex } from "node:stream";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as getInstanceInternals, r as initDevframe } from "../dev-
|
|
1
|
+
import { n as getInstanceInternals, r as initDevframe } from "../dev-CZ1fu4J1.mjs";
|
|
2
2
|
export { getInstanceInternals, initDevframe };
|
package/dist/adapters/mcp.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { t as DEVFRAME_EVENTS } from "../events-BV4Dj59a.mjs";
|
|
|
3
3
|
import { t as isAllowedOrigin } from "../origin-DZit9g29.mjs";
|
|
4
4
|
import { r as timingSafeEqual } from "../crypto-token-TVbGGFuj.mjs";
|
|
5
5
|
import { t as diagnostics } from "../diagnostics-DZA6KQ_Z.mjs";
|
|
6
|
-
import { t as createHostContext } from "../context-
|
|
6
|
+
import { t as createHostContext } from "../context-DwGevWqT.mjs";
|
|
7
7
|
import { t as toAgentToolName } from "../agent-tool-name-DGzeuWcO.mjs";
|
|
8
8
|
import { join } from "pathe";
|
|
9
9
|
import process from "node:process";
|
|
@@ -126,11 +126,8 @@ function returnToJsonSchema(schema) {
|
|
|
126
126
|
*/
|
|
127
127
|
function argsToJsonSchema(args) {
|
|
128
128
|
if (!args || args.length === 0) return {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
properties: {}
|
|
132
|
-
},
|
|
133
|
-
unwrapped: false
|
|
129
|
+
type: "object",
|
|
130
|
+
properties: {}
|
|
134
131
|
};
|
|
135
132
|
const properties = {};
|
|
136
133
|
const required = [];
|
|
@@ -140,13 +137,10 @@ function argsToJsonSchema(args) {
|
|
|
140
137
|
required.push(key);
|
|
141
138
|
}
|
|
142
139
|
return {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
additionalProperties: false
|
|
148
|
-
},
|
|
149
|
-
unwrapped: false
|
|
140
|
+
type: "object",
|
|
141
|
+
properties,
|
|
142
|
+
required,
|
|
143
|
+
additionalProperties: false
|
|
150
144
|
};
|
|
151
145
|
}
|
|
152
146
|
//#endregion
|
|
@@ -443,7 +437,7 @@ function projectTool(name, tool, ctx) {
|
|
|
443
437
|
};
|
|
444
438
|
}
|
|
445
439
|
function computeInputSchema(tool, ctx) {
|
|
446
|
-
if (tool.kind === "tool") return argsToJsonSchema(tool.args)
|
|
440
|
+
if (tool.kind === "tool") return argsToJsonSchema(tool.args);
|
|
447
441
|
if (tool.kind !== "rpc" || !tool.rpcName) return {
|
|
448
442
|
type: "object",
|
|
449
443
|
properties: {}
|
|
@@ -454,7 +448,7 @@ function computeInputSchema(tool, ctx) {
|
|
|
454
448
|
properties: {}
|
|
455
449
|
};
|
|
456
450
|
const args = def.args;
|
|
457
|
-
return argsToJsonSchema(args)
|
|
451
|
+
return argsToJsonSchema(args);
|
|
458
452
|
}
|
|
459
453
|
function computeOutputSchema(tool, ctx) {
|
|
460
454
|
if (tool.kind !== "rpc" || !tool.rpcName) return void 0;
|
package/dist/client/index.mjs
CHANGED
|
@@ -968,20 +968,6 @@ function createRpcClient(functions, options) {
|
|
|
968
968
|
});
|
|
969
969
|
}
|
|
970
970
|
//#endregion
|
|
971
|
-
//#region src/utils/promise.ts
|
|
972
|
-
function promiseWithResolver() {
|
|
973
|
-
let resolve;
|
|
974
|
-
let reject;
|
|
975
|
-
return {
|
|
976
|
-
promise: new Promise((_resolve, _reject) => {
|
|
977
|
-
resolve = _resolve;
|
|
978
|
-
reject = _reject;
|
|
979
|
-
}),
|
|
980
|
-
resolve,
|
|
981
|
-
reject
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
//#endregion
|
|
985
971
|
//#region src/client/rpc-live.ts
|
|
986
972
|
/**
|
|
987
973
|
* The transport-independent half of a live RPC client mode (connection
|
|
@@ -993,7 +979,7 @@ function createLiveRpcClientMode(options) {
|
|
|
993
979
|
let isTrusted = false;
|
|
994
980
|
let status = "connecting";
|
|
995
981
|
let connectionError = null;
|
|
996
|
-
const trustedPromise =
|
|
982
|
+
const trustedPromise = Promise.withResolvers();
|
|
997
983
|
function setStatus(next, error = null) {
|
|
998
984
|
if (error) connectionError = error;
|
|
999
985
|
else if (next === "connected") connectionError = null;
|
|
@@ -1604,14 +1590,14 @@ function qualifyName(namespace, name) {
|
|
|
1604
1590
|
return isQualifiedName(name) ? name : `${namespace}:${name}`;
|
|
1605
1591
|
}
|
|
1606
1592
|
//#endregion
|
|
1607
|
-
//#region src/
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1593
|
+
//#region src/settings-store.ts
|
|
1594
|
+
/**
|
|
1595
|
+
* The key-value store surface over a lazily-resolved shared state, shared by
|
|
1596
|
+
* the node-side (file-backed) and client-side (RPC-mirrored) settings stores.
|
|
1597
|
+
* Each side supplies its own `store()` resolver; the read/write/subscribe
|
|
1598
|
+
* behavior on top of it is identical.
|
|
1599
|
+
*/
|
|
1600
|
+
function createSettingsStore(store) {
|
|
1615
1601
|
return {
|
|
1616
1602
|
async get(key) {
|
|
1617
1603
|
return (await store()).value()[key];
|
|
@@ -1634,6 +1620,17 @@ function createClientSettingsStore(rpc, namespace, scope) {
|
|
|
1634
1620
|
}
|
|
1635
1621
|
};
|
|
1636
1622
|
}
|
|
1623
|
+
//#endregion
|
|
1624
|
+
//#region src/client/settings.ts
|
|
1625
|
+
function createClientSettingsStore(rpc, namespace, scope) {
|
|
1626
|
+
const stateKey = `devframe:settings:${scope}:${namespace}`;
|
|
1627
|
+
let statePromise;
|
|
1628
|
+
function store() {
|
|
1629
|
+
if (!statePromise) statePromise = rpc.sharedState.get(stateKey, { initialValue: {} });
|
|
1630
|
+
return statePromise;
|
|
1631
|
+
}
|
|
1632
|
+
return createSettingsStore(store);
|
|
1633
|
+
}
|
|
1637
1634
|
/**
|
|
1638
1635
|
* Build the client-side `settings` surface for a scope namespace. Mirrors
|
|
1639
1636
|
* the node-side stores over the shared-state sync protocol.
|
|
@@ -1134,25 +1134,14 @@ function qualifyName(namespace, name) {
|
|
|
1134
1134
|
return isQualifiedName(name) ? name : `${namespace}:${name}`;
|
|
1135
1135
|
}
|
|
1136
1136
|
//#endregion
|
|
1137
|
-
//#region src/
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
function store() {
|
|
1146
|
-
if (!statePromise) {
|
|
1147
|
-
const dir = context.host.getStorageDir(STORAGE_SCOPE[scope]);
|
|
1148
|
-
const filepath = join(dir, "settings", `${namespace}.json`);
|
|
1149
|
-
statePromise = context.rpc.sharedState.get(stateKey, { sharedState: createStorage({
|
|
1150
|
-
filepath,
|
|
1151
|
-
initialValue: {}
|
|
1152
|
-
}) });
|
|
1153
|
-
}
|
|
1154
|
-
return statePromise;
|
|
1155
|
-
}
|
|
1137
|
+
//#region src/settings-store.ts
|
|
1138
|
+
/**
|
|
1139
|
+
* The key-value store surface over a lazily-resolved shared state, shared by
|
|
1140
|
+
* the node-side (file-backed) and client-side (RPC-mirrored) settings stores.
|
|
1141
|
+
* Each side supplies its own `store()` resolver; the read/write/subscribe
|
|
1142
|
+
* behavior on top of it is identical.
|
|
1143
|
+
*/
|
|
1144
|
+
function createSettingsStore(store) {
|
|
1156
1145
|
return {
|
|
1157
1146
|
async get(key) {
|
|
1158
1147
|
return (await store()).value()[key];
|
|
@@ -1175,6 +1164,28 @@ function createNodeSettingsStore(context, namespace, scope) {
|
|
|
1175
1164
|
}
|
|
1176
1165
|
};
|
|
1177
1166
|
}
|
|
1167
|
+
//#endregion
|
|
1168
|
+
//#region src/node/settings.ts
|
|
1169
|
+
const STORAGE_SCOPE = {
|
|
1170
|
+
global: "global",
|
|
1171
|
+
project: "project"
|
|
1172
|
+
};
|
|
1173
|
+
function createNodeSettingsStore(context, namespace, scope) {
|
|
1174
|
+
const stateKey = `devframe:settings:${scope}:${namespace}`;
|
|
1175
|
+
let statePromise;
|
|
1176
|
+
function store() {
|
|
1177
|
+
if (!statePromise) {
|
|
1178
|
+
const dir = context.host.getStorageDir(STORAGE_SCOPE[scope]);
|
|
1179
|
+
const filepath = join(dir, "settings", `${namespace}.json`);
|
|
1180
|
+
statePromise = context.rpc.sharedState.get(stateKey, { sharedState: createStorage({
|
|
1181
|
+
filepath,
|
|
1182
|
+
initialValue: {}
|
|
1183
|
+
}) });
|
|
1184
|
+
}
|
|
1185
|
+
return statePromise;
|
|
1186
|
+
}
|
|
1187
|
+
return createSettingsStore(store);
|
|
1188
|
+
}
|
|
1178
1189
|
/**
|
|
1179
1190
|
* Build the node-side `settings` surface for a scope namespace. `project`
|
|
1180
1191
|
* persists under the host's `workspace` storage dir, `global` under its
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { t as resolveClientAssets } from "./client-assets-DNdhagGm.mjs";
|
|
2
2
|
import { DEVFRAME_CONNECTION_META_FILENAME } from "./constants.mjs";
|
|
3
3
|
import { t as diagnostics } from "./diagnostics-DZA6KQ_Z.mjs";
|
|
4
|
-
import { t as createHostContext } from "./context-
|
|
4
|
+
import { t as createHostContext } from "./context-DwGevWqT.mjs";
|
|
5
5
|
import { t as resolveStaticAssetsSource } from "./remote-assets-DMFzLSoH.mjs";
|
|
6
6
|
import { a as resolveMcpConfig, i as resolveDevServerPort, n as normalizeBasePath, r as resolveBasePath, s as importRuntimeModule, t as loadAutoMcpAdapter } from "./_shared-U8D-xzrp.mjs";
|
|
7
7
|
import { t as createH3DevframeHost } from "./host-h3-BROI6SQ4.mjs";
|
|
8
|
-
import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-
|
|
8
|
+
import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-xuu6jg51.mjs";
|
|
9
9
|
import { open } from "./utils/open.mjs";
|
|
10
10
|
import { mountStaticHandler } from "./utils/serve-static.mjs";
|
|
11
11
|
import { resolve } from "pathe";
|
|
@@ -150,8 +150,15 @@ interface CreateInstanceShellOptions<TContext extends DevframeNodeContext> {
|
|
|
150
150
|
app?: H3;
|
|
151
151
|
/** Public origin, or a getter. Derived from the first request when omitted. */
|
|
152
152
|
origin?: string | (() => string);
|
|
153
|
-
/**
|
|
154
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Resolved auth intent: `undefined`/`true` gates with {@link createInteractiveAuth}'s
|
|
155
|
+
* defaults, `false` opts out, a handler installs a custom scheme outright.
|
|
156
|
+
* A function gates too, but builds the handler itself from the now-ready
|
|
157
|
+
* `ctx` - the seam a wrapping host (e.g. `@devframes/hub`'s UI slot) uses to
|
|
158
|
+
* hand `createInteractiveAuth` a branded `banner` while still leaving `auth`
|
|
159
|
+
* itself unset for the caller.
|
|
160
|
+
*/
|
|
161
|
+
auth?: boolean | DevframeAuthHandler | ((ctx: TContext) => DevframeAuthHandler);
|
|
155
162
|
/** Host `node:http` server to share the WS upgrade with. */
|
|
156
163
|
server?: Server;
|
|
157
164
|
/** Explicit WebSocket control; see {@link DevframeWsOptions}. `false` disables the socket (SSE-only). */
|
|
@@ -366,11 +366,16 @@ function createInstanceShell(options) {
|
|
|
366
366
|
};
|
|
367
367
|
/**
|
|
368
368
|
* Auth resolution: gate by default, `false` opts out, a handler object
|
|
369
|
-
* installs a custom scheme
|
|
370
|
-
* gate (the server behind `ws.url` owns
|
|
369
|
+
* installs a custom scheme, a function builds one from `ctx`. The `external`
|
|
370
|
+
* tier has no local transport to gate (the server behind `ws.url` owns
|
|
371
|
+
* auth) so it resolves to nothing.
|
|
371
372
|
*/
|
|
372
373
|
function resolveAuth() {
|
|
373
374
|
if (options.auth === false) return false;
|
|
375
|
+
if (typeof options.auth === "function") {
|
|
376
|
+
authHandler = options.auth(ctx);
|
|
377
|
+
return authHandler;
|
|
378
|
+
}
|
|
374
379
|
if (typeof options.auth === "object") {
|
|
375
380
|
authHandler = options.auth;
|
|
376
381
|
return options.auth;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { v as RpcFunctionDefinitionAny } from "../types-Dq4i156u.mjs";
|
|
2
2
|
import { At as AgentHandle, Bt as DevframeAgentHostEvents, F as DevframeDefinition, Ft as AgentTool, It as AgentToolInput, Lt as AgentToolProvider, Mt as AgentResource, Nt as AgentResourceContent, Pt as AgentResourceInput, Rt as AgentToolProviderHandle, Vt as EventEmitter, jt as AgentManifest, o as DevframeNodeContext, xt as DevframeHost, zt as DevframeAgentHost$1 } from "../context-BBWPLDHh.mjs";
|
|
3
3
|
import { a as RemoteAssetsStore, o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
|
|
4
|
-
import { a as InstanceShellInit, c as StartedServer, d as samePath, f as DevframeInstanceRecord, h as registerDevframeInstance, i as InstanceShellApi, l as createInstanceShell, m as listLiveDevframeInstances, n as InstanceRegisterConfig, o as InstanceShellInternals, p as DevframeInstanceRegistration, r as InstanceShell, s as InstanceWsTier, t as CreateInstanceShellOptions, u as resolveInstanceRegister } from "../instance-shell-
|
|
4
|
+
import { a as InstanceShellInit, c as StartedServer, d as samePath, f as DevframeInstanceRecord, h as registerDevframeInstance, i as InstanceShellApi, l as createInstanceShell, m as listLiveDevframeInstances, n as InstanceRegisterConfig, o as InstanceShellInternals, p as DevframeInstanceRegistration, r as InstanceShell, s as InstanceWsTier, t as CreateInstanceShellOptions, u as resolveInstanceRegister } from "../instance-shell-BUyYrKlu.mjs";
|
|
5
5
|
import { a as resolveBasePath, i as normalizeBasePath, n as ResolvedMcpConfig, r as loadAutoMcpAdapter, s as resolveMcpConfig } from "../_shared-DEAMiPfH.mjs";
|
|
6
6
|
import { n as CreateContextRpcServerOptions, r as createContextRpcServer, t as ContextRpcServer } from "../rpc-core-DiCr5etS.mjs";
|
|
7
7
|
//#region src/client-assets.d.ts
|
package/dist/internal/index.mjs
CHANGED
|
@@ -5,6 +5,6 @@ import { n as coerceAgentPositionalArgs, t as DevframeAgentHost } from "../host-
|
|
|
5
5
|
import { a as resolveMcpConfig, n as normalizeBasePath, r as resolveBasePath, s as importRuntimeModule, t as loadAutoMcpAdapter } from "../_shared-U8D-xzrp.mjs";
|
|
6
6
|
import { t as createH3DevframeHost } from "../host-h3-BROI6SQ4.mjs";
|
|
7
7
|
import { i as registerDevframeInstance, n as listLiveDevframeInstances } from "../instance-registry-DCq762YJ.mjs";
|
|
8
|
-
import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, r as samePath, t as createInstanceShell } from "../instance-shell-
|
|
8
|
+
import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, r as samePath, t as createInstanceShell } from "../instance-shell-xuu6jg51.mjs";
|
|
9
9
|
import { t as createContextRpcServer } from "../rpc-core-CvkU23bQ.mjs";
|
|
10
10
|
export { DevframeAgentHost, coerceAgentPositionalArgs, createContextRpcServer, createH3DevframeHost, createInstanceShell, createRpcWireCodec, diagnostics, importRuntimeModule, listLiveDevframeInstances, loadAutoMcpAdapter, normalizeBasePath, normalizeHttpServerUrl, peekRpcWireFrame, registerDevframeInstance, resolveBasePath, resolveClientAssets, resolveInstanceRegister, resolveMcpConfig, samePath };
|
package/dist/node/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Tt as DevframeAuthHandler, o as DevframeNodeContext, s as DevframeNodeRpcSession } from "../context-BBWPLDHh.mjs";
|
|
2
2
|
import "../index-1ezCLThh.mjs";
|
|
3
|
+
import { ColorFn } from "../utils/colors.mjs";
|
|
3
4
|
//#region src/recipes/interactive-auth.d.ts
|
|
4
5
|
interface CreateInteractiveAuthOptions {
|
|
5
6
|
/**
|
|
@@ -12,14 +13,12 @@ interface CreateInteractiveAuthOptions {
|
|
|
12
13
|
/**
|
|
13
14
|
* Print the current code + magic-link URL. Devframe stays headless, so
|
|
14
15
|
* there is no default banner printed automatically; call
|
|
15
|
-
* `auth.printBanner()` yourself once the server is listening.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* `auth.printBanner()` yourself once the server is listening. Defaults to
|
|
17
|
+
* {@link createAuthBanner}'s output; pass its result here directly to
|
|
18
|
+
* rebrand the box (title / colors), or your own function to replace the
|
|
19
|
+
* format outright.
|
|
18
20
|
*/
|
|
19
|
-
banner?:
|
|
20
|
-
code: string;
|
|
21
|
-
url: string;
|
|
22
|
-
}) => void;
|
|
21
|
+
banner?: AuthBannerFunction;
|
|
23
22
|
/**
|
|
24
23
|
* Called once a code exchange succeeds, so a host rendering its own
|
|
25
24
|
* banner can retract it. Fires after the rotated code is printed, so
|
|
@@ -37,6 +36,33 @@ interface CreateInteractiveAuthOptions {
|
|
|
37
36
|
*/
|
|
38
37
|
serverUrl?: () => string;
|
|
39
38
|
}
|
|
39
|
+
/** Signature of `options.banner`: render the current auth code + magic-link URL. */
|
|
40
|
+
type AuthBannerFunction = (info: {
|
|
41
|
+
code: string;
|
|
42
|
+
url: string;
|
|
43
|
+
}) => void;
|
|
44
|
+
/** Palette for {@link createAuthBanner}'s box - one color per part, so a host can rebrand a subset. */
|
|
45
|
+
interface CreateAuthBannerColorsOptions {
|
|
46
|
+
border: ColorFn;
|
|
47
|
+
title: ColorFn;
|
|
48
|
+
label: ColorFn;
|
|
49
|
+
code: ColorFn;
|
|
50
|
+
url: ColorFn;
|
|
51
|
+
}
|
|
52
|
+
interface CreateAuthBannerOptions {
|
|
53
|
+
/** Box title. Defaults to `'Devframe'` - set to your product name for branding. */
|
|
54
|
+
title?: string;
|
|
55
|
+
/** Palette overrides; unset colors fall back to dim/bold/cyan defaults. */
|
|
56
|
+
colors?: Partial<CreateAuthBannerColorsOptions>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build a {@link AuthBannerFunction} that renders the auth code + magic-link
|
|
60
|
+
* URL as a small bordered box, its two rows label-aligned. `createInteractiveAuth`
|
|
61
|
+
* falls back to `createAuthBanner()` when no `banner` is given; call this
|
|
62
|
+
* yourself to rebrand the box (`title` / `colors`) and pass the result as
|
|
63
|
+
* `options.banner`.
|
|
64
|
+
*/
|
|
65
|
+
declare function createAuthBanner(options?: CreateAuthBannerOptions): AuthBannerFunction;
|
|
40
66
|
/**
|
|
41
67
|
* Package the interactive OTP auth protocol devframe's primitives
|
|
42
68
|
* (`exchangeTempAuthCode`, `verifyAuthToken`, `revokeAuthToken`,
|
|
@@ -60,4 +86,4 @@ interface CreateInteractiveAuthOptions {
|
|
|
60
86
|
*/
|
|
61
87
|
declare function createInteractiveAuth(context: DevframeNodeContext, options?: CreateInteractiveAuthOptions): DevframeAuthHandler;
|
|
62
88
|
//#endregion
|
|
63
|
-
export { CreateInteractiveAuthOptions, createInteractiveAuth };
|
|
89
|
+
export { AuthBannerFunction, CreateAuthBannerColorsOptions, CreateAuthBannerOptions, CreateInteractiveAuthOptions, createAuthBanner, createInteractiveAuth };
|
|
@@ -5,8 +5,50 @@ import { a as verifyAuthToken, n as exchangeTempAuthCode, r as getTempAuthCode,
|
|
|
5
5
|
import { t as getInternalContext } from "../context-jXO5vzjH.mjs";
|
|
6
6
|
import { t as s } from "../simple-schema-Bi40l-P6.mjs";
|
|
7
7
|
//#region src/recipes/interactive-auth.ts
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Build a {@link AuthBannerFunction} that renders the auth code + magic-link
|
|
10
|
+
* URL as a small bordered box, its two rows label-aligned. `createInteractiveAuth`
|
|
11
|
+
* falls back to `createAuthBanner()` when no `banner` is given; call this
|
|
12
|
+
* yourself to rebrand the box (`title` / `colors`) and pass the result as
|
|
13
|
+
* `options.banner`.
|
|
14
|
+
*/
|
|
15
|
+
function createAuthBanner(options = {}) {
|
|
16
|
+
const title = options.title ?? "Devframe";
|
|
17
|
+
const palette = {
|
|
18
|
+
border: colors.dim,
|
|
19
|
+
title: colors.bold,
|
|
20
|
+
label: colors.dim,
|
|
21
|
+
code: colors.bold,
|
|
22
|
+
url: colors.cyan,
|
|
23
|
+
...options.colors
|
|
24
|
+
};
|
|
25
|
+
return (info) => {
|
|
26
|
+
const rows = [[
|
|
27
|
+
"auth code",
|
|
28
|
+
info.code,
|
|
29
|
+
palette.code
|
|
30
|
+
], [
|
|
31
|
+
"or open",
|
|
32
|
+
info.url,
|
|
33
|
+
palette.url
|
|
34
|
+
]];
|
|
35
|
+
const labelWidth = Math.max(...rows.map(([label]) => label.length));
|
|
36
|
+
const contentWidth = Math.max(...rows.map(([, value]) => labelWidth + 2 + value.length));
|
|
37
|
+
const titleBarLength = title.length + 3;
|
|
38
|
+
const lineWidth = Math.max(contentWidth, titleBarLength - 2);
|
|
39
|
+
const top = [
|
|
40
|
+
palette.border(`╭─`),
|
|
41
|
+
palette.title(title),
|
|
42
|
+
palette.border(`${"─".repeat(Math.max(lineWidth + 2 - titleBarLength, 0))}╮`)
|
|
43
|
+
].join(" ");
|
|
44
|
+
const bottom = `╰${"─".repeat(lineWidth + 2)}╯`;
|
|
45
|
+
const body = rows.map(([label, value, color]) => {
|
|
46
|
+
const plain = `${label.padEnd(labelWidth)} ${value}`;
|
|
47
|
+
const pad = " ".repeat(lineWidth - plain.length);
|
|
48
|
+
return `${palette.border("│")} ${palette.label(label.padEnd(labelWidth))} ${color(value)}${pad} ${palette.border("│")}`;
|
|
49
|
+
});
|
|
50
|
+
console.log(`\n${palette.border(top)}\n${body.join("\n")}\n${palette.border(bottom)}\n`);
|
|
51
|
+
};
|
|
10
52
|
}
|
|
11
53
|
/**
|
|
12
54
|
* Package the interactive OTP auth protocol devframe's primitives
|
|
@@ -39,13 +81,14 @@ function createInteractiveAuth(context, options = {}) {
|
|
|
39
81
|
function resolveServerUrl() {
|
|
40
82
|
return options.serverUrl?.() ?? context.host.resolveOrigin();
|
|
41
83
|
}
|
|
84
|
+
const banner = options.banner ?? createAuthBanner();
|
|
42
85
|
let bannerPrintedForCode;
|
|
43
86
|
function printBanner() {
|
|
44
87
|
const code = getTempAuthCode();
|
|
45
88
|
if (code === bannerPrintedForCode) return;
|
|
46
89
|
bannerPrintedForCode = code;
|
|
47
90
|
const url = buildOtpAuthUrl(resolveServerUrl(), code);
|
|
48
|
-
|
|
91
|
+
banner({
|
|
49
92
|
code,
|
|
50
93
|
url
|
|
51
94
|
});
|
|
@@ -146,4 +189,4 @@ function createInteractiveAuth(context, options = {}) {
|
|
|
146
189
|
};
|
|
147
190
|
}
|
|
148
191
|
//#endregion
|
|
149
|
-
export { createInteractiveAuth };
|
|
192
|
+
export { createAuthBanner, createInteractiveAuth };
|
package/package.json
CHANGED