okengine 0.19.2 → 0.19.4
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/package.json +1 -1
- package/site/content/docs/elements/channel/index.mdx +1 -1
- package/site/content/docs/elements/clock/index.mdx +106 -17
- package/site/content/docs/elements/clock/schedules.mdx +39 -11
- package/site/content/docs/elements/flow/consumers.mdx +129 -86
- package/site/content/docs/elements/flow/index.mdx +3 -3
- package/site/content/docs/elements/flow/routing.mdx +11 -8
- package/site/content/docs/elements/signal/broadcast.mdx +15 -14
- package/site/content/docs/elements/signal/index.mdx +99 -36
- package/site/content/docs/elements/signal/live.mdx +5 -13
- package/site/content/docs/elements/signal/once.mdx +88 -28
- package/site/content/docs/reference/errors.mdx +41 -27
- package/site/content/docs/understand/the-architecture.mdx +2 -2
- package/src/cli/competitor-mention-removal.test.ts +3 -3
- package/src/compiler/extract.test.ts +237 -15
- package/src/compiler/extract.ts +75 -4
- package/src/compiler/flow-path.test.ts +23 -0
- package/src/compiler/flow-path.ts +17 -1
- package/src/console/ui-next/dist/assets/{access-page-DceEWH9u.js → access-page-rO2HLPab.js} +1 -1
- package/src/console/ui-next/dist/assets/{agent-disclosure-tC9s2VFd.js → agent-disclosure-ae8w8JLx.js} +1 -1
- package/src/console/ui-next/dist/assets/{cache-glyph-C-naNQSR.js → cache-glyph-C-uHdh5d.js} +1 -1
- package/src/console/ui-next/dist/assets/{call-pii-button-DnZ_MlDn.js → call-pii-button-BJH54w4s.js} +1 -1
- package/src/console/ui-next/dist/assets/{collapsible-RekgR6Qz.js → collapsible-CaE8cs9p.js} +1 -1
- package/src/console/ui-next/dist/assets/{duration-tone-DugtWBS0.js → duration-tone-DdOQkQVK.js} +1 -1
- package/src/console/ui-next/dist/assets/{flows-page-DVmn1ZuQ.js → flows-page-DWeBszQQ.js} +1 -1
- package/src/console/ui-next/dist/assets/{highlighted-json-CvBGaiSD.js → highlighted-json-B2gBsC4B.js} +1 -1
- package/src/console/ui-next/dist/assets/{http-method-D7_OXbdC.js → http-method-BnMl0dJt.js} +1 -1
- package/src/console/ui-next/dist/assets/{index-DH0K2f6N.js → index-CBAP48v5.js} +3 -3
- package/src/console/ui-next/dist/assets/index-VxoEz295.css +2 -0
- package/src/console/ui-next/dist/assets/{observability-page-qJzF2nSN.js → observability-page-DVpcJEnW.js} +1 -1
- package/src/console/ui-next/dist/assets/{replica-lag-Vqk0pUBA.js → replica-lag-BUQf2Nf6.js} +1 -1
- package/src/console/ui-next/dist/assets/{request-meta-BtShi4sG.js → request-meta-CPkGDQgT.js} +1 -1
- package/src/console/ui-next/dist/assets/{store-page-CMsYH_vH.js → store-page-CwS_cY4V.js} +1 -1
- package/src/console/ui-next/dist/assets/{trace-detail-sheet-ycFB2uua.js → trace-detail-sheet-DNX7Y2bd.js} +1 -1
- package/src/console/ui-next/dist/assets/{tree-expand-toggle-iG1jcWgU.js → tree-expand-toggle-Bhdk27aF.js} +1 -1
- package/src/console/ui-next/dist/assets/{units-page-Bavchke4.js → units-page-CsBh0XbI.js} +1 -1
- package/src/console/ui-next/dist/assets/{vault-page-DxUFhiZI.js → vault-page-CsTlPtK9.js} +1 -1
- package/src/console/ui-next/dist/index.html +2 -2
- package/src/kernel/app.ts +87 -1
- package/src/kernel/errors-flow-name.ts +20 -4
- package/src/kernel/errors-once-signal.ts +25 -0
- package/src/kernel/errors.registry.test.ts +12 -2
- package/src/kernel/flow-name.test.ts +105 -20
- package/src/kernel/flow.ts +3 -3
- package/src/kernel/on.ts +0 -5
- package/src/kernel/once-signal.test.ts +71 -0
- package/src/kernel/stamp-http.test.ts +2 -1
- package/src/kernel/stamp-http.ts +5 -7
- package/src/kernel/unit.ts +1 -2
- package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +0 -2
|
@@ -2069,21 +2069,21 @@ export const app = oke({
|
|
|
2069
2069
|
});
|
|
2070
2070
|
});
|
|
2071
2071
|
|
|
2072
|
-
describe("extractManifest — inline Signal/Clock +
|
|
2072
|
+
describe("extractManifest — inline Signal/Clock + explicit / tree names", () => {
|
|
2073
2073
|
test("inline signal.once / clock.every stamp element maps and flow.trigger", async () => {
|
|
2074
2074
|
const source = `
|
|
2075
2075
|
import { on, flow, signal, clock } from "okengine";
|
|
2076
2076
|
|
|
2077
2077
|
on(
|
|
2078
2078
|
signal.once("link-clicked", { retries: 3, deadLetter: true }),
|
|
2079
|
-
flow({ do: async (input, fx) => {
|
|
2079
|
+
flow("hooks.linkClicked", { do: async (input, fx) => {
|
|
2080
2080
|
await fx.store("sql:links").set("x", input);
|
|
2081
2081
|
} }),
|
|
2082
2082
|
);
|
|
2083
2083
|
|
|
2084
2084
|
on(
|
|
2085
2085
|
clock.every("cleanup", "10m"),
|
|
2086
|
-
flow({ do: async (_input, fx) => {
|
|
2086
|
+
flow("ops.cleanup", { do: async (_input, fx) => {
|
|
2087
2087
|
await fx.store("sql:links").set("y", 1);
|
|
2088
2088
|
} }),
|
|
2089
2089
|
);
|
|
@@ -2095,16 +2095,16 @@ on(
|
|
|
2095
2095
|
deadLetter: true,
|
|
2096
2096
|
});
|
|
2097
2097
|
expect(manifest.clocks?.cleanup).toMatchObject({ every: "10m" });
|
|
2098
|
-
expect(manifest.flows?.["
|
|
2099
|
-
expect(manifest.flows?.cleanup?.trigger).toEqual({ every: "10m" });
|
|
2098
|
+
expect(manifest.flows?.["hooks.linkClicked"]?.trigger).toEqual({ signal: "link-clicked" });
|
|
2099
|
+
expect(manifest.flows?.["ops.cleanup"]?.trigger).toEqual({ every: "10m" });
|
|
2100
2100
|
});
|
|
2101
2101
|
|
|
2102
|
-
test("
|
|
2102
|
+
test("explicit flow name is independent of the trigger name", async () => {
|
|
2103
2103
|
const source = `
|
|
2104
2104
|
import { on, flow, signal, clock } from "okengine";
|
|
2105
2105
|
|
|
2106
2106
|
export const orderPlaced = signal.once("order-placed");
|
|
2107
|
-
on(orderPlaced, flow({ do: () => ({ ok: true }) }));
|
|
2107
|
+
on(orderPlaced, flow("orders.fulfill", { do: () => ({ ok: true }) }));
|
|
2108
2108
|
|
|
2109
2109
|
on(
|
|
2110
2110
|
clock.every("metrics.cleanup", "1h"),
|
|
@@ -2112,12 +2112,13 @@ on(
|
|
|
2112
2112
|
);
|
|
2113
2113
|
`;
|
|
2114
2114
|
const manifest = await extractFromSources({ "workers.ts": source });
|
|
2115
|
-
expect(manifest.flows?.["
|
|
2115
|
+
expect(manifest.flows?.["orders.fulfill"]?.trigger).toEqual({ signal: "order-placed" });
|
|
2116
2116
|
expect(manifest.flows?.["ops.sweep"]?.trigger).toEqual({ every: "1h" });
|
|
2117
2117
|
expect(manifest.flows?.["metrics.cleanup"]).toBeUndefined();
|
|
2118
|
+
expect(manifest.flows?.["order-placed"]).toBeUndefined();
|
|
2118
2119
|
});
|
|
2119
2120
|
|
|
2120
|
-
test("file-tree unit.export
|
|
2121
|
+
test("file-tree unit.export stamps a nameless Signal consumer", async () => {
|
|
2121
2122
|
const source = `
|
|
2122
2123
|
import { on, flow, signal } from "okengine";
|
|
2123
2124
|
export const onCreated = on(
|
|
@@ -2132,15 +2133,236 @@ export const onCreated = on(
|
|
|
2132
2133
|
expect(manifest.flows?.["note-created"]).toBeUndefined();
|
|
2133
2134
|
});
|
|
2134
2135
|
|
|
2135
|
-
test("two
|
|
2136
|
+
test("two differently-named flows on the same clock extract cleanly", async () => {
|
|
2137
|
+
const source = `
|
|
2138
|
+
import { on, flow, clock } from "okengine";
|
|
2139
|
+
export const tick = clock.every("metrics.tick", "1h");
|
|
2140
|
+
on(tick, flow("ops.sweep", { do: () => ({ a: true }) }));
|
|
2141
|
+
on(tick, flow("ops.report", { do: () => ({ b: true }) }));
|
|
2142
|
+
`;
|
|
2143
|
+
const manifest = await extractFromSources({ "clock-fanout.ts": source });
|
|
2144
|
+
expect(manifest.clocks?.["metrics.tick"]).toMatchObject({ every: "1h" });
|
|
2145
|
+
expect(manifest.flows?.["ops.sweep"]?.trigger).toEqual({ every: "1h" });
|
|
2146
|
+
expect(manifest.flows?.["ops.report"]?.trigger).toEqual({ every: "1h" });
|
|
2147
|
+
});
|
|
2148
|
+
|
|
2149
|
+
// Exact Clock docs Inline sample — explicit flow name, trigger written inline.
|
|
2150
|
+
const clockInlineExplicitDocsSample = `
|
|
2151
|
+
import { on, flow, clock } from "okengine";
|
|
2152
|
+
|
|
2153
|
+
export const pingExternal = on(
|
|
2154
|
+
clock.every("health.pingExternal", "30s"),
|
|
2155
|
+
flow("health.pingExternal", {
|
|
2156
|
+
plane: "operator",
|
|
2157
|
+
do: async (_, fx) => {
|
|
2158
|
+
await fx.call(pingUpstream);
|
|
2159
|
+
},
|
|
2160
|
+
}),
|
|
2161
|
+
);
|
|
2162
|
+
`;
|
|
2163
|
+
|
|
2164
|
+
test("docs Clock Inline (explicit name) extracts outside src/flows/<unit>/", async () => {
|
|
2165
|
+
const manifest = await extractFromSources({ "ping.ts": clockInlineExplicitDocsSample });
|
|
2166
|
+
expect(manifest.clocks?.["health.pingExternal"]?.every).toBe("30s");
|
|
2167
|
+
expect(manifest.flows?.["health.pingExternal"]?.trigger).toEqual({ every: "30s" });
|
|
2168
|
+
expect(manifest.flows?.["pingExternal"]).toBeUndefined();
|
|
2169
|
+
});
|
|
2170
|
+
|
|
2171
|
+
test("docs Clock named-export (shared schedule) extracts two explicit flows", async () => {
|
|
2172
|
+
const clockSource = `
|
|
2173
|
+
import { clock } from "okengine";
|
|
2174
|
+
|
|
2175
|
+
export const tickClock = clock.every("metrics.tick", "1h");
|
|
2176
|
+
`;
|
|
2177
|
+
const flowsSource = `
|
|
2178
|
+
import { on, flow } from "okengine";
|
|
2179
|
+
import { tickClock } from "@/clocks/metrics";
|
|
2180
|
+
|
|
2181
|
+
export const sweep = on(
|
|
2182
|
+
tickClock,
|
|
2183
|
+
flow("ops.sweep", {
|
|
2184
|
+
plane: "operator",
|
|
2185
|
+
do: async (_, fx) => {
|
|
2186
|
+
await fx.call(sweepMetrics);
|
|
2187
|
+
},
|
|
2188
|
+
}),
|
|
2189
|
+
);
|
|
2190
|
+
|
|
2191
|
+
export const report = on(
|
|
2192
|
+
tickClock,
|
|
2193
|
+
flow("ops.report", {
|
|
2194
|
+
plane: "operator",
|
|
2195
|
+
do: async (_, fx) => {
|
|
2196
|
+
await fx.call(reportMetrics);
|
|
2197
|
+
},
|
|
2198
|
+
}),
|
|
2199
|
+
);
|
|
2200
|
+
`;
|
|
2201
|
+
const manifest = await extractFromSources({
|
|
2202
|
+
"src/clocks/metrics.ts": clockSource,
|
|
2203
|
+
"src/flows/ops/metrics.ts": flowsSource,
|
|
2204
|
+
});
|
|
2205
|
+
expect(manifest.clocks?.["metrics.tick"]).toMatchObject({ every: "1h" });
|
|
2206
|
+
expect(manifest.flows?.["ops.sweep"]?.trigger).toEqual({ every: "1h" });
|
|
2207
|
+
expect(manifest.flows?.["ops.report"]?.trigger).toEqual({ every: "1h" });
|
|
2208
|
+
});
|
|
2209
|
+
});
|
|
2210
|
+
|
|
2211
|
+
describe("extractManifest — nameless Signal/Clock consumers fail OKE1072", () => {
|
|
2212
|
+
test("nameless flow({ do }) on signal.once fails OKE1072", async () => {
|
|
2213
|
+
const source = `
|
|
2214
|
+
import { on, flow, signal } from "okengine";
|
|
2215
|
+
on(signal.once("link-clicked"), flow({ do: () => ({ ok: true }) }));
|
|
2216
|
+
`;
|
|
2217
|
+
await expect(extractFromSources({ "once.ts": source })).rejects.toThrow(/OKE1072/);
|
|
2218
|
+
});
|
|
2219
|
+
|
|
2220
|
+
test("nameless flow({ do }) on signal.broadcast fails OKE1072", async () => {
|
|
2136
2221
|
const source = `
|
|
2137
2222
|
import { on, flow, signal } from "okengine";
|
|
2138
|
-
|
|
2139
|
-
on(ping, flow({ do: () => ({ a: true }) }));
|
|
2140
|
-
on(ping, flow({ do: () => ({ b: true }) }));
|
|
2223
|
+
on(signal.broadcast("catalog.changed"), flow({ do: () => ({ ok: true }) }));
|
|
2141
2224
|
`;
|
|
2142
|
-
await expect(extractFromSources({ "
|
|
2143
|
-
|
|
2225
|
+
await expect(extractFromSources({ "broadcast.ts": source })).rejects.toThrow(/OKE1072/);
|
|
2226
|
+
});
|
|
2227
|
+
|
|
2228
|
+
test("nameless flow({ do }) on signal.live fails OKE1072", async () => {
|
|
2229
|
+
const source = `
|
|
2230
|
+
import { on, flow, signal } from "okengine";
|
|
2231
|
+
on(signal.live("order-status", { optional: true }), flow({ do: () => ({ ok: true }) }));
|
|
2232
|
+
`;
|
|
2233
|
+
await expect(extractFromSources({ "live.ts": source })).rejects.toThrow(/OKE1072/);
|
|
2234
|
+
});
|
|
2235
|
+
|
|
2236
|
+
test("nameless flow({ do }) on clock.every fails OKE1072", async () => {
|
|
2237
|
+
const source = `
|
|
2238
|
+
import { on, flow, clock } from "okengine";
|
|
2239
|
+
on(clock.every("cleanup", "10m"), flow({ do: () => ({ ok: true }) }));
|
|
2240
|
+
`;
|
|
2241
|
+
await expect(extractFromSources({ "clock.ts": source })).rejects.toThrow(/OKE1072/);
|
|
2242
|
+
});
|
|
2243
|
+
|
|
2244
|
+
// Exact Signal docs Inline sample — tree path vs anywhere else.
|
|
2245
|
+
const signalInlineDocsSample = `
|
|
2246
|
+
import { on, flow, signal } from "okengine";
|
|
2247
|
+
import { z } from "zod";
|
|
2248
|
+
|
|
2249
|
+
export const ingestWebhook = on(
|
|
2250
|
+
signal.once("hooks.inbound", {
|
|
2251
|
+
schema: z.object({ id: z.string() }),
|
|
2252
|
+
retries: 3,
|
|
2253
|
+
deadLetter: true,
|
|
2254
|
+
}),
|
|
2255
|
+
flow({
|
|
2256
|
+
do: async ({ id }, fx) => {
|
|
2257
|
+
await fx.call(persistHook, { id });
|
|
2258
|
+
},
|
|
2259
|
+
}),
|
|
2260
|
+
);
|
|
2261
|
+
`;
|
|
2262
|
+
|
|
2263
|
+
test("docs Inline sample at src/flows/hooks/inbound.ts stamps hooks.ingestWebhook", async () => {
|
|
2264
|
+
const manifest = await extractFromSources({
|
|
2265
|
+
"src/flows/hooks/inbound.ts": signalInlineDocsSample,
|
|
2266
|
+
});
|
|
2267
|
+
expect(manifest.flows?.["hooks.ingestWebhook"]?.trigger).toEqual({ signal: "hooks.inbound" });
|
|
2268
|
+
expect(manifest.signals?.["hooks.inbound"]?.delivery).toBe("once");
|
|
2269
|
+
expect(manifest.flows?.["ingestWebhook"]).toBeUndefined();
|
|
2270
|
+
expect(manifest.flows?.["hooks.inbound"]).toBeUndefined();
|
|
2271
|
+
});
|
|
2272
|
+
|
|
2273
|
+
test("docs Inline sample outside src/flows/<unit>/ fails OKE1072", async () => {
|
|
2274
|
+
try {
|
|
2275
|
+
await extractFromSources({ "inbound.ts": signalInlineDocsSample });
|
|
2276
|
+
expect.unreachable("extract should throw OKE1072");
|
|
2277
|
+
} catch (err) {
|
|
2278
|
+
expect(err).toBeInstanceOf(Error);
|
|
2279
|
+
const message = (err as Error).message;
|
|
2280
|
+
expect(message).toMatch(/OKE1072/);
|
|
2281
|
+
expect(message).toContain("hooks.inbound");
|
|
2282
|
+
expect(message).toContain('flow("unit.export"');
|
|
2283
|
+
expect(message).toContain("src/flows/<unit>/");
|
|
2284
|
+
}
|
|
2285
|
+
});
|
|
2286
|
+
|
|
2287
|
+
test("docs Inline sample under src/signals/ fails OKE1072", async () => {
|
|
2288
|
+
await expect(
|
|
2289
|
+
extractFromSources({ "src/signals/inbound.ts": signalInlineDocsSample }),
|
|
2290
|
+
).rejects.toThrow(/OKE1072/);
|
|
2291
|
+
});
|
|
2292
|
+
|
|
2293
|
+
const clockInlineDocsSample = `
|
|
2294
|
+
import { on, flow, clock } from "okengine";
|
|
2295
|
+
|
|
2296
|
+
export const pingExternal = on(
|
|
2297
|
+
clock.every("health.pingExternal", "30s"),
|
|
2298
|
+
flow({
|
|
2299
|
+
plane: "operator",
|
|
2300
|
+
do: async (_, fx) => {
|
|
2301
|
+
await fx.call(pingUpstream);
|
|
2302
|
+
},
|
|
2303
|
+
}),
|
|
2304
|
+
);
|
|
2305
|
+
`;
|
|
2306
|
+
|
|
2307
|
+
test("docs Clock Inline sample at src/flows/health/ping.ts stamps health.pingExternal", async () => {
|
|
2308
|
+
const manifest = await extractFromSources({
|
|
2309
|
+
"src/flows/health/ping.ts": clockInlineDocsSample,
|
|
2310
|
+
});
|
|
2311
|
+
expect(manifest.flows?.["health.pingExternal"]?.trigger).toEqual({ every: "30s" });
|
|
2312
|
+
expect(manifest.clocks?.["health.pingExternal"]?.every).toBe("30s");
|
|
2313
|
+
expect(manifest.flows?.["pingExternal"]).toBeUndefined();
|
|
2314
|
+
});
|
|
2315
|
+
|
|
2316
|
+
test("docs Clock Inline sample outside src/flows/<unit>/ fails OKE1072", async () => {
|
|
2317
|
+
await expect(extractFromSources({ "ping.ts": clockInlineDocsSample })).rejects.toThrow(
|
|
2318
|
+
/OKE1072/,
|
|
2144
2319
|
);
|
|
2145
2320
|
});
|
|
2146
2321
|
});
|
|
2322
|
+
|
|
2323
|
+
describe("extractManifest — once-signal uniqueness OKE1071", () => {
|
|
2324
|
+
test("two differently-named flows on the same once signal fail OKE1071", async () => {
|
|
2325
|
+
const source = `
|
|
2326
|
+
import { on, flow, signal } from "okengine";
|
|
2327
|
+
export const orderPlaced = signal.once("orders.placed");
|
|
2328
|
+
on(orderPlaced, flow("orders.charge", { do: () => ({ a: true }) }));
|
|
2329
|
+
on(orderPlaced, flow("orders.ship", { do: () => ({ b: true }) }));
|
|
2330
|
+
`;
|
|
2331
|
+
try {
|
|
2332
|
+
await extractFromSources({ "dup-once.ts": source });
|
|
2333
|
+
expect.unreachable("extract should throw OKE1071");
|
|
2334
|
+
} catch (err) {
|
|
2335
|
+
expect(err).toBeInstanceOf(Error);
|
|
2336
|
+
const message = (err as Error).message;
|
|
2337
|
+
expect(message).toMatch(/OKE1071/);
|
|
2338
|
+
expect(message).toContain("orders.placed");
|
|
2339
|
+
expect(message).toContain("orders.charge");
|
|
2340
|
+
expect(message).toContain("orders.ship");
|
|
2341
|
+
expect(message).toMatch(/signal\.broadcast/);
|
|
2342
|
+
}
|
|
2343
|
+
});
|
|
2344
|
+
|
|
2345
|
+
test("the same scenario with signal.broadcast does not fail", async () => {
|
|
2346
|
+
const source = `
|
|
2347
|
+
import { on, flow, signal } from "okengine";
|
|
2348
|
+
export const catalogChanged = signal.broadcast("catalog.changed");
|
|
2349
|
+
on(catalogChanged, flow("cache.invalidate", { do: () => ({ a: true }) }));
|
|
2350
|
+
on(catalogChanged, flow("search.reindex", { do: () => ({ b: true }) }));
|
|
2351
|
+
`;
|
|
2352
|
+
const manifest = await extractFromSources({ "fanout.ts": source });
|
|
2353
|
+
expect(manifest.signals?.["catalog.changed"]?.delivery).toBe("broadcast");
|
|
2354
|
+
expect(manifest.flows?.["cache.invalidate"]?.trigger).toEqual({ signal: "catalog.changed" });
|
|
2355
|
+
expect(manifest.flows?.["search.reindex"]?.trigger).toEqual({ signal: "catalog.changed" });
|
|
2356
|
+
});
|
|
2357
|
+
|
|
2358
|
+
test("a single flow bound to once extracts cleanly", async () => {
|
|
2359
|
+
const source = `
|
|
2360
|
+
import { on, flow, signal } from "okengine";
|
|
2361
|
+
export const emailTask = signal.once("tasks.email");
|
|
2362
|
+
on(emailTask, flow("workers.email", { do: () => ({ ok: true }) }));
|
|
2363
|
+
`;
|
|
2364
|
+
const manifest = await extractFromSources({ "once.ts": source });
|
|
2365
|
+
expect(manifest.signals?.["tasks.email"]?.delivery).toBe("once");
|
|
2366
|
+
expect(manifest.flows?.["workers.email"]?.trigger).toEqual({ signal: "tasks.email" });
|
|
2367
|
+
});
|
|
2368
|
+
});
|
package/src/compiler/extract.ts
CHANGED
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
type InferBinding,
|
|
56
56
|
type Literal,
|
|
57
57
|
} from "./effects-infer.ts";
|
|
58
|
-
import { nameFromFlowFile, pathFromFlowFile } from "./flow-path.ts";
|
|
58
|
+
import { isFlowsTreeFile, nameFromFlowFile, pathFromFlowFile } from "./flow-path.ts";
|
|
59
59
|
import {
|
|
60
60
|
defaultListInSchema,
|
|
61
61
|
jsonSchemaFromAst,
|
|
@@ -204,6 +204,10 @@ export async function extractManifest(options: ExtractManifestOptions = {}): Pro
|
|
|
204
204
|
// Pass 3 — resolve deferred refs (agent tools, journey paths).
|
|
205
205
|
finalizeRefs(scope);
|
|
206
206
|
|
|
207
|
+
// Pass 4 — once-signal uniqueness (every flow.trigger.signal + delivery
|
|
208
|
+
// is known). HTTP / live uniqueness is construction-time in `oke()`.
|
|
209
|
+
assertOnceSignalSingleFlow(scope);
|
|
210
|
+
|
|
207
211
|
// Stable ordering for golden files.
|
|
208
212
|
const flows = sortRecord(scope.flows);
|
|
209
213
|
const signals = sortRecord(scope.signals);
|
|
@@ -1848,13 +1852,21 @@ function registerFlow(args: {
|
|
|
1848
1852
|
const trigger = args.triggerNode
|
|
1849
1853
|
? parseTrigger(args.triggerNode, args.scope, args.file.path)
|
|
1850
1854
|
: undefined;
|
|
1851
|
-
const inherited = elementTriggerName(args.triggerNode, args.scope);
|
|
1852
1855
|
|
|
1856
|
+
const signalOrClock = isSignalOrClockTrigger(trigger);
|
|
1857
|
+
const treeName =
|
|
1858
|
+
!signalOrClock || isFlowsTreeFile(args.file.path)
|
|
1859
|
+
? nameFromFlowFile(args.file.path, args.exportName)
|
|
1860
|
+
: undefined;
|
|
1861
|
+
|
|
1862
|
+
// Signal / Clock: explicit `flow("name")` or a real `src/flows/<unit>/`
|
|
1863
|
+
// tree stamp. A bare `export const` outside that folder is not a name —
|
|
1864
|
+
// **OKE1072**, same as `oke()`. HTTP still falls through to exportName.
|
|
1853
1865
|
const name =
|
|
1854
1866
|
stringArg(args.flowCall.arguments[0]) ??
|
|
1855
|
-
|
|
1867
|
+
treeName ??
|
|
1868
|
+
(signalOrClock ? unnamedElementFlowName(args.triggerNode, args.scope, trigger) : undefined) ??
|
|
1856
1869
|
args.exportName ??
|
|
1857
|
-
inherited ??
|
|
1858
1870
|
`flow_${Object.keys(args.scope.flows).length + 1}`;
|
|
1859
1871
|
|
|
1860
1872
|
if (args.exportName) {
|
|
@@ -2386,10 +2398,46 @@ function putFlow(scope: ProjectScope, name: string, flow: Flow): void {
|
|
|
2386
2398
|
scope.flows[name] = flow;
|
|
2387
2399
|
}
|
|
2388
2400
|
|
|
2401
|
+
/**
|
|
2402
|
+
* Refuse two different Flow names bound to the same `signal.once`.
|
|
2403
|
+
*
|
|
2404
|
+
* Horizontal replicas of one Flow are a single `on()` in source — this only
|
|
2405
|
+
* fires when the Manifest itself lists two or more Flow names on that signal.
|
|
2406
|
+
* `signal.broadcast` / `signal.live` bindings are unrestricted.
|
|
2407
|
+
*
|
|
2408
|
+
* @param scope - Project scope after flow collection
|
|
2409
|
+
*/
|
|
2410
|
+
function assertOnceSignalSingleFlow(scope: ProjectScope): void {
|
|
2411
|
+
const once = new Map<string, string>();
|
|
2412
|
+
for (const [name, flow] of Object.entries(scope.flows)) {
|
|
2413
|
+
const s = flow.trigger?.signal;
|
|
2414
|
+
if (!s || scope.signals[s]?.delivery !== "once") continue;
|
|
2415
|
+
const prev = once.get(s);
|
|
2416
|
+
if (prev) {
|
|
2417
|
+
throw new Error(
|
|
2418
|
+
`OKE1071: once signal "${s}" bound to ${prev}, ${name}. Use signal.broadcast.`,
|
|
2419
|
+
);
|
|
2420
|
+
}
|
|
2421
|
+
once.set(s, name);
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
/**
|
|
2426
|
+
* True when the parsed trigger is a Signal or Clock (cron / every).
|
|
2427
|
+
*
|
|
2428
|
+
* @param parsed - Parsed `on()` trigger
|
|
2429
|
+
*/
|
|
2430
|
+
function isSignalOrClockTrigger(parsed: ParsedTrigger | undefined): boolean {
|
|
2431
|
+
const t = parsed?.trigger;
|
|
2432
|
+
return Boolean(t && (t.signal || t.cron || t.every));
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2389
2435
|
/**
|
|
2390
2436
|
* Stable Signal / Clock name on `on()`'s first argument, when one exists.
|
|
2391
2437
|
* HTTP has no inherent name of this kind — returns undefined.
|
|
2392
2438
|
*
|
|
2439
|
+
* Used only for **OKE1072** diagnostics — never as a Flow name.
|
|
2440
|
+
*
|
|
2393
2441
|
* @param node - Trigger AST
|
|
2394
2442
|
* @param scope - Project scope
|
|
2395
2443
|
*/
|
|
@@ -2422,6 +2470,29 @@ function elementTriggerName(node: AstNode | undefined, scope: ProjectScope): str
|
|
|
2422
2470
|
return undefined;
|
|
2423
2471
|
}
|
|
2424
2472
|
|
|
2473
|
+
/**
|
|
2474
|
+
* Fail loud when a Signal / Clock consumer has no explicit or tree-derived name.
|
|
2475
|
+
* HTTP still falls through to the generic `flow_*` placeholder (OKE1045 at boot).
|
|
2476
|
+
*
|
|
2477
|
+
* @param triggerNode - Trigger AST
|
|
2478
|
+
* @param scope - Project scope
|
|
2479
|
+
* @param parsed - Parsed trigger
|
|
2480
|
+
* @returns Never for Signal / Clock; `undefined` otherwise
|
|
2481
|
+
*/
|
|
2482
|
+
function unnamedElementFlowName(
|
|
2483
|
+
triggerNode: AstNode | undefined,
|
|
2484
|
+
scope: ProjectScope,
|
|
2485
|
+
parsed: ParsedTrigger | undefined,
|
|
2486
|
+
): undefined {
|
|
2487
|
+
if (!isSignalOrClockTrigger(parsed)) return undefined;
|
|
2488
|
+
const triggerName = elementTriggerName(triggerNode, scope);
|
|
2489
|
+
const kind = parsed?.trigger?.signal ? "signal" : "clock";
|
|
2490
|
+
const target = triggerName ? `${kind} "${triggerName}"` : kind;
|
|
2491
|
+
throw new Error(
|
|
2492
|
+
`OKE1072: nameless flow({ do }) bound to ${target}. Use flow("unit.export", { do }) or export it from a src/flows/<unit>/ file so the tree can stamp unit.export.`,
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2425
2496
|
/**
|
|
2426
2497
|
* Inline `signal.once(…)` / `clock.every(…)` as `on()`'s first argument.
|
|
2427
2498
|
*
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { describe, expect, test } from "bun:test";
|
|
6
6
|
import {
|
|
7
7
|
importSpecifierFromWalked,
|
|
8
|
+
isFlowsTreeFile,
|
|
8
9
|
nameFromFlowFile,
|
|
9
10
|
pathFromFlowFile,
|
|
10
11
|
toPosixPath,
|
|
@@ -93,4 +94,26 @@ describe("nameFromFlowFile / unitFromFlowFile", () => {
|
|
|
93
94
|
expect(nameFromFlowFile("main/health.ts", "health")).toBe("main.health");
|
|
94
95
|
expect(nameFromFlowFile("main/route.ts", "root")).toBe("main.root");
|
|
95
96
|
});
|
|
97
|
+
|
|
98
|
+
test("Signal Inline docs path stamps hooks.ingestWebhook; a bare file does not", () => {
|
|
99
|
+
expect(nameFromFlowFile("src/flows/hooks/inbound.ts", "ingestWebhook")).toBe(
|
|
100
|
+
"hooks.ingestWebhook",
|
|
101
|
+
);
|
|
102
|
+
expect(unitFromFlowFile("src/flows/hooks/inbound.ts")).toBe("hooks");
|
|
103
|
+
expect(nameFromFlowFile("inbound.ts", "ingestWebhook")).toBeUndefined();
|
|
104
|
+
expect(unitFromFlowFile("inbound.ts")).toBeUndefined();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe("isFlowsTreeFile", () => {
|
|
109
|
+
test("src/flows/<unit>/ and /flows/ mark a tree file; other folders do not", () => {
|
|
110
|
+
expect(isFlowsTreeFile("src/flows/hooks/inbound.ts")).toBe(true);
|
|
111
|
+
expect(isFlowsTreeFile("src/flows/health/ping.ts")).toBe(true);
|
|
112
|
+
expect(isFlowsTreeFile("app/src/flows/notes/on-created.ts")).toBe(true);
|
|
113
|
+
expect(isFlowsTreeFile("flows/hooks/inbound.ts")).toBe(true);
|
|
114
|
+
expect(isFlowsTreeFile("inbound.ts")).toBe(false);
|
|
115
|
+
expect(isFlowsTreeFile("src/signals/inbound.ts")).toBe(false);
|
|
116
|
+
expect(isFlowsTreeFile("src/clocks/digest.ts")).toBe(false);
|
|
117
|
+
expect(isFlowsTreeFile("lib/inbound.ts")).toBe(false);
|
|
118
|
+
});
|
|
96
119
|
});
|
|
@@ -131,7 +131,9 @@ export function pathFromFlowFile(relFromFlowsDirOrSource: string): string | unde
|
|
|
131
131
|
/**
|
|
132
132
|
* Infer `unit.export` from a flow file + export name.
|
|
133
133
|
*
|
|
134
|
-
* `[id]` / `(group)` never enter the name.
|
|
134
|
+
* `[id]` / `(group)` never enter the name. A path that is not under a unit
|
|
135
|
+
* folder (bare `inbound.ts`, or `src/flows/inbound.ts` with no unit) returns
|
|
136
|
+
* `undefined` — Signal / Clock extract then fails **OKE1072**.
|
|
135
137
|
*
|
|
136
138
|
* @param filePath - Source path under `flows/`
|
|
137
139
|
* @param exportName - `export const` binding
|
|
@@ -146,6 +148,20 @@ export function nameFromFlowFile(
|
|
|
146
148
|
return `${unit}.${exportName}`;
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
/**
|
|
152
|
+
* True when the path is under a flows tree (`src/flows/…` or `…/flows/…`).
|
|
153
|
+
*
|
|
154
|
+
* Adopt-relative `unit/file.ts` (no prefix) is not a tree path — generate-adopt
|
|
155
|
+
* prefixes the unit before {@link nameFromFlowFile}. Without this gate, a
|
|
156
|
+
* nameless Signal worker in `src/signals/inbound.ts` would stamp `src.ingestWebhook`.
|
|
157
|
+
*
|
|
158
|
+
* @param filePath - Source path
|
|
159
|
+
*/
|
|
160
|
+
export function isFlowsTreeFile(filePath: string): boolean {
|
|
161
|
+
const posix = toPosixPath(filePath);
|
|
162
|
+
return posix.includes("/flows/") || posix.startsWith("src/flows/") || posix.startsWith("flows/");
|
|
163
|
+
}
|
|
164
|
+
|
|
149
165
|
/**
|
|
150
166
|
* First-level folder under `src/flows` — the client unit.
|
|
151
167
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{r as t}from"./react-dom-Ddte4I-Q.js";import{A as n}from"./xyflow-yApv7D4e.js";import{Cr as r,Dr as i,E as a,Er as o,F as s,Fr as c,I as l,Ir as u,Lr as d,Nr as f,Pr as p,R as m,Rr as h,Sr as g,Tr as _,Vr as v,Yi as y,_r as b,ar as x,br as S,c as C,cr as w,dr as T,ha as ee,i as E,kr as D,l as O,lr as k,mr as A,nr as j,o as M,pr as N,rr as P,s as F,sr as I,tr as L,u as te,ur as R,vr as z,wr as B,x as V,xr as H}from"./shortcut-keys-3ILd8oGn.js";import{i as ne,t as re}from"./http-method-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{r as t}from"./react-dom-Ddte4I-Q.js";import{A as n}from"./xyflow-yApv7D4e.js";import{Cr as r,Dr as i,E as a,Er as o,F as s,Fr as c,I as l,Ir as u,Lr as d,Nr as f,Pr as p,R as m,Rr as h,Sr as g,Tr as _,Vr as v,Yi as y,_r as b,ar as x,br as S,c as C,cr as w,dr as T,ha as ee,i as E,kr as D,l as O,lr as k,mr as A,nr as j,o as M,pr as N,rr as P,s as F,sr as I,tr as L,u as te,ur as R,vr as z,wr as B,x as V,xr as H}from"./shortcut-keys-3ILd8oGn.js";import{i as ne,t as re}from"./http-method-BnMl0dJt.js";import{a as ie,c as ae,h as oe,i as se,n as ce,o as le,r as ue,s as U,t as de}from"./element-icons-BI8cJgdh.js";import{t as fe}from"./UserIcon-DaE2PB5_.js";import{t as pe}from"./PlusSignIcon-CwG3nxfu.js";import{bt as W,ct as me,it as he}from"./index-CBAP48v5.js";import{t as ge}from"./explorer-empty-CJs5A-wm.js";import{a as G,c as _e,l as K,n as q,o as ve,r as ye,s as be,t as xe}from"./detail-header-DVWNjWjg.js";import{n as Se,t as J}from"./copy-inline-button-CAYD18cr.js";var Ce=[[`path`,{d:`M5 21H19`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:`1.5`,key:`0`}],[`path`,{d:`M12.125 12.75H12M12.25 12.75C12.25 12.8881 12.1381 13 12 13C11.8619 13 11.75 12.8881 11.75 12.75C11.75 12.6119 11.8619 12.5 12 12.5C12.1381 12.5 12.25 12.6119 12.25 12.75Z`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:`1.5`,key:`1`}],[`path`,{d:`M14.9152 7.61089L13.8078 5.38179C13.019 3.79393 12.6246 3 12 3C11.3754 3 10.981 3.79393 10.1922 5.38179L9.08483 7.61089C8.58107 8.62494 8.32919 9.13197 7.87976 9.24608C7.8485 9.25401 7.81689 9.26043 7.78503 9.26533C7.32682 9.3357 6.89919 8.96678 6.04393 8.22895C4.0124 6.47635 2.99663 5.60004 2.38034 5.94899C2.34045 5.97157 2.30213 5.99686 2.26565 6.02467C1.70197 6.45439 2.09541 7.74136 2.88229 10.3153L4.04783 14.1279C4.47098 15.5121 4.68255 16.2042 5.21787 16.6021C5.75318 17 6.47261 17 7.91147 17L16.0886 16.9999C17.5274 16.9999 18.2468 16.9999 18.7821 16.602C19.3175 16.2041 19.529 15.512 19.9522 14.1279L21.1177 10.3153C21.9046 7.74137 22.298 6.4544 21.7344 6.02468C21.6979 5.99687 21.6595 5.97158 21.6197 5.94899C21.0034 5.60006 19.9876 6.47636 17.9561 8.22896C17.1008 8.96679 16.6732 9.3357 16.215 9.26533C16.1831 9.26043 16.1515 9.25401 16.1202 9.24607C15.6708 9.13197 15.4189 8.62494 14.9152 7.61089Z`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:`1.5`,key:`2`}]],Y=e(t(),1);function we(e,t){if(e==null)return`never`;let n=e-t;if(Math.abs(n)<6e4)return`just now`;let r=Ee(Math.abs(n));return n<0?`${r} ago`:`in ${r}`}function Te(e,t){return e==null?`never`:e<=t?`expired`:we(e,t)}function Ee(e){if(e<36e5)return`${Math.floor(e/6e4)}m`;if(e<864e5)return`${Math.floor(e/36e5)}h`;let t=Math.floor(e/864e5);return t<100?`${t}d`:`${Math.floor(t/30)}mo`}var X=864e5;function De(e){let t=/^(\d+)(ms|s|m|h|d)$/.exec(e.trim());if(!t)return 0;let n=Number(t[1]);switch(t[2]){case`ms`:return n;case`s`:return n*1e3;case`m`:return n*6e4;case`h`:return n*36e5;case`d`:return n*X;default:return 0}}function Oe(e,t,n=``){if(e===`never`)return null;if(e===`30d`)return t+30*X;if(e===`90d`)return t+90*X;let r=De(n);return r>0?t+r:null}var Z=36e5;function ke(e,t){if(e==null)return{choice:`never`,custom:``};let n=e-t;return n<=0?{choice:`never`,custom:``}:Math.abs(n-30*X)<Z?{choice:`30d`,custom:``}:Math.abs(n-90*X)<Z?{choice:`90d`,custom:``}:{choice:`custom`,custom:Me(n)}}var Ae=7*X;function je(e,t){if(e==null||e<=t)return{choice:`90d`,custom:``};let n=e-t;return Math.abs(n-30*X)<=Ae?{choice:`30d`,custom:``}:Math.abs(n-90*X)<=Ae?{choice:`90d`,custom:``}:{choice:`custom`,custom:Me(n)}}function Me(e){return e<=0?``:e>=X&&e%X===0?`${e/X}d`:e>=Z&&e%Z===0?`${e/Z}h`:e>=6e4&&e%6e4==0?`${e/6e4}m`:e>=X?`${Math.max(1,Math.round(e/X))}d`:e>=Z?`${Math.max(1,Math.round(e/Z))}h`:`${Math.max(1,Math.round(e/6e4))}m`}var Ne=[`s`,`m`,`h`,`d`,`ms`],Pe={s:`Seconds`,m:`Minutes`,h:`Hours`,d:`Days`,ms:`Milliseconds`};function Fe(e,t,n){let r=e.trim(),i=t.trim();if(r.length===0&&i.length===0)return null;if(r.length===0||i.length===0||!/^\d+$/.test(r)||!/^\d+$/.test(i))return;let a=Number(r),o=Number(i);if(a<=0||o<=0)return;let s=`${o}${n}`;if(!(De(s)<=0))return{max:a,per:s}}function Ie(e){let t=/^(\d+)(ms|s|m|h|d)$/.exec(e.trim());return t?{count:t[1],unit:t[2]}:{count:``,unit:`m`}}function Le(e){let t=ze(e);return t.length===0?null:Be(t)?`ip`:Ve(t)?`host`:null}function Re(e){let t=new Set,n=[];for(let r of e.split(/[\s,]+/)){let e=ze(r);e.length===0||t.has(e)||Le(e)!=null&&(t.add(e),n.push(e))}return n}function ze(e){let t=e.trim().toLowerCase();if(t=t.replace(/^https?:\/\//,``),t.startsWith(`[`)&&t.includes(`]`)){let e=t.indexOf(`]`),n=t.slice(1,e),r=t.slice(e+1);t=r.startsWith(`:`)||r.startsWith(`/`)?n:`${n}${r}`}let n=t.indexOf(`/`);return n>=0&&(t=t.slice(0,n)),t.endsWith(`.`)&&(t=t.slice(0,-1)),t}function Be(e){return/^\d{1,3}(?:\.\d{1,3}){3}$/.test(e)?e.split(`.`).every(e=>Number(e)<=255):!e.includes(`:`)||!/^[0-9a-f:]+$/.test(e)||e.split(`::`).length>2?!1:e.split(`:`).filter(e=>e.length>0).length>=1}function Ve(e){if(e===`localhost`)return!0;if(e.length>253||e.includes(`:`))return!1;let t=e.split(`.`);return t.length<2?!1:t.every((e,n)=>!(e.length===0||e.length>63||!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(e)||n===t.length-1&&!/^[a-z]{2,63}$/.test(e)))}function He(e){let t=[],n=new Map;for(let r of e){let e=r.indexOf(`:`),i=e<=0?r:r.slice(0,e),a=e<=0?r:r.slice(e+1),o=n.get(i);if(o){o.push({scope:r,action:a});continue}t.push(i),n.set(i,[{scope:r,action:a}])}return t.map(e=>({group:e,items:n.get(e)??[]}))}var Q=n(),Ue=`GET /secure
|
|
2
2
|
Authorization: Bearer <secret>`,We=`{ "ok": true }`;function Ge({keyRow:e,blast:t,now:n,leading:r,onEdit:a,onRefresh:s,onRevoke:c,onRotate:l,rotatePending:u}){let d=e.revokedAt!==null,f=e.expiresAt!==null&&e.expiresAt<=n,p=t?.lastUsedAt??e.lastUsedAt,m=t?.callVolume??0,h=Te(e.expiresAt,n),g=we(p,n),_=e.rateLimit?`${e.rateLimit.max} / ${e.rateLimit.per}`:`none`,v=(0,Y.useMemo)(()=>He(e.scopes),[e.scopes]),y=e.creatorScopes.length,b=y>0&&e.scopes.length<y;return(0,Q.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col overflow-y-auto`,"data-slot":`access-detail`,"aria-label":`Access key detail`,"aria-live":`polite`,children:[(0,Q.jsx)(xe,{dataSlot:`access-detail-header`,leading:r,icon:(0,Q.jsx)(i,{icon:oe,className:`size-4`}),title:e.name,badge:(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsxs)(`span`,{className:`inline-flex items-center gap-1 font-mono text-[10px] font-medium tracking-[0.08em] text-muted-foreground uppercase`,children:[(0,Q.jsx)(i,{icon:e.plane===`operator`?Ce:fe,className:`size-3`,"aria-hidden":!0}),e.plane]}),d?(0,Q.jsx)(`span`,{className:`font-mono text-[10px] text-destructive`,children:`revoked`}):null,f&&!d?(0,Q.jsx)(`span`,{className:`font-mono text-[10px] text-amber-700 dark:text-amber-400`,children:`expired`}):null,e.unused90d&&!d&&!f?(0,Q.jsx)(`span`,{className:`font-mono text-[10px] text-amber-700 dark:text-amber-400`,children:`unused`}):null]}),subtitle:(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(`code`,{className:`min-w-0 truncate font-mono text-[11px] leading-none text-foreground/80`,children:e.id}),(0,Q.jsx)(J,{value:e.id,label:`Copy ${e.id}`})]}),actions:(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsx)(U,{label:`Rename or re-attenuate scopes`,className:`flex self-stretch`,children:(0,Q.jsx)(V,{type:`button`,variant:`ghost`,size:`sm`,className:`h-full rounded-none`,disabled:d,onClick:a,children:`Edit`})}),(0,Q.jsx)(U,{label:`Reset expiry from now. The secret stays the same.`,className:`flex self-stretch`,children:(0,Q.jsx)(V,{type:`button`,variant:`ghost`,size:`sm`,className:`h-full rounded-none`,"data-slot":`access-refresh`,disabled:d,onClick:s,children:`Refresh`})}),(0,Q.jsx)(U,{label:`Mint a new secret. The current secret stops working after residual TTL.`,className:`flex self-stretch`,children:(0,Q.jsx)(V,{type:`button`,variant:`ghost`,size:`sm`,className:`h-full rounded-none`,disabled:u||d,onClick:l,children:`Rotate`})}),(0,Q.jsx)(U,{label:`Irreversible. Residual sessions may continue for the access TTL.`,className:`flex self-stretch`,children:(0,Q.jsx)(V,{type:`button`,variant:`destructive`,size:`sm`,className:`h-full rounded-none`,disabled:d,onClick:c,children:`Revoke`})})]})}),(0,Q.jsx)(Ke,{revoked:d,expired:f,unused:e.unused90d,residual:t?.residualAccessNote}),(0,Q.jsxs)(`div`,{className:z,"data-slot":`access-briefing`,role:`group`,"aria-label":`Usage`,children:[(0,Q.jsx)(Xe,{label:`calls`,value:String(m)}),(0,Q.jsx)(Xe,{label:`used`,value:g,hint:p?new Date(p).toISOString():`No recorded call`,warn:p==null&&!d}),(0,Q.jsx)(Xe,{label:`expires`,value:h,hint:e.expiresAt?new Date(e.expiresAt).toISOString():`No expiry`,warn:f&&!d}),(0,Q.jsx)(Xe,{label:`rate`,value:_})]}),(0,Q.jsxs)(`section`,{className:`shrink-0 border-b border-border/60`,"aria-label":`Scopes`,children:[(0,Q.jsx)($,{title:`Scopes`,meta:b?`${e.scopes.length} of ${y}`:String(e.scopes.length),children:e.scopes.length>0?(0,Q.jsx)(J,{value:e.scopes.join(`
|
|
3
3
|
`),label:`Copy scopes`}):null}),v.length===0?(0,Q.jsx)(`p`,{className:`px-2 py-1.5 text-[11px] text-muted-foreground`,children:`No scopes granted.`}):(0,Q.jsx)(`ul`,{"data-slot":`access-scopes`,children:v.map(e=>(0,Q.jsxs)(`li`,{className:A,"aria-label":e.group,children:[(0,Q.jsx)(`span`,{className:o(B,`w-[5.5rem] shrink-0`),children:e.group}),(0,Q.jsx)(`div`,{className:`flex min-w-0 flex-1 flex-wrap items-center gap-x-2`,children:e.items.map(e=>(0,Q.jsx)(`span`,{title:e.scope,className:`font-mono text-[11px] text-foreground`,children:e.action},e.scope))}),(0,Q.jsx)(Ze,{value:e.items.map(e=>e.scope).join(`
|
|
4
4
|
`),label:`Copy ${e.group} scopes`})]},e.group))})]}),(0,Q.jsxs)(`section`,{className:`shrink-0 border-b border-border/60`,"aria-label":`Key`,children:[(0,Q.jsx)($,{title:`Key`}),(0,Q.jsxs)(`dl`,{"data-slot":`access-key-facts`,children:[(0,Q.jsx)(Qe,{label:`Issuer`,value:e.creatorId,copy:e.creatorId,copyLabel:`Copy ${e.creatorId}`}),(0,Q.jsx)(Qe,{label:`Created`,value:we(e.createdAt,n),hint:new Date(e.createdAt).toISOString()}),(0,Q.jsx)(Qe,{label:`Expires`,value:h,hint:e.expiresAt?new Date(e.expiresAt).toISOString():void 0,warn:f&&!d}),(0,Q.jsx)(Qe,{label:`Rate`,value:_})]})]}),(0,Q.jsx)(qe,{entries:e.ipAllowlist}),(0,Q.jsx)(Je,{sourceAddresses:t?.sourceAddresses??[],residual:t?.residualAccessNote,lastUsed:p,now:n}),(0,Q.jsx)(Ye,{scopes:e.scopes})]})}function Ke({revoked:e,expired:t,unused:n,residual:r}){return e?(0,Q.jsx)(`section`,{className:o(z,`border-destructive/25 bg-destructive/5`),"aria-label":`Revoked`,role:`status`,children:(0,Q.jsxs)(`p`,{className:`flex min-w-0 flex-1 items-center px-2 text-[12px] text-destructive`,children:[`Revoked`,(0,Q.jsxs)(`span`,{className:`text-muted-foreground`,children:[` `,`· `,r??`This secret no longer authenticates.`]})]})}):t?(0,Q.jsx)(`section`,{className:o(z,`border-amber-500/25 bg-amber-500/5`),"aria-label":`Expired`,role:`status`,children:(0,Q.jsxs)(`p`,{className:`flex min-w-0 flex-1 items-center px-2 text-[12px] text-amber-900 dark:text-amber-300`,children:[`Expired`,r?(0,Q.jsxs)(`span`,{className:`text-muted-foreground`,children:[` · `,r]}):null]})}):n?(0,Q.jsx)(`section`,{className:o(z,`border-amber-500/25 bg-amber-500/5`),"aria-label":`Unused`,role:`status`,children:(0,Q.jsxs)(`p`,{className:`flex min-w-0 flex-1 items-center px-2 text-[12px] text-amber-900 dark:text-amber-300`,children:[`No calls in 90 days`,(0,Q.jsx)(`span`,{className:`text-muted-foreground`,children:` · rotate or revoke`})]})}):null}function qe({entries:e}){return(0,Q.jsxs)(`section`,{className:`shrink-0 border-b border-border/60`,"aria-label":`Allow`,children:[(0,Q.jsx)($,{title:`Allow`,meta:e.length>0?String(e.length):`any`}),e.length===0?(0,Q.jsx)(`p`,{className:`px-2 py-1.5 text-[11px] text-muted-foreground`,children:`Any origin.`}):(0,Q.jsx)(`ul`,{"data-slot":`access-allow`,children:e.map(e=>{let t=Le(e);return(0,Q.jsxs)(`li`,{className:A,children:[(0,Q.jsx)(`span`,{className:o(B,`w-[5.5rem] shrink-0`),children:t===`ip`?`IP`:t===`host`?`Host`:`—`}),(0,Q.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-[11px]`,children:e}),(0,Q.jsx)(Ze,{value:e,label:`Copy ${e}`})]},e)})})]})}function Je({sourceAddresses:e,residual:t,lastUsed:n,now:r}){return(0,Q.jsxs)(`section`,{className:`shrink-0 border-b border-border/60`,"aria-label":`Usage`,children:[(0,Q.jsx)($,{title:`Usage`,meta:n?we(n,r):`never`}),e.length===0?(0,Q.jsx)(`p`,{className:`px-2 py-1.5 text-[11px] text-muted-foreground`,children:`No observed source IPs.`}):(0,Q.jsx)(`ul`,{"data-slot":`access-sources`,children:e.map(e=>(0,Q.jsxs)(`li`,{className:A,children:[(0,Q.jsx)(`span`,{className:o(B,`w-[5.5rem] shrink-0`),children:`IP`}),(0,Q.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-[11px]`,children:e}),(0,Q.jsx)(Ze,{value:e,label:`Copy ${e}`})]},e))}),t?(0,Q.jsx)(`p`,{className:`border-t border-border/60 px-2 py-1.5 text-[11px] text-muted-foreground`,children:t}):null]})}function Ye({scopes:e}){return(0,Q.jsxs)(`section`,{"data-slot":`access-call-example`,children:[(0,Q.jsx)($,{title:`Request`,children:(0,Q.jsx)(J,{value:Ue,label:`Copy request`})}),(0,Q.jsxs)(`div`,{className:`flex min-w-0 border-b border-border/60`,children:[(0,Q.jsx)(`div`,{className:o(`w-1 shrink-0 self-stretch`,ne(`GET`)),"aria-hidden":!0}),(0,Q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Q.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2 px-2.5 py-2`,children:[(0,Q.jsx)(`span`,{className:o(`shrink-0 font-mono text-[10px] font-semibold tracking-[0.08em] uppercase`,_(re(`GET`))),children:`GET`}),(0,Q.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-xs text-foreground select-all`,children:`/secure`})]}),(0,Q.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2 border-t border-border/60 px-2.5 py-2`,children:[(0,Q.jsx)(`span`,{className:`w-[7.5rem] shrink-0 truncate font-mono text-[11px] font-medium text-sky-600 dark:text-sky-400`,children:`Authorization`}),(0,Q.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-[11px] text-muted-foreground`,children:`Bearer <secret>`})]})]})]}),(0,Q.jsx)($,{title:`Response`,children:(0,Q.jsx)(J,{value:We,label:`Copy response`})}),(0,Q.jsxs)(`div`,{className:`flex min-w-0 border-b border-border/60`,children:[(0,Q.jsx)(`div`,{className:`w-1 shrink-0 self-stretch bg-emerald-500`,"aria-hidden":!0}),(0,Q.jsx)(`p`,{className:`min-w-0 flex-1 px-2.5 py-2 font-mono text-[11px] text-foreground/80 select-all`,children:We})]}),(0,Q.jsxs)(`p`,{className:`px-2 py-1.5 text-[11px] text-muted-foreground`,children:[`Seed the Bearer secret from create / rotate. The key is the issuer; gates see`,` `,e.join(`, `)||`its scopes`,`.`]})]})}function $({title:e,meta:t,children:n}){return(0,Q.jsxs)(`header`,{className:o(z,`items-center gap-2 px-2`),children:[(0,Q.jsx)(`h3`,{className:o(B,`shrink-0 leading-none`),children:e}),t?(0,Q.jsx)(`span`,{className:o(x,!n&&`ml-auto`),children:t}):null,n?(0,Q.jsx)(`div`,{className:`ml-auto flex items-center`,children:n}):null]})}function Xe({label:e,value:t,hint:n,warn:r=!1}){return(0,Q.jsxs)(`span`,{title:n,className:o(S,H,`gap-1.5`),children:[(0,Q.jsx)(`span`,{className:`tracking-[0.08em] uppercase`,children:e}),(0,Q.jsx)(`span`,{className:o(`font-mono tabular-nums text-foreground`,r&&`text-amber-800 dark:text-amber-400`),children:t})]})}function Ze({value:e,label:t}){return(0,Q.jsx)(`div`,{className:`opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100`,children:(0,Q.jsx)(J,{value:e,label:t})})}function Qe({label:e,value:t,hint:n,copy:r,copyLabel:i,warn:a=!1}){return(0,Q.jsxs)(`div`,{className:A,children:[(0,Q.jsx)(`dt`,{className:o(B,`w-[5.5rem] shrink-0`),children:e}),(0,Q.jsx)(`dd`,{className:o(`min-w-0 flex-1 truncate font-mono text-[11px]`,a&&`text-amber-800 dark:text-amber-400`),title:n,children:t}),r?(0,Q.jsx)(Ze,{value:r,label:i??`Copy ${e}`}):null]})}var $e=[`console.access.list`];function et(){return y({queryKey:$e,queryFn:async()=>{let e=await c();if(e.error||!e.data)throw Error(e.error?.message??`Empty access list`);return e.data}})}function tt({rows:e,selectedKey:t,query:n,loading:r=!1,onSelect:i}){let a=e.filter(e=>e.plane===`user`),o=e.filter(e=>e.plane===`operator`);return(0,Q.jsxs)(`div`,{id:`access-list`,"data-slot":`access-list`,className:`min-h-0 flex-1 overflow-y-auto`,children:[r&&e.length===0?(0,Q.jsx)(`p`,{className:R,children:`Loading…`}):null,!r&&e.length===0&&n.trim().length>0?(0,Q.jsx)(`p`,{className:R,children:`No keys match.`}):null,(0,Q.jsx)(nt,{label:`User`,icon:fe,rows:a,selectedKey:t,onSelect:i}),(0,Q.jsx)(nt,{label:`Operator`,icon:Ce,rows:o,selectedKey:t,onSelect:i})]})}function nt(e){return(0,Q.jsxs)(`section`,{className:L,"aria-label":e.label,children:[(0,Q.jsxs)(`div`,{className:j,children:[(0,Q.jsx)(i,{icon:e.icon,className:o(k,`text-muted-foreground`),"aria-hidden":!0}),(0,Q.jsx)(`span`,{className:o(P,`flex-1`),children:e.label}),(0,Q.jsx)(`span`,{className:x,children:e.rows.length})]}),e.rows.map(t=>{let n=t.id===e.selectedKey,r=t.revokedAt!==null;return(0,Q.jsxs)(`button`,{type:`button`,"data-slot":`access-key-row`,className:o(A,n&&`bg-muted/70 text-foreground`),onClick:()=>e.onSelect(t.id),children:[(0,Q.jsx)(`span`,{className:o(N,n&&`bg-sky-500`)}),(0,Q.jsx)(i,{icon:oe,className:o(k,`text-muted-foreground`)}),(0,Q.jsx)(`span`,{className:o(`min-w-0 truncate`,r&&`text-muted-foreground line-through`),children:t.name}),r?(0,Q.jsx)(`span`,{className:`ml-auto text-[10px] text-muted-foreground`,children:`revoked`}):t.unused90d?(0,Q.jsx)(`span`,{className:`ml-auto text-[10px] text-amber-700 dark:text-amber-400`,children:`unused`}):(0,Q.jsx)(`span`,{className:o(`ml-auto tabular-nums text-[10px] text-muted-foreground`),children:t.scopes.length})]},t.id)})]})}function rt({entries:e,rateMax:t,rateCount:n,rateUnit:r,onEntries:c,onRateMax:u,onRateCount:d,onRateUnit:f}){let[p,h]=(0,Y.useState)(``),_=Re(p),v=p.trim().length>0&&_.length===0,y=()=>{if(_.length===0)return;let t=new Set(e),n=[...e];for(let e of _)t.has(e)||(t.add(e),n.push(e));c(n),h(``)};return(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsxs)(`div`,{className:`border-b border-border/50`,"data-slot":`access-allow-field`,children:[(0,Q.jsxs)(`div`,{className:`flex items-stretch`,children:[(0,Q.jsx)(`p`,{className:`flex h-8 w-[5.5rem] shrink-0 items-center px-4 text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`Allow`}),(0,Q.jsx)(a,{value:p,onChange:e=>h(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),y())},placeholder:`203.0.113.4 or ci.example.com`,autoComplete:`off`,"aria-label":`Add allow entry`,"aria-invalid":v,flat:!0,className:o(q,`min-w-0 flex-1 font-mono`)}),e.length>0?(0,Q.jsx)(`span`,{className:o(x,`flex h-8 items-center pr-2`),children:e.length}):null,(0,Q.jsx)(`button`,{type:`button`,className:o(w,`h-8`),"aria-label":`Add allow entry`,disabled:_.length===0,onClick:y,children:(0,Q.jsx)(i,{icon:pe,className:`size-3.5`,"aria-hidden":!0})})]}),v?(0,Q.jsx)(`p`,{className:`border-t border-border/50 px-4 py-2 text-[11px] text-destructive`,children:`Need an IP or host — 203.0.113.4, ::1, localhost, or ci.example.com.`}):e.length===0?(0,Q.jsx)(`p`,{className:`border-t border-border/50 px-4 py-2 text-[11px] text-muted-foreground`,children:`Any client. Add an IP or host.`}):(0,Q.jsx)(`div`,{role:`list`,"aria-label":`Allow list`,children:e.map(t=>{let n=Le(t);return(0,Q.jsxs)(`div`,{role:`listitem`,"data-slot":`access-allow-entry`,"data-kind":n??`invalid`,className:o(A,`last:border-b-0`),children:[(0,Q.jsx)(`span`,{className:o(B,`w-[5.5rem] shrink-0 px-1.5`,n==null&&`text-destructive`),children:n===`ip`?`IP`:n===`host`?`Host`:`Bad`}),(0,Q.jsx)(`span`,{className:o(`min-w-0 truncate font-mono text-[11px]`,n==null&&`text-destructive`),children:t}),(0,Q.jsx)(`button`,{type:`button`,className:o(I,`ml-auto opacity-0 group-hover:opacity-100 focus-visible:opacity-100`),"aria-label":`Remove ${t}`,onClick:()=>c(e.filter(e=>e!==t)),children:(0,Q.jsx)(i,{icon:D,className:`size-3`,"aria-hidden":!0})})]},t)})})]}),(0,Q.jsxs)(`div`,{className:`flex items-stretch border-b border-border/50`,"data-slot":`access-rate-field`,children:[(0,Q.jsx)(`p`,{className:`flex h-8 w-[5.5rem] shrink-0 items-center px-4 text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`Rate`}),(0,Q.jsxs)(`label`,{className:`flex min-w-0 flex-1 items-stretch border-r border-border/50`,children:[(0,Q.jsx)(`span`,{className:`flex h-8 shrink-0 items-center pl-1 text-[10px] font-semibold tracking-[0.08em] text-muted-foreground uppercase`,children:`Max`}),(0,Q.jsx)(a,{value:t,onChange:e=>u(e.target.value),placeholder:`none`,inputMode:`numeric`,autoComplete:`off`,"aria-label":`Rate max`,flat:!0,className:o(q,`min-w-0 flex-1 px-2 font-mono tabular-nums`)})]}),(0,Q.jsxs)(`label`,{className:`flex min-w-0 flex-1 items-stretch`,children:[(0,Q.jsx)(`span`,{className:`flex h-8 shrink-0 items-center pl-2 text-[10px] font-semibold tracking-[0.08em] text-muted-foreground uppercase`,children:`Every`}),(0,Q.jsx)(a,{value:n,onChange:e=>d(e.target.value),placeholder:`1`,inputMode:`numeric`,autoComplete:`off`,"aria-label":`Rate window`,flat:!0,className:o(q,`min-w-0 flex-1 px-2 font-mono tabular-nums`)})]}),(0,Q.jsx)(`div`,{className:`flex h-8 shrink-0 items-stretch`,role:`group`,"aria-label":`Rate unit`,children:Ne.map(e=>(0,Q.jsxs)(s,{children:[(0,Q.jsx)(m,{render:t=>(0,Q.jsx)(`button`,{...t,type:`button`,"aria-pressed":r===e,"aria-label":Pe[e],onClick:n=>{t.onClick?.(n),f(e)},className:o(S,`h-8 px-1.5 font-mono font-semibold`,r===e?g:H),children:e})}),(0,Q.jsx)(l,{side:`bottom`,className:`text-[11px]`,children:Pe[e]})]},e))})]})]})}function it({expires:e,customExpires:t,onExpires:n,onCustomExpires:r}){return(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsxs)(ve,{label:`Expires`,children:[(0,Q.jsx)(G,{active:e===`never`,onClick:()=>n(`never`),children:`never`}),(0,Q.jsx)(G,{active:e===`30d`,onClick:()=>n(`30d`),children:`30d`}),(0,Q.jsx)(G,{active:e===`90d`,onClick:()=>n(`90d`),children:`90d`}),(0,Q.jsx)(G,{active:e===`custom`,onClick:()=>n(`custom`),children:`custom`})]}),e===`custom`?(0,Q.jsx)(_e,{label:`Duration`,hint:`7d · 12h · 30m`,children:(0,Q.jsx)(a,{value:t,onChange:e=>r(e.target.value),placeholder:`7d`,autoComplete:`off`,"aria-label":`Custom expiry duration`,flat:!0,className:o(q,`font-mono`)})}):null]})}function at({value:e,placeholder:t,label:n,onChange:r}){return(0,Q.jsxs)(`label`,{className:`relative min-w-0 flex-1`,children:[(0,Q.jsx)(i,{icon:he,className:`pointer-events-none absolute top-1/2 left-3 size-3.5 -translate-y-1/2 text-muted-foreground`,"aria-hidden":!0}),(0,Q.jsx)(a,{value:e,onChange:e=>r(e.target.value),placeholder:t,"aria-label":n,autoComplete:`off`,flat:!0,className:o(ye)})]})}function ot({scopes:e,selected:t,empty:n,onChange:r}){let[i,a]=(0,Y.useState)(``),s=new Set(t),c=(0,Y.useMemo)(()=>st(e,i),[e,i]),l=(0,Y.useMemo)(()=>He(c),[c]),u=e.join(`\0`);return(0,Y.useEffect)(()=>{a(``)},[u]),(0,Q.jsxs)(`div`,{className:`border-b border-border/50`,"data-slot":`access-scope-field`,children:[(0,Q.jsxs)(`div`,{className:`flex items-stretch`,children:[(0,Q.jsx)(`p`,{className:`flex h-8 w-[5.5rem] shrink-0 items-center px-4 text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`Scopes`}),e.length>0?(0,Q.jsx)(at,{value:i,placeholder:`Search scopes`,label:`Search scopes`,onChange:a}):null]}),e.length===0?(0,Q.jsx)(`p`,{className:`border-t border-border/50 px-4 py-3 text-[11px] text-muted-foreground`,children:n}):c.length===0?(0,Q.jsx)(`p`,{className:`border-t border-border/50 px-4 py-3 text-[11px] text-muted-foreground`,children:`No scopes match.`}):(0,Q.jsx)(`div`,{className:`max-h-56 overflow-y-auto`,role:`group`,"aria-label":`Scopes`,children:l.map(e=>(0,Q.jsxs)(`div`,{className:`flex items-stretch border-t border-border/50`,role:`group`,"aria-label":e.group,children:[(0,Q.jsx)(`p`,{className:`flex w-[5.5rem] shrink-0 items-center px-4 font-mono text-[10px] font-semibold tracking-[0.08em] text-muted-foreground uppercase`,children:e.group}),(0,Q.jsx)(`div`,{className:`flex min-w-0 flex-1 flex-wrap items-stretch`,children:e.items.map(e=>{let n=s.has(e.scope);return(0,Q.jsx)(`button`,{type:`button`,"aria-pressed":n,"aria-label":e.scope,"data-slot":`access-scope-chip`,title:e.scope,onClick:()=>{r(n?t.filter(t=>t!==e.scope):[...t,e.scope])},className:o(`inline-flex h-8 min-w-0 items-center px-2 font-mono text-[10px] font-semibold outline-none select-none`,`focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-inset`,n?`bg-muted text-foreground`:`text-muted-foreground hover:text-foreground`),children:e.action},e.scope)})})]},e.group))})]})}function st(e,t){let n=t.trim().toLowerCase();return n.length===0?e:e.filter(e=>e.toLowerCase().includes(n))}function ct({open:e,users:t,userScopes:n,operatorScopes:r,pending:i,error:s,onOpenChange:c,onSubmit:l}){let[u,d]=(0,Y.useState)(`user`),[f,p]=(0,Y.useState)(``),[m,h]=(0,Y.useState)(``),[g,_]=(0,Y.useState)([]),[v,y]=(0,Y.useState)(`never`),[b,x]=(0,Y.useState)(``),[S,w]=(0,Y.useState)([]),[T,ee]=(0,Y.useState)(``),[D,k]=(0,Y.useState)(``),[j,P]=(0,Y.useState)(`m`),[I,L]=(0,Y.useState)(``),R=t.find(e=>e.id===m)??null,z=(0,Y.useMemo)(()=>{let e=I.trim().toLowerCase(),n=e.length===0?t:t.filter(t=>t.name.toLowerCase().includes(e)||t.id.toLowerCase().includes(e)||t.email.toLowerCase().includes(e));return R&&!n.some(e=>e.id===R.id)?[R,...n]:n},[t,I,R]),B=(0,Y.useMemo)(()=>u===`operator`?r:R==null?[]:R.scopes.length>0?R.scopes:n,[u,n,r,R]);(0,Y.useEffect)(()=>{e||(d(`user`),p(``),h(``),_([]),y(`never`),x(``),w([]),ee(``),k(``),P(`m`),L(``))},[e]),(0,Y.useEffect)(()=>{_(e=>{let t=e.filter(e=>B.includes(e));if(t.length>0)return t;let n=B[0];return n?[n]:[]})},[B]);let V=De(b),H=Fe(T,D,j),ne=f.trim().length>0&&g.length>0&&!i&&H!==void 0&&(u===`operator`||m.length>0)&&(v!==`custom`||V>0);return(0,Q.jsx)(E,{open:e,modal:!1,disablePointerDismissal:!0,onOpenChange:c,children:(0,Q.jsxs)(M,{side:`right`,showOverlay:!1,className:`gap-0 p-0 data-[side=right]:sm:max-w-md`,"data-slot":`access-create-sheet`,children:[(0,Q.jsxs)(O,{className:`gap-1 border-b border-border/50`,children:[(0,Q.jsx)(te,{className:`text-sm`,children:`Create API key`}),(0,Q.jsx)(F,{className:`text-[11px]`,children:u===`user`?`User-plane keys require an issuer. The key cannot exceed that user's grants.`:`Operator keys inherit the actor ceiling. Absence is impossible — only grantable scopes appear.`})]}),(0,Q.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto`,children:[(0,Q.jsxs)(`div`,{className:`flex items-stretch border-b border-border/50`,"data-slot":`access-name-field`,children:[(0,Q.jsx)(`p`,{className:`flex h-8 w-[5.5rem] shrink-0 items-center px-4 text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`Name`}),(0,Q.jsx)(a,{value:f,onChange:e=>p(e.target.value),placeholder:`CI deploy`,autoComplete:`off`,"aria-label":`Key name`,flat:!0,className:o(q,`min-w-0 flex-1`)})]}),(0,Q.jsxs)(ve,{label:`Plane`,children:[(0,Q.jsx)(G,{active:u===`user`,icon:fe,onClick:()=>{d(`user`)},children:`user`}),(0,Q.jsx)(G,{active:u===`operator`,icon:Ce,onClick:()=>{d(`operator`),h(``),L(``)},children:`operator`})]}),(0,Q.jsx)(it,{expires:v,customExpires:b,onExpires:y,onCustomExpires:x}),(0,Q.jsx)(rt,{entries:S,rateMax:T,rateCount:D,rateUnit:j,onEntries:w,onRateMax:ee,onRateCount:k,onRateUnit:P}),u===`user`?(0,Q.jsxs)(`div`,{className:`border-b border-border/50`,"data-slot":`access-issuer-field`,children:[(0,Q.jsxs)(`div`,{className:`flex items-stretch`,children:[(0,Q.jsx)(`p`,{className:`flex h-8 w-[5.5rem] shrink-0 items-center px-4 text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`Issuer`}),t.length>0?(0,Q.jsx)(at,{value:I,placeholder:`Search users`,label:`Search users`,onChange:L}):null]}),t.length===0?(0,Q.jsx)(`p`,{className:`border-t border-border/50 px-4 py-3 text-[11px] text-muted-foreground`,children:`No users on this plane.`}):z.length===0?(0,Q.jsx)(`p`,{className:`border-t border-border/50 px-4 py-3 text-[11px] text-muted-foreground`,children:`No users match.`}):(0,Q.jsx)(`div`,{className:`max-h-56 overflow-y-auto`,children:z.map(e=>{let t=e.id===m;return(0,Q.jsxs)(`button`,{type:`button`,"data-slot":`access-creator-user`,"aria-pressed":t,className:o(A,t&&`bg-muted/70 text-foreground`),onClick:()=>h(e.id),children:[(0,Q.jsx)(`span`,{className:o(N,t&&`bg-sky-500`)}),(0,Q.jsx)(`span`,{className:`min-w-0 truncate`,children:e.name}),(0,Q.jsx)(`span`,{className:`ml-auto shrink-0 font-mono text-[10px] text-muted-foreground`,children:e.id})]},e.id)})})]}):null,(0,Q.jsx)(ot,{scopes:B,selected:g,empty:u===`user`&&m.length===0?`Select an issuer to see grantable scopes.`:u===`user`?`This user has no grants.`:`No grantable scopes on this plane.`,onChange:_}),s?(0,Q.jsx)(be,{slot:`access-create-error`,children:s}):null]}),(0,Q.jsxs)(C,{children:[(0,Q.jsx)(K,{split:!0,onClick:()=>c(!1),disabled:i,children:`Cancel`}),(0,Q.jsx)(K,{variant:`default`,disabled:!ne,"data-slot":`access-create-submit`,onClick:()=>{if(H===void 0)return;let e=Oe(v,Date.now(),b);l({plane:u,name:f.trim(),scopes:g,...u===`user`?{creatorUserId:m}:{},...e==null?{}:{expiresAt:e},...H==null?{}:{rateLimit:H},...S.length>0?{ipAllowlist:S}:{}})},children:i?`Creating…`:`Create`})]})]})})}function lt({open:e,keyRow:t,users:n,operators:r,operatorScopes:s,pending:c,error:l,now:u=Date.now(),onOpenChange:d,onSubmit:f}){let p=ke(t.expiresAt,u),[m,h]=(0,Y.useState)(t.name),[g,_]=(0,Y.useState)(t.scopes),[v,y]=(0,Y.useState)(p.choice),[b,x]=(0,Y.useState)(p.custom),[S,w]=(0,Y.useState)(t.ipAllowlist),T=Ie(t.rateLimit?.per??``),[ee,D]=(0,Y.useState)(t.rateLimit?String(t.rateLimit.max):``),[k,A]=(0,Y.useState)(T.count),[j,N]=(0,Y.useState)(T.unit);(0,Y.useEffect)(()=>{if(!e)return;let n=ke(t.expiresAt,u);h(t.name),_(t.scopes),y(n.choice),x(n.custom),w(t.ipAllowlist);let r=Ie(t.rateLimit?.per??``);D(t.rateLimit?String(t.rateLimit.max):``),A(r.count),N(r.unit)},[e,t.id]);let P=t.creatorId??``,I=(0,Y.useMemo)(()=>P.length===0?null:n.find(e=>e.id===P)??r.find(e=>e.id===P)??null,[P,r,n]),L=I?I.name.trim()||I.email.trim()||I.id:P||`Unknown`,R=(0,Y.useMemo)(()=>{let e=t.creatorScopes??[];return e.length>0?e:t.plane===`operator`?I&&I.scopes.length>0?I.scopes:s:I?.scopes??[]},[I,t.creatorScopes,t.plane,s]),z=Array.from(new Set([...R,...t.scopes])),B=De(b),V=Fe(ee,k,j),H=m.trim().length>0&&g.length>0&&!c&&V!==void 0&&(v!==`custom`||B>0);return(0,Q.jsx)(E,{open:e,modal:!1,disablePointerDismissal:!0,onOpenChange:d,children:(0,Q.jsxs)(M,{side:`right`,showOverlay:!1,className:`gap-0 p-0 data-[side=right]:sm:max-w-md`,"data-slot":`access-edit-sheet`,children:[(0,Q.jsxs)(O,{className:`gap-1 border-b border-border/50`,children:[(0,Q.jsx)(te,{className:`text-sm`,children:`Edit key`}),(0,Q.jsx)(F,{className:`text-[11px]`,children:`Change name, expiry, allow, rate, and scopes. Issuer stays frozen.`})]}),(0,Q.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto`,children:[(0,Q.jsxs)(`div`,{className:`flex items-stretch border-b border-border/50`,"data-slot":`access-name-field`,children:[(0,Q.jsx)(`p`,{className:`flex h-8 w-[5.5rem] shrink-0 items-center px-4 text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`Name`}),(0,Q.jsx)(a,{value:m,onChange:e=>h(e.target.value),placeholder:`CI deploy`,autoComplete:`off`,"aria-label":`Key name`,flat:!0,className:o(q,`min-w-0 flex-1`)})]}),(0,Q.jsxs)(`div`,{className:`flex items-stretch border-b border-border/50`,"data-slot":`access-issuer-field`,children:[(0,Q.jsx)(`p`,{className:`flex h-8 w-[5.5rem] shrink-0 items-center px-4 text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`Issuer`}),(0,Q.jsxs)(`p`,{className:`flex min-w-0 flex-1 items-center gap-1.5 px-4 text-[12px] text-muted-foreground`,"aria-label":`Issuer ${L}`,children:[(0,Q.jsx)(i,{icon:t.plane===`operator`?Ce:fe,className:`size-3 shrink-0`,"aria-hidden":!0}),(0,Q.jsx)(`span`,{className:`min-w-0 truncate text-foreground`,children:L})]}),P.length>0&&P!==L?(0,Q.jsx)(`span`,{className:`flex h-8 shrink-0 items-center pr-4 font-mono text-[10px] text-muted-foreground`,children:P}):null]}),(0,Q.jsx)(it,{expires:v,customExpires:b,onExpires:y,onCustomExpires:x}),(0,Q.jsx)(rt,{entries:S,rateMax:ee,rateCount:k,rateUnit:j,onEntries:w,onRateMax:D,onRateCount:A,onRateUnit:N}),(0,Q.jsx)(ot,{scopes:z,selected:g,empty:t.plane===`user`&&I==null?`Issuer is gone. Only scopes already on this key remain.`:t.plane===`user`?`This issuer has no grants.`:`No grantable scopes on this plane.`,onChange:_}),l?(0,Q.jsx)(be,{slot:`access-edit-error`,children:l}):null]}),(0,Q.jsxs)(C,{children:[(0,Q.jsx)(K,{split:!0,onClick:()=>d(!1),disabled:c,children:`Cancel`}),(0,Q.jsx)(K,{variant:`default`,disabled:!H,"data-slot":`access-edit-submit`,onClick:()=>{V!==void 0&&f({name:m.trim(),scopes:g,expiresAt:Oe(v,Date.now(),b),rateLimit:V,ipAllowlist:S})},children:c?`Saving…`:`Save`})]})]})})}function ut({open:e,keyRow:t,pending:n,error:r,now:i=Date.now(),onOpenChange:a,onSubmit:o}){let s=je(t.expiresAt,i),[c,l]=(0,Y.useState)(s.choice),[u,d]=(0,Y.useState)(s.custom);(0,Y.useEffect)(()=>{if(!e)return;let n=je(t.expiresAt,i);l(n.choice),d(n.custom)},[e,t.id]);let f=De(u);return(0,Q.jsx)(E,{open:e,modal:!1,disablePointerDismissal:!0,onOpenChange:a,children:(0,Q.jsxs)(M,{side:`right`,showOverlay:!1,className:`gap-0 p-0 data-[side=right]:sm:max-w-md`,"data-slot":`access-refresh-sheet`,children:[(0,Q.jsxs)(O,{className:`gap-1 border-b border-border/50`,children:[(0,Q.jsx)(te,{className:`text-sm`,children:`Refresh expiry`}),(0,Q.jsx)(F,{className:`text-[11px]`,children:`Reset the deadline from now. The secret does not change.`})]}),(0,Q.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto`,children:[(0,Q.jsx)(it,{expires:c,customExpires:u,onExpires:l,onCustomExpires:d}),r?(0,Q.jsx)(be,{slot:`access-refresh-error`,children:r}):null]}),(0,Q.jsxs)(C,{children:[(0,Q.jsx)(K,{split:!0,onClick:()=>a(!1),disabled:n,children:`Cancel`}),(0,Q.jsx)(K,{variant:`default`,disabled:!(!n&&(c!==`custom`||f>0)),"data-slot":`access-refresh-submit`,onClick:()=>{o(Oe(c,Date.now(),u))},children:n?`Refreshing…`:`Refresh`})]})]})})}function dt({secret:e,title:t=`New API key`,onDismiss:n}){let[r,i]=(0,Y.useState)(!1);return(0,Q.jsx)(E,{open:e!==null,onOpenChange:e=>{e||n()},children:(0,Q.jsxs)(M,{side:`right`,showOverlay:!1,className:`gap-0 p-0 data-[side=right]:sm:max-w-md`,"data-slot":`access-secret-sheet`,children:[(0,Q.jsxs)(O,{className:`gap-1 border-b border-border/50`,children:[(0,Q.jsx)(te,{className:`text-sm`,children:t}),(0,Q.jsx)(F,{className:`text-[11px]`,children:`Shown once. Store it offline. This Console process does not keep it for you.`})]}),(0,Q.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto`,children:[(0,Q.jsx)(`p`,{className:`border-b border-border/50 px-4 py-3 font-mono text-[11px] break-all`,children:e}),(0,Q.jsx)(`p`,{className:`px-4 py-3 text-[11px] text-muted-foreground`,role:`status`,children:`Copying puts the secret on the clipboard. Anyone with this device can read it until you clear it.`})]}),(0,Q.jsxs)(C,{children:[(0,Q.jsx)(K,{split:!0,disabled:!e,onClick:()=>{e&&(navigator.clipboard?.writeText(e),i(!0))},children:r?`Copied`:`Copy (clipboard warning)`}),(0,Q.jsx)(K,{variant:`destructive`,onClick:()=>{i(!1),n()},children:`I have stored this key`})]})]})})}function ft(){let e=et(),t=ee(),{query:n,selectedKey:a,action:o,setQuery:s,setSelectedKey:c,setAction:l}=me(),m=ce(),[g]=(0,Y.useState)(()=>Date.now()),[_,x]=(0,Y.useState)(null),[S,C]=(0,Y.useState)(`New API key`),E=(0,Y.useMemo)(()=>{let t=e.data?.userPlane.keys??[],n=e.data?.operatorPlane.keys??[];return[...t,...n]},[e.data]),D=(0,Y.useMemo)(()=>{let e=n.trim().toLowerCase();return e?E.filter(t=>t.name.toLowerCase().includes(e)||t.id.toLowerCase().includes(e)||t.scopes.some(t=>t.toLowerCase().includes(e))):E},[E,n]),O=D.find(e=>e.id===a)??E.find(e=>e.id===a),k=y({queryKey:[`console.access.blast`,O?.id],queryFn:async()=>{if(!O)throw Error(`no key`);let e=await p(O.id);if(e.error||!e.data)throw Error(e.error?.message??`blast failed`);return e.data},enabled:O!==void 0});(0,Y.useEffect)(()=>{let e=e=>{if(e.key!==`/`||e.metaKey||e.ctrlKey||e.altKey)return;let t=e.target;if(t instanceof HTMLElement){let e=t.tagName;if(e===`INPUT`||e===`TEXTAREA`||t.isContentEditable)return}e.preventDefault(),document.querySelector(`[data-slot='access-search-input']`)?.focus()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]);let A=()=>{t.invalidateQueries({queryKey:$e})},j=W({mutationFn:f,onSuccess:e=>{if(e.error||!e.data)throw Error(e.error?v(e.error):`create failed`);C(`New API key`),x(e.data.secret),c(e.data.key.id),l(null),A()}}),M=W({mutationFn:e=>d({keyId:O.id,confirmation:e.confirmation,reason:e.reason}),onSuccess:e=>{if(e.error||!e.data)throw Error(e.error?v(e.error):`rotate failed`);C(`Rotated API key`),x(e.data.secret),l(null),A()}}),N=W({mutationFn:e=>u({keyId:O.id,confirmation:e.confirmation,reason:e.reason}),onSuccess:e=>{if(e.error||!e.data)throw Error(e.error?v(e.error):`revoke failed`);l(null),A()}}),P=W({mutationFn:h,onSuccess:e=>{if(e.error||!e.data)throw Error(e.error?v(e.error):`update failed`);l(null),A()}}),F=W({mutationFn:e=>h({keyId:O.id,expiresAt:e}),onSuccess:e=>{if(e.error||!e.data)throw Error(e.error?v(e.error):`refresh failed`);l(null),A()}}),I=(0,Q.jsx)(le,{open:m.open,onToggle:m.toggle,noun:`keys`,controlsId:`access-list`,dataSlot:`access-list-toggle`});return(0,Q.jsxs)(`div`,{className:T,"data-slot":`access-page`,children:[(0,Q.jsxs)(ie,{orientation:`horizontal`,className:`min-h-0 flex-1`,children:[(0,Q.jsx)(se,{panelRef:m.panelRef,collapsible:!0,collapsedSize:0,defaultSize:b.start.defaultSize,minSize:b.start.minSize,onResize:m.onResize,className:`min-h-0 overflow-hidden`,children:(0,Q.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col overflow-hidden`,children:[(0,Q.jsxs)(`div`,{className:r,children:[(0,Q.jsx)(ae,{"data-slot":`access-search-input`,placeholder:`Search keys`,"aria-label":`Search keys`,value:n,onChange:e=>s(e.target.value)}),(0,Q.jsx)(U,{label:`Create key`,className:`flex self-stretch`,children:(0,Q.jsx)(`button`,{type:`button`,className:w,"data-slot":`access-create`,"aria-label":`Create key`,onClick:()=>l(`create`),children:(0,Q.jsx)(i,{icon:pe,className:`size-3.5`})})})]}),(0,Q.jsx)(tt,{rows:D,selectedKey:a,query:n,loading:e.isLoading,onSelect:c})]})}),m.open?(0,Q.jsx)(ue,{withHandle:!0}):null,(0,Q.jsx)(se,{defaultSize:b.end.defaultSize,minSize:b.end.minSize,className:`min-h-0 overflow-hidden`,children:O?(0,Q.jsx)(Ge,{keyRow:O,blast:k.data,now:g,leading:I,onEdit:()=>l(`edit`),onRefresh:()=>l(`refresh`),onRevoke:()=>l(`revoke`),onRotate:()=>l(`rotate`),rotatePending:M.isPending}):(0,Q.jsx)(ge,{icon:de.gate.icon,iconClassName:`border-border/70`,title:e.isLoading?`Loading keys…`:E.length>0?`Select a key`:`No keys yet`,leading:I,description:e.isLoading?`Reading planes and grantable scopes.`:E.length>0&&n.trim().length>0?(0,Q.jsxs)(Q.Fragment,{children:[`Nothing matches `,(0,Q.jsx)(`span`,{className:`font-mono`,children:n}),`.`,` `,(0,Q.jsx)(`button`,{type:`button`,className:`underline underline-offset-2 hover:text-foreground`,onClick:()=>s(``),children:`Clear search`})]}):`Create one to mint a secret once.`})})]}),(0,Q.jsx)(ct,{open:o===`create`,users:e.data?.userPlane.users??[],userScopes:e.data?.userPlane.grantableScopes??[],operatorScopes:e.data?.operatorPlane.grantableScopes??[],pending:j.isPending,error:j.error instanceof Error?j.error.message:null,onOpenChange:e=>{e||l(null)},onSubmit:e=>j.mutate(e)}),O?(0,Q.jsx)(lt,{open:o===`edit`,keyRow:O,users:e.data?.userPlane.users??[],operators:e.data?.operatorPlane.operators??[],operatorScopes:e.data?.operatorPlane.grantableScopes??[],pending:P.isPending,error:P.error instanceof Error?P.error.message:null,onOpenChange:e=>{e||l(null)},onSubmit:e=>P.mutate({keyId:O.id,...e})}):null,O?(0,Q.jsx)(ut,{open:o===`refresh`,keyRow:O,pending:F.isPending,error:F.error instanceof Error?F.error.message:null,onOpenChange:e=>{e||l(null)},onSubmit:e=>F.mutate(e)}):null,O?(0,Q.jsx)(Se,{open:o===`revoke`,onOpenChange:e=>{e||l(null)},phrase:`REVOKE`,title:`Revoke ${O.name}`,description:`Irreversible. Residual sessions may continue for the access TTL.`,pending:N.isPending,error:N.error instanceof Error?N.error.message:null,confirmLabel:`Revoke key`,slot:`access-revoke-sheet`,onConfirm:e=>N.mutate({confirmation:`REVOKE`,reason:e.reason})}):null,O?(0,Q.jsx)(Se,{open:o===`rotate`,onOpenChange:e=>{e||l(null)},phrase:`ROTATE`,title:`Rotate ${O.name}`,description:`Mints a new secret once. The current secret stops after residual TTL.`,pending:M.isPending,error:M.error instanceof Error?M.error.message:null,confirmLabel:`Rotate key`,confirmVariant:`ghost`,slot:`access-rotate-sheet`,onConfirm:e=>M.mutate({confirmation:`ROTATE`,reason:e.reason})}):null,(0,Q.jsx)(dt,{secret:_,title:S,onDismiss:()=>x(null)})]})}export{ft as AccessPage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as e}from"./xyflow-yApv7D4e.js";import{Er as t}from"./shortcut-keys-3ILd8oGn.js";import{X as n,c as r,l as i}from"./index-
|
|
1
|
+
import{A as e}from"./xyflow-yApv7D4e.js";import{Er as t}from"./shortcut-keys-3ILd8oGn.js";import{X as n,c as r,l as i}from"./index-CBAP48v5.js";var a=e();function o({open:e,openHeight:o=`auto`,className:s,style:c,transition:l,...u}){let d=i()??!1;return(0,a.jsx)(r.div,{...u,"aria-hidden":!e,inert:!e||void 0,initial:!1,animate:d?{opacity:+!!e}:{opacity:+!!e,clipPath:e?`inset(0 0 0% 0)`:`inset(0 0 100% 0)`,y:e?0:-4},transition:l??{duration:d?0:e?.22:.14,ease:n},className:t(`overflow-hidden`,s),style:{...c,height:e?o:0,pointerEvents:e?void 0:`none`,transformOrigin:`top`}})}export{o as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as e,f as t}from"./xyflow-yApv7D4e.js";import{Dr as n,Er as r,F as i,I as a,R as o}from"./shortcut-keys-3ILd8oGn.js";import{C as s,S as c,b as l,g as u,h as d,n as f,x as p}from"./request-meta-
|
|
1
|
+
import{A as e,f as t}from"./xyflow-yApv7D4e.js";import{Dr as n,Er as r,F as i,I as a,R as o}from"./shortcut-keys-3ILd8oGn.js";import{C as s,S as c,b as l,g as u,h as d,n as f,x as p}from"./request-meta-CPkGDQgT.js";import{t as m}from"./dagre.esm-B1_XeuLP.js";function h(e){let t=e.indexOf(`.`);return t===-1?e:e.slice(0,t)}function g(e){let t=e.indexOf(`.`);return t===-1?e:e.slice(t+1)}function _(e){let t=e?.flows??{},n=new Map;for(let e of Object.keys(t)){let r=t[e]?.effects?.calls??[];for(let t of r){let r=n.get(t)??[];r.push(e),n.set(t,r)}}for(let[e,t]of n)t.sort((e,t)=>e.localeCompare(t)),n.set(e,t);return n}function v(e,t){return _(e).get(t)??[]}function y(e){return e.startsWith(`sql:`)?{id:e,kind:`store`,label:e.slice(4),facet:`sql`}:e.startsWith(`kv:`)?{id:e,kind:`store`,label:e.slice(3),facet:`kv`}:e.startsWith(`files:`)?{id:e,kind:`store`,label:e.slice(6),facet:`files`}:e.startsWith(`index:`)?{id:e,kind:`store`,label:e.slice(6),facet:`index`}:e.startsWith(`signal:`)?{id:e,kind:`signal`,label:e.slice(7)}:e.startsWith(`ai:`)?{id:e,kind:`ai`,label:e.slice(3)}:e.startsWith(`vault:`)?{id:e,kind:`vault`,label:e.slice(6)}:e.startsWith(`channel:`)?{id:e,kind:`channel`,label:e.slice(8)}:e.startsWith(`gate:`)?{id:e,kind:`gate`,label:e.slice(5)}:e.startsWith(`clock:`)?{id:e,kind:`clock`,label:e.slice(6)}:null}function b(e,n,r,i,a=!1){let o=d[i];return{id:e,source:n,target:r,type:`smoothstep`,animated:a,data:{kind:i},style:{stroke:o,strokeWidth:i===`calls`?2.5:2.25},pathOptions:{borderRadius:28},zIndex:u.edge,markerEnd:{type:t.ArrowClosed,width:14,height:14,color:o}}}function x(e){let t=e?.flows??{},n=new Set(Object.keys(t)),r=[],i=new Map;for(let e of[...n].sort()){let t=h(e),n=i.get(t)??[];n.push(e),i.set(t,n)}let a=new Map,o=new Map;for(let e of n){let n=t[e];if(!n)continue;if(n.trigger?.signal){let t=`signal:${n.trigger.signal}`,i=y(t);i&&a.set(t,i),r.push(b(`e:${t}->flow:${e}`,t,`flow:${e}`,`trigger`))}if(n.trigger?.cron||n.trigger?.every){let t=`clock:${e}`,i=n.trigger.cron??n.trigger.every??e;a.set(t,{id:t,kind:`clock`,label:i,facet:n.trigger.cron?`cron`:`every`}),r.push(b(`e:${t}->flow:${e}`,t,`flow:${e}`,`trigger`))}for(let t of n.gates??[]){let n=`gate:${t}`;a.set(n,{id:n,kind:`gate`,label:t}),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}-gates->${n}`,`flow:${e}`,n,`gates`))}let i=n.effects;if(i){for(let t of i.reads??[]){let n=y(t);n&&(a.set(t,n),o.set(t,(o.get(t)??0)+1),r.push(b(`e:flow:${e}-reads->${t}`,`flow:${e}`,t,`reads`)))}for(let t of i.writes??[]){let n=y(t);n&&(a.set(t,n),o.set(t,(o.get(t)??0)+1),r.push(b(`e:flow:${e}-writes->${t}`,`flow:${e}`,t,`writes`)))}for(let t of i.emits??[]){let n=`signal:${t}`,i=y(n);i&&(a.set(n,i),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}->${n}`,`flow:${e}`,n,`emits`)))}for(let t of i.asks??[]){let n=`ai:${t}`,i=y(n);i&&(a.set(n,i),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}->${n}`,`flow:${e}`,n,`asks`)))}for(let t of i.sends??[]){let n=`channel:${t}`,i=y(n);i&&(a.set(n,i),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}->${n}`,`flow:${e}`,n,`sends`)))}for(let t of i.secrets??[]){let n=`vault:${t}`,i=y(n);i&&(a.set(n,i),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}->${n}`,`flow:${e}`,n,`secrets`)))}for(let t of i.calls??[]){let n=s(t);if(n){let t=c(n.server);a.set(t,{id:t,kind:`ai`,label:n.server}),o.set(t,(o.get(t)??0)+1),r.push(b(`e:flow:${e}->${t}`,`flow:${e}`,t,`calls`,!0));continue}r.push(b(`e:flow:${e}->flow:${t}`,`flow:${e}`,`flow:${t}`,`calls`,!0))}}}return{nodes:S(i,t,a,o),edges:r,flowIds:n}}function S(e,t,n,r){let i=new m.graphlib.Graph({compound:!0});i.setGraph({rankdir:`LR`,align:`UL`,nodesep:16,ranksep:88,edgesep:12,marginx:8,marginy:8}),i.setDefaultEdgeLabel(()=>({}));for(let[t,n]of[...e.entries()].sort()){i.setNode(`unit:${t}`,{});for(let e of n)i.setNode(`flow:${e}`,{...l.flow}),i.setParent(`flow:${e}`,`unit:${t}`)}for(let e of n.values())i.setNode(e.id,{...l[e.kind]});let a=new Set;for(let n of e.values())for(let e of n){let n=t[e];if(!n)continue;let r=(e,t)=>{let n=`${e}->${t}`;a.has(n)||i.hasNode(e)&&i.hasNode(t)&&(a.add(n),i.setEdge(e,t))};n.trigger?.signal&&r(`signal:${n.trigger.signal}`,`flow:${e}`),(n.trigger?.cron||n.trigger?.every)&&r(`clock:${e}`,`flow:${e}`);for(let t of n.gates??[])r(`flow:${e}`,`gate:${t}`);let o=n.effects;if(o){for(let t of o.reads??[])r(`flow:${e}`,t);for(let t of o.writes??[])r(`flow:${e}`,t);for(let t of o.emits??[])r(`flow:${e}`,`signal:${t}`);for(let t of o.asks??[])r(`flow:${e}`,`ai:${t}`);for(let t of o.sends??[])r(`flow:${e}`,`channel:${t}`);for(let t of o.secrets??[])r(`flow:${e}`,`vault:${t}`);for(let t of o.calls??[]){let n=s(t);n?r(`flow:${e}`,c(n.server)):r(`flow:${e}`,`flow:${t}`)}}}m.layout(i);let o=[],{headerH:d,padX:f,padBottom:h}=p;for(let[n,r]of[...e.entries()].sort()){let e=`unit:${n}`,a=i.node(e);if(!a)continue;let s=a.x??0,c=a.y??0,p=r.length*l.flow.height+Math.max(0,r.length-1)*10,m=l.flow.width+f*2,_=d+p+h,v=s-m/2,y=c-_/2;o.push({id:e,type:`unit`,position:{x:v,y},data:{kind:`unit`,label:n,refId:e,badge:String(r.length)},selectable:!1,draggable:!1,zIndex:u.unit,width:m,height:_,style:{width:m,height:_}}),r.forEach((r,i)=>{let a=t[r];a&&o.push({id:`flow:${r}`,type:`flow`,position:{x:f,y:d+i*(l.flow.height+10)},parentId:e,extent:`parent`,zIndex:u.leaf,data:{kind:`flow`,label:g(r),refId:r,unit:n,plane:a.plane??`user`,badge:a.plane??`user`},draggable:!1,width:l.flow.width,height:l.flow.height,style:{width:l.flow.width,height:l.flow.height}})})}let _=[...n.values()].sort((e,t)=>e.kind.localeCompare(t.kind)||e.label.localeCompare(t.label));for(let e of _){let t=i.node(e.id),n=l[e.kind],a=r.get(e.id)??0;o.push({id:e.id,type:e.kind,position:{x:(t?.x??0)-n.width/2,y:(t?.y??0)-n.height/2},data:{kind:e.kind,label:e.label,refId:e.id,...e.facet===void 0?{}:{facet:e.facet},badge:e.facet??(a>0?String(a):e.kind)},draggable:!1,zIndex:u.leaf,width:n.width,height:n.height,style:{width:n.width,height:n.height}})}return o}function C(e,t,n,r={}){let i=t.size>0||n.size>0;return e.map(e=>{if(e.data.kind===`unit`||e.data.kind===`law`)return e;let a=e.data.kind===`flow`?t.has(e.data.refId):n.has(e.id);return{...e,data:{...e.data,highlighted:a,dimmed:i&&!a,active:r.activeNodeId!=null&&e.id===r.activeNodeId,focused:r.focusedNodeId!=null&&e.id===r.focusedNodeId}}})}function w(e,t){let n=new Map(t.map(e=>[e.id,e]));return t.some(e=>e.data.highlighted===!0)?e.map(e=>{let t=n.get(e.source),r=n.get(e.target),i=t?.data.highlighted===!0&&r?.data.highlighted===!0,a=d[e.data?.kind??`reads`];return{...e,animated:i?!0:e.animated,style:{...e.style,stroke:a,opacity:i?1:.32,strokeWidth:i?2.75:1.75},markerEnd:e.markerEnd&&typeof e.markerEnd==`object`?{...e.markerEnd,color:a}:e.markerEnd}}):e.map(e=>({...e,style:{...e.style,opacity:1}}))}var T=100;function E(e,t){return e.filter(e=>t.has(e.flow)).sort((e,t)=>t.startedAt-e.startedAt).slice(0,T)}var D=e();function O({cache:e,dataSlot:t}){let s=f(e);return(0,D.jsxs)(i,{children:[(0,D.jsx)(o,{render:i=>(0,D.jsx)(`span`,{...i,className:r(`flex w-4 shrink-0 items-center justify-center`,s.className),"data-slot":t,"data-cache":e,"aria-label":s.label,children:(0,D.jsx)(n,{icon:s.icon,className:`size-3`,"aria-hidden":!0})})}),(0,D.jsx)(a,{side:`top`,children:s.label})]})}export{w as a,h as c,C as i,E as n,x as o,g as r,v as s,O as t};
|