@apicircle/core 1.0.9 → 1.1.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/dist/index.cjs CHANGED
@@ -22,31 +22,35 @@ var src_exports = {};
22
22
  __export(src_exports, {
23
23
  ANONYMOUS_ACTOR: () => ANONYMOUS_ACTOR,
24
24
  APICIRCLE_FOLDER_EXPORT_FORMAT: () => APICIRCLE_FOLDER_EXPORT_FORMAT,
25
- ATTACHMENTS_DIR: () => ATTACHMENTS_DIR,
26
25
  DESKTOP_APP_ORIGIN: () => DESKTOP_APP_ORIGIN,
27
26
  EMPTY_UNPUSHED_SUMMARY: () => EMPTY_UNPUSHED_SUMMARY,
28
27
  HTTP_HEADERS_MAP: () => HTTP_HEADERS_MAP,
29
28
  OAuth2TokenError: () => OAuth2TokenError,
30
29
  PlanRunDeniedError: () => PlanRunDeniedError,
30
+ REGISTRY_JSON_PATH: () => REGISTRY_JSON_PATH,
31
31
  RemoteWorkspaceParseError: () => RemoteWorkspaceParseError,
32
32
  TRANSFORM_FORMAT_LABELS: () => TRANSFORM_FORMAT_LABELS,
33
33
  WORKSPACE_DIR: () => WORKSPACE_DIR,
34
- WORKSPACE_JSON_PATH: () => WORKSPACE_JSON_PATH,
34
+ appendReleaseEntry: () => appendReleaseEntry,
35
35
  applyAuth: () => applyAuth,
36
36
  applyAwsSigV4: () => applyAwsSigV4,
37
37
  applyContentTypeForBodyType: () => applyContentTypeForBodyType,
38
+ applyLinkedEnvironmentOverrides: () => applyLinkedEnvironmentOverrides,
38
39
  applyLinkedUpdate: () => applyLinkedUpdate,
39
40
  applyMerge: () => applyMerge,
40
41
  applyMutation: () => applyMutation,
41
42
  applyPathParams: () => applyPathParams,
42
43
  assertNoPlaintextCredentials: () => assertNoPlaintextCredentials,
43
44
  attachmentPath: () => attachmentPath,
45
+ attachmentsDir: () => attachmentsDir,
44
46
  buildAuthorizeUrl: () => buildAuthorizeUrl,
45
47
  buildAutoHeaders: () => buildAutoHeaders,
46
48
  buildDigestAuthHeader: () => buildDigestAuthHeader,
47
49
  buildHawkAuthHeader: () => buildHawkAuthHeader,
50
+ buildLinkedSnapshot: () => buildLinkedSnapshot,
48
51
  buildNtlmType1Negotiate: () => buildNtlmType1Negotiate,
49
52
  buildNtlmType3Authenticate: () => buildNtlmType3Authenticate,
53
+ buildReleaseEntry: () => buildReleaseEntry,
50
54
  buildRequest: () => buildRequest,
51
55
  buildScope: () => buildScope,
52
56
  collectAttachmentSlots: () => collectAttachmentSlots,
@@ -60,6 +64,7 @@ __export(src_exports, {
60
64
  composeUrl: () => composeUrl,
61
65
  composeUrlWithQuery: () => composeUrlWithQuery,
62
66
  computeCodeChallenge: () => computeCodeChallenge,
67
+ computeRequestOverridePatch: () => computeRequestOverridePatch,
63
68
  computeThreeWayDiff: () => computeThreeWayDiff,
64
69
  computeTransformSavings: () => computeTransformSavings,
65
70
  decryptString: () => decryptString,
@@ -72,6 +77,7 @@ __export(src_exports, {
72
77
  exportKey: () => exportKey,
73
78
  extractContext: () => extractContext,
74
79
  fetchOAuth2Token: () => fetchOAuth2Token,
80
+ fetchRemoteWorkspaceJson: () => fetchRemoteWorkspaceJson,
75
81
  findPathPlaceholders: () => findPathPlaceholders,
76
82
  generateAesKey: () => generateAesKey,
77
83
  generateCodeVerifier: () => generateCodeVerifier,
@@ -89,14 +95,18 @@ __export(src_exports, {
89
95
  hasUnpushedChanges: () => hasUnpushedChanges,
90
96
  importApicircleFolderInto: () => importApicircleFolderInto,
91
97
  importKey: () => importKey,
98
+ initSecretCrypto: () => initSecretCrypto,
92
99
  isApicircleEnvironment: () => isApicircleEnvironment,
93
100
  isApicircleFolderExport: () => isApicircleFolderExport,
94
101
  isDesktop: () => isDesktop,
102
+ isEmptyOverridePatch: () => isEmptyOverridePatch,
95
103
  isInsomniaExport: () => isInsomniaExport,
96
104
  isPostmanEnvironment: () => isPostmanEnvironment,
97
105
  isPostmanV2Collection: () => isPostmanV2Collection,
98
106
  isValidSemver: () => isValidSemver,
107
+ ledgerFromProbe: () => ledgerFromProbe,
99
108
  lookup: () => lookup,
109
+ mergeRequestOverride: () => mergeRequestOverride,
100
110
  mergeWithAutoHeaders: () => mergeWithAutoHeaders,
101
111
  normalizeContentType: () => normalizeContentType,
102
112
  parseApicircleEnvironment: () => parseApicircleEnvironment,
@@ -107,12 +117,15 @@ __export(src_exports, {
107
117
  parseDigestChallenge: () => parseDigestChallenge,
108
118
  parseGraphqlSchema: () => parseGraphqlSchema,
109
119
  parseInsomniaCollection: () => parseInsomniaCollection,
120
+ parseLinkedWorkspaceJson: () => parseLinkedWorkspaceJson,
110
121
  parseNtlmType2Challenge: () => parseNtlmType2Challenge,
111
122
  parsePostmanCollection: () => parsePostmanCollection,
112
123
  parsePostmanEnvironment: () => parsePostmanEnvironment,
124
+ parseRegistryActiveId: () => parseRegistryActiveId,
113
125
  parseSemver: () => parseSemver,
114
126
  parseUrlQuery: () => parseUrlQuery,
115
127
  parseWorkspaceJson: () => parseWorkspaceJson,
128
+ plaintextEnvMap: () => plaintextEnvMap,
116
129
  pollDeviceFlow: () => pollDeviceFlow,
117
130
  preSendValidation: () => preSendValidation,
118
131
  previewLinkedUpdate: () => previewLinkedUpdate,
@@ -125,6 +138,7 @@ __export(src_exports, {
125
138
  requestRunToExecutionResult: () => requestRunToExecutionResult,
126
139
  resolveInheritedAuth: () => resolveInheritedAuth,
127
140
  resolvePlanRef: () => resolvePlanRef,
141
+ resolveRequestForExecution: () => resolveRequestForExecution,
128
142
  resolveString: () => resolveString,
129
143
  resolveStringMap: () => resolveStringMap,
130
144
  runAssertions: () => runAssertions,
@@ -146,7 +160,9 @@ __export(src_exports, {
146
160
  toYaml: () => toYaml,
147
161
  tokenizeCurl: () => tokenizeCurl,
148
162
  tryParsePayload: () => tryParsePayload,
163
+ unlockSecretCrypto: () => unlockSecretCrypto,
149
164
  validateBranchName: () => validateBranchName,
165
+ workspaceJsonPath: () => workspaceJsonPath,
150
166
  yankRelease: () => yankRelease
151
167
  });
152
168
  module.exports = __toCommonJS(src_exports);
@@ -1207,8 +1223,7 @@ async function importPkcs8(pem, algorithm) {
1207
1223
  "JWT: PKCS#1 RSA PEM (`BEGIN RSA PRIVATE KEY`) is not supported. Convert with `openssl pkcs8 -topk8 -in key.pem -out pkcs8.pem -nocrypt`."
1208
1224
  );
1209
1225
  }
1210
- const envelope = /-----BEGIN [A-Z ]+-----([\s\S]*?)-----END [A-Z ]+-----/.exec(pem);
1211
- const body = envelope ? envelope[1] : pem;
1226
+ const body = extractPemBody(pem);
1212
1227
  const stripped = body.replace(/\s+/g, "");
1213
1228
  if (!stripped) {
1214
1229
  throw new Error("JWT: PEM key is empty after stripping headers/whitespace");
@@ -1229,6 +1244,19 @@ async function importPkcs8(pem, algorithm) {
1229
1244
  ["sign"]
1230
1245
  );
1231
1246
  }
1247
+ function extractPemBody(pem) {
1248
+ const BEGIN = "-----BEGIN ";
1249
+ const END = "-----END ";
1250
+ const FENCE = "-----";
1251
+ const beginAt = pem.indexOf(BEGIN);
1252
+ if (beginAt === -1) return pem;
1253
+ const beginHeaderEnd = pem.indexOf(FENCE, beginAt + BEGIN.length);
1254
+ if (beginHeaderEnd === -1) return pem;
1255
+ const bodyStart = beginHeaderEnd + FENCE.length;
1256
+ const endAt = pem.indexOf(END, bodyStart);
1257
+ if (endAt === -1) return pem;
1258
+ return pem.slice(bodyStart, endAt);
1259
+ }
1232
1260
  function base64UrlEncode(bytes) {
1233
1261
  let s = "";
1234
1262
  for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);
@@ -1683,6 +1711,10 @@ async function fetchOAuth2Token(args) {
1683
1711
  if (args.extraParams) {
1684
1712
  for (const [k, v] of Object.entries(args.extraParams)) body.set(k, v);
1685
1713
  }
1714
+ const tokenUrlParsed = new URL(args.tokenUrl);
1715
+ if (tokenUrlParsed.protocol !== "https:" && tokenUrlParsed.protocol !== "http:") {
1716
+ throw new Error(`Token URL must use HTTP or HTTPS, got ${tokenUrlParsed.protocol}`);
1717
+ }
1686
1718
  const response = await fetchImpl(args.tokenUrl, {
1687
1719
  method: "POST",
1688
1720
  headers,
@@ -2629,6 +2661,30 @@ function getVariableAutocomplete(text, cursorPosition, scope) {
2629
2661
  );
2630
2662
  }
2631
2663
 
2664
+ // src/request/resolveInheritedAuth.ts
2665
+ var NONE = { type: "none" };
2666
+ function resolveInheritedAuth({
2667
+ requestAuth,
2668
+ folderId,
2669
+ folders
2670
+ }) {
2671
+ if (requestAuth.type !== "inherit") return requestAuth;
2672
+ let cursor = folderId;
2673
+ const visited = /* @__PURE__ */ new Set();
2674
+ while (cursor !== null) {
2675
+ if (visited.has(cursor)) {
2676
+ break;
2677
+ }
2678
+ visited.add(cursor);
2679
+ const folder = folders[cursor];
2680
+ if (!folder) break;
2681
+ const auth = folder.auth;
2682
+ if (auth && auth.type !== "inherit" && auth.type !== "none") return auth;
2683
+ cursor = folder.parentId;
2684
+ }
2685
+ return NONE;
2686
+ }
2687
+
2632
2688
  // src/request/preSendValidation.ts
2633
2689
  var TYPED_BODY_CT = {
2634
2690
  json: ["application/json", "application/ld+json", "application/vnd.api+json"],
@@ -2641,7 +2697,8 @@ function collectMissing(value, scope) {
2641
2697
  }
2642
2698
  function preSendValidation({
2643
2699
  request,
2644
- scope
2700
+ scope,
2701
+ folders
2645
2702
  }) {
2646
2703
  const warnings = [];
2647
2704
  const blockers = [];
@@ -2716,29 +2773,43 @@ function preSendValidation({
2716
2773
  });
2717
2774
  }
2718
2775
  }
2719
- const auth = request.auth;
2776
+ let effectiveAuth = request.auth;
2777
+ let resolvedFromInherit = false;
2778
+ if (folders && effectiveAuth?.type === "inherit") {
2779
+ effectiveAuth = resolveInheritedAuth({
2780
+ requestAuth: { type: "inherit" },
2781
+ folderId: request.folderId,
2782
+ folders
2783
+ });
2784
+ resolvedFromInherit = true;
2785
+ }
2786
+ const auth = effectiveAuth;
2787
+ const inheritedNote = resolvedFromInherit ? " (resolved from folder-level auth)" : "";
2720
2788
  if (auth) {
2721
2789
  if (auth.type === "bearer" && !auth.token?.trim()) {
2722
- blockers.push({ kind: "auth-fields-missing", message: "Bearer token is empty." });
2790
+ blockers.push({
2791
+ kind: "auth-fields-missing",
2792
+ message: `Bearer token is empty.${inheritedNote}`
2793
+ });
2723
2794
  } else if (auth.type === "basic") {
2724
2795
  if (!auth.username?.trim() || !auth.password?.trim()) {
2725
2796
  blockers.push({
2726
2797
  kind: "auth-fields-missing",
2727
- message: "Basic auth requires both username and password."
2798
+ message: `Basic auth requires both username and password.${inheritedNote}`
2728
2799
  });
2729
2800
  }
2730
2801
  } else if (auth.type === "api-key") {
2731
2802
  if (!auth.key?.trim() || !auth.value?.trim()) {
2732
2803
  blockers.push({
2733
2804
  kind: "auth-fields-missing",
2734
- message: "API key auth requires both name and value."
2805
+ message: `API key auth requires both name and value.${inheritedNote}`
2735
2806
  });
2736
2807
  }
2737
2808
  } else if (auth.type === "custom-header") {
2738
2809
  if (!auth.key?.trim()) {
2739
2810
  blockers.push({
2740
2811
  kind: "auth-fields-missing",
2741
- message: "Custom header auth requires a header name."
2812
+ message: `Custom header auth requires a header name.${inheritedNote}`
2742
2813
  });
2743
2814
  }
2744
2815
  }
@@ -3125,6 +3196,15 @@ async function executeRequest(req, opts = {}) {
3125
3196
  );
3126
3197
  const redirectMode = isBrowserRuntime() ? "follow" : "manual";
3127
3198
  let currentUrl = builtRequest.url;
3199
+ try {
3200
+ const parsedUrl = new URL(currentUrl);
3201
+ if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
3202
+ throw new Error(`Unsupported URL scheme: ${parsedUrl.protocol}`);
3203
+ }
3204
+ } catch (e) {
3205
+ if (e instanceof Error && e.message.startsWith("Unsupported URL scheme")) throw e;
3206
+ throw new Error(`Invalid request URL: ${currentUrl}`);
3207
+ }
3128
3208
  let currentHeaders = { ...builtRequest.headers };
3129
3209
  let currentMethod = builtRequest.method;
3130
3210
  let currentBody = builtRequest.body;
@@ -3423,30 +3503,6 @@ function base64UrlEncode2(bytes) {
3423
3503
  return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
3424
3504
  }
3425
3505
 
3426
- // src/request/resolveInheritedAuth.ts
3427
- var NONE = { type: "none" };
3428
- function resolveInheritedAuth({
3429
- requestAuth,
3430
- folderId,
3431
- folders
3432
- }) {
3433
- if (requestAuth.type !== "inherit") return requestAuth;
3434
- let cursor = folderId;
3435
- const visited = /* @__PURE__ */ new Set();
3436
- while (cursor !== null) {
3437
- if (visited.has(cursor)) {
3438
- break;
3439
- }
3440
- visited.add(cursor);
3441
- const folder = folders[cursor];
3442
- if (!folder) break;
3443
- const auth = folder.auth;
3444
- if (auth && auth.type !== "inherit" && auth.type !== "none") return auth;
3445
- cursor = folder.parentId;
3446
- }
3447
- return NONE;
3448
- }
3449
-
3450
3506
  // src/request/parseCurl.ts
3451
3507
  var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
3452
3508
  function tokenizeCurl(input) {
@@ -3748,10 +3804,12 @@ function parsePostmanCollection(input) {
3748
3804
  items.forEach((item, idx) => {
3749
3805
  const pathIds = parentPathIds ? [...parentPathIds, idx] : [idx];
3750
3806
  if (Array.isArray(item.item)) {
3807
+ const folderAuth = item.auth ? parseAuth(item.auth, warnings, item.name) : void 0;
3751
3808
  folders.push({
3752
3809
  name: (item.name ?? "Untitled folder").trim() || "Untitled folder",
3753
3810
  pathIds,
3754
- parentPathIds
3811
+ parentPathIds,
3812
+ ...folderAuth && folderAuth.type !== "none" ? { auth: folderAuth } : {}
3755
3813
  });
3756
3814
  walk(item.item, pathIds);
3757
3815
  return;
@@ -3992,10 +4050,12 @@ function parseInsomniaCollection(input) {
3992
4050
  const parentPath = r.parentId ? folderIndexById.get(r.parentId) ?? null : null;
3993
4051
  const ourPath = parentPath ? [...parentPath, folderCounter++] : [folderCounter++];
3994
4052
  folderIndexById.set(r._id ?? "", ourPath);
4053
+ const folderAuth = r.authentication ? parseAuth2(r.authentication, warnings, r.name) : void 0;
3995
4054
  folders.push({
3996
4055
  name: (r.name ?? "Untitled folder").trim() || "Untitled folder",
3997
4056
  pathIds: ourPath,
3998
- parentPathIds: parentPath
4057
+ parentPathIds: parentPath,
4058
+ ...folderAuth && folderAuth.type !== "none" ? { auth: folderAuth } : {}
3999
4059
  });
4000
4060
  }
4001
4061
  const requests = [];
@@ -4396,7 +4456,7 @@ function serializeFolderExport(envelope) {
4396
4456
  return JSON.stringify(envelope, null, 2);
4397
4457
  }
4398
4458
  function suggestFolderExportFilename(envelope) {
4399
- const slug = envelope.folder.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4459
+ const slug = envelope.folder.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-/, "").replace(/-$/, "");
4400
4460
  const base = slug || "folder";
4401
4461
  return `${base}.apicircle.json`;
4402
4462
  }
@@ -5022,6 +5082,140 @@ function extractContext(result, extractions) {
5022
5082
  return { extracted, warnings };
5023
5083
  }
5024
5084
 
5085
+ // src/environment/resolveRequest.ts
5086
+ var import_shared2 = require("@apicircle/shared");
5087
+ function resolveRequestForExecution(args) {
5088
+ const refs = args.envPriorityOverride && args.envPriorityOverride.length > 0 ? args.envPriorityOverride : args.synced.environments.priorityOrder;
5089
+ const flatEnvs = {};
5090
+ for (const [name, vars] of Object.entries(args.localEnvs)) {
5091
+ flatEnvs[(0, import_shared2.envPriorityKey)({ kind: "local", name })] = vars;
5092
+ }
5093
+ for (const [linkId, byEnv] of Object.entries(args.linkedEnvs ?? {})) {
5094
+ for (const [envName, vars] of Object.entries(byEnv)) {
5095
+ flatEnvs[(0, import_shared2.envPriorityKey)({ kind: "linked", linkedWorkspaceId: linkId, envName })] = vars;
5096
+ }
5097
+ }
5098
+ const ctxMap = { ...args.globalContext ?? {} };
5099
+ for (const v of args.planVariables ?? []) {
5100
+ if (v.key) ctxMap[v.key] = v.value;
5101
+ }
5102
+ for (const v of args.request.contextVars) {
5103
+ if (v.key) ctxMap[v.key] = v.value;
5104
+ }
5105
+ const contextVars = Object.entries(ctxMap).map(([key, value]) => ({ key, value }));
5106
+ const scope = buildScope({
5107
+ contextVars,
5108
+ environments: flatEnvs,
5109
+ activeEnvName: null,
5110
+ // priorityOrder is the sole list the resolver consults.
5111
+ priorityOrder: refs.map(import_shared2.envPriorityKey),
5112
+ secrets: args.secrets ?? {}
5113
+ });
5114
+ const missing = /* @__PURE__ */ new Set();
5115
+ const interp = (s) => {
5116
+ const r = resolveString(s, scope);
5117
+ for (const m of r.missing) missing.add(m);
5118
+ return r.value;
5119
+ };
5120
+ const url = interp(args.request.url);
5121
+ const headers = args.request.headers.map((h) => ({
5122
+ ...h,
5123
+ key: interp(h.key),
5124
+ value: interp(h.value)
5125
+ }));
5126
+ const query = args.request.query.map((q) => ({
5127
+ ...q,
5128
+ key: interp(q.key),
5129
+ value: interp(q.value)
5130
+ }));
5131
+ let body = args.request.body;
5132
+ if (body.type === "json" || body.type === "text" || body.type === "xml" || body.type === "graphql" || body.type === "urlencoded") {
5133
+ body = { ...body, content: interp(body.content) };
5134
+ } else if (body.type === "form-data" && body.formRows) {
5135
+ body = {
5136
+ ...body,
5137
+ formRows: body.formRows.map(
5138
+ (row) => row.kind === "text" ? { ...row, key: interp(row.key), value: interp(row.value) } : { ...row, key: interp(row.key) }
5139
+ )
5140
+ };
5141
+ }
5142
+ const inheritedAuth = resolveInheritedAuth({
5143
+ requestAuth: args.request.auth ?? { type: "none" },
5144
+ folderId: args.request.folderId,
5145
+ folders: args.synced.collections.folders
5146
+ });
5147
+ const auth = interpolateAuthVariables(inheritedAuth, interp);
5148
+ return {
5149
+ request: { ...args.request, url, headers, query, body, auth },
5150
+ scope,
5151
+ missing: [...missing]
5152
+ };
5153
+ }
5154
+ function interpolateAuthVariables(auth, interp) {
5155
+ const resolved = {};
5156
+ for (const [key, value] of Object.entries(auth)) {
5157
+ resolved[key] = key !== "type" && typeof value === "string" ? interp(value) : value;
5158
+ }
5159
+ return resolved;
5160
+ }
5161
+ function applyLinkedEnvironmentOverrides(source, linkedWorkspaceId, synced) {
5162
+ const overrides = Object.values(synced.linkedOverrides.environmentVars).filter(
5163
+ (o) => o.linkedWorkspaceId === linkedWorkspaceId
5164
+ );
5165
+ if (overrides.length === 0) return source;
5166
+ const items = {};
5167
+ for (const [envName, env] of Object.entries(source.items)) {
5168
+ const envOverrides = overrides.filter((o) => o.envName === envName);
5169
+ if (envOverrides.length === 0) {
5170
+ items[envName] = env;
5171
+ continue;
5172
+ }
5173
+ const removed = new Set(envOverrides.filter((o) => o.removed).map((o) => o.varKey));
5174
+ const replaceMap = new Map(envOverrides.filter((o) => !o.removed).map((o) => [o.varKey, o]));
5175
+ const variables = [];
5176
+ const seenKeys = /* @__PURE__ */ new Set();
5177
+ for (const v of env.variables) {
5178
+ if (removed.has(v.key)) continue;
5179
+ const ov = replaceMap.get(v.key);
5180
+ if (ov) {
5181
+ variables.push({
5182
+ key: v.key,
5183
+ value: ov.value ?? v.value,
5184
+ encrypted: ov.encrypted ?? v.encrypted,
5185
+ ...ov.secretKeyId !== void 0 ? { secretKeyId: ov.secretKeyId } : v.secretKeyId !== void 0 ? { secretKeyId: v.secretKeyId } : {}
5186
+ });
5187
+ } else {
5188
+ variables.push(v);
5189
+ }
5190
+ seenKeys.add(v.key);
5191
+ }
5192
+ for (const ov of envOverrides) {
5193
+ if (ov.removed) continue;
5194
+ if (seenKeys.has(ov.varKey)) continue;
5195
+ variables.push({
5196
+ key: ov.varKey,
5197
+ value: ov.value ?? "",
5198
+ encrypted: ov.encrypted ?? false,
5199
+ ...ov.secretKeyId !== void 0 ? { secretKeyId: ov.secretKeyId } : {}
5200
+ });
5201
+ }
5202
+ items[envName] = { ...env, variables };
5203
+ }
5204
+ return { ...source, items };
5205
+ }
5206
+ function plaintextEnvMap(source) {
5207
+ const out = {};
5208
+ for (const [name, env] of Object.entries(source.items)) {
5209
+ const vars = {};
5210
+ for (const v of env.variables) {
5211
+ if (v.encrypted) continue;
5212
+ vars[v.key] = v.value;
5213
+ }
5214
+ out[name] = vars;
5215
+ }
5216
+ return out;
5217
+ }
5218
+
5025
5219
  // src/secrets/crypto.ts
5026
5220
  var IV_BYTES = 12;
5027
5221
  var SALT_BYTES = 16;
@@ -5106,6 +5300,95 @@ function base64ToBytes(b64) {
5106
5300
  return out;
5107
5301
  }
5108
5302
 
5303
+ // src/secrets/passphraseKey.ts
5304
+ var PBKDF2_HASH = "SHA-256";
5305
+ var PBKDF2_ITERATIONS2 = 12e5;
5306
+ var SALT_BYTES2 = 16;
5307
+ var VERIFIER_SENTINEL = "apicircle/passphrase-verifier/v1";
5308
+ function base64Encode2(bytes) {
5309
+ let binary = "";
5310
+ for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
5311
+ return btoa(binary);
5312
+ }
5313
+ function base64Decode2(b64) {
5314
+ const binary = atob(b64);
5315
+ const bytes = new Uint8Array(binary.length);
5316
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
5317
+ return bytes;
5318
+ }
5319
+ function utf8Bytes(s) {
5320
+ return new TextEncoder().encode(s);
5321
+ }
5322
+ async function deriveKey(passphrase, salt, iterations) {
5323
+ const baseKey = await crypto.subtle.importKey(
5324
+ "raw",
5325
+ utf8Bytes(passphrase),
5326
+ { name: "PBKDF2" },
5327
+ false,
5328
+ ["deriveKey"]
5329
+ );
5330
+ return crypto.subtle.deriveKey(
5331
+ {
5332
+ name: "PBKDF2",
5333
+ salt,
5334
+ iterations,
5335
+ hash: PBKDF2_HASH
5336
+ },
5337
+ baseKey,
5338
+ { name: "AES-GCM", length: 256 },
5339
+ /* extractable */
5340
+ false,
5341
+ ["encrypt", "decrypt"]
5342
+ );
5343
+ }
5344
+ async function computeVerifier(key) {
5345
+ const iv = new Uint8Array(12);
5346
+ const ct = await crypto.subtle.encrypt(
5347
+ { name: "AES-GCM", iv },
5348
+ key,
5349
+ utf8Bytes(VERIFIER_SENTINEL)
5350
+ );
5351
+ return base64Encode2(new Uint8Array(ct));
5352
+ }
5353
+ async function initSecretCrypto(passphrase, iterations = PBKDF2_ITERATIONS2) {
5354
+ if (passphrase.length === 0) throw new Error("Passphrase cannot be empty");
5355
+ if (iterations < 1) throw new Error("iterations must be >= 1");
5356
+ const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES2));
5357
+ const key = await deriveKey(passphrase, salt, iterations);
5358
+ const verifier = await computeVerifier(key);
5359
+ return {
5360
+ crypto: {
5361
+ kdf: "pbkdf2-sha256-v1",
5362
+ salt: base64Encode2(salt),
5363
+ iterations,
5364
+ verifier
5365
+ },
5366
+ key
5367
+ };
5368
+ }
5369
+ async function unlockSecretCrypto(passphrase, blob) {
5370
+ if (blob.kdf !== "pbkdf2-sha256-v1") {
5371
+ return { ok: false, reason: `Unsupported KDF: ${String(blob.kdf)}` };
5372
+ }
5373
+ let salt;
5374
+ try {
5375
+ salt = base64Decode2(blob.salt);
5376
+ } catch {
5377
+ return { ok: false, reason: "Workspace secret salt is corrupt." };
5378
+ }
5379
+ let key;
5380
+ try {
5381
+ key = await deriveKey(passphrase, salt, blob.iterations);
5382
+ } catch (err) {
5383
+ return { ok: false, reason: err instanceof Error ? err.message : "Key derivation failed" };
5384
+ }
5385
+ const verifier = await computeVerifier(key);
5386
+ if (verifier !== blob.verifier) {
5387
+ return { ok: false, reason: "Wrong passphrase." };
5388
+ }
5389
+ return { ok: true, key };
5390
+ }
5391
+
5109
5392
  // src/git/branchNames.ts
5110
5393
  var SLUG_FALLBACK = "workspace";
5111
5394
  var SUFFIX_LEN = 6;
@@ -5165,10 +5448,32 @@ function sortedReplacer(_key, value) {
5165
5448
 
5166
5449
  // src/git/repoPaths.ts
5167
5450
  var WORKSPACE_DIR = ".apicircle";
5168
- var WORKSPACE_JSON_PATH = `${WORKSPACE_DIR}/workspace.json`;
5169
- var ATTACHMENTS_DIR = `${WORKSPACE_DIR}/attachments`;
5170
- function attachmentPath(slotId) {
5171
- return `${ATTACHMENTS_DIR}/${slotId}`;
5451
+ var REGISTRY_JSON_PATH = `${WORKSPACE_DIR}/registry.json`;
5452
+ function workspaceJsonPath(workspaceId) {
5453
+ return `${WORKSPACE_DIR}/workspace-${workspaceId}/workspace.json`;
5454
+ }
5455
+ function attachmentsDir(workspaceId) {
5456
+ return `${WORKSPACE_DIR}/workspace-${workspaceId}/attachments`;
5457
+ }
5458
+ function attachmentPath(workspaceId, slotId) {
5459
+ return `${attachmentsDir(workspaceId)}/${slotId}`;
5460
+ }
5461
+ function parseRegistryActiveId(registryJsonContent) {
5462
+ try {
5463
+ const parsed = JSON.parse(registryJsonContent);
5464
+ return parsed.activeWorkspaceId ?? parsed.workspaces?.[0]?.id ?? null;
5465
+ } catch {
5466
+ return null;
5467
+ }
5468
+ }
5469
+ async function fetchRemoteWorkspaceJson(fetchFile) {
5470
+ const registryContent = await fetchFile(REGISTRY_JSON_PATH);
5471
+ if (registryContent === null) return { error: "No .apicircle/registry.json found in repo" };
5472
+ const wsId = parseRegistryActiveId(registryContent);
5473
+ if (!wsId) return { error: "Registry is empty \u2014 no workspaces found" };
5474
+ const wsContent = await fetchFile(workspaceJsonPath(wsId));
5475
+ if (wsContent === null) return { error: `No workspace.json at .apicircle/workspace-${wsId}/` };
5476
+ return { workspaceId: wsId, content: wsContent };
5172
5477
  }
5173
5478
 
5174
5479
  // src/git/parseWorkspaceJson.ts
@@ -5427,18 +5732,14 @@ function sortVersionsDesc(versions) {
5427
5732
  }
5428
5733
 
5429
5734
  // src/release/publishRelease.ts
5430
- async function publishRelease(synced, args) {
5735
+ async function buildReleaseEntry(synced, args) {
5431
5736
  const version = args.version.trim();
5432
5737
  if (!isValidSemver(version)) {
5433
5738
  throw new Error(`Invalid semver: ${args.version}`);
5434
5739
  }
5435
- const ledger = synced.releases.self ?? emptyLedger();
5436
- if (ledger.versions.some((v) => v.version === version)) {
5437
- throw new Error(`Version ${version} already exists in this workspace's release ledger`);
5438
- }
5439
5740
  const snapshotSource = serializeWorkspaceForGit(synced);
5440
5741
  const workspaceSnapshot = await sha256Hex2(snapshotSource);
5441
- const entry = {
5742
+ return {
5442
5743
  version,
5443
5744
  publishedAt: args.publishedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
5444
5745
  notes: args.notes,
@@ -5448,23 +5749,36 @@ async function publishRelease(synced, args) {
5448
5749
  ...args.sha ? { sha: args.sha } : {},
5449
5750
  ...args.tagName ? { tagName: args.tagName } : {}
5450
5751
  };
5752
+ }
5753
+ function appendReleaseEntry(synced, entry, now = entry.publishedAt) {
5754
+ if (!isValidSemver(entry.version)) {
5755
+ throw new Error(`Invalid semver: ${entry.version}`);
5756
+ }
5757
+ const ledger = synced.releases.self ?? emptyLedger();
5758
+ if (ledger.versions.some((v) => v.version === entry.version)) {
5759
+ throw new Error(`Version ${entry.version} already exists in this workspace's release ledger`);
5760
+ }
5451
5761
  const next = {
5452
5762
  versions: [...ledger.versions, entry],
5453
- currentVersion: version
5763
+ currentVersion: entry.version
5454
5764
  };
5455
5765
  return {
5456
5766
  ...synced,
5457
5767
  releases: { ...synced.releases, self: next },
5458
- meta: { ...synced.meta, updatedAt: entry.publishedAt }
5768
+ meta: { ...synced.meta, updatedAt: now }
5459
5769
  };
5460
5770
  }
5461
- function deprecateRelease(synced, version) {
5462
- return mapReleaseVersion(synced, version, (v) => ({ ...v, deprecated: true }));
5771
+ async function publishRelease(synced, args) {
5772
+ const entry = await buildReleaseEntry(synced, args);
5773
+ return appendReleaseEntry(synced, entry);
5774
+ }
5775
+ function deprecateRelease(synced, version, now = (/* @__PURE__ */ new Date()).toISOString()) {
5776
+ return mapReleaseVersion(synced, version, (v) => ({ ...v, deprecated: true }), now);
5463
5777
  }
5464
- function yankRelease(synced, version) {
5465
- return mapReleaseVersion(synced, version, (v) => ({ ...v, yanked: true }));
5778
+ function yankRelease(synced, version, now = (/* @__PURE__ */ new Date()).toISOString()) {
5779
+ return mapReleaseVersion(synced, version, (v) => ({ ...v, yanked: true }), now);
5466
5780
  }
5467
- function mapReleaseVersion(synced, version, fn) {
5781
+ function mapReleaseVersion(synced, version, fn, now) {
5468
5782
  const ledger = synced.releases.self;
5469
5783
  if (!ledger) throw new Error("No releases to modify");
5470
5784
  const idx = ledger.versions.findIndex((v) => v.version === version);
@@ -5474,7 +5788,7 @@ function mapReleaseVersion(synced, version, fn) {
5474
5788
  return {
5475
5789
  ...synced,
5476
5790
  releases: { ...synced.releases, self: { ...ledger, versions } },
5477
- meta: { ...synced.meta, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }
5791
+ meta: { ...synced.meta, updatedAt: now }
5478
5792
  };
5479
5793
  }
5480
5794
  function emptyLedger() {
@@ -5486,6 +5800,99 @@ async function sha256Hex2(text) {
5486
5800
  return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
5487
5801
  }
5488
5802
 
5803
+ // src/linked/linkedSnapshot.ts
5804
+ var LINKED_FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
5805
+ var MAX_LINKED_JSON_BYTES = 16 * 1024 * 1024;
5806
+ function parseLinkedWorkspaceJson(text) {
5807
+ if (text.length > MAX_LINKED_JSON_BYTES) {
5808
+ throw new Error("Remote workspace.json exceeds 16 MiB");
5809
+ }
5810
+ let raw;
5811
+ try {
5812
+ raw = JSON.parse(
5813
+ text,
5814
+ (key, value) => LINKED_FORBIDDEN_KEYS.has(key) ? void 0 : value
5815
+ );
5816
+ } catch {
5817
+ throw new Error("Remote workspace.json is not valid JSON");
5818
+ }
5819
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
5820
+ throw new Error("Remote workspace.json is not an object");
5821
+ }
5822
+ const obj = raw;
5823
+ const asObject = (v) => typeof v === "object" && v !== null ? v : void 0;
5824
+ return {
5825
+ workspaceId: typeof obj.workspaceId === "string" ? obj.workspaceId : void 0,
5826
+ releases: asObject(obj.releases),
5827
+ collections: asObject(obj.collections),
5828
+ environments: asObject(obj.environments),
5829
+ secretKeys: asObject(obj.secretKeys),
5830
+ globalAssets: asObject(obj.globalAssets)
5831
+ };
5832
+ }
5833
+ function ledgerFromProbe(parsed) {
5834
+ return parsed.releases?.self ?? { versions: [], currentVersion: null };
5835
+ }
5836
+ function buildLinkedSnapshot(parsed, link) {
5837
+ if (!parsed.collections && !parsed.environments) return null;
5838
+ return {
5839
+ pulledAt: link.linkedAt,
5840
+ ref: link.pinnedVersion ? `v${link.pinnedVersion}` : `HEAD@${link.source.branch}`,
5841
+ collections: parsed.collections ?? {
5842
+ tree: { id: "remote-root", type: "root", children: [] },
5843
+ requests: {},
5844
+ folders: {}
5845
+ },
5846
+ environments: parsed.environments ?? {
5847
+ items: {},
5848
+ activeName: null,
5849
+ priorityOrder: []
5850
+ },
5851
+ ...parsed.secretKeys ? { secretKeys: parsed.secretKeys } : {},
5852
+ ...parsed.globalAssets ? { globalAssets: parsed.globalAssets } : {}
5853
+ };
5854
+ }
5855
+
5856
+ // src/linked/requestOverride.ts
5857
+ var OVERRIDABLE_FIELDS = [
5858
+ "name",
5859
+ "method",
5860
+ "url",
5861
+ "headers",
5862
+ "query",
5863
+ "pathParams",
5864
+ "cookies",
5865
+ "body",
5866
+ "auth",
5867
+ "contextVars",
5868
+ "extractions",
5869
+ "assertions"
5870
+ ];
5871
+ function mergeRequestOverride(base, patch) {
5872
+ const merged = { ...base };
5873
+ const p = patch;
5874
+ const target = merged;
5875
+ for (const field of OVERRIDABLE_FIELDS) {
5876
+ if (p[field] !== void 0) target[field] = p[field];
5877
+ }
5878
+ return merged;
5879
+ }
5880
+ function computeRequestOverridePatch(base, effective) {
5881
+ const baseRec = { ...base };
5882
+ const effRec = { ...effective };
5883
+ const patch = {};
5884
+ const patchRec = patch;
5885
+ for (const field of OVERRIDABLE_FIELDS) {
5886
+ if (JSON.stringify(baseRec[field]) !== JSON.stringify(effRec[field])) {
5887
+ patchRec[field] = effRec[field];
5888
+ }
5889
+ }
5890
+ return patch;
5891
+ }
5892
+ function isEmptyOverridePatch(patch) {
5893
+ return Object.keys(patch).filter((k) => OVERRIDABLE_FIELDS.includes(k)).length === 0;
5894
+ }
5895
+
5489
5896
  // src/editors/contentTypeLanguageMap.ts
5490
5897
  var CONTENT_TYPE_LANGUAGE_MAP = {
5491
5898
  "application/json": "json",
@@ -6418,7 +6825,8 @@ function previewLinkedUpdate(args) {
6418
6825
  status,
6419
6826
  base,
6420
6827
  target,
6421
- override
6828
+ override,
6829
+ ...status === "both-changed" && base && target && override ? { autoMergeable: requestOverrideIsDisjoint(base, target, override) } : {}
6422
6830
  });
6423
6831
  }
6424
6832
  const baseFolders = args.base?.collections.folders ?? {};
@@ -6498,6 +6906,34 @@ function classifyRequest(base, target, override) {
6498
6906
  if (sourceChanged && !hasOverride) return "source-only";
6499
6907
  return "both-changed";
6500
6908
  }
6909
+ var OVERRIDABLE_REQUEST_FIELDS = [
6910
+ "name",
6911
+ "method",
6912
+ "url",
6913
+ "headers",
6914
+ "query",
6915
+ "pathParams",
6916
+ "cookies",
6917
+ "body",
6918
+ "auth",
6919
+ "contextVars",
6920
+ "extractions",
6921
+ "assertions"
6922
+ ];
6923
+ function requestOverrideIsDisjoint(base, target, override) {
6924
+ const baseRec = { ...base };
6925
+ const targetRec = { ...target };
6926
+ const overriddenFields = Object.keys(override.patch);
6927
+ for (const f of overriddenFields) {
6928
+ if (!OVERRIDABLE_REQUEST_FIELDS.includes(f)) {
6929
+ continue;
6930
+ }
6931
+ if (!structurallyEqual2(baseRec[f], targetRec[f])) {
6932
+ return false;
6933
+ }
6934
+ }
6935
+ return true;
6936
+ }
6501
6937
  function classifyFolder(base, target) {
6502
6938
  if (!base && target) return "new-in-source";
6503
6939
  if (base && !target) return "removed-in-source";
@@ -6547,7 +6983,7 @@ function applyLinkedUpdate(args) {
6547
6983
  continue;
6548
6984
  }
6549
6985
  if (entry.status === "both-changed") {
6550
- const choice = args.resolutions[id];
6986
+ const choice = args.resolutions[id] ?? (entry.autoMergeable ? "mine" : void 0);
6551
6987
  if (!choice) {
6552
6988
  throw new Error(
6553
6989
  `applyLinkedUpdate: unresolved both-changed entry "${entry.label}" (${id})`
@@ -6558,7 +6994,8 @@ function applyLinkedUpdate(args) {
6558
6994
  else if (entry.bucket === "environment-var") envVarOverridesByKey.delete(entry.key);
6559
6995
  log.push({ entryKey: id, bucket: entry.bucket, action: "accept-source" });
6560
6996
  } else {
6561
- log.push({ entryKey: id, bucket: entry.bucket, action: "keep-mine" });
6997
+ const auto = entry.autoMergeable === true && !args.resolutions[id];
6998
+ log.push({ entryKey: id, bucket: entry.bucket, action: auto ? "auto-merge" : "keep-mine" });
6562
6999
  }
6563
7000
  }
6564
7001
  }
@@ -6574,7 +7011,7 @@ function structurallyEqual2(a, b) {
6574
7011
  }
6575
7012
 
6576
7013
  // src/workspace/applyMutation.ts
6577
- var import_shared2 = require("@apicircle/shared");
7014
+ var import_shared3 = require("@apicircle/shared");
6578
7015
 
6579
7016
  // src/workspace/apicircleFolderImport.ts
6580
7017
  function importApicircleFolderInto(synced, parsed, parentFolderId) {
@@ -6815,6 +7252,8 @@ function applyMutation(state, patch, options = {}) {
6815
7252
  return applyFolderDelete(state, patch.id, now);
6816
7253
  case "folder.move":
6817
7254
  return applyFolderMove(state, patch.id, patch.newParentId, now);
7255
+ case "folder.update":
7256
+ return applyFolderUpdate(state, patch.id, patch.patch, now);
6818
7257
  case "folder.import_apicircle":
6819
7258
  return applyFolderImportApicircle(state, patch.parsed, patch.parentFolderId, now);
6820
7259
  case "environment.upsert":
@@ -6827,6 +7266,10 @@ function applyMutation(state, patch, options = {}) {
6827
7266
  return applyEnvSetPriority(state, patch.order, now);
6828
7267
  case "secretKey.upsert":
6829
7268
  return applySecretKeyUpsert(state, patch.meta, now);
7269
+ case "secret.crypto.set":
7270
+ return applySecretCryptoSet(state, patch.crypto, now);
7271
+ case "secret.crypto.clear":
7272
+ return applySecretCryptoClear(state, now);
6830
7273
  case "assertion.upsert":
6831
7274
  return applyAssertionUpsert(state, patch.requestId, patch.assertion, now);
6832
7275
  case "assertion.delete":
@@ -6835,6 +7278,34 @@ function applyMutation(state, patch, options = {}) {
6835
7278
  return applyMockUpsert(state, patch.mock, now);
6836
7279
  case "mock.delete":
6837
7280
  return applyMockDelete(state, patch.id, now);
7281
+ case "release.publish":
7282
+ return applyReleasePublish(state, patch.entry, now);
7283
+ case "release.deprecate":
7284
+ return applyReleaseDeprecate(state, patch.version, now);
7285
+ case "release.yank":
7286
+ return applyReleaseYank(state, patch.version, now);
7287
+ case "linkedWorkspace.upsert":
7288
+ return applyLinkedWorkspaceUpsert(state, patch.link, patch.ledger, patch.snapshot, now);
7289
+ case "linkedWorkspace.remove":
7290
+ return applyLinkedWorkspaceRemove(state, patch.id, now);
7291
+ case "linkedWorkspace.applyUpdate":
7292
+ return applyLinkedWorkspaceApplyUpdate(state, patch, now);
7293
+ case "linkedOverride.setRequest":
7294
+ return applyLinkedOverrideSetRequest(state, patch.override, now);
7295
+ case "linkedOverride.removeRequest":
7296
+ return applyLinkedOverrideRemoveRequest(state, patch.linkedWorkspaceId, patch.itemId, now);
7297
+ case "linkedOverride.setEnvVar":
7298
+ return applyLinkedOverrideSetEnvVar(state, patch.override, now);
7299
+ case "linkedOverride.removeEnvVar":
7300
+ return applyLinkedOverrideRemoveEnvVar(
7301
+ state,
7302
+ patch.linkedWorkspaceId,
7303
+ patch.envName,
7304
+ patch.varKey,
7305
+ now
7306
+ );
7307
+ case "linkedOverride.clearForLink":
7308
+ return applyLinkedOverrideClearForLink(state, patch.linkedWorkspaceId, now);
6838
7309
  case "globalAsset.upsertFile":
6839
7310
  return applyGlobalAssetUpsertFile(state, patch.file, now);
6840
7311
  case "globalAsset.removeFile":
@@ -6871,12 +7342,13 @@ function applyRequestCreate(state, request, now) {
6871
7342
  if (state.synced.collections.requests[request.id]) {
6872
7343
  return { next: state, changedIds: [] };
6873
7344
  }
7345
+ const tree = request.folderId ? state.synced.collections.tree : pushTreeChild(state.synced.collections.tree, { kind: "request", id: request.id });
6874
7346
  const synced = {
6875
7347
  ...state.synced,
6876
7348
  collections: {
6877
7349
  ...state.synced.collections,
6878
7350
  requests: { ...state.synced.collections.requests, [request.id]: request },
6879
- tree: pushTreeChild(state.synced.collections.tree, { kind: "request", id: request.id })
7351
+ tree
6880
7352
  },
6881
7353
  meta: { ...state.synced.meta, updatedAt: now }
6882
7354
  };
@@ -6925,12 +7397,13 @@ function applyFolderCreate(state, folder, now) {
6925
7397
  if (state.synced.collections.folders[folder.id]) {
6926
7398
  return { next: state, changedIds: [] };
6927
7399
  }
7400
+ const tree = folder.parentId ? state.synced.collections.tree : pushTreeChild(state.synced.collections.tree, { kind: "folder", id: folder.id });
6928
7401
  const synced = {
6929
7402
  ...state.synced,
6930
7403
  collections: {
6931
7404
  ...state.synced.collections,
6932
7405
  folders: { ...state.synced.collections.folders, [folder.id]: folder },
6933
- tree: pushTreeChild(state.synced.collections.tree, { kind: "folder", id: folder.id })
7406
+ tree
6934
7407
  },
6935
7408
  meta: { ...state.synced.meta, updatedAt: now }
6936
7409
  };
@@ -6999,6 +7472,57 @@ function applyFolderMove(state, id, newParentId, now) {
6999
7472
  };
7000
7473
  return { next: { ...state, synced }, changedIds: [id] };
7001
7474
  }
7475
+ function applyFolderUpdate(state, id, patch, now) {
7476
+ const folder = state.synced.collections.folders[id];
7477
+ if (!folder) {
7478
+ return { next: state, changedIds: [] };
7479
+ }
7480
+ const nameChanging = "name" in patch && patch.name !== void 0;
7481
+ const authChanging = "auth" in patch;
7482
+ if (!nameChanging && !authChanging) {
7483
+ return { next: state, changedIds: [] };
7484
+ }
7485
+ let nextName = folder.name;
7486
+ if (nameChanging) {
7487
+ const trimmed = patch.name.trim();
7488
+ if (!trimmed) {
7489
+ } else if (trimmed === folder.name) {
7490
+ } else if (!isFolderNameUnique(state, folder.parentId, trimmed, id)) {
7491
+ return { next: state, changedIds: [] };
7492
+ } else {
7493
+ nextName = trimmed;
7494
+ }
7495
+ }
7496
+ const nextFolder = { ...folder, name: nextName };
7497
+ if (authChanging) {
7498
+ if (patch.auth === void 0) {
7499
+ delete nextFolder.auth;
7500
+ } else {
7501
+ nextFolder.auth = patch.auth;
7502
+ }
7503
+ }
7504
+ if (nextFolder.name === folder.name && nextFolder.auth === folder.auth) {
7505
+ return { next: state, changedIds: [] };
7506
+ }
7507
+ const synced = {
7508
+ ...state.synced,
7509
+ collections: {
7510
+ ...state.synced.collections,
7511
+ folders: { ...state.synced.collections.folders, [id]: nextFolder }
7512
+ },
7513
+ meta: { ...state.synced.meta, updatedAt: now }
7514
+ };
7515
+ return { next: { ...state, synced }, changedIds: [id] };
7516
+ }
7517
+ function isFolderNameUnique(state, parentId, trimmedCandidate, ignoreId) {
7518
+ const target = trimmedCandidate.toLowerCase();
7519
+ for (const f of Object.values(state.synced.collections.folders)) {
7520
+ if (f.id === ignoreId) continue;
7521
+ if (f.parentId !== parentId) continue;
7522
+ if (f.name.trim().toLowerCase() === target) return false;
7523
+ }
7524
+ return true;
7525
+ }
7002
7526
  function applyFolderImportApicircle(state, parsed, parentFolderId, now) {
7003
7527
  const result = importApicircleFolderInto(
7004
7528
  state.synced,
@@ -7078,7 +7602,7 @@ function applyEnvSetPriority(state, order, now) {
7078
7602
  const knownLocal = new Set(Object.keys(state.synced.environments.items));
7079
7603
  const seen = /* @__PURE__ */ new Set();
7080
7604
  const filtered = order.filter((ref) => {
7081
- const key = (0, import_shared2.envPriorityKey)(ref);
7605
+ const key = (0, import_shared3.envPriorityKey)(ref);
7082
7606
  if (seen.has(key)) return false;
7083
7607
  if (ref.kind === "local" && !knownLocal.has(ref.name)) return false;
7084
7608
  seen.add(key);
@@ -7089,7 +7613,7 @@ function applyEnvSetPriority(state, order, now) {
7089
7613
  environments: { ...state.synced.environments, priorityOrder: filtered },
7090
7614
  meta: { ...state.synced.meta, updatedAt: now }
7091
7615
  };
7092
- return { next: { ...state, synced }, changedIds: filtered.map(import_shared2.envPriorityKey) };
7616
+ return { next: { ...state, synced }, changedIds: filtered.map(import_shared3.envPriorityKey) };
7093
7617
  }
7094
7618
  function applySecretKeyUpsert(state, meta, now) {
7095
7619
  if (!meta.id || !meta.label.trim() || !meta.salt) {
@@ -7105,6 +7629,28 @@ function applySecretKeyUpsert(state, meta, now) {
7105
7629
  };
7106
7630
  return { next: { ...state, synced }, changedIds: [meta.id] };
7107
7631
  }
7632
+ function applySecretCryptoSet(state, crypto2, now) {
7633
+ if (!crypto2 || crypto2.kdf !== "pbkdf2-sha256-v1" || !crypto2.salt || !crypto2.verifier || !(crypto2.iterations >= 1)) {
7634
+ return { next: state, changedIds: [] };
7635
+ }
7636
+ const synced = {
7637
+ ...state.synced,
7638
+ secretCrypto: { ...crypto2 },
7639
+ meta: { ...state.synced.meta, updatedAt: now }
7640
+ };
7641
+ return { next: { ...state, synced }, changedIds: ["secret.crypto"] };
7642
+ }
7643
+ function applySecretCryptoClear(state, now) {
7644
+ if (!state.synced.secretCrypto) {
7645
+ return { next: state, changedIds: [] };
7646
+ }
7647
+ const synced = {
7648
+ ...state.synced,
7649
+ secretCrypto: null,
7650
+ meta: { ...state.synced.meta, updatedAt: now }
7651
+ };
7652
+ return { next: { ...state, synced }, changedIds: ["secret.crypto"] };
7653
+ }
7108
7654
  function applyAssertionUpsert(state, requestId, assertion, now) {
7109
7655
  const request = state.synced.collections.requests[requestId];
7110
7656
  if (!request) {
@@ -7162,6 +7708,191 @@ function applyMockDelete(state, id, now) {
7162
7708
  } : state.local;
7163
7709
  return { next: { synced, local }, changedIds: [id] };
7164
7710
  }
7711
+ function applyReleasePublish(state, entry, now) {
7712
+ const synced = appendReleaseEntry(state.synced, entry, now);
7713
+ return { next: { ...state, synced }, changedIds: [entry.version] };
7714
+ }
7715
+ function applyReleaseDeprecate(state, version, now) {
7716
+ const synced = deprecateRelease(state.synced, version, now);
7717
+ return { next: { ...state, synced }, changedIds: [version] };
7718
+ }
7719
+ function applyReleaseYank(state, version, now) {
7720
+ const synced = yankRelease(state.synced, version, now);
7721
+ return { next: { ...state, synced }, changedIds: [version] };
7722
+ }
7723
+ function applyLinkedWorkspaceUpsert(state, link, ledger, snapshot2, now) {
7724
+ const synced = {
7725
+ ...state.synced,
7726
+ linkedWorkspaces: { ...state.synced.linkedWorkspaces, [link.id]: link },
7727
+ releases: ledger ? {
7728
+ ...state.synced.releases,
7729
+ perLink: { ...state.synced.releases.perLink, [link.id]: ledger }
7730
+ } : state.synced.releases,
7731
+ meta: { ...state.synced.meta, updatedAt: now }
7732
+ };
7733
+ const local = snapshot2 ? {
7734
+ ...state.local,
7735
+ linkedCollections: { ...state.local.linkedCollections, [link.id]: snapshot2 }
7736
+ } : state.local;
7737
+ return { next: { synced, local }, changedIds: [link.id] };
7738
+ }
7739
+ function applyLinkedWorkspaceRemove(state, id, now) {
7740
+ if (!state.synced.linkedWorkspaces[id]) {
7741
+ return { next: state, changedIds: [] };
7742
+ }
7743
+ const linkedWorkspaces = { ...state.synced.linkedWorkspaces };
7744
+ delete linkedWorkspaces[id];
7745
+ const perLink = { ...state.synced.releases.perLink };
7746
+ delete perLink[id];
7747
+ const prefix = `${id}:`;
7748
+ const dropPrefixed = (map) => Object.fromEntries(Object.entries(map).filter(([k]) => !k.startsWith(prefix)));
7749
+ const synced = {
7750
+ ...state.synced,
7751
+ linkedWorkspaces,
7752
+ releases: { ...state.synced.releases, perLink },
7753
+ linkedOverrides: {
7754
+ requests: dropPrefixed(state.synced.linkedOverrides.requests),
7755
+ environmentVars: dropPrefixed(state.synced.linkedOverrides.environmentVars)
7756
+ },
7757
+ meta: { ...state.synced.meta, updatedAt: now }
7758
+ };
7759
+ const linkedCollections = { ...state.local.linkedCollections };
7760
+ delete linkedCollections[id];
7761
+ const githubLinks = { ...state.local.sessions.github.links };
7762
+ delete githubLinks[id];
7763
+ const local = {
7764
+ ...state.local,
7765
+ linkedCollections,
7766
+ sessions: {
7767
+ ...state.local.sessions,
7768
+ github: { ...state.local.sessions.github, links: githubLinks }
7769
+ }
7770
+ };
7771
+ return { next: { synced, local }, changedIds: [id] };
7772
+ }
7773
+ function applyLinkedWorkspaceApplyUpdate(state, patch, now) {
7774
+ const link = state.synced.linkedWorkspaces[patch.id];
7775
+ if (!link) {
7776
+ return { next: state, changedIds: [] };
7777
+ }
7778
+ const prefix = `${patch.id}:`;
7779
+ const otherRequests = Object.fromEntries(
7780
+ Object.entries(state.synced.linkedOverrides.requests).filter(([k]) => !k.startsWith(prefix))
7781
+ );
7782
+ for (const o of patch.requestOverrides) {
7783
+ otherRequests[`${o.linkedWorkspaceId}:${o.itemId}`] = o;
7784
+ }
7785
+ const otherEnvVars = Object.fromEntries(
7786
+ Object.entries(state.synced.linkedOverrides.environmentVars).filter(
7787
+ ([k]) => !k.startsWith(prefix)
7788
+ )
7789
+ );
7790
+ for (const o of patch.envVarOverrides) {
7791
+ otherEnvVars[`${o.linkedWorkspaceId}:${o.envName}:${o.varKey}`] = o;
7792
+ }
7793
+ const synced = {
7794
+ ...state.synced,
7795
+ linkedWorkspaces: {
7796
+ ...state.synced.linkedWorkspaces,
7797
+ [patch.id]: { ...link, pinnedVersion: patch.pinnedVersion }
7798
+ },
7799
+ releases: {
7800
+ ...state.synced.releases,
7801
+ perLink: { ...state.synced.releases.perLink, [patch.id]: patch.ledger }
7802
+ },
7803
+ linkedOverrides: { requests: otherRequests, environmentVars: otherEnvVars },
7804
+ meta: { ...state.synced.meta, updatedAt: now }
7805
+ };
7806
+ const local = {
7807
+ ...state.local,
7808
+ linkedCollections: { ...state.local.linkedCollections, [patch.id]: patch.snapshot }
7809
+ };
7810
+ return { next: { synced, local }, changedIds: [patch.id] };
7811
+ }
7812
+ function applyLinkedOverrideSetRequest(state, override, now) {
7813
+ const key = `${override.linkedWorkspaceId}:${override.itemId}`;
7814
+ const synced = {
7815
+ ...state.synced,
7816
+ linkedOverrides: {
7817
+ ...state.synced.linkedOverrides,
7818
+ requests: {
7819
+ ...state.synced.linkedOverrides.requests,
7820
+ [key]: { ...override, updatedAt: now }
7821
+ }
7822
+ },
7823
+ meta: { ...state.synced.meta, updatedAt: now }
7824
+ };
7825
+ return { next: { ...state, synced }, changedIds: [key] };
7826
+ }
7827
+ function applyLinkedOverrideRemoveRequest(state, linkedWorkspaceId, itemId, now) {
7828
+ const key = `${linkedWorkspaceId}:${itemId}`;
7829
+ if (!state.synced.linkedOverrides.requests[key]) {
7830
+ return { next: state, changedIds: [] };
7831
+ }
7832
+ const requests = { ...state.synced.linkedOverrides.requests };
7833
+ delete requests[key];
7834
+ const synced = {
7835
+ ...state.synced,
7836
+ linkedOverrides: { ...state.synced.linkedOverrides, requests },
7837
+ meta: { ...state.synced.meta, updatedAt: now }
7838
+ };
7839
+ return { next: { ...state, synced }, changedIds: [key] };
7840
+ }
7841
+ function applyLinkedOverrideSetEnvVar(state, override, now) {
7842
+ const key = `${override.linkedWorkspaceId}:${override.envName}:${override.varKey}`;
7843
+ const synced = {
7844
+ ...state.synced,
7845
+ linkedOverrides: {
7846
+ ...state.synced.linkedOverrides,
7847
+ environmentVars: {
7848
+ ...state.synced.linkedOverrides.environmentVars,
7849
+ [key]: { ...override, updatedAt: now }
7850
+ }
7851
+ },
7852
+ meta: { ...state.synced.meta, updatedAt: now }
7853
+ };
7854
+ return { next: { ...state, synced }, changedIds: [key] };
7855
+ }
7856
+ function applyLinkedOverrideRemoveEnvVar(state, linkedWorkspaceId, envName, varKey, now) {
7857
+ const key = `${linkedWorkspaceId}:${envName}:${varKey}`;
7858
+ if (!state.synced.linkedOverrides.environmentVars[key]) {
7859
+ return { next: state, changedIds: [] };
7860
+ }
7861
+ const environmentVars = { ...state.synced.linkedOverrides.environmentVars };
7862
+ delete environmentVars[key];
7863
+ const synced = {
7864
+ ...state.synced,
7865
+ linkedOverrides: { ...state.synced.linkedOverrides, environmentVars },
7866
+ meta: { ...state.synced.meta, updatedAt: now }
7867
+ };
7868
+ return { next: { ...state, synced }, changedIds: [key] };
7869
+ }
7870
+ function applyLinkedOverrideClearForLink(state, linkedWorkspaceId, now) {
7871
+ const prefix = `${linkedWorkspaceId}:`;
7872
+ const requestKeys = Object.keys(state.synced.linkedOverrides.requests).filter(
7873
+ (k) => k.startsWith(prefix)
7874
+ );
7875
+ const envKeys = Object.keys(state.synced.linkedOverrides.environmentVars).filter(
7876
+ (k) => k.startsWith(prefix)
7877
+ );
7878
+ if (requestKeys.length === 0 && envKeys.length === 0) {
7879
+ return { next: state, changedIds: [] };
7880
+ }
7881
+ const requests = Object.fromEntries(
7882
+ Object.entries(state.synced.linkedOverrides.requests).filter(([k]) => !k.startsWith(prefix))
7883
+ );
7884
+ const environmentVars = Object.fromEntries(
7885
+ Object.entries(state.synced.linkedOverrides.environmentVars).filter(
7886
+ ([k]) => !k.startsWith(prefix)
7887
+ )
7888
+ );
7889
+ const synced = {
7890
+ ...state.synced,
7891
+ linkedOverrides: { requests, environmentVars },
7892
+ meta: { ...state.synced.meta, updatedAt: now }
7893
+ };
7894
+ return { next: { ...state, synced }, changedIds: [...requestKeys, ...envKeys] };
7895
+ }
7165
7896
  function applyGlobalAssetUpsertFile(state, file, now) {
7166
7897
  const files = state.synced.globalAssets.files ?? {};
7167
7898
  const existing = files[file.id];
@@ -7232,6 +7963,14 @@ function applyGlobalAssetRemoveFile(state, id, now) {
7232
7963
  delete nextUsage[id];
7233
7964
  local = { ...local, assetUsageIndex: nextUsage };
7234
7965
  }
7966
+ const existing = files[id];
7967
+ const hadRemoteRef = Boolean(existing.workingBranchRef || existing.baseBranchRef);
7968
+ if (hadRemoteRef && !(local.pendingAttachmentDeletes ?? []).includes(existing.slotId)) {
7969
+ local = {
7970
+ ...local,
7971
+ pendingAttachmentDeletes: [...local.pendingAttachmentDeletes ?? [], existing.slotId]
7972
+ };
7973
+ }
7235
7974
  const synced = {
7236
7975
  ...state.synced,
7237
7976
  collections: { ...state.synced.collections, requests },
@@ -7388,7 +8127,7 @@ function evictSnapshotsToCap(entries, maxBytes) {
7388
8127
  };
7389
8128
  }
7390
8129
  function applySnapshotCapture(state, args, now) {
7391
- const id = args.id ?? (0, import_shared2.generateId)();
8130
+ const id = args.id ?? (0, import_shared3.generateId)();
7392
8131
  const snapshot2 = {
7393
8132
  id,
7394
8133
  createdAt: now,
@@ -7477,7 +8216,7 @@ function applyHistoryPurge(state, olderThanMs) {
7477
8216
  }
7478
8217
 
7479
8218
  // src/workspace/runPlan.ts
7480
- var import_shared3 = require("@apicircle/shared");
8219
+ var import_shared4 = require("@apicircle/shared");
7481
8220
  var MAX_REQUEST_RUNS = 500;
7482
8221
  var MAX_PLAN_RUNS = 200;
7483
8222
  var ANONYMOUS_ACTOR = { kind: "unknown", name: "unknown" };
@@ -7543,22 +8282,6 @@ function lookupPlanStepRequest(step, synced, local) {
7543
8282
  linkedGlobalAssets: snapshot2.globalAssets
7544
8283
  };
7545
8284
  }
7546
- function mergeRequestOverride(base, patch) {
7547
- const merged = { ...base };
7548
- if (patch.name !== void 0) merged.name = patch.name;
7549
- if (patch.method !== void 0) merged.method = patch.method;
7550
- if (patch.url !== void 0) merged.url = patch.url;
7551
- if (patch.headers !== void 0) merged.headers = patch.headers;
7552
- if (patch.query !== void 0) merged.query = patch.query;
7553
- if (patch.pathParams !== void 0) merged.pathParams = patch.pathParams;
7554
- if (patch.cookies !== void 0) merged.cookies = patch.cookies;
7555
- if (patch.body !== void 0) merged.body = patch.body;
7556
- if (patch.auth !== void 0) merged.auth = patch.auth;
7557
- if (patch.contextVars !== void 0) merged.contextVars = patch.contextVars;
7558
- if (patch.extractions !== void 0) merged.extractions = patch.extractions;
7559
- if (patch.assertions !== void 0) merged.assertions = patch.assertions;
7560
- return merged;
7561
- }
7562
8285
  function applyEnvironmentOverrides(source, linkedWorkspaceId, synced) {
7563
8286
  const overrides = Object.values(synced.linkedOverrides.environmentVars).filter(
7564
8287
  (override) => override.linkedWorkspaceId === linkedWorkspaceId
@@ -7624,7 +8347,7 @@ async function runPlan(state, planId, opts = {}) {
7624
8347
  const baseRefs = plan.envPriorityOrder.length > 0 ? plan.envPriorityOrder : state.synced.environments.priorityOrder;
7625
8348
  const envRefs = opts.env ? [{ kind: "local", name: opts.env }, ...baseRefs] : baseRefs;
7626
8349
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
7627
- const planRunId = (0, import_shared3.generateId)();
8350
+ const planRunId = (0, import_shared4.generateId)();
7628
8351
  const t0 = Date.now();
7629
8352
  const stepRecords = [];
7630
8353
  const newRequestRuns = [];
@@ -7657,7 +8380,7 @@ async function runPlan(state, planId, opts = {}) {
7657
8380
  const lookup2 = lookupPlanStepRequest(step, state.synced, state.local);
7658
8381
  const baseRequest = lookup2.request;
7659
8382
  if (!baseRequest) {
7660
- const runId = (0, import_shared3.generateId)();
8383
+ const runId = (0, import_shared4.generateId)();
7661
8384
  const error = lookup2.error ?? "Request no longer exists in workspace.";
7662
8385
  newRequestRuns.push(orphanRun(runId, step.requestId, error));
7663
8386
  stepRecords.push({ requestRunId: runId, passed: false });
@@ -7775,7 +8498,7 @@ function buildEnvMaps(synced, secretsById, local) {
7775
8498
  vars[v.key] = v.value;
7776
8499
  }
7777
8500
  }
7778
- flat[(0, import_shared3.envPriorityKey)({ kind: "local", name })] = vars;
8501
+ flat[(0, import_shared4.envPriorityKey)({ kind: "local", name })] = vars;
7779
8502
  }
7780
8503
  if (local) {
7781
8504
  for (const [linkId, snapshot2] of Object.entries(local.linkedCollections)) {
@@ -7792,7 +8515,7 @@ function buildEnvMaps(synced, secretsById, local) {
7792
8515
  vars[variable.key] = variable.value;
7793
8516
  }
7794
8517
  }
7795
- flat[(0, import_shared3.envPriorityKey)({ kind: "linked", linkedWorkspaceId: linkId, envName })] = vars;
8518
+ flat[(0, import_shared4.envPriorityKey)({ kind: "linked", linkedWorkspaceId: linkId, envName })] = vars;
7796
8519
  }
7797
8520
  }
7798
8521
  }
@@ -7819,7 +8542,7 @@ function resolveRequest(request, synced, plan, envRefs, globalContext, flatEnvs,
7819
8542
  contextVars: Object.entries(ctxMap).map(([key, value]) => ({ key, value })),
7820
8543
  environments: flatEnvs,
7821
8544
  activeEnvName: null,
7822
- priorityOrder: envRefs.map(import_shared3.envPriorityKey),
8545
+ priorityOrder: envRefs.map(import_shared4.envPriorityKey),
7823
8546
  secrets: secretsByLabel
7824
8547
  });
7825
8548
  const missing = /* @__PURE__ */ new Set();
@@ -7889,7 +8612,7 @@ function orphanRun(id, requestId, error) {
7889
8612
  function buildRequestRun(resolved, result, assertions) {
7890
8613
  const { preview, truncated } = clampPreview(result.body ?? "");
7891
8614
  return {
7892
- id: (0, import_shared3.generateId)(),
8615
+ id: (0, import_shared4.generateId)(),
7893
8616
  requestId: resolved.id,
7894
8617
  startedAt: result.startedAt,
7895
8618
  durationMs: result.durationMs,
@@ -7909,8 +8632,8 @@ function buildRequestRun(resolved, result, assertions) {
7909
8632
  };
7910
8633
  }
7911
8634
  function clampPreview(value) {
7912
- if (value.length <= import_shared3.RUN_BODY_PREVIEW_LIMIT) return { preview: value, truncated: false };
7913
- return { preview: value.slice(0, import_shared3.RUN_BODY_PREVIEW_LIMIT), truncated: true };
8635
+ if (value.length <= import_shared4.RUN_BODY_PREVIEW_LIMIT) return { preview: value, truncated: false };
8636
+ return { preview: value.slice(0, import_shared4.RUN_BODY_PREVIEW_LIMIT), truncated: true };
7914
8637
  }
7915
8638
  function redactUrlCredentials(url) {
7916
8639
  try {
@@ -8133,9 +8856,9 @@ function toCsv(value) {
8133
8856
  }
8134
8857
 
8135
8858
  // src/transform/computeSavings.ts
8136
- var import_shared4 = require("@apicircle/shared");
8859
+ var import_shared5 = require("@apicircle/shared");
8137
8860
  function computeTransformSavings(body, contentType) {
8138
- const originalBytes = (0, import_shared4.utf8ByteLength)(body);
8861
+ const originalBytes = (0, import_shared5.utf8ByteLength)(body);
8139
8862
  if (!isJsonLike(body, contentType)) {
8140
8863
  return { originalBytes, minifiedBytes: originalBytes, candidates: [] };
8141
8864
  }
@@ -8146,7 +8869,7 @@ function computeTransformSavings(body, contentType) {
8146
8869
  return { originalBytes, minifiedBytes: originalBytes, candidates: [] };
8147
8870
  }
8148
8871
  const minified = JSON.stringify(parsed);
8149
- const minifiedBytes = (0, import_shared4.utf8ByteLength)(minified);
8872
+ const minifiedBytes = (0, import_shared5.utf8ByteLength)(minified);
8150
8873
  const candidates = [];
8151
8874
  try {
8152
8875
  const toon = toToon(parsed);
@@ -8173,7 +8896,7 @@ function computeTransformSavings(body, contentType) {
8173
8896
  };
8174
8897
  }
8175
8898
  function makeCandidate(format, preview, baselineBytes) {
8176
- const bytes = (0, import_shared4.utf8ByteLength)(preview);
8899
+ const bytes = (0, import_shared5.utf8ByteLength)(preview);
8177
8900
  const ratio = baselineBytes === 0 ? 0 : 1 - bytes / baselineBytes;
8178
8901
  return {
8179
8902
  format,
@@ -8197,31 +8920,35 @@ var TRANSFORM_FORMAT_LABELS = {
8197
8920
  0 && (module.exports = {
8198
8921
  ANONYMOUS_ACTOR,
8199
8922
  APICIRCLE_FOLDER_EXPORT_FORMAT,
8200
- ATTACHMENTS_DIR,
8201
8923
  DESKTOP_APP_ORIGIN,
8202
8924
  EMPTY_UNPUSHED_SUMMARY,
8203
8925
  HTTP_HEADERS_MAP,
8204
8926
  OAuth2TokenError,
8205
8927
  PlanRunDeniedError,
8928
+ REGISTRY_JSON_PATH,
8206
8929
  RemoteWorkspaceParseError,
8207
8930
  TRANSFORM_FORMAT_LABELS,
8208
8931
  WORKSPACE_DIR,
8209
- WORKSPACE_JSON_PATH,
8932
+ appendReleaseEntry,
8210
8933
  applyAuth,
8211
8934
  applyAwsSigV4,
8212
8935
  applyContentTypeForBodyType,
8936
+ applyLinkedEnvironmentOverrides,
8213
8937
  applyLinkedUpdate,
8214
8938
  applyMerge,
8215
8939
  applyMutation,
8216
8940
  applyPathParams,
8217
8941
  assertNoPlaintextCredentials,
8218
8942
  attachmentPath,
8943
+ attachmentsDir,
8219
8944
  buildAuthorizeUrl,
8220
8945
  buildAutoHeaders,
8221
8946
  buildDigestAuthHeader,
8222
8947
  buildHawkAuthHeader,
8948
+ buildLinkedSnapshot,
8223
8949
  buildNtlmType1Negotiate,
8224
8950
  buildNtlmType3Authenticate,
8951
+ buildReleaseEntry,
8225
8952
  buildRequest,
8226
8953
  buildScope,
8227
8954
  collectAttachmentSlots,
@@ -8235,6 +8962,7 @@ var TRANSFORM_FORMAT_LABELS = {
8235
8962
  composeUrl,
8236
8963
  composeUrlWithQuery,
8237
8964
  computeCodeChallenge,
8965
+ computeRequestOverridePatch,
8238
8966
  computeThreeWayDiff,
8239
8967
  computeTransformSavings,
8240
8968
  decryptString,
@@ -8247,6 +8975,7 @@ var TRANSFORM_FORMAT_LABELS = {
8247
8975
  exportKey,
8248
8976
  extractContext,
8249
8977
  fetchOAuth2Token,
8978
+ fetchRemoteWorkspaceJson,
8250
8979
  findPathPlaceholders,
8251
8980
  generateAesKey,
8252
8981
  generateCodeVerifier,
@@ -8264,14 +8993,18 @@ var TRANSFORM_FORMAT_LABELS = {
8264
8993
  hasUnpushedChanges,
8265
8994
  importApicircleFolderInto,
8266
8995
  importKey,
8996
+ initSecretCrypto,
8267
8997
  isApicircleEnvironment,
8268
8998
  isApicircleFolderExport,
8269
8999
  isDesktop,
9000
+ isEmptyOverridePatch,
8270
9001
  isInsomniaExport,
8271
9002
  isPostmanEnvironment,
8272
9003
  isPostmanV2Collection,
8273
9004
  isValidSemver,
9005
+ ledgerFromProbe,
8274
9006
  lookup,
9007
+ mergeRequestOverride,
8275
9008
  mergeWithAutoHeaders,
8276
9009
  normalizeContentType,
8277
9010
  parseApicircleEnvironment,
@@ -8282,12 +9015,15 @@ var TRANSFORM_FORMAT_LABELS = {
8282
9015
  parseDigestChallenge,
8283
9016
  parseGraphqlSchema,
8284
9017
  parseInsomniaCollection,
9018
+ parseLinkedWorkspaceJson,
8285
9019
  parseNtlmType2Challenge,
8286
9020
  parsePostmanCollection,
8287
9021
  parsePostmanEnvironment,
9022
+ parseRegistryActiveId,
8288
9023
  parseSemver,
8289
9024
  parseUrlQuery,
8290
9025
  parseWorkspaceJson,
9026
+ plaintextEnvMap,
8291
9027
  pollDeviceFlow,
8292
9028
  preSendValidation,
8293
9029
  previewLinkedUpdate,
@@ -8300,6 +9036,7 @@ var TRANSFORM_FORMAT_LABELS = {
8300
9036
  requestRunToExecutionResult,
8301
9037
  resolveInheritedAuth,
8302
9038
  resolvePlanRef,
9039
+ resolveRequestForExecution,
8303
9040
  resolveString,
8304
9041
  resolveStringMap,
8305
9042
  runAssertions,
@@ -8321,7 +9058,9 @@ var TRANSFORM_FORMAT_LABELS = {
8321
9058
  toYaml,
8322
9059
  tokenizeCurl,
8323
9060
  tryParsePayload,
9061
+ unlockSecretCrypto,
8324
9062
  validateBranchName,
9063
+ workspaceJsonPath,
8325
9064
  yankRelease
8326
9065
  });
8327
9066
  //# sourceMappingURL=index.cjs.map