@postman-cse/onboarding-repo-sync 2.1.6 → 2.1.7
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/action.cjs +140 -37
- package/dist/cli.cjs +140 -37
- package/dist/index.cjs +140 -37
- package/package.json +1 -1
package/dist/action.cjs
CHANGED
|
@@ -125114,12 +125114,14 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
125114
125114
|
prod: {
|
|
125115
125115
|
apiBaseUrl: "https://api.getpostman.com",
|
|
125116
125116
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
125117
|
+
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
125117
125118
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
125118
125119
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125119
125120
|
},
|
|
125120
125121
|
beta: {
|
|
125121
125122
|
apiBaseUrl: "https://api.getpostman-beta.com",
|
|
125122
125123
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
125124
|
+
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
125123
125125
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
125124
125126
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125125
125127
|
}
|
|
@@ -127587,6 +127589,14 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127587
127589
|
createFlights.set(key, { fingerprint, promise: pending });
|
|
127588
127590
|
return pending;
|
|
127589
127591
|
}
|
|
127592
|
+
/**
|
|
127593
|
+
* Reconcile an ambiguous create. Returns the adopted match, `undefined`
|
|
127594
|
+
* when every discovery read succeeded and found nothing (the create is
|
|
127595
|
+
* conclusively absent, so a fallback resend cannot duplicate), or `null`
|
|
127596
|
+
* when the outcome is inconclusive (non-ambiguous error, or a discovery
|
|
127597
|
+
* read itself failed — in that case a resend could duplicate a committed
|
|
127598
|
+
* twin and must not fire).
|
|
127599
|
+
*/
|
|
127590
127600
|
async discoverAfterAmbiguousCreate(discover, error2) {
|
|
127591
127601
|
if (!this.isAmbiguousCreateOutcome(error2)) {
|
|
127592
127602
|
return null;
|
|
@@ -127595,12 +127605,31 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127595
127605
|
if (attempt > 0) {
|
|
127596
127606
|
await this.sleep(this.reconcileDelayMs);
|
|
127597
127607
|
}
|
|
127598
|
-
|
|
127608
|
+
let found;
|
|
127609
|
+
try {
|
|
127610
|
+
found = await discover();
|
|
127611
|
+
} catch {
|
|
127612
|
+
return null;
|
|
127613
|
+
}
|
|
127599
127614
|
if (found) {
|
|
127600
127615
|
return found;
|
|
127601
127616
|
}
|
|
127602
127617
|
}
|
|
127603
|
-
return
|
|
127618
|
+
return void 0;
|
|
127619
|
+
}
|
|
127620
|
+
/**
|
|
127621
|
+
* After an ambiguous create failed AND discovery proved the asset absent,
|
|
127622
|
+
* re-attempt the create once with the cold `/_api` fallback enabled: the
|
|
127623
|
+
* reconcile above guarantees no committed twin, so the resend cannot
|
|
127624
|
+
* duplicate. Returns null when the resend also fails (caller rethrows the
|
|
127625
|
+
* original error).
|
|
127626
|
+
*/
|
|
127627
|
+
async resendAbsentCreate(operation) {
|
|
127628
|
+
try {
|
|
127629
|
+
return await operation();
|
|
127630
|
+
} catch {
|
|
127631
|
+
return null;
|
|
127632
|
+
}
|
|
127604
127633
|
}
|
|
127605
127634
|
publicEnvironmentUid(data, bareId) {
|
|
127606
127635
|
const owner = String(data?.owner ?? "").trim();
|
|
@@ -127648,17 +127677,18 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127648
127677
|
name: envName,
|
|
127649
127678
|
values: normalizedValues
|
|
127650
127679
|
};
|
|
127680
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
127681
|
+
{
|
|
127682
|
+
service: "sync",
|
|
127683
|
+
method: "post",
|
|
127684
|
+
path: `/environment/import?workspace=${ws}`,
|
|
127685
|
+
body,
|
|
127686
|
+
...fallback ? { fallback } : {}
|
|
127687
|
+
},
|
|
127688
|
+
{ retryTransient: false }
|
|
127689
|
+
);
|
|
127651
127690
|
try {
|
|
127652
|
-
const
|
|
127653
|
-
{
|
|
127654
|
-
service: "sync",
|
|
127655
|
-
method: "post",
|
|
127656
|
-
path: `/environment/import?workspace=${ws}`,
|
|
127657
|
-
body
|
|
127658
|
-
},
|
|
127659
|
-
{ retryTransient: false }
|
|
127660
|
-
);
|
|
127661
|
-
const data = this.dataOf(response);
|
|
127691
|
+
const data = this.dataOf(await send2());
|
|
127662
127692
|
const bareId = this.idOf(data);
|
|
127663
127693
|
if (!bareId) {
|
|
127664
127694
|
throw new Error("Environment import did not return a UID");
|
|
@@ -127673,6 +127703,15 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127673
127703
|
await this.updateEnvironment(adopted, envName, values);
|
|
127674
127704
|
return adopted;
|
|
127675
127705
|
}
|
|
127706
|
+
if (adopted === void 0) {
|
|
127707
|
+
const retried = await this.resendAbsentCreate(async () => {
|
|
127708
|
+
const data = this.dataOf(await send2("auto"));
|
|
127709
|
+
const bareId = this.idOf(data);
|
|
127710
|
+
if (!bareId) throw new Error("Environment import did not return a UID");
|
|
127711
|
+
return this.publicEnvironmentUid(data, bareId);
|
|
127712
|
+
});
|
|
127713
|
+
if (retried) return retried;
|
|
127714
|
+
}
|
|
127676
127715
|
throw error2;
|
|
127677
127716
|
}
|
|
127678
127717
|
});
|
|
@@ -127804,19 +127843,20 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127804
127843
|
private: false,
|
|
127805
127844
|
...environment ? { environment } : {}
|
|
127806
127845
|
};
|
|
127807
|
-
|
|
127808
|
-
|
|
127809
|
-
|
|
127810
|
-
|
|
127811
|
-
|
|
127812
|
-
|
|
127813
|
-
|
|
127814
|
-
|
|
127815
|
-
|
|
127816
|
-
|
|
127817
|
-
|
|
127818
|
-
|
|
127819
|
-
|
|
127846
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
127847
|
+
{
|
|
127848
|
+
service: "mock",
|
|
127849
|
+
method: "post",
|
|
127850
|
+
path: `/mocks?workspace=${ws}`,
|
|
127851
|
+
body,
|
|
127852
|
+
...fallback ? { fallback } : {}
|
|
127853
|
+
},
|
|
127854
|
+
// Unsafe create: never blind re-POST. An ESOCKETTIMEDOUT after accept
|
|
127855
|
+
// may still have created the mock; reconcile via discovery below and
|
|
127856
|
+
// let the orchestrator retry the whole create-or-adopt cycle.
|
|
127857
|
+
{ retryTransient: false }
|
|
127858
|
+
);
|
|
127859
|
+
const parseMock = (response) => {
|
|
127820
127860
|
const record = this.dataOf(response);
|
|
127821
127861
|
const uid = this.idOf(record);
|
|
127822
127862
|
if (!uid) {
|
|
@@ -127826,6 +127866,9 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127826
127866
|
uid,
|
|
127827
127867
|
url: String(record?.url ?? record?.mockUrl ?? "").trim()
|
|
127828
127868
|
};
|
|
127869
|
+
};
|
|
127870
|
+
try {
|
|
127871
|
+
return parseMock(await send2());
|
|
127829
127872
|
} catch (error2) {
|
|
127830
127873
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127831
127874
|
() => this.findMockByCollection(collection, environment, mockName),
|
|
@@ -127834,6 +127877,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127834
127877
|
if (adopted) {
|
|
127835
127878
|
return { uid: adopted.uid, url: adopted.mockUrl };
|
|
127836
127879
|
}
|
|
127880
|
+
if (adopted === void 0) {
|
|
127881
|
+
const retried = await this.resendAbsentCreate(async () => parseMock(await send2("auto")));
|
|
127882
|
+
if (retried) return retried;
|
|
127883
|
+
}
|
|
127837
127884
|
throw error2;
|
|
127838
127885
|
}
|
|
127839
127886
|
});
|
|
@@ -127940,21 +127987,25 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127940
127987
|
distribution: null,
|
|
127941
127988
|
...environment ? { environment } : {}
|
|
127942
127989
|
};
|
|
127943
|
-
|
|
127944
|
-
|
|
127945
|
-
|
|
127946
|
-
|
|
127947
|
-
|
|
127948
|
-
|
|
127949
|
-
|
|
127950
|
-
|
|
127951
|
-
|
|
127952
|
-
|
|
127990
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
127991
|
+
{
|
|
127992
|
+
service: "monitors",
|
|
127993
|
+
method: "post",
|
|
127994
|
+
path: `/jobTemplates?workspace=${ws}`,
|
|
127995
|
+
body,
|
|
127996
|
+
...fallback ? { fallback } : {}
|
|
127997
|
+
},
|
|
127998
|
+
{ retryTransient: false }
|
|
127999
|
+
);
|
|
128000
|
+
const parseMonitor = (response) => {
|
|
127953
128001
|
const uid = this.idOf(this.dataOf(response));
|
|
127954
128002
|
if (!uid) {
|
|
127955
128003
|
throw new Error("Monitor create did not return a UID");
|
|
127956
128004
|
}
|
|
127957
128005
|
return uid;
|
|
128006
|
+
};
|
|
128007
|
+
try {
|
|
128008
|
+
return parseMonitor(await send2());
|
|
127958
128009
|
} catch (error2) {
|
|
127959
128010
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127960
128011
|
() => this.findMonitorByCollection(collection, environment, monitorName),
|
|
@@ -127963,6 +128014,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127963
128014
|
if (adopted?.uid) {
|
|
127964
128015
|
return adopted.uid;
|
|
127965
128016
|
}
|
|
128017
|
+
if (adopted === void 0) {
|
|
128018
|
+
const retried = await this.resendAbsentCreate(async () => parseMonitor(await send2("auto")));
|
|
128019
|
+
if (retried) return retried;
|
|
128020
|
+
}
|
|
127966
128021
|
throw error2;
|
|
127967
128022
|
}
|
|
127968
128023
|
});
|
|
@@ -128191,6 +128246,7 @@ var AccessTokenGatewayClient = class {
|
|
|
128191
128246
|
fetchImpl;
|
|
128192
128247
|
secretMasker;
|
|
128193
128248
|
maxRetries;
|
|
128249
|
+
fallbackBaseUrl;
|
|
128194
128250
|
retryBaseDelayMs;
|
|
128195
128251
|
sleepImpl;
|
|
128196
128252
|
constructor(options) {
|
|
@@ -128203,6 +128259,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128203
128259
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
128204
128260
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.tokenProvider.current()]);
|
|
128205
128261
|
this.maxRetries = options.maxRetries ?? 3;
|
|
128262
|
+
const fallbackEnv = typeof process !== "undefined" ? process.env?.POSTMAN_ITEM_CREATE_FALLBACK : void 0;
|
|
128263
|
+
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
128206
128264
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
128207
128265
|
this.sleepImpl = options.sleepImpl ?? defaultSleep;
|
|
128208
128266
|
}
|
|
@@ -128221,8 +128279,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128221
128279
|
}
|
|
128222
128280
|
return headers;
|
|
128223
128281
|
}
|
|
128224
|
-
async send(request) {
|
|
128225
|
-
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
128282
|
+
async send(request, baseUrl) {
|
|
128283
|
+
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
128226
128284
|
return this.fetchImpl(url, {
|
|
128227
128285
|
method: "POST",
|
|
128228
128286
|
headers: this.buildHeaders(request.headers),
|
|
@@ -128235,6 +128293,43 @@ var AccessTokenGatewayClient = class {
|
|
|
128235
128293
|
})
|
|
128236
128294
|
});
|
|
128237
128295
|
}
|
|
128296
|
+
/**
|
|
128297
|
+
* One cold, serial attempt against the fallback base URL after the primary
|
|
128298
|
+
* budget is exhausted on a transient failure. Never hedged in parallel with
|
|
128299
|
+
* the primary; only fires when the request would otherwise throw. Callers
|
|
128300
|
+
* with `retryTransient: false` still reconcile first — the fallback attempt
|
|
128301
|
+
* here is the resend, so it is only used for requests whose mutation is
|
|
128302
|
+
* known idempotent or already reconciled by the caller's adopt-on-ambiguous
|
|
128303
|
+
* loop.
|
|
128304
|
+
*/
|
|
128305
|
+
async tryFallback(request) {
|
|
128306
|
+
if (!this.fallbackBaseUrl) return null;
|
|
128307
|
+
try {
|
|
128308
|
+
return await this.send(request, this.fallbackBaseUrl);
|
|
128309
|
+
} catch {
|
|
128310
|
+
return null;
|
|
128311
|
+
}
|
|
128312
|
+
}
|
|
128313
|
+
/**
|
|
128314
|
+
* Run the fallback attempt and classify its response the same way the
|
|
128315
|
+
* primary path would. Returns the success response, or null when the
|
|
128316
|
+
* fallback also failed transiently (caller then throws the original error).
|
|
128317
|
+
* Non-transient fallback failures (4xx) surface as their own HttpError since
|
|
128318
|
+
* they are the freshest authoritative answer.
|
|
128319
|
+
*/
|
|
128320
|
+
fallbackEligible(request, retryTransient) {
|
|
128321
|
+
if (!this.fallbackBaseUrl) return false;
|
|
128322
|
+
return retryTransient || request.fallback === "auto";
|
|
128323
|
+
}
|
|
128324
|
+
async attemptFallback(request, retryTransient) {
|
|
128325
|
+
if (!this.fallbackEligible(request, retryTransient)) return null;
|
|
128326
|
+
const response = await this.tryFallback(request);
|
|
128327
|
+
if (!response) return null;
|
|
128328
|
+
if (response.ok) return response;
|
|
128329
|
+
const body = await response.text().catch(() => "");
|
|
128330
|
+
if (isRetryableSafeReadResponse(response.status)) return null;
|
|
128331
|
+
throw this.toHttpError(request, response, body);
|
|
128332
|
+
}
|
|
128238
128333
|
/**
|
|
128239
128334
|
* Send a gateway request, refreshing the token once on an auth failure and
|
|
128240
128335
|
* optionally retrying transient downstream failures (5xx / Bifrost read
|
|
@@ -128257,6 +128352,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128257
128352
|
await this.sleepImpl(delay);
|
|
128258
128353
|
continue;
|
|
128259
128354
|
}
|
|
128355
|
+
const fallbackResponse2 = await this.attemptFallback(request, retryTransient);
|
|
128356
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
128260
128357
|
throw error2;
|
|
128261
128358
|
}
|
|
128262
128359
|
if (response.ok) {
|
|
@@ -128278,6 +128375,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128278
128375
|
await this.sleepImpl(delay);
|
|
128279
128376
|
continue;
|
|
128280
128377
|
}
|
|
128378
|
+
const fallbackResponse = await this.attemptFallback(request, retryTransient);
|
|
128379
|
+
if (fallbackResponse) return fallbackResponse;
|
|
128281
128380
|
throw this.toHttpError(request, response, body);
|
|
128282
128381
|
}
|
|
128283
128382
|
}
|
|
@@ -128904,6 +129003,7 @@ function resolveInputs(env = process.env) {
|
|
|
128904
129003
|
postmanStack,
|
|
128905
129004
|
postmanApiBase: endpointProfile.apiBaseUrl,
|
|
128906
129005
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
129006
|
+
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
128907
129007
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
128908
129008
|
postmanIapubBase: endpointProfile.iapubBaseUrl
|
|
128909
129009
|
};
|
|
@@ -130045,6 +130145,8 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130045
130145
|
const gateway = new AccessTokenGatewayClient({
|
|
130046
130146
|
tokenProvider,
|
|
130047
130147
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
130148
|
+
// No fallback on the org-mode probe: the expected non-org 400 must
|
|
130149
|
+
// surface verbatim, not be re-fired against the /_api alias.
|
|
130048
130150
|
secretMasker: masker
|
|
130049
130151
|
});
|
|
130050
130152
|
const squads = await gateway.getSquads(teamId);
|
|
@@ -130100,6 +130202,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
130100
130202
|
const gateway = new AccessTokenGatewayClient({
|
|
130101
130203
|
tokenProvider,
|
|
130102
130204
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
130205
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
130103
130206
|
teamId: resolved.teamId,
|
|
130104
130207
|
orgMode: inputs.orgMode,
|
|
130105
130208
|
secretMasker: masker
|
package/dist/cli.cjs
CHANGED
|
@@ -123217,12 +123217,14 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
123217
123217
|
prod: {
|
|
123218
123218
|
apiBaseUrl: "https://api.getpostman.com",
|
|
123219
123219
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
123220
|
+
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
123220
123221
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
123221
123222
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
123222
123223
|
},
|
|
123223
123224
|
beta: {
|
|
123224
123225
|
apiBaseUrl: "https://api.getpostman-beta.com",
|
|
123225
123226
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
123227
|
+
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
123226
123228
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
123227
123229
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
123228
123230
|
}
|
|
@@ -125690,6 +125692,14 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125690
125692
|
createFlights.set(key, { fingerprint, promise: pending });
|
|
125691
125693
|
return pending;
|
|
125692
125694
|
}
|
|
125695
|
+
/**
|
|
125696
|
+
* Reconcile an ambiguous create. Returns the adopted match, `undefined`
|
|
125697
|
+
* when every discovery read succeeded and found nothing (the create is
|
|
125698
|
+
* conclusively absent, so a fallback resend cannot duplicate), or `null`
|
|
125699
|
+
* when the outcome is inconclusive (non-ambiguous error, or a discovery
|
|
125700
|
+
* read itself failed — in that case a resend could duplicate a committed
|
|
125701
|
+
* twin and must not fire).
|
|
125702
|
+
*/
|
|
125693
125703
|
async discoverAfterAmbiguousCreate(discover, error) {
|
|
125694
125704
|
if (!this.isAmbiguousCreateOutcome(error)) {
|
|
125695
125705
|
return null;
|
|
@@ -125698,12 +125708,31 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125698
125708
|
if (attempt > 0) {
|
|
125699
125709
|
await this.sleep(this.reconcileDelayMs);
|
|
125700
125710
|
}
|
|
125701
|
-
|
|
125711
|
+
let found;
|
|
125712
|
+
try {
|
|
125713
|
+
found = await discover();
|
|
125714
|
+
} catch {
|
|
125715
|
+
return null;
|
|
125716
|
+
}
|
|
125702
125717
|
if (found) {
|
|
125703
125718
|
return found;
|
|
125704
125719
|
}
|
|
125705
125720
|
}
|
|
125706
|
-
return
|
|
125721
|
+
return void 0;
|
|
125722
|
+
}
|
|
125723
|
+
/**
|
|
125724
|
+
* After an ambiguous create failed AND discovery proved the asset absent,
|
|
125725
|
+
* re-attempt the create once with the cold `/_api` fallback enabled: the
|
|
125726
|
+
* reconcile above guarantees no committed twin, so the resend cannot
|
|
125727
|
+
* duplicate. Returns null when the resend also fails (caller rethrows the
|
|
125728
|
+
* original error).
|
|
125729
|
+
*/
|
|
125730
|
+
async resendAbsentCreate(operation) {
|
|
125731
|
+
try {
|
|
125732
|
+
return await operation();
|
|
125733
|
+
} catch {
|
|
125734
|
+
return null;
|
|
125735
|
+
}
|
|
125707
125736
|
}
|
|
125708
125737
|
publicEnvironmentUid(data, bareId) {
|
|
125709
125738
|
const owner = String(data?.owner ?? "").trim();
|
|
@@ -125751,17 +125780,18 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125751
125780
|
name: envName,
|
|
125752
125781
|
values: normalizedValues
|
|
125753
125782
|
};
|
|
125783
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
125784
|
+
{
|
|
125785
|
+
service: "sync",
|
|
125786
|
+
method: "post",
|
|
125787
|
+
path: `/environment/import?workspace=${ws}`,
|
|
125788
|
+
body,
|
|
125789
|
+
...fallback ? { fallback } : {}
|
|
125790
|
+
},
|
|
125791
|
+
{ retryTransient: false }
|
|
125792
|
+
);
|
|
125754
125793
|
try {
|
|
125755
|
-
const
|
|
125756
|
-
{
|
|
125757
|
-
service: "sync",
|
|
125758
|
-
method: "post",
|
|
125759
|
-
path: `/environment/import?workspace=${ws}`,
|
|
125760
|
-
body
|
|
125761
|
-
},
|
|
125762
|
-
{ retryTransient: false }
|
|
125763
|
-
);
|
|
125764
|
-
const data = this.dataOf(response);
|
|
125794
|
+
const data = this.dataOf(await send2());
|
|
125765
125795
|
const bareId = this.idOf(data);
|
|
125766
125796
|
if (!bareId) {
|
|
125767
125797
|
throw new Error("Environment import did not return a UID");
|
|
@@ -125776,6 +125806,15 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125776
125806
|
await this.updateEnvironment(adopted, envName, values);
|
|
125777
125807
|
return adopted;
|
|
125778
125808
|
}
|
|
125809
|
+
if (adopted === void 0) {
|
|
125810
|
+
const retried = await this.resendAbsentCreate(async () => {
|
|
125811
|
+
const data = this.dataOf(await send2("auto"));
|
|
125812
|
+
const bareId = this.idOf(data);
|
|
125813
|
+
if (!bareId) throw new Error("Environment import did not return a UID");
|
|
125814
|
+
return this.publicEnvironmentUid(data, bareId);
|
|
125815
|
+
});
|
|
125816
|
+
if (retried) return retried;
|
|
125817
|
+
}
|
|
125779
125818
|
throw error;
|
|
125780
125819
|
}
|
|
125781
125820
|
});
|
|
@@ -125907,19 +125946,20 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125907
125946
|
private: false,
|
|
125908
125947
|
...environment ? { environment } : {}
|
|
125909
125948
|
};
|
|
125910
|
-
|
|
125911
|
-
|
|
125912
|
-
|
|
125913
|
-
|
|
125914
|
-
|
|
125915
|
-
|
|
125916
|
-
|
|
125917
|
-
|
|
125918
|
-
|
|
125919
|
-
|
|
125920
|
-
|
|
125921
|
-
|
|
125922
|
-
|
|
125949
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
125950
|
+
{
|
|
125951
|
+
service: "mock",
|
|
125952
|
+
method: "post",
|
|
125953
|
+
path: `/mocks?workspace=${ws}`,
|
|
125954
|
+
body,
|
|
125955
|
+
...fallback ? { fallback } : {}
|
|
125956
|
+
},
|
|
125957
|
+
// Unsafe create: never blind re-POST. An ESOCKETTIMEDOUT after accept
|
|
125958
|
+
// may still have created the mock; reconcile via discovery below and
|
|
125959
|
+
// let the orchestrator retry the whole create-or-adopt cycle.
|
|
125960
|
+
{ retryTransient: false }
|
|
125961
|
+
);
|
|
125962
|
+
const parseMock = (response) => {
|
|
125923
125963
|
const record = this.dataOf(response);
|
|
125924
125964
|
const uid = this.idOf(record);
|
|
125925
125965
|
if (!uid) {
|
|
@@ -125929,6 +125969,9 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125929
125969
|
uid,
|
|
125930
125970
|
url: String(record?.url ?? record?.mockUrl ?? "").trim()
|
|
125931
125971
|
};
|
|
125972
|
+
};
|
|
125973
|
+
try {
|
|
125974
|
+
return parseMock(await send2());
|
|
125932
125975
|
} catch (error) {
|
|
125933
125976
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
125934
125977
|
() => this.findMockByCollection(collection, environment, mockName),
|
|
@@ -125937,6 +125980,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125937
125980
|
if (adopted) {
|
|
125938
125981
|
return { uid: adopted.uid, url: adopted.mockUrl };
|
|
125939
125982
|
}
|
|
125983
|
+
if (adopted === void 0) {
|
|
125984
|
+
const retried = await this.resendAbsentCreate(async () => parseMock(await send2("auto")));
|
|
125985
|
+
if (retried) return retried;
|
|
125986
|
+
}
|
|
125940
125987
|
throw error;
|
|
125941
125988
|
}
|
|
125942
125989
|
});
|
|
@@ -126043,21 +126090,25 @@ var PostmanGatewayAssetsClient = class {
|
|
|
126043
126090
|
distribution: null,
|
|
126044
126091
|
...environment ? { environment } : {}
|
|
126045
126092
|
};
|
|
126046
|
-
|
|
126047
|
-
|
|
126048
|
-
|
|
126049
|
-
|
|
126050
|
-
|
|
126051
|
-
|
|
126052
|
-
|
|
126053
|
-
|
|
126054
|
-
|
|
126055
|
-
|
|
126093
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
126094
|
+
{
|
|
126095
|
+
service: "monitors",
|
|
126096
|
+
method: "post",
|
|
126097
|
+
path: `/jobTemplates?workspace=${ws}`,
|
|
126098
|
+
body,
|
|
126099
|
+
...fallback ? { fallback } : {}
|
|
126100
|
+
},
|
|
126101
|
+
{ retryTransient: false }
|
|
126102
|
+
);
|
|
126103
|
+
const parseMonitor = (response) => {
|
|
126056
126104
|
const uid = this.idOf(this.dataOf(response));
|
|
126057
126105
|
if (!uid) {
|
|
126058
126106
|
throw new Error("Monitor create did not return a UID");
|
|
126059
126107
|
}
|
|
126060
126108
|
return uid;
|
|
126109
|
+
};
|
|
126110
|
+
try {
|
|
126111
|
+
return parseMonitor(await send2());
|
|
126061
126112
|
} catch (error) {
|
|
126062
126113
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
126063
126114
|
() => this.findMonitorByCollection(collection, environment, monitorName),
|
|
@@ -126066,6 +126117,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
126066
126117
|
if (adopted?.uid) {
|
|
126067
126118
|
return adopted.uid;
|
|
126068
126119
|
}
|
|
126120
|
+
if (adopted === void 0) {
|
|
126121
|
+
const retried = await this.resendAbsentCreate(async () => parseMonitor(await send2("auto")));
|
|
126122
|
+
if (retried) return retried;
|
|
126123
|
+
}
|
|
126069
126124
|
throw error;
|
|
126070
126125
|
}
|
|
126071
126126
|
});
|
|
@@ -126294,6 +126349,7 @@ var AccessTokenGatewayClient = class {
|
|
|
126294
126349
|
fetchImpl;
|
|
126295
126350
|
secretMasker;
|
|
126296
126351
|
maxRetries;
|
|
126352
|
+
fallbackBaseUrl;
|
|
126297
126353
|
retryBaseDelayMs;
|
|
126298
126354
|
sleepImpl;
|
|
126299
126355
|
constructor(options) {
|
|
@@ -126306,6 +126362,8 @@ var AccessTokenGatewayClient = class {
|
|
|
126306
126362
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
126307
126363
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.tokenProvider.current()]);
|
|
126308
126364
|
this.maxRetries = options.maxRetries ?? 3;
|
|
126365
|
+
const fallbackEnv = typeof process !== "undefined" ? process.env?.POSTMAN_ITEM_CREATE_FALLBACK : void 0;
|
|
126366
|
+
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
126309
126367
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
126310
126368
|
this.sleepImpl = options.sleepImpl ?? defaultSleep;
|
|
126311
126369
|
}
|
|
@@ -126324,8 +126382,8 @@ var AccessTokenGatewayClient = class {
|
|
|
126324
126382
|
}
|
|
126325
126383
|
return headers;
|
|
126326
126384
|
}
|
|
126327
|
-
async send(request) {
|
|
126328
|
-
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
126385
|
+
async send(request, baseUrl) {
|
|
126386
|
+
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
126329
126387
|
return this.fetchImpl(url, {
|
|
126330
126388
|
method: "POST",
|
|
126331
126389
|
headers: this.buildHeaders(request.headers),
|
|
@@ -126338,6 +126396,43 @@ var AccessTokenGatewayClient = class {
|
|
|
126338
126396
|
})
|
|
126339
126397
|
});
|
|
126340
126398
|
}
|
|
126399
|
+
/**
|
|
126400
|
+
* One cold, serial attempt against the fallback base URL after the primary
|
|
126401
|
+
* budget is exhausted on a transient failure. Never hedged in parallel with
|
|
126402
|
+
* the primary; only fires when the request would otherwise throw. Callers
|
|
126403
|
+
* with `retryTransient: false` still reconcile first — the fallback attempt
|
|
126404
|
+
* here is the resend, so it is only used for requests whose mutation is
|
|
126405
|
+
* known idempotent or already reconciled by the caller's adopt-on-ambiguous
|
|
126406
|
+
* loop.
|
|
126407
|
+
*/
|
|
126408
|
+
async tryFallback(request) {
|
|
126409
|
+
if (!this.fallbackBaseUrl) return null;
|
|
126410
|
+
try {
|
|
126411
|
+
return await this.send(request, this.fallbackBaseUrl);
|
|
126412
|
+
} catch {
|
|
126413
|
+
return null;
|
|
126414
|
+
}
|
|
126415
|
+
}
|
|
126416
|
+
/**
|
|
126417
|
+
* Run the fallback attempt and classify its response the same way the
|
|
126418
|
+
* primary path would. Returns the success response, or null when the
|
|
126419
|
+
* fallback also failed transiently (caller then throws the original error).
|
|
126420
|
+
* Non-transient fallback failures (4xx) surface as their own HttpError since
|
|
126421
|
+
* they are the freshest authoritative answer.
|
|
126422
|
+
*/
|
|
126423
|
+
fallbackEligible(request, retryTransient) {
|
|
126424
|
+
if (!this.fallbackBaseUrl) return false;
|
|
126425
|
+
return retryTransient || request.fallback === "auto";
|
|
126426
|
+
}
|
|
126427
|
+
async attemptFallback(request, retryTransient) {
|
|
126428
|
+
if (!this.fallbackEligible(request, retryTransient)) return null;
|
|
126429
|
+
const response = await this.tryFallback(request);
|
|
126430
|
+
if (!response) return null;
|
|
126431
|
+
if (response.ok) return response;
|
|
126432
|
+
const body = await response.text().catch(() => "");
|
|
126433
|
+
if (isRetryableSafeReadResponse(response.status)) return null;
|
|
126434
|
+
throw this.toHttpError(request, response, body);
|
|
126435
|
+
}
|
|
126341
126436
|
/**
|
|
126342
126437
|
* Send a gateway request, refreshing the token once on an auth failure and
|
|
126343
126438
|
* optionally retrying transient downstream failures (5xx / Bifrost read
|
|
@@ -126360,6 +126455,8 @@ var AccessTokenGatewayClient = class {
|
|
|
126360
126455
|
await this.sleepImpl(delay);
|
|
126361
126456
|
continue;
|
|
126362
126457
|
}
|
|
126458
|
+
const fallbackResponse2 = await this.attemptFallback(request, retryTransient);
|
|
126459
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
126363
126460
|
throw error;
|
|
126364
126461
|
}
|
|
126365
126462
|
if (response.ok) {
|
|
@@ -126381,6 +126478,8 @@ var AccessTokenGatewayClient = class {
|
|
|
126381
126478
|
await this.sleepImpl(delay);
|
|
126382
126479
|
continue;
|
|
126383
126480
|
}
|
|
126481
|
+
const fallbackResponse = await this.attemptFallback(request, retryTransient);
|
|
126482
|
+
if (fallbackResponse) return fallbackResponse;
|
|
126384
126483
|
throw this.toHttpError(request, response, body);
|
|
126385
126484
|
}
|
|
126386
126485
|
}
|
|
@@ -126952,6 +127051,7 @@ function resolveInputs(env = process.env) {
|
|
|
126952
127051
|
postmanStack,
|
|
126953
127052
|
postmanApiBase: endpointProfile.apiBaseUrl,
|
|
126954
127053
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
127054
|
+
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
126955
127055
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
126956
127056
|
postmanIapubBase: endpointProfile.iapubBaseUrl
|
|
126957
127057
|
};
|
|
@@ -127955,6 +128055,8 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
127955
128055
|
const gateway = new AccessTokenGatewayClient({
|
|
127956
128056
|
tokenProvider,
|
|
127957
128057
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
128058
|
+
// No fallback on the org-mode probe: the expected non-org 400 must
|
|
128059
|
+
// surface verbatim, not be re-fired against the /_api alias.
|
|
127958
128060
|
secretMasker: masker
|
|
127959
128061
|
});
|
|
127960
128062
|
const squads = await gateway.getSquads(teamId);
|
|
@@ -128010,6 +128112,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
128010
128112
|
const gateway = new AccessTokenGatewayClient({
|
|
128011
128113
|
tokenProvider,
|
|
128012
128114
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
128115
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
128013
128116
|
teamId: resolved.teamId,
|
|
128014
128117
|
orgMode: inputs.orgMode,
|
|
128015
128118
|
secretMasker: masker
|
package/dist/index.cjs
CHANGED
|
@@ -125134,12 +125134,14 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
125134
125134
|
prod: {
|
|
125135
125135
|
apiBaseUrl: "https://api.getpostman.com",
|
|
125136
125136
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
125137
|
+
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
125137
125138
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
125138
125139
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125139
125140
|
},
|
|
125140
125141
|
beta: {
|
|
125141
125142
|
apiBaseUrl: "https://api.getpostman-beta.com",
|
|
125142
125143
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
125144
|
+
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
125143
125145
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
125144
125146
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125145
125147
|
}
|
|
@@ -127607,6 +127609,14 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127607
127609
|
createFlights.set(key, { fingerprint, promise: pending });
|
|
127608
127610
|
return pending;
|
|
127609
127611
|
}
|
|
127612
|
+
/**
|
|
127613
|
+
* Reconcile an ambiguous create. Returns the adopted match, `undefined`
|
|
127614
|
+
* when every discovery read succeeded and found nothing (the create is
|
|
127615
|
+
* conclusively absent, so a fallback resend cannot duplicate), or `null`
|
|
127616
|
+
* when the outcome is inconclusive (non-ambiguous error, or a discovery
|
|
127617
|
+
* read itself failed — in that case a resend could duplicate a committed
|
|
127618
|
+
* twin and must not fire).
|
|
127619
|
+
*/
|
|
127610
127620
|
async discoverAfterAmbiguousCreate(discover, error2) {
|
|
127611
127621
|
if (!this.isAmbiguousCreateOutcome(error2)) {
|
|
127612
127622
|
return null;
|
|
@@ -127615,12 +127625,31 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127615
127625
|
if (attempt > 0) {
|
|
127616
127626
|
await this.sleep(this.reconcileDelayMs);
|
|
127617
127627
|
}
|
|
127618
|
-
|
|
127628
|
+
let found;
|
|
127629
|
+
try {
|
|
127630
|
+
found = await discover();
|
|
127631
|
+
} catch {
|
|
127632
|
+
return null;
|
|
127633
|
+
}
|
|
127619
127634
|
if (found) {
|
|
127620
127635
|
return found;
|
|
127621
127636
|
}
|
|
127622
127637
|
}
|
|
127623
|
-
return
|
|
127638
|
+
return void 0;
|
|
127639
|
+
}
|
|
127640
|
+
/**
|
|
127641
|
+
* After an ambiguous create failed AND discovery proved the asset absent,
|
|
127642
|
+
* re-attempt the create once with the cold `/_api` fallback enabled: the
|
|
127643
|
+
* reconcile above guarantees no committed twin, so the resend cannot
|
|
127644
|
+
* duplicate. Returns null when the resend also fails (caller rethrows the
|
|
127645
|
+
* original error).
|
|
127646
|
+
*/
|
|
127647
|
+
async resendAbsentCreate(operation) {
|
|
127648
|
+
try {
|
|
127649
|
+
return await operation();
|
|
127650
|
+
} catch {
|
|
127651
|
+
return null;
|
|
127652
|
+
}
|
|
127624
127653
|
}
|
|
127625
127654
|
publicEnvironmentUid(data, bareId) {
|
|
127626
127655
|
const owner = String(data?.owner ?? "").trim();
|
|
@@ -127668,17 +127697,18 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127668
127697
|
name: envName,
|
|
127669
127698
|
values: normalizedValues
|
|
127670
127699
|
};
|
|
127700
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
127701
|
+
{
|
|
127702
|
+
service: "sync",
|
|
127703
|
+
method: "post",
|
|
127704
|
+
path: `/environment/import?workspace=${ws}`,
|
|
127705
|
+
body,
|
|
127706
|
+
...fallback ? { fallback } : {}
|
|
127707
|
+
},
|
|
127708
|
+
{ retryTransient: false }
|
|
127709
|
+
);
|
|
127671
127710
|
try {
|
|
127672
|
-
const
|
|
127673
|
-
{
|
|
127674
|
-
service: "sync",
|
|
127675
|
-
method: "post",
|
|
127676
|
-
path: `/environment/import?workspace=${ws}`,
|
|
127677
|
-
body
|
|
127678
|
-
},
|
|
127679
|
-
{ retryTransient: false }
|
|
127680
|
-
);
|
|
127681
|
-
const data = this.dataOf(response);
|
|
127711
|
+
const data = this.dataOf(await send2());
|
|
127682
127712
|
const bareId = this.idOf(data);
|
|
127683
127713
|
if (!bareId) {
|
|
127684
127714
|
throw new Error("Environment import did not return a UID");
|
|
@@ -127693,6 +127723,15 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127693
127723
|
await this.updateEnvironment(adopted, envName, values);
|
|
127694
127724
|
return adopted;
|
|
127695
127725
|
}
|
|
127726
|
+
if (adopted === void 0) {
|
|
127727
|
+
const retried = await this.resendAbsentCreate(async () => {
|
|
127728
|
+
const data = this.dataOf(await send2("auto"));
|
|
127729
|
+
const bareId = this.idOf(data);
|
|
127730
|
+
if (!bareId) throw new Error("Environment import did not return a UID");
|
|
127731
|
+
return this.publicEnvironmentUid(data, bareId);
|
|
127732
|
+
});
|
|
127733
|
+
if (retried) return retried;
|
|
127734
|
+
}
|
|
127696
127735
|
throw error2;
|
|
127697
127736
|
}
|
|
127698
127737
|
});
|
|
@@ -127824,19 +127863,20 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127824
127863
|
private: false,
|
|
127825
127864
|
...environment ? { environment } : {}
|
|
127826
127865
|
};
|
|
127827
|
-
|
|
127828
|
-
|
|
127829
|
-
|
|
127830
|
-
|
|
127831
|
-
|
|
127832
|
-
|
|
127833
|
-
|
|
127834
|
-
|
|
127835
|
-
|
|
127836
|
-
|
|
127837
|
-
|
|
127838
|
-
|
|
127839
|
-
|
|
127866
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
127867
|
+
{
|
|
127868
|
+
service: "mock",
|
|
127869
|
+
method: "post",
|
|
127870
|
+
path: `/mocks?workspace=${ws}`,
|
|
127871
|
+
body,
|
|
127872
|
+
...fallback ? { fallback } : {}
|
|
127873
|
+
},
|
|
127874
|
+
// Unsafe create: never blind re-POST. An ESOCKETTIMEDOUT after accept
|
|
127875
|
+
// may still have created the mock; reconcile via discovery below and
|
|
127876
|
+
// let the orchestrator retry the whole create-or-adopt cycle.
|
|
127877
|
+
{ retryTransient: false }
|
|
127878
|
+
);
|
|
127879
|
+
const parseMock = (response) => {
|
|
127840
127880
|
const record = this.dataOf(response);
|
|
127841
127881
|
const uid = this.idOf(record);
|
|
127842
127882
|
if (!uid) {
|
|
@@ -127846,6 +127886,9 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127846
127886
|
uid,
|
|
127847
127887
|
url: String(record?.url ?? record?.mockUrl ?? "").trim()
|
|
127848
127888
|
};
|
|
127889
|
+
};
|
|
127890
|
+
try {
|
|
127891
|
+
return parseMock(await send2());
|
|
127849
127892
|
} catch (error2) {
|
|
127850
127893
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127851
127894
|
() => this.findMockByCollection(collection, environment, mockName),
|
|
@@ -127854,6 +127897,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127854
127897
|
if (adopted) {
|
|
127855
127898
|
return { uid: adopted.uid, url: adopted.mockUrl };
|
|
127856
127899
|
}
|
|
127900
|
+
if (adopted === void 0) {
|
|
127901
|
+
const retried = await this.resendAbsentCreate(async () => parseMock(await send2("auto")));
|
|
127902
|
+
if (retried) return retried;
|
|
127903
|
+
}
|
|
127857
127904
|
throw error2;
|
|
127858
127905
|
}
|
|
127859
127906
|
});
|
|
@@ -127960,21 +128007,25 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127960
128007
|
distribution: null,
|
|
127961
128008
|
...environment ? { environment } : {}
|
|
127962
128009
|
};
|
|
127963
|
-
|
|
127964
|
-
|
|
127965
|
-
|
|
127966
|
-
|
|
127967
|
-
|
|
127968
|
-
|
|
127969
|
-
|
|
127970
|
-
|
|
127971
|
-
|
|
127972
|
-
|
|
128010
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
128011
|
+
{
|
|
128012
|
+
service: "monitors",
|
|
128013
|
+
method: "post",
|
|
128014
|
+
path: `/jobTemplates?workspace=${ws}`,
|
|
128015
|
+
body,
|
|
128016
|
+
...fallback ? { fallback } : {}
|
|
128017
|
+
},
|
|
128018
|
+
{ retryTransient: false }
|
|
128019
|
+
);
|
|
128020
|
+
const parseMonitor = (response) => {
|
|
127973
128021
|
const uid = this.idOf(this.dataOf(response));
|
|
127974
128022
|
if (!uid) {
|
|
127975
128023
|
throw new Error("Monitor create did not return a UID");
|
|
127976
128024
|
}
|
|
127977
128025
|
return uid;
|
|
128026
|
+
};
|
|
128027
|
+
try {
|
|
128028
|
+
return parseMonitor(await send2());
|
|
127978
128029
|
} catch (error2) {
|
|
127979
128030
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127980
128031
|
() => this.findMonitorByCollection(collection, environment, monitorName),
|
|
@@ -127983,6 +128034,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127983
128034
|
if (adopted?.uid) {
|
|
127984
128035
|
return adopted.uid;
|
|
127985
128036
|
}
|
|
128037
|
+
if (adopted === void 0) {
|
|
128038
|
+
const retried = await this.resendAbsentCreate(async () => parseMonitor(await send2("auto")));
|
|
128039
|
+
if (retried) return retried;
|
|
128040
|
+
}
|
|
127986
128041
|
throw error2;
|
|
127987
128042
|
}
|
|
127988
128043
|
});
|
|
@@ -128211,6 +128266,7 @@ var AccessTokenGatewayClient = class {
|
|
|
128211
128266
|
fetchImpl;
|
|
128212
128267
|
secretMasker;
|
|
128213
128268
|
maxRetries;
|
|
128269
|
+
fallbackBaseUrl;
|
|
128214
128270
|
retryBaseDelayMs;
|
|
128215
128271
|
sleepImpl;
|
|
128216
128272
|
constructor(options) {
|
|
@@ -128223,6 +128279,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128223
128279
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
128224
128280
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.tokenProvider.current()]);
|
|
128225
128281
|
this.maxRetries = options.maxRetries ?? 3;
|
|
128282
|
+
const fallbackEnv = typeof process !== "undefined" ? process.env?.POSTMAN_ITEM_CREATE_FALLBACK : void 0;
|
|
128283
|
+
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
128226
128284
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
128227
128285
|
this.sleepImpl = options.sleepImpl ?? defaultSleep;
|
|
128228
128286
|
}
|
|
@@ -128241,8 +128299,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128241
128299
|
}
|
|
128242
128300
|
return headers;
|
|
128243
128301
|
}
|
|
128244
|
-
async send(request) {
|
|
128245
|
-
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
128302
|
+
async send(request, baseUrl) {
|
|
128303
|
+
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
128246
128304
|
return this.fetchImpl(url, {
|
|
128247
128305
|
method: "POST",
|
|
128248
128306
|
headers: this.buildHeaders(request.headers),
|
|
@@ -128255,6 +128313,43 @@ var AccessTokenGatewayClient = class {
|
|
|
128255
128313
|
})
|
|
128256
128314
|
});
|
|
128257
128315
|
}
|
|
128316
|
+
/**
|
|
128317
|
+
* One cold, serial attempt against the fallback base URL after the primary
|
|
128318
|
+
* budget is exhausted on a transient failure. Never hedged in parallel with
|
|
128319
|
+
* the primary; only fires when the request would otherwise throw. Callers
|
|
128320
|
+
* with `retryTransient: false` still reconcile first — the fallback attempt
|
|
128321
|
+
* here is the resend, so it is only used for requests whose mutation is
|
|
128322
|
+
* known idempotent or already reconciled by the caller's adopt-on-ambiguous
|
|
128323
|
+
* loop.
|
|
128324
|
+
*/
|
|
128325
|
+
async tryFallback(request) {
|
|
128326
|
+
if (!this.fallbackBaseUrl) return null;
|
|
128327
|
+
try {
|
|
128328
|
+
return await this.send(request, this.fallbackBaseUrl);
|
|
128329
|
+
} catch {
|
|
128330
|
+
return null;
|
|
128331
|
+
}
|
|
128332
|
+
}
|
|
128333
|
+
/**
|
|
128334
|
+
* Run the fallback attempt and classify its response the same way the
|
|
128335
|
+
* primary path would. Returns the success response, or null when the
|
|
128336
|
+
* fallback also failed transiently (caller then throws the original error).
|
|
128337
|
+
* Non-transient fallback failures (4xx) surface as their own HttpError since
|
|
128338
|
+
* they are the freshest authoritative answer.
|
|
128339
|
+
*/
|
|
128340
|
+
fallbackEligible(request, retryTransient) {
|
|
128341
|
+
if (!this.fallbackBaseUrl) return false;
|
|
128342
|
+
return retryTransient || request.fallback === "auto";
|
|
128343
|
+
}
|
|
128344
|
+
async attemptFallback(request, retryTransient) {
|
|
128345
|
+
if (!this.fallbackEligible(request, retryTransient)) return null;
|
|
128346
|
+
const response = await this.tryFallback(request);
|
|
128347
|
+
if (!response) return null;
|
|
128348
|
+
if (response.ok) return response;
|
|
128349
|
+
const body = await response.text().catch(() => "");
|
|
128350
|
+
if (isRetryableSafeReadResponse(response.status)) return null;
|
|
128351
|
+
throw this.toHttpError(request, response, body);
|
|
128352
|
+
}
|
|
128258
128353
|
/**
|
|
128259
128354
|
* Send a gateway request, refreshing the token once on an auth failure and
|
|
128260
128355
|
* optionally retrying transient downstream failures (5xx / Bifrost read
|
|
@@ -128277,6 +128372,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128277
128372
|
await this.sleepImpl(delay);
|
|
128278
128373
|
continue;
|
|
128279
128374
|
}
|
|
128375
|
+
const fallbackResponse2 = await this.attemptFallback(request, retryTransient);
|
|
128376
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
128280
128377
|
throw error2;
|
|
128281
128378
|
}
|
|
128282
128379
|
if (response.ok) {
|
|
@@ -128298,6 +128395,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128298
128395
|
await this.sleepImpl(delay);
|
|
128299
128396
|
continue;
|
|
128300
128397
|
}
|
|
128398
|
+
const fallbackResponse = await this.attemptFallback(request, retryTransient);
|
|
128399
|
+
if (fallbackResponse) return fallbackResponse;
|
|
128301
128400
|
throw this.toHttpError(request, response, body);
|
|
128302
128401
|
}
|
|
128303
128402
|
}
|
|
@@ -128924,6 +129023,7 @@ function resolveInputs(env = process.env) {
|
|
|
128924
129023
|
postmanStack,
|
|
128925
129024
|
postmanApiBase: endpointProfile.apiBaseUrl,
|
|
128926
129025
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
129026
|
+
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
128927
129027
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
128928
129028
|
postmanIapubBase: endpointProfile.iapubBaseUrl
|
|
128929
129029
|
};
|
|
@@ -130065,6 +130165,8 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130065
130165
|
const gateway = new AccessTokenGatewayClient({
|
|
130066
130166
|
tokenProvider,
|
|
130067
130167
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
130168
|
+
// No fallback on the org-mode probe: the expected non-org 400 must
|
|
130169
|
+
// surface verbatim, not be re-fired against the /_api alias.
|
|
130068
130170
|
secretMasker: masker
|
|
130069
130171
|
});
|
|
130070
130172
|
const squads = await gateway.getSquads(teamId);
|
|
@@ -130120,6 +130222,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
130120
130222
|
const gateway = new AccessTokenGatewayClient({
|
|
130121
130223
|
tokenProvider,
|
|
130122
130224
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
130225
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
130123
130226
|
teamId: resolved.teamId,
|
|
130124
130227
|
orgMode: inputs.orgMode,
|
|
130125
130228
|
secretMasker: masker
|