@postman-cse/onboarding-bootstrap 2.9.6 → 2.9.8
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 +85 -16
- package/dist/cli.cjs +84 -16
- package/dist/index.cjs +85 -16
- package/package.json +2 -2
package/dist/action.cjs
CHANGED
|
@@ -258195,6 +258195,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
258195
258195
|
prod: {
|
|
258196
258196
|
apiBaseUrl: "https://api.getpostman.com",
|
|
258197
258197
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
258198
|
+
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
258198
258199
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
258199
258200
|
gatewayBaseUrl: "https://gateway.postman.com",
|
|
258200
258201
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
@@ -258202,6 +258203,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
258202
258203
|
beta: {
|
|
258203
258204
|
apiBaseUrl: "https://api.getpostman-beta.com",
|
|
258204
258205
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
258206
|
+
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
258205
258207
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
258206
258208
|
gatewayBaseUrl: "https://gateway.postman-beta.com",
|
|
258207
258209
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
@@ -265363,31 +265365,42 @@ ${error2.responseBody ?? ""}`
|
|
|
265363
265365
|
method: "post",
|
|
265364
265366
|
path: `/v3/collections/${cid}/items/`,
|
|
265365
265367
|
retry: "none",
|
|
265368
|
+
// The transport's cold /_api fallback only fires after the primary
|
|
265369
|
+
// budget is exhausted; by then this loop has reconciled the item as
|
|
265370
|
+
// absent (match == null), so a fallback resend cannot duplicate a
|
|
265371
|
+
// committed create.
|
|
265372
|
+
fallback: "auto",
|
|
265366
265373
|
headers: { "X-Entity-Type": kind },
|
|
265367
265374
|
body: this.buildItemCreateBody(item, parentId)
|
|
265368
265375
|
});
|
|
265369
265376
|
} catch (error2) {
|
|
265370
265377
|
if (!isAmbiguousTransportError(error2)) throw error2;
|
|
265371
265378
|
const name = String(item.name ?? "Untitled");
|
|
265372
|
-
const
|
|
265373
|
-
|
|
265374
|
-
|
|
265375
|
-
|
|
265376
|
-
|
|
265377
|
-
|
|
265378
|
-
|
|
265379
|
-
|
|
265380
|
-
|
|
265381
|
-
|
|
265382
|
-
|
|
265383
|
-
|
|
265384
|
-
|
|
265379
|
+
const findCommittedItem = async () => {
|
|
265380
|
+
const matches = (await this.listCollectionItems(cid)).filter((candidate) => {
|
|
265381
|
+
if (String(candidate.name ?? candidate.title ?? "") !== name) return false;
|
|
265382
|
+
if (String(candidate.$kind ?? candidate.type ?? "http-request") !== kind) return false;
|
|
265383
|
+
const position = asRecord8(candidate.position);
|
|
265384
|
+
const parent = asRecord8(position?.parent);
|
|
265385
|
+
const candidateParent = String(parent?.id ?? position?.parent ?? candidate.parent ?? "").trim();
|
|
265386
|
+
return Boolean(candidateParent) && this.bareModelId(candidateParent) === this.bareModelId(parentId);
|
|
265387
|
+
});
|
|
265388
|
+
return adoptExactMatch(
|
|
265389
|
+
`collection-item:${cid}:${parentId}:${kind}:${name}`,
|
|
265390
|
+
matches,
|
|
265391
|
+
(candidate) => String(candidate.id ?? "")
|
|
265392
|
+
);
|
|
265393
|
+
};
|
|
265394
|
+
let match = await findCommittedItem();
|
|
265395
|
+
if (!match) {
|
|
265396
|
+
await this.sleep(fullJitterDelayMs(attempt - 1, 300, 2e3, this.random));
|
|
265397
|
+
match = await findCommittedItem();
|
|
265398
|
+
}
|
|
265385
265399
|
if (match) {
|
|
265386
265400
|
created = { data: { id: match.id } };
|
|
265387
265401
|
} else {
|
|
265388
265402
|
const retriable = error2 instanceof HttpError && error2.status >= 500;
|
|
265389
265403
|
if (!retriable || attempt === maxAttempts) throw error2;
|
|
265390
|
-
await this.sleep(fullJitterDelayMs(attempt - 1, 300, 2e3, this.random));
|
|
265391
265404
|
continue;
|
|
265392
265405
|
}
|
|
265393
265406
|
}
|
|
@@ -265734,6 +265747,7 @@ var AccessTokenGatewayClient = class {
|
|
|
265734
265747
|
orgMode;
|
|
265735
265748
|
fetchImpl;
|
|
265736
265749
|
secretMasker;
|
|
265750
|
+
fallbackBaseUrl;
|
|
265737
265751
|
maxRetries;
|
|
265738
265752
|
retryBaseDelayMs;
|
|
265739
265753
|
retryMaxDelayMs;
|
|
@@ -265749,6 +265763,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265749
265763
|
this.orgMode = options.orgMode ?? false;
|
|
265750
265764
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
265751
265765
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.tokenProvider.current()]);
|
|
265766
|
+
const fallbackEnv = typeof process !== "undefined" ? process.env?.POSTMAN_ITEM_CREATE_FALLBACK : void 0;
|
|
265767
|
+
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
265752
265768
|
this.maxRetries = options.maxRetries ?? 3;
|
|
265753
265769
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
265754
265770
|
this.retryMaxDelayMs = options.retryMaxDelayMs ?? 5e3;
|
|
@@ -265771,8 +265787,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265771
265787
|
}
|
|
265772
265788
|
return headers;
|
|
265773
265789
|
}
|
|
265774
|
-
async send(request) {
|
|
265775
|
-
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
265790
|
+
async send(request, baseUrl) {
|
|
265791
|
+
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
265776
265792
|
const controller = new AbortController();
|
|
265777
265793
|
const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
265778
265794
|
try {
|
|
@@ -265802,6 +265818,50 @@ var AccessTokenGatewayClient = class {
|
|
|
265802
265818
|
* 200 envelope carrying an inner collection-service error is treated as that
|
|
265803
265819
|
* inner status. The auth-refresh-once path is independent of the retry budget.
|
|
265804
265820
|
*/
|
|
265821
|
+
/**
|
|
265822
|
+
* One cold, serial attempt against the fallback base URL after the primary
|
|
265823
|
+
* budget is exhausted on a transient failure. Never hedged in parallel with
|
|
265824
|
+
* the primary; only fires when the request would otherwise throw. Callers
|
|
265825
|
+
* with `retry: 'none'` still reconcile first — the fallback attempt here is
|
|
265826
|
+
* the resend, so it is only used for requests whose mutation is known
|
|
265827
|
+
* idempotent or already reconciled by the caller's adopt-on-ambiguous loop.
|
|
265828
|
+
*/
|
|
265829
|
+
async tryFallback(request) {
|
|
265830
|
+
if (!this.fallbackBaseUrl) return null;
|
|
265831
|
+
try {
|
|
265832
|
+
return await this.send(request, this.fallbackBaseUrl);
|
|
265833
|
+
} catch {
|
|
265834
|
+
return null;
|
|
265835
|
+
}
|
|
265836
|
+
}
|
|
265837
|
+
/**
|
|
265838
|
+
* Run the fallback attempt and classify its response the same way the
|
|
265839
|
+
* primary path would. Returns the rebuilt success response, or null when the
|
|
265840
|
+
* fallback also failed transiently (caller then throws the original error).
|
|
265841
|
+
* Non-transient fallback failures (4xx, inner errors) surface as their own
|
|
265842
|
+
* HttpError since they are the freshest authoritative answer.
|
|
265843
|
+
*/
|
|
265844
|
+
fallbackEligible(request) {
|
|
265845
|
+
if (!this.fallbackBaseUrl) return false;
|
|
265846
|
+
const retryMode = request.retry ?? (request.method === "get" ? "safe" : "none");
|
|
265847
|
+
return retryMode === "safe" || request.fallback === "auto";
|
|
265848
|
+
}
|
|
265849
|
+
async attemptFallback(request) {
|
|
265850
|
+
if (!this.fallbackEligible(request)) return null;
|
|
265851
|
+
const response = await this.tryFallback(request);
|
|
265852
|
+
if (!response) return null;
|
|
265853
|
+
const body2 = await response.text().catch(() => "");
|
|
265854
|
+
if (response.ok) {
|
|
265855
|
+
const innerStatus = detectInnerError(body2);
|
|
265856
|
+
if (innerStatus !== null) {
|
|
265857
|
+
if (isTransientGatewayError(innerStatus, body2)) return null;
|
|
265858
|
+
throw this.toInnerHttpError(request, innerStatus, body2);
|
|
265859
|
+
}
|
|
265860
|
+
return this.rebuildResponse(response, body2);
|
|
265861
|
+
}
|
|
265862
|
+
if (isTransientGatewayError(response.status, body2)) return null;
|
|
265863
|
+
throw this.toHttpError(request, response, body2);
|
|
265864
|
+
}
|
|
265805
265865
|
async request(request) {
|
|
265806
265866
|
if (!this.tokenProvider.current() && this.tokenProvider.canRefresh()) {
|
|
265807
265867
|
await this.tokenProvider.refresh();
|
|
@@ -265819,6 +265879,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265819
265879
|
await this.sleepImpl(delay);
|
|
265820
265880
|
continue;
|
|
265821
265881
|
}
|
|
265882
|
+
const fallbackResponse2 = await this.attemptFallback(request);
|
|
265883
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
265822
265884
|
throw error2;
|
|
265823
265885
|
}
|
|
265824
265886
|
if (response.ok) {
|
|
@@ -265831,6 +265893,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265831
265893
|
await this.sleepImpl(delay);
|
|
265832
265894
|
continue;
|
|
265833
265895
|
}
|
|
265896
|
+
const fallbackResponse2 = await this.attemptFallback(request);
|
|
265897
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
265834
265898
|
throw this.toInnerHttpError(request, innerStatus, okBody);
|
|
265835
265899
|
}
|
|
265836
265900
|
return this.rebuildResponse(response, okBody);
|
|
@@ -265859,6 +265923,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265859
265923
|
await this.sleepImpl(delay);
|
|
265860
265924
|
continue;
|
|
265861
265925
|
}
|
|
265926
|
+
const fallbackResponse = await this.attemptFallback(request);
|
|
265927
|
+
if (fallbackResponse) return fallbackResponse;
|
|
265862
265928
|
throw this.toHttpError(request, response, body2);
|
|
265863
265929
|
}
|
|
265864
265930
|
}
|
|
@@ -311984,6 +312050,7 @@ function resolveInputs(env = process.env) {
|
|
|
311984
312050
|
postmanStack,
|
|
311985
312051
|
postmanApiBase: endpointProfile.apiBaseUrl,
|
|
311986
312052
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
312053
|
+
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
311987
312054
|
postmanGatewayBase: endpointProfile.gatewayBaseUrl,
|
|
311988
312055
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
311989
312056
|
postmanIapubBase: endpointProfile.iapubBaseUrl,
|
|
@@ -313738,6 +313805,7 @@ async function runAction(actionCore = core_exports, actionExec = exec_exports, a
|
|
|
313738
313805
|
gateway: new AccessTokenGatewayClient({
|
|
313739
313806
|
tokenProvider: probeProvider,
|
|
313740
313807
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
313808
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
313741
313809
|
teamId: inputs.teamId || "",
|
|
313742
313810
|
orgMode: false,
|
|
313743
313811
|
secretMasker: createSecretMasker([inputs.postmanApiKey, inputs.postmanAccessToken])
|
|
@@ -313860,6 +313928,7 @@ function createBootstrapDependencies(inputs, factories, orgMode = false) {
|
|
|
313860
313928
|
const gatewayClient = inputs.postmanAccessToken || inputs.postmanApiKey ? new AccessTokenGatewayClient({
|
|
313861
313929
|
tokenProvider,
|
|
313862
313930
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
313931
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
313863
313932
|
teamId: inputs.teamId || "",
|
|
313864
313933
|
orgMode,
|
|
313865
313934
|
secretMasker
|
package/dist/cli.cjs
CHANGED
|
@@ -256513,6 +256513,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
256513
256513
|
prod: {
|
|
256514
256514
|
apiBaseUrl: "https://api.getpostman.com",
|
|
256515
256515
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
256516
|
+
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
256516
256517
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
256517
256518
|
gatewayBaseUrl: "https://gateway.postman.com",
|
|
256518
256519
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
@@ -256520,6 +256521,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
256520
256521
|
beta: {
|
|
256521
256522
|
apiBaseUrl: "https://api.getpostman-beta.com",
|
|
256522
256523
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
256524
|
+
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
256523
256525
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
256524
256526
|
gatewayBaseUrl: "https://gateway.postman-beta.com",
|
|
256525
256527
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
@@ -263681,31 +263683,42 @@ ${error.responseBody ?? ""}`
|
|
|
263681
263683
|
method: "post",
|
|
263682
263684
|
path: `/v3/collections/${cid}/items/`,
|
|
263683
263685
|
retry: "none",
|
|
263686
|
+
// The transport's cold /_api fallback only fires after the primary
|
|
263687
|
+
// budget is exhausted; by then this loop has reconciled the item as
|
|
263688
|
+
// absent (match == null), so a fallback resend cannot duplicate a
|
|
263689
|
+
// committed create.
|
|
263690
|
+
fallback: "auto",
|
|
263684
263691
|
headers: { "X-Entity-Type": kind },
|
|
263685
263692
|
body: this.buildItemCreateBody(item, parentId)
|
|
263686
263693
|
});
|
|
263687
263694
|
} catch (error) {
|
|
263688
263695
|
if (!isAmbiguousTransportError(error)) throw error;
|
|
263689
263696
|
const name = String(item.name ?? "Untitled");
|
|
263690
|
-
const
|
|
263691
|
-
|
|
263692
|
-
|
|
263693
|
-
|
|
263694
|
-
|
|
263695
|
-
|
|
263696
|
-
|
|
263697
|
-
|
|
263698
|
-
|
|
263699
|
-
|
|
263700
|
-
|
|
263701
|
-
|
|
263702
|
-
|
|
263697
|
+
const findCommittedItem = async () => {
|
|
263698
|
+
const matches = (await this.listCollectionItems(cid)).filter((candidate) => {
|
|
263699
|
+
if (String(candidate.name ?? candidate.title ?? "") !== name) return false;
|
|
263700
|
+
if (String(candidate.$kind ?? candidate.type ?? "http-request") !== kind) return false;
|
|
263701
|
+
const position = asRecord8(candidate.position);
|
|
263702
|
+
const parent = asRecord8(position?.parent);
|
|
263703
|
+
const candidateParent = String(parent?.id ?? position?.parent ?? candidate.parent ?? "").trim();
|
|
263704
|
+
return Boolean(candidateParent) && this.bareModelId(candidateParent) === this.bareModelId(parentId);
|
|
263705
|
+
});
|
|
263706
|
+
return adoptExactMatch(
|
|
263707
|
+
`collection-item:${cid}:${parentId}:${kind}:${name}`,
|
|
263708
|
+
matches,
|
|
263709
|
+
(candidate) => String(candidate.id ?? "")
|
|
263710
|
+
);
|
|
263711
|
+
};
|
|
263712
|
+
let match = await findCommittedItem();
|
|
263713
|
+
if (!match) {
|
|
263714
|
+
await this.sleep(fullJitterDelayMs(attempt - 1, 300, 2e3, this.random));
|
|
263715
|
+
match = await findCommittedItem();
|
|
263716
|
+
}
|
|
263703
263717
|
if (match) {
|
|
263704
263718
|
created = { data: { id: match.id } };
|
|
263705
263719
|
} else {
|
|
263706
263720
|
const retriable = error instanceof HttpError && error.status >= 500;
|
|
263707
263721
|
if (!retriable || attempt === maxAttempts) throw error;
|
|
263708
|
-
await this.sleep(fullJitterDelayMs(attempt - 1, 300, 2e3, this.random));
|
|
263709
263722
|
continue;
|
|
263710
263723
|
}
|
|
263711
263724
|
}
|
|
@@ -264052,6 +264065,7 @@ var AccessTokenGatewayClient = class {
|
|
|
264052
264065
|
orgMode;
|
|
264053
264066
|
fetchImpl;
|
|
264054
264067
|
secretMasker;
|
|
264068
|
+
fallbackBaseUrl;
|
|
264055
264069
|
maxRetries;
|
|
264056
264070
|
retryBaseDelayMs;
|
|
264057
264071
|
retryMaxDelayMs;
|
|
@@ -264067,6 +264081,8 @@ var AccessTokenGatewayClient = class {
|
|
|
264067
264081
|
this.orgMode = options.orgMode ?? false;
|
|
264068
264082
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
264069
264083
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.tokenProvider.current()]);
|
|
264084
|
+
const fallbackEnv = typeof process !== "undefined" ? process.env?.POSTMAN_ITEM_CREATE_FALLBACK : void 0;
|
|
264085
|
+
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
264070
264086
|
this.maxRetries = options.maxRetries ?? 3;
|
|
264071
264087
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
264072
264088
|
this.retryMaxDelayMs = options.retryMaxDelayMs ?? 5e3;
|
|
@@ -264089,8 +264105,8 @@ var AccessTokenGatewayClient = class {
|
|
|
264089
264105
|
}
|
|
264090
264106
|
return headers;
|
|
264091
264107
|
}
|
|
264092
|
-
async send(request) {
|
|
264093
|
-
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
264108
|
+
async send(request, baseUrl) {
|
|
264109
|
+
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
264094
264110
|
const controller = new AbortController();
|
|
264095
264111
|
const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
264096
264112
|
try {
|
|
@@ -264120,6 +264136,50 @@ var AccessTokenGatewayClient = class {
|
|
|
264120
264136
|
* 200 envelope carrying an inner collection-service error is treated as that
|
|
264121
264137
|
* inner status. The auth-refresh-once path is independent of the retry budget.
|
|
264122
264138
|
*/
|
|
264139
|
+
/**
|
|
264140
|
+
* One cold, serial attempt against the fallback base URL after the primary
|
|
264141
|
+
* budget is exhausted on a transient failure. Never hedged in parallel with
|
|
264142
|
+
* the primary; only fires when the request would otherwise throw. Callers
|
|
264143
|
+
* with `retry: 'none'` still reconcile first — the fallback attempt here is
|
|
264144
|
+
* the resend, so it is only used for requests whose mutation is known
|
|
264145
|
+
* idempotent or already reconciled by the caller's adopt-on-ambiguous loop.
|
|
264146
|
+
*/
|
|
264147
|
+
async tryFallback(request) {
|
|
264148
|
+
if (!this.fallbackBaseUrl) return null;
|
|
264149
|
+
try {
|
|
264150
|
+
return await this.send(request, this.fallbackBaseUrl);
|
|
264151
|
+
} catch {
|
|
264152
|
+
return null;
|
|
264153
|
+
}
|
|
264154
|
+
}
|
|
264155
|
+
/**
|
|
264156
|
+
* Run the fallback attempt and classify its response the same way the
|
|
264157
|
+
* primary path would. Returns the rebuilt success response, or null when the
|
|
264158
|
+
* fallback also failed transiently (caller then throws the original error).
|
|
264159
|
+
* Non-transient fallback failures (4xx, inner errors) surface as their own
|
|
264160
|
+
* HttpError since they are the freshest authoritative answer.
|
|
264161
|
+
*/
|
|
264162
|
+
fallbackEligible(request) {
|
|
264163
|
+
if (!this.fallbackBaseUrl) return false;
|
|
264164
|
+
const retryMode = request.retry ?? (request.method === "get" ? "safe" : "none");
|
|
264165
|
+
return retryMode === "safe" || request.fallback === "auto";
|
|
264166
|
+
}
|
|
264167
|
+
async attemptFallback(request) {
|
|
264168
|
+
if (!this.fallbackEligible(request)) return null;
|
|
264169
|
+
const response = await this.tryFallback(request);
|
|
264170
|
+
if (!response) return null;
|
|
264171
|
+
const body2 = await response.text().catch(() => "");
|
|
264172
|
+
if (response.ok) {
|
|
264173
|
+
const innerStatus = detectInnerError(body2);
|
|
264174
|
+
if (innerStatus !== null) {
|
|
264175
|
+
if (isTransientGatewayError(innerStatus, body2)) return null;
|
|
264176
|
+
throw this.toInnerHttpError(request, innerStatus, body2);
|
|
264177
|
+
}
|
|
264178
|
+
return this.rebuildResponse(response, body2);
|
|
264179
|
+
}
|
|
264180
|
+
if (isTransientGatewayError(response.status, body2)) return null;
|
|
264181
|
+
throw this.toHttpError(request, response, body2);
|
|
264182
|
+
}
|
|
264123
264183
|
async request(request) {
|
|
264124
264184
|
if (!this.tokenProvider.current() && this.tokenProvider.canRefresh()) {
|
|
264125
264185
|
await this.tokenProvider.refresh();
|
|
@@ -264137,6 +264197,8 @@ var AccessTokenGatewayClient = class {
|
|
|
264137
264197
|
await this.sleepImpl(delay);
|
|
264138
264198
|
continue;
|
|
264139
264199
|
}
|
|
264200
|
+
const fallbackResponse2 = await this.attemptFallback(request);
|
|
264201
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
264140
264202
|
throw error;
|
|
264141
264203
|
}
|
|
264142
264204
|
if (response.ok) {
|
|
@@ -264149,6 +264211,8 @@ var AccessTokenGatewayClient = class {
|
|
|
264149
264211
|
await this.sleepImpl(delay);
|
|
264150
264212
|
continue;
|
|
264151
264213
|
}
|
|
264214
|
+
const fallbackResponse2 = await this.attemptFallback(request);
|
|
264215
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
264152
264216
|
throw this.toInnerHttpError(request, innerStatus, okBody);
|
|
264153
264217
|
}
|
|
264154
264218
|
return this.rebuildResponse(response, okBody);
|
|
@@ -264177,6 +264241,8 @@ var AccessTokenGatewayClient = class {
|
|
|
264177
264241
|
await this.sleepImpl(delay);
|
|
264178
264242
|
continue;
|
|
264179
264243
|
}
|
|
264244
|
+
const fallbackResponse = await this.attemptFallback(request);
|
|
264245
|
+
if (fallbackResponse) return fallbackResponse;
|
|
264180
264246
|
throw this.toHttpError(request, response, body2);
|
|
264181
264247
|
}
|
|
264182
264248
|
}
|
|
@@ -310296,6 +310362,7 @@ function resolveInputs(env = process.env) {
|
|
|
310296
310362
|
postmanStack,
|
|
310297
310363
|
postmanApiBase: endpointProfile.apiBaseUrl,
|
|
310298
310364
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
310365
|
+
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
310299
310366
|
postmanGatewayBase: endpointProfile.gatewayBaseUrl,
|
|
310300
310367
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
310301
310368
|
postmanIapubBase: endpointProfile.iapubBaseUrl,
|
|
@@ -312014,6 +312081,7 @@ function createBootstrapDependencies(inputs, factories, orgMode = false) {
|
|
|
312014
312081
|
const gatewayClient = inputs.postmanAccessToken || inputs.postmanApiKey ? new AccessTokenGatewayClient({
|
|
312015
312082
|
tokenProvider,
|
|
312016
312083
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
312084
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
312017
312085
|
teamId: inputs.teamId || "",
|
|
312018
312086
|
orgMode,
|
|
312019
312087
|
secretMasker
|
package/dist/index.cjs
CHANGED
|
@@ -258220,6 +258220,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
258220
258220
|
prod: {
|
|
258221
258221
|
apiBaseUrl: "https://api.getpostman.com",
|
|
258222
258222
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
258223
|
+
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
258223
258224
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
258224
258225
|
gatewayBaseUrl: "https://gateway.postman.com",
|
|
258225
258226
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
@@ -258227,6 +258228,7 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
258227
258228
|
beta: {
|
|
258228
258229
|
apiBaseUrl: "https://api.getpostman-beta.com",
|
|
258229
258230
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
258231
|
+
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
258230
258232
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
258231
258233
|
gatewayBaseUrl: "https://gateway.postman-beta.com",
|
|
258232
258234
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
@@ -265388,31 +265390,42 @@ ${error2.responseBody ?? ""}`
|
|
|
265388
265390
|
method: "post",
|
|
265389
265391
|
path: `/v3/collections/${cid}/items/`,
|
|
265390
265392
|
retry: "none",
|
|
265393
|
+
// The transport's cold /_api fallback only fires after the primary
|
|
265394
|
+
// budget is exhausted; by then this loop has reconciled the item as
|
|
265395
|
+
// absent (match == null), so a fallback resend cannot duplicate a
|
|
265396
|
+
// committed create.
|
|
265397
|
+
fallback: "auto",
|
|
265391
265398
|
headers: { "X-Entity-Type": kind },
|
|
265392
265399
|
body: this.buildItemCreateBody(item, parentId)
|
|
265393
265400
|
});
|
|
265394
265401
|
} catch (error2) {
|
|
265395
265402
|
if (!isAmbiguousTransportError(error2)) throw error2;
|
|
265396
265403
|
const name = String(item.name ?? "Untitled");
|
|
265397
|
-
const
|
|
265398
|
-
|
|
265399
|
-
|
|
265400
|
-
|
|
265401
|
-
|
|
265402
|
-
|
|
265403
|
-
|
|
265404
|
-
|
|
265405
|
-
|
|
265406
|
-
|
|
265407
|
-
|
|
265408
|
-
|
|
265409
|
-
|
|
265404
|
+
const findCommittedItem = async () => {
|
|
265405
|
+
const matches = (await this.listCollectionItems(cid)).filter((candidate) => {
|
|
265406
|
+
if (String(candidate.name ?? candidate.title ?? "") !== name) return false;
|
|
265407
|
+
if (String(candidate.$kind ?? candidate.type ?? "http-request") !== kind) return false;
|
|
265408
|
+
const position = asRecord8(candidate.position);
|
|
265409
|
+
const parent = asRecord8(position?.parent);
|
|
265410
|
+
const candidateParent = String(parent?.id ?? position?.parent ?? candidate.parent ?? "").trim();
|
|
265411
|
+
return Boolean(candidateParent) && this.bareModelId(candidateParent) === this.bareModelId(parentId);
|
|
265412
|
+
});
|
|
265413
|
+
return adoptExactMatch(
|
|
265414
|
+
`collection-item:${cid}:${parentId}:${kind}:${name}`,
|
|
265415
|
+
matches,
|
|
265416
|
+
(candidate) => String(candidate.id ?? "")
|
|
265417
|
+
);
|
|
265418
|
+
};
|
|
265419
|
+
let match = await findCommittedItem();
|
|
265420
|
+
if (!match) {
|
|
265421
|
+
await this.sleep(fullJitterDelayMs(attempt - 1, 300, 2e3, this.random));
|
|
265422
|
+
match = await findCommittedItem();
|
|
265423
|
+
}
|
|
265410
265424
|
if (match) {
|
|
265411
265425
|
created = { data: { id: match.id } };
|
|
265412
265426
|
} else {
|
|
265413
265427
|
const retriable = error2 instanceof HttpError && error2.status >= 500;
|
|
265414
265428
|
if (!retriable || attempt === maxAttempts) throw error2;
|
|
265415
|
-
await this.sleep(fullJitterDelayMs(attempt - 1, 300, 2e3, this.random));
|
|
265416
265429
|
continue;
|
|
265417
265430
|
}
|
|
265418
265431
|
}
|
|
@@ -265759,6 +265772,7 @@ var AccessTokenGatewayClient = class {
|
|
|
265759
265772
|
orgMode;
|
|
265760
265773
|
fetchImpl;
|
|
265761
265774
|
secretMasker;
|
|
265775
|
+
fallbackBaseUrl;
|
|
265762
265776
|
maxRetries;
|
|
265763
265777
|
retryBaseDelayMs;
|
|
265764
265778
|
retryMaxDelayMs;
|
|
@@ -265774,6 +265788,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265774
265788
|
this.orgMode = options.orgMode ?? false;
|
|
265775
265789
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
265776
265790
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.tokenProvider.current()]);
|
|
265791
|
+
const fallbackEnv = typeof process !== "undefined" ? process.env?.POSTMAN_ITEM_CREATE_FALLBACK : void 0;
|
|
265792
|
+
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
265777
265793
|
this.maxRetries = options.maxRetries ?? 3;
|
|
265778
265794
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
265779
265795
|
this.retryMaxDelayMs = options.retryMaxDelayMs ?? 5e3;
|
|
@@ -265796,8 +265812,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265796
265812
|
}
|
|
265797
265813
|
return headers;
|
|
265798
265814
|
}
|
|
265799
|
-
async send(request) {
|
|
265800
|
-
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
265815
|
+
async send(request, baseUrl) {
|
|
265816
|
+
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
265801
265817
|
const controller = new AbortController();
|
|
265802
265818
|
const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
265803
265819
|
try {
|
|
@@ -265827,6 +265843,50 @@ var AccessTokenGatewayClient = class {
|
|
|
265827
265843
|
* 200 envelope carrying an inner collection-service error is treated as that
|
|
265828
265844
|
* inner status. The auth-refresh-once path is independent of the retry budget.
|
|
265829
265845
|
*/
|
|
265846
|
+
/**
|
|
265847
|
+
* One cold, serial attempt against the fallback base URL after the primary
|
|
265848
|
+
* budget is exhausted on a transient failure. Never hedged in parallel with
|
|
265849
|
+
* the primary; only fires when the request would otherwise throw. Callers
|
|
265850
|
+
* with `retry: 'none'` still reconcile first — the fallback attempt here is
|
|
265851
|
+
* the resend, so it is only used for requests whose mutation is known
|
|
265852
|
+
* idempotent or already reconciled by the caller's adopt-on-ambiguous loop.
|
|
265853
|
+
*/
|
|
265854
|
+
async tryFallback(request) {
|
|
265855
|
+
if (!this.fallbackBaseUrl) return null;
|
|
265856
|
+
try {
|
|
265857
|
+
return await this.send(request, this.fallbackBaseUrl);
|
|
265858
|
+
} catch {
|
|
265859
|
+
return null;
|
|
265860
|
+
}
|
|
265861
|
+
}
|
|
265862
|
+
/**
|
|
265863
|
+
* Run the fallback attempt and classify its response the same way the
|
|
265864
|
+
* primary path would. Returns the rebuilt success response, or null when the
|
|
265865
|
+
* fallback also failed transiently (caller then throws the original error).
|
|
265866
|
+
* Non-transient fallback failures (4xx, inner errors) surface as their own
|
|
265867
|
+
* HttpError since they are the freshest authoritative answer.
|
|
265868
|
+
*/
|
|
265869
|
+
fallbackEligible(request) {
|
|
265870
|
+
if (!this.fallbackBaseUrl) return false;
|
|
265871
|
+
const retryMode = request.retry ?? (request.method === "get" ? "safe" : "none");
|
|
265872
|
+
return retryMode === "safe" || request.fallback === "auto";
|
|
265873
|
+
}
|
|
265874
|
+
async attemptFallback(request) {
|
|
265875
|
+
if (!this.fallbackEligible(request)) return null;
|
|
265876
|
+
const response = await this.tryFallback(request);
|
|
265877
|
+
if (!response) return null;
|
|
265878
|
+
const body2 = await response.text().catch(() => "");
|
|
265879
|
+
if (response.ok) {
|
|
265880
|
+
const innerStatus = detectInnerError(body2);
|
|
265881
|
+
if (innerStatus !== null) {
|
|
265882
|
+
if (isTransientGatewayError(innerStatus, body2)) return null;
|
|
265883
|
+
throw this.toInnerHttpError(request, innerStatus, body2);
|
|
265884
|
+
}
|
|
265885
|
+
return this.rebuildResponse(response, body2);
|
|
265886
|
+
}
|
|
265887
|
+
if (isTransientGatewayError(response.status, body2)) return null;
|
|
265888
|
+
throw this.toHttpError(request, response, body2);
|
|
265889
|
+
}
|
|
265830
265890
|
async request(request) {
|
|
265831
265891
|
if (!this.tokenProvider.current() && this.tokenProvider.canRefresh()) {
|
|
265832
265892
|
await this.tokenProvider.refresh();
|
|
@@ -265844,6 +265904,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265844
265904
|
await this.sleepImpl(delay);
|
|
265845
265905
|
continue;
|
|
265846
265906
|
}
|
|
265907
|
+
const fallbackResponse2 = await this.attemptFallback(request);
|
|
265908
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
265847
265909
|
throw error2;
|
|
265848
265910
|
}
|
|
265849
265911
|
if (response.ok) {
|
|
@@ -265856,6 +265918,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265856
265918
|
await this.sleepImpl(delay);
|
|
265857
265919
|
continue;
|
|
265858
265920
|
}
|
|
265921
|
+
const fallbackResponse2 = await this.attemptFallback(request);
|
|
265922
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
265859
265923
|
throw this.toInnerHttpError(request, innerStatus, okBody);
|
|
265860
265924
|
}
|
|
265861
265925
|
return this.rebuildResponse(response, okBody);
|
|
@@ -265884,6 +265948,8 @@ var AccessTokenGatewayClient = class {
|
|
|
265884
265948
|
await this.sleepImpl(delay);
|
|
265885
265949
|
continue;
|
|
265886
265950
|
}
|
|
265951
|
+
const fallbackResponse = await this.attemptFallback(request);
|
|
265952
|
+
if (fallbackResponse) return fallbackResponse;
|
|
265887
265953
|
throw this.toHttpError(request, response, body2);
|
|
265888
265954
|
}
|
|
265889
265955
|
}
|
|
@@ -312009,6 +312075,7 @@ function resolveInputs(env = process.env) {
|
|
|
312009
312075
|
postmanStack,
|
|
312010
312076
|
postmanApiBase: endpointProfile.apiBaseUrl,
|
|
312011
312077
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
312078
|
+
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
312012
312079
|
postmanGatewayBase: endpointProfile.gatewayBaseUrl,
|
|
312013
312080
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
312014
312081
|
postmanIapubBase: endpointProfile.iapubBaseUrl,
|
|
@@ -313766,6 +313833,7 @@ async function runAction(actionCore = core_exports, actionExec = exec_exports, a
|
|
|
313766
313833
|
gateway: new AccessTokenGatewayClient({
|
|
313767
313834
|
tokenProvider: probeProvider,
|
|
313768
313835
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
313836
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
313769
313837
|
teamId: inputs.teamId || "",
|
|
313770
313838
|
orgMode: false,
|
|
313771
313839
|
secretMasker: createSecretMasker([inputs.postmanApiKey, inputs.postmanAccessToken])
|
|
@@ -313888,6 +313956,7 @@ function createBootstrapDependencies(inputs, factories, orgMode = false) {
|
|
|
313888
313956
|
const gatewayClient = inputs.postmanAccessToken || inputs.postmanApiKey ? new AccessTokenGatewayClient({
|
|
313889
313957
|
tokenProvider,
|
|
313890
313958
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
313959
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
313891
313960
|
teamId: inputs.teamId || "",
|
|
313892
313961
|
orgMode,
|
|
313893
313962
|
secretMasker
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postman-cse/onboarding-bootstrap",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.8",
|
|
4
4
|
"description": "Bootstrap Postman workspaces, specs, and collections from OpenAPI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -79,4 +79,4 @@
|
|
|
79
79
|
"type": "git",
|
|
80
80
|
"url": "https://github.com/postman-cs/postman-bootstrap-action"
|
|
81
81
|
}
|
|
82
|
-
}
|
|
82
|
+
}
|