index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. "use strict";
  2. var __spreadArrays = (this && this.__spreadArrays) || function () {
  3. for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
  4. for (var r = Array(s), k = 0, i = 0; i < il; i++)
  5. for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
  6. r[k] = a[j];
  7. return r;
  8. };
  9. Object.defineProperty(exports, "__esModule", { value: true });
  10. exports.Checker = exports.createCheckers = void 0;
  11. var types_1 = require("./types");
  12. var util_1 = require("./util");
  13. /**
  14. * Export functions used to define interfaces.
  15. */
  16. var types_2 = require("./types");
  17. Object.defineProperty(exports, "TArray", { enumerable: true, get: function () { return types_2.TArray; } });
  18. Object.defineProperty(exports, "TEnumType", { enumerable: true, get: function () { return types_2.TEnumType; } });
  19. Object.defineProperty(exports, "TEnumLiteral", { enumerable: true, get: function () { return types_2.TEnumLiteral; } });
  20. Object.defineProperty(exports, "TFunc", { enumerable: true, get: function () { return types_2.TFunc; } });
  21. Object.defineProperty(exports, "TIface", { enumerable: true, get: function () { return types_2.TIface; } });
  22. Object.defineProperty(exports, "TLiteral", { enumerable: true, get: function () { return types_2.TLiteral; } });
  23. Object.defineProperty(exports, "TName", { enumerable: true, get: function () { return types_2.TName; } });
  24. Object.defineProperty(exports, "TOptional", { enumerable: true, get: function () { return types_2.TOptional; } });
  25. Object.defineProperty(exports, "TParam", { enumerable: true, get: function () { return types_2.TParam; } });
  26. Object.defineProperty(exports, "TParamList", { enumerable: true, get: function () { return types_2.TParamList; } });
  27. Object.defineProperty(exports, "TProp", { enumerable: true, get: function () { return types_2.TProp; } });
  28. Object.defineProperty(exports, "TTuple", { enumerable: true, get: function () { return types_2.TTuple; } });
  29. Object.defineProperty(exports, "TType", { enumerable: true, get: function () { return types_2.TType; } });
  30. Object.defineProperty(exports, "TUnion", { enumerable: true, get: function () { return types_2.TUnion; } });
  31. Object.defineProperty(exports, "TIntersection", { enumerable: true, get: function () { return types_2.TIntersection; } });
  32. Object.defineProperty(exports, "array", { enumerable: true, get: function () { return types_2.array; } });
  33. Object.defineProperty(exports, "enumlit", { enumerable: true, get: function () { return types_2.enumlit; } });
  34. Object.defineProperty(exports, "enumtype", { enumerable: true, get: function () { return types_2.enumtype; } });
  35. Object.defineProperty(exports, "func", { enumerable: true, get: function () { return types_2.func; } });
  36. Object.defineProperty(exports, "iface", { enumerable: true, get: function () { return types_2.iface; } });
  37. Object.defineProperty(exports, "lit", { enumerable: true, get: function () { return types_2.lit; } });
  38. Object.defineProperty(exports, "name", { enumerable: true, get: function () { return types_2.name; } });
  39. Object.defineProperty(exports, "opt", { enumerable: true, get: function () { return types_2.opt; } });
  40. Object.defineProperty(exports, "param", { enumerable: true, get: function () { return types_2.param; } });
  41. Object.defineProperty(exports, "tuple", { enumerable: true, get: function () { return types_2.tuple; } });
  42. Object.defineProperty(exports, "union", { enumerable: true, get: function () { return types_2.union; } });
  43. Object.defineProperty(exports, "intersection", { enumerable: true, get: function () { return types_2.intersection; } });
  44. Object.defineProperty(exports, "BasicType", { enumerable: true, get: function () { return types_2.BasicType; } });
  45. var util_2 = require("./util");
  46. Object.defineProperty(exports, "VError", { enumerable: true, get: function () { return util_2.VError; } });
  47. /**
  48. * Takes one of more type suites (e.g. a module generated by `ts-interface-builder`), and combines
  49. * them into a suite of interface checkers. If a type is used by name, that name should be present
  50. * among the passed-in type suites.
  51. *
  52. * The returned object maps type names to Checker objects.
  53. */
  54. function createCheckers() {
  55. var typeSuite = [];
  56. for (var _i = 0; _i < arguments.length; _i++) {
  57. typeSuite[_i] = arguments[_i];
  58. }
  59. var fullSuite = Object.assign.apply(Object, __spreadArrays([{}, types_1.basicTypes], typeSuite));
  60. var checkers = {};
  61. for (var _a = 0, typeSuite_1 = typeSuite; _a < typeSuite_1.length; _a++) {
  62. var suite_1 = typeSuite_1[_a];
  63. for (var _b = 0, _c = Object.keys(suite_1); _b < _c.length; _b++) {
  64. var name = _c[_b];
  65. checkers[name] = new Checker(fullSuite, suite_1[name]);
  66. }
  67. }
  68. return checkers;
  69. }
  70. exports.createCheckers = createCheckers;
  71. /**
  72. * Checker implements validation of objects, and also includes accessors to validate method calls.
  73. * Checkers should be created using `createCheckers()`.
  74. */
  75. var Checker = /** @class */ (function () {
  76. // Create checkers by using `createCheckers()` function.
  77. function Checker(suite, ttype, _path) {
  78. if (_path === void 0) { _path = 'value'; }
  79. this.suite = suite;
  80. this.ttype = ttype;
  81. this._path = _path;
  82. this.props = new Map();
  83. if (ttype instanceof types_1.TIface) {
  84. for (var _i = 0, _a = ttype.props; _i < _a.length; _i++) {
  85. var p = _a[_i];
  86. this.props.set(p.name, p.ttype);
  87. }
  88. }
  89. this.checkerPlain = this.ttype.getChecker(suite, false);
  90. this.checkerStrict = this.ttype.getChecker(suite, true);
  91. }
  92. /**
  93. * Set the path to report in errors, instead of the default "value". (E.g. if the Checker is for
  94. * a "person" interface, set path to "person" to report e.g. "person.name is not a string".)
  95. */
  96. Checker.prototype.setReportedPath = function (path) {
  97. this._path = path;
  98. };
  99. /**
  100. * Check that the given value satisfies this checker's type, or throw Error.
  101. */
  102. Checker.prototype.check = function (value) { return this._doCheck(this.checkerPlain, value); };
  103. /**
  104. * A fast check for whether or not the given value satisfies this Checker's type. This returns
  105. * true or false, does not produce an error message, and is fast both on success and on failure.
  106. */
  107. Checker.prototype.test = function (value) {
  108. return this.checkerPlain(value, new util_1.NoopContext());
  109. };
  110. /**
  111. * Returns an error object describing the errors if the given value does not satisfy this
  112. * Checker's type, or null if it does.
  113. */
  114. Checker.prototype.validate = function (value) {
  115. return this._doValidate(this.checkerPlain, value);
  116. };
  117. /**
  118. * Check that the given value satisfies this checker's type strictly. This checks that objects
  119. * and tuples have no extra members. Note that this prevents backward compatibility, so usually
  120. * a plain check() is more appropriate.
  121. */
  122. Checker.prototype.strictCheck = function (value) { return this._doCheck(this.checkerStrict, value); };
  123. /**
  124. * A fast strict check for whether or not the given value satisfies this Checker's type. Returns
  125. * true or false, does not produce an error message, and is fast both on success and on failure.
  126. */
  127. Checker.prototype.strictTest = function (value) {
  128. return this.checkerStrict(value, new util_1.NoopContext());
  129. };
  130. /**
  131. * Returns an error object describing the errors if the given value does not satisfy this
  132. * Checker's type strictly, or null if it does.
  133. */
  134. Checker.prototype.strictValidate = function (value) {
  135. return this._doValidate(this.checkerStrict, value);
  136. };
  137. /**
  138. * If this checker is for an interface, returns a Checker for the type required for the given
  139. * property of this interface.
  140. */
  141. Checker.prototype.getProp = function (prop) {
  142. var ttype = this.props.get(prop);
  143. if (!ttype) {
  144. throw new Error("Type has no property " + prop);
  145. }
  146. return new Checker(this.suite, ttype, this._path + "." + prop);
  147. };
  148. /**
  149. * If this checker is for an interface, returns a Checker for the argument-list required to call
  150. * the given method of this interface. E.g. if this Checker is for the interface:
  151. * interface Foo {
  152. * find(s: string, pos?: number): number;
  153. * }
  154. * Then methodArgs("find").check(...) will succeed for ["foo"] and ["foo", 3], but not for [17].
  155. */
  156. Checker.prototype.methodArgs = function (methodName) {
  157. var tfunc = this._getMethod(methodName);
  158. return new Checker(this.suite, tfunc.paramList);
  159. };
  160. /**
  161. * If this checker is for an interface, returns a Checker for the return value of the given
  162. * method of this interface.
  163. */
  164. Checker.prototype.methodResult = function (methodName) {
  165. var tfunc = this._getMethod(methodName);
  166. return new Checker(this.suite, tfunc.result);
  167. };
  168. /**
  169. * If this checker is for a function, returns a Checker for its argument-list.
  170. */
  171. Checker.prototype.getArgs = function () {
  172. if (!(this.ttype instanceof types_1.TFunc)) {
  173. throw new Error("getArgs() applied to non-function");
  174. }
  175. return new Checker(this.suite, this.ttype.paramList);
  176. };
  177. /**
  178. * If this checker is for a function, returns a Checker for its result.
  179. */
  180. Checker.prototype.getResult = function () {
  181. if (!(this.ttype instanceof types_1.TFunc)) {
  182. throw new Error("getResult() applied to non-function");
  183. }
  184. return new Checker(this.suite, this.ttype.result);
  185. };
  186. /**
  187. * Return the type for which this is a checker.
  188. */
  189. Checker.prototype.getType = function () {
  190. return this.ttype;
  191. };
  192. /**
  193. * Actual implementation of check() and strictCheck().
  194. */
  195. Checker.prototype._doCheck = function (checkerFunc, value) {
  196. var noopCtx = new util_1.NoopContext();
  197. if (!checkerFunc(value, noopCtx)) {
  198. var detailCtx = new util_1.DetailContext();
  199. checkerFunc(value, detailCtx);
  200. throw detailCtx.getError(this._path);
  201. }
  202. };
  203. Checker.prototype._doValidate = function (checkerFunc, value) {
  204. var noopCtx = new util_1.NoopContext();
  205. if (checkerFunc(value, noopCtx)) {
  206. return null;
  207. }
  208. var detailCtx = new util_1.DetailContext();
  209. checkerFunc(value, detailCtx);
  210. return detailCtx.getErrorDetail(this._path);
  211. };
  212. Checker.prototype._getMethod = function (methodName) {
  213. var ttype = this.props.get(methodName);
  214. if (!ttype) {
  215. throw new Error("Type has no property " + methodName);
  216. }
  217. if (!(ttype instanceof types_1.TFunc)) {
  218. throw new Error("Property " + methodName + " is not a method");
  219. }
  220. return ttype;
  221. };
  222. return Checker;
  223. }());
  224. exports.Checker = Checker;