callman-core 1.7.1 → 1.8.0

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.
Files changed (109) hide show
  1. package/dist/scenario-runner/runScenario.d.ts.map +1 -1
  2. package/dist/scenario-runner/runScenario.js +8 -0
  3. package/dist/scenario-runner/runScenario.js.map +1 -1
  4. package/dist/scenario-runner/types.d.ts +1 -1
  5. package/dist/scenario-runner/types.d.ts.map +1 -1
  6. package/dist/script/executor.d.ts.map +1 -1
  7. package/dist/script/executor.js +75 -9
  8. package/dist/script/executor.js.map +1 -1
  9. package/dist/script/features/collectionVariables.d.ts +16 -0
  10. package/dist/script/features/collectionVariables.d.ts.map +1 -0
  11. package/dist/script/features/collectionVariables.js +83 -0
  12. package/dist/script/features/collectionVariables.js.map +1 -0
  13. package/dist/script/features/cryptojs.d.ts +8 -12
  14. package/dist/script/features/cryptojs.d.ts.map +1 -1
  15. package/dist/script/features/cryptojs.js +15 -99
  16. package/dist/script/features/cryptojs.js.map +1 -1
  17. package/dist/script/features/environment.d.ts +8 -1
  18. package/dist/script/features/environment.d.ts.map +1 -1
  19. package/dist/script/features/environment.js +25 -1
  20. package/dist/script/features/environment.js.map +1 -1
  21. package/dist/script/features/execution.d.ts +17 -0
  22. package/dist/script/features/execution.d.ts.map +1 -0
  23. package/dist/script/features/execution.js +60 -0
  24. package/dist/script/features/execution.js.map +1 -0
  25. package/dist/script/features/headerList.d.ts +44 -0
  26. package/dist/script/features/headerList.d.ts.map +1 -0
  27. package/dist/script/features/headerList.js +284 -0
  28. package/dist/script/features/headerList.js.map +1 -0
  29. package/dist/script/features/info.d.ts +10 -0
  30. package/dist/script/features/info.d.ts.map +1 -0
  31. package/dist/script/features/info.js +32 -0
  32. package/dist/script/features/info.js.map +1 -0
  33. package/dist/script/features/request.d.ts +3 -2
  34. package/dist/script/features/request.d.ts.map +1 -1
  35. package/dist/script/features/request.js +38 -29
  36. package/dist/script/features/request.js.map +1 -1
  37. package/dist/script/features/response.d.ts +7 -5
  38. package/dist/script/features/response.d.ts.map +1 -1
  39. package/dist/script/features/response.js +16 -8
  40. package/dist/script/features/response.js.map +1 -1
  41. package/dist/script/features/responseAssertions.d.ts +50 -0
  42. package/dist/script/features/responseAssertions.d.ts.map +1 -0
  43. package/dist/script/features/responseAssertions.js +293 -0
  44. package/dist/script/features/responseAssertions.js.map +1 -0
  45. package/dist/script/features/timers.d.ts +17 -0
  46. package/dist/script/features/timers.d.ts.map +1 -0
  47. package/dist/script/features/timers.js +152 -0
  48. package/dist/script/features/timers.js.map +1 -0
  49. package/dist/script/features/variables.d.ts +8 -1
  50. package/dist/script/features/variables.d.ts.map +1 -1
  51. package/dist/script/features/variables.js +57 -11
  52. package/dist/script/features/variables.js.map +1 -1
  53. package/dist/script/scope.d.ts +10 -0
  54. package/dist/script/scope.d.ts.map +1 -1
  55. package/dist/script/scope.js +13 -4
  56. package/dist/script/scope.js.map +1 -1
  57. package/dist/script/types.d.ts +51 -1
  58. package/dist/script/types.d.ts.map +1 -1
  59. package/dist/templating/generator-metadata.d.ts +1 -0
  60. package/dist/templating/generator-metadata.d.ts.map +1 -1
  61. package/dist/templating/generator-metadata.js +76 -0
  62. package/dist/templating/generator-metadata.js.map +1 -1
  63. package/dist/templating/postman-generators.d.ts +12 -0
  64. package/dist/templating/postman-generators.d.ts.map +1 -0
  65. package/dist/templating/postman-generators.js +577 -0
  66. package/dist/templating/postman-generators.js.map +1 -0
  67. package/dist/templating/template-engine.d.ts.map +1 -1
  68. package/dist/templating/template-engine.js +16 -0
  69. package/dist/templating/template-engine.js.map +1 -1
  70. package/dist/variables/resolver.d.ts.map +1 -1
  71. package/dist/variables/resolver.js +15 -0
  72. package/dist/variables/resolver.js.map +1 -1
  73. package/dist-cjs/scenario-runner/runScenario.js +8 -0
  74. package/dist-cjs/scenario-runner/runScenario.js.map +1 -1
  75. package/dist-cjs/script/executor.js +78 -9
  76. package/dist-cjs/script/executor.js.map +1 -1
  77. package/dist-cjs/script/features/collectionVariables.js +87 -0
  78. package/dist-cjs/script/features/collectionVariables.js.map +1 -0
  79. package/dist-cjs/script/features/cryptojs.js +18 -99
  80. package/dist-cjs/script/features/cryptojs.js.map +1 -1
  81. package/dist-cjs/script/features/environment.js +25 -1
  82. package/dist-cjs/script/features/environment.js.map +1 -1
  83. package/dist-cjs/script/features/execution.js +64 -0
  84. package/dist-cjs/script/features/execution.js.map +1 -0
  85. package/dist-cjs/script/features/headerList.js +289 -0
  86. package/dist-cjs/script/features/headerList.js.map +1 -0
  87. package/dist-cjs/script/features/info.js +36 -0
  88. package/dist-cjs/script/features/info.js.map +1 -0
  89. package/dist-cjs/script/features/request.js +38 -29
  90. package/dist-cjs/script/features/request.js.map +1 -1
  91. package/dist-cjs/script/features/response.js +16 -8
  92. package/dist-cjs/script/features/response.js.map +1 -1
  93. package/dist-cjs/script/features/responseAssertions.js +297 -0
  94. package/dist-cjs/script/features/responseAssertions.js.map +1 -0
  95. package/dist-cjs/script/features/timers.js +156 -0
  96. package/dist-cjs/script/features/timers.js.map +1 -0
  97. package/dist-cjs/script/features/variables.js +57 -11
  98. package/dist-cjs/script/features/variables.js.map +1 -1
  99. package/dist-cjs/script/scope.js +13 -4
  100. package/dist-cjs/script/scope.js.map +1 -1
  101. package/dist-cjs/templating/generator-metadata.js +77 -1
  102. package/dist-cjs/templating/generator-metadata.js.map +1 -1
  103. package/dist-cjs/templating/postman-generators.js +581 -0
  104. package/dist-cjs/templating/postman-generators.js.map +1 -0
  105. package/dist-cjs/templating/template-engine.js +16 -0
  106. package/dist-cjs/templating/template-engine.js.map +1 -1
  107. package/dist-cjs/variables/resolver.js +15 -0
  108. package/dist-cjs/variables/resolver.js.map +1 -1
  109. package/package.json +6 -2
@@ -0,0 +1,50 @@
1
+ import { PmAssertion, type AssertionFlags } from "./assertions.js";
2
+ export declare class ResponseAssertion extends PmAssertion {
3
+ constructor(actual: unknown, flags?: AssertionFlags);
4
+ get not(): ResponseAssertion;
5
+ get deep(): ResponseAssertion;
6
+ get nested(): ResponseAssertion;
7
+ private decide;
8
+ private readStatus;
9
+ private readContentType;
10
+ private readRawBody;
11
+ private readJsonBody;
12
+ private statusInRange;
13
+ private statusExactly;
14
+ get ok(): ResponseAssertion;
15
+ get success(): ResponseAssertion;
16
+ get info(): ResponseAssertion;
17
+ get redirection(): ResponseAssertion;
18
+ get clientError(): ResponseAssertion;
19
+ get serverError(): ResponseAssertion;
20
+ get error(): ResponseAssertion;
21
+ get notFound(): ResponseAssertion;
22
+ get unauthorized(): ResponseAssertion;
23
+ get forbidden(): ResponseAssertion;
24
+ get badRequest(): ResponseAssertion;
25
+ get rateLimited(): ResponseAssertion;
26
+ get accepted(): ResponseAssertion;
27
+ get withBody(): ResponseAssertion;
28
+ get json(): ResponseAssertion;
29
+ get xml(): ResponseAssertion;
30
+ get html(): ResponseAssertion;
31
+ /**
32
+ * `.have.body()` — non-empty body.
33
+ * `.have.body("substring")` — body string contains substring.
34
+ */
35
+ body(expected?: unknown): ResponseAssertion;
36
+ /**
37
+ * `.have.jsonBody()` — body parses as JSON (non-undefined).
38
+ * `.have.jsonBody("path.to.field")` — dot-path lookup must exist.
39
+ * `.have.jsonBody("path.to.field", expected)` — dot-path lookup must
40
+ * deep-equal `expected`.
41
+ */
42
+ jsonBody(path?: unknown, expected?: unknown): ResponseAssertion;
43
+ /**
44
+ * `.have.jsonSchema(schema)` — placeholder. Real implementation arrives
45
+ * in the Phase 2.4 work that bundles ajv. Throws a clear error today so
46
+ * scripts fail fast rather than silently passing.
47
+ */
48
+ jsonSchema(_schema: unknown): ResponseAssertion;
49
+ }
50
+ //# sourceMappingURL=responseAssertions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseAssertions.d.ts","sourceRoot":"","sources":["../../../src/script/features/responseAssertions.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAgBnE,qBAAa,iBAAkB,SAAQ,WAAW;gBACpC,MAAM,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB;IAMvD,IAAa,GAAG,IAAI,iBAAiB,CAKpC;IACD,IAAa,IAAI,IAAI,iBAAiB,CAErC;IACD,IAAa,MAAM,IAAI,iBAAiB,CAKvC;IAGD,OAAO,CAAC,MAAM;IAgBd,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,eAAe;IA6BvB,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,aAAa;IAUrB,IAAa,EAAE,IAAI,iBAAiB,CAEnC;IAED,IAAI,OAAO,IAAI,iBAAiB,CAE/B;IAED,IAAI,IAAI,IAAI,iBAAiB,CAE5B;IAED,IAAI,WAAW,IAAI,iBAAiB,CAEnC;IAED,IAAI,WAAW,IAAI,iBAAiB,CAEnC;IAED,IAAI,WAAW,IAAI,iBAAiB,CAEnC;IAED,IAAI,KAAK,IAAI,iBAAiB,CAQ7B;IAGD,IAAI,QAAQ,IAAI,iBAAiB,CAEhC;IAED,IAAI,YAAY,IAAI,iBAAiB,CAEpC;IAED,IAAI,SAAS,IAAI,iBAAiB,CAEjC;IAED,IAAI,UAAU,IAAI,iBAAiB,CAElC;IAED,IAAI,WAAW,IAAI,iBAAiB,CAEnC;IAED,IAAI,QAAQ,IAAI,iBAAiB,CAEhC;IAED,IAAI,QAAQ,IAAI,iBAAiB,CAQhC;IAGD,IAAI,IAAI,IAAI,iBAAiB,CAW5B;IAED,IAAI,GAAG,IAAI,iBAAiB,CAW3B;IAED,IAAI,IAAI,IAAI,iBAAiB,CAQ5B;IAGD;;;OAGG;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,iBAAiB;IAiB3C;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,iBAAiB;IAmC/D;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,iBAAiB;CAKhD"}
@@ -0,0 +1,293 @@
1
+ // ResponseAssertion — Postman-compatible response-shape shortcuts.
2
+ //
3
+ // Extends PmAssertion with the family of getters and methods that scripts
4
+ // reach for on `pm.response.to.*`:
5
+ //
6
+ // pm.response.to.be.ok // 2xx
7
+ // pm.response.to.be.success // 2xx (alias)
8
+ // pm.response.to.be.info // 1xx
9
+ // pm.response.to.be.redirection // 3xx
10
+ // pm.response.to.be.clientError // 4xx
11
+ // pm.response.to.be.serverError // 5xx
12
+ // pm.response.to.be.notFound // 404
13
+ // pm.response.to.be.unauthorized // 401
14
+ // pm.response.to.be.forbidden // 403
15
+ // pm.response.to.be.badRequest // 400
16
+ // pm.response.to.be.rateLimited // 429
17
+ //
18
+ // pm.response.to.be.json // content-type includes application/json
19
+ // pm.response.to.be.xml // includes xml
20
+ // pm.response.to.be.html // includes html
21
+ //
22
+ // pm.response.to.have.body(text?) // substring or non-empty
23
+ // pm.response.to.have.jsonBody(path?, val?) // dot-path JSON lookup
24
+ //
25
+ // Each predicate honours `.not` for negation, and returns the assertion so
26
+ // chains keep going: `pm.response.to.be.success.and.have.body("ok")`.
27
+ //
28
+ // Back-compat note: PmAssertion already exposes a `.ok` getter that checks
29
+ // truthiness. We override it here to the 2xx range semantic Postman uses.
30
+ // Existing Callman scripts that called `pm.response.to.be.ok` previously
31
+ // always passed (a ResponseApi object is truthy by construction), so the
32
+ // new behaviour is strictly more useful — failing responses now fail the
33
+ // assertion as they should.
34
+ import { PmAssertion } from "./assertions.js";
35
+ import { safeGet } from "../../utils/get.js";
36
+ const isObject = (value) => typeof value === "object" && value !== null;
37
+ const formatValue = (value) => {
38
+ if (typeof value === "string")
39
+ return `"${value}"`;
40
+ if (value === undefined)
41
+ return "undefined";
42
+ try {
43
+ return JSON.stringify(value);
44
+ }
45
+ catch {
46
+ return String(value);
47
+ }
48
+ };
49
+ export class ResponseAssertion extends PmAssertion {
50
+ constructor(actual, flags = {}) {
51
+ super(actual, flags);
52
+ }
53
+ // ── Modifier getters preserve the subclass so the response-specific
54
+ // predicates stay available after .not / .deep / .nested ───────────────
55
+ get not() {
56
+ return new ResponseAssertion(this.actual, {
57
+ ...this.flags,
58
+ negated: !this.flags.negated,
59
+ });
60
+ }
61
+ get deep() {
62
+ return new ResponseAssertion(this.actual, { ...this.flags, deep: true });
63
+ }
64
+ get nested() {
65
+ return new ResponseAssertion(this.actual, {
66
+ ...this.flags,
67
+ nested: true,
68
+ });
69
+ }
70
+ // ── Internal assertion + status helpers ────────────────────────────────
71
+ decide(pass, positiveMessage, negativeMessage) {
72
+ const finalPass = this.flags.negated ? !pass : pass;
73
+ if (!finalPass) {
74
+ throw new Error(this.flags.negated
75
+ ? negativeMessage ?? `Expected NOT: ${positiveMessage}`
76
+ : positiveMessage);
77
+ }
78
+ return this;
79
+ }
80
+ readStatus() {
81
+ if (isObject(this.actual)) {
82
+ const raw = this.actual.status;
83
+ if (typeof raw === "number" && Number.isFinite(raw)) {
84
+ return raw;
85
+ }
86
+ }
87
+ throw new Error("Response shortcut requires a response object (missing numeric `status`)");
88
+ }
89
+ readContentType() {
90
+ if (!isObject(this.actual))
91
+ return "";
92
+ const direct = this.actual.contentType;
93
+ if (typeof direct === "string" && direct.length > 0) {
94
+ return direct.toLowerCase();
95
+ }
96
+ // Fall back to looking it up in the headers HeaderList / record.
97
+ const headers = this.actual.headers;
98
+ if (isObject(headers)) {
99
+ // HeaderList exposes a case-insensitive .get() — prefer it.
100
+ const headerGetter = headers.get;
101
+ if (typeof headerGetter === "function") {
102
+ const got = headerGetter.call(headers, "content-type");
103
+ if (typeof got === "string")
104
+ return got.toLowerCase();
105
+ }
106
+ else {
107
+ const lookup = Object.entries(headers).find(([key]) => key.toLowerCase() === "content-type");
108
+ if (lookup && typeof lookup[1] === "string") {
109
+ return lookup[1].toLowerCase();
110
+ }
111
+ }
112
+ }
113
+ return "";
114
+ }
115
+ readRawBody() {
116
+ if (!isObject(this.actual))
117
+ return "";
118
+ const raw = this.actual.rawBody;
119
+ if (typeof raw === "string")
120
+ return raw;
121
+ const body = this.actual.body;
122
+ if (typeof body === "string")
123
+ return body;
124
+ if (body !== null && body !== undefined) {
125
+ try {
126
+ return JSON.stringify(body);
127
+ }
128
+ catch {
129
+ return String(body);
130
+ }
131
+ }
132
+ return "";
133
+ }
134
+ readJsonBody() {
135
+ if (!isObject(this.actual))
136
+ return undefined;
137
+ const jsonFn = this.actual.json;
138
+ if (typeof jsonFn === "function") {
139
+ try {
140
+ return jsonFn.call(this.actual);
141
+ }
142
+ catch {
143
+ // fall through to other shapes
144
+ }
145
+ }
146
+ const direct = this.actual.jsonBody;
147
+ if (direct !== undefined)
148
+ return direct;
149
+ const body = this.actual.body;
150
+ if (body !== undefined)
151
+ return body;
152
+ return this.actual.data;
153
+ }
154
+ statusInRange(min, max, label) {
155
+ const status = this.readStatus();
156
+ return this.decide(status >= min && status <= max, `Expected status ${status} to be ${label} (${min}-${max})`, `Expected status ${status} NOT to be ${label} (${min}-${max})`);
157
+ }
158
+ statusExactly(expected, label) {
159
+ const status = this.readStatus();
160
+ return this.decide(status === expected, `Expected status ${status} to be ${expected} (${label})`, `Expected status ${status} NOT to be ${expected} (${label})`);
161
+ }
162
+ // ── Status-range predicates ───────────────────────────────────────────
163
+ get ok() {
164
+ return this.statusInRange(200, 299, "OK / 2xx");
165
+ }
166
+ get success() {
167
+ return this.statusInRange(200, 299, "success / 2xx");
168
+ }
169
+ get info() {
170
+ return this.statusInRange(100, 199, "informational / 1xx");
171
+ }
172
+ get redirection() {
173
+ return this.statusInRange(300, 399, "redirection / 3xx");
174
+ }
175
+ get clientError() {
176
+ return this.statusInRange(400, 499, "client error / 4xx");
177
+ }
178
+ get serverError() {
179
+ return this.statusInRange(500, 599, "server error / 5xx");
180
+ }
181
+ get error() {
182
+ // Postman's `.error` matches any 4xx OR 5xx response.
183
+ const status = this.readStatus();
184
+ return this.decide(status >= 400 && status <= 599, `Expected status ${status} to be an error (4xx-5xx)`, `Expected status ${status} NOT to be an error (4xx-5xx)`);
185
+ }
186
+ // ── Status-exact predicates ───────────────────────────────────────────
187
+ get notFound() {
188
+ return this.statusExactly(404, "Not Found");
189
+ }
190
+ get unauthorized() {
191
+ return this.statusExactly(401, "Unauthorized");
192
+ }
193
+ get forbidden() {
194
+ return this.statusExactly(403, "Forbidden");
195
+ }
196
+ get badRequest() {
197
+ return this.statusExactly(400, "Bad Request");
198
+ }
199
+ get rateLimited() {
200
+ return this.statusExactly(429, "Too Many Requests / rate limited");
201
+ }
202
+ get accepted() {
203
+ return this.statusExactly(202, "Accepted");
204
+ }
205
+ get withBody() {
206
+ // Postman shorthand — non-empty body.
207
+ const body = this.readRawBody();
208
+ return this.decide(body.length > 0, "Expected response to have a body", "Expected response NOT to have a body");
209
+ }
210
+ // ── Content-type predicates ───────────────────────────────────────────
211
+ get json() {
212
+ const ct = this.readContentType();
213
+ const isJson = ct.includes("application/json") ||
214
+ ct.includes("+json") ||
215
+ ct.includes("text/json");
216
+ return this.decide(isJson, `Expected response Content-Type to be JSON, got "${ct || "(none)"}"`, `Expected response Content-Type NOT to be JSON, got "${ct || "(none)"}"`);
217
+ }
218
+ get xml() {
219
+ const ct = this.readContentType();
220
+ const isXml = ct.includes("application/xml") ||
221
+ ct.includes("text/xml") ||
222
+ ct.includes("+xml");
223
+ return this.decide(isXml, `Expected response Content-Type to be XML, got "${ct || "(none)"}"`, `Expected response Content-Type NOT to be XML, got "${ct || "(none)"}"`);
224
+ }
225
+ get html() {
226
+ const ct = this.readContentType();
227
+ const isHtml = ct.includes("text/html");
228
+ return this.decide(isHtml, `Expected response Content-Type to be HTML, got "${ct || "(none)"}"`, `Expected response Content-Type NOT to be HTML, got "${ct || "(none)"}"`);
229
+ }
230
+ // ── Body / payload assertions ─────────────────────────────────────────
231
+ /**
232
+ * `.have.body()` — non-empty body.
233
+ * `.have.body("substring")` — body string contains substring.
234
+ */
235
+ body(expected) {
236
+ const raw = this.readRawBody();
237
+ if (expected === undefined) {
238
+ return this.decide(raw.length > 0, "Expected response to have a body", "Expected response NOT to have a body");
239
+ }
240
+ const needle = String(expected);
241
+ return this.decide(raw.includes(needle), `Expected response body to include ${formatValue(needle)}`, `Expected response body NOT to include ${formatValue(needle)}`);
242
+ }
243
+ /**
244
+ * `.have.jsonBody()` — body parses as JSON (non-undefined).
245
+ * `.have.jsonBody("path.to.field")` — dot-path lookup must exist.
246
+ * `.have.jsonBody("path.to.field", expected)` — dot-path lookup must
247
+ * deep-equal `expected`.
248
+ */
249
+ jsonBody(path, expected) {
250
+ const json = this.readJsonBody();
251
+ if (path === undefined) {
252
+ return this.decide(json !== undefined && json !== null, "Expected response body to be valid JSON", "Expected response body NOT to be valid JSON");
253
+ }
254
+ if (typeof path !== "string") {
255
+ throw new TypeError("jsonBody(path) — path must be a string");
256
+ }
257
+ const lookup = safeGet(json, path);
258
+ if (arguments.length < 2) {
259
+ return this.decide(lookup.exists, `Expected response body to have JSON path "${path}"`, `Expected response body NOT to have JSON path "${path}"`);
260
+ }
261
+ // Two-arg form: assert existence + deep equality.
262
+ if (!lookup.exists) {
263
+ return this.decide(false, `Expected response body to have JSON path "${path}"`, `Expected response body NOT to have JSON path "${path}"`);
264
+ }
265
+ return this.decide(deepEqual(lookup.value, expected), `Expected JSON path "${path}" to equal ${formatValue(expected)}, got ${formatValue(lookup.value)}`, `Expected JSON path "${path}" NOT to equal ${formatValue(expected)}`);
266
+ }
267
+ /**
268
+ * `.have.jsonSchema(schema)` — placeholder. Real implementation arrives
269
+ * in the Phase 2.4 work that bundles ajv. Throws a clear error today so
270
+ * scripts fail fast rather than silently passing.
271
+ */
272
+ jsonSchema(_schema) {
273
+ throw new Error("pm.response.to.have.jsonSchema is not yet supported — Phase 2.4 will land ajv-backed schema validation. Use pm.expect with manual checks for now.");
274
+ }
275
+ }
276
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
277
+ const deepEqual = (left, right) => {
278
+ if (Object.is(left, right))
279
+ return true;
280
+ if (Array.isArray(left) && Array.isArray(right)) {
281
+ return (left.length === right.length &&
282
+ left.every((value, index) => deepEqual(value, right[index])));
283
+ }
284
+ if (isRecord(left) && isRecord(right)) {
285
+ const leftKeys = Object.keys(left);
286
+ const rightKeys = Object.keys(right);
287
+ return (leftKeys.length === rightKeys.length &&
288
+ leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) &&
289
+ deepEqual(left[key], right[key])));
290
+ }
291
+ return false;
292
+ };
293
+ //# sourceMappingURL=responseAssertions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseAssertions.js","sourceRoot":"","sources":["../../../src/script/features/responseAssertions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface TimerApi {
2
+ setTimeout: (handler: unknown, delay?: unknown, ...args: unknown[]) => number;
3
+ clearTimeout: (id: unknown) => void;
4
+ setInterval: (handler: unknown, delay?: unknown, ...args: unknown[]) => number;
5
+ clearInterval: (id: unknown) => void;
6
+ }
7
+ export interface TimerFeature {
8
+ api: TimerApi;
9
+ /** Cancel every still-pending timer. Idempotent. */
10
+ dispose(): void;
11
+ /** Number of timers ever created — informational, for tests. */
12
+ totalCreated(): number;
13
+ /** Number of currently-active timers (not yet fired or cleared). */
14
+ activeCount(): number;
15
+ }
16
+ export declare const buildTimerFeature: () => TimerFeature;
17
+ //# sourceMappingURL=timers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timers.d.ts","sourceRoot":"","sources":["../../../src/script/features/timers.ts"],"names":[],"mappings":"AA2BA,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,MAAM,CAAC;IAC9E,YAAY,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,MAAM,CAAC;IAC/E,aAAa,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,QAAQ,CAAC;IACd,oDAAoD;IACpD,OAAO,IAAI,IAAI,CAAC;IAChB,gEAAgE;IAChE,YAAY,IAAI,MAAM,CAAC;IACvB,oEAAoE;IACpE,WAAW,IAAI,MAAM,CAAC;CACvB;AAeD,eAAO,MAAM,iBAAiB,QAAO,YAsHpC,CAAC"}
@@ -0,0 +1,152 @@
1
+ // Timer registry — exposes `setTimeout` / `clearTimeout` /
2
+ // `setInterval` / `clearInterval` inside the sandbox without leaking
3
+ // pending callbacks past the script's lifetime.
4
+ //
5
+ // Why this matters: Postman scripts routinely use
6
+ // await new Promise(r => setTimeout(r, 1000))
7
+ // for retry / poll patterns. We had this BLOCKED, so any such script
8
+ // died with `ReferenceError: setTimeout is not defined`. Re-enabling
9
+ // the globals naively would let a runaway `setInterval(fn, 100)`
10
+ // keep firing long after the script completed.
11
+ //
12
+ // The feature builds per-execution wrappers that:
13
+ // • register each timer id in a Map
14
+ // • cap each delay at MAX_TIMER_DELAY_MS (60 s) so a buggy script
15
+ // can't park work forever
16
+ // • cap the number of in-flight timers at MAX_TIMERS_PER_EXEC so a
17
+ // `for (;;) setTimeout(...)` loop can't drown the runtime
18
+ // • are torn down by `dispose()` once the script's outer Promise
19
+ // resolves/rejects (called from the executor's flush path)
20
+ //
21
+ // Each call returns a numeric id (1, 2, 3, ...) — opaque to the user
22
+ // script but unique per execution so clearTimeout works correctly even
23
+ // across nested feature builds.
24
+ const MAX_TIMER_DELAY_MS = 60_000;
25
+ const MAX_TIMERS_PER_EXEC = 1_000;
26
+ const clampDelay = (raw) => {
27
+ const n = Number(raw);
28
+ if (!Number.isFinite(n) || n < 0)
29
+ return 0;
30
+ return Math.min(n, MAX_TIMER_DELAY_MS);
31
+ };
32
+ export const buildTimerFeature = () => {
33
+ const handles = new Map();
34
+ let nextId = 1;
35
+ let totalCreated = 0;
36
+ let disposed = false;
37
+ const allocId = () => {
38
+ const id = nextId;
39
+ nextId += 1;
40
+ return id;
41
+ };
42
+ const clear = (id, alsoActive = true) => {
43
+ const handle = handles.get(id);
44
+ if (!handle)
45
+ return;
46
+ if (alsoActive) {
47
+ if (handle.kind === "timeout") {
48
+ clearTimeout(handle.hostId);
49
+ }
50
+ else {
51
+ clearInterval(handle.hostId);
52
+ }
53
+ }
54
+ handles.delete(id);
55
+ };
56
+ const api = {
57
+ setTimeout: (handler, delay, ...args) => {
58
+ if (disposed) {
59
+ // Once the script has been disposed, any further timer
60
+ // requests are no-ops. Returning 0 (never a valid id) makes
61
+ // a stray `clearTimeout(...)` after disposal harmless too.
62
+ return 0;
63
+ }
64
+ if (typeof handler !== "function") {
65
+ throw new TypeError("setTimeout(handler) — handler must be a function");
66
+ }
67
+ if (handles.size >= MAX_TIMERS_PER_EXEC) {
68
+ throw new Error(`setTimeout: exceeded the per-script timer limit (${MAX_TIMERS_PER_EXEC}). ` +
69
+ `Use a single retry loop instead of scheduling many timers.`);
70
+ }
71
+ const id = allocId();
72
+ totalCreated += 1;
73
+ const ms = clampDelay(delay);
74
+ const hostId = setTimeout(() => {
75
+ // Remove from registry BEFORE firing so the handler can call
76
+ // clearTimeout(id) on itself without throwing on a stale entry.
77
+ handles.delete(id);
78
+ try {
79
+ handler(...args);
80
+ }
81
+ catch (error) {
82
+ // The vm context already routes uncaught script errors back
83
+ // to the executor's catch via Promise rejection. A timer
84
+ // callback that throws after the script's main promise has
85
+ // resolved is logged but doesn't blow up the host.
86
+ // eslint-disable-next-line no-console
87
+ console.error("Script timer callback threw:", error);
88
+ }
89
+ }, ms);
90
+ handles.set(id, { hostId, kind: "timeout" });
91
+ return id;
92
+ },
93
+ clearTimeout: (id) => {
94
+ if (disposed)
95
+ return;
96
+ const numeric = Number(id);
97
+ if (!Number.isInteger(numeric))
98
+ return;
99
+ clear(numeric);
100
+ },
101
+ setInterval: (handler, delay, ...args) => {
102
+ if (disposed)
103
+ return 0;
104
+ if (typeof handler !== "function") {
105
+ throw new TypeError("setInterval(handler) — handler must be a function");
106
+ }
107
+ if (handles.size >= MAX_TIMERS_PER_EXEC) {
108
+ throw new Error(`setInterval: exceeded the per-script timer limit (${MAX_TIMERS_PER_EXEC}).`);
109
+ }
110
+ const id = allocId();
111
+ totalCreated += 1;
112
+ // Intervals must have a positive delay — a 0 ms interval would
113
+ // spin a fire-hose. Clamp to at least 1 ms; the upper bound is
114
+ // the same MAX_TIMER_DELAY_MS cap.
115
+ const ms = Math.max(1, clampDelay(delay));
116
+ const hostId = setInterval(() => {
117
+ try {
118
+ handler(...args);
119
+ }
120
+ catch (error) {
121
+ // eslint-disable-next-line no-console
122
+ console.error("Script interval callback threw:", error);
123
+ }
124
+ }, ms);
125
+ handles.set(id, { hostId, kind: "interval" });
126
+ return id;
127
+ },
128
+ clearInterval: (id) => {
129
+ if (disposed)
130
+ return;
131
+ const numeric = Number(id);
132
+ if (!Number.isInteger(numeric))
133
+ return;
134
+ clear(numeric);
135
+ },
136
+ };
137
+ const dispose = () => {
138
+ if (disposed)
139
+ return;
140
+ disposed = true;
141
+ for (const id of [...handles.keys()]) {
142
+ clear(id);
143
+ }
144
+ };
145
+ return {
146
+ api,
147
+ dispose,
148
+ totalCreated: () => totalCreated,
149
+ activeCount: () => handles.size,
150
+ };
151
+ };
152
+ //# sourceMappingURL=timers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timers.js","sourceRoot":"","sources":["../../../src/script/features/timers.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,13 @@
1
1
  export interface VariablesApi {
2
+ has: (key: string) => boolean;
3
+ get: (key: string) => string | undefined;
4
+ set: (key: string, value: unknown) => void;
5
+ unset: (key: string) => void;
6
+ toObject: () => Record<string, string>;
2
7
  resolve: (input: unknown) => string;
3
8
  replaceIn: (input: unknown) => string;
4
9
  }
5
- export declare const buildVariablesApi: (environment: Record<string, string>, globals: Record<string, string>) => VariablesApi;
10
+ export declare const buildVariablesApi: (environment: Record<string, string>, globals: Record<string, string>, options?: {
11
+ collectionVariables?: Record<string, string>;
12
+ }) => VariablesApi;
6
13
  //# sourceMappingURL=variables.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../../../src/script/features/variables.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;IACpC,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;CACvC;AASD,eAAO,MAAM,iBAAiB,GAC5B,aAAa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC9B,YAYF,CAAC"}
1
+ {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../../../src/script/features/variables.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACzC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;IACpC,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;CACvC;AASD,eAAO,MAAM,iBAAiB,GAC5B,aAAa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,UAAS;IAAE,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAO,KAC7D,YA8CF,CAAC"}
@@ -1,10 +1,19 @@
1
- // pm.variables — collection-runner template resolver.
1
+ // pm.variables — Postman-compatible variable scope.
2
2
  //
3
- // Bridges the script sandbox to callman-core's existing template resolver
4
- // (callman_core/src/variables/resolver.ts). Merges env + globals into a
5
- // single lookup table so user scripts can call:
6
- // pm.variables.resolve("Hello {{name}}")
7
- // regardless of which scope `name` lives in.
3
+ // Postman's `pm.variables` exposes:
4
+ // • `.has(key)` / `.get(key)` / `.set(key, value)` / `.unset(key)` /
5
+ // `.toObject()` — operate on the merged scope (iteration row >
6
+ // environment > globals). Writes go to a transient local store that
7
+ // survives the request's scripts but does NOT mutate the env / globals
8
+ // records visible to other requests in the same run.
9
+ // • `.resolve(template)` / `.replaceIn(template)` — both names supported
10
+ // for compatibility; substitutes `{{var}}` against the merged scope
11
+ // and ALL Postman dynamic tokens (`$randomUUID`, `$timestamp`, etc.).
12
+ //
13
+ // Earlier Callman releases only exposed `.resolve` / `.replaceIn`. The
14
+ // has/get/set/unset/toObject methods are added now so scripts that use
15
+ // `pm.variables.set(...)` and `pm.variables.get(...)` (a very common
16
+ // Postman pattern) work without rewrites.
8
17
  import { resolveTemplate } from "../../variables/resolver.js";
9
18
  const stringifyInput = (value) => {
10
19
  if (value === undefined || value === null) {
@@ -12,12 +21,49 @@ const stringifyInput = (value) => {
12
21
  }
13
22
  return String(value);
14
23
  };
15
- export const buildVariablesApi = (environment, globals) => {
16
- // Merge with environment taking precedence over globals (matches the
17
- // electron runtime.ts behavior where env was spread after globals).
18
- const mergedScope = { ...globals, ...environment };
19
- const resolve = (input) => resolveTemplate(stringifyInput(input), { env: mergedScope });
24
+ export const buildVariablesApi = (environment, globals, options = {}) => {
25
+ // Local (request-scoped) overlay. Writes via `pm.variables.set` land
26
+ // here so they take precedence over env / globals for subsequent reads
27
+ // in the same script execution, without polluting persistent state.
28
+ const local = {};
29
+ const collection = options.collectionVariables ?? {};
30
+ // Precedence on read: local > collection > environment > globals.
31
+ // This mirrors Postman's documented order.
32
+ const readMerged = () => ({
33
+ ...globals,
34
+ ...environment,
35
+ ...collection,
36
+ ...local,
37
+ });
38
+ const resolve = (input) => resolveTemplate(stringifyInput(input), { env: readMerged() });
20
39
  return {
40
+ has: (key) => {
41
+ const normalisedKey = String(key ?? "").trim();
42
+ if (!normalisedKey)
43
+ return false;
44
+ const merged = readMerged();
45
+ return Object.prototype.hasOwnProperty.call(merged, normalisedKey);
46
+ },
47
+ get: (key) => {
48
+ const normalisedKey = String(key ?? "").trim();
49
+ if (!normalisedKey)
50
+ return undefined;
51
+ const merged = readMerged();
52
+ return merged[normalisedKey];
53
+ },
54
+ set: (key, value) => {
55
+ const normalisedKey = String(key ?? "").trim();
56
+ if (!normalisedKey)
57
+ return;
58
+ local[normalisedKey] = stringifyInput(value);
59
+ },
60
+ unset: (key) => {
61
+ const normalisedKey = String(key ?? "").trim();
62
+ if (!normalisedKey)
63
+ return;
64
+ delete local[normalisedKey];
65
+ },
66
+ toObject: () => readMerged(),
21
67
  resolve,
22
68
  replaceIn: resolve,
23
69
  };