@docyrus/docyrus 0.0.4 → 0.0.5

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/main.js CHANGED
@@ -6,9 +6,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __esm = (fn, res) => function __init() {
10
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
- };
12
9
  var __commonJS = (cb, mod) => function __require() {
13
10
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
14
11
  };
@@ -14092,557 +14089,6 @@ var require_dist2 = __commonJS({
14092
14089
  }
14093
14090
  });
14094
14091
 
14095
- // src/tui/renderResult.tsx
14096
- function isRecord5(value) {
14097
- return typeof value === "object" && value !== null && !Array.isArray(value);
14098
- }
14099
- function formatValue(value) {
14100
- if (value === null) {
14101
- return "null";
14102
- }
14103
- if (Array.isArray(value)) {
14104
- return `[array:${value.length}]`;
14105
- }
14106
- if (typeof value === "object") {
14107
- return "[object]";
14108
- }
14109
- return String(value);
14110
- }
14111
- function renderArrayPreview(data, components) {
14112
- const { Box, Text } = components;
14113
- if (data.length === 0) {
14114
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "yellow", children: "Array is empty." });
14115
- }
14116
- const firstObject = data.find((item) => isRecord5(item));
14117
- const columns = firstObject ? Object.keys(firstObject).slice(0, 4) : [];
14118
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, { flexDirection: "column", children: [
14119
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
14120
- "Array items: ",
14121
- data.length
14122
- ] }),
14123
- columns.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
14124
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "cyan", children: columns.join(" | ") }),
14125
- data.slice(0, 20).map((item, index) => {
14126
- if (!isRecord5(item)) {
14127
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
14128
- index + 1,
14129
- ". ",
14130
- formatValue(item)
14131
- ] }, `row-${index}`);
14132
- }
14133
- const row = columns.map((column) => formatValue(item[column])).join(" | ");
14134
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
14135
- index + 1,
14136
- ". ",
14137
- row
14138
- ] }, `row-${index}`);
14139
- })
14140
- ] }),
14141
- columns.length === 0 && data.slice(0, 20).map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
14142
- index + 1,
14143
- ". ",
14144
- formatValue(item)
14145
- ] }, `value-${index}`)),
14146
- data.length > 20 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: "yellow", children: [
14147
- "... ",
14148
- data.length - 20,
14149
- " more rows omitted"
14150
- ] })
14151
- ] });
14152
- }
14153
- function renderObjectPreview(data, components) {
14154
- const { Box, Text } = components;
14155
- const keys = Object.keys(data);
14156
- const nestedLines = [];
14157
- for (const [key, value] of Object.entries(data)) {
14158
- if (!isRecord5(value) && !Array.isArray(value)) {
14159
- continue;
14160
- }
14161
- const serialized = JSON.stringify(value);
14162
- if (!serialized) {
14163
- continue;
14164
- }
14165
- const truncated = serialized.length > 120 ? `${serialized.slice(0, 120)}...` : serialized;
14166
- nestedLines.push(`${key}: ${truncated}`);
14167
- }
14168
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, { flexDirection: "column", children: [
14169
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
14170
- "Object keys: ",
14171
- keys.length
14172
- ] }),
14173
- keys.slice(0, 12).map((key) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [
14174
- key,
14175
- ": ",
14176
- formatValue(data[key])
14177
- ] }, key)),
14178
- keys.length > 12 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: "yellow", children: [
14179
- "... ",
14180
- keys.length - 12,
14181
- " more keys omitted"
14182
- ] }),
14183
- nestedLines.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
14184
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "cyan", children: "Nested preview" }),
14185
- nestedLines.slice(0, 5).map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: line }, `nested-${index}`))
14186
- ] })
14187
- ] });
14188
- }
14189
- function renderResult(params) {
14190
- const {
14191
- entry,
14192
- viewMode,
14193
- components
14194
- } = params;
14195
- const { Box, Text } = components;
14196
- if (!entry) {
14197
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "yellow", children: "No command executed yet." });
14198
- }
14199
- if (!entry.result.ok) {
14200
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, { flexDirection: "column", children: [
14201
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: "red", children: [
14202
- "Error: ",
14203
- entry.result.error?.message || "Command failed."
14204
- ] }),
14205
- entry.result.error?.details && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: entry.result.error.details })
14206
- ] });
14207
- }
14208
- if (viewMode === "json") {
14209
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: JSON.stringify(entry.result.data, null, 2) });
14210
- }
14211
- const payload = entry.result.data;
14212
- if (Array.isArray(payload)) {
14213
- return renderArrayPreview(payload, components);
14214
- }
14215
- if (isRecord5(payload)) {
14216
- return renderObjectPreview(payload, components);
14217
- }
14218
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: formatValue(payload) });
14219
- }
14220
- var import_jsx_runtime;
14221
- var init_renderResult = __esm({
14222
- "src/tui/renderResult.tsx"() {
14223
- "use strict";
14224
- import_jsx_runtime = require("react/jsx-runtime");
14225
- }
14226
- });
14227
-
14228
- // src/tui/useCommandInput.ts
14229
- function parseCommandLine(command) {
14230
- const args = [];
14231
- let current = "";
14232
- let quote = null;
14233
- let escaped = false;
14234
- for (const char of command) {
14235
- if (escaped) {
14236
- current += char;
14237
- escaped = false;
14238
- continue;
14239
- }
14240
- if (char === "\\") {
14241
- escaped = true;
14242
- continue;
14243
- }
14244
- if (quote) {
14245
- if (char === quote) {
14246
- quote = null;
14247
- } else {
14248
- current += char;
14249
- }
14250
- continue;
14251
- }
14252
- if (char === '"' || char === "'") {
14253
- quote = char;
14254
- continue;
14255
- }
14256
- if (/\s/.test(char)) {
14257
- if (current.length > 0) {
14258
- args.push(current);
14259
- current = "";
14260
- }
14261
- continue;
14262
- }
14263
- current += char;
14264
- }
14265
- if (quote) {
14266
- throw new Error("Invalid command syntax: unmatched quote.");
14267
- }
14268
- if (escaped) {
14269
- current += "\\";
14270
- }
14271
- if (current.length > 0) {
14272
- args.push(current);
14273
- }
14274
- return args;
14275
- }
14276
- function useCommandInput(options) {
14277
- const [input, setInput] = (0, import_react.useState)("");
14278
- const [history, setHistory] = (0, import_react.useState)([]);
14279
- const [historyCursor, setHistoryCursor] = (0, import_react.useState)(null);
14280
- const [draftInput, setDraftInput] = (0, import_react.useState)("");
14281
- const recallHistory = (0, import_react.useCallback)((direction) => {
14282
- if (history.length === 0) {
14283
- return;
14284
- }
14285
- if (direction === "up") {
14286
- if (historyCursor === null) {
14287
- setDraftInput(input);
14288
- setHistoryCursor(0);
14289
- setInput(history[0] || "");
14290
- return;
14291
- }
14292
- const nextCursor2 = Math.min(historyCursor + 1, history.length - 1);
14293
- setHistoryCursor(nextCursor2);
14294
- setInput(history[nextCursor2] || "");
14295
- return;
14296
- }
14297
- if (historyCursor === null) {
14298
- return;
14299
- }
14300
- const nextCursor = historyCursor - 1;
14301
- if (nextCursor < 0) {
14302
- setHistoryCursor(null);
14303
- setInput(draftInput);
14304
- return;
14305
- }
14306
- setHistoryCursor(nextCursor);
14307
- setInput(history[nextCursor] || "");
14308
- }, [draftInput, history, historyCursor, input]);
14309
- const submitInput = (0, import_react.useCallback)(() => {
14310
- if (options.busy) {
14311
- return;
14312
- }
14313
- const trimmed = input.trim();
14314
- if (!trimmed) {
14315
- return;
14316
- }
14317
- setHistory((previous) => {
14318
- if (previous[0] === trimmed) {
14319
- return previous;
14320
- }
14321
- return [trimmed, ...previous];
14322
- });
14323
- setHistoryCursor(null);
14324
- setDraftInput("");
14325
- setInput("");
14326
- options.onSubmit(trimmed);
14327
- }, [input, options]);
14328
- options.useInputHook((value, key) => {
14329
- if (key.ctrl && value === "c") {
14330
- options.onQuit();
14331
- return;
14332
- }
14333
- if (value === "q" && input.length === 0) {
14334
- options.onQuit();
14335
- return;
14336
- }
14337
- if (key.ctrl && value === "l") {
14338
- options.onClear();
14339
- return;
14340
- }
14341
- if (key.tab) {
14342
- options.onToggleView();
14343
- return;
14344
- }
14345
- if (key.upArrow) {
14346
- recallHistory("up");
14347
- return;
14348
- }
14349
- if (key.downArrow) {
14350
- recallHistory("down");
14351
- return;
14352
- }
14353
- if (key.return) {
14354
- submitInput();
14355
- return;
14356
- }
14357
- if (options.busy) {
14358
- return;
14359
- }
14360
- if (input.length === 0 && value.length === 1 && /[1-6]/.test(value)) {
14361
- options.onShortcut(Number(value));
14362
- return;
14363
- }
14364
- if (key.backspace || key.delete) {
14365
- setInput((previous) => previous.slice(0, -1));
14366
- return;
14367
- }
14368
- if (!value || key.ctrl || key.meta) {
14369
- return;
14370
- }
14371
- setHistoryCursor(null);
14372
- setInput((previous) => previous + value);
14373
- });
14374
- return {
14375
- input,
14376
- setInput
14377
- };
14378
- }
14379
- var import_react;
14380
- var init_useCommandInput = __esm({
14381
- "src/tui/useCommandInput.ts"() {
14382
- "use strict";
14383
- import_react = require("react");
14384
- }
14385
- });
14386
-
14387
- // src/tui/DocyrusTuiApp.tsx
14388
- var DocyrusTuiApp_exports = {};
14389
- __export(DocyrusTuiApp_exports, {
14390
- createDocyrusTuiApp: () => createDocyrusTuiApp
14391
- });
14392
- function isRecord6(value) {
14393
- return typeof value === "object" && value !== null && !Array.isArray(value);
14394
- }
14395
- function extractMetadata(payload) {
14396
- if (!isRecord6(payload)) {
14397
- return {};
14398
- }
14399
- const environmentValue = payload.environment;
14400
- const contextValue = payload.context;
14401
- const environment = isRecord6(environmentValue) && typeof environmentValue.id === "string" && typeof environmentValue.name === "string" ? { id: environmentValue.id, name: environmentValue.name } : void 0;
14402
- if (contextValue === null) {
14403
- return {
14404
- environment,
14405
- context: null
14406
- };
14407
- }
14408
- const context = isRecord6(contextValue) && typeof contextValue.email === "string" && typeof contextValue.tenantDisplay === "string" ? {
14409
- email: contextValue.email,
14410
- tenantDisplay: contextValue.tenantDisplay
14411
- } : void 0;
14412
- return {
14413
- environment,
14414
- context
14415
- };
14416
- }
14417
- function createDocyrusTuiApp(inkRuntime) {
14418
- const {
14419
- Box,
14420
- Text,
14421
- useApp,
14422
- useInput
14423
- } = inkRuntime;
14424
- return function DocyrusTuiApp(props) {
14425
- const { exit } = useApp();
14426
- const [entries, setEntries] = (0, import_react2.useState)([]);
14427
- const [viewMode, setViewMode] = (0, import_react2.useState)("pretty");
14428
- const [isRunning, setIsRunning] = (0, import_react2.useState)(false);
14429
- const [environment, setEnvironment] = (0, import_react2.useState)();
14430
- const [context, setContext] = (0, import_react2.useState)(void 0);
14431
- const [systemMessages, setSystemMessages] = (0, import_react2.useState)([]);
14432
- const [spinnerFrame, setSpinnerFrame] = (0, import_react2.useState)(0);
14433
- const applyCommandResult = (0, import_react2.useCallback)((result, command) => {
14434
- const entry = {
14435
- id: `${Date.now()}-${Math.random().toString(16).slice(2)}`,
14436
- command,
14437
- result,
14438
- createdAt: Date.now()
14439
- };
14440
- setEntries((previous) => [entry, ...previous]);
14441
- const messageLines = result.messages || [];
14442
- if (messageLines.length > 0) {
14443
- setSystemMessages((previous) => [...previous, ...messageLines]);
14444
- }
14445
- if (result.ok && result.data !== void 0) {
14446
- const metadata = extractMetadata(result.data);
14447
- if (metadata.environment) {
14448
- setEnvironment(metadata.environment);
14449
- }
14450
- if (metadata.context !== void 0) {
14451
- setContext(metadata.context);
14452
- }
14453
- }
14454
- }, []);
14455
- const executeArgs = (0, import_react2.useCallback)(async (args, commandText) => {
14456
- setIsRunning(true);
14457
- try {
14458
- const result = await props.runCliCommand(args);
14459
- applyCommandResult(result, commandText);
14460
- } finally {
14461
- setIsRunning(false);
14462
- }
14463
- }, [applyCommandResult, props]);
14464
- const onSubmit = (0, import_react2.useCallback)((line) => {
14465
- let args;
14466
- try {
14467
- args = parseCommandLine(line);
14468
- } catch (error48) {
14469
- const message = error48 instanceof Error ? error48.message : "Invalid command syntax.";
14470
- applyCommandResult({
14471
- ok: false,
14472
- command: line.trim(),
14473
- rawOutput: "",
14474
- error: {
14475
- message
14476
- },
14477
- durationMs: 0
14478
- }, line.trim());
14479
- return;
14480
- }
14481
- if (args.length === 0) {
14482
- return;
14483
- }
14484
- void executeArgs(args, line.trim());
14485
- }, [applyCommandResult, executeArgs]);
14486
- const onShortcut = (0, import_react2.useCallback)((shortcut) => {
14487
- const action = SHORTCUTS[shortcut];
14488
- if (!action || isRunning) {
14489
- return;
14490
- }
14491
- if (action.run) {
14492
- void executeArgs(parseCommandLine(action.run), action.run);
14493
- }
14494
- }, [executeArgs, isRunning]);
14495
- const { input, setInput } = useCommandInput({
14496
- busy: isRunning,
14497
- useInputHook: useInput,
14498
- onSubmit,
14499
- onToggleView: () => {
14500
- setViewMode((previous) => previous === "pretty" ? "json" : "pretty");
14501
- },
14502
- onClear: () => {
14503
- setEntries([]);
14504
- setSystemMessages([]);
14505
- },
14506
- onQuit: () => {
14507
- exit();
14508
- },
14509
- onShortcut: (shortcut) => {
14510
- const action = SHORTCUTS[shortcut];
14511
- if (!action) {
14512
- return;
14513
- }
14514
- if (action.template) {
14515
- setInput(action.template);
14516
- return;
14517
- }
14518
- onShortcut(shortcut);
14519
- }
14520
- });
14521
- (0, import_react2.useEffect)(() => {
14522
- if (!isRunning) {
14523
- return;
14524
- }
14525
- const timer = setInterval(() => {
14526
- setSpinnerFrame((previous) => (previous + 1) % 4);
14527
- }, 120);
14528
- return () => {
14529
- clearInterval(timer);
14530
- };
14531
- }, [isRunning]);
14532
- (0, import_react2.useEffect)(() => {
14533
- void executeArgs([], "(root)");
14534
- }, [executeArgs]);
14535
- const spinner = (0, import_react2.useMemo)(() => ["|", "/", "-", "\\"][spinnerFrame] || "|", [spinnerFrame]);
14536
- const latestEntry = entries[0] || null;
14537
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box, { flexDirection: "column", children: [
14538
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box, { borderStyle: "round", paddingX: 1, children: [
14539
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: "cyan", children: [
14540
- "docyrus tui v",
14541
- props.version
14542
- ] }),
14543
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
14544
- " | env: ",
14545
- environment ? `${environment.name} (${environment.id})` : "unknown"
14546
- ] }),
14547
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
14548
- " | user: ",
14549
- context ? context.email : "not-authenticated"
14550
- ] }),
14551
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
14552
- " | tenant: ",
14553
- context ? context.tenantDisplay : "-"
14554
- ] })
14555
- ] }),
14556
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box, { marginTop: 1, flexDirection: "row", children: [
14557
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box, { width: 44, borderStyle: "round", paddingX: 1, flexDirection: "column", marginRight: 1, children: [
14558
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "green", children: "Shortcuts" }),
14559
- Object.entries(SHORTCUTS).map(([key, shortcut]) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
14560
- key,
14561
- ". ",
14562
- shortcut.label
14563
- ] }, `shortcut-${key}`)),
14564
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "green", children: "Keys" }),
14565
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: "Enter run, Up/Down history, Tab toggle view" }),
14566
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: "Ctrl+L clear, q/Ctrl+C quit" }),
14567
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: isRunning ? `${spinner} running...` : "idle" }),
14568
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "green", children: "System Messages" }),
14569
- systemMessages.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "gray", children: "none" }),
14570
- systemMessages.slice(-6).map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: line }, `message-${index}`))
14571
- ] }),
14572
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box, { flexGrow: 1, flexDirection: "column", children: [
14573
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box, { borderStyle: "round", paddingX: 1, flexDirection: "column", minHeight: 10, children: [
14574
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "green", children: "Command History (latest first)" }),
14575
- entries.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "gray", children: "No commands yet." }),
14576
- entries.slice(0, 10).map((entry) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
14577
- entry.result.ok ? "OK" : "ERR",
14578
- " ",
14579
- entry.command || "(root)",
14580
- " [",
14581
- entry.result.durationMs,
14582
- "ms]"
14583
- ] }, entry.id))
14584
- ] }),
14585
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box, { borderStyle: "round", paddingX: 1, flexDirection: "column", marginTop: 1, minHeight: 10, children: [
14586
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: "green", children: [
14587
- "Result (",
14588
- viewMode,
14589
- ")"
14590
- ] }),
14591
- renderResult({
14592
- entry: latestEntry,
14593
- viewMode,
14594
- components: {
14595
- Box,
14596
- Text
14597
- }
14598
- })
14599
- ] })
14600
- ] })
14601
- ] }),
14602
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box, { marginTop: 1, borderStyle: "round", paddingX: 1, children: [
14603
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "cyan", children: "> " }),
14604
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: input })
14605
- ] })
14606
- ] });
14607
- };
14608
- }
14609
- var import_react2, import_jsx_runtime2, SHORTCUTS;
14610
- var init_DocyrusTuiApp = __esm({
14611
- "src/tui/DocyrusTuiApp.tsx"() {
14612
- "use strict";
14613
- import_react2 = require("react");
14614
- init_renderResult();
14615
- init_useCommandInput();
14616
- import_jsx_runtime2 = require("react/jsx-runtime");
14617
- SHORTCUTS = {
14618
- 1: {
14619
- run: "env list",
14620
- label: "env list"
14621
- },
14622
- 2: {
14623
- run: "auth who",
14624
- label: "auth who"
14625
- },
14626
- 3: {
14627
- run: "apps list",
14628
- label: "apps list"
14629
- },
14630
- 4: {
14631
- run: "discover namespaces",
14632
- label: "discover namespaces"
14633
- },
14634
- 5: {
14635
- template: "studio list-data-sources --appSlug ",
14636
- label: "insert: studio list-data-sources --appSlug "
14637
- },
14638
- 6: {
14639
- template: "ds list <appSlug> <dataSourceSlug>",
14640
- label: "insert: ds list <appSlug> <dataSourceSlug>"
14641
- }
14642
- };
14643
- }
14644
- });
14645
-
14646
14092
  // ../../node_modules/.pnpm/undici@7.22.0/node_modules/undici/lib/core/symbols.js
14647
14093
  var require_symbols = __commonJS({
14648
14094
  "../../node_modules/.pnpm/undici@7.22.0/node_modules/undici/lib/core/symbols.js"(exports2, module2) {
@@ -31575,10 +31021,10 @@ var require_headers = __commonJS({
31575
31021
  const lowercaseName = isLowerCase ? name : name.toLowerCase();
31576
31022
  const exists = this.headersMap.get(lowercaseName);
31577
31023
  if (exists) {
31578
- const delimiter2 = lowercaseName === "cookie" ? "; " : ", ";
31024
+ const delimiter = lowercaseName === "cookie" ? "; " : ", ";
31579
31025
  this.headersMap.set(lowercaseName, {
31580
31026
  name: exists.name,
31581
- value: `${exists.value}${delimiter2}${value}`
31027
+ value: `${exists.value}${delimiter}${value}`
31582
31028
  });
31583
31029
  } else {
31584
31030
  this.headersMap.set(lowercaseName, { name, value });
@@ -39920,8 +39366,8 @@ function emoji() {
39920
39366
  }
39921
39367
  var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
39922
39368
  var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
39923
- var mac = (delimiter2) => {
39924
- const escapedDelim = escapeRegex(delimiter2 ?? ":");
39369
+ var mac = (delimiter) => {
39370
+ const escapedDelim = escapeRegex(delimiter ?? ":");
39925
39371
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
39926
39372
  };
39927
39373
  var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
@@ -52262,7 +51708,7 @@ function isValidUnquotedKey(key) {
52262
51708
  function isIdentifierSegment(key) {
52263
51709
  return /^[A-Z_]\w*$/i.test(key);
52264
51710
  }
52265
- function isSafeUnquoted(value, delimiter2 = DEFAULT_DELIMITER) {
51711
+ function isSafeUnquoted(value, delimiter = DEFAULT_DELIMITER) {
52266
51712
  if (!value) return false;
52267
51713
  if (value !== value.trim()) return false;
52268
51714
  if (isBooleanOrNullLiteral(value) || isNumericLike(value)) return false;
@@ -52270,7 +51716,7 @@ function isSafeUnquoted(value, delimiter2 = DEFAULT_DELIMITER) {
52270
51716
  if (value.includes('"') || value.includes("\\")) return false;
52271
51717
  if (/[[\]{}]/.test(value)) return false;
52272
51718
  if (/[\n\r\t]/.test(value)) return false;
52273
- if (value.includes(delimiter2)) return false;
51719
+ if (value.includes(delimiter)) return false;
52274
51720
  if (value.startsWith(LIST_ITEM_MARKER)) return false;
52275
51721
  return true;
52276
51722
  }
@@ -52321,33 +51767,33 @@ function collectSingleKeyChain(startKey, startValue, maxDepth) {
52321
51767
  function buildFoldedKey(segments) {
52322
51768
  return segments.join(DOT);
52323
51769
  }
52324
- function encodePrimitive(value, delimiter2) {
51770
+ function encodePrimitive(value, delimiter) {
52325
51771
  if (value === null) return NULL_LITERAL;
52326
51772
  if (typeof value === "boolean") return String(value);
52327
51773
  if (typeof value === "number") return String(value);
52328
- return encodeStringLiteral(value, delimiter2);
51774
+ return encodeStringLiteral(value, delimiter);
52329
51775
  }
52330
- function encodeStringLiteral(value, delimiter2 = DEFAULT_DELIMITER) {
52331
- if (isSafeUnquoted(value, delimiter2)) return value;
51776
+ function encodeStringLiteral(value, delimiter = DEFAULT_DELIMITER) {
51777
+ if (isSafeUnquoted(value, delimiter)) return value;
52332
51778
  return `${DOUBLE_QUOTE}${escapeString(value)}${DOUBLE_QUOTE}`;
52333
51779
  }
52334
51780
  function encodeKey(key) {
52335
51781
  if (isValidUnquotedKey(key)) return key;
52336
51782
  return `${DOUBLE_QUOTE}${escapeString(key)}${DOUBLE_QUOTE}`;
52337
51783
  }
52338
- function encodeAndJoinPrimitives(values, delimiter2 = DEFAULT_DELIMITER) {
52339
- return values.map((v) => encodePrimitive(v, delimiter2)).join(delimiter2);
51784
+ function encodeAndJoinPrimitives(values, delimiter = DEFAULT_DELIMITER) {
51785
+ return values.map((v) => encodePrimitive(v, delimiter)).join(delimiter);
52340
51786
  }
52341
51787
  function formatHeader(length, options) {
52342
51788
  const key = options?.key;
52343
51789
  const fields = options?.fields;
52344
- const delimiter2 = options?.delimiter ?? COMMA;
51790
+ const delimiter = options?.delimiter ?? COMMA;
52345
51791
  let header = "";
52346
51792
  if (key) header += encodeKey(key);
52347
- header += `[${length}${delimiter2 !== DEFAULT_DELIMITER ? delimiter2 : ""}]`;
51793
+ header += `[${length}${delimiter !== DEFAULT_DELIMITER ? delimiter : ""}]`;
52348
51794
  if (fields) {
52349
51795
  const quotedFields = fields.map((f) => encodeKey(f));
52350
- header += `{${quotedFields.join(delimiter2)}}`;
51796
+ header += `{${quotedFields.join(delimiter)}}`;
52351
51797
  }
52352
51798
  header += ":";
52353
51799
  return header;
@@ -52440,12 +51886,12 @@ function* encodeArrayOfArraysAsListItemsLines(prefix, values, depth, options) {
52440
51886
  yield indentedListItem(depth + 1, arrayLine, options.indent);
52441
51887
  }
52442
51888
  }
52443
- function encodeInlineArrayLine(values, delimiter2, prefix) {
51889
+ function encodeInlineArrayLine(values, delimiter, prefix) {
52444
51890
  const header = formatHeader(values.length, {
52445
51891
  key: prefix,
52446
- delimiter: delimiter2
51892
+ delimiter
52447
51893
  });
52448
- const joinedValue = encodeAndJoinPrimitives(values, delimiter2);
51894
+ const joinedValue = encodeAndJoinPrimitives(values, delimiter);
52449
51895
  if (values.length === 0) return header;
52450
51896
  return `${header} ${joinedValue}`;
52451
51897
  }
@@ -64187,7 +63633,7 @@ function buildInputSchema(args, env, options) {
64187
63633
  // package.json
64188
63634
  var package_default = {
64189
63635
  name: "@docyrus/docyrus",
64190
- version: "0.0.4",
63636
+ version: "0.0.5",
64191
63637
  private: false,
64192
63638
  description: "Docyrus API CLI",
64193
63639
  main: "./main.js",
@@ -64195,13 +63641,14 @@ var package_default = {
64195
63641
  docyrus: "main.js"
64196
63642
  },
64197
63643
  dependencies: {
63644
+ "@opentui/core": "^0.1.85",
63645
+ "@opentui/react": "^0.1.85",
64198
63646
  incur: "^0.1.6",
64199
- ink: "^5.2.1",
64200
- react: "^18.3.1",
63647
+ react: "^19.1.1",
64201
63648
  undici: "^7.16.0"
64202
63649
  },
64203
63650
  devDependencies: {
64204
- "@types/react": "^18.3.28"
63651
+ "@types/react": "^19.1.13"
64205
63652
  },
64206
63653
  engines: {
64207
63654
  node: ">=22.19"
@@ -66518,83 +65965,103 @@ function createStudioCli(dependencies) {
66518
65965
  }
66519
65966
 
66520
65967
  // src/commands/tuiCommand.ts
65968
+ var import_node_child_process2 = require("node:child_process");
66521
65969
  var import_node_fs3 = require("node:fs");
66522
65970
  var import_node_path6 = require("node:path");
66523
- var import_node_module = require("node:module");
66524
- var import_node_url = require("node:url");
66525
- var dynamicImportModule = new Function("specifier", "return import(specifier);");
66526
- async function importRuntimeModule(specifier) {
66527
- try {
66528
- return await dynamicImportModule(specifier);
66529
- } catch (error48) {
66530
- const moduleError = error48;
66531
- if (moduleError?.code !== "ERR_MODULE_NOT_FOUND" && moduleError?.code !== "MODULE_NOT_FOUND") {
66532
- throw error48;
66533
- }
66534
- const runtimeRequire = (0, import_node_module.createRequire)(typeof __filename === "string" ? __filename : process.cwd());
66535
- const fallbackPaths = [
66536
- (0, import_node_path6.resolve)(process.cwd(), "apps/api-cli/node_modules"),
66537
- (0, import_node_path6.resolve)(__dirname, "../../../apps/api-cli/node_modules")
66538
- ];
66539
- const resolved = runtimeRequire.resolve(specifier, {
66540
- paths: fallbackPaths
66541
- });
66542
- return await dynamicImportModule((0, import_node_url.pathToFileURL)(resolved).href);
65971
+ function summarizeFailure(result) {
65972
+ const stderr = result.stderr?.toString().trim();
65973
+ if (stderr && stderr.length > 0) {
65974
+ return stderr;
66543
65975
  }
65976
+ if (typeof result.status === "number") {
65977
+ return `OpenTUI process exited with code ${result.status}.`;
65978
+ }
65979
+ if (result.signal) {
65980
+ return `OpenTUI process exited due to signal ${result.signal}.`;
65981
+ }
65982
+ return "OpenTUI process terminated unexpectedly.";
66544
65983
  }
66545
- function toErrorDetails(error48) {
66546
- if (error48 instanceof Error) {
66547
- return error48.message;
65984
+ function resolveCliScriptPath() {
65985
+ const argvScript = process.argv[1];
65986
+ if (argvScript && argvScript.trim().length > 0) {
65987
+ return (0, import_node_path6.isAbsolute)(argvScript) ? argvScript : (0, import_node_path6.resolve)(process.cwd(), argvScript);
66548
65988
  }
66549
- return String(error48);
65989
+ return __filename;
66550
65990
  }
66551
- function ensureRuntimeModulePaths() {
66552
- const fallbackPaths = [
66553
- (0, import_node_path6.resolve)(process.cwd(), "apps/api-cli/node_modules"),
66554
- (0, import_node_path6.resolve)(__dirname, "../../../apps/api-cli/node_modules")
66555
- ].filter((pathValue) => (0, import_node_fs3.existsSync)(pathValue));
66556
- if (fallbackPaths.length === 0) {
66557
- return;
65991
+ function resolveOpenTuiEntryPath(options = {}) {
65992
+ const cwd = options.cwd ?? process.cwd();
65993
+ const dirname6 = options.dirname ?? __dirname;
65994
+ const fileExists = options.existsSyncFn ?? import_node_fs3.existsSync;
65995
+ const candidates = [
65996
+ // Source/dev mode in monorepo. Prefer this first so Bun resolves deps via
65997
+ // apps/api-cli/node_modules in workspace runs (e.g. `pnpm docyrus tui`).
65998
+ (0, import_node_path6.resolve)(cwd, "apps/api-cli/src/tui/opentuiMain.tsx"),
65999
+ (0, import_node_path6.resolve)(dirname6, "../tui/opentuiMain.tsx"),
66000
+ // Dist mode (bundled command runtime)
66001
+ (0, import_node_path6.resolve)(dirname6, "tui.mjs"),
66002
+ (0, import_node_path6.resolve)(dirname6, "../tui.mjs"),
66003
+ (0, import_node_path6.resolve)(cwd, "dist/apps/api-cli/tui.mjs")
66004
+ ];
66005
+ const resolved = candidates.find((candidate) => fileExists(candidate));
66006
+ if (!resolved) {
66007
+ throw new UserInputError(
66008
+ `Unable to locate OpenTUI entry file. Checked: ${candidates.join(", ")}`
66009
+ );
66010
+ }
66011
+ return resolved;
66012
+ }
66013
+ function ensureBunAvailable(options = {}) {
66014
+ const spawnCommand = options.spawnSyncFn ?? import_node_child_process2.spawnSync;
66015
+ const result = spawnCommand("bun", ["--version"], {
66016
+ encoding: "utf8"
66017
+ });
66018
+ if (result.error || result.status !== 0) {
66019
+ throw new UserInputError(
66020
+ "Unable to start TUI because Bun is not available. Install Bun and retry: https://bun.sh",
66021
+ {
66022
+ cause: result.error
66023
+ }
66024
+ );
66025
+ }
66026
+ }
66027
+ function launchOpenTuiProcess(options) {
66028
+ const spawnCommand = options.spawnSyncFn ?? import_node_child_process2.spawnSync;
66029
+ const result = spawnCommand("bun", [options.entryPath], {
66030
+ stdio: ["inherit", "inherit", "pipe"],
66031
+ encoding: "utf8",
66032
+ env: options.env
66033
+ });
66034
+ if (result.error) {
66035
+ throw new UserInputError(
66036
+ `Unable to start OpenTUI process: ${result.error.message}`,
66037
+ {
66038
+ cause: result.error
66039
+ }
66040
+ );
66558
66041
  }
66559
- const existing = process.env.NODE_PATH ? process.env.NODE_PATH.split(import_node_path6.delimiter).filter((value) => value.length > 0) : [];
66560
- const merged = Array.from(/* @__PURE__ */ new Set([...fallbackPaths, ...existing]));
66561
- process.env.NODE_PATH = merged.join(import_node_path6.delimiter);
66562
- const initPathsValue = import_node_module.Module["_initPaths"];
66563
- if (typeof initPathsValue === "function") {
66564
- initPathsValue();
66042
+ if (result.status !== 0) {
66043
+ throw new UserInputError(
66044
+ `OpenTUI process failed: ${summarizeFailure(result)}`
66045
+ );
66565
66046
  }
66566
66047
  }
66567
66048
  function createTuiCli(dependencies) {
66568
66049
  return Cli_exports.create("tui", {
66569
- description: "Launch Docyrus TUI (Ink)",
66050
+ description: "Launch Docyrus TUI (OpenTUI, requires Bun)",
66570
66051
  env: EnvSchema,
66571
66052
  run: async () => {
66572
- try {
66573
- ensureRuntimeModulePaths();
66574
- const reactModule = await importRuntimeModule("react");
66575
- const inkModule = await importRuntimeModule("ink");
66576
- const { createDocyrusTuiApp: createDocyrusTuiApp2 } = await Promise.resolve().then(() => (init_DocyrusTuiApp(), DocyrusTuiApp_exports));
66577
- const reactLib = "default" in reactModule ? reactModule.default : reactModule;
66578
- const DocyrusTuiApp = createDocyrusTuiApp2({
66579
- render: inkModule.render,
66580
- Box: inkModule.Box,
66581
- Text: inkModule.Text,
66582
- useApp: inkModule.useApp,
66583
- useInput: inkModule.useInput
66584
- });
66585
- const app = inkModule.render(reactLib.createElement(DocyrusTuiApp, {
66586
- runCliCommand: dependencies.runCliCommand,
66587
- version: dependencies.version
66588
- }));
66589
- await app.waitUntilExit();
66590
- } catch (error48) {
66591
- throw new UserInputError(
66592
- `Unable to start TUI. Ensure 'ink' and 'react' are installed and compatible with your Node runtime. Cause: ${toErrorDetails(error48)}`,
66593
- {
66594
- cause: error48
66595
- }
66596
- );
66597
- }
66053
+ ensureBunAvailable();
66054
+ const entryPath = resolveOpenTuiEntryPath();
66055
+ const scriptPath = resolveCliScriptPath();
66056
+ launchOpenTuiProcess({
66057
+ entryPath,
66058
+ env: {
66059
+ ...process.env,
66060
+ DOCYRUS_TUI_VERSION: dependencies.version,
66061
+ DOCYRUS_TUI_EXECUTABLE: process.execPath,
66062
+ DOCYRUS_TUI_SCRIPT: scriptPath
66063
+ }
66064
+ });
66598
66065
  }
66599
66066
  });
66600
66067
  }
@@ -66778,7 +66245,7 @@ var ApiClient = class {
66778
66245
  };
66779
66246
 
66780
66247
  // src/services/authSession.ts
66781
- function isRecord7(value) {
66248
+ function isRecord5(value) {
66782
66249
  return typeof value === "object" && value !== null;
66783
66250
  }
66784
66251
  function extractRecordValue(record2, keys) {
@@ -67077,11 +66544,11 @@ var AuthSessionService = class {
67077
66544
  fetchFn: this.params.fetchFn
67078
66545
  });
67079
66546
  const payload = response.data;
67080
- const dataCandidate = isRecord7(payload) && isRecord7(payload.data) ? payload.data : payload;
67081
- if (!isRecord7(dataCandidate)) {
66547
+ const dataCandidate = isRecord5(payload) && isRecord5(payload.data) ? payload.data : payload;
66548
+ if (!isRecord5(dataCandidate)) {
67082
66549
  throw new AuthSessionError("Unable to parse /users/me response.");
67083
66550
  }
67084
- const tenantCandidate = isRecord7(dataCandidate.tenant) ? dataCandidate.tenant : void 0;
66551
+ const tenantCandidate = isRecord5(dataCandidate.tenant) ? dataCandidate.tenant : void 0;
67085
66552
  const userId = extractString2(dataCandidate, ["id", "user_id"]);
67086
66553
  const email3 = extractString2(dataCandidate, ["email"]);
67087
66554
  const tenantId = tenantCandidate ? extractString2(tenantCandidate, ["id"]) : extractString2(dataCandidate, ["tenant_id", "tenantId"]);
@@ -67107,13 +66574,13 @@ var AuthSessionService = class {
67107
66574
  fetchFn: this.params.fetchFn
67108
66575
  });
67109
66576
  const payload = response.data;
67110
- const listCandidate = Array.isArray(payload) ? payload : isRecord7(payload) && Array.isArray(payload.data) ? payload.data : null;
66577
+ const listCandidate = Array.isArray(payload) ? payload : isRecord5(payload) && Array.isArray(payload.data) ? payload.data : null;
67111
66578
  if (!listCandidate) {
67112
66579
  throw new AuthSessionError("Unable to parse tenant catalog response.");
67113
66580
  }
67114
66581
  const mapped = [];
67115
66582
  for (const item of listCandidate) {
67116
- if (!isRecord7(item)) {
66583
+ if (!isRecord5(item)) {
67117
66584
  continue;
67118
66585
  }
67119
66586
  const tenantId = extractString2(item, ["id", "tenant_id"]);
@@ -67826,90 +67293,6 @@ var TenantOpenApiService = class {
67826
67293
  }
67827
67294
  };
67828
67295
 
67829
- // src/services/tuiRunner.ts
67830
- function sanitizeCommandArgs(args) {
67831
- const cleaned = args.map((arg) => arg.trim()).filter((arg) => arg.length > 0);
67832
- const normalized = cleaned[0] === "docyrus" ? cleaned.slice(1) : cleaned;
67833
- const withoutJson = normalized.filter((arg) => arg !== "--json");
67834
- const firstArg = withoutJson[0];
67835
- if (firstArg === "tui" || firstArg === "interactive") {
67836
- throw new UserInputError("Already in TUI session.");
67837
- }
67838
- return withoutJson;
67839
- }
67840
- function parseJsonOutput(rawOutput) {
67841
- const trimmedOutput = rawOutput.trim();
67842
- if (!trimmedOutput) {
67843
- throw new UserInputError("Command produced no output.");
67844
- }
67845
- const lines = trimmedOutput.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
67846
- const candidates = [
67847
- lines.at(-1),
67848
- trimmedOutput
67849
- ].filter((candidate) => Boolean(candidate));
67850
- let lastParseError;
67851
- for (const candidate of candidates) {
67852
- try {
67853
- return JSON.parse(candidate);
67854
- } catch (error48) {
67855
- lastParseError = error48;
67856
- }
67857
- }
67858
- throw new UserInputError("Invalid command output format. Expected JSON output.", {
67859
- cause: lastParseError,
67860
- rawOutput: trimmedOutput
67861
- });
67862
- }
67863
- function createTuiRunner(options) {
67864
- const runCliCommand = async (args) => {
67865
- const startedAt = Date.now();
67866
- const messages = [];
67867
- let rawOutput = "";
67868
- let commandArgs = [];
67869
- let commandLabel = "";
67870
- try {
67871
- commandArgs = sanitizeCommandArgs(args);
67872
- commandLabel = commandArgs.join(" ").trim();
67873
- const cli2 = options.createExecutorCli((line) => {
67874
- messages.push(line);
67875
- });
67876
- await cli2.serve([...commandArgs, "--json"], {
67877
- stdout: (output) => {
67878
- rawOutput += output;
67879
- },
67880
- exit: () => {
67881
- }
67882
- });
67883
- const data = parseJsonOutput(rawOutput);
67884
- return {
67885
- ok: true,
67886
- command: commandLabel,
67887
- rawOutput: rawOutput.trim(),
67888
- data,
67889
- durationMs: Date.now() - startedAt,
67890
- messages: messages.length > 0 ? messages : void 0
67891
- };
67892
- } catch (error48) {
67893
- const message = error48 instanceof Error ? error48.message : "Failed to execute command.";
67894
- const details = rawOutput.trim() || void 0;
67895
- return {
67896
- ok: false,
67897
- command: commandLabel,
67898
- rawOutput: rawOutput.trim(),
67899
- error: {
67900
- message,
67901
- details
67902
- },
67903
- durationMs: Date.now() - startedAt,
67904
- messages: messages.length > 0 ? messages : void 0
67905
- };
67906
- }
67907
- };
67908
- return {
67909
- runCliCommand
67910
- };
67911
- }
67912
-
67913
67296
  // src/main.ts
67914
67297
  var ROOT_HELP_COMMANDS = [
67915
67298
  { command: "env", description: "Show active environment and list environments" },
@@ -67926,7 +67309,7 @@ var ROOT_HELP_COMMANDS = [
67926
67309
  { command: "ds list <appSlug> <dataSourceSlug>", description: "List data source items" },
67927
67310
  { command: "apps list", description: "List apps" },
67928
67311
  { command: "studio list-data-sources --appSlug <slug>", description: "List studio data sources" },
67929
- { command: "tui", description: "Launch interactive terminal UI" },
67312
+ { command: "tui", description: "Launch terminal UI (OpenTUI, requires Bun)" },
67930
67313
  { command: "curl <path>", description: "Send arbitrary API requests" }
67931
67314
  ];
67932
67315
  function createDocyrusCli(params) {
@@ -68002,18 +67385,7 @@ function createDocyrusCli(params) {
68002
67385
  authStore
68003
67386
  }));
68004
67387
  if (includeTui) {
68005
- const tuiRunner = createTuiRunner({
68006
- createExecutorCli: (onMessage) => createDocyrusCli({
68007
- fetchFn: params?.fetchFn,
68008
- authStore,
68009
- environmentConfigService,
68010
- now: params?.now,
68011
- includeTui: false,
68012
- onAuthMessage: onMessage
68013
- })
68014
- });
68015
67388
  cli2.command(createTuiCli({
68016
- runCliCommand: tuiRunner.runCliCommand,
68017
67389
  version: package_default.version
68018
67390
  }));
68019
67391
  }