@postman-cs/onboarding-repo-sync 2.10.4 → 2.10.6
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 +76 -2
- package/dist/cli.cjs +158 -15
- package/dist/index.cjs +76 -2
- package/package.json +2 -2
package/dist/action.cjs
CHANGED
|
@@ -127537,6 +127537,7 @@ function requireMockVisibility(mock, requested) {
|
|
|
127537
127537
|
return mock;
|
|
127538
127538
|
}
|
|
127539
127539
|
var MAX_CREATE_FLIGHTS = 256;
|
|
127540
|
+
var COLLECTION_LIST_PAGE_LIMIT = 100;
|
|
127540
127541
|
var createFlights = /* @__PURE__ */ new Map();
|
|
127541
127542
|
var PostmanGatewayAssetsClient = class {
|
|
127542
127543
|
gateway;
|
|
@@ -127708,8 +127709,80 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127708
127709
|
method: "get",
|
|
127709
127710
|
path: `/specifications/${id}/collections`
|
|
127710
127711
|
});
|
|
127711
|
-
|
|
127712
|
-
return
|
|
127712
|
+
if (!Array.isArray(response?.data)) throw new Error("SPEC_COLLECTION_LIST_RESPONSE_INVALID");
|
|
127713
|
+
return response.data.map((value) => {
|
|
127714
|
+
const entry = this.asRecord(value);
|
|
127715
|
+
const rawUid = entry?.collection ?? entry?.collectionId ?? entry?.id;
|
|
127716
|
+
if (!entry || typeof rawUid !== "string" || entry.name !== void 0 && typeof entry.name !== "string") {
|
|
127717
|
+
throw new Error("SPEC_COLLECTION_LIST_RESPONSE_INVALID");
|
|
127718
|
+
}
|
|
127719
|
+
const uid = this.requireSafePathSegment(rawUid, "Specification collection UID");
|
|
127720
|
+
return { uid, name: typeof entry.name === "string" ? entry.name.trim() : "" };
|
|
127721
|
+
});
|
|
127722
|
+
}
|
|
127723
|
+
/**
|
|
127724
|
+
* Authoritative workspace collection-name snapshot for GC. Drain the v3
|
|
127725
|
+
* collection service's cursor before returning: a partial inventory must not
|
|
127726
|
+
* authorize parent/spec deletion. This list route replaces per-relation full
|
|
127727
|
+
* exports in GC; `getCollection` remains reserved for repo file materialization.
|
|
127728
|
+
*/
|
|
127729
|
+
async listCollections(workspaceId) {
|
|
127730
|
+
const ws = this.requireSafePathSegment(workspaceId, "Workspace UID");
|
|
127731
|
+
const rows = [];
|
|
127732
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
127733
|
+
let cursor;
|
|
127734
|
+
for (let page = 0; page < COLLECTION_LIST_PAGE_LIMIT; page += 1) {
|
|
127735
|
+
const response = await this.gateway.requestJson({
|
|
127736
|
+
service: "collection",
|
|
127737
|
+
method: "get",
|
|
127738
|
+
path: `/v3/collections/?workspace=${ws}`,
|
|
127739
|
+
...cursor ? { query: { cursor } } : {}
|
|
127740
|
+
});
|
|
127741
|
+
if (!Array.isArray(response?.data)) throw new Error("COLLECTION_LIST_RESPONSE_INVALID");
|
|
127742
|
+
for (const value of response.data) {
|
|
127743
|
+
const record = this.asRecord(value);
|
|
127744
|
+
const rawUid = record?.id ?? record?.uid;
|
|
127745
|
+
const rawName = record?.name ?? record?.title;
|
|
127746
|
+
if (typeof rawUid !== "string" || typeof rawName !== "string") {
|
|
127747
|
+
throw new Error("COLLECTION_LIST_RESPONSE_INVALID");
|
|
127748
|
+
}
|
|
127749
|
+
const uid = rawUid.trim();
|
|
127750
|
+
const name = rawName.trim();
|
|
127751
|
+
if (!uid || !name || !/^[A-Za-z0-9._~-]+$/.test(uid) || uid === "." || uid === "..") {
|
|
127752
|
+
throw new Error("COLLECTION_LIST_RESPONSE_INVALID");
|
|
127753
|
+
}
|
|
127754
|
+
rows.push({ uid, name });
|
|
127755
|
+
}
|
|
127756
|
+
const meta = response.meta === void 0 ? null : this.asRecord(response.meta);
|
|
127757
|
+
if (response.meta !== void 0 && response.meta !== null && !meta) {
|
|
127758
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
127759
|
+
}
|
|
127760
|
+
const paginationValue = meta?.pagination;
|
|
127761
|
+
const pagination = paginationValue === void 0 ? null : this.asRecord(paginationValue);
|
|
127762
|
+
if (paginationValue !== void 0 && paginationValue !== null && !pagination) {
|
|
127763
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
127764
|
+
}
|
|
127765
|
+
const cursorValue = meta?.cursor;
|
|
127766
|
+
const cursorEnvelope = cursorValue === void 0 ? null : this.asRecord(cursorValue);
|
|
127767
|
+
if (cursorValue !== void 0 && cursorValue !== null && !cursorEnvelope) {
|
|
127768
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
127769
|
+
}
|
|
127770
|
+
const candidates = [pagination?.nextPage, cursorEnvelope?.next, meta?.nextCursor, response.nextCursor].filter((value) => value !== void 0 && value !== null && value !== "");
|
|
127771
|
+
if (candidates.some((value) => typeof value !== "string")) {
|
|
127772
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
127773
|
+
}
|
|
127774
|
+
const nextCursors = [...new Set(candidates.map((value) => String(value).trim()).filter(Boolean))];
|
|
127775
|
+
if (nextCursors.length > 1) throw new Error("COLLECTION_LIST_CURSOR_AMBIGUOUS");
|
|
127776
|
+
const next = nextCursors[0];
|
|
127777
|
+
if (!next) return rows;
|
|
127778
|
+
if (seenCursors.has(next)) throw new Error("COLLECTION_LIST_CURSOR_REPEATED");
|
|
127779
|
+
seenCursors.add(next);
|
|
127780
|
+
if (page === COLLECTION_LIST_PAGE_LIMIT - 1) {
|
|
127781
|
+
throw new Error("COLLECTION_LIST_PAGE_LIMIT_EXCEEDED");
|
|
127782
|
+
}
|
|
127783
|
+
cursor = next;
|
|
127784
|
+
}
|
|
127785
|
+
throw new Error("COLLECTION_LIST_PAGE_LIMIT_EXCEEDED");
|
|
127713
127786
|
}
|
|
127714
127787
|
async deleteSpec(specId) {
|
|
127715
127788
|
const id = this.requireSafePathSegment(specId, "Specification UID");
|
|
@@ -132164,6 +132237,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
132164
132237
|
deleteMock: gatewayAssets.deleteMock.bind(gatewayAssets),
|
|
132165
132238
|
deleteMonitor: gatewayAssets.deleteMonitor.bind(gatewayAssets),
|
|
132166
132239
|
deleteCollection: gatewayAssets.deleteCollection.bind(gatewayAssets),
|
|
132240
|
+
listCollections: gatewayAssets.listCollections.bind(gatewayAssets),
|
|
132167
132241
|
listSpecifications: gatewayAssets.listSpecifications.bind(gatewayAssets),
|
|
132168
132242
|
getSpecContent: gatewayAssets.getSpecContent.bind(gatewayAssets),
|
|
132169
132243
|
listSpecCollections: gatewayAssets.listSpecCollections.bind(gatewayAssets),
|
package/dist/cli.cjs
CHANGED
|
@@ -125642,6 +125642,7 @@ function requireMockVisibility(mock, requested) {
|
|
|
125642
125642
|
return mock;
|
|
125643
125643
|
}
|
|
125644
125644
|
var MAX_CREATE_FLIGHTS = 256;
|
|
125645
|
+
var COLLECTION_LIST_PAGE_LIMIT = 100;
|
|
125645
125646
|
var createFlights = /* @__PURE__ */ new Map();
|
|
125646
125647
|
var PostmanGatewayAssetsClient = class {
|
|
125647
125648
|
gateway;
|
|
@@ -125813,8 +125814,80 @@ var PostmanGatewayAssetsClient = class {
|
|
|
125813
125814
|
method: "get",
|
|
125814
125815
|
path: `/specifications/${id}/collections`
|
|
125815
125816
|
});
|
|
125816
|
-
|
|
125817
|
-
return
|
|
125817
|
+
if (!Array.isArray(response?.data)) throw new Error("SPEC_COLLECTION_LIST_RESPONSE_INVALID");
|
|
125818
|
+
return response.data.map((value) => {
|
|
125819
|
+
const entry = this.asRecord(value);
|
|
125820
|
+
const rawUid = entry?.collection ?? entry?.collectionId ?? entry?.id;
|
|
125821
|
+
if (!entry || typeof rawUid !== "string" || entry.name !== void 0 && typeof entry.name !== "string") {
|
|
125822
|
+
throw new Error("SPEC_COLLECTION_LIST_RESPONSE_INVALID");
|
|
125823
|
+
}
|
|
125824
|
+
const uid = this.requireSafePathSegment(rawUid, "Specification collection UID");
|
|
125825
|
+
return { uid, name: typeof entry.name === "string" ? entry.name.trim() : "" };
|
|
125826
|
+
});
|
|
125827
|
+
}
|
|
125828
|
+
/**
|
|
125829
|
+
* Authoritative workspace collection-name snapshot for GC. Drain the v3
|
|
125830
|
+
* collection service's cursor before returning: a partial inventory must not
|
|
125831
|
+
* authorize parent/spec deletion. This list route replaces per-relation full
|
|
125832
|
+
* exports in GC; `getCollection` remains reserved for repo file materialization.
|
|
125833
|
+
*/
|
|
125834
|
+
async listCollections(workspaceId) {
|
|
125835
|
+
const ws = this.requireSafePathSegment(workspaceId, "Workspace UID");
|
|
125836
|
+
const rows = [];
|
|
125837
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
125838
|
+
let cursor;
|
|
125839
|
+
for (let page = 0; page < COLLECTION_LIST_PAGE_LIMIT; page += 1) {
|
|
125840
|
+
const response = await this.gateway.requestJson({
|
|
125841
|
+
service: "collection",
|
|
125842
|
+
method: "get",
|
|
125843
|
+
path: `/v3/collections/?workspace=${ws}`,
|
|
125844
|
+
...cursor ? { query: { cursor } } : {}
|
|
125845
|
+
});
|
|
125846
|
+
if (!Array.isArray(response?.data)) throw new Error("COLLECTION_LIST_RESPONSE_INVALID");
|
|
125847
|
+
for (const value of response.data) {
|
|
125848
|
+
const record = this.asRecord(value);
|
|
125849
|
+
const rawUid = record?.id ?? record?.uid;
|
|
125850
|
+
const rawName = record?.name ?? record?.title;
|
|
125851
|
+
if (typeof rawUid !== "string" || typeof rawName !== "string") {
|
|
125852
|
+
throw new Error("COLLECTION_LIST_RESPONSE_INVALID");
|
|
125853
|
+
}
|
|
125854
|
+
const uid = rawUid.trim();
|
|
125855
|
+
const name = rawName.trim();
|
|
125856
|
+
if (!uid || !name || !/^[A-Za-z0-9._~-]+$/.test(uid) || uid === "." || uid === "..") {
|
|
125857
|
+
throw new Error("COLLECTION_LIST_RESPONSE_INVALID");
|
|
125858
|
+
}
|
|
125859
|
+
rows.push({ uid, name });
|
|
125860
|
+
}
|
|
125861
|
+
const meta = response.meta === void 0 ? null : this.asRecord(response.meta);
|
|
125862
|
+
if (response.meta !== void 0 && response.meta !== null && !meta) {
|
|
125863
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
125864
|
+
}
|
|
125865
|
+
const paginationValue = meta?.pagination;
|
|
125866
|
+
const pagination = paginationValue === void 0 ? null : this.asRecord(paginationValue);
|
|
125867
|
+
if (paginationValue !== void 0 && paginationValue !== null && !pagination) {
|
|
125868
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
125869
|
+
}
|
|
125870
|
+
const cursorValue = meta?.cursor;
|
|
125871
|
+
const cursorEnvelope = cursorValue === void 0 ? null : this.asRecord(cursorValue);
|
|
125872
|
+
if (cursorValue !== void 0 && cursorValue !== null && !cursorEnvelope) {
|
|
125873
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
125874
|
+
}
|
|
125875
|
+
const candidates = [pagination?.nextPage, cursorEnvelope?.next, meta?.nextCursor, response.nextCursor].filter((value) => value !== void 0 && value !== null && value !== "");
|
|
125876
|
+
if (candidates.some((value) => typeof value !== "string")) {
|
|
125877
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
125878
|
+
}
|
|
125879
|
+
const nextCursors = [...new Set(candidates.map((value) => String(value).trim()).filter(Boolean))];
|
|
125880
|
+
if (nextCursors.length > 1) throw new Error("COLLECTION_LIST_CURSOR_AMBIGUOUS");
|
|
125881
|
+
const next = nextCursors[0];
|
|
125882
|
+
if (!next) return rows;
|
|
125883
|
+
if (seenCursors.has(next)) throw new Error("COLLECTION_LIST_CURSOR_REPEATED");
|
|
125884
|
+
seenCursors.add(next);
|
|
125885
|
+
if (page === COLLECTION_LIST_PAGE_LIMIT - 1) {
|
|
125886
|
+
throw new Error("COLLECTION_LIST_PAGE_LIMIT_EXCEEDED");
|
|
125887
|
+
}
|
|
125888
|
+
cursor = next;
|
|
125889
|
+
}
|
|
125890
|
+
throw new Error("COLLECTION_LIST_PAGE_LIMIT_EXCEEDED");
|
|
125818
125891
|
}
|
|
125819
125892
|
async deleteSpec(specId) {
|
|
125820
125893
|
const id = this.requireSafePathSegment(specId, "Specification UID");
|
|
@@ -130073,6 +130146,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
130073
130146
|
deleteMock: gatewayAssets.deleteMock.bind(gatewayAssets),
|
|
130074
130147
|
deleteMonitor: gatewayAssets.deleteMonitor.bind(gatewayAssets),
|
|
130075
130148
|
deleteCollection: gatewayAssets.deleteCollection.bind(gatewayAssets),
|
|
130149
|
+
listCollections: gatewayAssets.listCollections.bind(gatewayAssets),
|
|
130076
130150
|
listSpecifications: gatewayAssets.listSpecifications.bind(gatewayAssets),
|
|
130077
130151
|
getSpecContent: gatewayAssets.getSpecContent.bind(gatewayAssets),
|
|
130078
130152
|
listSpecCollections: gatewayAssets.listSpecCollections.bind(gatewayAssets),
|
|
@@ -130389,8 +130463,53 @@ function markerFromSpecContent(content) {
|
|
|
130389
130463
|
function isGcCandidateName(name) {
|
|
130390
130464
|
return / @[A-Za-z0-9._-]+/.test(name) || /^\[[A-Z][A-Z0-9]*\] /.test(name);
|
|
130391
130465
|
}
|
|
130466
|
+
var BARE_COLLECTION_MODEL_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
130467
|
+
var PUBLIC_COLLECTION_MODEL_ID = /^\d+-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;
|
|
130468
|
+
var SAFE_COLLECTION_ID = /^[A-Za-z0-9._~-]+$/;
|
|
130469
|
+
function normalizedCollectionIdentity(raw) {
|
|
130470
|
+
if (typeof raw !== "string") return void 0;
|
|
130471
|
+
const value = raw.trim();
|
|
130472
|
+
if (!value || value === "." || value === ".." || !SAFE_COLLECTION_ID.test(value)) return void 0;
|
|
130473
|
+
const publicMatch = PUBLIC_COLLECTION_MODEL_ID.exec(value);
|
|
130474
|
+
if (publicMatch) return publicMatch[1].toLowerCase();
|
|
130475
|
+
if (BARE_COLLECTION_MODEL_ID.test(value)) return value.toLowerCase();
|
|
130476
|
+
return value;
|
|
130477
|
+
}
|
|
130478
|
+
function indexCollectionInventory(rows) {
|
|
130479
|
+
if (!Array.isArray(rows)) throw new Error("COLLECTION_INVENTORY_INVALID");
|
|
130480
|
+
const index = /* @__PURE__ */ new Map();
|
|
130481
|
+
for (const raw of rows) {
|
|
130482
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
130483
|
+
throw new Error("COLLECTION_INVENTORY_INVALID");
|
|
130484
|
+
}
|
|
130485
|
+
const record = raw;
|
|
130486
|
+
const identity = normalizedCollectionIdentity(record.uid);
|
|
130487
|
+
const uid = typeof record.uid === "string" ? record.uid.trim() : "";
|
|
130488
|
+
const name = typeof record.name === "string" ? record.name.trim() : "";
|
|
130489
|
+
if (!identity || !uid || !name) throw new Error("COLLECTION_INVENTORY_INVALID");
|
|
130490
|
+
const matches = index.get(identity) ?? [];
|
|
130491
|
+
matches.push({ uid, name });
|
|
130492
|
+
index.set(identity, matches);
|
|
130493
|
+
}
|
|
130494
|
+
return index;
|
|
130495
|
+
}
|
|
130392
130496
|
async function collectGcCandidates(postman, workspaceId) {
|
|
130393
130497
|
const candidates = [];
|
|
130498
|
+
let collectionInventory;
|
|
130499
|
+
try {
|
|
130500
|
+
collectionInventory = indexCollectionInventory(await postman.listCollections(workspaceId));
|
|
130501
|
+
} catch {
|
|
130502
|
+
collectionInventory = void 0;
|
|
130503
|
+
}
|
|
130504
|
+
const resolveGeneratedCollection = (uid) => {
|
|
130505
|
+
const identity = normalizedCollectionIdentity(uid);
|
|
130506
|
+
if (!identity || !collectionInventory) return void 0;
|
|
130507
|
+
const matches = collectionInventory.get(identity) ?? [];
|
|
130508
|
+
if (matches.length !== 1) return void 0;
|
|
130509
|
+
const match = matches[0];
|
|
130510
|
+
return isGcCandidateName(match.name) ? match : void 0;
|
|
130511
|
+
};
|
|
130512
|
+
const discoveredCollectionIdentities = /* @__PURE__ */ new Set();
|
|
130394
130513
|
const environments = await postman.listEnvironments(workspaceId);
|
|
130395
130514
|
for (const env of environments) {
|
|
130396
130515
|
if (!isGcCandidateName(env.name)) continue;
|
|
@@ -130428,14 +130547,11 @@ async function collectGcCandidates(postman, workspaceId) {
|
|
|
130428
130547
|
if (marker && monitor.collectionUid) ownedCollections.set(monitor.collectionUid, { marker });
|
|
130429
130548
|
}
|
|
130430
130549
|
for (const [uid, collection] of ownedCollections) {
|
|
130431
|
-
|
|
130432
|
-
|
|
130433
|
-
|
|
130434
|
-
|
|
130435
|
-
|
|
130436
|
-
candidates.push({ kind: "collection", uid, name, marker: collection.marker });
|
|
130437
|
-
}
|
|
130438
|
-
} catch {
|
|
130550
|
+
const resolved = resolveGeneratedCollection(uid);
|
|
130551
|
+
const identity = normalizedCollectionIdentity(resolved?.uid);
|
|
130552
|
+
if (resolved && identity && !discoveredCollectionIdentities.has(identity)) {
|
|
130553
|
+
candidates.push({ kind: "collection", uid: resolved.uid, name: resolved.name, marker: collection.marker });
|
|
130554
|
+
discoveredCollectionIdentities.add(identity);
|
|
130439
130555
|
}
|
|
130440
130556
|
}
|
|
130441
130557
|
const specifications = await postman.listSpecifications(workspaceId);
|
|
@@ -130447,16 +130563,42 @@ async function collectGcCandidates(postman, workspaceId) {
|
|
|
130447
130563
|
} catch {
|
|
130448
130564
|
marker = void 0;
|
|
130449
130565
|
}
|
|
130450
|
-
candidates.push({ kind: "spec", uid: spec.uid, name: spec.name, marker });
|
|
130451
130566
|
if (marker) {
|
|
130567
|
+
const linkedCandidates = [];
|
|
130568
|
+
let relationsResolved = true;
|
|
130452
130569
|
try {
|
|
130453
|
-
|
|
130454
|
-
|
|
130455
|
-
|
|
130570
|
+
const relations = await postman.listSpecCollections(spec.uid);
|
|
130571
|
+
if (relations.length === 0) relationsResolved = false;
|
|
130572
|
+
for (const collection of relations) {
|
|
130573
|
+
const relationIdentity = normalizedCollectionIdentity(collection.uid);
|
|
130574
|
+
if (!relationIdentity) {
|
|
130575
|
+
relationsResolved = false;
|
|
130576
|
+
continue;
|
|
130577
|
+
}
|
|
130578
|
+
if (discoveredCollectionIdentities.has(relationIdentity)) continue;
|
|
130579
|
+
const resolved = resolveGeneratedCollection(collection.uid);
|
|
130580
|
+
const resolvedIdentity = normalizedCollectionIdentity(resolved?.uid);
|
|
130581
|
+
if (!resolved || !resolvedIdentity || resolvedIdentity !== relationIdentity) {
|
|
130582
|
+
relationsResolved = false;
|
|
130583
|
+
continue;
|
|
130456
130584
|
}
|
|
130585
|
+
linkedCandidates.push({ kind: "collection", uid: resolved.uid, name: resolved.name, marker });
|
|
130457
130586
|
}
|
|
130458
130587
|
} catch {
|
|
130588
|
+
relationsResolved = false;
|
|
130459
130589
|
}
|
|
130590
|
+
if (!relationsResolved) {
|
|
130591
|
+
continue;
|
|
130592
|
+
}
|
|
130593
|
+
candidates.push({ kind: "spec", uid: spec.uid, name: spec.name, marker });
|
|
130594
|
+
for (const collection of linkedCandidates) {
|
|
130595
|
+
const identity = normalizedCollectionIdentity(collection.uid);
|
|
130596
|
+
if (!identity || discoveredCollectionIdentities.has(identity)) continue;
|
|
130597
|
+
candidates.push(collection);
|
|
130598
|
+
discoveredCollectionIdentities.add(identity);
|
|
130599
|
+
}
|
|
130600
|
+
} else {
|
|
130601
|
+
candidates.push({ kind: "spec", uid: spec.uid, name: spec.name, marker });
|
|
130460
130602
|
}
|
|
130461
130603
|
}
|
|
130462
130604
|
return candidates;
|
|
@@ -131117,7 +131259,7 @@ async function runGcCommand(argv, env, writeStdout) {
|
|
|
131117
131259
|
{ persistGeneratedApiKeySecret: false, env }
|
|
131118
131260
|
);
|
|
131119
131261
|
const dependencies = createCliDependencies(inputs, resolved);
|
|
131120
|
-
if (!dependencies.postman.deleteCollection || !dependencies.postman.listSpecifications || !dependencies.postman.getSpecContent || !dependencies.postman.listSpecCollections || !dependencies.postman.deleteSpec) {
|
|
131262
|
+
if (!dependencies.postman.deleteCollection || !dependencies.postman.listCollections || !dependencies.postman.listSpecifications || !dependencies.postman.getSpecContent || !dependencies.postman.listSpecCollections || !dependencies.postman.deleteSpec) {
|
|
131121
131263
|
throw new Error("gc requires the full branch-aware inventory client; this runtime is missing a spec or collection GC capability.");
|
|
131122
131264
|
}
|
|
131123
131265
|
const summary2 = await runGc({
|
|
@@ -131126,6 +131268,7 @@ async function runGcCommand(argv, env, writeStdout) {
|
|
|
131126
131268
|
postman: {
|
|
131127
131269
|
...dependencies.postman,
|
|
131128
131270
|
deleteCollection: dependencies.postman.deleteCollection,
|
|
131271
|
+
listCollections: dependencies.postman.listCollections,
|
|
131129
131272
|
listSpecifications: dependencies.postman.listSpecifications,
|
|
131130
131273
|
getSpecContent: dependencies.postman.getSpecContent,
|
|
131131
131274
|
listSpecCollections: dependencies.postman.listSpecCollections,
|
package/dist/index.cjs
CHANGED
|
@@ -127563,6 +127563,7 @@ function requireMockVisibility(mock, requested) {
|
|
|
127563
127563
|
return mock;
|
|
127564
127564
|
}
|
|
127565
127565
|
var MAX_CREATE_FLIGHTS = 256;
|
|
127566
|
+
var COLLECTION_LIST_PAGE_LIMIT = 100;
|
|
127566
127567
|
var createFlights = /* @__PURE__ */ new Map();
|
|
127567
127568
|
var PostmanGatewayAssetsClient = class {
|
|
127568
127569
|
gateway;
|
|
@@ -127734,8 +127735,80 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127734
127735
|
method: "get",
|
|
127735
127736
|
path: `/specifications/${id}/collections`
|
|
127736
127737
|
});
|
|
127737
|
-
|
|
127738
|
-
return
|
|
127738
|
+
if (!Array.isArray(response?.data)) throw new Error("SPEC_COLLECTION_LIST_RESPONSE_INVALID");
|
|
127739
|
+
return response.data.map((value) => {
|
|
127740
|
+
const entry = this.asRecord(value);
|
|
127741
|
+
const rawUid = entry?.collection ?? entry?.collectionId ?? entry?.id;
|
|
127742
|
+
if (!entry || typeof rawUid !== "string" || entry.name !== void 0 && typeof entry.name !== "string") {
|
|
127743
|
+
throw new Error("SPEC_COLLECTION_LIST_RESPONSE_INVALID");
|
|
127744
|
+
}
|
|
127745
|
+
const uid = this.requireSafePathSegment(rawUid, "Specification collection UID");
|
|
127746
|
+
return { uid, name: typeof entry.name === "string" ? entry.name.trim() : "" };
|
|
127747
|
+
});
|
|
127748
|
+
}
|
|
127749
|
+
/**
|
|
127750
|
+
* Authoritative workspace collection-name snapshot for GC. Drain the v3
|
|
127751
|
+
* collection service's cursor before returning: a partial inventory must not
|
|
127752
|
+
* authorize parent/spec deletion. This list route replaces per-relation full
|
|
127753
|
+
* exports in GC; `getCollection` remains reserved for repo file materialization.
|
|
127754
|
+
*/
|
|
127755
|
+
async listCollections(workspaceId) {
|
|
127756
|
+
const ws = this.requireSafePathSegment(workspaceId, "Workspace UID");
|
|
127757
|
+
const rows = [];
|
|
127758
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
127759
|
+
let cursor;
|
|
127760
|
+
for (let page = 0; page < COLLECTION_LIST_PAGE_LIMIT; page += 1) {
|
|
127761
|
+
const response = await this.gateway.requestJson({
|
|
127762
|
+
service: "collection",
|
|
127763
|
+
method: "get",
|
|
127764
|
+
path: `/v3/collections/?workspace=${ws}`,
|
|
127765
|
+
...cursor ? { query: { cursor } } : {}
|
|
127766
|
+
});
|
|
127767
|
+
if (!Array.isArray(response?.data)) throw new Error("COLLECTION_LIST_RESPONSE_INVALID");
|
|
127768
|
+
for (const value of response.data) {
|
|
127769
|
+
const record = this.asRecord(value);
|
|
127770
|
+
const rawUid = record?.id ?? record?.uid;
|
|
127771
|
+
const rawName = record?.name ?? record?.title;
|
|
127772
|
+
if (typeof rawUid !== "string" || typeof rawName !== "string") {
|
|
127773
|
+
throw new Error("COLLECTION_LIST_RESPONSE_INVALID");
|
|
127774
|
+
}
|
|
127775
|
+
const uid = rawUid.trim();
|
|
127776
|
+
const name = rawName.trim();
|
|
127777
|
+
if (!uid || !name || !/^[A-Za-z0-9._~-]+$/.test(uid) || uid === "." || uid === "..") {
|
|
127778
|
+
throw new Error("COLLECTION_LIST_RESPONSE_INVALID");
|
|
127779
|
+
}
|
|
127780
|
+
rows.push({ uid, name });
|
|
127781
|
+
}
|
|
127782
|
+
const meta = response.meta === void 0 ? null : this.asRecord(response.meta);
|
|
127783
|
+
if (response.meta !== void 0 && response.meta !== null && !meta) {
|
|
127784
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
127785
|
+
}
|
|
127786
|
+
const paginationValue = meta?.pagination;
|
|
127787
|
+
const pagination = paginationValue === void 0 ? null : this.asRecord(paginationValue);
|
|
127788
|
+
if (paginationValue !== void 0 && paginationValue !== null && !pagination) {
|
|
127789
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
127790
|
+
}
|
|
127791
|
+
const cursorValue = meta?.cursor;
|
|
127792
|
+
const cursorEnvelope = cursorValue === void 0 ? null : this.asRecord(cursorValue);
|
|
127793
|
+
if (cursorValue !== void 0 && cursorValue !== null && !cursorEnvelope) {
|
|
127794
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
127795
|
+
}
|
|
127796
|
+
const candidates = [pagination?.nextPage, cursorEnvelope?.next, meta?.nextCursor, response.nextCursor].filter((value) => value !== void 0 && value !== null && value !== "");
|
|
127797
|
+
if (candidates.some((value) => typeof value !== "string")) {
|
|
127798
|
+
throw new Error("COLLECTION_LIST_CURSOR_INVALID");
|
|
127799
|
+
}
|
|
127800
|
+
const nextCursors = [...new Set(candidates.map((value) => String(value).trim()).filter(Boolean))];
|
|
127801
|
+
if (nextCursors.length > 1) throw new Error("COLLECTION_LIST_CURSOR_AMBIGUOUS");
|
|
127802
|
+
const next = nextCursors[0];
|
|
127803
|
+
if (!next) return rows;
|
|
127804
|
+
if (seenCursors.has(next)) throw new Error("COLLECTION_LIST_CURSOR_REPEATED");
|
|
127805
|
+
seenCursors.add(next);
|
|
127806
|
+
if (page === COLLECTION_LIST_PAGE_LIMIT - 1) {
|
|
127807
|
+
throw new Error("COLLECTION_LIST_PAGE_LIMIT_EXCEEDED");
|
|
127808
|
+
}
|
|
127809
|
+
cursor = next;
|
|
127810
|
+
}
|
|
127811
|
+
throw new Error("COLLECTION_LIST_PAGE_LIMIT_EXCEEDED");
|
|
127739
127812
|
}
|
|
127740
127813
|
async deleteSpec(specId) {
|
|
127741
127814
|
const id = this.requireSafePathSegment(specId, "Specification UID");
|
|
@@ -132190,6 +132263,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
132190
132263
|
deleteMock: gatewayAssets.deleteMock.bind(gatewayAssets),
|
|
132191
132264
|
deleteMonitor: gatewayAssets.deleteMonitor.bind(gatewayAssets),
|
|
132192
132265
|
deleteCollection: gatewayAssets.deleteCollection.bind(gatewayAssets),
|
|
132266
|
+
listCollections: gatewayAssets.listCollections.bind(gatewayAssets),
|
|
132193
132267
|
listSpecifications: gatewayAssets.listSpecifications.bind(gatewayAssets),
|
|
132194
132268
|
getSpecContent: gatewayAssets.getSpecContent.bind(gatewayAssets),
|
|
132195
132269
|
listSpecCollections: gatewayAssets.listSpecCollections.bind(gatewayAssets),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postman-cs/onboarding-repo-sync",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.6",
|
|
4
4
|
"description": "Postman repo sync GitHub Action.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"docs:tables": "node scripts/render-action-tables.mjs",
|
|
28
28
|
"lint": "eslint .",
|
|
29
29
|
"lint:fix": "eslint . --fix",
|
|
30
|
-
"test": "vitest run --exclude tests/ci-workflow-template.test.ts && vitest run tests/ci-workflow-template.test.ts && node --test .github/scripts/dispatch-e2e-monitor.test.mjs .github/scripts/prefetch-vendored-deps.test.mjs",
|
|
30
|
+
"test": "vitest run --exclude tests/ci-workflow-template.test.ts && vitest run tests/ci-workflow-template.test.ts && node --test .github/scripts/dispatch-e2e-monitor.test.mjs .github/scripts/prefetch-vendored-deps.test.mjs .github/scripts/verify-e2e-release.test.mjs",
|
|
31
31
|
"test:emulator:git": "vitest run --config vitest.emulator.config.ts",
|
|
32
32
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
33
33
|
"record:cassettes": "RECORD_FAKE_CASSETTES=1 vitest run tests/contract/record-fake-cassettes.test.ts"
|