@postman-cse/onboarding-bootstrap 2.9.1 → 2.9.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/dist/action.cjs +34 -21
- package/dist/cli.cjs +85 -22
- package/dist/index.cjs +34 -21
- package/package.json +5 -3
package/dist/action.cjs
CHANGED
|
@@ -264257,7 +264257,8 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264257
264257
|
service: "collection",
|
|
264258
264258
|
method: "patch",
|
|
264259
264259
|
path: `/v3/collections/${this.bareModelId(collectionId)}`,
|
|
264260
|
-
|
|
264260
|
+
// Replacing a generated collection's name with the same value is idempotent.
|
|
264261
|
+
retry: "safe",
|
|
264261
264262
|
body: [{ op: "replace", path: "/name", value: name }]
|
|
264262
264263
|
});
|
|
264263
264264
|
}
|
|
@@ -264456,15 +264457,25 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264456
264457
|
}
|
|
264457
264458
|
// --- collection v3 mutation + tagging (live-proven 2026-06-30; see docs/REST-to-gateway.md) ---
|
|
264458
264459
|
//
|
|
264459
|
-
// These retire bootstrap's last asset-op PMAK dependencies.
|
|
264460
|
-
//
|
|
264461
|
-
//
|
|
264462
|
-
//
|
|
264463
|
-
|
|
264460
|
+
// These retire bootstrap's last asset-op PMAK dependencies. Collection ROOT
|
|
264461
|
+
// routes (GET/PATCH/DELETE `/v3/collections/:id`) accept the bare model id.
|
|
264462
|
+
// Collection ITEMS routes (`/v3/collections/:id/items/...`) must use the FULL
|
|
264463
|
+
// public uid (`<owner>-<uuid>`): bare model ids are flaky on org-mode squads
|
|
264464
|
+
// (live-proven 2026-07-14 on team 172912 / Northwind — immediate post-generation
|
|
264465
|
+
// `GET .../items/` returns 403 FORBIDDEN with bare id, 200 with full uid).
|
|
264466
|
+
// The tagging service is distinct and takes the FULL uid.
|
|
264467
|
+
/** `<owner>-<uuid>` public uid -> bare `<uuid>` model id (collection ROOT routes only). */
|
|
264464
264468
|
bareModelId(uid) {
|
|
264465
264469
|
const u = String(uid ?? "").trim();
|
|
264466
264470
|
return u.includes("-") ? u.slice(u.indexOf("-") + 1) : u;
|
|
264467
264471
|
}
|
|
264472
|
+
/**
|
|
264473
|
+
* Collection id for ITEMS routes. Prefer the full public uid; fall back to the
|
|
264474
|
+
* trimmed input when the caller already has a bare/model id.
|
|
264475
|
+
*/
|
|
264476
|
+
collectionItemsId(uid) {
|
|
264477
|
+
return String(uid ?? "").trim();
|
|
264478
|
+
}
|
|
264468
264479
|
/**
|
|
264469
264480
|
* PATCH a freshly-created item's `/scripts`, tolerating the two transient
|
|
264470
264481
|
* failures this immediate-after-create write is prone to on the shared gateway:
|
|
@@ -264523,9 +264534,9 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264523
264534
|
/**
|
|
264524
264535
|
* Inject smoke-test assertions into every leaf request of a spec-generated
|
|
264525
264536
|
* collection, over the v3 collection-items surface (no PMAK):
|
|
264526
|
-
* 1. `GET /v3/collections/:cid/items/` (
|
|
264537
|
+
* 1. `GET /v3/collections/:cid/items/` (FULL public uid, trailing slash) — flat list.
|
|
264527
264538
|
* 2. for each `http-request` leaf, `PATCH /v3/collections/:cid/items/:itemId`
|
|
264528
|
-
* (full uid for `:itemId`, `X-Entity-Type: http-request` header) with a
|
|
264539
|
+
* (full uid for `:cid` and `:itemId`, `X-Entity-Type: http-request` header) with a
|
|
264529
264540
|
* JSON-Patch that sets `/scripts` to the canonical v3 shape
|
|
264530
264541
|
* (`[{type:'afterResponse', code, language}]`). The v3 surface persists test
|
|
264531
264542
|
* scripts under `scripts`, NOT `events`: a `/events` patch returns 200 but is
|
|
@@ -264538,7 +264549,7 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264538
264549
|
*/
|
|
264539
264550
|
async injectTests(collectionUid, type) {
|
|
264540
264551
|
void type;
|
|
264541
|
-
const cid = this.
|
|
264552
|
+
const cid = this.collectionItemsId(collectionUid);
|
|
264542
264553
|
const listed = await this.gateway.requestJson({
|
|
264543
264554
|
service: "collection",
|
|
264544
264555
|
method: "get",
|
|
@@ -264709,7 +264720,7 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264709
264720
|
* Inject the deterministic OpenAPI contract assertions into every generated
|
|
264710
264721
|
* request of a spec-generated collection, entirely over the v3 collection
|
|
264711
264722
|
* surface (no PMAK, no v2.1.0 read/PUT):
|
|
264712
|
-
* 1. `GET /v3/collections/:cid/items/` — flat item list (
|
|
264723
|
+
* 1. `GET /v3/collections/:cid/items/` — flat item list (FULL public uid for `:cid`).
|
|
264713
264724
|
* 2. `GET /v3/collections/:cid/items/:itemId` (`X-Entity-Type: http-request`)
|
|
264714
264725
|
* — the full v3 IR record (method/url/headers/body) the matcher needs.
|
|
264715
264726
|
* 3. `planContractItemScripts` matches each request to its OpenAPI operation
|
|
@@ -264720,7 +264731,7 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264720
264731
|
* Returns the non-fatal instrumentation warnings for the caller to surface.
|
|
264721
264732
|
*/
|
|
264722
264733
|
async injectContractTests(collectionUid, index) {
|
|
264723
|
-
const cid = this.
|
|
264734
|
+
const cid = this.collectionItemsId(collectionUid);
|
|
264724
264735
|
const listed = await this.gateway.requestJson({
|
|
264725
264736
|
service: "collection",
|
|
264726
264737
|
method: "get",
|
|
@@ -265120,11 +265131,12 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
265120
265131
|
if (!rawId) {
|
|
265121
265132
|
throw new Error("Collection create did not return an id");
|
|
265122
265133
|
}
|
|
265123
|
-
const
|
|
265134
|
+
const itemsCid = this.collectionItemsId(rawId);
|
|
265135
|
+
const rootCid = this.bareModelId(rawId);
|
|
265124
265136
|
await options.onRootCreated?.(rawId);
|
|
265125
265137
|
try {
|
|
265126
|
-
await this.createItemTree(
|
|
265127
|
-
await this.applyCollectionLevelSettings(
|
|
265138
|
+
await this.createItemTree(itemsCid, asItemArray(v3.items), itemsCid);
|
|
265139
|
+
await this.applyCollectionLevelSettings(rootCid, v3, { rename: true });
|
|
265128
265140
|
} catch (error2) {
|
|
265129
265141
|
if (options.onRootCreated) throw error2;
|
|
265130
265142
|
let cleanupError;
|
|
@@ -265151,22 +265163,23 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
265151
265163
|
* from the converted v3 IR and reapply name/auth/variables.
|
|
265152
265164
|
*/
|
|
265153
265165
|
async updateCollection(collectionUid, collection) {
|
|
265154
|
-
const
|
|
265166
|
+
const itemsCid = this.collectionItemsId(collectionUid);
|
|
265167
|
+
const rootCid = this.bareModelId(collectionUid);
|
|
265155
265168
|
const v3 = this.normalizeCollectionForWrite(collection);
|
|
265156
|
-
const existingItems = await this.listCollectionItems(
|
|
265169
|
+
const existingItems = await this.listCollectionItems(itemsCid);
|
|
265157
265170
|
for (const item of existingItems) {
|
|
265158
265171
|
const itemId = String(item.id).trim();
|
|
265159
265172
|
try {
|
|
265160
265173
|
await this.gateway.requestJson({
|
|
265161
265174
|
service: "collection",
|
|
265162
265175
|
method: "delete",
|
|
265163
|
-
path: `/v3/collections/${
|
|
265176
|
+
path: `/v3/collections/${itemsCid}/items/${itemId}`,
|
|
265164
265177
|
retry: "none",
|
|
265165
265178
|
headers: { "X-Entity-Type": String(item.$kind ?? "http-request") }
|
|
265166
265179
|
});
|
|
265167
265180
|
} catch (error2) {
|
|
265168
265181
|
if (isAmbiguousTransportError(error2)) {
|
|
265169
|
-
const stillPresent = (await this.listCollectionItems(
|
|
265182
|
+
const stillPresent = (await this.listCollectionItems(itemsCid)).some(
|
|
265170
265183
|
(candidate) => String(candidate.id ?? "").trim() === itemId
|
|
265171
265184
|
);
|
|
265172
265185
|
if (!stillPresent) continue;
|
|
@@ -265177,14 +265190,14 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
265177
265190
|
}
|
|
265178
265191
|
}
|
|
265179
265192
|
}
|
|
265180
|
-
const remainingItems = await this.listCollectionItems(
|
|
265193
|
+
const remainingItems = await this.listCollectionItems(itemsCid);
|
|
265181
265194
|
if (remainingItems.length > 0) {
|
|
265182
265195
|
throw new Error(
|
|
265183
265196
|
`Collection delete verification failed: ${remainingItems.length} old items remain`
|
|
265184
265197
|
);
|
|
265185
265198
|
}
|
|
265186
|
-
await this.createItemTree(
|
|
265187
|
-
await this.applyCollectionLevelSettings(
|
|
265199
|
+
await this.createItemTree(itemsCid, asItemArray(v3.items), itemsCid);
|
|
265200
|
+
await this.applyCollectionLevelSettings(rootCid, v3, { rename: true, reconcileRemovals: true });
|
|
265188
265201
|
}
|
|
265189
265202
|
};
|
|
265190
265203
|
|
package/dist/cli.cjs
CHANGED
|
@@ -262575,7 +262575,8 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
262575
262575
|
service: "collection",
|
|
262576
262576
|
method: "patch",
|
|
262577
262577
|
path: `/v3/collections/${this.bareModelId(collectionId)}`,
|
|
262578
|
-
|
|
262578
|
+
// Replacing a generated collection's name with the same value is idempotent.
|
|
262579
|
+
retry: "safe",
|
|
262579
262580
|
body: [{ op: "replace", path: "/name", value: name }]
|
|
262580
262581
|
});
|
|
262581
262582
|
}
|
|
@@ -262774,15 +262775,25 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
262774
262775
|
}
|
|
262775
262776
|
// --- collection v3 mutation + tagging (live-proven 2026-06-30; see docs/REST-to-gateway.md) ---
|
|
262776
262777
|
//
|
|
262777
|
-
// These retire bootstrap's last asset-op PMAK dependencies.
|
|
262778
|
-
//
|
|
262779
|
-
//
|
|
262780
|
-
//
|
|
262781
|
-
|
|
262778
|
+
// These retire bootstrap's last asset-op PMAK dependencies. Collection ROOT
|
|
262779
|
+
// routes (GET/PATCH/DELETE `/v3/collections/:id`) accept the bare model id.
|
|
262780
|
+
// Collection ITEMS routes (`/v3/collections/:id/items/...`) must use the FULL
|
|
262781
|
+
// public uid (`<owner>-<uuid>`): bare model ids are flaky on org-mode squads
|
|
262782
|
+
// (live-proven 2026-07-14 on team 172912 / Northwind — immediate post-generation
|
|
262783
|
+
// `GET .../items/` returns 403 FORBIDDEN with bare id, 200 with full uid).
|
|
262784
|
+
// The tagging service is distinct and takes the FULL uid.
|
|
262785
|
+
/** `<owner>-<uuid>` public uid -> bare `<uuid>` model id (collection ROOT routes only). */
|
|
262782
262786
|
bareModelId(uid) {
|
|
262783
262787
|
const u = String(uid ?? "").trim();
|
|
262784
262788
|
return u.includes("-") ? u.slice(u.indexOf("-") + 1) : u;
|
|
262785
262789
|
}
|
|
262790
|
+
/**
|
|
262791
|
+
* Collection id for ITEMS routes. Prefer the full public uid; fall back to the
|
|
262792
|
+
* trimmed input when the caller already has a bare/model id.
|
|
262793
|
+
*/
|
|
262794
|
+
collectionItemsId(uid) {
|
|
262795
|
+
return String(uid ?? "").trim();
|
|
262796
|
+
}
|
|
262786
262797
|
/**
|
|
262787
262798
|
* PATCH a freshly-created item's `/scripts`, tolerating the two transient
|
|
262788
262799
|
* failures this immediate-after-create write is prone to on the shared gateway:
|
|
@@ -262841,9 +262852,9 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
262841
262852
|
/**
|
|
262842
262853
|
* Inject smoke-test assertions into every leaf request of a spec-generated
|
|
262843
262854
|
* collection, over the v3 collection-items surface (no PMAK):
|
|
262844
|
-
* 1. `GET /v3/collections/:cid/items/` (
|
|
262855
|
+
* 1. `GET /v3/collections/:cid/items/` (FULL public uid, trailing slash) — flat list.
|
|
262845
262856
|
* 2. for each `http-request` leaf, `PATCH /v3/collections/:cid/items/:itemId`
|
|
262846
|
-
* (full uid for `:itemId`, `X-Entity-Type: http-request` header) with a
|
|
262857
|
+
* (full uid for `:cid` and `:itemId`, `X-Entity-Type: http-request` header) with a
|
|
262847
262858
|
* JSON-Patch that sets `/scripts` to the canonical v3 shape
|
|
262848
262859
|
* (`[{type:'afterResponse', code, language}]`). The v3 surface persists test
|
|
262849
262860
|
* scripts under `scripts`, NOT `events`: a `/events` patch returns 200 but is
|
|
@@ -262856,7 +262867,7 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
262856
262867
|
*/
|
|
262857
262868
|
async injectTests(collectionUid, type) {
|
|
262858
262869
|
void type;
|
|
262859
|
-
const cid = this.
|
|
262870
|
+
const cid = this.collectionItemsId(collectionUid);
|
|
262860
262871
|
const listed = await this.gateway.requestJson({
|
|
262861
262872
|
service: "collection",
|
|
262862
262873
|
method: "get",
|
|
@@ -263027,7 +263038,7 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
263027
263038
|
* Inject the deterministic OpenAPI contract assertions into every generated
|
|
263028
263039
|
* request of a spec-generated collection, entirely over the v3 collection
|
|
263029
263040
|
* surface (no PMAK, no v2.1.0 read/PUT):
|
|
263030
|
-
* 1. `GET /v3/collections/:cid/items/` — flat item list (
|
|
263041
|
+
* 1. `GET /v3/collections/:cid/items/` — flat item list (FULL public uid for `:cid`).
|
|
263031
263042
|
* 2. `GET /v3/collections/:cid/items/:itemId` (`X-Entity-Type: http-request`)
|
|
263032
263043
|
* — the full v3 IR record (method/url/headers/body) the matcher needs.
|
|
263033
263044
|
* 3. `planContractItemScripts` matches each request to its OpenAPI operation
|
|
@@ -263038,7 +263049,7 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
263038
263049
|
* Returns the non-fatal instrumentation warnings for the caller to surface.
|
|
263039
263050
|
*/
|
|
263040
263051
|
async injectContractTests(collectionUid, index) {
|
|
263041
|
-
const cid = this.
|
|
263052
|
+
const cid = this.collectionItemsId(collectionUid);
|
|
263042
263053
|
const listed = await this.gateway.requestJson({
|
|
263043
263054
|
service: "collection",
|
|
263044
263055
|
method: "get",
|
|
@@ -263438,11 +263449,12 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
263438
263449
|
if (!rawId) {
|
|
263439
263450
|
throw new Error("Collection create did not return an id");
|
|
263440
263451
|
}
|
|
263441
|
-
const
|
|
263452
|
+
const itemsCid = this.collectionItemsId(rawId);
|
|
263453
|
+
const rootCid = this.bareModelId(rawId);
|
|
263442
263454
|
await options.onRootCreated?.(rawId);
|
|
263443
263455
|
try {
|
|
263444
|
-
await this.createItemTree(
|
|
263445
|
-
await this.applyCollectionLevelSettings(
|
|
263456
|
+
await this.createItemTree(itemsCid, asItemArray(v3.items), itemsCid);
|
|
263457
|
+
await this.applyCollectionLevelSettings(rootCid, v3, { rename: true });
|
|
263446
263458
|
} catch (error) {
|
|
263447
263459
|
if (options.onRootCreated) throw error;
|
|
263448
263460
|
let cleanupError;
|
|
@@ -263469,22 +263481,23 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
263469
263481
|
* from the converted v3 IR and reapply name/auth/variables.
|
|
263470
263482
|
*/
|
|
263471
263483
|
async updateCollection(collectionUid, collection) {
|
|
263472
|
-
const
|
|
263484
|
+
const itemsCid = this.collectionItemsId(collectionUid);
|
|
263485
|
+
const rootCid = this.bareModelId(collectionUid);
|
|
263473
263486
|
const v3 = this.normalizeCollectionForWrite(collection);
|
|
263474
|
-
const existingItems = await this.listCollectionItems(
|
|
263487
|
+
const existingItems = await this.listCollectionItems(itemsCid);
|
|
263475
263488
|
for (const item of existingItems) {
|
|
263476
263489
|
const itemId = String(item.id).trim();
|
|
263477
263490
|
try {
|
|
263478
263491
|
await this.gateway.requestJson({
|
|
263479
263492
|
service: "collection",
|
|
263480
263493
|
method: "delete",
|
|
263481
|
-
path: `/v3/collections/${
|
|
263494
|
+
path: `/v3/collections/${itemsCid}/items/${itemId}`,
|
|
263482
263495
|
retry: "none",
|
|
263483
263496
|
headers: { "X-Entity-Type": String(item.$kind ?? "http-request") }
|
|
263484
263497
|
});
|
|
263485
263498
|
} catch (error) {
|
|
263486
263499
|
if (isAmbiguousTransportError(error)) {
|
|
263487
|
-
const stillPresent = (await this.listCollectionItems(
|
|
263500
|
+
const stillPresent = (await this.listCollectionItems(itemsCid)).some(
|
|
263488
263501
|
(candidate) => String(candidate.id ?? "").trim() === itemId
|
|
263489
263502
|
);
|
|
263490
263503
|
if (!stillPresent) continue;
|
|
@@ -263495,14 +263508,14 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
263495
263508
|
}
|
|
263496
263509
|
}
|
|
263497
263510
|
}
|
|
263498
|
-
const remainingItems = await this.listCollectionItems(
|
|
263511
|
+
const remainingItems = await this.listCollectionItems(itemsCid);
|
|
263499
263512
|
if (remainingItems.length > 0) {
|
|
263500
263513
|
throw new Error(
|
|
263501
263514
|
`Collection delete verification failed: ${remainingItems.length} old items remain`
|
|
263502
263515
|
);
|
|
263503
263516
|
}
|
|
263504
|
-
await this.createItemTree(
|
|
263505
|
-
await this.applyCollectionLevelSettings(
|
|
263517
|
+
await this.createItemTree(itemsCid, asItemArray(v3.items), itemsCid);
|
|
263518
|
+
await this.applyCollectionLevelSettings(rootCid, v3, { rename: true, reconcileRemovals: true });
|
|
263506
263519
|
}
|
|
263507
263520
|
};
|
|
263508
263521
|
|
|
@@ -311847,6 +311860,44 @@ function createBootstrapDependencies(inputs, factories, orgMode = false) {
|
|
|
311847
311860
|
}
|
|
311848
311861
|
|
|
311849
311862
|
// src/cli.ts
|
|
311863
|
+
var HELP_TEXT = `Usage: postman-bootstrap [options]
|
|
311864
|
+
|
|
311865
|
+
Bootstrap Postman workspaces, specs, and collections from OpenAPI.
|
|
311866
|
+
|
|
311867
|
+
Options:
|
|
311868
|
+
--help Show this help and exit
|
|
311869
|
+
--version Show version and exit
|
|
311870
|
+
--result-json <path> Write JSON result (default: postman-bootstrap-result.json)
|
|
311871
|
+
--dotenv-path <path> Optional dotenv output path
|
|
311872
|
+
--<input-name> <value> Action input as kebab-case flag (same names as action.yml)
|
|
311873
|
+
|
|
311874
|
+
Examples:
|
|
311875
|
+
postman-bootstrap --help
|
|
311876
|
+
postman-bootstrap --project-name demo --spec-path ./openapi.yaml ...
|
|
311877
|
+
`;
|
|
311878
|
+
function wantsHelp(argv) {
|
|
311879
|
+
return argv.includes("--help") || argv.includes("-h");
|
|
311880
|
+
}
|
|
311881
|
+
function wantsVersion(argv) {
|
|
311882
|
+
return argv.includes("--version") || argv.includes("-V");
|
|
311883
|
+
}
|
|
311884
|
+
function resolvePackageVersion() {
|
|
311885
|
+
const candidates = [];
|
|
311886
|
+
if (typeof __filename === "string" && __filename) {
|
|
311887
|
+
candidates.push(import_node_path5.default.join(import_node_path5.default.dirname(__filename), "..", "package.json"));
|
|
311888
|
+
}
|
|
311889
|
+
candidates.push(import_node_path5.default.join(process.cwd(), "package.json"));
|
|
311890
|
+
for (const packageJsonPath of candidates) {
|
|
311891
|
+
try {
|
|
311892
|
+
const packageJson = JSON.parse((0, import_node_fs6.readFileSync)(packageJsonPath, "utf8"));
|
|
311893
|
+
if (packageJson.name === "@postman-cse/onboarding-bootstrap" && packageJson.version) {
|
|
311894
|
+
return String(packageJson.version).trim();
|
|
311895
|
+
}
|
|
311896
|
+
} catch {
|
|
311897
|
+
}
|
|
311898
|
+
}
|
|
311899
|
+
return "0.0.0";
|
|
311900
|
+
}
|
|
311850
311901
|
var ConsoleReporter = class {
|
|
311851
311902
|
error(message) {
|
|
311852
311903
|
console.error(message);
|
|
@@ -312110,6 +312161,19 @@ function validateCliInputs(inputs) {
|
|
|
312110
312161
|
}
|
|
312111
312162
|
}
|
|
312112
312163
|
async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
312164
|
+
const writeStdout = runtime.writeStdout ?? ((chunk) => process.stdout.write(chunk));
|
|
312165
|
+
if (wantsHelp(argv) && wantsVersion(argv)) {
|
|
312166
|
+
throw new Error("Cannot use --help and --version together");
|
|
312167
|
+
}
|
|
312168
|
+
if (wantsHelp(argv)) {
|
|
312169
|
+
writeStdout(HELP_TEXT);
|
|
312170
|
+
return;
|
|
312171
|
+
}
|
|
312172
|
+
if (wantsVersion(argv)) {
|
|
312173
|
+
writeStdout(`${resolvePackageVersion()}
|
|
312174
|
+
`);
|
|
312175
|
+
return;
|
|
312176
|
+
}
|
|
312113
312177
|
const env = runtime.env ?? process.env;
|
|
312114
312178
|
const config = parseCliArgs(argv, env);
|
|
312115
312179
|
const inputs = resolveInputs(config.inputEnv);
|
|
@@ -312138,7 +312202,6 @@ async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
312138
312202
|
const result = await (runtime.executeBootstrap ?? runBootstrap)(inputs, dependencies);
|
|
312139
312203
|
await writeOptionalFile(config.resultJsonPath, JSON.stringify(result, null, 2));
|
|
312140
312204
|
await writeOptionalFile(config.dotenvPath, toDotenv(result));
|
|
312141
|
-
const writeStdout = runtime.writeStdout ?? ((chunk) => process.stdout.write(chunk));
|
|
312142
312205
|
writeStdout(`${JSON.stringify(result, null, 2)}
|
|
312143
312206
|
`);
|
|
312144
312207
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -264276,7 +264276,8 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264276
264276
|
service: "collection",
|
|
264277
264277
|
method: "patch",
|
|
264278
264278
|
path: `/v3/collections/${this.bareModelId(collectionId)}`,
|
|
264279
|
-
|
|
264279
|
+
// Replacing a generated collection's name with the same value is idempotent.
|
|
264280
|
+
retry: "safe",
|
|
264280
264281
|
body: [{ op: "replace", path: "/name", value: name }]
|
|
264281
264282
|
});
|
|
264282
264283
|
}
|
|
@@ -264475,15 +264476,25 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264475
264476
|
}
|
|
264476
264477
|
// --- collection v3 mutation + tagging (live-proven 2026-06-30; see docs/REST-to-gateway.md) ---
|
|
264477
264478
|
//
|
|
264478
|
-
// These retire bootstrap's last asset-op PMAK dependencies.
|
|
264479
|
-
//
|
|
264480
|
-
//
|
|
264481
|
-
//
|
|
264482
|
-
|
|
264479
|
+
// These retire bootstrap's last asset-op PMAK dependencies. Collection ROOT
|
|
264480
|
+
// routes (GET/PATCH/DELETE `/v3/collections/:id`) accept the bare model id.
|
|
264481
|
+
// Collection ITEMS routes (`/v3/collections/:id/items/...`) must use the FULL
|
|
264482
|
+
// public uid (`<owner>-<uuid>`): bare model ids are flaky on org-mode squads
|
|
264483
|
+
// (live-proven 2026-07-14 on team 172912 / Northwind — immediate post-generation
|
|
264484
|
+
// `GET .../items/` returns 403 FORBIDDEN with bare id, 200 with full uid).
|
|
264485
|
+
// The tagging service is distinct and takes the FULL uid.
|
|
264486
|
+
/** `<owner>-<uuid>` public uid -> bare `<uuid>` model id (collection ROOT routes only). */
|
|
264483
264487
|
bareModelId(uid) {
|
|
264484
264488
|
const u = String(uid ?? "").trim();
|
|
264485
264489
|
return u.includes("-") ? u.slice(u.indexOf("-") + 1) : u;
|
|
264486
264490
|
}
|
|
264491
|
+
/**
|
|
264492
|
+
* Collection id for ITEMS routes. Prefer the full public uid; fall back to the
|
|
264493
|
+
* trimmed input when the caller already has a bare/model id.
|
|
264494
|
+
*/
|
|
264495
|
+
collectionItemsId(uid) {
|
|
264496
|
+
return String(uid ?? "").trim();
|
|
264497
|
+
}
|
|
264487
264498
|
/**
|
|
264488
264499
|
* PATCH a freshly-created item's `/scripts`, tolerating the two transient
|
|
264489
264500
|
* failures this immediate-after-create write is prone to on the shared gateway:
|
|
@@ -264542,9 +264553,9 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264542
264553
|
/**
|
|
264543
264554
|
* Inject smoke-test assertions into every leaf request of a spec-generated
|
|
264544
264555
|
* collection, over the v3 collection-items surface (no PMAK):
|
|
264545
|
-
* 1. `GET /v3/collections/:cid/items/` (
|
|
264556
|
+
* 1. `GET /v3/collections/:cid/items/` (FULL public uid, trailing slash) — flat list.
|
|
264546
264557
|
* 2. for each `http-request` leaf, `PATCH /v3/collections/:cid/items/:itemId`
|
|
264547
|
-
* (full uid for `:itemId`, `X-Entity-Type: http-request` header) with a
|
|
264558
|
+
* (full uid for `:cid` and `:itemId`, `X-Entity-Type: http-request` header) with a
|
|
264548
264559
|
* JSON-Patch that sets `/scripts` to the canonical v3 shape
|
|
264549
264560
|
* (`[{type:'afterResponse', code, language}]`). The v3 surface persists test
|
|
264550
264561
|
* scripts under `scripts`, NOT `events`: a `/events` patch returns 200 but is
|
|
@@ -264557,7 +264568,7 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264557
264568
|
*/
|
|
264558
264569
|
async injectTests(collectionUid, type) {
|
|
264559
264570
|
void type;
|
|
264560
|
-
const cid = this.
|
|
264571
|
+
const cid = this.collectionItemsId(collectionUid);
|
|
264561
264572
|
const listed = await this.gateway.requestJson({
|
|
264562
264573
|
service: "collection",
|
|
264563
264574
|
method: "get",
|
|
@@ -264728,7 +264739,7 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264728
264739
|
* Inject the deterministic OpenAPI contract assertions into every generated
|
|
264729
264740
|
* request of a spec-generated collection, entirely over the v3 collection
|
|
264730
264741
|
* surface (no PMAK, no v2.1.0 read/PUT):
|
|
264731
|
-
* 1. `GET /v3/collections/:cid/items/` — flat item list (
|
|
264742
|
+
* 1. `GET /v3/collections/:cid/items/` — flat item list (FULL public uid for `:cid`).
|
|
264732
264743
|
* 2. `GET /v3/collections/:cid/items/:itemId` (`X-Entity-Type: http-request`)
|
|
264733
264744
|
* — the full v3 IR record (method/url/headers/body) the matcher needs.
|
|
264734
264745
|
* 3. `planContractItemScripts` matches each request to its OpenAPI operation
|
|
@@ -264739,7 +264750,7 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
264739
264750
|
* Returns the non-fatal instrumentation warnings for the caller to surface.
|
|
264740
264751
|
*/
|
|
264741
264752
|
async injectContractTests(collectionUid, index) {
|
|
264742
|
-
const cid = this.
|
|
264753
|
+
const cid = this.collectionItemsId(collectionUid);
|
|
264743
264754
|
const listed = await this.gateway.requestJson({
|
|
264744
264755
|
service: "collection",
|
|
264745
264756
|
method: "get",
|
|
@@ -265139,11 +265150,12 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
265139
265150
|
if (!rawId) {
|
|
265140
265151
|
throw new Error("Collection create did not return an id");
|
|
265141
265152
|
}
|
|
265142
|
-
const
|
|
265153
|
+
const itemsCid = this.collectionItemsId(rawId);
|
|
265154
|
+
const rootCid = this.bareModelId(rawId);
|
|
265143
265155
|
await options.onRootCreated?.(rawId);
|
|
265144
265156
|
try {
|
|
265145
|
-
await this.createItemTree(
|
|
265146
|
-
await this.applyCollectionLevelSettings(
|
|
265157
|
+
await this.createItemTree(itemsCid, asItemArray(v3.items), itemsCid);
|
|
265158
|
+
await this.applyCollectionLevelSettings(rootCid, v3, { rename: true });
|
|
265147
265159
|
} catch (error2) {
|
|
265148
265160
|
if (options.onRootCreated) throw error2;
|
|
265149
265161
|
let cleanupError;
|
|
@@ -265170,22 +265182,23 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
265170
265182
|
* from the converted v3 IR and reapply name/auth/variables.
|
|
265171
265183
|
*/
|
|
265172
265184
|
async updateCollection(collectionUid, collection) {
|
|
265173
|
-
const
|
|
265185
|
+
const itemsCid = this.collectionItemsId(collectionUid);
|
|
265186
|
+
const rootCid = this.bareModelId(collectionUid);
|
|
265174
265187
|
const v3 = this.normalizeCollectionForWrite(collection);
|
|
265175
|
-
const existingItems = await this.listCollectionItems(
|
|
265188
|
+
const existingItems = await this.listCollectionItems(itemsCid);
|
|
265176
265189
|
for (const item of existingItems) {
|
|
265177
265190
|
const itemId = String(item.id).trim();
|
|
265178
265191
|
try {
|
|
265179
265192
|
await this.gateway.requestJson({
|
|
265180
265193
|
service: "collection",
|
|
265181
265194
|
method: "delete",
|
|
265182
|
-
path: `/v3/collections/${
|
|
265195
|
+
path: `/v3/collections/${itemsCid}/items/${itemId}`,
|
|
265183
265196
|
retry: "none",
|
|
265184
265197
|
headers: { "X-Entity-Type": String(item.$kind ?? "http-request") }
|
|
265185
265198
|
});
|
|
265186
265199
|
} catch (error2) {
|
|
265187
265200
|
if (isAmbiguousTransportError(error2)) {
|
|
265188
|
-
const stillPresent = (await this.listCollectionItems(
|
|
265201
|
+
const stillPresent = (await this.listCollectionItems(itemsCid)).some(
|
|
265189
265202
|
(candidate) => String(candidate.id ?? "").trim() === itemId
|
|
265190
265203
|
);
|
|
265191
265204
|
if (!stillPresent) continue;
|
|
@@ -265196,14 +265209,14 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
265196
265209
|
}
|
|
265197
265210
|
}
|
|
265198
265211
|
}
|
|
265199
|
-
const remainingItems = await this.listCollectionItems(
|
|
265212
|
+
const remainingItems = await this.listCollectionItems(itemsCid);
|
|
265200
265213
|
if (remainingItems.length > 0) {
|
|
265201
265214
|
throw new Error(
|
|
265202
265215
|
`Collection delete verification failed: ${remainingItems.length} old items remain`
|
|
265203
265216
|
);
|
|
265204
265217
|
}
|
|
265205
|
-
await this.createItemTree(
|
|
265206
|
-
await this.applyCollectionLevelSettings(
|
|
265218
|
+
await this.createItemTree(itemsCid, asItemArray(v3.items), itemsCid);
|
|
265219
|
+
await this.applyCollectionLevelSettings(rootCid, v3, { rename: true, reconcileRemovals: true });
|
|
265207
265220
|
}
|
|
265208
265221
|
};
|
|
265209
265222
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postman-cse/onboarding-bootstrap",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.3",
|
|
4
4
|
"description": "Bootstrap Postman workspaces, specs, and collections from OpenAPI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -18,8 +18,10 @@
|
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
20
|
"prepare": "git config core.hooksPath .githooks",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
21
|
+
"bundle": "rm -rf dist && esbuild src/index.ts --bundle --platform=node --target=node24 --format=cjs --alias:jsonc-parser=jsonc-parser/lib/esm/main.js --outfile=dist/index.cjs && esbuild src/main.ts --bundle --platform=node --target=node24 --format=cjs --alias:jsonc-parser=jsonc-parser/lib/esm/main.js --outfile=dist/action.cjs && esbuild src/cli.ts --bundle --platform=node --target=node24 --format=cjs --alias:jsonc-parser=jsonc-parser/lib/esm/main.js --banner:js='#!/usr/bin/env node' --outfile=dist/cli.cjs && chmod 755 dist/cli.cjs",
|
|
22
|
+
"build": "npm run typecheck && npm run bundle",
|
|
23
|
+
"verify:dist:assert": "git diff --ignore-space-at-eol --text --exit-code -- dist && node scripts/verify-dist-artifact.mjs",
|
|
24
|
+
"verify:dist": "npm run build && npm run verify:dist:assert",
|
|
23
25
|
"docs:tables": "node scripts/render-action-tables.mjs",
|
|
24
26
|
"lint": "eslint .",
|
|
25
27
|
"lint:fix": "eslint . --fix",
|