toolcraft-openapi 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/bin/generate.js +7 -0
  2. package/dist/define-client.js +2 -2
  3. package/dist/generate.js +2 -2
  4. package/dist/http.d.ts +21 -2
  5. package/dist/http.js +147 -22
  6. package/dist/index.d.ts +1 -1
  7. package/dist/lock.d.ts +1 -1
  8. package/dist/lock.js +109 -5
  9. package/dist/mock/fetch.js +1 -1
  10. package/dist/network-error.d.ts +2 -0
  11. package/dist/network-error.js +83 -0
  12. package/dist/spec-source.js +103 -3
  13. package/node_modules/@poe-code/design-system/dist/components/help-formatter-plain.d.ts +1 -0
  14. package/node_modules/@poe-code/design-system/dist/components/help-formatter-plain.js +1 -1
  15. package/node_modules/@poe-code/design-system/dist/components/text.d.ts +1 -0
  16. package/node_modules/@poe-code/design-system/dist/components/text.js +8 -0
  17. package/node_modules/@poe-code/design-system/dist/dashboard/buffer.js +8 -1
  18. package/node_modules/@poe-code/design-system/dist/dashboard/keymap.d.ts +5 -0
  19. package/node_modules/@poe-code/design-system/dist/dashboard/keymap.js +146 -12
  20. package/node_modules/@poe-code/design-system/dist/dashboard/terminal.js +31 -0
  21. package/node_modules/@poe-code/design-system/dist/dashboard/types.d.ts +1 -0
  22. package/node_modules/@poe-code/design-system/dist/explorer/actions.d.ts +16 -0
  23. package/node_modules/@poe-code/design-system/dist/explorer/actions.js +39 -0
  24. package/node_modules/@poe-code/design-system/dist/explorer/demo.d.ts +13 -0
  25. package/node_modules/@poe-code/design-system/dist/explorer/demo.js +297 -0
  26. package/node_modules/@poe-code/design-system/dist/explorer/events.d.ts +61 -0
  27. package/node_modules/@poe-code/design-system/dist/explorer/events.js +1 -0
  28. package/node_modules/@poe-code/design-system/dist/explorer/filter.d.ts +10 -0
  29. package/node_modules/@poe-code/design-system/dist/explorer/filter.js +95 -0
  30. package/node_modules/@poe-code/design-system/dist/explorer/index.d.ts +8 -0
  31. package/node_modules/@poe-code/design-system/dist/explorer/index.js +8 -0
  32. package/node_modules/@poe-code/design-system/dist/explorer/jobs.d.ts +7 -0
  33. package/node_modules/@poe-code/design-system/dist/explorer/jobs.js +59 -0
  34. package/node_modules/@poe-code/design-system/dist/explorer/keymap.d.ts +21 -0
  35. package/node_modules/@poe-code/design-system/dist/explorer/keymap.js +363 -0
  36. package/node_modules/@poe-code/design-system/dist/explorer/layout.d.ts +20 -0
  37. package/node_modules/@poe-code/design-system/dist/explorer/layout.js +73 -0
  38. package/node_modules/@poe-code/design-system/dist/explorer/reducer.d.ts +9 -0
  39. package/node_modules/@poe-code/design-system/dist/explorer/reducer.js +704 -0
  40. package/node_modules/@poe-code/design-system/dist/explorer/render/detail.d.ts +4 -0
  41. package/node_modules/@poe-code/design-system/dist/explorer/render/detail.js +96 -0
  42. package/node_modules/@poe-code/design-system/dist/explorer/render/footer.d.ts +4 -0
  43. package/node_modules/@poe-code/design-system/dist/explorer/render/footer.js +49 -0
  44. package/node_modules/@poe-code/design-system/dist/explorer/render/header.d.ts +4 -0
  45. package/node_modules/@poe-code/design-system/dist/explorer/render/header.js +56 -0
  46. package/node_modules/@poe-code/design-system/dist/explorer/render/index.d.ts +8 -0
  47. package/node_modules/@poe-code/design-system/dist/explorer/render/index.js +61 -0
  48. package/node_modules/@poe-code/design-system/dist/explorer/render/list.d.ts +4 -0
  49. package/node_modules/@poe-code/design-system/dist/explorer/render/list.js +106 -0
  50. package/node_modules/@poe-code/design-system/dist/explorer/render/modal.d.ts +3 -0
  51. package/node_modules/@poe-code/design-system/dist/explorer/render/modal.js +91 -0
  52. package/node_modules/@poe-code/design-system/dist/explorer/render/test-fixtures.d.ts +8 -0
  53. package/node_modules/@poe-code/design-system/dist/explorer/render/test-fixtures.js +156 -0
  54. package/node_modules/@poe-code/design-system/dist/explorer/runtime.d.ts +2 -0
  55. package/node_modules/@poe-code/design-system/dist/explorer/runtime.js +282 -0
  56. package/node_modules/@poe-code/design-system/dist/explorer/runtime.test-helpers.d.ts +50 -0
  57. package/node_modules/@poe-code/design-system/dist/explorer/runtime.test-helpers.js +101 -0
  58. package/node_modules/@poe-code/design-system/dist/explorer/state.d.ts +130 -0
  59. package/node_modules/@poe-code/design-system/dist/explorer/state.js +87 -0
  60. package/node_modules/@poe-code/design-system/dist/explorer/theme.d.ts +27 -0
  61. package/node_modules/@poe-code/design-system/dist/explorer/theme.js +97 -0
  62. package/node_modules/@poe-code/design-system/dist/index.d.ts +3 -0
  63. package/node_modules/@poe-code/design-system/dist/index.js +3 -0
  64. package/node_modules/@poe-code/design-system/package.json +1 -0
  65. package/package.json +2 -2
@@ -1,4 +1,5 @@
1
1
  import type { CommandInfo, FormatColumnsOptions, OptionInfo } from "./help-formatter.js";
2
+ export declare function stripAnsi(value: string): string;
2
3
  export declare function formatColumns(opts: FormatColumnsOptions): string;
3
4
  export declare function formatCommandList(commands: CommandInfo[]): string;
4
5
  export declare function formatOptionList(options: OptionInfo[]): string;
@@ -1,4 +1,4 @@
1
- function stripAnsi(value) {
1
+ export function stripAnsi(value) {
2
2
  let output = "";
3
3
  for (let index = 0; index < value.length; index += 1) {
4
4
  if (value[index] === "\u001b") {
@@ -10,6 +10,7 @@ export declare const text: {
10
10
  readonly usageCommand: (content: string) => string;
11
11
  readonly link: (content: string) => string;
12
12
  readonly muted: (content: string) => string;
13
+ readonly error: (content: string) => string;
13
14
  readonly badge: (content: string) => string;
14
15
  readonly selectLabel: (label: string, detail?: string) => string;
15
16
  };
@@ -91,6 +91,14 @@ export const text = {
91
91
  return `*${content}*`;
92
92
  return getTheme().muted(content);
93
93
  },
94
+ error(content) {
95
+ const format = resolveOutputFormat();
96
+ if (format === "json")
97
+ return content;
98
+ if (format === "markdown")
99
+ return `**${content}**`;
100
+ return getTheme().error(content);
101
+ },
94
102
  badge(content) {
95
103
  const format = resolveOutputFormat();
96
104
  if (format === "json")
@@ -126,6 +126,9 @@ export function cellToAnsi(cell) {
126
126
  if (style.dim) {
127
127
  painter = painter.dim;
128
128
  }
129
+ if (style.underline) {
130
+ painter = painter.underline;
131
+ }
129
132
  if (style.fg) {
130
133
  painter = applyForegroundColor(painter, style.fg);
131
134
  }
@@ -158,6 +161,9 @@ function normalizeStyle(style) {
158
161
  if (style?.dim !== undefined) {
159
162
  next.dim = style.dim;
160
163
  }
164
+ if (style?.underline !== undefined) {
165
+ next.underline = style.underline;
166
+ }
161
167
  return next;
162
168
  }
163
169
  function normalizeSize(value) {
@@ -168,7 +174,8 @@ function cellsEqual(left, right) {
168
174
  && left.style.fg === right.style.fg
169
175
  && left.style.bg === right.style.bg
170
176
  && left.style.bold === right.style.bold
171
- && left.style.dim === right.style.dim;
177
+ && left.style.dim === right.style.dim
178
+ && left.style.underline === right.style.underline;
172
179
  }
173
180
  function applyForegroundColor(instance, color) {
174
181
  if (color.startsWith("#")) {
@@ -1,3 +1,8 @@
1
1
  import type { KeypressEvent } from "./terminal.js";
2
2
  import type { Command } from "./types.js";
3
3
  export declare function createKeymap(overrides?: Partial<Record<Command, string[]>>): (event: KeypressEvent) => Command | undefined;
4
+ export declare function createKeymap<TCommand extends string>(overrides: Partial<Record<TCommand, string[]>> | undefined, options: {
5
+ commands: readonly TCommand[];
6
+ defaultBindings: Record<TCommand, readonly string[]>;
7
+ }): (event: KeypressEvent) => TCommand | undefined;
8
+ export declare function canonicalizeBinding(binding: string): string | undefined;
@@ -7,23 +7,78 @@ const defaultBindings = {
7
7
  retry: ["r"],
8
8
  "view-log": ["l"]
9
9
  };
10
- export function createKeymap(overrides) {
10
+ export function createKeymap(overrides, options) {
11
+ const resolvedCommands = options?.commands ?? commands;
12
+ const resolvedDefaults = options?.defaultBindings ?? defaultBindings;
11
13
  const bindings = new Map();
12
- for (const command of commands) {
13
- const keys = overrides?.[command] ?? defaultBindings[command];
14
- bindings.set(command, keys
14
+ const sequences = new Set();
15
+ let pendingSequence = "";
16
+ for (const command of resolvedCommands) {
17
+ const keys = overrides?.[command] ?? resolvedDefaults[command];
18
+ const commandBindings = keys
15
19
  .map(parseBinding)
16
- .filter((binding) => binding !== undefined));
20
+ .filter((binding) => binding !== undefined);
21
+ for (const binding of commandBindings) {
22
+ if (binding.sequence !== undefined) {
23
+ sequences.add(binding.sequence);
24
+ }
25
+ }
26
+ bindings.set(command, commandBindings);
17
27
  }
18
28
  return (event) => {
19
- for (const command of commands) {
29
+ for (const command of resolvedCommands) {
20
30
  const commandBindings = bindings.get(command);
21
- if (commandBindings?.some((binding) => matches(binding, event))) {
31
+ if (commandBindings?.some((binding) => matchesSingleKey(binding, event))) {
32
+ pendingSequence = "";
22
33
  return command;
23
34
  }
24
35
  }
36
+ const sequenceCommand = resolveSequence(event);
37
+ if (sequenceCommand !== undefined) {
38
+ return sequenceCommand;
39
+ }
25
40
  return undefined;
26
41
  };
42
+ function resolveSequence(event) {
43
+ const token = eventToSequenceToken(event);
44
+ if (token === undefined) {
45
+ pendingSequence = "";
46
+ return undefined;
47
+ }
48
+ pendingSequence = `${pendingSequence}${token}`;
49
+ for (const command of resolvedCommands) {
50
+ const commandBindings = bindings.get(command);
51
+ if (commandBindings?.some((binding) => binding.sequence === pendingSequence)) {
52
+ pendingSequence = "";
53
+ return command;
54
+ }
55
+ }
56
+ if (hasSequencePrefix(sequences, pendingSequence)) {
57
+ return undefined;
58
+ }
59
+ pendingSequence = token;
60
+ if (hasSequencePrefix(sequences, pendingSequence)) {
61
+ return undefined;
62
+ }
63
+ pendingSequence = "";
64
+ return undefined;
65
+ }
66
+ }
67
+ export function canonicalizeBinding(binding) {
68
+ const parsed = parseBinding(binding);
69
+ if (parsed === undefined) {
70
+ return undefined;
71
+ }
72
+ const modifiers = [
73
+ parsed.ctrl ? "ctrl" : undefined,
74
+ parsed.meta ? "meta" : undefined,
75
+ parsed.shift ? "shift" : undefined
76
+ ].filter((modifier) => modifier !== undefined);
77
+ const key = parsed.name ?? parsed.ch;
78
+ if (parsed.sequence !== undefined) {
79
+ return parsed.sequence.toLowerCase();
80
+ }
81
+ return key === undefined ? undefined : [...modifiers, key.toLowerCase()].join("+");
27
82
  }
28
83
  function parseBinding(binding) {
29
84
  const value = binding.trim();
@@ -56,25 +111,41 @@ function parseBinding(binding) {
56
111
  continue;
57
112
  }
58
113
  }
59
- if (parts.length === 1 && isShiftedCharacter(key)) {
114
+ const normalizedKey = normalizeKeyName(key);
115
+ if (parts.length === 1 && isShiftedCharacter(normalizedKey)) {
60
116
  shift = true;
61
117
  }
62
- if (key.length === 1) {
118
+ if (normalizedKey.length === 1) {
119
+ return {
120
+ ch: normalizeBindingCharacter(normalizedKey, shift),
121
+ ctrl,
122
+ meta,
123
+ shift
124
+ };
125
+ }
126
+ if (!ctrl &&
127
+ !meta &&
128
+ !shift &&
129
+ !isNamedKey(normalizedKey) &&
130
+ isPrintableSequence(normalizedKey)) {
63
131
  return {
64
- ch: normalizeBindingCharacter(key, shift),
132
+ sequence: normalizedKey,
65
133
  ctrl,
66
134
  meta,
67
135
  shift
68
136
  };
69
137
  }
70
138
  return {
71
- name: key.toLowerCase(),
139
+ name: normalizedKey.toLowerCase(),
72
140
  ctrl,
73
141
  meta,
74
142
  shift
75
143
  };
76
144
  }
77
- function matches(binding, event) {
145
+ function matchesSingleKey(binding, event) {
146
+ if (binding.sequence !== undefined) {
147
+ return false;
148
+ }
78
149
  if (binding.ctrl !== event.ctrl ||
79
150
  binding.meta !== event.meta ||
80
151
  binding.shift !== event.shift) {
@@ -88,6 +159,20 @@ function matches(binding, event) {
88
159
  }
89
160
  return false;
90
161
  }
162
+ function eventToSequenceToken(event) {
163
+ if (event.ctrl || event.meta || event.ch === undefined) {
164
+ return undefined;
165
+ }
166
+ return event.ch;
167
+ }
168
+ function hasSequencePrefix(sequences, prefix) {
169
+ for (const sequence of sequences) {
170
+ if (sequence.startsWith(prefix)) {
171
+ return true;
172
+ }
173
+ }
174
+ return false;
175
+ }
91
176
  function isShiftedCharacter(value) {
92
177
  return value.length === 1 && value.toLowerCase() !== value && value.toUpperCase() === value;
93
178
  }
@@ -97,3 +182,52 @@ function normalizeBindingCharacter(value, shift) {
97
182
  }
98
183
  return value.toUpperCase();
99
184
  }
185
+ function normalizeKeyName(value) {
186
+ if (value.toLowerCase() === "space") {
187
+ return " ";
188
+ }
189
+ if (value === "↑") {
190
+ return "up";
191
+ }
192
+ if (value === "↓") {
193
+ return "down";
194
+ }
195
+ if (value === "←") {
196
+ return "left";
197
+ }
198
+ if (value === "→") {
199
+ return "right";
200
+ }
201
+ return value;
202
+ }
203
+ function isNamedKey(value) {
204
+ return namedKeys.has(value.toLowerCase());
205
+ }
206
+ function isPrintableSequence(value) {
207
+ if (Array.from(value).length <= 1) {
208
+ return false;
209
+ }
210
+ for (const char of value) {
211
+ const codePoint = char.codePointAt(0);
212
+ if (codePoint === undefined || codePoint < 0x20 || codePoint === 0x7f) {
213
+ return false;
214
+ }
215
+ }
216
+ return true;
217
+ }
218
+ const namedKeys = new Set([
219
+ "backspace",
220
+ "delete",
221
+ "down",
222
+ "end",
223
+ "enter",
224
+ "escape",
225
+ "home",
226
+ "left",
227
+ "pagedown",
228
+ "pageup",
229
+ "return",
230
+ "right",
231
+ "tab",
232
+ "up"
233
+ ]);
@@ -185,6 +185,10 @@ export function parseKeypress(data) {
185
185
  return event;
186
186
  }
187
187
  function toKeypressEvent(str, key) {
188
+ const controlCharacter = controlCharacterToKeypress(key?.sequence);
189
+ if (controlCharacter !== undefined) {
190
+ return controlCharacter;
191
+ }
188
192
  const ctrl = key?.ctrl ?? false;
189
193
  const meta = key?.meta ?? false;
190
194
  const shift = key?.shift ?? false;
@@ -206,12 +210,22 @@ function extractPrintableCharacter(str, sequence) {
206
210
  if (isPrintableCharacter(str)) {
207
211
  return str;
208
212
  }
213
+ if (isSinglePrintableSequence(sequence)) {
214
+ return sequence;
215
+ }
209
216
  if (sequence === undefined || sequence.length <= 1 || sequence[0] !== "\u001b") {
210
217
  return undefined;
211
218
  }
212
219
  const candidate = sequence.slice(1);
213
220
  return isPrintableCharacter(candidate) ? candidate : undefined;
214
221
  }
222
+ function isSinglePrintableSequence(value) {
223
+ if (value === undefined || Array.from(value).length !== 1) {
224
+ return false;
225
+ }
226
+ const codePoint = value.codePointAt(0);
227
+ return codePoint !== undefined && codePoint >= 0x20 && codePoint !== 0x7f;
228
+ }
215
229
  function isPrintableCharacter(value) {
216
230
  if (value === undefined || Array.from(value).length !== 1) {
217
231
  return false;
@@ -219,6 +233,23 @@ function isPrintableCharacter(value) {
219
233
  const codePoint = value.codePointAt(0);
220
234
  return codePoint !== undefined && codePoint >= 0x20 && codePoint !== 0x7f;
221
235
  }
236
+ function controlCharacterToKeypress(sequence) {
237
+ if (sequence === "\u001f") {
238
+ return { ch: "/", ctrl: true, meta: false, shift: false };
239
+ }
240
+ if (sequence !== undefined && sequence.length === 1) {
241
+ const code = sequence.charCodeAt(0);
242
+ if (code >= 1 && code <= 26 && code !== 9 && code !== 10 && code !== 13) {
243
+ return {
244
+ name: String.fromCharCode(code + 96),
245
+ ctrl: true,
246
+ meta: false,
247
+ shift: false
248
+ };
249
+ }
250
+ }
251
+ return undefined;
252
+ }
222
253
  function cursorPositionAnsi(x, y) {
223
254
  return `\u001b[${normalizeCoordinate(y) + 1};${normalizeCoordinate(x) + 1}H`;
224
255
  }
@@ -23,6 +23,7 @@ export type CellStyle = {
23
23
  bg?: string;
24
24
  bold?: boolean;
25
25
  dim?: boolean;
26
+ underline?: boolean;
26
27
  };
27
28
  export type Cell = {
28
29
  ch: string;
@@ -0,0 +1,16 @@
1
+ import type { ExplorerEvent } from "./events.js";
2
+ import type { Action, ActionContext, ExplorerState, Row, Tone } from "./state.js";
3
+ export type ActionSource = "row" | "detail";
4
+ type ExplorerKeypressEvent = Extract<ExplorerEvent, {
5
+ type: "key";
6
+ }>["key"];
7
+ export type ActionRuntimeHandles = {
8
+ refresh: () => Promise<void>;
9
+ suspendAnd: <T>(fn: () => Promise<T>) => Promise<T>;
10
+ toast: (msg: string, tone?: Tone) => void;
11
+ confirm: (prompt: string) => Promise<boolean>;
12
+ exit: (after?: () => void | Promise<void>) => void;
13
+ };
14
+ export declare function resolveAction<R>(state: ExplorerState, keyEvent: ExplorerKeypressEvent): Action<R> | null;
15
+ export declare function buildActionContext<R>(state: ExplorerState, _action: Action<R>, source: ActionSource, runtimeHandles: ActionRuntimeHandles, rowsOverride?: Row[]): ActionContext<R>;
16
+ export {};
@@ -0,0 +1,39 @@
1
+ export function resolveAction(state, keyEvent) {
2
+ const target = state.bindings.resolve(keyEvent);
3
+ if (target?.type !== "action") {
4
+ return null;
5
+ }
6
+ const actionState = state.actionState.get(target.id);
7
+ if (actionState?.available !== true ||
8
+ actionState.running === true ||
9
+ actionState.action === undefined) {
10
+ return null;
11
+ }
12
+ return actionState.action;
13
+ }
14
+ export function buildActionContext(state, _action, source, runtimeHandles, rowsOverride) {
15
+ const row = rowsOverride?.[0] ?? currentRow(state) ?? { id: "", title: "" };
16
+ return {
17
+ row,
18
+ rows: rowsOverride ?? selectedRows(state, row),
19
+ item: source === "detail" ? currentDetailItem(state) : undefined,
20
+ filter: state.filter,
21
+ refresh: runtimeHandles.refresh,
22
+ suspendAnd: runtimeHandles.suspendAnd,
23
+ toast: runtimeHandles.toast,
24
+ confirm: runtimeHandles.confirm,
25
+ exit: runtimeHandles.exit
26
+ };
27
+ }
28
+ function currentRow(state) {
29
+ return state.rows[state.filtered[state.cursor] ?? -1];
30
+ }
31
+ function currentDetailItem(state) {
32
+ return state.detail.items?.[state.detail.cursor];
33
+ }
34
+ function selectedRows(state, fallback) {
35
+ if (state.selected.size === 0) {
36
+ return fallback.id === "" ? [] : [fallback];
37
+ }
38
+ return state.rows.filter((row) => state.selected.has(row.id));
39
+ }
@@ -0,0 +1,13 @@
1
+ import type { ExplorerConfig } from "./state.js";
2
+ type ExplorerDemoMode = "single-detail-mode" | "list-detail-mode";
3
+ export interface ExplorerDemoOptions {
4
+ mode: ExplorerDemoMode;
5
+ slowDetail: boolean;
6
+ }
7
+ export interface BuildExplorerDemoConfigOptions extends ExplorerDemoOptions {
8
+ onReorder?: (orderedIds: string[]) => void | Promise<void>;
9
+ }
10
+ export declare function parseExplorerDemoOptions(argv?: string[], env?: NodeJS.ProcessEnv): ExplorerDemoOptions;
11
+ export declare function buildExplorerDemoConfig(options: BuildExplorerDemoConfigOptions): ExplorerConfig<void>;
12
+ export declare function main(): Promise<void>;
13
+ export {};