@apicircle/shared 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +110 -0
- package/README.md +27 -0
- package/dist/index.cjs +547 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1245 -0
- package/dist/index.d.ts +1245 -0
- package/dist/index.js +487 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1245 @@
|
|
|
1
|
+
declare function generateId(): string;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pure validators shared between core and UI. Each returns a discriminated
|
|
5
|
+
* union so callers can branch cleanly: `.ok ? proceed : showError(reason)`.
|
|
6
|
+
*
|
|
7
|
+
* No throws — failures are explicit values. Validators never mutate input.
|
|
8
|
+
*
|
|
9
|
+
* Used by:
|
|
10
|
+
* - Inline UI feedback (`role="alert"` under inputs, disabled submit)
|
|
11
|
+
* - PreSendPanel + Send-time guards
|
|
12
|
+
* - Test fixtures that want to check shape without fabricating asserts
|
|
13
|
+
*/
|
|
14
|
+
type ValidationResult = {
|
|
15
|
+
ok: true;
|
|
16
|
+
} | {
|
|
17
|
+
ok: false;
|
|
18
|
+
reason: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Accepts any URL the browser can fetch + the variable-template form
|
|
22
|
+
* `{{NAME}}/path`. Empty + whitespace-only fail. Schemes other than
|
|
23
|
+
* http/https/file/{{...}} fail (mailto:/tel: aren't fetchable from
|
|
24
|
+
* Studio's executor).
|
|
25
|
+
*/
|
|
26
|
+
declare function validateUrl(value: string): ValidationResult;
|
|
27
|
+
declare function validateAwsRegion(value: string): ValidationResult;
|
|
28
|
+
/**
|
|
29
|
+
* Mock endpoint path pattern: must start with `/`, no whitespace, no
|
|
30
|
+
* query string (`?` is an error — query matching is a separate concern).
|
|
31
|
+
* Permits Express-style `:param` segments and `*` wildcards.
|
|
32
|
+
*/
|
|
33
|
+
declare function validateMockPath(value: string): ValidationResult;
|
|
34
|
+
/**
|
|
35
|
+
* Environment-variable key — the bit between `{{ }}` at resolve time.
|
|
36
|
+
* Allowed: ASCII letters, digits, underscore, hyphen. First character
|
|
37
|
+
* must be a letter or underscore (matches POSIX env-var naming).
|
|
38
|
+
*/
|
|
39
|
+
declare function validateEnvVarName(value: string): ValidationResult;
|
|
40
|
+
/**
|
|
41
|
+
* Plan name — same characters allowed as env-var names plus spaces, but
|
|
42
|
+
* must be non-empty after trim. Caller is responsible for uniqueness.
|
|
43
|
+
*/
|
|
44
|
+
declare function validatePlanName(value: string): ValidationResult;
|
|
45
|
+
/**
|
|
46
|
+
* GitHub PR title — non-empty after trim, ≤256 chars (GitHub's hard cap).
|
|
47
|
+
*/
|
|
48
|
+
declare function validatePRTitle(value: string): ValidationResult;
|
|
49
|
+
/**
|
|
50
|
+
* JSON validity — accepts only object/array roots (string/number/bool/null
|
|
51
|
+
* are technically valid JSON but rarely what users mean for headers/body
|
|
52
|
+
* payloads; we surface a clearer message).
|
|
53
|
+
*/
|
|
54
|
+
declare function validateJsonString(value: string, opts?: {
|
|
55
|
+
allowEmpty?: boolean;
|
|
56
|
+
allowRoots?: 'object' | 'array' | 'any';
|
|
57
|
+
}): ValidationResult;
|
|
58
|
+
declare function validateHttpHeaderName(value: string): ValidationResult;
|
|
59
|
+
/**
|
|
60
|
+
* JavaScript-compatible regular-expression body. Lets the user spot
|
|
61
|
+
* unclosed groups / bad character classes at edit time rather than at
|
|
62
|
+
* runtime where the rule silently never matches.
|
|
63
|
+
*/
|
|
64
|
+
declare function validateRegex(value: string, flags?: string): ValidationResult;
|
|
65
|
+
declare function validateJsonPath(value: string): ValidationResult;
|
|
66
|
+
/**
|
|
67
|
+
* Non-negative integer duration in milliseconds (or whatever unit the
|
|
68
|
+
* caller documents). 0 is allowed for "no wait"; negative values reject.
|
|
69
|
+
*/
|
|
70
|
+
declare function validatePositiveDuration(value: number | string): ValidationResult;
|
|
71
|
+
/**
|
|
72
|
+
* Returns the URL string if `value` is a syntactically valid URL whose scheme
|
|
73
|
+
* is `http:` or `https:` — otherwise `null`. Use this at every site that
|
|
74
|
+
* renders a third-party-supplied URL as `<a href>` or hands one to
|
|
75
|
+
* `window.open` / `shell.openExternal`. The OAuth2 device-flow
|
|
76
|
+
* `verification_uri` comes straight from the IdP and could in principle be
|
|
77
|
+
* `javascript:`, `data:`, `file:`, or a custom OS protocol handler —
|
|
78
|
+
* rendering any of those is an XSS / RCE foot-gun.
|
|
79
|
+
*
|
|
80
|
+
* `null` returns should be rendered as plain text so the user can still see
|
|
81
|
+
* and copy the value, but cannot one-click execute it.
|
|
82
|
+
*/
|
|
83
|
+
declare function safeExternalHref(value: unknown): string | null;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Human-readable byte size. UTF-8 byte count, base-1024 (KiB/MiB).
|
|
87
|
+
* 0 → "0 B", 1023 → "1023 B", 1024 → "1.0 KB", 1_500_000 → "1.4 MB".
|
|
88
|
+
*/
|
|
89
|
+
declare function formatBytes(bytes: number): string;
|
|
90
|
+
/** UTF-8 byte length of a string. Falls back to char length if TextEncoder unavailable. */
|
|
91
|
+
declare function utf8ByteLength(s: string): number;
|
|
92
|
+
|
|
93
|
+
type MockResponseBodyType = 'none' | 'json' | 'text' | 'xml' | 'urlencoded' | 'form-data' | 'binary';
|
|
94
|
+
type MockResponseBody = {
|
|
95
|
+
type: 'none';
|
|
96
|
+
content: '';
|
|
97
|
+
} | {
|
|
98
|
+
type: 'json';
|
|
99
|
+
content: string;
|
|
100
|
+
} | {
|
|
101
|
+
type: 'text';
|
|
102
|
+
content: string;
|
|
103
|
+
} | {
|
|
104
|
+
type: 'xml';
|
|
105
|
+
content: string;
|
|
106
|
+
} | {
|
|
107
|
+
type: 'urlencoded';
|
|
108
|
+
content: string;
|
|
109
|
+
} | {
|
|
110
|
+
type: 'form-data';
|
|
111
|
+
content: '';
|
|
112
|
+
formRows: Array<{
|
|
113
|
+
key: string;
|
|
114
|
+
value: string;
|
|
115
|
+
enabled: boolean;
|
|
116
|
+
}>;
|
|
117
|
+
} | {
|
|
118
|
+
type: 'binary';
|
|
119
|
+
content: '';
|
|
120
|
+
/** Attachment ref into Global Assets — same shape as request bodies. */
|
|
121
|
+
attachment?: AttachmentRef;
|
|
122
|
+
};
|
|
123
|
+
interface MockResponseConfig {
|
|
124
|
+
status: number;
|
|
125
|
+
headers: Array<{
|
|
126
|
+
key: string;
|
|
127
|
+
value: string;
|
|
128
|
+
enabled: boolean;
|
|
129
|
+
}>;
|
|
130
|
+
body: MockResponseBody;
|
|
131
|
+
/** Optional artificial latency before responding. */
|
|
132
|
+
delayMs?: number;
|
|
133
|
+
/**
|
|
134
|
+
* Optional response-shape multipliers. At runtime, each multiplier reads a
|
|
135
|
+
* value from the request (a query/path/header param or a JSON-path slice
|
|
136
|
+
* of the request body) and repeats the array element at `targetJsonPath`
|
|
137
|
+
* inside the response body that many times. Used to drive page-size
|
|
138
|
+
* aware mock responses without templating the body manually.
|
|
139
|
+
*
|
|
140
|
+
* Only fires when `body.type === 'json'`; ignored otherwise.
|
|
141
|
+
*/
|
|
142
|
+
multipliers?: MockResponseMultiplier[];
|
|
143
|
+
}
|
|
144
|
+
type MockMultiplierSourceKind = 'query' | 'pathParam' | 'header' | 'body-json-path';
|
|
145
|
+
interface MockMultiplierSource {
|
|
146
|
+
kind: MockMultiplierSourceKind;
|
|
147
|
+
/** Query/path/header name, or JSON path into the request body (e.g. "$.page.size"). */
|
|
148
|
+
key: string;
|
|
149
|
+
}
|
|
150
|
+
interface MockResponseMultiplier {
|
|
151
|
+
id: string;
|
|
152
|
+
/** Optional user-facing label. */
|
|
153
|
+
name?: string;
|
|
154
|
+
source: MockMultiplierSource;
|
|
155
|
+
/**
|
|
156
|
+
* JSON path into the *response body* pointing at the array to repeat
|
|
157
|
+
* (e.g. "$.items"). The first element of that array becomes the repeated
|
|
158
|
+
* template — additional elements are discarded.
|
|
159
|
+
*/
|
|
160
|
+
targetJsonPath: string;
|
|
161
|
+
/** Used when source is missing or non-numeric. */
|
|
162
|
+
defaultCount: number;
|
|
163
|
+
/** Optional inclusive lower bound on the resolved count. */
|
|
164
|
+
min?: number;
|
|
165
|
+
/** Optional inclusive upper bound on the resolved count. */
|
|
166
|
+
max?: number;
|
|
167
|
+
}
|
|
168
|
+
interface MockParamDef {
|
|
169
|
+
/** Stable id so the editor can reorder rows without losing focus. */
|
|
170
|
+
id: string;
|
|
171
|
+
name: string;
|
|
172
|
+
/** Free-form type hint (e.g. 'string', 'integer', 'uuid'). Documentation only. */
|
|
173
|
+
typeHint?: string;
|
|
174
|
+
required?: boolean;
|
|
175
|
+
description?: string;
|
|
176
|
+
example?: string;
|
|
177
|
+
}
|
|
178
|
+
interface MockRequestSchema {
|
|
179
|
+
/** Declared path params (auto-derived from `{slot}` segments in pathPattern + manual entries). */
|
|
180
|
+
pathParams: MockParamDef[];
|
|
181
|
+
queryParams: MockParamDef[];
|
|
182
|
+
headers: MockParamDef[];
|
|
183
|
+
cookies: MockParamDef[];
|
|
184
|
+
/** Optional documentation for the expected request body shape. */
|
|
185
|
+
body?: {
|
|
186
|
+
description?: string;
|
|
187
|
+
example?: string;
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
type MockValidationKind = 'header-required' | 'header-equals' | 'header-matches' | 'query-required' | 'query-equals' | 'query-matches' | 'cookie-required' | 'body-required' | 'content-type-equals';
|
|
191
|
+
interface MockValidationRule {
|
|
192
|
+
id: string;
|
|
193
|
+
kind: MockValidationKind;
|
|
194
|
+
/** Header / query / cookie name being validated (empty for body / content-type). */
|
|
195
|
+
target: string;
|
|
196
|
+
/** Expected literal or regex (when applicable). */
|
|
197
|
+
expected?: string;
|
|
198
|
+
/** Friendly message surfaced into the failResponse body / debugger. */
|
|
199
|
+
message?: string;
|
|
200
|
+
/**
|
|
201
|
+
* Disable without deleting — disabled rules are skipped during request
|
|
202
|
+
* validation but stay in the editor for what-if debugging. Defaults to
|
|
203
|
+
* `true` for newly authored rules.
|
|
204
|
+
*/
|
|
205
|
+
enabled: boolean;
|
|
206
|
+
/** Response returned when this rule fails. */
|
|
207
|
+
failResponse: MockResponseConfig;
|
|
208
|
+
}
|
|
209
|
+
type MockConditionScope = 'query' | 'pathParam' | 'header' | 'cookie' | 'body-json-path';
|
|
210
|
+
type MockConditionOp = 'equals' | 'not-equals' | 'matches' | 'gt' | 'lt' | 'gte' | 'lte' | 'present' | 'absent';
|
|
211
|
+
interface MockConditionClause {
|
|
212
|
+
id: string;
|
|
213
|
+
scope: MockConditionScope;
|
|
214
|
+
/** Name of the query/header/cookie/path-param OR a JSON-path for body matches. */
|
|
215
|
+
target: string;
|
|
216
|
+
op: MockConditionOp;
|
|
217
|
+
/** Comparison value (omitted for present/absent ops). */
|
|
218
|
+
value?: string;
|
|
219
|
+
}
|
|
220
|
+
interface MockResponseRule {
|
|
221
|
+
id: string;
|
|
222
|
+
/** User-facing rule label (e.g. "Page 1 — small response"). */
|
|
223
|
+
name: string;
|
|
224
|
+
/** Disable without deleting — useful for what-if testing. */
|
|
225
|
+
enabled: boolean;
|
|
226
|
+
/** AND-combined clauses; rule fires only when every clause matches. */
|
|
227
|
+
when: MockConditionClause[];
|
|
228
|
+
response: MockResponseConfig;
|
|
229
|
+
}
|
|
230
|
+
interface MockEndpoint {
|
|
231
|
+
/** Stable id; survives spec re-parses so per-endpoint overrides keep matching. */
|
|
232
|
+
id: string;
|
|
233
|
+
/** User-friendly label for the sidebar / picker. Defaults to "{METHOD} {pathPattern}". */
|
|
234
|
+
name: string;
|
|
235
|
+
method: HttpMethod;
|
|
236
|
+
/** OpenAPI-style path template, e.g. `/pets/{id}`. Hono routes get derived from this. */
|
|
237
|
+
pathPattern: string;
|
|
238
|
+
description?: string;
|
|
239
|
+
/** Declarative input schema — drives editor UI + runtime docs. */
|
|
240
|
+
requestSchema: MockRequestSchema;
|
|
241
|
+
/** Pre-validation gates evaluated before response rules. */
|
|
242
|
+
requestValidation: MockValidationRule[];
|
|
243
|
+
/** Conditional response rules (first match wins). */
|
|
244
|
+
responseRules: MockResponseRule[];
|
|
245
|
+
/** Fallback response when no rule matches. */
|
|
246
|
+
defaultResponse: MockResponseConfig;
|
|
247
|
+
/** Optional: name of the OpenAPI example chosen when multiple were present. */
|
|
248
|
+
example?: string;
|
|
249
|
+
}
|
|
250
|
+
type MockServerSource = {
|
|
251
|
+
kind: 'openapi';
|
|
252
|
+
spec: string;
|
|
253
|
+
format: 'json' | 'yaml';
|
|
254
|
+
} | {
|
|
255
|
+
kind: 'postman';
|
|
256
|
+
collection: string;
|
|
257
|
+
} | {
|
|
258
|
+
kind: 'insomnia';
|
|
259
|
+
export: string;
|
|
260
|
+
} | {
|
|
261
|
+
kind: 'manual';
|
|
262
|
+
endpoints: MockEndpoint[];
|
|
263
|
+
};
|
|
264
|
+
interface MockServer {
|
|
265
|
+
id: string;
|
|
266
|
+
name: string;
|
|
267
|
+
source: MockServerSource;
|
|
268
|
+
/**
|
|
269
|
+
* Resolved endpoint table — populated when the source is parsed; persisted
|
|
270
|
+
* so the desktop app doesn't re-parse on every start. Empty array for
|
|
271
|
+
* `kind: 'manual'` (the source carries the endpoints) — though in
|
|
272
|
+
* practice we mirror the manual endpoints into both fields so downstream
|
|
273
|
+
* consumers can read either one.
|
|
274
|
+
*/
|
|
275
|
+
endpoints: MockEndpoint[];
|
|
276
|
+
/** Default port used when starting; null = pick a free port at start. */
|
|
277
|
+
defaultPort: number | null;
|
|
278
|
+
cors: {
|
|
279
|
+
enabled: boolean;
|
|
280
|
+
origins: string[];
|
|
281
|
+
};
|
|
282
|
+
createdAt: string;
|
|
283
|
+
updatedAt: string;
|
|
284
|
+
}
|
|
285
|
+
/** Lives in WorkspaceLocal — never pushed to git. */
|
|
286
|
+
interface MockRuntime {
|
|
287
|
+
/** Keyed by mockServerId. Absent = not running. */
|
|
288
|
+
active: Record<string, MockRuntimeEntry>;
|
|
289
|
+
}
|
|
290
|
+
interface MockRuntimeEntry {
|
|
291
|
+
port: number;
|
|
292
|
+
/** null in browser-preview mode where there's no OS process. */
|
|
293
|
+
pid: number | null;
|
|
294
|
+
startedAt: string;
|
|
295
|
+
lastError: string | null;
|
|
296
|
+
requestCount: number;
|
|
297
|
+
}
|
|
298
|
+
declare function getAllowedMockResponseBodyTypes(status: number): MockResponseBodyType[];
|
|
299
|
+
/**
|
|
300
|
+
* If `currentBodyType` isn't allowed for `status`, return a safe
|
|
301
|
+
* fallback (`'json'` for status codes that allow bodies, `'none'`
|
|
302
|
+
* otherwise). Returns `null` when the current type is already
|
|
303
|
+
* allowed — caller can early-return.
|
|
304
|
+
*/
|
|
305
|
+
declare function coerceMockResponseBodyTypeForStatus(currentBodyType: MockResponseBodyType, status: number): MockResponseBodyType | null;
|
|
306
|
+
declare function makeDefaultMockResponseBody(type: MockResponseBodyType): MockResponseBody;
|
|
307
|
+
declare function makeDefaultMockResponse(): MockResponseConfig;
|
|
308
|
+
declare function makeDefaultRequestSchema(): MockRequestSchema;
|
|
309
|
+
|
|
310
|
+
type ThemeId = 'studio-dark' | 'graphite-dark' | 'midnight-blue' | 'workbench-light' | 'paper-light' | 'high-contrast-dark' | 'high-contrast-light' | 'dracula' | 'nord' | 'tokyo-night' | 'one-dark-pro' | 'monokai-pro' | 'gruvbox-dark' | 'solarized-dark' | 'catppuccin-mocha' | 'catppuccin-macchiato' | 'synthwave-84' | 'cobalt2' | 'rose-pine' | 'ayu-mirage' | 'night-owl' | 'github-dark' | 'material-palenight' | 'solarized-light' | 'github-light' | 'catppuccin-latte' | 'ayu-light' | 'atom-one-light' | 'rose-pine-dawn' | 'tokyo-night-day';
|
|
311
|
+
type FontFamilyId = 'system-mono' | 'jetbrains-mono' | 'fira-code' | 'cascadia-code' | 'ibm-plex-mono' | 'source-code-pro' | 'roboto-mono' | 'space-mono' | 'hack' | 'inconsolata' | 'anonymous-pro' | 'ubuntu-mono' | 'dm-mono' | 'geist-mono' | 'red-hat-mono' | 'azeret-mono' | 'victor-mono' | 'system-sans' | 'inter' | 'roboto' | 'open-sans' | 'lato' | 'source-sans-3' | 'nunito-sans' | 'manrope' | 'dm-sans' | 'geist' | 'plus-jakarta-sans' | 'ibm-plex-sans' | 'work-sans';
|
|
312
|
+
type PanelId = 'workspace' | 'link-workspace' | 'editor' | 'env' | 'execution' | 'history' | 'mocks' | 'mcp' | 'help';
|
|
313
|
+
/**
|
|
314
|
+
* Display name used when seeding a fresh workspace's registry entry on
|
|
315
|
+
* first boot. The name itself is local-only — it never lives in the
|
|
316
|
+
* git-synced doc — so two machines pulling the same workspace.json can
|
|
317
|
+
* each call their local copy whatever they want.
|
|
318
|
+
*/
|
|
319
|
+
declare const DEFAULT_WORKSPACE_NAME = "My Workspace";
|
|
320
|
+
interface WorkspaceSynced {
|
|
321
|
+
schemaVersion: 1;
|
|
322
|
+
workspaceId: string;
|
|
323
|
+
collections: {
|
|
324
|
+
tree: FolderNode;
|
|
325
|
+
requests: Record<string, Request>;
|
|
326
|
+
folders: Record<string, Folder>;
|
|
327
|
+
};
|
|
328
|
+
environments: {
|
|
329
|
+
items: Record<string, Environment>;
|
|
330
|
+
activeName: string | null;
|
|
331
|
+
/**
|
|
332
|
+
* Ordered list of envs the resolver layers into request scope. Mixes
|
|
333
|
+
* local and linked-workspace envs — the consumer picks order. See
|
|
334
|
+
* `EnvPriorityRef`.
|
|
335
|
+
*/
|
|
336
|
+
priorityOrder: EnvPriorityRef[];
|
|
337
|
+
};
|
|
338
|
+
linkedWorkspaces: Record<string, LinkedWorkspace>;
|
|
339
|
+
linkedOverrides: {
|
|
340
|
+
requests: Record<string, RequestOverride>;
|
|
341
|
+
environmentVars: Record<string, EnvironmentVariableOverride>;
|
|
342
|
+
};
|
|
343
|
+
releases: {
|
|
344
|
+
self: ReleaseHistory | null;
|
|
345
|
+
perLink: Record<string, ReleaseHistory>;
|
|
346
|
+
};
|
|
347
|
+
globalAssets: {
|
|
348
|
+
schemas: Record<string, GlobalSchema>;
|
|
349
|
+
graphql: Record<string, GlobalGraphQL>;
|
|
350
|
+
};
|
|
351
|
+
mockServers: Record<string, MockServer>;
|
|
352
|
+
/**
|
|
353
|
+
* Workspace-wide execution plans. Plan **definitions** travel through
|
|
354
|
+
* Git so collaborators on the same workspace see the same plans;
|
|
355
|
+
* plan **runs** (history) stay in `WorkspaceLocal.history.planRuns`
|
|
356
|
+
* because they're per-device and per-execution.
|
|
357
|
+
*
|
|
358
|
+
* Optional in the type: pre-migration workspaces persisted plans on
|
|
359
|
+
* `WorkspaceLocal.executionPlans` only; the hydration normalizer
|
|
360
|
+
* lifts those into `synced.executionPlans` on first load. The store
|
|
361
|
+
* always writes a populated value (defaulting to `{}`) after
|
|
362
|
+
* migration, so consumers can rely on `synced.executionPlans` being
|
|
363
|
+
* defined post-hydrate.
|
|
364
|
+
*/
|
|
365
|
+
executionPlans?: Record<string, ExecutionPlan>;
|
|
366
|
+
secretKeys?: Record<string, SecretKeyMeta>;
|
|
367
|
+
/**
|
|
368
|
+
* Workspace-passphrase crypto state. `null` when no passphrase has been
|
|
369
|
+
* set yet (the workspace either has no secrets, or hasn't been migrated
|
|
370
|
+
* to the passphrase model). Populated by `setupPassphrase` the first
|
|
371
|
+
* time a user creates a passphrase; from then on, decryption requires
|
|
372
|
+
* the same passphrase to be re-entered (in memory only).
|
|
373
|
+
*
|
|
374
|
+
* The actual encrypted secret-value payloads still live in device-local
|
|
375
|
+
* IndexedDB today; migrating those into the synced doc is its own
|
|
376
|
+
* follow-up.
|
|
377
|
+
*
|
|
378
|
+
* `kdf` / `salt` / `iterations` parameterise the PBKDF2 derivation;
|
|
379
|
+
* `verifier` lets us reject a wrong passphrase up front without trying
|
|
380
|
+
* to decrypt every payload. See `passphraseKey.ts` for the algorithm.
|
|
381
|
+
*/
|
|
382
|
+
secretCrypto?: SecretCryptoMeta | null;
|
|
383
|
+
meta: {
|
|
384
|
+
createdAt: string;
|
|
385
|
+
updatedAt: string;
|
|
386
|
+
appVersion: string;
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
interface FolderNode {
|
|
390
|
+
id: string;
|
|
391
|
+
type: 'root' | 'folder';
|
|
392
|
+
children: Array<{
|
|
393
|
+
kind: 'folder' | 'request';
|
|
394
|
+
id: string;
|
|
395
|
+
}>;
|
|
396
|
+
}
|
|
397
|
+
interface Folder {
|
|
398
|
+
id: string;
|
|
399
|
+
name: string;
|
|
400
|
+
parentId: string | null;
|
|
401
|
+
/**
|
|
402
|
+
* Optional folder-level auth. When a request has `auth.type === 'inherit'`,
|
|
403
|
+
* the runner walks up the folder chain and uses the first explicit
|
|
404
|
+
* (non-`inherit`, non-`none`) auth it finds. Absent here = no folder-level
|
|
405
|
+
* auth at this level (continue walking up).
|
|
406
|
+
*/
|
|
407
|
+
auth?: RequestAuth;
|
|
408
|
+
}
|
|
409
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
410
|
+
type BodyType = 'none' | 'json' | 'text' | 'form-data' | 'urlencoded' | 'binary' | 'xml' | 'graphql';
|
|
411
|
+
interface Request {
|
|
412
|
+
id: string;
|
|
413
|
+
name: string;
|
|
414
|
+
folderId: string | null;
|
|
415
|
+
method: HttpMethod;
|
|
416
|
+
url: string;
|
|
417
|
+
headers: Array<{
|
|
418
|
+
key: string;
|
|
419
|
+
value: string;
|
|
420
|
+
enabled: boolean;
|
|
421
|
+
}>;
|
|
422
|
+
query: Array<{
|
|
423
|
+
key: string;
|
|
424
|
+
value: string;
|
|
425
|
+
enabled: boolean;
|
|
426
|
+
}>;
|
|
427
|
+
/**
|
|
428
|
+
* Values for URL path placeholders (`:name` Express-style or `{name}`
|
|
429
|
+
* OpenAPI-style). Keys are expected to match placeholder names found in
|
|
430
|
+
* `url`. Missing keys substitute to empty string at send time. Absent =
|
|
431
|
+
* empty (no path params), so the field is optional in storage.
|
|
432
|
+
*/
|
|
433
|
+
pathParams?: Record<string, string>;
|
|
434
|
+
/**
|
|
435
|
+
* Cookies sent with the request. Joined into a single `Cookie` header at
|
|
436
|
+
* send time (existing user-set Cookie header wins). Absent = no cookies.
|
|
437
|
+
*/
|
|
438
|
+
cookies?: Array<{
|
|
439
|
+
key: string;
|
|
440
|
+
value: string;
|
|
441
|
+
enabled: boolean;
|
|
442
|
+
}>;
|
|
443
|
+
body: RequestBody;
|
|
444
|
+
auth: RequestAuth;
|
|
445
|
+
contextVars: Array<{
|
|
446
|
+
key: string;
|
|
447
|
+
value: string;
|
|
448
|
+
}>;
|
|
449
|
+
extractions: ContextExtraction[];
|
|
450
|
+
bodySchemaId?: string | null;
|
|
451
|
+
graphqlSchemaId?: string | null;
|
|
452
|
+
assertions: Assertion[];
|
|
453
|
+
createdAt: string;
|
|
454
|
+
updatedAt: string;
|
|
455
|
+
}
|
|
456
|
+
interface ContextExtraction {
|
|
457
|
+
id: string;
|
|
458
|
+
variable: string;
|
|
459
|
+
source: 'body' | 'header' | 'cookie' | 'status';
|
|
460
|
+
/**
|
|
461
|
+
* Source-specific path:
|
|
462
|
+
* - body: JSON path (dot/bracket, e.g. `data.token` or `items[0].id`)
|
|
463
|
+
* - header: header name (case-insensitive)
|
|
464
|
+
* - cookie: cookie name
|
|
465
|
+
* - status: ignored — the HTTP status code is the value
|
|
466
|
+
*/
|
|
467
|
+
path: string;
|
|
468
|
+
enabled: boolean;
|
|
469
|
+
}
|
|
470
|
+
interface GlobalSchema {
|
|
471
|
+
id: string;
|
|
472
|
+
name: string;
|
|
473
|
+
description?: string;
|
|
474
|
+
/** JSON Schema document, stored as a string so the user can paste any draft. */
|
|
475
|
+
schema: string;
|
|
476
|
+
createdAt: string;
|
|
477
|
+
updatedAt: string;
|
|
478
|
+
}
|
|
479
|
+
interface GlobalGraphQL {
|
|
480
|
+
id: string;
|
|
481
|
+
name: string;
|
|
482
|
+
description?: string;
|
|
483
|
+
kind: 'sdl' | 'introspection';
|
|
484
|
+
source: string;
|
|
485
|
+
createdAt: string;
|
|
486
|
+
updatedAt: string;
|
|
487
|
+
}
|
|
488
|
+
type RequestAuth = {
|
|
489
|
+
type: 'none';
|
|
490
|
+
} | {
|
|
491
|
+
type: 'inherit';
|
|
492
|
+
} | {
|
|
493
|
+
type: 'bearer';
|
|
494
|
+
token: string;
|
|
495
|
+
} | {
|
|
496
|
+
type: 'basic';
|
|
497
|
+
username: string;
|
|
498
|
+
password: string;
|
|
499
|
+
} | {
|
|
500
|
+
type: 'api-key';
|
|
501
|
+
key: string;
|
|
502
|
+
value: string;
|
|
503
|
+
addTo: 'header' | 'query' | 'cookie';
|
|
504
|
+
} | {
|
|
505
|
+
type: 'custom-header';
|
|
506
|
+
key: string;
|
|
507
|
+
value: string;
|
|
508
|
+
} | OAuth2ClientCredentialsAuth | OAuth2AuthCodeAuth | OAuth2PkceAuth | OAuth2PasswordAuth | OAuth2ImplicitAuth | OAuth2DeviceAuth | AwsSigV4Auth | DigestAuth | NtlmAuth | HawkAuth | JwtBearerAuth;
|
|
509
|
+
interface OAuth2TokenState {
|
|
510
|
+
accessToken: string;
|
|
511
|
+
tokenType: string;
|
|
512
|
+
refreshToken: string;
|
|
513
|
+
/**
|
|
514
|
+
* Epoch milliseconds when the access token expires, or 0 / null when
|
|
515
|
+
* unknown. Stored as number so all comparisons are direct
|
|
516
|
+
* `Date.now() < expiresAt` without round-tripping through Date()
|
|
517
|
+
* parsing on the hot path. Workspace serialization rolls it through
|
|
518
|
+
* JSON unchanged — git-side this is a number, not an ISO string.
|
|
519
|
+
*/
|
|
520
|
+
expiresAt: number | null;
|
|
521
|
+
/**
|
|
522
|
+
* Scope the IdP actually granted (may differ from the request's
|
|
523
|
+
* `scope` field if the user/client is missing some). Refresh keeps
|
|
524
|
+
* this; clearing the token resets to ''.
|
|
525
|
+
*/
|
|
526
|
+
obtainedScope: string;
|
|
527
|
+
}
|
|
528
|
+
interface OAuth2ClientCredentialsAuth extends OAuth2TokenState {
|
|
529
|
+
type: 'oauth2-client-credentials';
|
|
530
|
+
tokenUrl: string;
|
|
531
|
+
clientId: string;
|
|
532
|
+
clientSecret: string;
|
|
533
|
+
scope: string;
|
|
534
|
+
clientAuthMethod: 'header' | 'body';
|
|
535
|
+
}
|
|
536
|
+
interface OAuth2AuthCodeAuth extends OAuth2TokenState {
|
|
537
|
+
type: 'oauth2-auth-code';
|
|
538
|
+
authUrl: string;
|
|
539
|
+
tokenUrl: string;
|
|
540
|
+
clientId: string;
|
|
541
|
+
clientSecret: string;
|
|
542
|
+
redirectUri: string;
|
|
543
|
+
scope: string;
|
|
544
|
+
state: string;
|
|
545
|
+
}
|
|
546
|
+
interface OAuth2PkceAuth extends OAuth2TokenState {
|
|
547
|
+
type: 'oauth2-pkce';
|
|
548
|
+
authUrl: string;
|
|
549
|
+
tokenUrl: string;
|
|
550
|
+
clientId: string;
|
|
551
|
+
clientSecret: string;
|
|
552
|
+
redirectUri: string;
|
|
553
|
+
scope: string;
|
|
554
|
+
state: string;
|
|
555
|
+
codeVerifier: string;
|
|
556
|
+
codeChallengeMethod: 'S256' | 'plain';
|
|
557
|
+
}
|
|
558
|
+
interface OAuth2PasswordAuth extends OAuth2TokenState {
|
|
559
|
+
type: 'oauth2-password';
|
|
560
|
+
tokenUrl: string;
|
|
561
|
+
clientId: string;
|
|
562
|
+
clientSecret: string;
|
|
563
|
+
username: string;
|
|
564
|
+
password: string;
|
|
565
|
+
scope: string;
|
|
566
|
+
}
|
|
567
|
+
interface OAuth2ImplicitAuth extends Omit<OAuth2TokenState, 'refreshToken'> {
|
|
568
|
+
type: 'oauth2-implicit';
|
|
569
|
+
authUrl: string;
|
|
570
|
+
clientId: string;
|
|
571
|
+
redirectUri: string;
|
|
572
|
+
scope: string;
|
|
573
|
+
}
|
|
574
|
+
interface OAuth2DeviceAuth extends OAuth2TokenState {
|
|
575
|
+
type: 'oauth2-device';
|
|
576
|
+
deviceAuthUrl: string;
|
|
577
|
+
tokenUrl: string;
|
|
578
|
+
clientId: string;
|
|
579
|
+
scope: string;
|
|
580
|
+
deviceCode: string;
|
|
581
|
+
userCode: string;
|
|
582
|
+
verificationUri: string;
|
|
583
|
+
}
|
|
584
|
+
interface AwsSigV4Auth {
|
|
585
|
+
type: 'aws-sigv4';
|
|
586
|
+
accessKeyId: string;
|
|
587
|
+
secretAccessKey: string;
|
|
588
|
+
sessionToken: string;
|
|
589
|
+
region: string;
|
|
590
|
+
service: string;
|
|
591
|
+
addTo: 'header' | 'query';
|
|
592
|
+
}
|
|
593
|
+
interface DigestAuth {
|
|
594
|
+
type: 'digest';
|
|
595
|
+
username: string;
|
|
596
|
+
password: string;
|
|
597
|
+
}
|
|
598
|
+
interface NtlmAuth {
|
|
599
|
+
type: 'ntlm';
|
|
600
|
+
username: string;
|
|
601
|
+
password: string;
|
|
602
|
+
domain: string;
|
|
603
|
+
workstation: string;
|
|
604
|
+
}
|
|
605
|
+
interface HawkAuth {
|
|
606
|
+
type: 'hawk';
|
|
607
|
+
hawkId: string;
|
|
608
|
+
hawkKey: string;
|
|
609
|
+
algorithm: 'sha256' | 'sha1';
|
|
610
|
+
ext: string;
|
|
611
|
+
/**
|
|
612
|
+
* When true, the request body is folded into the Hawk MAC via the
|
|
613
|
+
* payload-hash extension (Hawk spec §3.2.5). Required for servers
|
|
614
|
+
* configured with strict body-binding; leave false for the looser
|
|
615
|
+
* "header-only" form that most public Hawk APIs accept.
|
|
616
|
+
*/
|
|
617
|
+
bindPayload?: boolean;
|
|
618
|
+
}
|
|
619
|
+
interface JwtBearerAuth {
|
|
620
|
+
type: 'jwt-bearer';
|
|
621
|
+
algorithm: 'HS256' | 'HS384' | 'HS512' | 'RS256' | 'RS384' | 'RS512' | 'PS256' | 'PS384' | 'PS512' | 'ES256' | 'ES384' | 'ES512' | 'EdDSA';
|
|
622
|
+
secretOrKey: string;
|
|
623
|
+
payload: string;
|
|
624
|
+
jwtHeaders: string;
|
|
625
|
+
token: string;
|
|
626
|
+
}
|
|
627
|
+
interface RequestBody {
|
|
628
|
+
type: BodyType;
|
|
629
|
+
content: string;
|
|
630
|
+
formRows?: FormDataRow[];
|
|
631
|
+
attachment?: AttachmentRef;
|
|
632
|
+
variables?: string;
|
|
633
|
+
}
|
|
634
|
+
type FormDataRow = {
|
|
635
|
+
kind: 'text';
|
|
636
|
+
key: string;
|
|
637
|
+
value: string;
|
|
638
|
+
enabled: boolean;
|
|
639
|
+
} | {
|
|
640
|
+
kind: 'file';
|
|
641
|
+
key: string;
|
|
642
|
+
slotId: string | null;
|
|
643
|
+
filename?: string;
|
|
644
|
+
size?: number;
|
|
645
|
+
mimeType?: string;
|
|
646
|
+
sha256?: string;
|
|
647
|
+
enabled: boolean;
|
|
648
|
+
};
|
|
649
|
+
interface AttachmentRef {
|
|
650
|
+
slotId: string | null;
|
|
651
|
+
filename?: string;
|
|
652
|
+
size?: number;
|
|
653
|
+
mimeType?: string;
|
|
654
|
+
sha256?: string;
|
|
655
|
+
}
|
|
656
|
+
interface Assertion {
|
|
657
|
+
id: string;
|
|
658
|
+
kind: 'status' | 'header' | 'json-path' | 'duration';
|
|
659
|
+
op: 'equals' | 'not-equals' | 'contains' | 'lt' | 'gt' | 'matches';
|
|
660
|
+
target?: string;
|
|
661
|
+
expected: string | number;
|
|
662
|
+
}
|
|
663
|
+
interface Environment {
|
|
664
|
+
name: string;
|
|
665
|
+
variables: EnvironmentVariable[];
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Entry in the global / plan-level environment priority order. Both local
|
|
669
|
+
* environments and linked-workspace environments are first-class citizens
|
|
670
|
+
* — the consumer can interleave them in any order and the resolver layers
|
|
671
|
+
* them top-down at request-time. The two `kind`s exist because linked envs
|
|
672
|
+
* need a `linkedWorkspaceId` to resolve against the right snapshot in
|
|
673
|
+
* `WorkspaceLocal.linkedCollections` (and to apply the consumer's per-row
|
|
674
|
+
* overrides from `synced.linkedOverrides.environmentVars`).
|
|
675
|
+
*
|
|
676
|
+
* Stored in `WorkspaceSynced.environments.priorityOrder` and
|
|
677
|
+
* `ExecutionPlan.envPriorityOrder`.
|
|
678
|
+
*/
|
|
679
|
+
type EnvPriorityRef = {
|
|
680
|
+
kind: 'local';
|
|
681
|
+
name: string;
|
|
682
|
+
} | {
|
|
683
|
+
kind: 'linked';
|
|
684
|
+
linkedWorkspaceId: string;
|
|
685
|
+
envName: string;
|
|
686
|
+
};
|
|
687
|
+
interface EnvironmentVariable {
|
|
688
|
+
key: string;
|
|
689
|
+
value: string;
|
|
690
|
+
encrypted: boolean;
|
|
691
|
+
secretKeyId?: string;
|
|
692
|
+
}
|
|
693
|
+
interface SecretKeyMeta {
|
|
694
|
+
id: string;
|
|
695
|
+
label: string;
|
|
696
|
+
salt: string;
|
|
697
|
+
createdAt: string;
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Workspace-passphrase crypto parameters. Persisted in `WorkspaceSynced.
|
|
701
|
+
* secretCrypto`, written by `setupPassphrase` and read by `unlockSecretCrypto`.
|
|
702
|
+
* Single-version contract for now (`pbkdf2-sha256-v1`); future versions
|
|
703
|
+
* will be additional discriminants on `kdf`.
|
|
704
|
+
*
|
|
705
|
+
* `salt` is base64-encoded 16 random bytes; `verifier` is base64-encoded
|
|
706
|
+
* AES-GCM ciphertext of a fixed sentinel string under the derived key with
|
|
707
|
+
* a zero IV — comparing it constant-time tells a right passphrase from a
|
|
708
|
+
* wrong one before any real decrypt is attempted.
|
|
709
|
+
*/
|
|
710
|
+
interface SecretCryptoMeta {
|
|
711
|
+
kdf: 'pbkdf2-sha256-v1';
|
|
712
|
+
salt: string;
|
|
713
|
+
iterations: number;
|
|
714
|
+
verifier: string;
|
|
715
|
+
}
|
|
716
|
+
interface LinkedWorkspace {
|
|
717
|
+
id: string;
|
|
718
|
+
kind: 'private' | 'public';
|
|
719
|
+
name: string;
|
|
720
|
+
description?: string;
|
|
721
|
+
source: {
|
|
722
|
+
provider: 'github';
|
|
723
|
+
repoFullName: string;
|
|
724
|
+
branch: string;
|
|
725
|
+
/**
|
|
726
|
+
* Which GitHub session credentials this link uses for `workspace.json`
|
|
727
|
+
* fetches at link / refresh time.
|
|
728
|
+
*
|
|
729
|
+
* - `'workspace'` — reuse `local.sessions.github.workspace` (the same
|
|
730
|
+
* PAT that pushes/pulls THIS workspace). Convenient when both repos
|
|
731
|
+
* are reachable from a single token.
|
|
732
|
+
* - `'dedicated'` — use a per-link PAT stored at
|
|
733
|
+
* `local.sessions.github.links[linkedWorkspaceId]`. Used when the
|
|
734
|
+
* source repo lives under a different account (different org, a
|
|
735
|
+
* bot user, a teammate's fork) that the workspace session can't
|
|
736
|
+
* read.
|
|
737
|
+
*
|
|
738
|
+
* Public links still pick a mode — even public-repo fetches today route
|
|
739
|
+
* through `GitHubClient.getContents`, which uses an auth header.
|
|
740
|
+
*/
|
|
741
|
+
sessionMode: 'workspace' | 'dedicated';
|
|
742
|
+
};
|
|
743
|
+
scope: Array<'collections' | 'environments'>;
|
|
744
|
+
pinnedVersion: string | null;
|
|
745
|
+
updatePolicy: 'manual';
|
|
746
|
+
linkedAt: string;
|
|
747
|
+
requiredSecretKeyIds: string[];
|
|
748
|
+
marketplace?: {
|
|
749
|
+
listedAs: string;
|
|
750
|
+
tags: string[];
|
|
751
|
+
summary: string;
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
interface ReleaseHistory {
|
|
755
|
+
versions: ReleaseVersion[];
|
|
756
|
+
currentVersion: string | null;
|
|
757
|
+
}
|
|
758
|
+
interface ReleaseVersion {
|
|
759
|
+
version: string;
|
|
760
|
+
publishedAt: string;
|
|
761
|
+
notes: string;
|
|
762
|
+
workspaceSnapshot: string;
|
|
763
|
+
sha?: string;
|
|
764
|
+
tagName?: string;
|
|
765
|
+
deprecated: boolean;
|
|
766
|
+
yanked: boolean;
|
|
767
|
+
}
|
|
768
|
+
interface WorkspaceLocal {
|
|
769
|
+
schemaVersion: 1;
|
|
770
|
+
workspaceId: string;
|
|
771
|
+
/**
|
|
772
|
+
* @deprecated Plans now live on `WorkspaceSynced.executionPlans` so
|
|
773
|
+
* they round-trip through Git (team-shared). This field is kept for
|
|
774
|
+
* one schema version to support hydration migration only — code
|
|
775
|
+
* should NOT write here. The hydration normalizer
|
|
776
|
+
* `liftLegacyExecutionPlansToSynced` lifts any value found here into
|
|
777
|
+
* `synced.executionPlans` on first load and clears it.
|
|
778
|
+
*/
|
|
779
|
+
executionPlans: Record<string, ExecutionPlan>;
|
|
780
|
+
history: {
|
|
781
|
+
requestRuns: RequestRun[];
|
|
782
|
+
planRuns: PlanRun[];
|
|
783
|
+
};
|
|
784
|
+
secretIndex: SecretIndex;
|
|
785
|
+
sessions: {
|
|
786
|
+
github: {
|
|
787
|
+
workspace: GitHubSession | null;
|
|
788
|
+
links: Record<string, GitHubSession>;
|
|
789
|
+
};
|
|
790
|
+
};
|
|
791
|
+
connectedRepo: ConnectedRepo | null;
|
|
792
|
+
workingBranch: WorkingBranch | null;
|
|
793
|
+
/**
|
|
794
|
+
* Blob sha of the scaffold `workspace.json` written by
|
|
795
|
+
* `seedInitialCommit`. Persisted so the next `createWorkingBranch` can
|
|
796
|
+
* recognise its own scaffold on the new branch and suppress the
|
|
797
|
+
* "remote already has content" first-pull prompt — that prompt only
|
|
798
|
+
* makes sense for genuinely pre-populated remote content, not the
|
|
799
|
+
* empty seed we just wrote ourselves. `null` once any other content
|
|
800
|
+
* has overwritten the scaffold.
|
|
801
|
+
*/
|
|
802
|
+
seededWorkspaceSha: string | null;
|
|
803
|
+
/**
|
|
804
|
+
* Set by `refreshWorkspace` when it detects that the working branch is
|
|
805
|
+
* functionally over: the PR was merged on GitHub, OR the branch ref was
|
|
806
|
+
* deleted out from under us (typically by GitHub's "delete branch on
|
|
807
|
+
* merge" setting). `workingBranch` is cleared at the same time so the
|
|
808
|
+
* UI flips back to the create-branch form, and this slot drives a
|
|
809
|
+
* one-time banner pointing the user toward starting a new branch.
|
|
810
|
+
* Cleared by `dismissRetiredBranch` once the user acknowledges or
|
|
811
|
+
* creates a new branch.
|
|
812
|
+
*/
|
|
813
|
+
retiredBranch: RetiredBranch | null;
|
|
814
|
+
sync: SyncSnapshot;
|
|
815
|
+
linkedCollections: Record<string, LinkedSnapshot>;
|
|
816
|
+
globalContext: Record<string, string>;
|
|
817
|
+
mockRuntime: MockRuntime;
|
|
818
|
+
ui: {
|
|
819
|
+
activeRequestId: string | null;
|
|
820
|
+
sidebarExpandedSections: string[];
|
|
821
|
+
themeId: ThemeId;
|
|
822
|
+
/**
|
|
823
|
+
* Workspace-bound font family. Switching workspaces applies this
|
|
824
|
+
* font; renaming a workspace does not affect it. Default
|
|
825
|
+
* `'system-mono'` matches the seed in `createEmptyWorkspace`.
|
|
826
|
+
*/
|
|
827
|
+
fontId: FontFamilyId;
|
|
828
|
+
/**
|
|
829
|
+
* Whole-UI text-size scaling, expressed as a percentage of the
|
|
830
|
+
* browser's default root font-size. The HTML root's `font-size` is
|
|
831
|
+
* set to this percentage at hydrate / switch time, scaling every
|
|
832
|
+
* Tailwind `rem`-based utility plus the Monaco editor's option in
|
|
833
|
+
* `MonacoEditorBase`. Range: `FONT_SIZE_PERCENT_MIN`..`MAX`, snapped
|
|
834
|
+
* to `FONT_SIZE_PERCENT_STEP`. Default `FONT_SIZE_PERCENT_DEFAULT`
|
|
835
|
+
* (100) — matches the browser baseline so first-paint before
|
|
836
|
+
* hydrate doesn't flash a different size.
|
|
837
|
+
*/
|
|
838
|
+
fontSizePercent: number;
|
|
839
|
+
};
|
|
840
|
+
/**
|
|
841
|
+
* User-tunable client-side settings. Local-only; never round-trips
|
|
842
|
+
* through Git so each developer can keep their own preferences.
|
|
843
|
+
*
|
|
844
|
+
* - `validateOnSend`: when true, the Editor surfaces a pre-send
|
|
845
|
+
* validation panel (warnings + blockers from
|
|
846
|
+
* `core/preSendValidation`) above the Send button. Default: true.
|
|
847
|
+
*/
|
|
848
|
+
settings: WorkspaceLocalSettings;
|
|
849
|
+
/**
|
|
850
|
+
* Pre-destructive snapshot ledger. Auto-captured before every operation
|
|
851
|
+
* that could lose work (push, merge, linked-update apply, yank, deprecate),
|
|
852
|
+
* and on user demand via the History panel. Local-only; never pushed.
|
|
853
|
+
*
|
|
854
|
+
* The ledger acts as a ring buffer: when total `sizeBytes` exceeds
|
|
855
|
+
* `maxBytes`, the oldest snapshots are evicted until the total drops
|
|
856
|
+
* back under cap. Set `maxBytes: Number.POSITIVE_INFINITY` to disable
|
|
857
|
+
* eviction.
|
|
858
|
+
*/
|
|
859
|
+
snapshots: WorkspaceSnapshotLedger;
|
|
860
|
+
}
|
|
861
|
+
interface WorkspaceLocalSettings {
|
|
862
|
+
validateOnSend: boolean;
|
|
863
|
+
/**
|
|
864
|
+
* Whether Monaco editors consume mouse-wheel events even when the user
|
|
865
|
+
* isn't intending to scroll the editor (e.g. they're hovering over the
|
|
866
|
+
* editor while scrolling the page). When `false`, wheel events bubble
|
|
867
|
+
* up to the page so long pages remain scrollable past the editor.
|
|
868
|
+
* When `true`, the editor scrolls first and only releases the wheel
|
|
869
|
+
* once it reaches its top/bottom (Monaco's default behavior).
|
|
870
|
+
*
|
|
871
|
+
* Default: `false` (page-scroll friendly).
|
|
872
|
+
*/
|
|
873
|
+
monacoConsumesWheel: boolean;
|
|
874
|
+
}
|
|
875
|
+
type WorkspaceSnapshotTrigger = 'manual' | 'pre-push' | 'pre-merge' | 'pre-linked-update' | 'pre-yank' | 'pre-deprecate';
|
|
876
|
+
interface WorkspaceSnapshot {
|
|
877
|
+
/** Stable id; survives ledger updates so restore is idempotent. */
|
|
878
|
+
id: string;
|
|
879
|
+
/** ISO timestamp the snapshot was captured at. */
|
|
880
|
+
createdAt: string;
|
|
881
|
+
/** What triggered the capture — informational, used for the History badge. */
|
|
882
|
+
triggeredBy: WorkspaceSnapshotTrigger;
|
|
883
|
+
/** Optional user-provided note (manual snapshots; the others auto-fill it). */
|
|
884
|
+
note?: string;
|
|
885
|
+
/**
|
|
886
|
+
* Verbatim copy of `WorkspaceSynced` at the moment of capture. Stored
|
|
887
|
+
* inline so restore is a single state replacement — no IPFS, no SHA-only
|
|
888
|
+
* placeholder. Cost: ~the size of `workspace.json`. The ring buffer +
|
|
889
|
+
* cap keep this bounded.
|
|
890
|
+
*/
|
|
891
|
+
workspaceSyncedSnapshot: WorkspaceSynced;
|
|
892
|
+
/**
|
|
893
|
+
* Approximate JSON byte length of `workspaceSyncedSnapshot` at capture
|
|
894
|
+
* time. Used for the storage meter + ring-buffer eviction; the exact
|
|
895
|
+
* persisted size after IDB compression may differ.
|
|
896
|
+
*/
|
|
897
|
+
sizeBytes: number;
|
|
898
|
+
}
|
|
899
|
+
interface WorkspaceSnapshotLedger {
|
|
900
|
+
entries: WorkspaceSnapshot[];
|
|
901
|
+
/**
|
|
902
|
+
* Cap on total `sizeBytes` across all entries. When exceeded, oldest
|
|
903
|
+
* entries are dropped until the total drops back under cap. Defaults
|
|
904
|
+
* to 50 MB (52,428,800).
|
|
905
|
+
*/
|
|
906
|
+
maxBytes: number;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Snapshot of a linked source workspace at a specific ref. Lives only
|
|
910
|
+
* in `WorkspaceLocal.linkedCollections[id]`. Refreshed on demand via
|
|
911
|
+
* the link card's Refresh ledger button (which pulls workspace.json
|
|
912
|
+
* and re-derives this snapshot).
|
|
913
|
+
*
|
|
914
|
+
* `ref` is the pinnedVersion when the link is pinned, otherwise
|
|
915
|
+
* `HEAD@<branch>` to make it obvious which moving target the snapshot
|
|
916
|
+
* is tracking.
|
|
917
|
+
*/
|
|
918
|
+
interface LinkedSnapshot {
|
|
919
|
+
pulledAt: string;
|
|
920
|
+
ref: string;
|
|
921
|
+
collections: WorkspaceSynced['collections'];
|
|
922
|
+
environments: WorkspaceSynced['environments'];
|
|
923
|
+
/**
|
|
924
|
+
* The source workspace's secret-key registry, cached so the link card
|
|
925
|
+
* can render slot labels (not just raw ids). Optional — older
|
|
926
|
+
* snapshots from before this field was tracked load with `undefined`,
|
|
927
|
+
* and the card falls back to showing ids until the next refresh.
|
|
928
|
+
*/
|
|
929
|
+
secretKeys?: Record<string, SecretKeyMeta>;
|
|
930
|
+
}
|
|
931
|
+
interface SecretIndex {
|
|
932
|
+
entries: Record<string, SecretEntry>;
|
|
933
|
+
}
|
|
934
|
+
interface SecretEntry {
|
|
935
|
+
id: string;
|
|
936
|
+
label: string;
|
|
937
|
+
createdAt: string;
|
|
938
|
+
origin: 'workspace' | 'linked';
|
|
939
|
+
linkedWorkspaceId?: string;
|
|
940
|
+
linkedKeyId?: string;
|
|
941
|
+
usedIn: SecretUsage[];
|
|
942
|
+
}
|
|
943
|
+
interface SecretUsage {
|
|
944
|
+
kind: 'request' | 'environment-var' | 'linked-workspace-input';
|
|
945
|
+
id: string;
|
|
946
|
+
label: string;
|
|
947
|
+
}
|
|
948
|
+
interface GitHubSession {
|
|
949
|
+
accountLogin: string;
|
|
950
|
+
tokenSecretId: string;
|
|
951
|
+
grantedScopes: string[];
|
|
952
|
+
addedAt: string;
|
|
953
|
+
lastVerifiedAt: string | null;
|
|
954
|
+
/**
|
|
955
|
+
* Whether this token can create pull requests, derived from a two-step
|
|
956
|
+
* check: (1) scope inspection (`repo` on classic PATs OR `pull_request`
|
|
957
|
+
* on fine-grained PATs covers PR creation), and (2) if the scope check
|
|
958
|
+
* is inconclusive, a real `GET /repos/:owner/:repo/pulls` probe against
|
|
959
|
+
* the connected repo. The PR-creation warning + Create PR button enable
|
|
960
|
+
* state both read this flag instead of doing string-includes checks
|
|
961
|
+
* against `grantedScopes` — which would false-fire for any classic PAT
|
|
962
|
+
* (classic PATs don't have a separate `pull_request` scope; `repo`
|
|
963
|
+
* already grants full PR powers, and that's what GitHub actually
|
|
964
|
+
* accepts at runtime).
|
|
965
|
+
*
|
|
966
|
+
* - `true` — scope check confirmed OR probe returned 200
|
|
967
|
+
* - `false` — probe returned 403 with missing-scope hint
|
|
968
|
+
* - `null` — not yet probed (no repo connected, or probe pending)
|
|
969
|
+
*/
|
|
970
|
+
canCreatePullRequests: boolean | null;
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Field-level override for a single linked request. Every field is
|
|
974
|
+
* optional — present ⇒ replaces the source workspace's value, absent ⇒
|
|
975
|
+
* inherits from the snapshot. Stored as a delta (smallest possible
|
|
976
|
+
* patch) so reset = drop the entry.
|
|
977
|
+
*
|
|
978
|
+
* The five identity / lifecycle fields (`id`, `folderId`, `createdAt`,
|
|
979
|
+
* `updatedAt`, plus `bodySchemaId` / `graphqlSchemaId` since those
|
|
980
|
+
* reference the source's globalAssets) are intentionally NOT
|
|
981
|
+
* overridable — keeping them source-pinned avoids stale references and
|
|
982
|
+
* keeps the consumer's tree structure under the source's control.
|
|
983
|
+
*/
|
|
984
|
+
type RequestOverridePatch = Partial<Pick<Request, 'name' | 'method' | 'url' | 'headers' | 'query' | 'pathParams' | 'cookies' | 'body' | 'auth' | 'contextVars' | 'extractions' | 'assertions'>>;
|
|
985
|
+
interface RequestOverride {
|
|
986
|
+
linkedWorkspaceId: string;
|
|
987
|
+
itemId: string;
|
|
988
|
+
patch: RequestOverridePatch;
|
|
989
|
+
updatedAt: string;
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Per-variable override on a linked workspace's environment. Keyed
|
|
993
|
+
* `${linkedWorkspaceId}:${envName}:${varKey}` in the parent record.
|
|
994
|
+
*
|
|
995
|
+
* Three modes:
|
|
996
|
+
* 1. Replace value: `value` (and optionally `encrypted` / `secretKeyId`) set,
|
|
997
|
+
* `removed` absent. Keeps the source variable but with the consumer's value.
|
|
998
|
+
* 2. Hide source variable: `removed: true`. The source's variable is dropped
|
|
999
|
+
* from the consumer's effective environment.
|
|
1000
|
+
* 3. Inject new variable: the `varKey` does not exist in the source's env;
|
|
1001
|
+
* the override row introduces it for this consumer only.
|
|
1002
|
+
*/
|
|
1003
|
+
interface EnvironmentVariableOverride {
|
|
1004
|
+
linkedWorkspaceId: string;
|
|
1005
|
+
envName: string;
|
|
1006
|
+
varKey: string;
|
|
1007
|
+
value?: string;
|
|
1008
|
+
encrypted?: boolean;
|
|
1009
|
+
secretKeyId?: string;
|
|
1010
|
+
removed?: boolean;
|
|
1011
|
+
updatedAt: string;
|
|
1012
|
+
}
|
|
1013
|
+
interface ExecutionPlan {
|
|
1014
|
+
id: string;
|
|
1015
|
+
name: string;
|
|
1016
|
+
/**
|
|
1017
|
+
* Steps run sequentially in this order. `enabled: false` skips the step
|
|
1018
|
+
* entirely at run time — useful for keeping a step in the plan while
|
|
1019
|
+
* temporarily routing around it. Defaults to `true` when missing on
|
|
1020
|
+
* older persisted plans (pre-`enabled` plans that haven't been touched
|
|
1021
|
+
* since the field landed).
|
|
1022
|
+
*/
|
|
1023
|
+
steps: Array<{
|
|
1024
|
+
requestId: string;
|
|
1025
|
+
linkedWorkspaceId?: string;
|
|
1026
|
+
enabled?: boolean;
|
|
1027
|
+
}>;
|
|
1028
|
+
/**
|
|
1029
|
+
* Plan-scoped overlay for the workspace's env priority order. Empty
|
|
1030
|
+
* means "inherit the workspace order"; non-empty replaces it for runs
|
|
1031
|
+
* of this plan. Mixes local + linked envs the same way the workspace
|
|
1032
|
+
* order does — see `EnvPriorityRef`.
|
|
1033
|
+
*/
|
|
1034
|
+
envPriorityOrder: EnvPriorityRef[];
|
|
1035
|
+
/**
|
|
1036
|
+
* Plan-level variables sit between context vars and the env priority
|
|
1037
|
+
* list in the resolver chain — they let a plan override an env value
|
|
1038
|
+
* without mutating the env. Keys are case-sensitive; later entries
|
|
1039
|
+
* silently win on duplicate keys (consistent with env vars).
|
|
1040
|
+
*/
|
|
1041
|
+
variables?: Array<{
|
|
1042
|
+
key: string;
|
|
1043
|
+
value: string;
|
|
1044
|
+
}>;
|
|
1045
|
+
/**
|
|
1046
|
+
* When `true`, runPlan halts the loop the first time a step's
|
|
1047
|
+
* assertions don't all pass. Only consulted when the run is launched
|
|
1048
|
+
* `withAssertions` — `Run` (without assertions) never short-circuits.
|
|
1049
|
+
* Defaults to `false` (continue past failed assertions).
|
|
1050
|
+
*/
|
|
1051
|
+
stopOnAssertionFailure?: boolean;
|
|
1052
|
+
createdAt: string;
|
|
1053
|
+
updatedAt: string;
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* Captured wire detail for a request run, written when the run completes.
|
|
1057
|
+
* Stored on `WorkspaceLocal.history` (capped, IDB-only). Body fields are
|
|
1058
|
+
* truncated past `RUN_BODY_PREVIEW_LIMIT` so a hundred history rows can't
|
|
1059
|
+
* blow up the IDB record.
|
|
1060
|
+
*/
|
|
1061
|
+
interface RequestRun {
|
|
1062
|
+
id: string;
|
|
1063
|
+
requestId: string;
|
|
1064
|
+
startedAt: string;
|
|
1065
|
+
durationMs: number;
|
|
1066
|
+
status: number | null;
|
|
1067
|
+
/** Empty string for network errors (status === null). */
|
|
1068
|
+
statusText: string;
|
|
1069
|
+
ok: boolean;
|
|
1070
|
+
error?: string;
|
|
1071
|
+
/** Final URL after path-param substitution + query composition. */
|
|
1072
|
+
url: string;
|
|
1073
|
+
method: string;
|
|
1074
|
+
/** Final headers actually sent on the wire (post-auth). */
|
|
1075
|
+
requestHeaders: Record<string, string>;
|
|
1076
|
+
/**
|
|
1077
|
+
* Best-effort string preview of the request body. `null` for binary/form
|
|
1078
|
+
* bodies (where the body isn't a string) or no body. Truncated past
|
|
1079
|
+
* `RUN_BODY_PREVIEW_LIMIT` bytes.
|
|
1080
|
+
*/
|
|
1081
|
+
requestBodyPreview: string | null;
|
|
1082
|
+
/** Headers received from the server. */
|
|
1083
|
+
responseHeaders: Record<string, string>;
|
|
1084
|
+
/** Truncated string preview of the response body. */
|
|
1085
|
+
responseBodyPreview: string;
|
|
1086
|
+
responseBodyKind: 'json' | 'text' | 'binary' | 'empty';
|
|
1087
|
+
responseTruncated: boolean;
|
|
1088
|
+
/**
|
|
1089
|
+
* Verdicts captured at run time. Snapshots the assertion definition so the
|
|
1090
|
+
* History detail view can render kind/op/target/expected even when the
|
|
1091
|
+
* source request has since been edited or deleted.
|
|
1092
|
+
*/
|
|
1093
|
+
assertions: Array<{
|
|
1094
|
+
assertionId: string;
|
|
1095
|
+
kind: Assertion['kind'];
|
|
1096
|
+
op: Assertion['op'];
|
|
1097
|
+
target?: string;
|
|
1098
|
+
expected: string | number;
|
|
1099
|
+
passed: boolean;
|
|
1100
|
+
detail?: string;
|
|
1101
|
+
}>;
|
|
1102
|
+
}
|
|
1103
|
+
/** Soft cap for body previews stored on a RequestRun (each side). */
|
|
1104
|
+
declare const RUN_BODY_PREVIEW_LIMIT: number;
|
|
1105
|
+
/**
|
|
1106
|
+
* UI text-size scaling bounds. `fontSizePercent` on `WorkspaceLocal.ui`
|
|
1107
|
+
* is clamped to `[MIN, MAX]` and snapped to `STEP`. Below 80% the
|
|
1108
|
+
* smallest chrome (10–11px bracketed Tailwind sizes) becomes unreadable;
|
|
1109
|
+
* above 150% layout pressure mounts in narrow panels.
|
|
1110
|
+
*/
|
|
1111
|
+
declare const FONT_SIZE_PERCENT_MIN = 80;
|
|
1112
|
+
declare const FONT_SIZE_PERCENT_MAX = 150;
|
|
1113
|
+
declare const FONT_SIZE_PERCENT_STEP = 10;
|
|
1114
|
+
declare const FONT_SIZE_PERCENT_DEFAULT = 100;
|
|
1115
|
+
interface PlanRun {
|
|
1116
|
+
id: string;
|
|
1117
|
+
planId: string;
|
|
1118
|
+
startedAt: string;
|
|
1119
|
+
durationMs: number;
|
|
1120
|
+
withAssertions: boolean;
|
|
1121
|
+
steps: Array<{
|
|
1122
|
+
requestRunId: string;
|
|
1123
|
+
passed: boolean;
|
|
1124
|
+
}>;
|
|
1125
|
+
}
|
|
1126
|
+
interface ConnectedRepo {
|
|
1127
|
+
fullName: string;
|
|
1128
|
+
owner: string;
|
|
1129
|
+
name: string;
|
|
1130
|
+
defaultBranch: string;
|
|
1131
|
+
visibility: 'public' | 'private' | 'internal';
|
|
1132
|
+
isPrivate: boolean;
|
|
1133
|
+
pushable: boolean;
|
|
1134
|
+
connectedAt: string;
|
|
1135
|
+
}
|
|
1136
|
+
interface WorkingBranch {
|
|
1137
|
+
/** Branch name on GitHub, e.g. `apicircle/payments-a3f9c2`. */
|
|
1138
|
+
name: string;
|
|
1139
|
+
/** Base branch (typically the repo's default — `main` / `master`). */
|
|
1140
|
+
baseBranch: string;
|
|
1141
|
+
/** `owner/name` on GitHub. */
|
|
1142
|
+
repoFullName: string;
|
|
1143
|
+
/** Owner login, stored redundantly so call sites don't have to re-split. */
|
|
1144
|
+
repoOwner: string;
|
|
1145
|
+
/** Repo name, same idea. */
|
|
1146
|
+
repoName: string;
|
|
1147
|
+
/** Commit SHA on this branch's HEAD at creation (= base SHA initially). */
|
|
1148
|
+
headSha: string;
|
|
1149
|
+
createdAt: string;
|
|
1150
|
+
lastPushedSha: string | null;
|
|
1151
|
+
diffSummary: {
|
|
1152
|
+
ahead: number;
|
|
1153
|
+
behind: number;
|
|
1154
|
+
staleAt: string;
|
|
1155
|
+
} | null;
|
|
1156
|
+
openPrUrl: string | null;
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* A working branch that's been retired — either the PR was merged or the
|
|
1160
|
+
* branch was deleted on GitHub (or both). Persisted on `local.retiredBranch`
|
|
1161
|
+
* so the create-branch form can surface a "this branch is done — create a
|
|
1162
|
+
* new one" banner pointing back at the closed PR.
|
|
1163
|
+
*
|
|
1164
|
+
* Reasons:
|
|
1165
|
+
* - `pr-merged` — PR was merged. Branch may still exist on GitHub
|
|
1166
|
+
* (no auto-delete) or may be gone; either way it's
|
|
1167
|
+
* functionally retired.
|
|
1168
|
+
* - `branch-deleted` — Branch ref returns 404. PR (if any) was not
|
|
1169
|
+
* merged — most likely a deliberate delete or a
|
|
1170
|
+
* closed-without-merge cleanup.
|
|
1171
|
+
*/
|
|
1172
|
+
interface RetiredBranch {
|
|
1173
|
+
/** Branch name that was retired. */
|
|
1174
|
+
branchName: string;
|
|
1175
|
+
/** Why the branch is retired. */
|
|
1176
|
+
reason: 'pr-merged' | 'branch-deleted';
|
|
1177
|
+
/** ISO timestamp when retirement was detected. */
|
|
1178
|
+
retiredAt: string;
|
|
1179
|
+
/** PR HTML URL if one was opened (kept across retirement so the banner can link it). */
|
|
1180
|
+
prUrl: string | null;
|
|
1181
|
+
/** PR number if known — useful for the banner copy ("PR #42 was merged"). */
|
|
1182
|
+
prNumber: number | null;
|
|
1183
|
+
}
|
|
1184
|
+
interface SyncSnapshot {
|
|
1185
|
+
lastPulledSnapshot: WorkspaceSynced | null;
|
|
1186
|
+
lastPulledSha: string | null;
|
|
1187
|
+
lastPulledAt: string | null;
|
|
1188
|
+
dirtyKeys: string[];
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
/**
|
|
1192
|
+
* Stable string key for an `EnvPriorityRef`. Used by the resolver as the
|
|
1193
|
+
* lookup key into the flattened `environments` map (which mixes local and
|
|
1194
|
+
* linked envs under composite keys), and by React lists as the row id.
|
|
1195
|
+
*
|
|
1196
|
+
* - local: `local:<envName>`
|
|
1197
|
+
* - linked: `linked:<linkedWorkspaceId>:<envName>`
|
|
1198
|
+
*
|
|
1199
|
+
* The `local:` prefix is intentional even for local envs — having a uniform
|
|
1200
|
+
* shape avoids ambiguity (a local env named `linked:abc:dev` would collide
|
|
1201
|
+
* with a linked env without the prefix). Treat keys as opaque; round-trip
|
|
1202
|
+
* through `parseEnvPriorityKey` rather than parsing inline.
|
|
1203
|
+
*/
|
|
1204
|
+
declare function envPriorityKey(ref: EnvPriorityRef): string;
|
|
1205
|
+
/**
|
|
1206
|
+
* Inverse of `envPriorityKey`. Returns null for unknown shapes — callers
|
|
1207
|
+
* use that to skip stale priority entries (e.g. a linked env that was
|
|
1208
|
+
* unlinked between pulls).
|
|
1209
|
+
*/
|
|
1210
|
+
declare function parseEnvPriorityKey(key: string): EnvPriorityRef | null;
|
|
1211
|
+
/**
|
|
1212
|
+
* Equality on EnvPriorityRef. Used for "is this env in the priority
|
|
1213
|
+
* list?" toggles and for diffing in tests.
|
|
1214
|
+
*/
|
|
1215
|
+
declare function envPriorityRefEqual(a: EnvPriorityRef, b: EnvPriorityRef): boolean;
|
|
1216
|
+
/**
|
|
1217
|
+
* Display name for an env priority entry. Used by sidebar + plan editor.
|
|
1218
|
+
* Linked entries get a "via {linkName}" suffix at render-time — we keep
|
|
1219
|
+
* just the env name here so the caller can format with workspace context.
|
|
1220
|
+
*/
|
|
1221
|
+
declare function envPriorityDisplayName(ref: EnvPriorityRef): string;
|
|
1222
|
+
|
|
1223
|
+
type RequestAuthType = RequestAuth['type'];
|
|
1224
|
+
declare function defaultAuthFor<T extends RequestAuthType>(type: T): Extract<RequestAuth, {
|
|
1225
|
+
type: T;
|
|
1226
|
+
}>;
|
|
1227
|
+
/** Best-effort upgrade of an unknown value into a valid RequestAuth. */
|
|
1228
|
+
declare function normalizeAuth(input: unknown): RequestAuth;
|
|
1229
|
+
declare const REQUEST_AUTH_TYPES: ReadonlyArray<RequestAuthType>;
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* Every MCP tool the server exposes. Namespaced by capability area so AI
|
|
1233
|
+
* clients can group them in their UI. Keep in sync with the registry in
|
|
1234
|
+
* `packages/mcp-server/src/tools/registry.ts`.
|
|
1235
|
+
*/
|
|
1236
|
+
type McpToolName = 'import.curl' | 'import.openapi' | 'import.postman' | 'import.insomnia' | 'import.har' | 'generate.code' | 'workspace.read' | 'workspace.write' | 'request.create' | 'request.read' | 'request.update' | 'request.delete' | 'folder.create' | 'folder.read' | 'folder.update' | 'folder.delete' | 'environment.create' | 'environment.read' | 'environment.update' | 'environment.delete' | 'environment.set_active' | 'environment.set_priority' | 'environment.export' | 'environment.import' | 'plan.create' | 'plan.run' | 'plan.read' | 'plan.update' | 'plan.delete' | 'plan.add_step' | 'plan.remove_step' | 'plan.reorder_steps' | 'plan.set_variables' | 'assertion.create' | 'assertion.read' | 'assertion.update' | 'assertion.delete' | 'history.list_runs' | 'history.get_run' | 'history.delete_run' | 'history.purge_by_age' | 'codebase.extract_collection' | 'prompt.create_environment' | 'prompt.create_assertion' | 'prompt.create_plan' | 'prompt.create_request' | 'prompt.update_request' | 'prompt.create_folder_tree' | 'prompt.add_plan_steps' | 'prompt.set_plan_variables' | 'prompt.create_mock_server' | 'prompt.add_mock_endpoint' | 'prompt.set_endpoint_validation_rules' | 'prompt.set_endpoint_response_rules' | 'prompt.set_endpoint_multipliers' | 'mock.create_from_openapi' | 'mock.create_from_postman' | 'mock.create_from_insomnia' | 'mock.create_manual' | 'mock.list' | 'mock.list_endpoints' | 'mock.start' | 'mock.stop' | 'mock.delete' | 'mock.add_endpoint' | 'mock.update_endpoint' | 'mock.delete_endpoint' | 'mock.set_validation_rules' | 'mock.set_response_rules' | 'mock.set_multipliers' | 'mock.import_postman_mock_collection';
|
|
1237
|
+
interface McpError {
|
|
1238
|
+
code: 'invalid_input' | 'not_found' | 'conflict' | 'unsupported' | 'internal';
|
|
1239
|
+
message: string;
|
|
1240
|
+
details?: unknown;
|
|
1241
|
+
}
|
|
1242
|
+
/** Helper: full enumeration of tool names — useful for the docs / config UIs. */
|
|
1243
|
+
declare const MCP_TOOL_NAMES: ReadonlyArray<McpToolName>;
|
|
1244
|
+
|
|
1245
|
+
export { type Assertion, type AttachmentRef, type AwsSigV4Auth, type BodyType, type ConnectedRepo, type ContextExtraction, DEFAULT_WORKSPACE_NAME, type DigestAuth, type EnvPriorityRef, type Environment, type EnvironmentVariable, type EnvironmentVariableOverride, type ExecutionPlan, FONT_SIZE_PERCENT_DEFAULT, FONT_SIZE_PERCENT_MAX, FONT_SIZE_PERCENT_MIN, FONT_SIZE_PERCENT_STEP, type Folder, type FolderNode, type FontFamilyId, type FormDataRow, type GitHubSession, type GlobalGraphQL, type GlobalSchema, type HawkAuth, type HttpMethod, type JwtBearerAuth, type LinkedSnapshot, type LinkedWorkspace, MCP_TOOL_NAMES, type McpError, type McpToolName, type MockConditionClause, type MockConditionOp, type MockConditionScope, type MockEndpoint, type MockMultiplierSource, type MockMultiplierSourceKind, type MockParamDef, type MockRequestSchema, type MockResponseBody, type MockResponseBodyType, type MockResponseConfig, type MockResponseMultiplier, type MockResponseRule, type MockRuntime, type MockRuntimeEntry, type MockServer, type MockServerSource, type MockValidationKind, type MockValidationRule, type NtlmAuth, type OAuth2AuthCodeAuth, type OAuth2ClientCredentialsAuth, type OAuth2DeviceAuth, type OAuth2ImplicitAuth, type OAuth2PasswordAuth, type OAuth2PkceAuth, type OAuth2TokenState, type PanelId, type PlanRun, REQUEST_AUTH_TYPES, RUN_BODY_PREVIEW_LIMIT, type ReleaseHistory, type ReleaseVersion, type Request, type RequestAuth, type RequestAuthType, type RequestBody, type RequestOverride, type RequestOverridePatch, type RequestRun, type RetiredBranch, type SecretCryptoMeta, type SecretEntry, type SecretIndex, type SecretKeyMeta, type SecretUsage, type SyncSnapshot, type ThemeId, type ValidationResult, type WorkingBranch, type WorkspaceLocal, type WorkspaceSnapshot, type WorkspaceSnapshotLedger, type WorkspaceSnapshotTrigger, type WorkspaceSynced, coerceMockResponseBodyTypeForStatus, defaultAuthFor, envPriorityDisplayName, envPriorityKey, envPriorityRefEqual, formatBytes, generateId, getAllowedMockResponseBodyTypes, makeDefaultMockResponse, makeDefaultMockResponseBody, makeDefaultRequestSchema, normalizeAuth, parseEnvPriorityKey, safeExternalHref, utf8ByteLength, validateAwsRegion, validateEnvVarName, validateHttpHeaderName, validateJsonPath, validateJsonString, validateMockPath, validatePRTitle, validatePlanName, validatePositiveDuration, validateRegex, validateUrl };
|