@postman-cs/onboarding-repo-sync 2.10.5 → 2.10.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/action.cjs 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
- const data2 = Array.isArray(response?.data) ? response.data : [];
127712
- return data2.map((entry) => this.asRecord(entry)).filter((entry) => entry !== null).map((entry) => ({ uid: String(entry.collection ?? entry.collectionId ?? entry.id ?? "").trim(), name: String(entry.name ?? "").trim() })).filter((entry) => entry.uid);
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
- const data2 = Array.isArray(response?.data) ? response.data : [];
125817
- return data2.map((entry) => this.asRecord(entry)).filter((entry) => entry !== null).map((entry) => ({ uid: String(entry.collection ?? entry.collectionId ?? entry.id ?? "").trim(), name: String(entry.name ?? "").trim() })).filter((entry) => entry.uid);
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,28 +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
  }
130392
- function exactCollectionName(payload) {
130393
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) return "";
130394
- const record = payload;
130395
- const info = record.info && typeof record.info === "object" && !Array.isArray(record.info) ? record.info : void 0;
130396
- return String(record.name ?? info?.name ?? "").trim();
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;
130397
130495
  }
130398
130496
  async function collectGcCandidates(postman, workspaceId) {
130399
130497
  const candidates = [];
130400
- const exactCollectionNames = /* @__PURE__ */ new Map();
130401
- const readGeneratedCollectionName = async (uid) => {
130402
- if (exactCollectionNames.has(uid)) return exactCollectionNames.get(uid);
130403
- let name;
130404
- try {
130405
- const candidate = exactCollectionName(await postman.getCollection(uid));
130406
- name = candidate && isGcCandidateName(candidate) ? candidate : void 0;
130407
- } catch {
130408
- name = void 0;
130409
- }
130410
- exactCollectionNames.set(uid, name);
130411
- return name;
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;
130412
130511
  };
130413
- const discoveredCollectionUids = /* @__PURE__ */ new Set();
130512
+ const discoveredCollectionIdentities = /* @__PURE__ */ new Set();
130414
130513
  const environments = await postman.listEnvironments(workspaceId);
130415
130514
  for (const env of environments) {
130416
130515
  if (!isGcCandidateName(env.name)) continue;
@@ -130448,10 +130547,11 @@ async function collectGcCandidates(postman, workspaceId) {
130448
130547
  if (marker && monitor.collectionUid) ownedCollections.set(monitor.collectionUid, { marker });
130449
130548
  }
130450
130549
  for (const [uid, collection] of ownedCollections) {
130451
- const name = await readGeneratedCollectionName(uid);
130452
- if (name) {
130453
- candidates.push({ kind: "collection", uid, name, marker: collection.marker });
130454
- discoveredCollectionUids.add(uid);
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);
130455
130555
  }
130456
130556
  }
130457
130557
  const specifications = await postman.listSpecifications(workspaceId);
@@ -130467,14 +130567,22 @@ async function collectGcCandidates(postman, workspaceId) {
130467
130567
  const linkedCandidates = [];
130468
130568
  let relationsResolved = true;
130469
130569
  try {
130470
- for (const collection of await postman.listSpecCollections(spec.uid)) {
130471
- if (discoveredCollectionUids.has(collection.uid)) continue;
130472
- const name = await readGeneratedCollectionName(collection.uid);
130473
- if (!name) {
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) {
130474
130582
  relationsResolved = false;
130475
130583
  continue;
130476
130584
  }
130477
- linkedCandidates.push({ kind: "collection", uid: collection.uid, name, marker });
130585
+ linkedCandidates.push({ kind: "collection", uid: resolved.uid, name: resolved.name, marker });
130478
130586
  }
130479
130587
  } catch {
130480
130588
  relationsResolved = false;
@@ -130484,9 +130592,10 @@ async function collectGcCandidates(postman, workspaceId) {
130484
130592
  }
130485
130593
  candidates.push({ kind: "spec", uid: spec.uid, name: spec.name, marker });
130486
130594
  for (const collection of linkedCandidates) {
130487
- if (discoveredCollectionUids.has(collection.uid)) continue;
130595
+ const identity = normalizedCollectionIdentity(collection.uid);
130596
+ if (!identity || discoveredCollectionIdentities.has(identity)) continue;
130488
130597
  candidates.push(collection);
130489
- discoveredCollectionUids.add(collection.uid);
130598
+ discoveredCollectionIdentities.add(identity);
130490
130599
  }
130491
130600
  } else {
130492
130601
  candidates.push({ kind: "spec", uid: spec.uid, name: spec.name, marker });
@@ -131150,7 +131259,7 @@ async function runGcCommand(argv, env, writeStdout) {
131150
131259
  { persistGeneratedApiKeySecret: false, env }
131151
131260
  );
131152
131261
  const dependencies = createCliDependencies(inputs, resolved);
131153
- 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) {
131154
131263
  throw new Error("gc requires the full branch-aware inventory client; this runtime is missing a spec or collection GC capability.");
131155
131264
  }
131156
131265
  const summary2 = await runGc({
@@ -131159,6 +131268,7 @@ async function runGcCommand(argv, env, writeStdout) {
131159
131268
  postman: {
131160
131269
  ...dependencies.postman,
131161
131270
  deleteCollection: dependencies.postman.deleteCollection,
131271
+ listCollections: dependencies.postman.listCollections,
131162
131272
  listSpecifications: dependencies.postman.listSpecifications,
131163
131273
  getSpecContent: dependencies.postman.getSpecContent,
131164
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
- const data2 = Array.isArray(response?.data) ? response.data : [];
127738
- return data2.map((entry) => this.asRecord(entry)).filter((entry) => entry !== null).map((entry) => ({ uid: String(entry.collection ?? entry.collectionId ?? entry.id ?? "").trim(), name: String(entry.name ?? "").trim() })).filter((entry) => entry.uid);
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.5",
3
+ "version": "2.10.7",
4
4
  "description": "Postman repo sync GitHub Action.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",