@typespec/spec-api 0.1.0-dev.0 → 0.1.0-dev.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/expectation.d.ts +8 -5
  3. package/dist/expectation.d.ts.map +1 -1
  4. package/dist/expectation.js +12 -8
  5. package/dist/expectation.js.map +1 -1
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/match-engine.d.ts +58 -0
  11. package/dist/match-engine.d.ts.map +1 -0
  12. package/dist/match-engine.js +156 -0
  13. package/dist/match-engine.js.map +1 -0
  14. package/dist/matchers/datetime.d.ts +8 -0
  15. package/dist/matchers/datetime.d.ts.map +1 -0
  16. package/dist/matchers/datetime.js +47 -0
  17. package/dist/matchers/datetime.js.map +1 -0
  18. package/dist/matchers/index.d.ts +39 -0
  19. package/dist/matchers/index.d.ts.map +1 -0
  20. package/dist/matchers/index.js +36 -0
  21. package/dist/matchers/index.js.map +1 -0
  22. package/dist/matchers/local-url.d.ts +3 -0
  23. package/dist/matchers/local-url.d.ts.map +1 -0
  24. package/dist/matchers/local-url.js +22 -0
  25. package/dist/matchers/local-url.js.map +1 -0
  26. package/dist/request-validations.d.ts +2 -2
  27. package/dist/request-validations.d.ts.map +1 -1
  28. package/dist/request-validations.js +52 -26
  29. package/dist/request-validations.js.map +1 -1
  30. package/dist/response-utils.d.ts +48 -11
  31. package/dist/response-utils.d.ts.map +1 -1
  32. package/dist/response-utils.js +70 -30
  33. package/dist/response-utils.js.map +1 -1
  34. package/dist/types.d.ts +2 -0
  35. package/dist/types.d.ts.map +1 -1
  36. package/package.json +10 -13
  37. package/src/expectation.ts +13 -9
  38. package/src/index.ts +10 -0
  39. package/src/match-engine.ts +221 -0
  40. package/src/matchers/datetime.ts +66 -0
  41. package/src/matchers/index.ts +48 -0
  42. package/src/matchers/local-url.ts +24 -0
  43. package/src/request-validations.ts +74 -31
  44. package/src/response-utils.ts +106 -34
  45. package/src/types.ts +2 -0
  46. package/temp/.tsbuildinfo +1 -1
  47. package/test/match-engine.test.ts +303 -0
  48. package/test/matchers/datetime.test.ts +232 -0
  49. package/test/matchers/local-url.test.ts +82 -0
  50. package/test/matchers/matcher-test-utils.ts +17 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @typespec/spec-api
2
2
 
3
+ ## 0.1.0-alpha.14
4
+
5
+ ### Features
6
+
7
+ - [#10011](https://github.com/microsoft/typespec/pull/10011) Add matcher framework for flexible value comparison in scenarios. `match.dateTime()` enables semantic datetime comparison that handles precision and timezone differences across languages.
8
+
9
+ ### Bug Fixes
10
+
11
+ - [#9995](https://github.com/microsoft/typespec/pull/9995) Remove prettier used for ValidationError message, in validateXmlBodyEquals.
12
+
13
+
14
+ ## 0.1.0-alpha.13
15
+
16
+ ### Bump dependencies
17
+
18
+ - [#9838](https://github.com/microsoft/typespec/pull/9838) Upgrade dependencies
19
+
20
+
3
21
  ## 0.1.0-alpha.12
4
22
 
5
23
  ### Bump dependencies
@@ -1,4 +1,4 @@
1
- import { CollectionFormat, RequestExt } from "./types.js";
1
+ import { CollectionFormat, RequestExt, Resolver, ResolverConfig } from "./types.js";
2
2
  /**
3
3
  * Class containing all the expectations that can be run on the request.
4
4
  */
@@ -53,11 +53,14 @@ export declare class RequestExpectation {
53
53
  */
54
54
  deepEqual(actual: unknown, expected: unknown, message?: string): void;
55
55
  /**
56
- * Expect the body of the request to be semantically equivalent to the provided XML string.
57
- * The XML declaration prefix will automatically be added to expectedBody.
58
- * @param expectedBody expected value of request body.
56
+ * Expect the body of the request to be semantically equivalent to the provided XML.
57
+ * Accepts a plain string or a Resolver (e.g. from `xml\`...\``).
58
+ * When a Resolver with matchers is provided, matcher-aware comparison is used.
59
+ * The XML declaration prefix will automatically be added.
60
+ * @param expectedBody expected XML body as a string or Resolver.
61
+ * @param config resolver config (required when expectedBody is a Resolver).
59
62
  * @throws {ValidationError} if there is an error.
60
63
  */
61
- xmlBodyEquals(expectedBody: string): void;
64
+ xmlBodyEquals(expectedBody: string | Resolver, config?: ResolverConfig): void;
62
65
  }
63
66
  //# sourceMappingURL=expectation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"expectation.d.ts","sourceRoot":"","sources":["../src/expectation.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG1D;;GAEG;AACH,qBAAa,kBAAkB;IACV,OAAO,CAAC,eAAe;gBAAf,eAAe,EAAE,UAAU;IACtD;;;;OAIG;IACI,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI;IAIxE;;;;OAIG;IACI,UAAU,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IAI7D;;;;OAIG;IACI,iBAAiB,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IAIpE;;;OAGG;IACI,SAAS,IAAI,IAAI;IAIxB;;;OAGG;IACI,YAAY,IAAI,IAAI;IAI3B;;;;;OAKG;IACI,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAItE;;;;OAIG;IACI,kBAAkB,CACvB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,EAChC,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,IAAI;IAIP;;;;OAIG;IACI,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,SAA0B,GAAG,IAAI;IAM7F;;;;;OAKG;IACI,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;CAGjD"}
1
+ {"version":3,"file":"expectation.d.ts","sourceRoot":"","sources":["../src/expectation.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGpF;;GAEG;AACH,qBAAa,kBAAkB;IACV,OAAO,CAAC,eAAe;gBAAf,eAAe,EAAE,UAAU;IACtD;;;;OAIG;IACI,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI;IAIxE;;;;OAIG;IACI,UAAU,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IAI7D;;;;OAIG;IACI,iBAAiB,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IAIpE;;;OAGG;IACI,SAAS,IAAI,IAAI;IAIxB;;;OAGG;IACI,YAAY,IAAI,IAAI;IAI3B;;;;;OAKG;IACI,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAItE;;;;OAIG;IACI,kBAAkB,CACvB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,EAChC,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,IAAI;IAIP;;;;OAIG;IACI,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,SAA0B,GAAG,IAAI;IAO7F;;;;;;;;OAQG;IACI,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI;CAGrF"}
@@ -1,4 +1,4 @@
1
- import deepEqual from "deep-equal";
1
+ import { matchValues } from "./match-engine.js";
2
2
  import { validateBodyEmpty, validateBodyEquals, validateBodyNotEmpty, validateCoercedDateBodyEquals, validateHeader, validateQueryParam, validateRawBodyEquals, validateXmlBodyEquals, } from "./request-validations.js";
3
3
  import { ValidationError } from "./validation-error.js";
4
4
  /**
@@ -70,18 +70,22 @@ export class RequestExpectation {
70
70
  * @param expected Expected value
71
71
  */
72
72
  deepEqual(actual, expected, message = "Values not deep equal") {
73
- if (!deepEqual(actual, expected, { strict: true })) {
74
- throw new ValidationError(message, expected, actual);
73
+ const result = matchValues(actual, expected);
74
+ if (!result.pass) {
75
+ throw new ValidationError(`${message}: ${result.message}`, expected, actual);
75
76
  }
76
77
  }
77
78
  /**
78
- * Expect the body of the request to be semantically equivalent to the provided XML string.
79
- * The XML declaration prefix will automatically be added to expectedBody.
80
- * @param expectedBody expected value of request body.
79
+ * Expect the body of the request to be semantically equivalent to the provided XML.
80
+ * Accepts a plain string or a Resolver (e.g. from `xml\`...\``).
81
+ * When a Resolver with matchers is provided, matcher-aware comparison is used.
82
+ * The XML declaration prefix will automatically be added.
83
+ * @param expectedBody expected XML body as a string or Resolver.
84
+ * @param config resolver config (required when expectedBody is a Resolver).
81
85
  * @throws {ValidationError} if there is an error.
82
86
  */
83
- xmlBodyEquals(expectedBody) {
84
- validateXmlBodyEquals(this.originalRequest, expectedBody);
87
+ xmlBodyEquals(expectedBody, config) {
88
+ validateXmlBodyEquals(this.originalRequest, expectedBody, config);
85
89
  }
86
90
  }
87
91
  //# sourceMappingURL=expectation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"expectation.js","sourceRoot":"","sources":["../src/expectation.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD;;GAEG;AACH,MAAM,OAAO,kBAAkB;IACF;IAA3B,YAA2B,eAA2B;QAA3B,oBAAe,GAAf,eAAe,CAAY;IAAG,CAAC;IAC1D;;;;OAIG;IACI,aAAa,CAAC,eAA4C;QAC/D,qBAAqB,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAC/D,CAAC;IAED;;;;OAIG;IACI,UAAU,CAAC,eAAoC;QACpD,kBAAkB,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACI,iBAAiB,CAAC,eAAoC;QAC3D,6BAA6B,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IACvE,CAAC;IAED;;;OAGG;IACI,SAAS;QACd,iBAAiB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACI,YAAY;QACjB,oBAAoB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;OAKG;IACI,cAAc,CAAC,UAAkB,EAAE,aAAqB;QAC7D,cAAc,CAAC,IAAI,CAAC,eAAe,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAClE,CAAC;IAED;;;;OAIG;IACI,kBAAkB,CACvB,SAAiB,EACjB,aAAgC,EAChC,gBAAmC;QAEnC,kBAAkB,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC;IACvF,CAAC;IAED;;;;OAIG;IACI,SAAS,CAAC,MAAe,EAAE,QAAiB,EAAE,OAAO,GAAG,uBAAuB;QACpF,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,eAAe,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACI,aAAa,CAAC,YAAoB;QACvC,qBAAqB,CAAC,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;IAC5D,CAAC;CACF"}
1
+ {"version":3,"file":"expectation.js","sourceRoot":"","sources":["../src/expectation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD;;GAEG;AACH,MAAM,OAAO,kBAAkB;IACF;IAA3B,YAA2B,eAA2B;QAA3B,oBAAe,GAAf,eAAe,CAAY;IAAG,CAAC;IAC1D;;;;OAIG;IACI,aAAa,CAAC,eAA4C;QAC/D,qBAAqB,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAC/D,CAAC;IAED;;;;OAIG;IACI,UAAU,CAAC,eAAoC;QACpD,kBAAkB,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACI,iBAAiB,CAAC,eAAoC;QAC3D,6BAA6B,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IACvE,CAAC;IAED;;;OAGG;IACI,SAAS;QACd,iBAAiB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACI,YAAY;QACjB,oBAAoB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;OAKG;IACI,cAAc,CAAC,UAAkB,EAAE,aAAqB;QAC7D,cAAc,CAAC,IAAI,CAAC,eAAe,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAClE,CAAC;IAED;;;;OAIG;IACI,kBAAkB,CACvB,SAAiB,EACjB,aAAgC,EAChC,gBAAmC;QAEnC,kBAAkB,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC;IACvF,CAAC;IAED;;;;OAIG;IACI,SAAS,CAAC,MAAe,EAAE,QAAiB,EAAE,OAAO,GAAG,uBAAuB;QACpF,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,eAAe,CAAC,GAAG,OAAO,KAAK,MAAM,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACI,aAAa,CAAC,YAA+B,EAAE,MAAuB;QAC3E,qBAAqB,CAAC,IAAI,CAAC,eAAe,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC;CACF"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export { createMatcher, err, isMatcher, match, matchValues, ok, type MatchResult, type MockValueMatcher, } from "./matchers/index.js";
1
2
  export { MockRequest } from "./mock-request.js";
2
3
  export { BODY_EMPTY_ERROR_MESSAGE, BODY_NOT_EMPTY_ERROR_MESSAGE, BODY_NOT_EQUAL_ERROR_MESSAGE, validateBodyEmpty, validateBodyEquals, validateBodyNotEmpty, validateCoercedDateBodyEquals, validateHeader, validateQueryParam, validateRawBodyEquals, validateValueFormat, validateXmlBodyEquals, } from "./request-validations.js";
3
4
  export { dyn, dynItem, expandDyns, json, multipart, xml } from "./response-utils.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,4BAA4B,EAC5B,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EACL,sBAAsB,EACtB,UAAU,EACV,aAAa,EACb,QAAQ,EACR,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,gBAAgB,EAChB,IAAI,EACJ,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,QAAQ,EACR,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,GAAG,EACH,SAAS,EACT,KAAK,EACL,WAAW,EACX,EAAE,EACF,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,4BAA4B,EAC5B,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EACL,sBAAsB,EACtB,UAAU,EACV,aAAa,EACb,QAAQ,EACR,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,gBAAgB,EAChB,IAAI,EACJ,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,QAAQ,EACR,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { createMatcher, err, isMatcher, match, matchValues, ok, } from "./matchers/index.js";
1
2
  export { MockRequest } from "./mock-request.js";
2
3
  export { BODY_EMPTY_ERROR_MESSAGE, BODY_NOT_EMPTY_ERROR_MESSAGE, BODY_NOT_EQUAL_ERROR_MESSAGE, validateBodyEmpty, validateBodyEquals, validateBodyNotEmpty, validateCoercedDateBodyEquals, validateHeader, validateQueryParam, validateRawBodyEquals, validateValueFormat, validateXmlBodyEquals, } from "./request-validations.js";
3
4
  export { dyn, dynItem, expandDyns, json, multipart, xml } from "./response-utils.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,4BAA4B,EAC5B,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAEL,UAAU,EACV,aAAa,EACb,QAAQ,EACR,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,IAAI,GAmBL,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,GAAG,EACH,SAAS,EACT,KAAK,EACL,WAAW,EACX,EAAE,GAGH,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,4BAA4B,EAC5B,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAEL,UAAU,EACV,aAAa,EACb,QAAQ,EACR,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,IAAI,GAmBL,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Matcher framework for Spector mock API validation.
3
+ *
4
+ * Matchers are special objects that can be placed anywhere in an expected value tree.
5
+ * The comparison engine recognizes them and delegates to `matcher.check(actual)`
6
+ * instead of doing strict equality — enabling flexible comparisons for types like
7
+ * datetime that serialize differently across languages.
8
+ */
9
+ /** Symbol used to identify matcher objects */
10
+ export declare const MatcherSymbol: unique symbol;
11
+ /** Result of a match operation */
12
+ export type MatchResult = {
13
+ pass: true;
14
+ } | {
15
+ pass: false;
16
+ message: string;
17
+ };
18
+ /** Create a passing match result */
19
+ export declare function ok(): MatchResult;
20
+ /** Create a failing match result with a message */
21
+ export declare function err(message: string): MatchResult;
22
+ /**
23
+ * Interface for custom value matchers.
24
+ * Implement this to create new matcher types.
25
+ */
26
+ export interface MockValueMatcher<T = unknown> {
27
+ readonly [MatcherSymbol]: true;
28
+ /** Check whether the actual value matches the expectation */
29
+ check(actual: unknown, config?: MatcherConfig): MatchResult;
30
+ /** The raw value to use when serializing */
31
+ serialize(config?: MatcherConfig): T;
32
+ /** Human-readable description for debugging */
33
+ toString(): string;
34
+ }
35
+ /** Configuration available to matchers at runtime */
36
+ export interface MatcherConfig {
37
+ baseUrl: string;
38
+ }
39
+ interface MatcherImpl<T> {
40
+ check(actual: unknown): MatchResult;
41
+ serialize(): T;
42
+ toString?: () => string;
43
+ }
44
+ /** Create a MockValueMatcher with the MatcherSymbol already set.
45
+ * Accepts either a plain implementation object (for matchers that don't need config)
46
+ * or a factory function `(config) => impl` (for matchers that do).
47
+ */
48
+ export declare function createMatcher<T = unknown>(implOrFactory: MatcherImpl<T> | ((config: MatcherConfig) => MatcherImpl<T>)): MockValueMatcher<T>;
49
+ /** Type guard to check if a value is a MockValueMatcher */
50
+ export declare function isMatcher(value: unknown): value is MockValueMatcher;
51
+ /**
52
+ * Recursively compares actual vs expected values.
53
+ * When a MockValueMatcher is encountered in the expected tree, delegates to matcher.check().
54
+ * Otherwise uses strict equality semantics (same as deep-equal with strict: true).
55
+ */
56
+ export declare function matchValues(actual: unknown, expected: unknown, path?: string, config?: MatcherConfig): MatchResult;
57
+ export {};
58
+ //# sourceMappingURL=match-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-engine.d.ts","sourceRoot":"","sources":["../src/match-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,8CAA8C;AAC9C,eAAO,MAAM,aAAa,EAAE,OAAO,MAAqC,CAAC;AAEzE,kCAAkC;AAClC,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAI5E,oCAAoC;AACpC,wBAAgB,EAAE,IAAI,WAAW,CAEhC;AAED,mDAAmD;AACnD,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAEhD;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO;IAC3C,QAAQ,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC;IAC/B,6DAA6D;IAC7D,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,WAAW,CAAC;IAC5D,4CAA4C;IAC5C,SAAS,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,CAAC,CAAC;IAGrC,+CAA+C;IAC/C,QAAQ,IAAI,MAAM,CAAC;CACpB;AAED,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,UAAU,WAAW,CAAC,CAAC;IACrB,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,WAAW,CAAC;IACpC,SAAS,IAAI,CAAC,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EACvC,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,GAC1E,gBAAgB,CAAC,CAAC,CAAC,CAqBrB;AAED,2DAA2D;AAC3D,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAOnE;AAiBD;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,OAAO,EACjB,IAAI,GAAE,MAAY,EAClB,MAAM,GAAE,aAA2B,GAClC,WAAW,CAoGb"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Matcher framework for Spector mock API validation.
3
+ *
4
+ * Matchers are special objects that can be placed anywhere in an expected value tree.
5
+ * The comparison engine recognizes them and delegates to `matcher.check(actual)`
6
+ * instead of doing strict equality — enabling flexible comparisons for types like
7
+ * datetime that serialize differently across languages.
8
+ */
9
+ /** Symbol used to identify matcher objects */
10
+ export const MatcherSymbol = Symbol.for("SpectorMatcher");
11
+ const OK = Object.freeze({ pass: true });
12
+ /** Create a passing match result */
13
+ export function ok() {
14
+ return OK;
15
+ }
16
+ /** Create a failing match result with a message */
17
+ export function err(message) {
18
+ return { pass: false, message };
19
+ }
20
+ const emptyConfig = { baseUrl: "" };
21
+ /** Create a MockValueMatcher with the MatcherSymbol already set.
22
+ * Accepts either a plain implementation object (for matchers that don't need config)
23
+ * or a factory function `(config) => impl` (for matchers that do).
24
+ */
25
+ export function createMatcher(implOrFactory) {
26
+ const resolve = typeof implOrFactory === "function"
27
+ ? (config) => implOrFactory(config)
28
+ : () => implOrFactory;
29
+ return {
30
+ [MatcherSymbol]: true,
31
+ check(actual, config) {
32
+ return resolve(config ?? emptyConfig).check(actual);
33
+ },
34
+ serialize(config) {
35
+ return resolve(config ?? emptyConfig).serialize();
36
+ },
37
+ toJSON() {
38
+ return resolve(emptyConfig).serialize();
39
+ },
40
+ toString() {
41
+ const impl = resolve(emptyConfig);
42
+ return impl.toString?.() ?? String(impl.serialize());
43
+ },
44
+ };
45
+ }
46
+ /** Type guard to check if a value is a MockValueMatcher */
47
+ export function isMatcher(value) {
48
+ return (typeof value === "object" &&
49
+ value !== null &&
50
+ MatcherSymbol in value &&
51
+ value[MatcherSymbol] === true);
52
+ }
53
+ function formatValue(value) {
54
+ if (value === null)
55
+ return "null";
56
+ if (value === undefined)
57
+ return "undefined";
58
+ if (typeof value === "string")
59
+ return `"${value}"`;
60
+ if (Buffer.isBuffer(value))
61
+ return `Buffer(${value.length})`;
62
+ if (Array.isArray(value))
63
+ return `Array(${value.length})`;
64
+ if (typeof value === "object")
65
+ return JSON.stringify(value);
66
+ return String(value);
67
+ }
68
+ function pathErr(message, path) {
69
+ const prefix = path ? `at ${path}: ` : "";
70
+ return err(`${prefix}${message}`);
71
+ }
72
+ /**
73
+ * Recursively compares actual vs expected values.
74
+ * When a MockValueMatcher is encountered in the expected tree, delegates to matcher.check().
75
+ * Otherwise uses strict equality semantics (same as deep-equal with strict: true).
76
+ */
77
+ export function matchValues(actual, expected, path = "$", config = emptyConfig) {
78
+ if (expected === actual) {
79
+ return ok();
80
+ }
81
+ if (isMatcher(expected)) {
82
+ const result = expected.check(actual, config);
83
+ if (!result.pass) {
84
+ return pathErr(result.message, path);
85
+ }
86
+ return result;
87
+ }
88
+ if (typeof expected !== typeof actual) {
89
+ return pathErr(`Type mismatch: expected ${typeof expected} but got ${typeof actual} (${formatValue(actual)})`, path);
90
+ }
91
+ if (expected === null || actual === null) {
92
+ return pathErr(`Expected ${formatValue(expected)} but got ${formatValue(actual)}`, path);
93
+ }
94
+ if (Array.isArray(expected)) {
95
+ if (!Array.isArray(actual)) {
96
+ return pathErr(`Expected an array but got ${formatValue(actual)}`, path);
97
+ }
98
+ if (expected.length !== actual.length) {
99
+ return pathErr(`Array length mismatch: expected ${expected.length} but got ${actual.length}`, path);
100
+ }
101
+ for (let i = 0; i < expected.length; i++) {
102
+ const result = matchValues(actual[i], expected[i], `${path}[${i}]`, config);
103
+ if (!result.pass) {
104
+ return result;
105
+ }
106
+ }
107
+ return ok();
108
+ }
109
+ if (Buffer.isBuffer(expected)) {
110
+ if (!Buffer.isBuffer(actual)) {
111
+ return pathErr(`Expected a Buffer but got ${typeof actual}`, path);
112
+ }
113
+ if (!expected.equals(actual)) {
114
+ return pathErr(`Buffer contents differ`, path);
115
+ }
116
+ return ok();
117
+ }
118
+ if (typeof expected === "object") {
119
+ const expectedObj = expected;
120
+ const actualObj = actual;
121
+ // Keys with undefined values in expected mean "must not be present in actual"
122
+ const expectedPresentKeys = Object.keys(expectedObj).filter((k) => expectedObj[k] !== undefined);
123
+ const expectedAbsentKeys = Object.keys(expectedObj).filter((k) => expectedObj[k] === undefined);
124
+ const actualKeys = Object.keys(actualObj);
125
+ // Verify keys that should be absent are not in actual
126
+ for (const key of expectedAbsentKeys) {
127
+ if (key in actualObj && actualObj[key] !== undefined) {
128
+ return pathErr(`Key "${key}" should not be present but got ${formatValue(actualObj[key])}`, path);
129
+ }
130
+ }
131
+ if (expectedPresentKeys.length !== actualKeys.length) {
132
+ const missing = expectedPresentKeys.filter((k) => !(k in actualObj));
133
+ const extra = actualKeys.filter((k) => !expectedPresentKeys.includes(k) && !expectedAbsentKeys.includes(k));
134
+ const parts = [
135
+ `Key count mismatch: expected ${expectedPresentKeys.length} but got ${actualKeys.length}`,
136
+ ];
137
+ if (missing.length > 0)
138
+ parts.push(`missing: [${missing.join(", ")}]`);
139
+ if (extra.length > 0)
140
+ parts.push(`extra: [${extra.join(", ")}]`);
141
+ return pathErr(parts.join(". "), path);
142
+ }
143
+ for (const key of expectedPresentKeys) {
144
+ if (!(key in actualObj)) {
145
+ return pathErr(`Missing key "${key}"`, path);
146
+ }
147
+ const result = matchValues(actualObj[key], expectedObj[key], `${path}.${key}`, config);
148
+ if (!result.pass) {
149
+ return result;
150
+ }
151
+ }
152
+ return ok();
153
+ }
154
+ return pathErr(`Expected ${formatValue(expected)} but got ${formatValue(actual)}`, path);
155
+ }
156
+ //# sourceMappingURL=match-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-engine.js","sourceRoot":"","sources":["../src/match-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type MockValueMatcher } from "../match-engine.js";
2
+ export declare const dateTimeMatcher: {
3
+ rfc3339(value: string): MockValueMatcher<string>;
4
+ /** Like rfc3339 but rejects timezone offsets — only Z (UTC) suffix is allowed. */
5
+ utcRfc3339(value: string): MockValueMatcher<string>;
6
+ rfc7231(value: string): MockValueMatcher<string>;
7
+ };
8
+ //# sourceMappingURL=datetime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datetime.d.ts","sourceRoot":"","sources":["../../src/matchers/datetime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,gBAAgB,EAAM,MAAM,oBAAoB,CAAC;AAiDnF,eAAO,MAAM,eAAe;mBACX,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAGhD,kFAAkF;sBAChE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;mBAQpC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;CAGjD,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { createMatcher, err, ok } from "../match-engine.js";
2
+ const rfc3339Pattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/i;
3
+ const utcRfc3339Pattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/i;
4
+ const rfc7231Pattern = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s\d{2}\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT$/i;
5
+ function createDateTimeMatcher(value, label, formatName, formatPattern) {
6
+ const expectedMs = Date.parse(value);
7
+ if (isNaN(expectedMs)) {
8
+ throw new Error(`${label}: invalid datetime value: ${value}`);
9
+ }
10
+ return createMatcher({
11
+ check(actual) {
12
+ if (typeof actual !== "string") {
13
+ return err(`${label}: expected a string but got ${typeof actual} (${JSON.stringify(actual)})`);
14
+ }
15
+ if (!formatPattern.test(actual)) {
16
+ return err(`${label}: expected ${formatName} format but got "${actual}"`);
17
+ }
18
+ const actualMs = Date.parse(actual);
19
+ if (isNaN(actualMs)) {
20
+ return err(`${label}: value "${actual}" matches ${formatName} format but is not a valid date`);
21
+ }
22
+ if (actualMs !== expectedMs) {
23
+ return err(`${label}: timestamps differ \u2014 expected ${new Date(expectedMs).toISOString()} but got ${new Date(actualMs).toISOString()}`);
24
+ }
25
+ return ok();
26
+ },
27
+ serialize() {
28
+ return value;
29
+ },
30
+ toString() {
31
+ return `${label}(${value})`;
32
+ },
33
+ });
34
+ }
35
+ export const dateTimeMatcher = {
36
+ rfc3339(value) {
37
+ return createDateTimeMatcher(value, "match.dateTime.rfc3339", "rfc3339", rfc3339Pattern);
38
+ },
39
+ /** Like rfc3339 but rejects timezone offsets — only Z (UTC) suffix is allowed. */
40
+ utcRfc3339(value) {
41
+ return createDateTimeMatcher(value, "match.dateTime.utcRfc3339", "utcRfc3339", utcRfc3339Pattern);
42
+ },
43
+ rfc7231(value) {
44
+ return createDateTimeMatcher(value, "match.dateTime.rfc7231", "rfc7231", rfc7231Pattern);
45
+ },
46
+ };
47
+ //# sourceMappingURL=datetime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datetime.js","sourceRoot":"","sources":["../../src/matchers/datetime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,GAAG,EAAyB,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAEnF,MAAM,cAAc,GAAG,oEAAoE,CAAC;AAC5F,MAAM,iBAAiB,GAAG,iDAAiD,CAAC;AAC5E,MAAM,cAAc,GAClB,4HAA4H,CAAC;AAE/H,SAAS,qBAAqB,CAC5B,KAAa,EACb,KAAa,EACb,UAAkB,EAClB,aAAqB;IAErB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,6BAA6B,KAAK,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,aAAa,CAAC;QACnB,KAAK,CAAC,MAAe;YACnB,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,OAAO,GAAG,CACR,GAAG,KAAK,+BAA+B,OAAO,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CACnF,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAChC,OAAO,GAAG,CAAC,GAAG,KAAK,cAAc,UAAU,oBAAoB,MAAM,GAAG,CAAC,CAAC;YAC5E,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpB,OAAO,GAAG,CACR,GAAG,KAAK,YAAY,MAAM,aAAa,UAAU,iCAAiC,CACnF,CAAC;YACJ,CAAC;YACD,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;gBAC5B,OAAO,GAAG,CACR,GAAG,KAAK,uCAAuC,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,YAAY,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,EAAE,CAChI,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QACD,SAAS;YACP,OAAO,KAAK,CAAC;QACf,CAAC;QACD,QAAQ;YACN,OAAO,GAAG,KAAK,IAAI,KAAK,GAAG,CAAC;QAC9B,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,OAAO,CAAC,KAAa;QACnB,OAAO,qBAAqB,CAAC,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAC3F,CAAC;IACD,kFAAkF;IAClF,UAAU,CAAC,KAAa;QACtB,OAAO,qBAAqB,CAC1B,KAAK,EACL,2BAA2B,EAC3B,YAAY,EACZ,iBAAiB,CAClB,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,KAAa;QACnB,OAAO,qBAAqB,CAAC,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAC3F,CAAC;CACF,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { baseUrlMatcher } from "./local-url.js";
2
+ export { createMatcher, err, isMatcher, MatcherSymbol, matchValues, ok, type MatcherConfig, type MatchResult, type MockValueMatcher, } from "../match-engine.js";
3
+ export { dateTimeMatcher } from "./datetime.js";
4
+ /**
5
+ * Namespace for built-in matchers.
6
+ */
7
+ export declare const match: {
8
+ /**
9
+ * Matchers for comparing datetime values semantically.
10
+ * Validates that the actual value is in the correct format and represents
11
+ * the same point in time as the expected value.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * match.dateTime.rfc3339("2022-08-26T18:38:00.000Z")
16
+ * match.dateTime.utcRfc3339("2022-08-26T18:38:00.000Z") // rejects offsets, only Z
17
+ * match.dateTime.rfc7231("Fri, 26 Aug 2022 14:38:00 GMT")
18
+ * ```
19
+ */
20
+ dateTime: {
21
+ rfc3339(value: string): import("../match-engine.js").MockValueMatcher<string>;
22
+ utcRfc3339(value: string): import("../match-engine.js").MockValueMatcher<string>;
23
+ rfc7231(value: string): import("../match-engine.js").MockValueMatcher<string>;
24
+ };
25
+ /**
26
+ * Matcher for URL values that include the server's base URL.
27
+ *
28
+ * The matcher is created with just the path portion. At runtime, `expandDyns()`
29
+ * resolves it by injecting the server's actual base URL (e.g. `http://localhost:3000`).
30
+ * The resolved matcher validates that the actual value equals `baseUrl + path`.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * match.localUrl("/payload/pageable/next-page")
35
+ * ```
36
+ */
37
+ localUrl: typeof baseUrlMatcher;
38
+ };
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/matchers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EACL,aAAa,EACb,GAAG,EACH,SAAS,EACT,aAAa,EACb,WAAW,EACX,EAAE,EACF,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,KAAK;IAChB;;;;;;;;;;;OAWG;;;;;;IAGH;;;;;;;;;;;OAWG;;CAEJ,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { dateTimeMatcher } from "./datetime.js";
2
+ import { baseUrlMatcher } from "./local-url.js";
3
+ export { createMatcher, err, isMatcher, MatcherSymbol, matchValues, ok, } from "../match-engine.js";
4
+ export { dateTimeMatcher } from "./datetime.js";
5
+ /**
6
+ * Namespace for built-in matchers.
7
+ */
8
+ export const match = {
9
+ /**
10
+ * Matchers for comparing datetime values semantically.
11
+ * Validates that the actual value is in the correct format and represents
12
+ * the same point in time as the expected value.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * match.dateTime.rfc3339("2022-08-26T18:38:00.000Z")
17
+ * match.dateTime.utcRfc3339("2022-08-26T18:38:00.000Z") // rejects offsets, only Z
18
+ * match.dateTime.rfc7231("Fri, 26 Aug 2022 14:38:00 GMT")
19
+ * ```
20
+ */
21
+ dateTime: dateTimeMatcher,
22
+ /**
23
+ * Matcher for URL values that include the server's base URL.
24
+ *
25
+ * The matcher is created with just the path portion. At runtime, `expandDyns()`
26
+ * resolves it by injecting the server's actual base URL (e.g. `http://localhost:3000`).
27
+ * The resolved matcher validates that the actual value equals `baseUrl + path`.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * match.localUrl("/payload/pageable/next-page")
32
+ * ```
33
+ */
34
+ localUrl: baseUrlMatcher,
35
+ };
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/matchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EACL,aAAa,EACb,GAAG,EACH,SAAS,EACT,aAAa,EACb,WAAW,EACX,EAAE,GAIH,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB;;;;;;;;;;;OAWG;IACH,QAAQ,EAAE,eAAe;IAEzB;;;;;;;;;;;OAWG;IACH,QAAQ,EAAE,cAAc;CACzB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type MockValueMatcher } from "../match-engine.js";
2
+ export declare function baseUrlMatcher(path: string): MockValueMatcher<string>;
3
+ //# sourceMappingURL=local-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-url.d.ts","sourceRoot":"","sources":["../../src/matchers/local-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,gBAAgB,EAAM,MAAM,oBAAoB,CAAC;AAEnF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAqBrE"}
@@ -0,0 +1,22 @@
1
+ import { createMatcher, err, ok } from "../match-engine.js";
2
+ export function baseUrlMatcher(path) {
3
+ return createMatcher((config) => ({
4
+ check(actual) {
5
+ if (typeof actual !== "string") {
6
+ return err(`match.localUrl: expected a string but got ${typeof actual} (${JSON.stringify(actual)})`);
7
+ }
8
+ const expected = config.baseUrl + path;
9
+ if (actual !== expected) {
10
+ return err(`match.localUrl: expected "${expected}" but got "${actual}"`);
11
+ }
12
+ return ok();
13
+ },
14
+ serialize() {
15
+ return config.baseUrl + path;
16
+ },
17
+ toString() {
18
+ return `match.localUrl("${path}")`;
19
+ },
20
+ }));
21
+ }
22
+ //# sourceMappingURL=local-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-url.js","sourceRoot":"","sources":["../../src/matchers/local-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,GAAG,EAAyB,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAEnF,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,aAAa,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAChC,KAAK,CAAC,MAAe;YACnB,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,OAAO,GAAG,CACR,6CAA6C,OAAO,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CACzF,CAAC;YACJ,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;YACvC,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACxB,OAAO,GAAG,CAAC,6BAA6B,QAAQ,cAAc,MAAM,GAAG,CAAC,CAAC;YAC3E,CAAC;YACD,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QACD,SAAS;YACP,OAAO,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;QAC/B,CAAC;QACD,QAAQ;YACN,OAAO,mBAAmB,IAAI,IAAI,CAAC;QACrC,CAAC;KACF,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -1,10 +1,10 @@
1
- import { CollectionFormat, RequestExt } from "./types.js";
1
+ import { CollectionFormat, RequestExt, Resolver, ResolverConfig } from "./types.js";
2
2
  export declare const BODY_NOT_EQUAL_ERROR_MESSAGE = "Body provided doesn't match expected body";
3
3
  export declare const BODY_EMPTY_ERROR_MESSAGE = "Body should exists";
4
4
  export declare const BODY_NOT_EMPTY_ERROR_MESSAGE = "Body should be empty";
5
5
  export declare const validateRawBodyEquals: (request: RequestExt, expectedRawBody: string | Buffer | undefined) => void;
6
6
  export declare const validateBodyEquals: (request: RequestExt, expectedBody: unknown | undefined) => void;
7
- export declare const validateXmlBodyEquals: (request: RequestExt, expectedBody: string) => void;
7
+ export declare const validateXmlBodyEquals: (request: RequestExt, expectedBody: string | Resolver, config?: ResolverConfig) => void;
8
8
  export declare const validateCoercedDateBodyEquals: (request: RequestExt, expectedBody: unknown | undefined) => void;
9
9
  export declare const validateBodyEmpty: (request: RequestExt) => void;
10
10
  export declare const validateBodyNotEmpty: (request: RequestExt) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"request-validations.d.ts","sourceRoot":"","sources":["../src/request-validations.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG1D,eAAO,MAAM,4BAA4B,8CAA8C,CAAC;AACxF,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAC7D,eAAO,MAAM,4BAA4B,yBAAyB,CAAC;AAEnE,eAAO,MAAM,qBAAqB,GAChC,SAAS,UAAU,EACnB,iBAAiB,MAAM,GAAG,MAAM,GAAG,SAAS,KAC3C,IAaF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,SAAS,UAAU,EACnB,cAAc,OAAO,GAAG,SAAS,KAChC,IAWF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,SAAS,UAAU,EAAE,cAAc,MAAM,KAAG,IA8BjF,CAAC;AAEF,eAAO,MAAM,6BAA6B,GACxC,SAAS,UAAU,EACnB,cAAc,OAAO,GAAG,SAAS,KAChC,IAWF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,SAAS,UAAU,KAAG,IAUvD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,SAAS,UAAU,KAAG,IAU1D,CAAC;AAUF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,SAAS,UAAU,EAAE,YAAY,MAAM,EAAE,UAAU,MAAM,KAAG,IAK1F,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC7B,SAAS,UAAU,EACnB,WAAW,MAAM,EACjB,UAAU,MAAM,GAAG,MAAM,EAAE,EAC3B,mBAAmB,gBAAgB,KAClC,IA+BF,CAAC;AAWF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,MAAM,EACb,QAAQ,MAAM,GAAG,SAAS,GAAG,SAAS,KACrC,IAwBF,CAAC"}
1
+ {"version":3,"file":"request-validations.d.ts","sourceRoot":"","sources":["../src/request-validations.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGpF,eAAO,MAAM,4BAA4B,8CAA8C,CAAC;AACxF,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAC7D,eAAO,MAAM,4BAA4B,yBAAyB,CAAC;AAEnE,eAAO,MAAM,qBAAqB,GAChC,SAAS,UAAU,EACnB,iBAAiB,MAAM,GAAG,MAAM,GAAG,SAAS,KAC3C,IAaF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,SAAS,UAAU,EACnB,cAAc,OAAO,GAAG,SAAS,KAChC,IAgBF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,SAAS,UAAU,EACnB,cAAc,MAAM,GAAG,QAAQ,EAC/B,SAAS,cAAc,KACtB,IA2CF,CAAC;AAkBF,eAAO,MAAM,6BAA6B,GACxC,SAAS,UAAU,EACnB,cAAc,OAAO,GAAG,SAAS,KAChC,IAgBF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,SAAS,UAAU,KAAG,IAUvD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,SAAS,UAAU,KAAG,IAU1D,CAAC;AAUF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,SAAS,UAAU,EAAE,YAAY,MAAM,EAAE,UAAU,MAAM,KAAG,IAK1F,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC7B,SAAS,UAAU,EACnB,WAAW,MAAM,EACjB,UAAU,MAAM,GAAG,MAAM,EAAE,EAC3B,mBAAmB,gBAAgB,KAClC,IA+BF,CAAC;AAWF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,MAAM,EACb,QAAQ,MAAM,GAAG,SAAS,GAAG,SAAS,KACrC,IAwBF,CAAC"}