@postman-cse/onboarding-repo-sync 2.1.1 → 2.1.3
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/README.md +2 -0
- package/dist/action.cjs +376 -138
- package/dist/cli.cjs +376 -138
- package/dist/index.cjs +376 -138
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -125394,12 +125394,20 @@ async function retry(operation, options = {}) {
|
|
|
125394
125394
|
}
|
|
125395
125395
|
|
|
125396
125396
|
// src/lib/postman/postman-gateway-assets-client.ts
|
|
125397
|
+
var MAX_CREATE_FLIGHTS = 256;
|
|
125398
|
+
var createFlights = /* @__PURE__ */ new Map();
|
|
125397
125399
|
var PostmanGatewayAssetsClient = class {
|
|
125398
125400
|
gateway;
|
|
125399
125401
|
workspaceId;
|
|
125402
|
+
sleep;
|
|
125403
|
+
reconcileAttempts;
|
|
125404
|
+
reconcileDelayMs;
|
|
125400
125405
|
constructor(options) {
|
|
125401
125406
|
this.gateway = options.gateway;
|
|
125402
125407
|
this.workspaceId = String(options.workspaceId || "").trim();
|
|
125408
|
+
this.sleep = options.sleep ?? sleep;
|
|
125409
|
+
this.reconcileAttempts = Math.max(1, options.reconcileAttempts ?? 3);
|
|
125410
|
+
this.reconcileDelayMs = Math.max(0, options.reconcileDelayMs ?? 500);
|
|
125403
125411
|
}
|
|
125404
125412
|
asRecord(value) {
|
|
125405
125413
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
@@ -125429,8 +125437,64 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125429
125437
|
const parts = trimmed.split("-");
|
|
125430
125438
|
return parts.length >= 6 ? parts.slice(1).join("-") : trimmed;
|
|
125431
125439
|
}
|
|
125432
|
-
|
|
125433
|
-
|
|
125440
|
+
isAmbiguousCreateOutcome(error) {
|
|
125441
|
+
if (error instanceof HttpError) {
|
|
125442
|
+
return error.status === 408 || error.status === 429 || error.status >= 500;
|
|
125443
|
+
}
|
|
125444
|
+
return error instanceof Error;
|
|
125445
|
+
}
|
|
125446
|
+
isRetryableIdempotentWriteOutcome(error) {
|
|
125447
|
+
if (error instanceof HttpError) {
|
|
125448
|
+
return error.status === 408 || error.status === 429 || error.status >= 500;
|
|
125449
|
+
}
|
|
125450
|
+
return error instanceof Error;
|
|
125451
|
+
}
|
|
125452
|
+
selectExactMatch(kind, identity, matches) {
|
|
125453
|
+
if (matches.length > 1) {
|
|
125454
|
+
const ids = matches.map((match) => match.uid).join(", ");
|
|
125455
|
+
throw new Error(
|
|
125456
|
+
`Multiple ${kind}s match ${identity}: ${ids}. Refusing to choose one; remove duplicates or pass an explicit asset ID.`
|
|
125457
|
+
);
|
|
125458
|
+
}
|
|
125459
|
+
return matches[0] ?? null;
|
|
125460
|
+
}
|
|
125461
|
+
async singleFlight(key, fingerprint, kind, operation) {
|
|
125462
|
+
const existing = createFlights.get(key);
|
|
125463
|
+
if (existing) {
|
|
125464
|
+
if (existing.fingerprint !== fingerprint) {
|
|
125465
|
+
throw new Error(`Incompatible concurrent ${kind} create for ${key}`);
|
|
125466
|
+
}
|
|
125467
|
+
return existing.promise;
|
|
125468
|
+
}
|
|
125469
|
+
if (createFlights.size >= MAX_CREATE_FLIGHTS) {
|
|
125470
|
+
throw new Error(`Too many concurrent Postman asset creates (limit ${MAX_CREATE_FLIGHTS})`);
|
|
125471
|
+
}
|
|
125472
|
+
const pending = operation().finally(() => {
|
|
125473
|
+
if (createFlights.get(key)?.promise === pending) {
|
|
125474
|
+
createFlights.delete(key);
|
|
125475
|
+
}
|
|
125476
|
+
});
|
|
125477
|
+
createFlights.set(key, { fingerprint, promise: pending });
|
|
125478
|
+
return pending;
|
|
125479
|
+
}
|
|
125480
|
+
async discoverAfterAmbiguousCreate(discover, error) {
|
|
125481
|
+
if (!this.isAmbiguousCreateOutcome(error)) {
|
|
125482
|
+
return null;
|
|
125483
|
+
}
|
|
125484
|
+
for (let attempt = 0; attempt < this.reconcileAttempts; attempt += 1) {
|
|
125485
|
+
if (attempt > 0) {
|
|
125486
|
+
await this.sleep(this.reconcileDelayMs);
|
|
125487
|
+
}
|
|
125488
|
+
const found = await discover();
|
|
125489
|
+
if (found) {
|
|
125490
|
+
return found;
|
|
125491
|
+
}
|
|
125492
|
+
}
|
|
125493
|
+
return null;
|
|
125494
|
+
}
|
|
125495
|
+
publicEnvironmentUid(data, bareId) {
|
|
125496
|
+
const owner = String(data?.owner ?? "").trim();
|
|
125497
|
+
return owner && !bareId.startsWith(`${owner}-`) ? `${owner}-${bareId}` : bareId;
|
|
125434
125498
|
}
|
|
125435
125499
|
// --- environments (service: sync) ---
|
|
125436
125500
|
//
|
|
@@ -125441,9 +125505,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125441
125505
|
/**
|
|
125442
125506
|
* Create/upsert an environment through the sync service.
|
|
125443
125507
|
* POST /environment/import?workspace=:ws { id:<uuid>, name, values } ->
|
|
125444
|
-
* { data:{ id:<bare uuid>, owner } }. The id is generated once
|
|
125445
|
-
*
|
|
125446
|
-
*
|
|
125508
|
+
* { data:{ id:<bare uuid>, owner } }. The id is generated once for the
|
|
125509
|
+
* operation. Unsafe creates submit once (no blind retry); on an ambiguous
|
|
125510
|
+
* response the client discovers by exact workspace-scoped name before
|
|
125511
|
+
* failing.
|
|
125447
125512
|
*
|
|
125448
125513
|
* Returns the PUBLIC uid (`<owner>-<uuid>`), not the bare model id the sync
|
|
125449
125514
|
* import echoes: mock/monitor create reference the environment by its public
|
|
@@ -125453,33 +125518,54 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125453
125518
|
*/
|
|
125454
125519
|
async createEnvironment(workspaceId, name, values) {
|
|
125455
125520
|
const ws = workspaceId || this.workspaceId;
|
|
125456
|
-
const
|
|
125457
|
-
const
|
|
125458
|
-
|
|
125459
|
-
|
|
125460
|
-
|
|
125461
|
-
|
|
125462
|
-
|
|
125463
|
-
|
|
125464
|
-
|
|
125465
|
-
|
|
125466
|
-
|
|
125467
|
-
|
|
125468
|
-
|
|
125469
|
-
|
|
125470
|
-
|
|
125471
|
-
|
|
125472
|
-
|
|
125473
|
-
|
|
125474
|
-
|
|
125475
|
-
|
|
125476
|
-
|
|
125477
|
-
|
|
125478
|
-
|
|
125479
|
-
|
|
125480
|
-
|
|
125481
|
-
|
|
125482
|
-
|
|
125521
|
+
const envName = String(name ?? "").trim();
|
|
125522
|
+
const flightKey = `environment:${ws}:${envName}`;
|
|
125523
|
+
const normalizedValues = values.map((v) => ({
|
|
125524
|
+
key: v.key,
|
|
125525
|
+
value: v.value,
|
|
125526
|
+
type: v.type ?? "default",
|
|
125527
|
+
enabled: v.enabled ?? true
|
|
125528
|
+
}));
|
|
125529
|
+
return this.singleFlight(flightKey, JSON.stringify(normalizedValues), "environment", async () => {
|
|
125530
|
+
const existing = await this.findEnvironmentByName(ws, envName);
|
|
125531
|
+
if (existing?.uid) {
|
|
125532
|
+
await this.updateEnvironment(existing.uid, envName, values);
|
|
125533
|
+
return existing.uid;
|
|
125534
|
+
}
|
|
125535
|
+
const id = crypto.randomUUID();
|
|
125536
|
+
const body = {
|
|
125537
|
+
id,
|
|
125538
|
+
name: envName,
|
|
125539
|
+
values: normalizedValues
|
|
125540
|
+
};
|
|
125541
|
+
try {
|
|
125542
|
+
const response = await this.gateway.requestJson(
|
|
125543
|
+
{
|
|
125544
|
+
service: "sync",
|
|
125545
|
+
method: "post",
|
|
125546
|
+
path: `/environment/import?workspace=${ws}`,
|
|
125547
|
+
body
|
|
125548
|
+
},
|
|
125549
|
+
{ retryTransient: false }
|
|
125550
|
+
);
|
|
125551
|
+
const data = this.dataOf(response);
|
|
125552
|
+
const bareId = this.idOf(data);
|
|
125553
|
+
if (!bareId) {
|
|
125554
|
+
throw new Error("Environment import did not return a UID");
|
|
125555
|
+
}
|
|
125556
|
+
return this.publicEnvironmentUid(data, bareId);
|
|
125557
|
+
} catch (error) {
|
|
125558
|
+
const adopted = await this.discoverAfterAmbiguousCreate(async () => {
|
|
125559
|
+
const match = await this.findEnvironmentByName(ws, envName);
|
|
125560
|
+
return match?.uid ?? null;
|
|
125561
|
+
}, error);
|
|
125562
|
+
if (adopted) {
|
|
125563
|
+
await this.updateEnvironment(adopted, envName, values);
|
|
125564
|
+
return adopted;
|
|
125565
|
+
}
|
|
125566
|
+
throw error;
|
|
125567
|
+
}
|
|
125568
|
+
});
|
|
125483
125569
|
}
|
|
125484
125570
|
/**
|
|
125485
125571
|
* Update an existing environment through the sync service.
|
|
@@ -125509,7 +125595,7 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125509
125595
|
path: `/environment/${id}`,
|
|
125510
125596
|
body
|
|
125511
125597
|
}),
|
|
125512
|
-
{ maxAttempts: 5, delayMs: 2e3, backoffMultiplier: 2, maxDelayMs: 15e3, shouldRetry: (e) => this.
|
|
125598
|
+
{ maxAttempts: 5, delayMs: 2e3, backoffMultiplier: 2, maxDelayMs: 15e3, shouldRetry: (e) => this.isRetryableIdempotentWriteOutcome(e) }
|
|
125513
125599
|
);
|
|
125514
125600
|
}
|
|
125515
125601
|
/**
|
|
@@ -125533,13 +125619,37 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125533
125619
|
*/
|
|
125534
125620
|
async listEnvironments(workspaceId) {
|
|
125535
125621
|
const ws = workspaceId || this.workspaceId;
|
|
125536
|
-
const response = await this.gateway.requestJson(
|
|
125537
|
-
|
|
125538
|
-
|
|
125539
|
-
|
|
125540
|
-
|
|
125622
|
+
const response = await this.gateway.requestJson(
|
|
125623
|
+
{
|
|
125624
|
+
service: "sync",
|
|
125625
|
+
method: "post",
|
|
125626
|
+
path: `/list/environment?workspace=${ws}`
|
|
125627
|
+
},
|
|
125628
|
+
{ retryTransient: true }
|
|
125629
|
+
);
|
|
125541
125630
|
const items = Array.isArray(response?.data) ? response.data : [];
|
|
125542
|
-
return items.map((raw) => this.asRecord(raw)).filter((e) => e !== null).map((e) =>
|
|
125631
|
+
return items.map((raw) => this.asRecord(raw)).filter((e) => e !== null).map((e) => {
|
|
125632
|
+
const bareOrPublic = this.idOf(e);
|
|
125633
|
+
return {
|
|
125634
|
+
name: String(e.name ?? ""),
|
|
125635
|
+
uid: this.publicEnvironmentUid(e, bareOrPublic)
|
|
125636
|
+
};
|
|
125637
|
+
});
|
|
125638
|
+
}
|
|
125639
|
+
/** Exact name match within a workspace. Prefer tracked UIDs before calling. */
|
|
125640
|
+
async findEnvironmentByName(workspaceId, name) {
|
|
125641
|
+
const want = String(name ?? "").trim();
|
|
125642
|
+
if (!want) {
|
|
125643
|
+
return null;
|
|
125644
|
+
}
|
|
125645
|
+
const environments = await this.listEnvironments(workspaceId);
|
|
125646
|
+
const matches = environments.filter((entry) => entry.name === want);
|
|
125647
|
+
const match = this.selectExactMatch(
|
|
125648
|
+
"environment",
|
|
125649
|
+
`workspace ${workspaceId} and name "${want}"`,
|
|
125650
|
+
matches
|
|
125651
|
+
);
|
|
125652
|
+
return match?.uid ? { uid: match.uid, name: match.name } : null;
|
|
125543
125653
|
}
|
|
125544
125654
|
// --- collection read (service: collection, v3 export) ---
|
|
125545
125655
|
//
|
|
@@ -125569,32 +125679,51 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125569
125679
|
// --- mocks (service: mock) ---
|
|
125570
125680
|
async createMock(workspaceId, name, collectionUid, environmentUid) {
|
|
125571
125681
|
const ws = workspaceId || this.workspaceId;
|
|
125682
|
+
const mockName = String(name ?? "").trim();
|
|
125572
125683
|
const collection = String(collectionUid ?? "").trim();
|
|
125573
125684
|
const environment = String(environmentUid ?? "").trim();
|
|
125574
|
-
const
|
|
125575
|
-
|
|
125576
|
-
collection,
|
|
125577
|
-
|
|
125578
|
-
|
|
125579
|
-
|
|
125580
|
-
|
|
125581
|
-
|
|
125582
|
-
|
|
125583
|
-
|
|
125584
|
-
|
|
125585
|
-
|
|
125586
|
-
|
|
125587
|
-
|
|
125588
|
-
|
|
125589
|
-
|
|
125590
|
-
|
|
125591
|
-
|
|
125592
|
-
|
|
125593
|
-
|
|
125594
|
-
|
|
125595
|
-
|
|
125596
|
-
|
|
125597
|
-
|
|
125685
|
+
const flightKey = `mock:${ws}:${collection}:${environment}:${mockName}`;
|
|
125686
|
+
return this.singleFlight(flightKey, flightKey, "mock", async () => {
|
|
125687
|
+
const existing = await this.findMockByCollection(collection, environment, mockName);
|
|
125688
|
+
if (existing) {
|
|
125689
|
+
return { uid: existing.uid, url: existing.mockUrl };
|
|
125690
|
+
}
|
|
125691
|
+
const body = {
|
|
125692
|
+
name: mockName,
|
|
125693
|
+
collection,
|
|
125694
|
+
private: false,
|
|
125695
|
+
...environment ? { environment } : {}
|
|
125696
|
+
};
|
|
125697
|
+
try {
|
|
125698
|
+
const response = await this.gateway.requestJson(
|
|
125699
|
+
{
|
|
125700
|
+
service: "mock",
|
|
125701
|
+
method: "post",
|
|
125702
|
+
path: `/mocks?workspace=${ws}`,
|
|
125703
|
+
body
|
|
125704
|
+
},
|
|
125705
|
+
{ retryTransient: false }
|
|
125706
|
+
);
|
|
125707
|
+
const record = this.dataOf(response);
|
|
125708
|
+
const uid = this.idOf(record);
|
|
125709
|
+
if (!uid) {
|
|
125710
|
+
throw new Error("Mock create did not return a UID");
|
|
125711
|
+
}
|
|
125712
|
+
return {
|
|
125713
|
+
uid,
|
|
125714
|
+
url: String(record?.url ?? record?.mockUrl ?? "").trim()
|
|
125715
|
+
};
|
|
125716
|
+
} catch (error) {
|
|
125717
|
+
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
125718
|
+
() => this.findMockByCollection(collection, environment, mockName),
|
|
125719
|
+
error
|
|
125720
|
+
);
|
|
125721
|
+
if (adopted) {
|
|
125722
|
+
return { uid: adopted.uid, url: adopted.mockUrl };
|
|
125723
|
+
}
|
|
125724
|
+
throw error;
|
|
125725
|
+
}
|
|
125726
|
+
});
|
|
125598
125727
|
}
|
|
125599
125728
|
async listMocks() {
|
|
125600
125729
|
const response = await this.gateway.requestJson({
|
|
@@ -125623,10 +125752,19 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125623
125752
|
return false;
|
|
125624
125753
|
}
|
|
125625
125754
|
}
|
|
125626
|
-
async findMockByCollection(collectionUid) {
|
|
125755
|
+
async findMockByCollection(collectionUid, environmentUid, name) {
|
|
125627
125756
|
const mocks = await this.listMocks();
|
|
125628
125757
|
const want = String(collectionUid ?? "").trim();
|
|
125629
|
-
const
|
|
125758
|
+
const environment = String(environmentUid ?? "").trim();
|
|
125759
|
+
const mockName = String(name ?? "").trim();
|
|
125760
|
+
const matches = mocks.filter(
|
|
125761
|
+
(mock) => mock.collection === want && mock.environment === environment && mock.name === mockName
|
|
125762
|
+
);
|
|
125763
|
+
const match = this.selectExactMatch(
|
|
125764
|
+
"mock",
|
|
125765
|
+
`workspace ${this.workspaceId}, name "${mockName}", collection ${want}, and environment ${environment || "(none)"}`,
|
|
125766
|
+
matches
|
|
125767
|
+
);
|
|
125630
125768
|
return match ? { uid: match.uid, mockUrl: match.mockUrl } : null;
|
|
125631
125769
|
}
|
|
125632
125770
|
// --- monitors (service: monitors; collection-based = jobTemplates) ---
|
|
@@ -125643,32 +125781,51 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125643
125781
|
async createMonitor(workspaceId, name, collectionUid, environmentUid, cronSchedule) {
|
|
125644
125782
|
const ws = workspaceId || this.workspaceId;
|
|
125645
125783
|
const effectiveCron = cronSchedule && cronSchedule.trim() ? cronSchedule.trim() : "0 0 * * 0";
|
|
125784
|
+
const monitorName = String(name ?? "").trim();
|
|
125646
125785
|
const collection = String(collectionUid ?? "").trim();
|
|
125647
125786
|
const environment = String(environmentUid ?? "").trim();
|
|
125648
|
-
const
|
|
125649
|
-
|
|
125650
|
-
collection,
|
|
125651
|
-
|
|
125652
|
-
|
|
125653
|
-
|
|
125654
|
-
|
|
125655
|
-
|
|
125656
|
-
|
|
125657
|
-
|
|
125658
|
-
|
|
125659
|
-
|
|
125660
|
-
|
|
125661
|
-
|
|
125662
|
-
|
|
125663
|
-
|
|
125664
|
-
|
|
125665
|
-
|
|
125666
|
-
|
|
125667
|
-
|
|
125668
|
-
|
|
125669
|
-
|
|
125670
|
-
|
|
125671
|
-
|
|
125787
|
+
const flightKey = `monitor:${ws}:${collection}:${environment}:${monitorName}`;
|
|
125788
|
+
return this.singleFlight(flightKey, effectiveCron, "monitor", async () => {
|
|
125789
|
+
const existing = await this.findMonitorByCollection(collection, environment, monitorName);
|
|
125790
|
+
if (existing?.uid) {
|
|
125791
|
+
return existing.uid;
|
|
125792
|
+
}
|
|
125793
|
+
const body = {
|
|
125794
|
+
name: monitorName,
|
|
125795
|
+
collection,
|
|
125796
|
+
options: { strictSSL: false, followRedirects: true, requestTimeout: null, requestDelay: 0 },
|
|
125797
|
+
notifications: { onFailure: [], onError: [] },
|
|
125798
|
+
retry: {},
|
|
125799
|
+
schedule: { cronPattern: effectiveCron, timeZone: "UTC" },
|
|
125800
|
+
distribution: null,
|
|
125801
|
+
...environment ? { environment } : {}
|
|
125802
|
+
};
|
|
125803
|
+
try {
|
|
125804
|
+
const response = await this.gateway.requestJson(
|
|
125805
|
+
{
|
|
125806
|
+
service: "monitors",
|
|
125807
|
+
method: "post",
|
|
125808
|
+
path: `/jobTemplates?workspace=${ws}`,
|
|
125809
|
+
body
|
|
125810
|
+
},
|
|
125811
|
+
{ retryTransient: false }
|
|
125812
|
+
);
|
|
125813
|
+
const uid = this.idOf(this.dataOf(response));
|
|
125814
|
+
if (!uid) {
|
|
125815
|
+
throw new Error("Monitor create did not return a UID");
|
|
125816
|
+
}
|
|
125817
|
+
return uid;
|
|
125818
|
+
} catch (error) {
|
|
125819
|
+
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
125820
|
+
() => this.findMonitorByCollection(collection, environment, monitorName),
|
|
125821
|
+
error
|
|
125822
|
+
);
|
|
125823
|
+
if (adopted?.uid) {
|
|
125824
|
+
return adopted.uid;
|
|
125825
|
+
}
|
|
125826
|
+
throw error;
|
|
125827
|
+
}
|
|
125828
|
+
});
|
|
125672
125829
|
}
|
|
125673
125830
|
async listMonitors() {
|
|
125674
125831
|
const response = await this.gateway.requestJson({
|
|
@@ -125691,24 +125848,30 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125691
125848
|
return false;
|
|
125692
125849
|
}
|
|
125693
125850
|
}
|
|
125694
|
-
async findMonitorByCollection(collectionUid) {
|
|
125851
|
+
async findMonitorByCollection(collectionUid, environmentUid, name) {
|
|
125695
125852
|
const want = String(collectionUid ?? "").trim();
|
|
125696
|
-
const
|
|
125697
|
-
|
|
125698
|
-
|
|
125699
|
-
|
|
125700
|
-
|
|
125701
|
-
|
|
125702
|
-
const
|
|
125703
|
-
|
|
125853
|
+
const environment = String(environmentUid ?? "").trim();
|
|
125854
|
+
const monitorName = String(name ?? "").trim();
|
|
125855
|
+
const monitors = await this.listMonitors();
|
|
125856
|
+
const matches = monitors.filter(
|
|
125857
|
+
(monitor) => monitor.collectionUid === want && monitor.environmentUid === environment && monitor.name === monitorName
|
|
125858
|
+
);
|
|
125859
|
+
const match = this.selectExactMatch(
|
|
125860
|
+
"monitor",
|
|
125861
|
+
`workspace ${this.workspaceId}, name "${monitorName}", collection ${want}, and environment ${environment || "(none)"}`,
|
|
125862
|
+
matches
|
|
125863
|
+
);
|
|
125704
125864
|
return match?.uid ? { uid: match.uid, name: match.name } : null;
|
|
125705
125865
|
}
|
|
125706
125866
|
async runMonitor(uid) {
|
|
125707
|
-
await this.gateway.requestJson(
|
|
125708
|
-
|
|
125709
|
-
|
|
125710
|
-
|
|
125711
|
-
|
|
125867
|
+
await this.gateway.requestJson(
|
|
125868
|
+
{
|
|
125869
|
+
service: "monitors",
|
|
125870
|
+
method: "post",
|
|
125871
|
+
path: `/jobTemplates/${uid}/jobs`
|
|
125872
|
+
},
|
|
125873
|
+
{ retryTransient: false }
|
|
125874
|
+
);
|
|
125712
125875
|
}
|
|
125713
125876
|
};
|
|
125714
125877
|
|
|
@@ -125874,12 +126037,8 @@ async function mintAccessTokenIfNeeded(inputs, log, setSecret2, fetchImpl = fetc
|
|
|
125874
126037
|
function isExpiredAuthError(status, body) {
|
|
125875
126038
|
return status === 401 || body.includes("UNAUTHENTICATED") || body.includes("authenticationError");
|
|
125876
126039
|
}
|
|
125877
|
-
function
|
|
125878
|
-
|
|
125879
|
-
if (status >= 500 && (body.includes("ESOCKETTIMEDOUT") || body.includes("ETIMEDOUT") || body.includes("ECONNRESET") || body.includes("serverError") || body.includes("downstream"))) {
|
|
125880
|
-
return true;
|
|
125881
|
-
}
|
|
125882
|
-
return false;
|
|
126040
|
+
function isRetryableSafeReadResponse(status) {
|
|
126041
|
+
return status === 408 || status === 429 || status >= 500;
|
|
125883
126042
|
}
|
|
125884
126043
|
function defaultSleep(ms) {
|
|
125885
126044
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
@@ -125938,14 +126097,28 @@ var AccessTokenGatewayClient = class {
|
|
|
125938
126097
|
}
|
|
125939
126098
|
/**
|
|
125940
126099
|
* Send a gateway request, refreshing the token once on an auth failure and
|
|
125941
|
-
* retrying transient downstream failures (5xx / Bifrost read
|
|
125942
|
-
* exponential backoff.
|
|
125943
|
-
*
|
|
126100
|
+
* optionally retrying transient downstream failures (5xx / Bifrost read
|
|
126101
|
+
* timeouts) with exponential backoff. Safe reads keep transient retries;
|
|
126102
|
+
* unsafe creates pass `{ retryTransient: false }` and reconcile after an
|
|
126103
|
+
* ambiguous response instead of re-POSTing. Auth refresh remains independent
|
|
126104
|
+
* of the transient-retry budget.
|
|
125944
126105
|
*/
|
|
125945
|
-
async request(request) {
|
|
126106
|
+
async request(request, options = {}) {
|
|
126107
|
+
const retryTransient = options.retryTransient ?? request.method === "get";
|
|
125946
126108
|
let attempt = 0;
|
|
125947
126109
|
for (; ; ) {
|
|
125948
|
-
let response
|
|
126110
|
+
let response;
|
|
126111
|
+
try {
|
|
126112
|
+
response = await this.send(request);
|
|
126113
|
+
} catch (error) {
|
|
126114
|
+
if (retryTransient && attempt < this.maxRetries) {
|
|
126115
|
+
const delay = this.retryBaseDelayMs * 2 ** attempt;
|
|
126116
|
+
attempt += 1;
|
|
126117
|
+
await this.sleepImpl(delay);
|
|
126118
|
+
continue;
|
|
126119
|
+
}
|
|
126120
|
+
throw error;
|
|
126121
|
+
}
|
|
125949
126122
|
if (response.ok) {
|
|
125950
126123
|
return response;
|
|
125951
126124
|
}
|
|
@@ -125959,7 +126132,7 @@ var AccessTokenGatewayClient = class {
|
|
|
125959
126132
|
const retryBody = await response.text().catch(() => "");
|
|
125960
126133
|
throw this.toHttpError(request, response, retryBody);
|
|
125961
126134
|
}
|
|
125962
|
-
if (
|
|
126135
|
+
if (retryTransient && isRetryableSafeReadResponse(response.status) && attempt < this.maxRetries) {
|
|
125963
126136
|
const delay = this.retryBaseDelayMs * 2 ** attempt;
|
|
125964
126137
|
attempt += 1;
|
|
125965
126138
|
await this.sleepImpl(delay);
|
|
@@ -125969,8 +126142,8 @@ var AccessTokenGatewayClient = class {
|
|
|
125969
126142
|
}
|
|
125970
126143
|
}
|
|
125971
126144
|
/** Send a gateway request and parse the JSON body, or null when empty. */
|
|
125972
|
-
async requestJson(request) {
|
|
125973
|
-
const response = await this.request(request);
|
|
126145
|
+
async requestJson(request, options = {}) {
|
|
126146
|
+
const response = await this.request(request, options);
|
|
125974
126147
|
const text = await response.text().catch(() => "");
|
|
125975
126148
|
if (!text.trim()) {
|
|
125976
126149
|
return null;
|
|
@@ -126373,18 +126546,28 @@ async function upsertEnvironments(inputs, dependencies, resourcesState) {
|
|
|
126373
126546
|
for (const envName of inputs.environments) {
|
|
126374
126547
|
const runtimeUrl = String(inputs.envRuntimeUrls[envName] || "").trim();
|
|
126375
126548
|
const values = buildEnvironmentValues(envName, runtimeUrl);
|
|
126376
|
-
const
|
|
126377
|
-
|
|
126378
|
-
|
|
126379
|
-
|
|
126380
|
-
|
|
126381
|
-
|
|
126549
|
+
const displayName = `${inputs.projectName} - ${envName}`;
|
|
126550
|
+
let existingUid = String(envUids[envName] || "").trim();
|
|
126551
|
+
if (!existingUid) {
|
|
126552
|
+
const discovered = await dependencies.postman.findEnvironmentByName(
|
|
126553
|
+
inputs.workspaceId,
|
|
126554
|
+
displayName
|
|
126382
126555
|
);
|
|
126556
|
+
if (discovered?.uid) {
|
|
126557
|
+
existingUid = discovered.uid;
|
|
126558
|
+
dependencies.core.info(
|
|
126559
|
+
`Discovered existing environment for ${displayName}: ${existingUid}`
|
|
126560
|
+
);
|
|
126561
|
+
}
|
|
126562
|
+
}
|
|
126563
|
+
if (existingUid) {
|
|
126564
|
+
await dependencies.postman.updateEnvironment(existingUid, displayName, values);
|
|
126565
|
+
envUids[envName] = existingUid;
|
|
126383
126566
|
continue;
|
|
126384
126567
|
}
|
|
126385
126568
|
envUids[envName] = await dependencies.postman.createEnvironment(
|
|
126386
126569
|
inputs.workspaceId,
|
|
126387
|
-
|
|
126570
|
+
displayName,
|
|
126388
126571
|
values
|
|
126389
126572
|
);
|
|
126390
126573
|
}
|
|
@@ -126430,10 +126613,33 @@ function writeJsonFile(path5, content, normalize3 = false) {
|
|
|
126430
126613
|
const data = normalize3 ? stripVolatileFields(content) : content;
|
|
126431
126614
|
(0, import_node_fs3.writeFileSync)(path5, JSON.stringify(data, null, 2));
|
|
126432
126615
|
}
|
|
126433
|
-
function
|
|
126434
|
-
|
|
126435
|
-
|
|
126436
|
-
}
|
|
126616
|
+
function buildMappedSpecCloudKey(mappedSource, specSyncMode, releaseLabel) {
|
|
126617
|
+
if (specSyncMode !== "version") {
|
|
126618
|
+
return mappedSource;
|
|
126619
|
+
}
|
|
126620
|
+
const normalized = normalizeReleaseLabel(releaseLabel || "");
|
|
126621
|
+
if (!normalized) {
|
|
126622
|
+
return void 0;
|
|
126623
|
+
}
|
|
126624
|
+
return `${mappedSource}#release=${normalized}`;
|
|
126625
|
+
}
|
|
126626
|
+
function resolveDurableWorkspaceId(options) {
|
|
126627
|
+
const { candidateId, priorId, workspaceLinkEnabled, workspaceLinkStatus } = options;
|
|
126628
|
+
const candidate = candidateId.trim();
|
|
126629
|
+
const prior = priorId?.trim() || void 0;
|
|
126630
|
+
if (!workspaceLinkEnabled) {
|
|
126631
|
+
return candidate || prior;
|
|
126632
|
+
}
|
|
126633
|
+
if (workspaceLinkStatus === "success") {
|
|
126634
|
+
return candidate || void 0;
|
|
126635
|
+
}
|
|
126636
|
+
return prior === candidate ? prior : void 0;
|
|
126637
|
+
}
|
|
126638
|
+
function buildResourcesManifest(workspaceId, collectionMap, envMap, artifactDir, localSpecRefs, mappedSpecRef, specId, existingSpecs) {
|
|
126639
|
+
const manifest = {};
|
|
126640
|
+
if (workspaceId) {
|
|
126641
|
+
manifest.workspace = { id: workspaceId };
|
|
126642
|
+
}
|
|
126437
126643
|
const localResources = {};
|
|
126438
126644
|
const cloudResources = {};
|
|
126439
126645
|
const collectionKeys = Object.keys(collectionMap);
|
|
@@ -126454,8 +126660,12 @@ function buildResourcesManifest(workspaceId, collectionMap, envMap, artifactDir,
|
|
|
126454
126660
|
if (localSpecRefs.length > 0) {
|
|
126455
126661
|
localResources.specs = localSpecRefs;
|
|
126456
126662
|
}
|
|
126663
|
+
const specs = { ...existingSpecs || {} };
|
|
126457
126664
|
if (mappedSpecRef && specId) {
|
|
126458
|
-
|
|
126665
|
+
specs[mappedSpecRef] = specId;
|
|
126666
|
+
}
|
|
126667
|
+
if (Object.keys(specs).length > 0) {
|
|
126668
|
+
cloudResources.specs = specs;
|
|
126459
126669
|
}
|
|
126460
126670
|
if (Object.keys(localResources).length > 0) {
|
|
126461
126671
|
manifest.localResources = localResources;
|
|
@@ -126522,7 +126732,7 @@ function assertPathWithinCwd(targetPath, fieldName) {
|
|
|
126522
126732
|
throw new Error(`${fieldName} must stay within the repository root; received ${targetPath}`);
|
|
126523
126733
|
}
|
|
126524
126734
|
}
|
|
126525
|
-
async function exportArtifacts(inputs, dependencies, envUids, assetProjectName) {
|
|
126735
|
+
async function exportArtifacts(inputs, dependencies, envUids, assetProjectName, options) {
|
|
126526
126736
|
if (!inputs.workspaceId) {
|
|
126527
126737
|
return;
|
|
126528
126738
|
}
|
|
@@ -126556,6 +126766,11 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName)
|
|
|
126556
126766
|
const manifestCollections = {};
|
|
126557
126767
|
const discoveredSpecs = scanLocalSpecReferences();
|
|
126558
126768
|
const mappedSpec = resolveMappedSpecReference(inputs.specPath, discoveredSpecs);
|
|
126769
|
+
const mappedSpecCloudKey = mappedSpec && inputs.specId ? buildMappedSpecCloudKey(
|
|
126770
|
+
mappedSpec.configRelativePath,
|
|
126771
|
+
inputs.specSyncMode,
|
|
126772
|
+
options.releaseLabel
|
|
126773
|
+
) : void 0;
|
|
126559
126774
|
if (inputs.baselineCollectionId) {
|
|
126560
126775
|
const col = await dependencies.postman.getCollection(inputs.baselineCollectionId);
|
|
126561
126776
|
const dirName = getCollectionDirectoryName("Baseline", assetProjectName);
|
|
@@ -126581,14 +126796,21 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName)
|
|
|
126581
126796
|
true
|
|
126582
126797
|
);
|
|
126583
126798
|
}
|
|
126799
|
+
const durableWorkspaceId = resolveDurableWorkspaceId({
|
|
126800
|
+
candidateId: inputs.workspaceId,
|
|
126801
|
+
priorId: options.priorWorkspaceId,
|
|
126802
|
+
workspaceLinkEnabled: inputs.workspaceLinkEnabled,
|
|
126803
|
+
workspaceLinkStatus: options.workspaceLinkStatus
|
|
126804
|
+
});
|
|
126584
126805
|
(0, import_node_fs3.writeFileSync)(".postman/resources.yaml", buildResourcesManifest(
|
|
126585
|
-
|
|
126806
|
+
durableWorkspaceId,
|
|
126586
126807
|
manifestCollections,
|
|
126587
126808
|
envUids,
|
|
126588
126809
|
inputs.artifactDir,
|
|
126589
126810
|
discoveredSpecs.map((spec) => spec.configRelativePath),
|
|
126590
|
-
|
|
126591
|
-
inputs.specId || void 0
|
|
126811
|
+
mappedSpecCloudKey,
|
|
126812
|
+
inputs.specId || void 0,
|
|
126813
|
+
options.existingSpecs
|
|
126592
126814
|
));
|
|
126593
126815
|
if (mappedSpec && Object.keys(manifestCollections).length > 0) {
|
|
126594
126816
|
(0, import_node_fs3.writeFileSync)(
|
|
@@ -126755,12 +126977,17 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
126755
126977
|
const mockEnvUid = envUids.dev || envUids.prod || Object.values(envUids)[0];
|
|
126756
126978
|
if (mockEnvUid) {
|
|
126757
126979
|
let resolvedMockUrl = "";
|
|
126980
|
+
const mockName = `${assetProjectName} Mock`;
|
|
126758
126981
|
if (inputs.mockUrl) {
|
|
126759
126982
|
resolvedMockUrl = inputs.mockUrl;
|
|
126760
126983
|
dependencies.core.info(`Reusing mock from explicit input: ${resolvedMockUrl}`);
|
|
126761
126984
|
}
|
|
126762
126985
|
if (!resolvedMockUrl && inputs.baselineCollectionId) {
|
|
126763
|
-
const discovered = await dependencies.postman.findMockByCollection(
|
|
126986
|
+
const discovered = await dependencies.postman.findMockByCollection(
|
|
126987
|
+
inputs.baselineCollectionId,
|
|
126988
|
+
mockEnvUid,
|
|
126989
|
+
mockName
|
|
126990
|
+
);
|
|
126764
126991
|
if (discovered) {
|
|
126765
126992
|
resolvedMockUrl = discovered.mockUrl;
|
|
126766
126993
|
dependencies.core.info(`Discovered existing mock for collection ${inputs.baselineCollectionId}: ${resolvedMockUrl}`);
|
|
@@ -126769,7 +126996,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
126769
126996
|
if (!resolvedMockUrl) {
|
|
126770
126997
|
const mock = await dependencies.postman.createMock(
|
|
126771
126998
|
inputs.workspaceId,
|
|
126772
|
-
|
|
126999
|
+
mockName,
|
|
126773
127000
|
inputs.baselineCollectionId,
|
|
126774
127001
|
mockEnvUid
|
|
126775
127002
|
);
|
|
@@ -126784,6 +127011,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
126784
127011
|
const effectiveCron = inputs.monitorCron && inputs.monitorCron.trim() ? inputs.monitorCron.trim() : "";
|
|
126785
127012
|
if (monitorEnvUid && inputs.monitorType !== "cli") {
|
|
126786
127013
|
let resolvedMonitorId = "";
|
|
127014
|
+
const monitorName = `${assetProjectName} - Smoke Monitor`;
|
|
126787
127015
|
if (inputs.monitorId) {
|
|
126788
127016
|
const valid = await dependencies.postman.monitorExists(inputs.monitorId);
|
|
126789
127017
|
if (valid) {
|
|
@@ -126794,7 +127022,11 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
126794
127022
|
}
|
|
126795
127023
|
}
|
|
126796
127024
|
if (!resolvedMonitorId && inputs.smokeCollectionId) {
|
|
126797
|
-
const discovered = await dependencies.postman.findMonitorByCollection(
|
|
127025
|
+
const discovered = await dependencies.postman.findMonitorByCollection(
|
|
127026
|
+
inputs.smokeCollectionId,
|
|
127027
|
+
monitorEnvUid,
|
|
127028
|
+
monitorName
|
|
127029
|
+
);
|
|
126798
127030
|
if (discovered) {
|
|
126799
127031
|
resolvedMonitorId = discovered.uid;
|
|
126800
127032
|
dependencies.core.info(`Discovered existing monitor for collection ${inputs.smokeCollectionId}: ${resolvedMonitorId}`);
|
|
@@ -126803,7 +127035,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
126803
127035
|
if (!resolvedMonitorId) {
|
|
126804
127036
|
resolvedMonitorId = await dependencies.postman.createMonitor(
|
|
126805
127037
|
inputs.workspaceId,
|
|
126806
|
-
|
|
127038
|
+
monitorName,
|
|
126807
127039
|
inputs.smokeCollectionId,
|
|
126808
127040
|
monitorEnvUid,
|
|
126809
127041
|
effectiveCron || void 0
|
|
@@ -126837,7 +127069,12 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
126837
127069
|
);
|
|
126838
127070
|
}
|
|
126839
127071
|
}
|
|
126840
|
-
await exportArtifacts(inputs, dependencies, envUids, assetProjectName
|
|
127072
|
+
await exportArtifacts(inputs, dependencies, envUids, assetProjectName, {
|
|
127073
|
+
workspaceLinkStatus: outputs["workspace-link-status"],
|
|
127074
|
+
priorWorkspaceId: resourcesState?.workspace?.id,
|
|
127075
|
+
existingSpecs: resourcesState?.cloudResources?.specs,
|
|
127076
|
+
releaseLabel
|
|
127077
|
+
});
|
|
126841
127078
|
const commit = await commitAndPushGeneratedFiles(inputs, dependencies);
|
|
126842
127079
|
outputs["commit-sha"] = commit.commitSha;
|
|
126843
127080
|
if (commit.resolvedCurrentRef) {
|
|
@@ -127016,6 +127253,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
127016
127253
|
createEnvironment: gatewayAssets.createEnvironment.bind(gatewayAssets),
|
|
127017
127254
|
getEnvironment: gatewayAssets.getEnvironment.bind(gatewayAssets),
|
|
127018
127255
|
updateEnvironment: gatewayAssets.updateEnvironment.bind(gatewayAssets),
|
|
127256
|
+
findEnvironmentByName: gatewayAssets.findEnvironmentByName.bind(gatewayAssets),
|
|
127019
127257
|
// Collection read via the v3 export endpoint — returns canonical v3 IR,
|
|
127020
127258
|
// written to disk by `convertAndSplitAnyCollection`. PMAK is never used for
|
|
127021
127259
|
// collection reads.
|