@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 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,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
- try {
130432
- const payload = await postman.getCollection(uid);
130433
- const info = payload?.info && typeof payload.info === "object" ? payload.info : void 0;
130434
- const name = String(payload?.name ?? info?.name ?? "").trim();
130435
- if (name && isGcCandidateName(name)) {
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
- for (const collection of await postman.listSpecCollections(spec.uid)) {
130454
- if (!ownedCollections.has(collection.uid) && isGcCandidateName(collection.name)) {
130455
- candidates.push({ kind: "collection", uid: collection.uid, name: collection.name || `${spec.name} collection`, marker });
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
- 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.4",
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"