@schmock/cli 2.2.0 → 2.2.1

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 (3) hide show
  1. package/dist/bin.js +45 -28
  2. package/dist/index.js +45 -28
  3. package/package.json +3 -3
package/dist/bin.js CHANGED
@@ -24058,7 +24058,7 @@ async function runPluginPipeline(plugins, context, initialResponse, logger) {
24058
24058
  if (errorResult instanceof Error) {
24059
24059
  throw new PluginError(plugin.name, errorResult);
24060
24060
  }
24061
- if (typeof errorResult === "object" && errorResult !== null && "status" in errorResult) {
24061
+ if (isStatusTuple(errorResult) || typeof errorResult === "object" && errorResult !== null && "status" in errorResult) {
24062
24062
  response = errorResult;
24063
24063
  break;
24064
24064
  }
@@ -24079,7 +24079,7 @@ async function runPluginPipeline(plugins, context, initialResponse, logger) {
24079
24079
 
24080
24080
  // ../core/src/response-parser.ts
24081
24081
  function isResponseObject(value) {
24082
- return typeof value === "object" && value !== null && "status" in value && "body" in value;
24082
+ return typeof value === "object" && value !== null && "status" in value && typeof value.status === "number" && "body" in value;
24083
24083
  }
24084
24084
  function parseResponse(result, routeConfig) {
24085
24085
  let status = 200;
@@ -24201,18 +24201,19 @@ class CallableMockInstance {
24201
24201
  });
24202
24202
  }
24203
24203
  defineRoute(route, generator, config) {
24204
- if (!config.contentType) {
24204
+ const routeConfig = { ...config };
24205
+ if (!routeConfig.contentType) {
24205
24206
  if (typeof generator === "function") {
24206
- config.contentType = "application/json";
24207
+ routeConfig.contentType = "application/json";
24207
24208
  } else if (typeof generator === "string" || typeof generator === "number" || typeof generator === "boolean") {
24208
- config.contentType = "text/plain";
24209
+ routeConfig.contentType = "text/plain";
24209
24210
  } else if (Buffer.isBuffer(generator)) {
24210
- config.contentType = "application/octet-stream";
24211
+ routeConfig.contentType = "application/octet-stream";
24211
24212
  } else {
24212
- config.contentType = "application/json";
24213
+ routeConfig.contentType = "application/json";
24213
24214
  }
24214
24215
  }
24215
- if (typeof generator !== "function" && config.contentType === "application/json") {
24216
+ if (typeof generator !== "function" && routeConfig.contentType === "application/json") {
24216
24217
  try {
24217
24218
  JSON.stringify(generator);
24218
24219
  } catch (_error) {
@@ -24220,7 +24221,8 @@ class CallableMockInstance {
24220
24221
  }
24221
24222
  }
24222
24223
  const parsed = parseRouteKey(route);
24223
- const existing = this.routes.find((r) => r.method === parsed.method && r.path === parsed.path);
24224
+ const normalizedParsedPath = normalizePath(parsed.path);
24225
+ const existing = this.routes.find((r) => r.method === parsed.method && normalizePath(r.path) === normalizedParsedPath);
24224
24226
  if (existing) {
24225
24227
  this.logger.log("warning", `Duplicate route: ${route} — first registration wins`);
24226
24228
  return this;
@@ -24231,7 +24233,7 @@ class CallableMockInstance {
24231
24233
  method: parsed.method,
24232
24234
  path: parsed.path,
24233
24235
  generator,
24234
- config
24236
+ config: routeConfig
24235
24237
  };
24236
24238
  this.routes.push(compiledRoute);
24237
24239
  if (parsed.params.length === 0) {
@@ -24239,7 +24241,7 @@ class CallableMockInstance {
24239
24241
  this.staticRoutes.set(key, compiledRoute);
24240
24242
  }
24241
24243
  this.logger.log("route", `Route defined: ${route}`, {
24242
- contentType: config.contentType,
24244
+ contentType: routeConfig.contentType,
24243
24245
  generatorType: typeof generator,
24244
24246
  hasParams: parsed.params.length > 0
24245
24247
  });
@@ -24261,11 +24263,21 @@ class CallableMockInstance {
24261
24263
  }
24262
24264
  return this;
24263
24265
  }
24266
+ cloneRecord(r) {
24267
+ try {
24268
+ return structuredClone(r);
24269
+ } catch {
24270
+ return {
24271
+ ...r,
24272
+ response: { ...r.response }
24273
+ };
24274
+ }
24275
+ }
24264
24276
  history(method, path) {
24265
24277
  if (method || path) {
24266
- return this.requestHistory.filter((r) => (!method || r.method === method) && (!path || r.path === path));
24278
+ return this.requestHistory.filter((r) => (!method || r.method === method) && (!path || r.path === path)).map((r) => this.cloneRecord(r));
24267
24279
  }
24268
- return [...this.requestHistory];
24280
+ return this.requestHistory.map((r) => this.cloneRecord(r));
24269
24281
  }
24270
24282
  called(method, path) {
24271
24283
  if (method || path) {
@@ -24282,9 +24294,11 @@ class CallableMockInstance {
24282
24294
  lastRequest(method, path) {
24283
24295
  if (method || path) {
24284
24296
  const filtered = this.requestHistory.filter((r) => (!method || r.method === method) && (!path || r.path === path));
24285
- return filtered[filtered.length - 1];
24297
+ const last2 = filtered[filtered.length - 1];
24298
+ return last2 ? this.cloneRecord(last2) : undefined;
24286
24299
  }
24287
- return this.requestHistory[this.requestHistory.length - 1];
24300
+ const last = this.requestHistory[this.requestHistory.length - 1];
24301
+ return last ? this.cloneRecord(last) : undefined;
24288
24302
  }
24289
24303
  getRoutes() {
24290
24304
  return this.routes.map((r) => ({
@@ -24327,9 +24341,7 @@ class CallableMockInstance {
24327
24341
  this.requestHistory = [];
24328
24342
  this.listeners.clear();
24329
24343
  if (this.globalConfig.state) {
24330
- for (const key of Object.keys(this.globalConfig.state)) {
24331
- delete this.globalConfig.state[key];
24332
- }
24344
+ this.globalConfig.state = {};
24333
24345
  }
24334
24346
  this.logger.log("lifecycle", "Mock fully reset");
24335
24347
  }
@@ -24339,9 +24351,7 @@ class CallableMockInstance {
24339
24351
  }
24340
24352
  resetState() {
24341
24353
  if (this.globalConfig.state) {
24342
- for (const key of Object.keys(this.globalConfig.state)) {
24343
- delete this.globalConfig.state[key];
24344
- }
24354
+ this.globalConfig.state = {};
24345
24355
  }
24346
24356
  this.logger.log("lifecycle", "State cleared");
24347
24357
  }
@@ -24607,7 +24617,7 @@ function schmock(config) {
24607
24617
  return callableInstance;
24608
24618
  }
24609
24619
  // ../openapi/package.json
24610
- var version = "2.2.0";
24620
+ var version = "2.2.1";
24611
24621
 
24612
24622
  // ../openapi/src/utils.ts
24613
24623
  function isRecord(value) {
@@ -30221,7 +30231,9 @@ function enhanceSchemaWithSmartMapping(schema) {
30221
30231
  function enhanceFieldSchema(fieldName, fieldSchema) {
30222
30232
  const enhanced = { ...fieldSchema };
30223
30233
  if (enhanced.faker) {
30224
- validateFakerMethod(enhanced.faker);
30234
+ if (typeof enhanced.faker === "string") {
30235
+ validateFakerMethod(enhanced.faker);
30236
+ }
30225
30237
  return enhanced;
30226
30238
  }
30227
30239
  const hasComposition = enhanced.allOf || enhanced.anyOf || enhanced.oneOf;
@@ -30237,12 +30249,17 @@ function enhanceFieldSchema(fieldName, fieldSchema) {
30237
30249
  }
30238
30250
  const match = findBestMapping(fieldName, enhanced);
30239
30251
  if (match) {
30240
- enhanced.faker = match.mapping.fakerMethod;
30241
- if (match.mapping.format) {
30242
- enhanced.format = match.mapping.format;
30252
+ const { fakerMethod, format, trueProbability, fakerArgs } = match.mapping;
30253
+ if (fakerArgs) {
30254
+ enhanced.faker = { [fakerMethod]: [fakerArgs] };
30255
+ } else {
30256
+ enhanced.faker = fakerMethod;
30257
+ }
30258
+ if (format) {
30259
+ enhanced.format = format;
30243
30260
  }
30244
- if (match.mapping.trueProbability !== undefined) {
30245
- enhanced.schmockTrueProbability = match.mapping.trueProbability;
30261
+ if (trueProbability !== undefined) {
30262
+ enhanced.schmockTrueProbability = trueProbability;
30246
30263
  }
30247
30264
  }
30248
30265
  return enhanced;
package/dist/index.js CHANGED
@@ -24057,7 +24057,7 @@ async function runPluginPipeline(plugins, context, initialResponse, logger) {
24057
24057
  if (errorResult instanceof Error) {
24058
24058
  throw new PluginError(plugin.name, errorResult);
24059
24059
  }
24060
- if (typeof errorResult === "object" && errorResult !== null && "status" in errorResult) {
24060
+ if (isStatusTuple(errorResult) || typeof errorResult === "object" && errorResult !== null && "status" in errorResult) {
24061
24061
  response = errorResult;
24062
24062
  break;
24063
24063
  }
@@ -24078,7 +24078,7 @@ async function runPluginPipeline(plugins, context, initialResponse, logger) {
24078
24078
 
24079
24079
  // ../core/src/response-parser.ts
24080
24080
  function isResponseObject(value) {
24081
- return typeof value === "object" && value !== null && "status" in value && "body" in value;
24081
+ return typeof value === "object" && value !== null && "status" in value && typeof value.status === "number" && "body" in value;
24082
24082
  }
24083
24083
  function parseResponse(result, routeConfig) {
24084
24084
  let status = 200;
@@ -24200,18 +24200,19 @@ class CallableMockInstance {
24200
24200
  });
24201
24201
  }
24202
24202
  defineRoute(route, generator, config) {
24203
- if (!config.contentType) {
24203
+ const routeConfig = { ...config };
24204
+ if (!routeConfig.contentType) {
24204
24205
  if (typeof generator === "function") {
24205
- config.contentType = "application/json";
24206
+ routeConfig.contentType = "application/json";
24206
24207
  } else if (typeof generator === "string" || typeof generator === "number" || typeof generator === "boolean") {
24207
- config.contentType = "text/plain";
24208
+ routeConfig.contentType = "text/plain";
24208
24209
  } else if (Buffer.isBuffer(generator)) {
24209
- config.contentType = "application/octet-stream";
24210
+ routeConfig.contentType = "application/octet-stream";
24210
24211
  } else {
24211
- config.contentType = "application/json";
24212
+ routeConfig.contentType = "application/json";
24212
24213
  }
24213
24214
  }
24214
- if (typeof generator !== "function" && config.contentType === "application/json") {
24215
+ if (typeof generator !== "function" && routeConfig.contentType === "application/json") {
24215
24216
  try {
24216
24217
  JSON.stringify(generator);
24217
24218
  } catch (_error) {
@@ -24219,7 +24220,8 @@ class CallableMockInstance {
24219
24220
  }
24220
24221
  }
24221
24222
  const parsed = parseRouteKey(route);
24222
- const existing = this.routes.find((r) => r.method === parsed.method && r.path === parsed.path);
24223
+ const normalizedParsedPath = normalizePath(parsed.path);
24224
+ const existing = this.routes.find((r) => r.method === parsed.method && normalizePath(r.path) === normalizedParsedPath);
24223
24225
  if (existing) {
24224
24226
  this.logger.log("warning", `Duplicate route: ${route} — first registration wins`);
24225
24227
  return this;
@@ -24230,7 +24232,7 @@ class CallableMockInstance {
24230
24232
  method: parsed.method,
24231
24233
  path: parsed.path,
24232
24234
  generator,
24233
- config
24235
+ config: routeConfig
24234
24236
  };
24235
24237
  this.routes.push(compiledRoute);
24236
24238
  if (parsed.params.length === 0) {
@@ -24238,7 +24240,7 @@ class CallableMockInstance {
24238
24240
  this.staticRoutes.set(key, compiledRoute);
24239
24241
  }
24240
24242
  this.logger.log("route", `Route defined: ${route}`, {
24241
- contentType: config.contentType,
24243
+ contentType: routeConfig.contentType,
24242
24244
  generatorType: typeof generator,
24243
24245
  hasParams: parsed.params.length > 0
24244
24246
  });
@@ -24260,11 +24262,21 @@ class CallableMockInstance {
24260
24262
  }
24261
24263
  return this;
24262
24264
  }
24265
+ cloneRecord(r) {
24266
+ try {
24267
+ return structuredClone(r);
24268
+ } catch {
24269
+ return {
24270
+ ...r,
24271
+ response: { ...r.response }
24272
+ };
24273
+ }
24274
+ }
24263
24275
  history(method, path) {
24264
24276
  if (method || path) {
24265
- return this.requestHistory.filter((r) => (!method || r.method === method) && (!path || r.path === path));
24277
+ return this.requestHistory.filter((r) => (!method || r.method === method) && (!path || r.path === path)).map((r) => this.cloneRecord(r));
24266
24278
  }
24267
- return [...this.requestHistory];
24279
+ return this.requestHistory.map((r) => this.cloneRecord(r));
24268
24280
  }
24269
24281
  called(method, path) {
24270
24282
  if (method || path) {
@@ -24281,9 +24293,11 @@ class CallableMockInstance {
24281
24293
  lastRequest(method, path) {
24282
24294
  if (method || path) {
24283
24295
  const filtered = this.requestHistory.filter((r) => (!method || r.method === method) && (!path || r.path === path));
24284
- return filtered[filtered.length - 1];
24296
+ const last2 = filtered[filtered.length - 1];
24297
+ return last2 ? this.cloneRecord(last2) : undefined;
24285
24298
  }
24286
- return this.requestHistory[this.requestHistory.length - 1];
24299
+ const last = this.requestHistory[this.requestHistory.length - 1];
24300
+ return last ? this.cloneRecord(last) : undefined;
24287
24301
  }
24288
24302
  getRoutes() {
24289
24303
  return this.routes.map((r) => ({
@@ -24326,9 +24340,7 @@ class CallableMockInstance {
24326
24340
  this.requestHistory = [];
24327
24341
  this.listeners.clear();
24328
24342
  if (this.globalConfig.state) {
24329
- for (const key of Object.keys(this.globalConfig.state)) {
24330
- delete this.globalConfig.state[key];
24331
- }
24343
+ this.globalConfig.state = {};
24332
24344
  }
24333
24345
  this.logger.log("lifecycle", "Mock fully reset");
24334
24346
  }
@@ -24338,9 +24350,7 @@ class CallableMockInstance {
24338
24350
  }
24339
24351
  resetState() {
24340
24352
  if (this.globalConfig.state) {
24341
- for (const key of Object.keys(this.globalConfig.state)) {
24342
- delete this.globalConfig.state[key];
24343
- }
24353
+ this.globalConfig.state = {};
24344
24354
  }
24345
24355
  this.logger.log("lifecycle", "State cleared");
24346
24356
  }
@@ -24606,7 +24616,7 @@ function schmock(config) {
24606
24616
  return callableInstance;
24607
24617
  }
24608
24618
  // ../openapi/package.json
24609
- var version = "2.2.0";
24619
+ var version = "2.2.1";
24610
24620
 
24611
24621
  // ../openapi/src/utils.ts
24612
24622
  function isRecord(value) {
@@ -30220,7 +30230,9 @@ function enhanceSchemaWithSmartMapping(schema) {
30220
30230
  function enhanceFieldSchema(fieldName, fieldSchema) {
30221
30231
  const enhanced = { ...fieldSchema };
30222
30232
  if (enhanced.faker) {
30223
- validateFakerMethod(enhanced.faker);
30233
+ if (typeof enhanced.faker === "string") {
30234
+ validateFakerMethod(enhanced.faker);
30235
+ }
30224
30236
  return enhanced;
30225
30237
  }
30226
30238
  const hasComposition = enhanced.allOf || enhanced.anyOf || enhanced.oneOf;
@@ -30236,12 +30248,17 @@ function enhanceFieldSchema(fieldName, fieldSchema) {
30236
30248
  }
30237
30249
  const match = findBestMapping(fieldName, enhanced);
30238
30250
  if (match) {
30239
- enhanced.faker = match.mapping.fakerMethod;
30240
- if (match.mapping.format) {
30241
- enhanced.format = match.mapping.format;
30251
+ const { fakerMethod, format, trueProbability, fakerArgs } = match.mapping;
30252
+ if (fakerArgs) {
30253
+ enhanced.faker = { [fakerMethod]: [fakerArgs] };
30254
+ } else {
30255
+ enhanced.faker = fakerMethod;
30256
+ }
30257
+ if (format) {
30258
+ enhanced.format = format;
30242
30259
  }
30243
- if (match.mapping.trueProbability !== undefined) {
30244
- enhanced.schmockTrueProbability = match.mapping.trueProbability;
30260
+ if (trueProbability !== undefined) {
30261
+ enhanced.schmockTrueProbability = trueProbability;
30245
30262
  }
30246
30263
  }
30247
30264
  return enhanced;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@schmock/cli",
3
3
  "description": "CLI for running Schmock mock servers from OpenAPI specs",
4
- "version": "2.2.0",
4
+ "version": "2.2.1",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -32,8 +32,8 @@
32
32
  },
33
33
  "license": "MIT",
34
34
  "dependencies": {
35
- "@schmock/core": "^2.2.0",
36
- "@schmock/openapi": "^2.2.0"
35
+ "@schmock/core": "^2.2.1",
36
+ "@schmock/openapi": "^2.2.1"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@amiceli/vitest-cucumber": "^6.5.0",