@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/action.cjs
CHANGED
|
@@ -127291,12 +127291,20 @@ async function retry(operation, options = {}) {
|
|
|
127291
127291
|
}
|
|
127292
127292
|
|
|
127293
127293
|
// src/lib/postman/postman-gateway-assets-client.ts
|
|
127294
|
+
var MAX_CREATE_FLIGHTS = 256;
|
|
127295
|
+
var createFlights = /* @__PURE__ */ new Map();
|
|
127294
127296
|
var PostmanGatewayAssetsClient = class {
|
|
127295
127297
|
gateway;
|
|
127296
127298
|
workspaceId;
|
|
127299
|
+
sleep;
|
|
127300
|
+
reconcileAttempts;
|
|
127301
|
+
reconcileDelayMs;
|
|
127297
127302
|
constructor(options) {
|
|
127298
127303
|
this.gateway = options.gateway;
|
|
127299
127304
|
this.workspaceId = String(options.workspaceId || "").trim();
|
|
127305
|
+
this.sleep = options.sleep ?? sleep;
|
|
127306
|
+
this.reconcileAttempts = Math.max(1, options.reconcileAttempts ?? 3);
|
|
127307
|
+
this.reconcileDelayMs = Math.max(0, options.reconcileDelayMs ?? 500);
|
|
127300
127308
|
}
|
|
127301
127309
|
asRecord(value) {
|
|
127302
127310
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
@@ -127326,8 +127334,64 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127326
127334
|
const parts = trimmed.split("-");
|
|
127327
127335
|
return parts.length >= 6 ? parts.slice(1).join("-") : trimmed;
|
|
127328
127336
|
}
|
|
127329
|
-
|
|
127330
|
-
|
|
127337
|
+
isAmbiguousCreateOutcome(error2) {
|
|
127338
|
+
if (error2 instanceof HttpError) {
|
|
127339
|
+
return error2.status === 408 || error2.status === 429 || error2.status >= 500;
|
|
127340
|
+
}
|
|
127341
|
+
return error2 instanceof Error;
|
|
127342
|
+
}
|
|
127343
|
+
isRetryableIdempotentWriteOutcome(error2) {
|
|
127344
|
+
if (error2 instanceof HttpError) {
|
|
127345
|
+
return error2.status === 408 || error2.status === 429 || error2.status >= 500;
|
|
127346
|
+
}
|
|
127347
|
+
return error2 instanceof Error;
|
|
127348
|
+
}
|
|
127349
|
+
selectExactMatch(kind, identity, matches) {
|
|
127350
|
+
if (matches.length > 1) {
|
|
127351
|
+
const ids = matches.map((match) => match.uid).join(", ");
|
|
127352
|
+
throw new Error(
|
|
127353
|
+
`Multiple ${kind}s match ${identity}: ${ids}. Refusing to choose one; remove duplicates or pass an explicit asset ID.`
|
|
127354
|
+
);
|
|
127355
|
+
}
|
|
127356
|
+
return matches[0] ?? null;
|
|
127357
|
+
}
|
|
127358
|
+
async singleFlight(key, fingerprint, kind, operation) {
|
|
127359
|
+
const existing = createFlights.get(key);
|
|
127360
|
+
if (existing) {
|
|
127361
|
+
if (existing.fingerprint !== fingerprint) {
|
|
127362
|
+
throw new Error(`Incompatible concurrent ${kind} create for ${key}`);
|
|
127363
|
+
}
|
|
127364
|
+
return existing.promise;
|
|
127365
|
+
}
|
|
127366
|
+
if (createFlights.size >= MAX_CREATE_FLIGHTS) {
|
|
127367
|
+
throw new Error(`Too many concurrent Postman asset creates (limit ${MAX_CREATE_FLIGHTS})`);
|
|
127368
|
+
}
|
|
127369
|
+
const pending = operation().finally(() => {
|
|
127370
|
+
if (createFlights.get(key)?.promise === pending) {
|
|
127371
|
+
createFlights.delete(key);
|
|
127372
|
+
}
|
|
127373
|
+
});
|
|
127374
|
+
createFlights.set(key, { fingerprint, promise: pending });
|
|
127375
|
+
return pending;
|
|
127376
|
+
}
|
|
127377
|
+
async discoverAfterAmbiguousCreate(discover, error2) {
|
|
127378
|
+
if (!this.isAmbiguousCreateOutcome(error2)) {
|
|
127379
|
+
return null;
|
|
127380
|
+
}
|
|
127381
|
+
for (let attempt = 0; attempt < this.reconcileAttempts; attempt += 1) {
|
|
127382
|
+
if (attempt > 0) {
|
|
127383
|
+
await this.sleep(this.reconcileDelayMs);
|
|
127384
|
+
}
|
|
127385
|
+
const found = await discover();
|
|
127386
|
+
if (found) {
|
|
127387
|
+
return found;
|
|
127388
|
+
}
|
|
127389
|
+
}
|
|
127390
|
+
return null;
|
|
127391
|
+
}
|
|
127392
|
+
publicEnvironmentUid(data, bareId) {
|
|
127393
|
+
const owner = String(data?.owner ?? "").trim();
|
|
127394
|
+
return owner && !bareId.startsWith(`${owner}-`) ? `${owner}-${bareId}` : bareId;
|
|
127331
127395
|
}
|
|
127332
127396
|
// --- environments (service: sync) ---
|
|
127333
127397
|
//
|
|
@@ -127338,9 +127402,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127338
127402
|
/**
|
|
127339
127403
|
* Create/upsert an environment through the sync service.
|
|
127340
127404
|
* POST /environment/import?workspace=:ws { id:<uuid>, name, values } ->
|
|
127341
|
-
* { data:{ id:<bare uuid>, owner } }. The id is generated once
|
|
127342
|
-
*
|
|
127343
|
-
*
|
|
127405
|
+
* { data:{ id:<bare uuid>, owner } }. The id is generated once for the
|
|
127406
|
+
* operation. Unsafe creates submit once (no blind retry); on an ambiguous
|
|
127407
|
+
* response the client discovers by exact workspace-scoped name before
|
|
127408
|
+
* failing.
|
|
127344
127409
|
*
|
|
127345
127410
|
* Returns the PUBLIC uid (`<owner>-<uuid>`), not the bare model id the sync
|
|
127346
127411
|
* import echoes: mock/monitor create reference the environment by its public
|
|
@@ -127350,33 +127415,54 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127350
127415
|
*/
|
|
127351
127416
|
async createEnvironment(workspaceId, name, values) {
|
|
127352
127417
|
const ws = workspaceId || this.workspaceId;
|
|
127353
|
-
const
|
|
127354
|
-
const
|
|
127355
|
-
|
|
127356
|
-
|
|
127357
|
-
|
|
127358
|
-
|
|
127359
|
-
|
|
127360
|
-
|
|
127361
|
-
|
|
127362
|
-
|
|
127363
|
-
|
|
127364
|
-
|
|
127365
|
-
|
|
127366
|
-
|
|
127367
|
-
|
|
127368
|
-
|
|
127369
|
-
|
|
127370
|
-
|
|
127371
|
-
|
|
127372
|
-
|
|
127373
|
-
|
|
127374
|
-
|
|
127375
|
-
|
|
127376
|
-
|
|
127377
|
-
|
|
127378
|
-
|
|
127379
|
-
|
|
127418
|
+
const envName = String(name ?? "").trim();
|
|
127419
|
+
const flightKey = `environment:${ws}:${envName}`;
|
|
127420
|
+
const normalizedValues = values.map((v) => ({
|
|
127421
|
+
key: v.key,
|
|
127422
|
+
value: v.value,
|
|
127423
|
+
type: v.type ?? "default",
|
|
127424
|
+
enabled: v.enabled ?? true
|
|
127425
|
+
}));
|
|
127426
|
+
return this.singleFlight(flightKey, JSON.stringify(normalizedValues), "environment", async () => {
|
|
127427
|
+
const existing = await this.findEnvironmentByName(ws, envName);
|
|
127428
|
+
if (existing?.uid) {
|
|
127429
|
+
await this.updateEnvironment(existing.uid, envName, values);
|
|
127430
|
+
return existing.uid;
|
|
127431
|
+
}
|
|
127432
|
+
const id = crypto.randomUUID();
|
|
127433
|
+
const body = {
|
|
127434
|
+
id,
|
|
127435
|
+
name: envName,
|
|
127436
|
+
values: normalizedValues
|
|
127437
|
+
};
|
|
127438
|
+
try {
|
|
127439
|
+
const response = await this.gateway.requestJson(
|
|
127440
|
+
{
|
|
127441
|
+
service: "sync",
|
|
127442
|
+
method: "post",
|
|
127443
|
+
path: `/environment/import?workspace=${ws}`,
|
|
127444
|
+
body
|
|
127445
|
+
},
|
|
127446
|
+
{ retryTransient: false }
|
|
127447
|
+
);
|
|
127448
|
+
const data = this.dataOf(response);
|
|
127449
|
+
const bareId = this.idOf(data);
|
|
127450
|
+
if (!bareId) {
|
|
127451
|
+
throw new Error("Environment import did not return a UID");
|
|
127452
|
+
}
|
|
127453
|
+
return this.publicEnvironmentUid(data, bareId);
|
|
127454
|
+
} catch (error2) {
|
|
127455
|
+
const adopted = await this.discoverAfterAmbiguousCreate(async () => {
|
|
127456
|
+
const match = await this.findEnvironmentByName(ws, envName);
|
|
127457
|
+
return match?.uid ?? null;
|
|
127458
|
+
}, error2);
|
|
127459
|
+
if (adopted) {
|
|
127460
|
+
await this.updateEnvironment(adopted, envName, values);
|
|
127461
|
+
return adopted;
|
|
127462
|
+
}
|
|
127463
|
+
throw error2;
|
|
127464
|
+
}
|
|
127465
|
+
});
|
|
127380
127466
|
}
|
|
127381
127467
|
/**
|
|
127382
127468
|
* Update an existing environment through the sync service.
|
|
@@ -127406,7 +127492,7 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127406
127492
|
path: `/environment/${id}`,
|
|
127407
127493
|
body
|
|
127408
127494
|
}),
|
|
127409
|
-
{ maxAttempts: 5, delayMs: 2e3, backoffMultiplier: 2, maxDelayMs: 15e3, shouldRetry: (e) => this.
|
|
127495
|
+
{ maxAttempts: 5, delayMs: 2e3, backoffMultiplier: 2, maxDelayMs: 15e3, shouldRetry: (e) => this.isRetryableIdempotentWriteOutcome(e) }
|
|
127410
127496
|
);
|
|
127411
127497
|
}
|
|
127412
127498
|
/**
|
|
@@ -127430,13 +127516,37 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127430
127516
|
*/
|
|
127431
127517
|
async listEnvironments(workspaceId) {
|
|
127432
127518
|
const ws = workspaceId || this.workspaceId;
|
|
127433
|
-
const response = await this.gateway.requestJson(
|
|
127434
|
-
|
|
127435
|
-
|
|
127436
|
-
|
|
127437
|
-
|
|
127519
|
+
const response = await this.gateway.requestJson(
|
|
127520
|
+
{
|
|
127521
|
+
service: "sync",
|
|
127522
|
+
method: "post",
|
|
127523
|
+
path: `/list/environment?workspace=${ws}`
|
|
127524
|
+
},
|
|
127525
|
+
{ retryTransient: true }
|
|
127526
|
+
);
|
|
127438
127527
|
const items = Array.isArray(response?.data) ? response.data : [];
|
|
127439
|
-
return items.map((raw) => this.asRecord(raw)).filter((e) => e !== null).map((e) =>
|
|
127528
|
+
return items.map((raw) => this.asRecord(raw)).filter((e) => e !== null).map((e) => {
|
|
127529
|
+
const bareOrPublic = this.idOf(e);
|
|
127530
|
+
return {
|
|
127531
|
+
name: String(e.name ?? ""),
|
|
127532
|
+
uid: this.publicEnvironmentUid(e, bareOrPublic)
|
|
127533
|
+
};
|
|
127534
|
+
});
|
|
127535
|
+
}
|
|
127536
|
+
/** Exact name match within a workspace. Prefer tracked UIDs before calling. */
|
|
127537
|
+
async findEnvironmentByName(workspaceId, name) {
|
|
127538
|
+
const want = String(name ?? "").trim();
|
|
127539
|
+
if (!want) {
|
|
127540
|
+
return null;
|
|
127541
|
+
}
|
|
127542
|
+
const environments = await this.listEnvironments(workspaceId);
|
|
127543
|
+
const matches = environments.filter((entry) => entry.name === want);
|
|
127544
|
+
const match = this.selectExactMatch(
|
|
127545
|
+
"environment",
|
|
127546
|
+
`workspace ${workspaceId} and name "${want}"`,
|
|
127547
|
+
matches
|
|
127548
|
+
);
|
|
127549
|
+
return match?.uid ? { uid: match.uid, name: match.name } : null;
|
|
127440
127550
|
}
|
|
127441
127551
|
// --- collection read (service: collection, v3 export) ---
|
|
127442
127552
|
//
|
|
@@ -127466,32 +127576,51 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127466
127576
|
// --- mocks (service: mock) ---
|
|
127467
127577
|
async createMock(workspaceId, name, collectionUid, environmentUid) {
|
|
127468
127578
|
const ws = workspaceId || this.workspaceId;
|
|
127579
|
+
const mockName = String(name ?? "").trim();
|
|
127469
127580
|
const collection = String(collectionUid ?? "").trim();
|
|
127470
127581
|
const environment = String(environmentUid ?? "").trim();
|
|
127471
|
-
const
|
|
127472
|
-
|
|
127473
|
-
collection,
|
|
127474
|
-
|
|
127475
|
-
|
|
127476
|
-
|
|
127477
|
-
|
|
127478
|
-
|
|
127479
|
-
|
|
127480
|
-
|
|
127481
|
-
|
|
127482
|
-
|
|
127483
|
-
|
|
127484
|
-
|
|
127485
|
-
|
|
127486
|
-
|
|
127487
|
-
|
|
127488
|
-
|
|
127489
|
-
|
|
127490
|
-
|
|
127491
|
-
|
|
127492
|
-
|
|
127493
|
-
|
|
127494
|
-
|
|
127582
|
+
const flightKey = `mock:${ws}:${collection}:${environment}:${mockName}`;
|
|
127583
|
+
return this.singleFlight(flightKey, flightKey, "mock", async () => {
|
|
127584
|
+
const existing = await this.findMockByCollection(collection, environment, mockName);
|
|
127585
|
+
if (existing) {
|
|
127586
|
+
return { uid: existing.uid, url: existing.mockUrl };
|
|
127587
|
+
}
|
|
127588
|
+
const body = {
|
|
127589
|
+
name: mockName,
|
|
127590
|
+
collection,
|
|
127591
|
+
private: false,
|
|
127592
|
+
...environment ? { environment } : {}
|
|
127593
|
+
};
|
|
127594
|
+
try {
|
|
127595
|
+
const response = await this.gateway.requestJson(
|
|
127596
|
+
{
|
|
127597
|
+
service: "mock",
|
|
127598
|
+
method: "post",
|
|
127599
|
+
path: `/mocks?workspace=${ws}`,
|
|
127600
|
+
body
|
|
127601
|
+
},
|
|
127602
|
+
{ retryTransient: false }
|
|
127603
|
+
);
|
|
127604
|
+
const record = this.dataOf(response);
|
|
127605
|
+
const uid = this.idOf(record);
|
|
127606
|
+
if (!uid) {
|
|
127607
|
+
throw new Error("Mock create did not return a UID");
|
|
127608
|
+
}
|
|
127609
|
+
return {
|
|
127610
|
+
uid,
|
|
127611
|
+
url: String(record?.url ?? record?.mockUrl ?? "").trim()
|
|
127612
|
+
};
|
|
127613
|
+
} catch (error2) {
|
|
127614
|
+
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127615
|
+
() => this.findMockByCollection(collection, environment, mockName),
|
|
127616
|
+
error2
|
|
127617
|
+
);
|
|
127618
|
+
if (adopted) {
|
|
127619
|
+
return { uid: adopted.uid, url: adopted.mockUrl };
|
|
127620
|
+
}
|
|
127621
|
+
throw error2;
|
|
127622
|
+
}
|
|
127623
|
+
});
|
|
127495
127624
|
}
|
|
127496
127625
|
async listMocks() {
|
|
127497
127626
|
const response = await this.gateway.requestJson({
|
|
@@ -127520,10 +127649,19 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127520
127649
|
return false;
|
|
127521
127650
|
}
|
|
127522
127651
|
}
|
|
127523
|
-
async findMockByCollection(collectionUid) {
|
|
127652
|
+
async findMockByCollection(collectionUid, environmentUid, name) {
|
|
127524
127653
|
const mocks = await this.listMocks();
|
|
127525
127654
|
const want = String(collectionUid ?? "").trim();
|
|
127526
|
-
const
|
|
127655
|
+
const environment = String(environmentUid ?? "").trim();
|
|
127656
|
+
const mockName = String(name ?? "").trim();
|
|
127657
|
+
const matches = mocks.filter(
|
|
127658
|
+
(mock) => mock.collection === want && mock.environment === environment && mock.name === mockName
|
|
127659
|
+
);
|
|
127660
|
+
const match = this.selectExactMatch(
|
|
127661
|
+
"mock",
|
|
127662
|
+
`workspace ${this.workspaceId}, name "${mockName}", collection ${want}, and environment ${environment || "(none)"}`,
|
|
127663
|
+
matches
|
|
127664
|
+
);
|
|
127527
127665
|
return match ? { uid: match.uid, mockUrl: match.mockUrl } : null;
|
|
127528
127666
|
}
|
|
127529
127667
|
// --- monitors (service: monitors; collection-based = jobTemplates) ---
|
|
@@ -127540,32 +127678,51 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127540
127678
|
async createMonitor(workspaceId, name, collectionUid, environmentUid, cronSchedule) {
|
|
127541
127679
|
const ws = workspaceId || this.workspaceId;
|
|
127542
127680
|
const effectiveCron = cronSchedule && cronSchedule.trim() ? cronSchedule.trim() : "0 0 * * 0";
|
|
127681
|
+
const monitorName = String(name ?? "").trim();
|
|
127543
127682
|
const collection = String(collectionUid ?? "").trim();
|
|
127544
127683
|
const environment = String(environmentUid ?? "").trim();
|
|
127545
|
-
const
|
|
127546
|
-
|
|
127547
|
-
collection,
|
|
127548
|
-
|
|
127549
|
-
|
|
127550
|
-
|
|
127551
|
-
|
|
127552
|
-
|
|
127553
|
-
|
|
127554
|
-
|
|
127555
|
-
|
|
127556
|
-
|
|
127557
|
-
|
|
127558
|
-
|
|
127559
|
-
|
|
127560
|
-
|
|
127561
|
-
|
|
127562
|
-
|
|
127563
|
-
|
|
127564
|
-
|
|
127565
|
-
|
|
127566
|
-
|
|
127567
|
-
|
|
127568
|
-
|
|
127684
|
+
const flightKey = `monitor:${ws}:${collection}:${environment}:${monitorName}`;
|
|
127685
|
+
return this.singleFlight(flightKey, effectiveCron, "monitor", async () => {
|
|
127686
|
+
const existing = await this.findMonitorByCollection(collection, environment, monitorName);
|
|
127687
|
+
if (existing?.uid) {
|
|
127688
|
+
return existing.uid;
|
|
127689
|
+
}
|
|
127690
|
+
const body = {
|
|
127691
|
+
name: monitorName,
|
|
127692
|
+
collection,
|
|
127693
|
+
options: { strictSSL: false, followRedirects: true, requestTimeout: null, requestDelay: 0 },
|
|
127694
|
+
notifications: { onFailure: [], onError: [] },
|
|
127695
|
+
retry: {},
|
|
127696
|
+
schedule: { cronPattern: effectiveCron, timeZone: "UTC" },
|
|
127697
|
+
distribution: null,
|
|
127698
|
+
...environment ? { environment } : {}
|
|
127699
|
+
};
|
|
127700
|
+
try {
|
|
127701
|
+
const response = await this.gateway.requestJson(
|
|
127702
|
+
{
|
|
127703
|
+
service: "monitors",
|
|
127704
|
+
method: "post",
|
|
127705
|
+
path: `/jobTemplates?workspace=${ws}`,
|
|
127706
|
+
body
|
|
127707
|
+
},
|
|
127708
|
+
{ retryTransient: false }
|
|
127709
|
+
);
|
|
127710
|
+
const uid = this.idOf(this.dataOf(response));
|
|
127711
|
+
if (!uid) {
|
|
127712
|
+
throw new Error("Monitor create did not return a UID");
|
|
127713
|
+
}
|
|
127714
|
+
return uid;
|
|
127715
|
+
} catch (error2) {
|
|
127716
|
+
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127717
|
+
() => this.findMonitorByCollection(collection, environment, monitorName),
|
|
127718
|
+
error2
|
|
127719
|
+
);
|
|
127720
|
+
if (adopted?.uid) {
|
|
127721
|
+
return adopted.uid;
|
|
127722
|
+
}
|
|
127723
|
+
throw error2;
|
|
127724
|
+
}
|
|
127725
|
+
});
|
|
127569
127726
|
}
|
|
127570
127727
|
async listMonitors() {
|
|
127571
127728
|
const response = await this.gateway.requestJson({
|
|
@@ -127588,24 +127745,30 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127588
127745
|
return false;
|
|
127589
127746
|
}
|
|
127590
127747
|
}
|
|
127591
|
-
async findMonitorByCollection(collectionUid) {
|
|
127748
|
+
async findMonitorByCollection(collectionUid, environmentUid, name) {
|
|
127592
127749
|
const want = String(collectionUid ?? "").trim();
|
|
127593
|
-
const
|
|
127594
|
-
|
|
127595
|
-
|
|
127596
|
-
|
|
127597
|
-
|
|
127598
|
-
|
|
127599
|
-
const
|
|
127600
|
-
|
|
127750
|
+
const environment = String(environmentUid ?? "").trim();
|
|
127751
|
+
const monitorName = String(name ?? "").trim();
|
|
127752
|
+
const monitors = await this.listMonitors();
|
|
127753
|
+
const matches = monitors.filter(
|
|
127754
|
+
(monitor) => monitor.collectionUid === want && monitor.environmentUid === environment && monitor.name === monitorName
|
|
127755
|
+
);
|
|
127756
|
+
const match = this.selectExactMatch(
|
|
127757
|
+
"monitor",
|
|
127758
|
+
`workspace ${this.workspaceId}, name "${monitorName}", collection ${want}, and environment ${environment || "(none)"}`,
|
|
127759
|
+
matches
|
|
127760
|
+
);
|
|
127601
127761
|
return match?.uid ? { uid: match.uid, name: match.name } : null;
|
|
127602
127762
|
}
|
|
127603
127763
|
async runMonitor(uid) {
|
|
127604
|
-
await this.gateway.requestJson(
|
|
127605
|
-
|
|
127606
|
-
|
|
127607
|
-
|
|
127608
|
-
|
|
127764
|
+
await this.gateway.requestJson(
|
|
127765
|
+
{
|
|
127766
|
+
service: "monitors",
|
|
127767
|
+
method: "post",
|
|
127768
|
+
path: `/jobTemplates/${uid}/jobs`
|
|
127769
|
+
},
|
|
127770
|
+
{ retryTransient: false }
|
|
127771
|
+
);
|
|
127609
127772
|
}
|
|
127610
127773
|
};
|
|
127611
127774
|
|
|
@@ -127771,12 +127934,8 @@ async function mintAccessTokenIfNeeded(inputs, log, setSecret2, fetchImpl = fetc
|
|
|
127771
127934
|
function isExpiredAuthError(status, body) {
|
|
127772
127935
|
return status === 401 || body.includes("UNAUTHENTICATED") || body.includes("authenticationError");
|
|
127773
127936
|
}
|
|
127774
|
-
function
|
|
127775
|
-
|
|
127776
|
-
if (status >= 500 && (body.includes("ESOCKETTIMEDOUT") || body.includes("ETIMEDOUT") || body.includes("ECONNRESET") || body.includes("serverError") || body.includes("downstream"))) {
|
|
127777
|
-
return true;
|
|
127778
|
-
}
|
|
127779
|
-
return false;
|
|
127937
|
+
function isRetryableSafeReadResponse(status) {
|
|
127938
|
+
return status === 408 || status === 429 || status >= 500;
|
|
127780
127939
|
}
|
|
127781
127940
|
function defaultSleep(ms) {
|
|
127782
127941
|
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
@@ -127835,14 +127994,28 @@ var AccessTokenGatewayClient = class {
|
|
|
127835
127994
|
}
|
|
127836
127995
|
/**
|
|
127837
127996
|
* Send a gateway request, refreshing the token once on an auth failure and
|
|
127838
|
-
* retrying transient downstream failures (5xx / Bifrost read
|
|
127839
|
-
* exponential backoff.
|
|
127840
|
-
*
|
|
127997
|
+
* optionally retrying transient downstream failures (5xx / Bifrost read
|
|
127998
|
+
* timeouts) with exponential backoff. Safe reads keep transient retries;
|
|
127999
|
+
* unsafe creates pass `{ retryTransient: false }` and reconcile after an
|
|
128000
|
+
* ambiguous response instead of re-POSTing. Auth refresh remains independent
|
|
128001
|
+
* of the transient-retry budget.
|
|
127841
128002
|
*/
|
|
127842
|
-
async request(request) {
|
|
128003
|
+
async request(request, options = {}) {
|
|
128004
|
+
const retryTransient = options.retryTransient ?? request.method === "get";
|
|
127843
128005
|
let attempt = 0;
|
|
127844
128006
|
for (; ; ) {
|
|
127845
|
-
let response
|
|
128007
|
+
let response;
|
|
128008
|
+
try {
|
|
128009
|
+
response = await this.send(request);
|
|
128010
|
+
} catch (error2) {
|
|
128011
|
+
if (retryTransient && attempt < this.maxRetries) {
|
|
128012
|
+
const delay = this.retryBaseDelayMs * 2 ** attempt;
|
|
128013
|
+
attempt += 1;
|
|
128014
|
+
await this.sleepImpl(delay);
|
|
128015
|
+
continue;
|
|
128016
|
+
}
|
|
128017
|
+
throw error2;
|
|
128018
|
+
}
|
|
127846
128019
|
if (response.ok) {
|
|
127847
128020
|
return response;
|
|
127848
128021
|
}
|
|
@@ -127856,7 +128029,7 @@ var AccessTokenGatewayClient = class {
|
|
|
127856
128029
|
const retryBody = await response.text().catch(() => "");
|
|
127857
128030
|
throw this.toHttpError(request, response, retryBody);
|
|
127858
128031
|
}
|
|
127859
|
-
if (
|
|
128032
|
+
if (retryTransient && isRetryableSafeReadResponse(response.status) && attempt < this.maxRetries) {
|
|
127860
128033
|
const delay = this.retryBaseDelayMs * 2 ** attempt;
|
|
127861
128034
|
attempt += 1;
|
|
127862
128035
|
await this.sleepImpl(delay);
|
|
@@ -127866,8 +128039,8 @@ var AccessTokenGatewayClient = class {
|
|
|
127866
128039
|
}
|
|
127867
128040
|
}
|
|
127868
128041
|
/** Send a gateway request and parse the JSON body, or null when empty. */
|
|
127869
|
-
async requestJson(request) {
|
|
127870
|
-
const response = await this.request(request);
|
|
128042
|
+
async requestJson(request, options = {}) {
|
|
128043
|
+
const response = await this.request(request, options);
|
|
127871
128044
|
const text = await response.text().catch(() => "");
|
|
127872
128045
|
if (!text.trim()) {
|
|
127873
128046
|
return null;
|
|
@@ -128459,18 +128632,28 @@ async function upsertEnvironments(inputs, dependencies, resourcesState) {
|
|
|
128459
128632
|
for (const envName of inputs.environments) {
|
|
128460
128633
|
const runtimeUrl = String(inputs.envRuntimeUrls[envName] || "").trim();
|
|
128461
128634
|
const values = buildEnvironmentValues(envName, runtimeUrl);
|
|
128462
|
-
const
|
|
128463
|
-
|
|
128464
|
-
|
|
128465
|
-
|
|
128466
|
-
|
|
128467
|
-
|
|
128635
|
+
const displayName = `${inputs.projectName} - ${envName}`;
|
|
128636
|
+
let existingUid = String(envUids[envName] || "").trim();
|
|
128637
|
+
if (!existingUid) {
|
|
128638
|
+
const discovered = await dependencies.postman.findEnvironmentByName(
|
|
128639
|
+
inputs.workspaceId,
|
|
128640
|
+
displayName
|
|
128468
128641
|
);
|
|
128642
|
+
if (discovered?.uid) {
|
|
128643
|
+
existingUid = discovered.uid;
|
|
128644
|
+
dependencies.core.info(
|
|
128645
|
+
`Discovered existing environment for ${displayName}: ${existingUid}`
|
|
128646
|
+
);
|
|
128647
|
+
}
|
|
128648
|
+
}
|
|
128649
|
+
if (existingUid) {
|
|
128650
|
+
await dependencies.postman.updateEnvironment(existingUid, displayName, values);
|
|
128651
|
+
envUids[envName] = existingUid;
|
|
128469
128652
|
continue;
|
|
128470
128653
|
}
|
|
128471
128654
|
envUids[envName] = await dependencies.postman.createEnvironment(
|
|
128472
128655
|
inputs.workspaceId,
|
|
128473
|
-
|
|
128656
|
+
displayName,
|
|
128474
128657
|
values
|
|
128475
128658
|
);
|
|
128476
128659
|
}
|
|
@@ -128516,10 +128699,33 @@ function writeJsonFile(path9, content, normalize3 = false) {
|
|
|
128516
128699
|
const data = normalize3 ? stripVolatileFields(content) : content;
|
|
128517
128700
|
(0, import_node_fs3.writeFileSync)(path9, JSON.stringify(data, null, 2));
|
|
128518
128701
|
}
|
|
128519
|
-
function
|
|
128520
|
-
|
|
128521
|
-
|
|
128522
|
-
}
|
|
128702
|
+
function buildMappedSpecCloudKey(mappedSource, specSyncMode, releaseLabel) {
|
|
128703
|
+
if (specSyncMode !== "version") {
|
|
128704
|
+
return mappedSource;
|
|
128705
|
+
}
|
|
128706
|
+
const normalized = normalizeReleaseLabel(releaseLabel || "");
|
|
128707
|
+
if (!normalized) {
|
|
128708
|
+
return void 0;
|
|
128709
|
+
}
|
|
128710
|
+
return `${mappedSource}#release=${normalized}`;
|
|
128711
|
+
}
|
|
128712
|
+
function resolveDurableWorkspaceId(options) {
|
|
128713
|
+
const { candidateId, priorId, workspaceLinkEnabled, workspaceLinkStatus } = options;
|
|
128714
|
+
const candidate = candidateId.trim();
|
|
128715
|
+
const prior = priorId?.trim() || void 0;
|
|
128716
|
+
if (!workspaceLinkEnabled) {
|
|
128717
|
+
return candidate || prior;
|
|
128718
|
+
}
|
|
128719
|
+
if (workspaceLinkStatus === "success") {
|
|
128720
|
+
return candidate || void 0;
|
|
128721
|
+
}
|
|
128722
|
+
return prior === candidate ? prior : void 0;
|
|
128723
|
+
}
|
|
128724
|
+
function buildResourcesManifest(workspaceId, collectionMap, envMap, artifactDir, localSpecRefs, mappedSpecRef, specId, existingSpecs) {
|
|
128725
|
+
const manifest = {};
|
|
128726
|
+
if (workspaceId) {
|
|
128727
|
+
manifest.workspace = { id: workspaceId };
|
|
128728
|
+
}
|
|
128523
128729
|
const localResources = {};
|
|
128524
128730
|
const cloudResources = {};
|
|
128525
128731
|
const collectionKeys = Object.keys(collectionMap);
|
|
@@ -128540,8 +128746,12 @@ function buildResourcesManifest(workspaceId, collectionMap, envMap, artifactDir,
|
|
|
128540
128746
|
if (localSpecRefs.length > 0) {
|
|
128541
128747
|
localResources.specs = localSpecRefs;
|
|
128542
128748
|
}
|
|
128749
|
+
const specs = { ...existingSpecs || {} };
|
|
128543
128750
|
if (mappedSpecRef && specId) {
|
|
128544
|
-
|
|
128751
|
+
specs[mappedSpecRef] = specId;
|
|
128752
|
+
}
|
|
128753
|
+
if (Object.keys(specs).length > 0) {
|
|
128754
|
+
cloudResources.specs = specs;
|
|
128545
128755
|
}
|
|
128546
128756
|
if (Object.keys(localResources).length > 0) {
|
|
128547
128757
|
manifest.localResources = localResources;
|
|
@@ -128608,7 +128818,7 @@ function assertPathWithinCwd(targetPath, fieldName) {
|
|
|
128608
128818
|
throw new Error(`${fieldName} must stay within the repository root; received ${targetPath}`);
|
|
128609
128819
|
}
|
|
128610
128820
|
}
|
|
128611
|
-
async function exportArtifacts(inputs, dependencies, envUids, assetProjectName) {
|
|
128821
|
+
async function exportArtifacts(inputs, dependencies, envUids, assetProjectName, options) {
|
|
128612
128822
|
if (!inputs.workspaceId) {
|
|
128613
128823
|
return;
|
|
128614
128824
|
}
|
|
@@ -128642,6 +128852,11 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName)
|
|
|
128642
128852
|
const manifestCollections = {};
|
|
128643
128853
|
const discoveredSpecs = scanLocalSpecReferences();
|
|
128644
128854
|
const mappedSpec = resolveMappedSpecReference(inputs.specPath, discoveredSpecs);
|
|
128855
|
+
const mappedSpecCloudKey = mappedSpec && inputs.specId ? buildMappedSpecCloudKey(
|
|
128856
|
+
mappedSpec.configRelativePath,
|
|
128857
|
+
inputs.specSyncMode,
|
|
128858
|
+
options.releaseLabel
|
|
128859
|
+
) : void 0;
|
|
128645
128860
|
if (inputs.baselineCollectionId) {
|
|
128646
128861
|
const col = await dependencies.postman.getCollection(inputs.baselineCollectionId);
|
|
128647
128862
|
const dirName = getCollectionDirectoryName("Baseline", assetProjectName);
|
|
@@ -128667,14 +128882,21 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName)
|
|
|
128667
128882
|
true
|
|
128668
128883
|
);
|
|
128669
128884
|
}
|
|
128885
|
+
const durableWorkspaceId = resolveDurableWorkspaceId({
|
|
128886
|
+
candidateId: inputs.workspaceId,
|
|
128887
|
+
priorId: options.priorWorkspaceId,
|
|
128888
|
+
workspaceLinkEnabled: inputs.workspaceLinkEnabled,
|
|
128889
|
+
workspaceLinkStatus: options.workspaceLinkStatus
|
|
128890
|
+
});
|
|
128670
128891
|
(0, import_node_fs3.writeFileSync)(".postman/resources.yaml", buildResourcesManifest(
|
|
128671
|
-
|
|
128892
|
+
durableWorkspaceId,
|
|
128672
128893
|
manifestCollections,
|
|
128673
128894
|
envUids,
|
|
128674
128895
|
inputs.artifactDir,
|
|
128675
128896
|
discoveredSpecs.map((spec) => spec.configRelativePath),
|
|
128676
|
-
|
|
128677
|
-
inputs.specId || void 0
|
|
128897
|
+
mappedSpecCloudKey,
|
|
128898
|
+
inputs.specId || void 0,
|
|
128899
|
+
options.existingSpecs
|
|
128678
128900
|
));
|
|
128679
128901
|
if (mappedSpec && Object.keys(manifestCollections).length > 0) {
|
|
128680
128902
|
(0, import_node_fs3.writeFileSync)(
|
|
@@ -128841,12 +129063,17 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
128841
129063
|
const mockEnvUid = envUids.dev || envUids.prod || Object.values(envUids)[0];
|
|
128842
129064
|
if (mockEnvUid) {
|
|
128843
129065
|
let resolvedMockUrl = "";
|
|
129066
|
+
const mockName = `${assetProjectName} Mock`;
|
|
128844
129067
|
if (inputs.mockUrl) {
|
|
128845
129068
|
resolvedMockUrl = inputs.mockUrl;
|
|
128846
129069
|
dependencies.core.info(`Reusing mock from explicit input: ${resolvedMockUrl}`);
|
|
128847
129070
|
}
|
|
128848
129071
|
if (!resolvedMockUrl && inputs.baselineCollectionId) {
|
|
128849
|
-
const discovered = await dependencies.postman.findMockByCollection(
|
|
129072
|
+
const discovered = await dependencies.postman.findMockByCollection(
|
|
129073
|
+
inputs.baselineCollectionId,
|
|
129074
|
+
mockEnvUid,
|
|
129075
|
+
mockName
|
|
129076
|
+
);
|
|
128850
129077
|
if (discovered) {
|
|
128851
129078
|
resolvedMockUrl = discovered.mockUrl;
|
|
128852
129079
|
dependencies.core.info(`Discovered existing mock for collection ${inputs.baselineCollectionId}: ${resolvedMockUrl}`);
|
|
@@ -128855,7 +129082,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
128855
129082
|
if (!resolvedMockUrl) {
|
|
128856
129083
|
const mock = await dependencies.postman.createMock(
|
|
128857
129084
|
inputs.workspaceId,
|
|
128858
|
-
|
|
129085
|
+
mockName,
|
|
128859
129086
|
inputs.baselineCollectionId,
|
|
128860
129087
|
mockEnvUid
|
|
128861
129088
|
);
|
|
@@ -128870,6 +129097,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
128870
129097
|
const effectiveCron = inputs.monitorCron && inputs.monitorCron.trim() ? inputs.monitorCron.trim() : "";
|
|
128871
129098
|
if (monitorEnvUid && inputs.monitorType !== "cli") {
|
|
128872
129099
|
let resolvedMonitorId = "";
|
|
129100
|
+
const monitorName = `${assetProjectName} - Smoke Monitor`;
|
|
128873
129101
|
if (inputs.monitorId) {
|
|
128874
129102
|
const valid = await dependencies.postman.monitorExists(inputs.monitorId);
|
|
128875
129103
|
if (valid) {
|
|
@@ -128880,7 +129108,11 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
128880
129108
|
}
|
|
128881
129109
|
}
|
|
128882
129110
|
if (!resolvedMonitorId && inputs.smokeCollectionId) {
|
|
128883
|
-
const discovered = await dependencies.postman.findMonitorByCollection(
|
|
129111
|
+
const discovered = await dependencies.postman.findMonitorByCollection(
|
|
129112
|
+
inputs.smokeCollectionId,
|
|
129113
|
+
monitorEnvUid,
|
|
129114
|
+
monitorName
|
|
129115
|
+
);
|
|
128884
129116
|
if (discovered) {
|
|
128885
129117
|
resolvedMonitorId = discovered.uid;
|
|
128886
129118
|
dependencies.core.info(`Discovered existing monitor for collection ${inputs.smokeCollectionId}: ${resolvedMonitorId}`);
|
|
@@ -128889,7 +129121,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
128889
129121
|
if (!resolvedMonitorId) {
|
|
128890
129122
|
resolvedMonitorId = await dependencies.postman.createMonitor(
|
|
128891
129123
|
inputs.workspaceId,
|
|
128892
|
-
|
|
129124
|
+
monitorName,
|
|
128893
129125
|
inputs.smokeCollectionId,
|
|
128894
129126
|
monitorEnvUid,
|
|
128895
129127
|
effectiveCron || void 0
|
|
@@ -128923,7 +129155,12 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
128923
129155
|
);
|
|
128924
129156
|
}
|
|
128925
129157
|
}
|
|
128926
|
-
await exportArtifacts(inputs, dependencies, envUids, assetProjectName
|
|
129158
|
+
await exportArtifacts(inputs, dependencies, envUids, assetProjectName, {
|
|
129159
|
+
workspaceLinkStatus: outputs["workspace-link-status"],
|
|
129160
|
+
priorWorkspaceId: resourcesState?.workspace?.id,
|
|
129161
|
+
existingSpecs: resourcesState?.cloudResources?.specs,
|
|
129162
|
+
releaseLabel
|
|
129163
|
+
});
|
|
128927
129164
|
const commit = await commitAndPushGeneratedFiles(inputs, dependencies);
|
|
128928
129165
|
outputs["commit-sha"] = commit.commitSha;
|
|
128929
129166
|
if (commit.resolvedCurrentRef) {
|
|
@@ -129102,6 +129339,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
129102
129339
|
createEnvironment: gatewayAssets.createEnvironment.bind(gatewayAssets),
|
|
129103
129340
|
getEnvironment: gatewayAssets.getEnvironment.bind(gatewayAssets),
|
|
129104
129341
|
updateEnvironment: gatewayAssets.updateEnvironment.bind(gatewayAssets),
|
|
129342
|
+
findEnvironmentByName: gatewayAssets.findEnvironmentByName.bind(gatewayAssets),
|
|
129105
129343
|
// Collection read via the v3 export endpoint — returns canonical v3 IR,
|
|
129106
129344
|
// written to disk by `convertAndSplitAnyCollection`. PMAK is never used for
|
|
129107
129345
|
// collection reads.
|