@postman-cse/onboarding-bootstrap 2.1.0 → 2.1.2
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 +305 -87
- package/dist/cli.cjs +305 -87
- package/dist/index.cjs +305 -87
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -296676,9 +296676,19 @@ function collectParameterChecks(root, pathItem, operation, version2, operationId
|
|
|
296676
296676
|
if (defaultSerialization) warnings.push(`CONTRACT_SCHEMA_NOT_COMPILED: parameter ${location2}:${name} schema on ${operationId} skipped (${packed.unsupported})`);
|
|
296677
296677
|
continue;
|
|
296678
296678
|
}
|
|
296679
|
-
if (location2 === "path"
|
|
296680
|
-
|
|
296681
|
-
|
|
296679
|
+
if (location2 === "path") {
|
|
296680
|
+
const containingSegment = pathTemplate.split("/").find((segment) => segment.includes(`{${name}}`));
|
|
296681
|
+
if (containingSegment !== void 0 && containingSegment !== `{${name}}`) {
|
|
296682
|
+
const segmentParts = containingSegment.split(/(\{[^}]+\})/).filter(Boolean);
|
|
296683
|
+
let extractable = true;
|
|
296684
|
+
for (let partIndex = 0; partIndex < segmentParts.length - 1; partIndex += 1) {
|
|
296685
|
+
if (/^\{[^}]+\}$/.test(segmentParts[partIndex]) && /^\{[^}]+\}$/.test(segmentParts[partIndex + 1])) extractable = false;
|
|
296686
|
+
}
|
|
296687
|
+
if (!extractable) {
|
|
296688
|
+
warnings.push(`CONTRACT_PATH_PARAM_COMPOUND_SEGMENT_NOT_VALIDATED: path parameter ${name} of ${operationId} is in an ambiguous adjacent-parameter path segment and is not schema-validated`);
|
|
296689
|
+
continue;
|
|
296690
|
+
}
|
|
296691
|
+
}
|
|
296682
296692
|
}
|
|
296683
296693
|
const scalarSchema = packedScalarSchema(packed);
|
|
296684
296694
|
if (scalarSchema !== void 0) {
|
|
@@ -297398,7 +297408,7 @@ function createContractScript(operation, warnings = []) {
|
|
|
297398
297408
|
' function requestPathSegments() { var raw = ""; try { raw = typeof pm.request.url.getPath === "function" ? String(pm.request.url.getPath() || "") : ""; } catch (ignored) {} if (!raw) { var path = pm.request.url.path; raw = Array.isArray(path) ? "/" + path.join("/") : String(path || ""); } return raw.split("?")[0].split("#")[0].split("/").filter(function (segment) { return segment.length > 0; }); }',
|
|
297399
297409
|
// Server path prefixes sit ahead of the template segments, so the
|
|
297400
297410
|
// template aligns against the trailing request segments.
|
|
297401
|
-
' function pathParamValue(name) { var template = String(contract.path).split("/").filter(function (segment) { return segment.length > 0; }); var actual = requestPathSegments(); var offset = actual.length - template.length; if (offset < 0) return undefined; for (var i = 0; i < template.length; i += 1) {
|
|
297411
|
+
' function pathParamValue(name) { var template = String(contract.path).split("/").filter(function (segment) { return segment.length > 0; }); var actual = requestPathSegments(); var offset = actual.length - template.length; if (offset < 0) return undefined; var token = "{" + name + "}"; for (var i = 0; i < template.length; i += 1) { var seg = template[i]; var actualSeg = actual[offset + i]; if (actualSeg === undefined) continue; if (seg === token) { try { return decodeURIComponent(actualSeg); } catch (ignored) { return actualSeg; } } if (seg.indexOf(token) === -1) continue; var chunks = [], j = 0, bad = false; while (j < seg.length) { if (seg.charAt(j) === "{") { var close = seg.indexOf("}", j); if (close === -1) { bad = true; break; } chunks.push({ p: seg.slice(j + 1, close) }); j = close + 1; } else { var nb = seg.indexOf("{", j); var lit = nb === -1 ? seg.slice(j) : seg.slice(j, nb); chunks.push({ l: lit }); j = nb === -1 ? seg.length : nb; } } if (bad) return undefined; var pos = 0, found, ok = true; for (var c = 0; c < chunks.length; c += 1) { var ch = chunks[c]; if (ch.l !== undefined) { if (actualSeg.indexOf(ch.l, pos) === pos) pos += ch.l.length; else { ok = false; break; } } else { var nextLit = (chunks[c + 1] && chunks[c + 1].l !== undefined) ? chunks[c + 1].l : undefined; var isLast = c === chunks.length - 1; var end; if (isLast) { end = actualSeg.length; } else if (nextLit === undefined) { ok = false; break; } else { var idx = actualSeg.indexOf(nextLit, pos + 1); if (idx === -1) { ok = false; break; } end = idx; } if (end <= pos) { ok = false; break; } if (ch.p === name) found = actualSeg.slice(pos, end); pos = end; } } if (ok && pos === actualSeg.length && found !== undefined) { try { return decodeURIComponent(found); } catch (ignored) { return found; } } } return undefined; }',
|
|
297402
297412
|
' function isPlaceholder(value) { var text = String(value).trim(); return /^<[^<>]*>$/.test(text) || text.indexOf("{{") !== -1; }',
|
|
297403
297413
|
' function splitDelimited(value, decode) { if (decode === "csv") return value.split(","); if (decode === "ssv") return value.split(/%20| /); return value.split(/%7C|\\|/i); }',
|
|
297404
297414
|
" function decodeComponent(value) { try { return decodeURIComponent(value); } catch (ignored) { return value; } }",
|
|
@@ -297830,7 +297840,7 @@ function extractGitRepoUrl(value) {
|
|
|
297830
297840
|
}
|
|
297831
297841
|
var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
297832
297842
|
static GENERATION_LOCKED_MAX_RETRIES = 5;
|
|
297833
|
-
static GENERATION_POLL_ATTEMPTS =
|
|
297843
|
+
static GENERATION_POLL_ATTEMPTS = 90;
|
|
297834
297844
|
static GENERATION_POLL_DELAY_MS = 2e3;
|
|
297835
297845
|
gateway;
|
|
297836
297846
|
sleep;
|
|
@@ -298205,6 +298215,40 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
298205
298215
|
const u = String(uid ?? "").trim();
|
|
298206
298216
|
return u.includes("-") ? u.slice(u.indexOf("-") + 1) : u;
|
|
298207
298217
|
}
|
|
298218
|
+
/**
|
|
298219
|
+
* PATCH a freshly-created item's `/scripts`, tolerating the two transient
|
|
298220
|
+
* failures this immediate-after-create write is prone to on the shared gateway:
|
|
298221
|
+
* - `404 RESOURCE_NOT_FOUND` — the create write returns the assigned id, but
|
|
298222
|
+
* an immediate PATCH can hit a replica that has not yet observed the create
|
|
298223
|
+
* (read-after-write lag, live-observed on org-mode teams).
|
|
298224
|
+
* - a downstream `5xx` (e.g. `500 ESOCKETTIMEDOUT`) — a Bifrost/gateway read
|
|
298225
|
+
* timeout, not a durable rejection.
|
|
298226
|
+
* `op:add /scripts` is idempotent (overwrites), so retrying either is safe.
|
|
298227
|
+
* This is a deeper, longer-backoff budget than the gateway client's inner
|
|
298228
|
+
* transient retry, to wait out a longer platform hiccup on this fragile write.
|
|
298229
|
+
* Non-transient errors (e.g. 4xx schema rejections) surface immediately.
|
|
298230
|
+
*/
|
|
298231
|
+
async patchNewItemScripts(cid, itemId, scripts) {
|
|
298232
|
+
const maxAttempts = 6;
|
|
298233
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
298234
|
+
try {
|
|
298235
|
+
await this.gateway.requestJson({
|
|
298236
|
+
service: "collection",
|
|
298237
|
+
method: "patch",
|
|
298238
|
+
path: `/v3/collections/${cid}/items/${itemId}`,
|
|
298239
|
+
headers: { "X-Entity-Type": "http-request" },
|
|
298240
|
+
body: [{ op: "add", path: "/scripts", value: scripts }]
|
|
298241
|
+
});
|
|
298242
|
+
return;
|
|
298243
|
+
} catch (error) {
|
|
298244
|
+
const retriable = error instanceof HttpError && (error.status === 404 || error.status >= 500);
|
|
298245
|
+
if (!retriable || attempt === maxAttempts - 1) {
|
|
298246
|
+
throw error;
|
|
298247
|
+
}
|
|
298248
|
+
await this.sleep(Math.min(2e3, 300 * 2 ** attempt));
|
|
298249
|
+
}
|
|
298250
|
+
}
|
|
298251
|
+
}
|
|
298208
298252
|
/**
|
|
298209
298253
|
* Apply tag slugs via the dedicated `tagging` service:
|
|
298210
298254
|
* `PUT /v1/tags/collections/:uid` (full uid), body `{ tags:[{ slug }] }` — the
|
|
@@ -298322,26 +298366,14 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
298322
298366
|
});
|
|
298323
298367
|
const newItemId = String(asRecord7(created?.data)?.id ?? "").trim();
|
|
298324
298368
|
if (!newItemId) return;
|
|
298325
|
-
await this.
|
|
298326
|
-
|
|
298327
|
-
|
|
298328
|
-
|
|
298329
|
-
|
|
298330
|
-
|
|
298331
|
-
|
|
298332
|
-
|
|
298333
|
-
path: "/scripts",
|
|
298334
|
-
value: toV3Scripts([
|
|
298335
|
-
'if (pm.environment.get("CI") === "true") { return; }',
|
|
298336
|
-
"const body = pm.response.json();",
|
|
298337
|
-
"if (body.SecretString) {",
|
|
298338
|
-
" const secrets = JSON.parse(body.SecretString);",
|
|
298339
|
-
" Object.entries(secrets).forEach(([k, v]) => pm.collectionVariables.set(k, v));",
|
|
298340
|
-
"}"
|
|
298341
|
-
])
|
|
298342
|
-
}
|
|
298343
|
-
]
|
|
298344
|
-
});
|
|
298369
|
+
await this.patchNewItemScripts(cid, newItemId, toV3Scripts([
|
|
298370
|
+
'if (pm.environment.get("CI") === "true") { return; }',
|
|
298371
|
+
"const body = pm.response.json();",
|
|
298372
|
+
"if (body.SecretString) {",
|
|
298373
|
+
" const secrets = JSON.parse(body.SecretString);",
|
|
298374
|
+
" Object.entries(secrets).forEach(([k, v]) => pm.collectionVariables.set(k, v));",
|
|
298375
|
+
"}"
|
|
298376
|
+
]));
|
|
298345
298377
|
}
|
|
298346
298378
|
// --- workspace roles + member resolution (live-proven 2026-06-30) ---
|
|
298347
298379
|
//
|
|
@@ -298500,26 +298532,14 @@ var PostmanGatewayAssetsClient = class _PostmanGatewayAssetsClient {
|
|
|
298500
298532
|
});
|
|
298501
298533
|
const newItemId = String(asRecord7(created?.data)?.id ?? "").trim();
|
|
298502
298534
|
if (newItemId) {
|
|
298503
|
-
await this.
|
|
298504
|
-
|
|
298505
|
-
|
|
298506
|
-
|
|
298507
|
-
|
|
298508
|
-
|
|
298509
|
-
|
|
298510
|
-
|
|
298511
|
-
path: "/scripts",
|
|
298512
|
-
value: toV3Scripts([
|
|
298513
|
-
'if (pm.environment.get("CI") === "true") { return; }',
|
|
298514
|
-
"const body = pm.response.json();",
|
|
298515
|
-
"if (body.SecretString) {",
|
|
298516
|
-
" const secrets = JSON.parse(body.SecretString);",
|
|
298517
|
-
" Object.entries(secrets).forEach(([k, v]) => pm.collectionVariables.set(k, v));",
|
|
298518
|
-
"}"
|
|
298519
|
-
])
|
|
298520
|
-
}
|
|
298521
|
-
]
|
|
298522
|
-
});
|
|
298535
|
+
await this.patchNewItemScripts(cid, newItemId, toV3Scripts([
|
|
298536
|
+
'if (pm.environment.get("CI") === "true") { return; }',
|
|
298537
|
+
"const body = pm.response.json();",
|
|
298538
|
+
"if (body.SecretString) {",
|
|
298539
|
+
" const secrets = JSON.parse(body.SecretString);",
|
|
298540
|
+
" Object.entries(secrets).forEach(([k, v]) => pm.collectionVariables.set(k, v));",
|
|
298541
|
+
"}"
|
|
298542
|
+
]));
|
|
298523
298543
|
}
|
|
298524
298544
|
}
|
|
298525
298545
|
return plan.warnings;
|
|
@@ -299355,7 +299375,7 @@ function resolveActionVersion(explicit) {
|
|
|
299355
299375
|
if (explicit) {
|
|
299356
299376
|
return explicit;
|
|
299357
299377
|
}
|
|
299358
|
-
return "2.1.
|
|
299378
|
+
return "2.1.2" ? "2.1.2" : "unknown";
|
|
299359
299379
|
}
|
|
299360
299380
|
function telemetryDisabled(env) {
|
|
299361
299381
|
const flag = String(env.POSTMAN_ACTIONS_TELEMETRY ?? "").trim().toLowerCase();
|
|
@@ -311939,27 +311959,28 @@ function classifyNamedType(named) {
|
|
|
311939
311959
|
function describeType(type) {
|
|
311940
311960
|
let current = type;
|
|
311941
311961
|
let nonNull = false;
|
|
311942
|
-
let list = false;
|
|
311943
|
-
let listItemNonNull = false;
|
|
311944
311962
|
if ((0, import_graphql.isNonNullType)(current)) {
|
|
311945
311963
|
nonNull = true;
|
|
311946
311964
|
current = current.ofType;
|
|
311947
311965
|
}
|
|
311948
|
-
|
|
311949
|
-
|
|
311966
|
+
const lists = [];
|
|
311967
|
+
while ((0, import_graphql.isListType)(current)) {
|
|
311950
311968
|
current = current.ofType;
|
|
311969
|
+
let itemNonNull = false;
|
|
311951
311970
|
if ((0, import_graphql.isNonNullType)(current)) {
|
|
311952
|
-
|
|
311971
|
+
itemNonNull = true;
|
|
311953
311972
|
current = current.ofType;
|
|
311954
311973
|
}
|
|
311974
|
+
lists.push({ itemNonNull });
|
|
311955
311975
|
}
|
|
311956
311976
|
const named = (0, import_graphql.getNamedType)(current);
|
|
311957
311977
|
return {
|
|
311958
311978
|
name: named.name,
|
|
311959
311979
|
kind: classifyNamedType(named),
|
|
311960
311980
|
nonNull,
|
|
311961
|
-
list,
|
|
311962
|
-
listItemNonNull
|
|
311981
|
+
list: lists.length > 0,
|
|
311982
|
+
listItemNonNull: lists.length > 0 ? lists[0].itemNonNull : false,
|
|
311983
|
+
lists
|
|
311963
311984
|
};
|
|
311964
311985
|
}
|
|
311965
311986
|
function describeArgument(arg) {
|
|
@@ -311996,7 +312017,7 @@ function collectRootOperations(rootType, kind, schema, shapes) {
|
|
|
311996
312017
|
}
|
|
311997
312018
|
if (returns.kind === "union") {
|
|
311998
312019
|
opWarnings.push(
|
|
311999
|
-
`
|
|
312020
|
+
`GQL_UNION_MEMBER_FIELDS_NOT_EXPANDED: ${kind}.${fieldName} returns union ${returns.name}; its __typename is validated (object + declared member name) but member-specific fields are not expanded or asserted`
|
|
312000
312021
|
);
|
|
312001
312022
|
}
|
|
312002
312023
|
if (returns.kind === "unknown") {
|
|
@@ -312060,9 +312081,12 @@ function parseGraphQLSchema(content, opts = {}) {
|
|
|
312060
312081
|
}
|
|
312061
312082
|
for (const operation of operations) warnings.push(...operation.warnings);
|
|
312062
312083
|
const enumValues = {};
|
|
312084
|
+
const unionMembers = {};
|
|
312063
312085
|
for (const namedType of Object.values(schema.getTypeMap())) {
|
|
312064
312086
|
if ((0, import_graphql.isEnumType)(namedType)) {
|
|
312065
312087
|
enumValues[namedType.name] = namedType.getValues().map((value) => value.name);
|
|
312088
|
+
} else if ((0, import_graphql.isUnionType)(namedType)) {
|
|
312089
|
+
unionMembers[namedType.name] = namedType.getTypes().map((member) => member.name).sort((x, y) => x.localeCompare(y));
|
|
312066
312090
|
}
|
|
312067
312091
|
}
|
|
312068
312092
|
return {
|
|
@@ -312070,6 +312094,7 @@ function parseGraphQLSchema(content, opts = {}) {
|
|
|
312070
312094
|
operations,
|
|
312071
312095
|
objectShapes,
|
|
312072
312096
|
enumValues,
|
|
312097
|
+
unionMembers,
|
|
312073
312098
|
warnings
|
|
312074
312099
|
};
|
|
312075
312100
|
}
|
|
@@ -312077,6 +312102,7 @@ function parseGraphQLSchema(content, opts = {}) {
|
|
|
312077
312102
|
// src/lib/protocols/graphql/selection.ts
|
|
312078
312103
|
var SELECTION_DEPTH = 1;
|
|
312079
312104
|
function selectFields(typeRef, index, depth) {
|
|
312105
|
+
if (typeRef.kind === "union") return [];
|
|
312080
312106
|
if (typeRef.kind !== "object" && typeRef.kind !== "interface") return null;
|
|
312081
312107
|
const shape = index.objectShapes[typeRef.name];
|
|
312082
312108
|
if (!shape) return [];
|
|
@@ -312110,8 +312136,8 @@ var DEFAULT_URL = "{{baseUrl}}/graphql";
|
|
|
312110
312136
|
function argTypeSdl(arg) {
|
|
312111
312137
|
const ref = arg.type;
|
|
312112
312138
|
let inner = ref.name;
|
|
312113
|
-
|
|
312114
|
-
inner = ref.
|
|
312139
|
+
for (let i = ref.lists.length - 1; i >= 0; i -= 1) {
|
|
312140
|
+
inner = ref.lists[i].itemNonNull ? `[${inner}!]` : `[${inner}]`;
|
|
312115
312141
|
}
|
|
312116
312142
|
return ref.nonNull ? `${inner}!` : inner;
|
|
312117
312143
|
}
|
|
@@ -312280,12 +312306,25 @@ function buildShapeAssertions(operation, index, warnings) {
|
|
|
312280
312306
|
return emitValueAssertions("value", operation.returns, selection, operation.id, index, warnings);
|
|
312281
312307
|
}
|
|
312282
312308
|
function emitValueAssertions(accessor, ref, selection, ctx, index, warnings) {
|
|
312283
|
-
if (ref.
|
|
312284
|
-
const
|
|
312285
|
-
const
|
|
312309
|
+
if (ref.lists.length > 0) {
|
|
312310
|
+
const [outer, ...rest] = ref.lists;
|
|
312311
|
+
const innerRef = {
|
|
312312
|
+
...ref,
|
|
312313
|
+
lists: rest,
|
|
312314
|
+
list: rest.length > 0,
|
|
312315
|
+
listItemNonNull: rest.length > 0 ? rest[0].itemNonNull : false
|
|
312316
|
+
};
|
|
312317
|
+
const elementLines = emitValueAssertions("__el", innerRef, selection, `${ctx} (list element)`, index, warnings);
|
|
312286
312318
|
const lines = [`pm.expect(${accessor}, ${JSON.stringify(`${ctx}: expected a list`)}).to.be.an("array");`];
|
|
312287
|
-
|
|
312288
|
-
|
|
312319
|
+
const body = [];
|
|
312320
|
+
if (outer.itemNonNull) {
|
|
312321
|
+
body.push(`pm.expect(__el, ${JSON.stringify(`${ctx} (list element): a non-null list item ([T!]) was null`)}).to.not.be.null;`);
|
|
312322
|
+
body.push(...elementLines);
|
|
312323
|
+
} else if (elementLines.length > 0) {
|
|
312324
|
+
body.push("if (__el === null || __el === undefined) return;", ...elementLines);
|
|
312325
|
+
}
|
|
312326
|
+
if (body.length > 0) {
|
|
312327
|
+
lines.push(`${accessor}.forEach(function (__el) {`, ...body.map((line) => ` ${line}`), "});");
|
|
312289
312328
|
}
|
|
312290
312329
|
return lines;
|
|
312291
312330
|
}
|
|
@@ -312303,8 +312342,22 @@ function emitValueAssertions(accessor, ref, selection, ctx, index, warnings) {
|
|
|
312303
312342
|
return lines;
|
|
312304
312343
|
}
|
|
312305
312344
|
if (ref.kind === "union") {
|
|
312306
|
-
|
|
312307
|
-
|
|
312345
|
+
const members = index.unionMembers[ref.name];
|
|
312346
|
+
const objMsg = JSON.stringify(ctx + ": expected union " + ref.name + " value as an object");
|
|
312347
|
+
const presentMsg = JSON.stringify(ctx + ": union " + ref.name + " value must carry __typename");
|
|
312348
|
+
const stringMsg = JSON.stringify(ctx + ": union " + ref.name + " __typename must be a string");
|
|
312349
|
+
const lines = [
|
|
312350
|
+
"pm.expect(" + accessor + ", " + objMsg + ').to.be.an("object");',
|
|
312351
|
+
"pm.expect(" + accessor + ", " + presentMsg + ').to.have.property("__typename");',
|
|
312352
|
+
"pm.expect(" + accessor + " && " + accessor + ".__typename, " + stringMsg + ').to.be.a("string");'
|
|
312353
|
+
];
|
|
312354
|
+
if (members && members.length > 0) {
|
|
312355
|
+
const memberMsg = JSON.stringify(ctx + ": __typename is not a declared member of union " + ref.name);
|
|
312356
|
+
lines.push("pm.expect(" + accessor + " && " + accessor + ".__typename, " + memberMsg + ").to.be.oneOf(" + JSON.stringify(members) + ");");
|
|
312357
|
+
} else {
|
|
312358
|
+
warnings.push("GQL_UNION_MEMBERS_UNKNOWN: " + ctx + " union " + ref.name + " member set was not resolved; only object + string __typename is asserted");
|
|
312359
|
+
}
|
|
312360
|
+
return lines;
|
|
312308
312361
|
}
|
|
312309
312362
|
warnings.push(`GQL_UNKNOWN_RETURN_TYPE: ${ctx} return type ${ref.name} could not be classified; only presence is asserted`);
|
|
312310
312363
|
return [];
|
|
@@ -312315,6 +312368,7 @@ function emitFieldAssertions(objectAccessor, parentTypeName, field, ctx, index,
|
|
|
312315
312368
|
const lines = [];
|
|
312316
312369
|
if (field.type.nonNull) {
|
|
312317
312370
|
lines.push(`pm.expect(${objectAccessor}, ${JSON.stringify(`${parentTypeName} is missing non-null field '${field.name}'`)}).to.have.property(${propName});`);
|
|
312371
|
+
lines.push(`pm.expect(${prop}, ${JSON.stringify(`${parentTypeName}.${field.name} is declared non-null but was null`)}).to.not.be.null;`);
|
|
312318
312372
|
}
|
|
312319
312373
|
const valueLines = emitValueAssertions(prop, field.type, field.selection, `${ctx}.${field.name}`, index, warnings);
|
|
312320
312374
|
if (valueLines.length > 0) {
|
|
@@ -312420,19 +312474,25 @@ function asArray6(value) {
|
|
|
312420
312474
|
}
|
|
312421
312475
|
var SCALAR_JSON_TYPE = {
|
|
312422
312476
|
double: { jsonType: "double" },
|
|
312423
|
-
float
|
|
312424
|
-
|
|
312425
|
-
|
|
312426
|
-
|
|
312427
|
-
|
|
312428
|
-
|
|
312429
|
-
|
|
312430
|
-
|
|
312431
|
-
|
|
312432
|
-
|
|
312433
|
-
|
|
312434
|
-
|
|
312435
|
-
|
|
312477
|
+
// proto float is float32; carry a format so the runtime enforces float32 range
|
|
312478
|
+
// (a finite double like 3.5e38 overflows float32 and must fail).
|
|
312479
|
+
float: { jsonType: "double", jsonFormat: "proto-float32" },
|
|
312480
|
+
// 32-bit integers JSON-encode as numbers; `intType` carries the exact protobuf
|
|
312481
|
+
// integer domain so the runtime range/sign-checks it (not just integrality).
|
|
312482
|
+
int32: { jsonType: "number", intType: "int32" },
|
|
312483
|
+
sint32: { jsonType: "number", intType: "sint32" },
|
|
312484
|
+
sfixed32: { jsonType: "number", intType: "sfixed32" },
|
|
312485
|
+
fixed32: { jsonType: "number", intType: "fixed32" },
|
|
312486
|
+
uint32: { jsonType: "number", intType: "uint32" },
|
|
312487
|
+
// 64-bit integers are JSON-encoded as strings by the proto JSON mapping and by
|
|
312488
|
+
// protobufjs default toObject; `intType` carries the exact domain so the runtime
|
|
312489
|
+
// lexically validates and RANGE-checks the string (string comparison avoids JS
|
|
312490
|
+
// double precision loss beyond 2^53).
|
|
312491
|
+
int64: { jsonType: "string", intType: "int64" },
|
|
312492
|
+
uint64: { jsonType: "string", intType: "uint64" },
|
|
312493
|
+
sint64: { jsonType: "string", intType: "sint64" },
|
|
312494
|
+
fixed64: { jsonType: "string", intType: "fixed64" },
|
|
312495
|
+
sfixed64: { jsonType: "string", intType: "sfixed64" },
|
|
312436
312496
|
bool: { jsonType: "boolean" },
|
|
312437
312497
|
string: { jsonType: "string" },
|
|
312438
312498
|
// bytes are base64 strings in proto JSON.
|
|
@@ -312443,11 +312503,11 @@ var WELL_KNOWN_JSON_TYPE = {
|
|
|
312443
312503
|
"google.protobuf.Duration": { jsonType: "string", jsonFormat: "proto-duration" },
|
|
312444
312504
|
"google.protobuf.FieldMask": { jsonType: "string", jsonFormat: "proto-field-mask" },
|
|
312445
312505
|
"google.protobuf.DoubleValue": { jsonType: "double", nullable: true },
|
|
312446
|
-
"google.protobuf.FloatValue": { jsonType: "double", nullable: true },
|
|
312447
|
-
"google.protobuf.Int32Value": { jsonType: "number", nullable: true },
|
|
312448
|
-
"google.protobuf.UInt32Value": { jsonType: "number", nullable: true },
|
|
312449
|
-
"google.protobuf.Int64Value": { jsonType: "string", nullable: true },
|
|
312450
|
-
"google.protobuf.UInt64Value": { jsonType: "string", nullable: true },
|
|
312506
|
+
"google.protobuf.FloatValue": { jsonType: "double", jsonFormat: "proto-float32", nullable: true },
|
|
312507
|
+
"google.protobuf.Int32Value": { jsonType: "number", intType: "int32", nullable: true },
|
|
312508
|
+
"google.protobuf.UInt32Value": { jsonType: "number", intType: "uint32", nullable: true },
|
|
312509
|
+
"google.protobuf.Int64Value": { jsonType: "string", intType: "int64", nullable: true },
|
|
312510
|
+
"google.protobuf.UInt64Value": { jsonType: "string", intType: "uint64", nullable: true },
|
|
312451
312511
|
"google.protobuf.BoolValue": { jsonType: "boolean", nullable: true },
|
|
312452
312512
|
"google.protobuf.StringValue": { jsonType: "string", nullable: true },
|
|
312453
312513
|
"google.protobuf.BytesValue": { jsonType: "string", jsonFormat: "proto-bytes", nullable: true },
|
|
@@ -312494,7 +312554,7 @@ function stripLeadingDot(name) {
|
|
|
312494
312554
|
}
|
|
312495
312555
|
function classifyValueType(protoType, resolved) {
|
|
312496
312556
|
const wkt = WELL_KNOWN_JSON_TYPE[stripLeadingDot(protoType)];
|
|
312497
|
-
if (wkt) return { jsonType: wkt.jsonType, jsonFormat: wkt.jsonFormat, nullable: wkt.nullable };
|
|
312557
|
+
if (wkt) return { jsonType: wkt.jsonType, jsonFormat: wkt.jsonFormat, nullable: wkt.nullable, intType: wkt.intType };
|
|
312498
312558
|
if (resolved && Array.isArray(resolved.fieldsArray)) {
|
|
312499
312559
|
return { jsonType: "object", messageType: stripLeadingDot(resolved.fullName) };
|
|
312500
312560
|
}
|
|
@@ -312502,9 +312562,14 @@ function classifyValueType(protoType, resolved) {
|
|
|
312502
312562
|
return { jsonType: "enum", enumType: stripLeadingDot(resolved.fullName) };
|
|
312503
312563
|
}
|
|
312504
312564
|
const scalar = SCALAR_JSON_TYPE[protoType];
|
|
312505
|
-
if (scalar) return { jsonType: scalar.jsonType, jsonFormat: scalar.jsonFormat };
|
|
312565
|
+
if (scalar) return { jsonType: scalar.jsonType, jsonFormat: scalar.jsonFormat, intType: scalar.intType };
|
|
312506
312566
|
return { jsonType: "unknown" };
|
|
312507
312567
|
}
|
|
312568
|
+
function classifyMapKey(keyType) {
|
|
312569
|
+
if (keyType === "bool") return "boolean";
|
|
312570
|
+
if (keyType && /^(?:u?int|sint|s?fixed)(?:32|64)$/.test(keyType)) return keyType;
|
|
312571
|
+
return void 0;
|
|
312572
|
+
}
|
|
312508
312573
|
function toLowerCamelCase(name) {
|
|
312509
312574
|
return name.replace(/_+([a-zA-Z0-9])/g, (_match, char) => char.toUpperCase()).replace(/_+$/g, "");
|
|
312510
312575
|
}
|
|
@@ -312533,6 +312598,7 @@ function fieldDescriptor(field, warnings, context) {
|
|
|
312533
312598
|
if (value.jsonType === "unknown") {
|
|
312534
312599
|
warnings.push(`PROTO_FIELD_TYPE_UNRESOLVED: map field ${context}.${field.name} has value type ${protoType} that could not be resolved; map values are not asserted`);
|
|
312535
312600
|
}
|
|
312601
|
+
const mapKeyType = classifyMapKey(field.keyType);
|
|
312536
312602
|
return {
|
|
312537
312603
|
name: String(field.name),
|
|
312538
312604
|
jsonName: protoJsonName(field),
|
|
@@ -312542,8 +312608,10 @@ function fieldDescriptor(field, warnings, context) {
|
|
|
312542
312608
|
map: true,
|
|
312543
312609
|
optional: Boolean(field.optional),
|
|
312544
312610
|
required: Boolean(field.required),
|
|
312611
|
+
...mapKeyType ? { mapKeyType } : {},
|
|
312545
312612
|
...value.jsonType !== "unknown" ? { mapValueType: value.jsonType } : {},
|
|
312546
312613
|
...value.jsonFormat ? { mapValueFormat: value.jsonFormat } : {},
|
|
312614
|
+
...value.intType ? { mapValueIntType: value.intType } : {},
|
|
312547
312615
|
...value.enumType ? { mapValueEnumType: value.enumType } : {},
|
|
312548
312616
|
...value.messageType ? { mapValueMessageType: value.messageType } : {}
|
|
312549
312617
|
};
|
|
@@ -312563,6 +312631,7 @@ function fieldDescriptor(field, warnings, context) {
|
|
|
312563
312631
|
optional: Boolean(field.optional),
|
|
312564
312632
|
required: Boolean(field.required),
|
|
312565
312633
|
...classified.nullable ? { nullable: true } : {},
|
|
312634
|
+
...classified.intType ? { intType: classified.intType } : {},
|
|
312566
312635
|
...classified.messageType ? { messageType: classified.messageType } : {},
|
|
312567
312636
|
...classified.enumType ? { enumType: classified.enumType } : {}
|
|
312568
312637
|
};
|
|
@@ -312798,13 +312867,16 @@ function buildShape(messageFullName, index, warnings, operationId, label, depth,
|
|
|
312798
312867
|
jsonName: field.jsonName,
|
|
312799
312868
|
jsonType: field.jsonType,
|
|
312800
312869
|
...field.jsonFormat ? { jsonFormat: field.jsonFormat } : {},
|
|
312870
|
+
...field.intType ? { intType: field.intType } : {},
|
|
312801
312871
|
repeated: field.repeated,
|
|
312802
312872
|
map: field.map,
|
|
312803
312873
|
required: field.required,
|
|
312804
312874
|
...field.nullable ? { nullable: true } : {},
|
|
312805
312875
|
...enumValues ? { enumValues } : {},
|
|
312876
|
+
...field.mapKeyType ? { mapKeyType: field.mapKeyType } : {},
|
|
312806
312877
|
...field.mapValueType ? { mapValueType: field.mapValueType } : {},
|
|
312807
312878
|
...field.mapValueFormat ? { mapValueFormat: field.mapValueFormat } : {},
|
|
312879
|
+
...field.mapValueIntType ? { mapValueIntType: field.mapValueIntType } : {},
|
|
312808
312880
|
...mapValueEnumValues ? { mapValueEnumValues } : {}
|
|
312809
312881
|
};
|
|
312810
312882
|
if (field.messageType && field.jsonType === "object" && !field.map) {
|
|
@@ -312871,18 +312943,38 @@ function createGrpcScript(spec) {
|
|
|
312871
312943
|
' if (expected === "any") return true;',
|
|
312872
312944
|
" return true;",
|
|
312873
312945
|
"}",
|
|
312946
|
+
'var GRPC_INT_SPECS = { int32:{s:true,b:32,min:"-2147483648",max:"2147483647"}, sint32:{s:true,b:32,min:"-2147483648",max:"2147483647"}, sfixed32:{s:true,b:32,min:"-2147483648",max:"2147483647"}, uint32:{s:false,b:32,min:"0",max:"4294967295"}, fixed32:{s:false,b:32,min:"0",max:"4294967295"}, int64:{s:true,b:64,min:"-9223372036854775808",max:"9223372036854775807"}, sint64:{s:true,b:64,min:"-9223372036854775808",max:"9223372036854775807"}, sfixed64:{s:true,b:64,min:"-9223372036854775808",max:"9223372036854775807"}, uint64:{s:false,b:64,min:"0",max:"18446744073709551615"}, fixed64:{s:false,b:64,min:"0",max:"18446744073709551615"} };',
|
|
312947
|
+
'function grpcDecStr(n) { var s = String(n); return (s.indexOf("e") === -1 && s.indexOf("E") === -1 && s.indexOf(".") === -1) ? s : null; }',
|
|
312948
|
+
'function grpcCmpIntStr(a, b) { var na = a.charAt(0) === "-", nb = b.charAt(0) === "-"; if (na !== nb) return na ? -1 : 1; var aa = (na ? a.slice(1) : a).replace(/^0+(?=[0-9])/, ""); var bb = (nb ? b.slice(1) : b).replace(/^0+(?=[0-9])/, ""); var mag; if (aa.length !== bb.length) mag = aa.length < bb.length ? -1 : 1; else mag = aa < bb ? -1 : (aa > bb ? 1 : 0); return na ? -mag : mag; }',
|
|
312949
|
+
'function grpcNormIntStr(s) { var neg = false; if (s.charAt(0) === "-") { neg = true; s = s.slice(1); } else if (s.charAt(0) === "+") { s = s.slice(1); } var ei = s.indexOf("e"); if (ei === -1) ei = s.indexOf("E"); var exp = 0; if (ei !== -1) { exp = parseInt(s.slice(ei + 1), 10); s = s.slice(0, ei); } var dot = s.indexOf("."); var intp = dot === -1 ? s : s.slice(0, dot); var frac = dot === -1 ? "" : s.slice(dot + 1); var digits = intp + frac; if (digits.length === 0) return null; if (/^0+$/.test(digits)) return "0"; if (exp >= 0) { var intpSize = intp === "0" ? 0 : intp.length; if (intpSize + exp > 20) return null; } var netExp = exp - frac.length; var out; if (netExp >= 0) { if (digits.length + netExp > 40) return null; out = digits; for (var z = 0; z < netExp; z++) out += "0"; } else { var cut = -netExp; var keepLen = digits.length - cut; var dropped = keepLen <= 0 ? digits : digits.slice(keepLen); for (var d = 0; d < dropped.length; d++) { if (dropped.charAt(d) !== "0") return null; } out = keepLen <= 0 ? "0" : digits.slice(0, keepLen); } var st = 0; while (st < out.length - 1 && out.charAt(st) === "0") st++; out = out.slice(st); if (out === "0") return "0"; if (out.length > 40) return null; return neg ? "-" + out : out; }',
|
|
312950
|
+
"function matchesInt(intType, value) {",
|
|
312951
|
+
" var spec = GRPC_INT_SPECS[intType]; if (!spec) return true;",
|
|
312952
|
+
" var num, canonical;",
|
|
312953
|
+
' if (typeof value === "number") { if (!Number.isFinite(value) || !Number.isInteger(value)) return false; num = value; canonical = grpcDecStr(value); }',
|
|
312954
|
+
' else if (typeof value === "string") { if (!/^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?$/.test(value)) return false; canonical = grpcNormIntStr(value); if (canonical === null) return false; num = Number(value); }',
|
|
312955
|
+
" else { return false; }",
|
|
312956
|
+
' if (canonical === "-0") canonical = "0";',
|
|
312957
|
+
' if (!spec.s && ((canonical !== null && canonical.charAt(0) === "-") || num < 0)) return false;',
|
|
312958
|
+
" if (spec.b === 32) return num >= Number(spec.min) && num <= Number(spec.max);",
|
|
312959
|
+
" if (canonical !== null) return grpcCmpIntStr(canonical, spec.min) >= 0 && grpcCmpIntStr(canonical, spec.max) <= 0;",
|
|
312960
|
+
" return false;",
|
|
312961
|
+
"}",
|
|
312962
|
+
'function matchesIntKey(intType, key) { var spec = GRPC_INT_SPECS[intType]; if (!spec) return true; if (!(spec.s ? /^[+-]?[0-9]+$/ : /^[0-9]+$/).test(key)) return false; var neg = key.charAt(0) === "-"; var body = (key.charAt(0) === "+" || key.charAt(0) === "-") ? key.slice(1) : key; if (body.length === 0) return false; var canon = neg ? "-" + body : body; return grpcCmpIntStr(canon, spec.min) >= 0 && grpcCmpIntStr(canon, spec.max) <= 0; }',
|
|
312963
|
+
"function matchesEnumNumber(n) { return Number.isInteger(n) && n >= -2147483648 && n <= 2147483647; }",
|
|
312874
312964
|
"function daysFromCivil(y, m, d) { y -= m <= 2 ? 1 : 0; var era = Math.floor(y / 400); var yoe = y - era * 400; var mp = m + (m > 2 ? -3 : 9); var doy = Math.floor((153 * mp + 2) / 5) + d - 1; var doe = yoe * 365 + Math.floor(yoe / 4) - Math.floor(yoe / 100) + doy; return era * 146097 + doe - 719468; }",
|
|
312875
312965
|
"function validDate(y, m, d) { if (y < 1 || y > 9999 || m < 1 || m > 12 || d < 1) return false; var mdays = [31, ((y % 4 === 0 && y % 100 !== 0) || y % 400 === 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; return d <= mdays[m - 1]; }",
|
|
312876
312966
|
'function validProtoTimestamp(value) { if (typeof value !== "string") return false; var m = value.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:\\.([0-9]{1,9}))?(Z|[+-][0-9]{2}:[0-9]{2})$/); if (!m) return false; var y = Number(m[1]), mo = Number(m[2]), d = Number(m[3]), h = Number(m[4]), mi = Number(m[5]), s = Number(m[6]); if (!validDate(y, mo, d) || h > 23 || mi > 59 || s > 59) return false; var off = 0; if (m[8] !== "Z") { var sign = m[8][0] === "-" ? -1 : 1; var oh = Number(m[8].slice(1, 3)), om = Number(m[8].slice(4, 6)); if (oh > 23 || om > 59) return false; off = sign * (oh * 3600 + om * 60); } var sec = daysFromCivil(y, mo, d) * 86400 + h * 3600 + mi * 60 + s - off; return sec >= -62135596800 && sec <= 253402300799; }',
|
|
312877
312967
|
'function validProtoDuration(value) { if (typeof value !== "string") return false; var m = value.match(/^[+-]?(?:(0|[1-9][0-9]*)(?:\\.[0-9]{0,9})?|\\.[0-9]{0,9})s$/); if (!m) return false; return !m[1] || Number(m[1]) <= 315576000000; }',
|
|
312878
312968
|
'function validProtoFieldMask(value) { if (typeof value !== "string") return false; if (value === "") return true; var paths = value.split(","); for (var i = 0; i < paths.length; i++) { if (!/^[a-z][A-Za-z0-9]*(\\.[a-z][A-Za-z0-9]*)*$/.test(paths[i])) return false; } return true; }',
|
|
312879
312969
|
'function validProtoBytes(value) { if (typeof value !== "string") return false; if (!/^(?:[A-Za-z0-9+/]*|[A-Za-z0-9_-]*)={0,2}$/.test(value)) return false; var firstPad = value.indexOf("="); if (firstPad !== -1 && firstPad < value.length - (value.endsWith("==") ? 2 : 1)) return false; var pad = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0; var raw = value.length - pad; if (raw % 4 === 1) return false; return pad === 0 || (raw + pad) % 4 === 0 && pad === (4 - raw % 4) % 4; }',
|
|
312970
|
+
'function validProtoFloat32(value) { if (value === "NaN" || value === "Infinity" || value === "-Infinity") return true; var n = typeof value === "number" ? value : Number(value); if (!Number.isFinite(n)) return false; return Number.isFinite(Math.fround(n)); }',
|
|
312880
312971
|
"function matchesFormat(format, value) {",
|
|
312881
312972
|
" if (!format) return true;",
|
|
312882
312973
|
' if (format === "proto-timestamp") return validProtoTimestamp(value);',
|
|
312883
312974
|
' if (format === "proto-duration") return validProtoDuration(value);',
|
|
312884
312975
|
' if (format === "proto-field-mask") return validProtoFieldMask(value);',
|
|
312885
312976
|
' if (format === "proto-bytes") return validProtoBytes(value);',
|
|
312977
|
+
' if (format === "proto-float32") return validProtoFloat32(value);',
|
|
312886
312978
|
" return true;",
|
|
312887
312979
|
"}",
|
|
312888
312980
|
"function formatLabel(format) {",
|
|
@@ -312890,6 +312982,7 @@ function createGrpcScript(spec) {
|
|
|
312890
312982
|
' if (format === "proto-duration") return "a valid ProtoJSON Duration";',
|
|
312891
312983
|
' if (format === "proto-field-mask") return "a valid ProtoJSON FieldMask";',
|
|
312892
312984
|
' if (format === "proto-bytes") return "valid ProtoJSON base64 bytes";',
|
|
312985
|
+
' if (format === "proto-float32") return "a float32-representable number";',
|
|
312893
312986
|
' return format || "valid ProtoJSON";',
|
|
312894
312987
|
"}",
|
|
312895
312988
|
// Recursive shape checker: validates fields (with nested message descent,
|
|
@@ -312903,14 +312996,15 @@ function createGrpcScript(spec) {
|
|
|
312903
312996
|
' if (field.required && !present) { pm.expect.fail("gRPC response is missing required field " + label); return; }',
|
|
312904
312997
|
" if (!present) return;",
|
|
312905
312998
|
" var value = obj[key];",
|
|
312906
|
-
" if (
|
|
312999
|
+
" if (value === null) return;",
|
|
312907
313000
|
" if (field.repeated) {",
|
|
312908
313001
|
' if (!matchesScalar("array", value)) { pm.expect.fail("gRPC field " + label + " must be a repeated (array) value but was " + jsonTypeOf(value)); return; }',
|
|
312909
313002
|
" for (var i = 0; i < value.length; i++) {",
|
|
312910
313003
|
' var elem = value[i]; var elemLabel = label + "[" + i + "]";',
|
|
312911
313004
|
' if (field.shape) { if (!matchesScalar("object", elem)) { pm.expect.fail("gRPC repeated field " + elemLabel + " must be an object but was " + jsonTypeOf(elem)); } else { grpcCheckShape(elem, field.shape, elemLabel + "."); } continue; }',
|
|
312912
|
-
' if (field.enumValues && field.enumValues.length > 0) { if (typeof elem === "number") { if (!
|
|
313005
|
+
' if (field.enumValues && field.enumValues.length > 0) { if (typeof elem === "number") { if (!matchesEnumNumber(elem)) pm.expect.fail("gRPC repeated enum field " + elemLabel + " must be an int32-range integer but was " + elem); continue; } if (typeof elem !== "string") { pm.expect.fail("gRPC repeated enum field " + elemLabel + " must be a string or number but was " + jsonTypeOf(elem)); } else if (field.enumValues.indexOf(elem) === -1) { pm.expect.fail("gRPC repeated enum field " + elemLabel + " has value " + elem + " not in [" + field.enumValues.join(", ") + "]"); } continue; }',
|
|
312913
313006
|
' if (field.jsonType === "any") continue;',
|
|
313007
|
+
' if (field.intType) { if (!matchesInt(field.intType, elem)) pm.expect.fail("gRPC repeated field " + elemLabel + " must be a valid " + field.intType + " (in range) but was " + JSON.stringify(elem)); continue; }',
|
|
312914
313008
|
' if (!matchesScalar(field.jsonType, elem)) pm.expect.fail("gRPC repeated field " + elemLabel + " must be " + field.jsonType + " but was " + jsonTypeOf(elem));',
|
|
312915
313009
|
' else if (!matchesFormat(field.jsonFormat, elem)) pm.expect.fail("gRPC repeated field " + elemLabel + " must be " + formatLabel(field.jsonFormat));',
|
|
312916
313010
|
" }",
|
|
@@ -312918,17 +313012,28 @@ function createGrpcScript(spec) {
|
|
|
312918
313012
|
" }",
|
|
312919
313013
|
" if (field.map) {",
|
|
312920
313014
|
' if (!matchesScalar("object", value)) { pm.expect.fail("gRPC map field " + label + " must be an object but was " + jsonTypeOf(value)); return; }',
|
|
312921
|
-
|
|
313015
|
+
" var keys = Object.keys(value);",
|
|
313016
|
+
" for (var k = 0; k < keys.length; k++) {",
|
|
313017
|
+
' var mk = keys[k], mv = value[mk], mvLabel = label + "[" + mk + "]";',
|
|
313018
|
+
' if (field.mapKeyType === "boolean") { if (mk !== "true" && mk !== "false") pm.expect.fail("gRPC map key " + mvLabel + " must be the string true or false but was " + mk); }',
|
|
313019
|
+
' else if (field.mapKeyType) { if (!matchesIntKey(field.mapKeyType, mk)) pm.expect.fail("gRPC map key " + mvLabel + " must be a valid " + field.mapKeyType + " string (in range) but was " + mk); }',
|
|
313020
|
+
' if (field.mapValueShape && matchesScalar("object", mv)) { grpcCheckShape(mv, field.mapValueShape, mvLabel + "."); }',
|
|
313021
|
+
' else if (field.mapValueIntType) { if (!matchesInt(field.mapValueIntType, mv)) pm.expect.fail("gRPC map value " + mvLabel + " must be a valid " + field.mapValueIntType + " (in range) but was " + JSON.stringify(mv)); }',
|
|
313022
|
+
' else if (field.mapValueEnumValues && field.mapValueEnumValues.length > 0) { if (typeof mv === "number") { if (!matchesEnumNumber(mv)) pm.expect.fail("gRPC map enum value " + mvLabel + " must be an int32-range integer but was " + mv); } else if (typeof mv !== "string") { pm.expect.fail("gRPC map enum value " + mvLabel + " must be a string or number but was " + jsonTypeOf(mv)); } else if (field.mapValueEnumValues.indexOf(mv) === -1) { pm.expect.fail("gRPC map enum value " + mvLabel + " has value " + mv + " not in [" + field.mapValueEnumValues.join(", ") + "]"); } }',
|
|
313023
|
+
' else if (field.mapValueType && !matchesScalar(field.mapValueType, mv)) { pm.expect.fail("gRPC map value " + mvLabel + " must be " + field.mapValueType + " but was " + jsonTypeOf(mv)); }',
|
|
313024
|
+
' else if (field.mapValueType && !matchesFormat(field.mapValueFormat, mv)) { pm.expect.fail("gRPC map value " + mvLabel + " must be " + formatLabel(field.mapValueFormat)); }',
|
|
313025
|
+
" }",
|
|
312922
313026
|
" return;",
|
|
312923
313027
|
" }",
|
|
312924
313028
|
" if (field.enumValues && field.enumValues.length > 0) {",
|
|
312925
|
-
' if (typeof value === "number") { if (!
|
|
313029
|
+
' if (typeof value === "number") { if (!matchesEnumNumber(value)) pm.expect.fail("gRPC enum field " + label + " must be an int32-range integer but was " + value); return; }',
|
|
312926
313030
|
' if (typeof value !== "string") { pm.expect.fail("gRPC enum field " + label + " must be a string or number but was " + jsonTypeOf(value)); return; }',
|
|
312927
313031
|
' if (field.enumValues.indexOf(value) === -1) pm.expect.fail("gRPC enum field " + label + " has value " + value + " not in [" + field.enumValues.join(", ") + "]");',
|
|
312928
313032
|
" return;",
|
|
312929
313033
|
" }",
|
|
312930
313034
|
' if (field.jsonType === "any") return;',
|
|
312931
313035
|
' if (field.shape) { if (!matchesScalar("object", value)) { pm.expect.fail("gRPC field " + label + " must be an object but was " + jsonTypeOf(value)); return; } grpcCheckShape(value, field.shape, label + "."); return; }',
|
|
313036
|
+
' if (field.intType) { if (!matchesInt(field.intType, value)) pm.expect.fail("gRPC field " + label + " must be a valid " + field.intType + " (in range) but was " + JSON.stringify(value)); return; }',
|
|
312932
313037
|
' if (!matchesScalar(field.jsonType, value)) pm.expect.fail("gRPC field " + label + " must be " + field.jsonType + " but was " + jsonTypeOf(value));',
|
|
312933
313038
|
' else if (!matchesFormat(field.jsonFormat, value)) pm.expect.fail("gRPC field " + label + " must be " + formatLabel(field.jsonFormat));',
|
|
312934
313039
|
"}",
|
|
@@ -312978,6 +313083,103 @@ function methodPathOf(item) {
|
|
|
312978
313083
|
const value = payload?.methodPath;
|
|
312979
313084
|
return typeof value === "string" ? value : "";
|
|
312980
313085
|
}
|
|
313086
|
+
var GRPC_INT_SPECS = {
|
|
313087
|
+
int32: { signed: true, bits: 32, min: "-2147483648", max: "2147483647" },
|
|
313088
|
+
sint32: { signed: true, bits: 32, min: "-2147483648", max: "2147483647" },
|
|
313089
|
+
sfixed32: { signed: true, bits: 32, min: "-2147483648", max: "2147483647" },
|
|
313090
|
+
uint32: { signed: false, bits: 32, min: "0", max: "4294967295" },
|
|
313091
|
+
fixed32: { signed: false, bits: 32, min: "0", max: "4294967295" },
|
|
313092
|
+
int64: { signed: true, bits: 64, min: "-9223372036854775808", max: "9223372036854775807" },
|
|
313093
|
+
sint64: { signed: true, bits: 64, min: "-9223372036854775808", max: "9223372036854775807" },
|
|
313094
|
+
sfixed64: { signed: true, bits: 64, min: "-9223372036854775808", max: "9223372036854775807" },
|
|
313095
|
+
uint64: { signed: false, bits: 64, min: "0", max: "18446744073709551615" },
|
|
313096
|
+
fixed64: { signed: false, bits: 64, min: "0", max: "18446744073709551615" }
|
|
313097
|
+
};
|
|
313098
|
+
function grpcDecStr(n) {
|
|
313099
|
+
const s = String(n);
|
|
313100
|
+
return s.indexOf("e") === -1 && s.indexOf("E") === -1 && s.indexOf(".") === -1 ? s : null;
|
|
313101
|
+
}
|
|
313102
|
+
function grpcCmpIntStr(a, b) {
|
|
313103
|
+
const na = a.charAt(0) === "-";
|
|
313104
|
+
const nb = b.charAt(0) === "-";
|
|
313105
|
+
if (na !== nb) return na ? -1 : 1;
|
|
313106
|
+
const aa = (na ? a.slice(1) : a).replace(/^0+(?=[0-9])/, "");
|
|
313107
|
+
const bb = (nb ? b.slice(1) : b).replace(/^0+(?=[0-9])/, "");
|
|
313108
|
+
let mag;
|
|
313109
|
+
if (aa.length !== bb.length) mag = aa.length < bb.length ? -1 : 1;
|
|
313110
|
+
else mag = aa < bb ? -1 : aa > bb ? 1 : 0;
|
|
313111
|
+
return na ? -mag : mag;
|
|
313112
|
+
}
|
|
313113
|
+
function grpcNormIntStr(input) {
|
|
313114
|
+
let s = input;
|
|
313115
|
+
let neg = false;
|
|
313116
|
+
if (s.charAt(0) === "-") {
|
|
313117
|
+
neg = true;
|
|
313118
|
+
s = s.slice(1);
|
|
313119
|
+
} else if (s.charAt(0) === "+") {
|
|
313120
|
+
s = s.slice(1);
|
|
313121
|
+
}
|
|
313122
|
+
let ei = s.indexOf("e");
|
|
313123
|
+
if (ei === -1) ei = s.indexOf("E");
|
|
313124
|
+
let exp = 0;
|
|
313125
|
+
if (ei !== -1) {
|
|
313126
|
+
exp = parseInt(s.slice(ei + 1), 10);
|
|
313127
|
+
s = s.slice(0, ei);
|
|
313128
|
+
}
|
|
313129
|
+
const dot = s.indexOf(".");
|
|
313130
|
+
const intp = dot === -1 ? s : s.slice(0, dot);
|
|
313131
|
+
const frac = dot === -1 ? "" : s.slice(dot + 1);
|
|
313132
|
+
const digits = intp + frac;
|
|
313133
|
+
if (digits.length === 0) return null;
|
|
313134
|
+
if (/^0+$/.test(digits)) return "0";
|
|
313135
|
+
if (exp >= 0) {
|
|
313136
|
+
const intpSize = intp === "0" ? 0 : intp.length;
|
|
313137
|
+
if (intpSize + exp > 20) return null;
|
|
313138
|
+
}
|
|
313139
|
+
const netExp = exp - frac.length;
|
|
313140
|
+
let out;
|
|
313141
|
+
if (netExp >= 0) {
|
|
313142
|
+
if (digits.length + netExp > 40) return null;
|
|
313143
|
+
out = digits + "0".repeat(netExp);
|
|
313144
|
+
} else {
|
|
313145
|
+
const cut = -netExp;
|
|
313146
|
+
const keepLen = digits.length - cut;
|
|
313147
|
+
const dropped = keepLen <= 0 ? digits : digits.slice(keepLen);
|
|
313148
|
+
for (let d = 0; d < dropped.length; d += 1) {
|
|
313149
|
+
if (dropped.charAt(d) !== "0") return null;
|
|
313150
|
+
}
|
|
313151
|
+
out = keepLen <= 0 ? "0" : digits.slice(0, keepLen);
|
|
313152
|
+
}
|
|
313153
|
+
let st = 0;
|
|
313154
|
+
while (st < out.length - 1 && out.charAt(st) === "0") st += 1;
|
|
313155
|
+
out = out.slice(st);
|
|
313156
|
+
if (out === "0") return "0";
|
|
313157
|
+
if (out.length > 40) return null;
|
|
313158
|
+
return neg ? `-${out}` : out;
|
|
313159
|
+
}
|
|
313160
|
+
function matchesIntValue(intType, value) {
|
|
313161
|
+
const spec = GRPC_INT_SPECS[intType];
|
|
313162
|
+
if (!spec) return true;
|
|
313163
|
+
let num;
|
|
313164
|
+
let canonical;
|
|
313165
|
+
if (typeof value === "number") {
|
|
313166
|
+
if (!Number.isFinite(value) || !Number.isInteger(value)) return false;
|
|
313167
|
+
num = value;
|
|
313168
|
+
canonical = grpcDecStr(value);
|
|
313169
|
+
} else if (typeof value === "string") {
|
|
313170
|
+
if (!/^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?$/.test(value)) return false;
|
|
313171
|
+
canonical = grpcNormIntStr(value);
|
|
313172
|
+
if (canonical === null) return false;
|
|
313173
|
+
num = Number(value);
|
|
313174
|
+
} else {
|
|
313175
|
+
return false;
|
|
313176
|
+
}
|
|
313177
|
+
if (canonical === "-0") canonical = "0";
|
|
313178
|
+
if (!spec.signed && (canonical !== null && canonical.charAt(0) === "-" || num < 0)) return false;
|
|
313179
|
+
if (spec.bits === 32) return num >= Number(spec.min) && num <= Number(spec.max);
|
|
313180
|
+
if (canonical !== null) return grpcCmpIntStr(canonical, spec.min) >= 0 && grpcCmpIntStr(canonical, spec.max) <= 0;
|
|
313181
|
+
return false;
|
|
313182
|
+
}
|
|
312981
313183
|
function matchesScalarValue(expected, value) {
|
|
312982
313184
|
const isJsonNumberString = (text) => /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?$/.test(text) && Number.isFinite(Number(text));
|
|
312983
313185
|
switch (expected) {
|
|
@@ -313066,6 +313268,12 @@ function validProtoBytes(value) {
|
|
|
313066
313268
|
if (raw % 4 === 1) return false;
|
|
313067
313269
|
return pad === 0 || (raw + pad) % 4 === 0 && pad === (4 - raw % 4) % 4;
|
|
313068
313270
|
}
|
|
313271
|
+
function validProtoFloat32(value) {
|
|
313272
|
+
if (value === "NaN" || value === "Infinity" || value === "-Infinity") return true;
|
|
313273
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
313274
|
+
if (!Number.isFinite(n)) return false;
|
|
313275
|
+
return Number.isFinite(Math.fround(n));
|
|
313276
|
+
}
|
|
313069
313277
|
function matchesFormatValue(format3, value) {
|
|
313070
313278
|
switch (format3) {
|
|
313071
313279
|
case void 0:
|
|
@@ -313078,6 +313286,8 @@ function matchesFormatValue(format3, value) {
|
|
|
313078
313286
|
return validProtoFieldMask(value);
|
|
313079
313287
|
case "proto-bytes":
|
|
313080
313288
|
return validProtoBytes(value);
|
|
313289
|
+
case "proto-float32":
|
|
313290
|
+
return validProtoFloat32(value);
|
|
313081
313291
|
default:
|
|
313082
313292
|
return true;
|
|
313083
313293
|
}
|
|
@@ -313112,6 +313322,12 @@ function staticRequestCheck(item, shape, methodPath2, warnings) {
|
|
|
313112
313322
|
continue;
|
|
313113
313323
|
}
|
|
313114
313324
|
if (field.jsonType === "any" || field.enumValues || field.map || field.shape) continue;
|
|
313325
|
+
if (field.intType) {
|
|
313326
|
+
if (!matchesIntValue(field.intType, value)) {
|
|
313327
|
+
warnings.push(`PROTO_REQUEST_FIELD_TYPE_MISMATCH: ${methodPath2} request field ${field.name} must be a valid ${field.intType} (in range)`);
|
|
313328
|
+
}
|
|
313329
|
+
continue;
|
|
313330
|
+
}
|
|
313115
313331
|
if (!matchesScalarValue(field.jsonType, value)) {
|
|
313116
313332
|
warnings.push(`PROTO_REQUEST_FIELD_TYPE_MISMATCH: ${methodPath2} request field ${field.name} must be ${field.jsonType}`);
|
|
313117
313333
|
} else if (!matchesFormatValue(field.jsonFormat, value)) {
|
|
@@ -313121,6 +313337,7 @@ function staticRequestCheck(item, shape, methodPath2, warnings) {
|
|
|
313121
313337
|
}
|
|
313122
313338
|
function instrumentGrpcCollection(collection, index) {
|
|
313123
313339
|
const warnings = [...index.warnings, ...index.operations.flatMap((operation) => operation.warnings)];
|
|
313340
|
+
warnings.push("GRPC_UNKNOWN_FIELDS_NOT_REJECTED: extra response JSON keys are not rejected (proto3 forward-compat + open well-known types; unknown wire fields are not surfaced by the binary->JSON decode)");
|
|
313124
313341
|
const specs = /* @__PURE__ */ new Map();
|
|
313125
313342
|
const requestShapes = /* @__PURE__ */ new Map();
|
|
313126
313343
|
for (const operation of index.operations) {
|
|
@@ -313627,6 +313844,7 @@ function createSoapScript(operation, warnings = []) {
|
|
|
313627
313844
|
` pm.expect(bodyText, "expected SOAP response element <" + soap.expectedResponseElement + "> not found").to.match(new RegExp(${JSON.stringify(responseRegex)}));`,
|
|
313628
313845
|
"});"
|
|
313629
313846
|
);
|
|
313847
|
+
warnings.push(`SOAP_RESPONSE_BODY_WRAPPER_ONLY: operation ${operation.name} asserts the SOAP envelope/body/fault and the top-level response element <${operation.expectedResponseElement}> but NOT its child element/scalar shapes (WSDL/XSD payload validation is out of scope)`);
|
|
313630
313848
|
} else if (operation.output) {
|
|
313631
313849
|
warnings.push(`SOAP_RESPONSE_ELEMENT_UNKNOWN: operation ${operation.name} has an output message but no resolvable response element; only Envelope/Body/Fault are asserted`);
|
|
313632
313850
|
}
|