@jakobkg/shapes-ts 0.3.1 → 0.4.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.
package/README.md CHANGED
@@ -6,7 +6,7 @@ When describing the shape of your data in shapes-ts, you get the corresponding
6
6
  TS type and a validation utility for free!
7
7
 
8
8
  ```typescript
9
- const CreditCategory = Shapes.enum(["director", "writer", "actor/actress"])
9
+ const CreditCategory = Shapes.enum(["director", "writer", "actor/actress"]);
10
10
 
11
11
  const Credits = Shapes.object({
12
12
  category: CreditCategory,
@@ -41,8 +41,8 @@ if (!Movie.check(movieData)) {
41
41
 
42
42
  // Past this point, movieData is typed as Movie
43
43
 
44
- for (const member of movieData.cast) {
45
- console.log(`${member.actor} as ${member.role}`);
44
+ for (const credit of movieData.credits) {
45
+ console.log(`${credit.name}: ${credit.category}`);
46
46
  }
47
47
  ```
48
48
 
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * as Shapes from "./shapes";
2
+ export { type Shape } from "./shapes";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/shapes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/shapes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC"}
package/dist/shapes.d.ts CHANGED
@@ -7,11 +7,13 @@ declare const AllowUnknownProperties: unique symbol;
7
7
  export type Type<T> = T extends Shape<infer U> ? U : never;
8
8
  type ShapePredicate<T> = {
9
9
  predicate: (x: T) => boolean;
10
- description: string | undefined;
10
+ description?: string | undefined;
11
11
  };
12
- interface Shape<T> {
12
+ export type Shape<T> = {
13
13
  readonly typename: string;
14
14
  readonly [Predicates]: ShapePredicate<T>[];
15
+ readonly [Properties]?: Record<string, Shape<T>>;
16
+ readonly [AllowUnknownProperties]?: boolean;
15
17
  check(x: unknown): x is T;
16
18
  /**
17
19
  * Adds a custom validation predicate to the shape
@@ -19,15 +21,11 @@ interface Shape<T> {
19
21
  * @param description Optional description of the constraint for error messages
20
22
  * @returns A new shape with the additional validation
21
23
  */
22
- where(predicate: (x: T) => boolean, description: string | undefined): Shape<T>;
24
+ where(predicate: (x: T) => boolean, description?: string | undefined): Shape<T>;
23
25
  and<U>(other: Shape<U>): Shape<T & U>;
24
26
  or<U>(other: Shape<U>): Shape<T | U>;
25
- }
26
- interface ObjectShape<T = Record<string, unknown>> extends Shape<T> {
27
- readonly [Properties]: Record<string, Shape<T>>;
28
- readonly [AllowUnknownProperties]?: boolean;
29
- }
30
- interface ObjectShapeOptions {
27
+ };
28
+ interface ObjectOptions {
31
29
  readonly allowUnknownProperties?: boolean;
32
30
  readonly additionalPermittedProperties?: Record<string, Shape<Record<string, unknown>>>;
33
31
  }
@@ -78,7 +76,10 @@ export declare function array<T>(shape: Shape<T>): Shape<T[]>;
78
76
  * });
79
77
  * ```
80
78
  */
81
- export declare function object<T extends Record<string, Shape<any>>>(properties: T, options?: ObjectShapeOptions): ObjectShape<{
79
+ export declare function object<T extends Record<string, Shape<any>>>(typename: string, properties: T, options?: ObjectOptions | undefined): Shape<{
80
+ [K in keyof T]: Type<T[K]>;
81
+ }>;
82
+ export declare function object<T extends Record<string, Shape<any>>>(properties: T, options?: ObjectOptions | undefined): Shape<{
82
83
  [K in keyof T]: Type<T[K]>;
83
84
  }>;
84
85
  /**
@@ -87,12 +88,12 @@ export declare function object<T extends Record<string, Shape<any>>>(properties:
87
88
  * Shapes.tuple([Shapes.number(), Shape.string()]) is equivalent to TS type [number, string]
88
89
  * Shapes.tuple([Shapes.number()], Shapes.string()) is equivalent to TS type [number, ...string]
89
90
  */
90
- export declare function tuple<Shapes extends Shape<any>[], Partial extends {
91
+ export declare function tuple<Shapes extends Shape<any>[], Elements extends {
91
92
  [K in keyof Shapes]: Type<Shapes[K]>;
92
- }, Tuple extends RestShape extends Shape<infer Rest> ? [...Partial, ...Rest[]] : [...Partial], RestShape extends Shape<any> | undefined = undefined>(shapes: [...Shapes], rest?: RestShape): Shape<Tuple>;
93
+ }, Tuple extends RestShape extends Shape<infer Rest> ? [...Elements, ...Rest[]] : [...Elements], RestShape extends Shape<any> | undefined = undefined>(shapes: [...Shapes], rest?: RestShape): Shape<Tuple>;
93
94
  export { enumOf as enum };
94
95
  /**
95
- * Creates a shape representing an enum type
96
+ * Creates a shape representing an enum type.
96
97
  * (Not an actual enum as made using the enum keyword)
97
98
  *
98
99
  * `Shapes.enum(["a", "b", "c"])` is equivalent to `"a" | "b" | "c"`
@@ -1 +1 @@
1
- {"version":3,"file":"shapes.d.ts","sourceRoot":"","sources":["../src/shapes/shapes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shapes.d.ts","sourceRoot":"","sources":["../src/shapes/shapes.ts"],"names":[],"mappings":"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"}
package/dist/shapes.js CHANGED
@@ -56,46 +56,34 @@ function isBoolean(input) {
56
56
  function isUndefined(input) {
57
57
  return input === undefined;
58
58
  }
59
- function makeUnion(left, right) {
60
- var _a;
61
- return _a = {
62
- typename: "".concat(left.typename, " | ").concat(right.typename)
63
- },
64
- _a[Predicates] = [],
65
- _a.where = function (predicate, description) {
66
- var _a;
67
- return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
68
- },
69
- _a.check = function (x) {
70
- return (left.check(x) || right.check(x)) &&
71
- this[Predicates].every(function (p) { return p.predicate(x); });
72
- },
73
- _a.and = function (other) {
74
- return makeIntersection(this, other);
75
- },
76
- _a.or = function (other) {
77
- return makeUnion(this, other);
78
- },
79
- _a;
59
+ /// HELLA UTILS
60
+ function tryPredicates(self, input) {
61
+ return self[Predicates].every(function (p) {
62
+ try {
63
+ return p.predicate(input);
64
+ }
65
+ catch (_) {
66
+ return false;
67
+ }
68
+ });
80
69
  }
81
- function makeIntersection(left, right) {
70
+ /// PRIMITIVE SHAPE FACTORIES
71
+ /**
72
+ * Creates a base object that implements the most basic shared logic for all shapes
73
+ *
74
+ * `.typename` and `.check(x)` on the returned object are stubs and should be overwritten
75
+ */
76
+ function base() {
82
77
  var _a;
83
78
  return _a = {
84
- typename: "".concat(left.typename, " & ").concat(right.typename)
79
+ typename: "",
80
+ check: function (_) { return false; }
85
81
  },
86
82
  _a[Predicates] = [],
87
83
  _a.where = function (predicate, description) {
88
84
  var _a;
89
85
  return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
90
86
  },
91
- _a.check = function (x) {
92
- var _a, _b;
93
- // Trickery: combine permitted properties of left and right
94
- var tolerantLeft = __assign(__assign({}, left), (_a = {}, _a[Properties] = __assign(__assign({}, right[Properties]), left[Properties]), _a));
95
- var tolerantRight = __assign(__assign({}, right), (_b = {}, _b[Properties] = __assign(__assign({}, left[Properties]), right[Properties]), _b));
96
- return tolerantLeft.check(x) && tolerantRight.check(x) &&
97
- this[Predicates].every(function (p) { return p.predicate(x); });
98
- },
99
87
  _a.and = function (other) {
100
88
  return makeIntersection(this, other);
101
89
  },
@@ -104,79 +92,29 @@ function makeIntersection(left, right) {
104
92
  },
105
93
  _a;
106
94
  }
107
- /// PRIMITIVE SHAPE FACTORIES
95
+ function makePrimitive(name, guard) {
96
+ return __assign(__assign({}, base()), { typename: name, check: function (x) {
97
+ return guard(x) && tryPredicates(this, x);
98
+ } });
99
+ }
108
100
  /**
109
101
  * Creates a shape representing a JS `number`.
110
102
  * Does not support BigInt.
111
103
  */
112
104
  function number() {
113
- var _a;
114
- return _a = {
115
- typename: "number"
116
- },
117
- _a[Predicates] = [],
118
- _a.check = function (x) {
119
- return isNumber(x) && this[Predicates].every(function (p) { return p.predicate(x); });
120
- },
121
- _a.where = function (predicate, description) {
122
- var _a;
123
- return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
124
- },
125
- _a.and = function (other) {
126
- return makeIntersection(this, other);
127
- },
128
- _a.or = function (other) {
129
- return makeUnion(this, other);
130
- },
131
- _a;
105
+ return makePrimitive("number", isNumber);
132
106
  }
133
107
  /**
134
108
  * Creates a shape representing a JS `string`.
135
109
  */
136
110
  function string() {
137
- var _a;
138
- return _a = {
139
- typename: "string",
140
- check: function (x) {
141
- return isString(x) && this[Predicates].every(function (p) { return p.predicate(x); });
142
- }
143
- },
144
- _a[Predicates] = [],
145
- _a.where = function (predicate, description) {
146
- var _a;
147
- return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
148
- },
149
- _a.and = function (other) {
150
- return makeIntersection(this, other);
151
- },
152
- _a.or = function (other) {
153
- return makeUnion(this, other);
154
- },
155
- _a;
111
+ return makePrimitive("string", isString);
156
112
  }
157
113
  /**
158
114
  * Creates a shape representing a JS `boolean`.
159
115
  */
160
116
  function boolean() {
161
- var _a;
162
- return _a = {
163
- typename: "boolean",
164
- check: function (x) {
165
- return isBoolean(x) && this[Predicates].every(function (p) { return p.predicate(x); });
166
- }
167
- },
168
- _a[Predicates] = [],
169
- _a.where = function (predicate, description) {
170
- var _a;
171
- return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
172
- },
173
- _a.and = function (other) {
174
- return makeIntersection(this, other);
175
- },
176
- _a.or = function (other) {
177
- return makeUnion(this, other);
178
- },
179
- _a;
117
+ return makePrimitive("boolean", isBoolean);
180
118
  }
181
119
  /**
182
120
  * Creates a shape representing a primitive literal type.
@@ -187,137 +125,102 @@ function boolean() {
187
125
  * where the type is just the literal `1`
188
126
  */
189
127
  function literal(x) {
190
- var _a;
191
128
  function matchesLiteral(u) {
192
129
  return u === x;
193
130
  }
194
- return _a = {
195
- typename: isUndefined(x) ? "undefined" : JSON.stringify(x)
196
- },
197
- _a[Predicates] = [],
198
- _a.check = function (x) {
199
- return matchesLiteral(x) &&
200
- this[Predicates].every(function (p) { return p.predicate(x); });
201
- },
202
- _a.where = function (predicate, description) {
203
- var _a;
204
- return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
205
- },
206
- _a.and = function (other) {
207
- return makeIntersection(this, other);
208
- },
209
- _a.or = function (other) {
210
- return makeUnion(this, other);
211
- },
212
- _a;
131
+ return __assign(__assign({}, base()), { typename: isUndefined(x) ? "undefined" : JSON.stringify(x), check: function (x) {
132
+ return matchesLiteral(x) && tryPredicates(this, x);
133
+ } });
213
134
  }
214
135
  /// COMPLEX SHAPE FACTORIES
136
+ function makeUnion(left, right) {
137
+ return __assign(__assign({}, base()), { typename: "".concat(left.typename, " | ").concat(right.typename), check: function (x) {
138
+ return (left.check(x) || right.check(x)) && tryPredicates(this, x);
139
+ } });
140
+ }
141
+ function makeIntersection(left, right) {
142
+ var _a, _b, _c;
143
+ // Trickery: combine permitted properties of left and right shape
144
+ var tolerantLeft = __assign(__assign({}, left), (_a = {}, _a[AllowUnknownProperties] = true, _a));
145
+ var tolerantRight = __assign(__assign({}, right), (_b = {}, _b[AllowUnknownProperties] = true, _b));
146
+ var combinedProperties = __assign(__assign({}, left[Properties]), right[Properties]);
147
+ return __assign(__assign({}, base()), (_c = { typename: "".concat(left.typename, " & ").concat(right.typename) }, _c[Properties] = combinedProperties, _c[AllowUnknownProperties] = !!(left[AllowUnknownProperties] && right[AllowUnknownProperties]), _c.check = function (x) {
148
+ if (!tolerantLeft.check(x) || !tolerantRight.check(x))
149
+ return false;
150
+ if (!this[AllowUnknownProperties] &&
151
+ (left[Properties] !== undefined || right[Properties] !== undefined)) {
152
+ for (var key in x) {
153
+ if (!(key in combinedProperties))
154
+ return false;
155
+ }
156
+ }
157
+ return tryPredicates(this, x);
158
+ }, _c));
159
+ }
215
160
  /**
216
161
  * Creates an array shape, representing `Array<T>` (aka `T[]`).
217
162
  * Takes the shape representing `T` as a parameter.
218
163
  */
219
164
  function array(shape) {
220
- var _a;
221
- var typename = "Array<".concat(shape.typename, ">");
222
- return _a = {
223
- typename: typename,
224
- check: function (x) {
225
- function innerMatches(x) {
226
- return x.every(function (entry) { return shape.check(entry); });
227
- }
228
- return isArray(x) && innerMatches(x) &&
229
- this[Predicates].every(function (p) { return p.predicate(x); });
230
- }
231
- },
232
- _a[Predicates] = [],
233
- _a.where = function (predicate, description) {
234
- var _a;
235
- return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
236
- },
237
- _a.and = function (other) {
238
- return makeIntersection(this, other);
239
- },
240
- _a.or = function (other) {
241
- return makeUnion(this, other);
242
- },
243
- _a;
165
+ function innerMatches(x) {
166
+ return x.every(function (entry) { return shape.check(entry); });
167
+ }
168
+ return __assign(__assign({}, base()), { typename: "Array<".concat(shape.typename, ">"), check: function (x) {
169
+ return isArray(x) && innerMatches(x) && tryPredicates(this, x);
170
+ } });
244
171
  }
245
- /**
246
- * Creates an object shape.
247
- *
248
- * @example
249
- * ```typescript
250
- * const Group = Shapes.object({
251
- * id: Shapes.number(),
252
- * name: Shapes.string(),
253
- * });
254
- *
255
- * const User = Shapes.object({
256
- * id: Shapes.number(),
257
- * name: Shapes.string(),
258
- * groups: Shapes.nullable(
259
- * Shapes.array(Group)
260
- * )
261
- * });
262
- * ```
263
- */
264
172
  // deno-lint-ignore no-explicit-any
265
- function object(properties, options) {
173
+ function object(nameOrProperties, propertiesOrOptions, maybeOptions) {
266
174
  var _a;
267
175
  var _b;
176
+ var typename;
177
+ var properties;
178
+ var options;
179
+ if (typeof nameOrProperties === "string") {
180
+ typename = nameOrProperties;
181
+ properties = propertiesOrOptions;
182
+ options = maybeOptions;
183
+ }
184
+ else {
185
+ properties = nameOrProperties;
186
+ options = propertiesOrOptions;
187
+ }
268
188
  var allowUnknownProperties = (_b = options === null || options === void 0 ? void 0 : options.allowUnknownProperties) !== null && _b !== void 0 ? _b : false;
269
- return _a = {
270
- typename: "Object"
271
- },
272
- _a[AllowUnknownProperties] = allowUnknownProperties,
273
- _a.check = function (x) {
274
- var _this = this;
275
- var matchesShape = function (input) {
276
- // Check that input is an object
277
- if (!isObject(input)) {
189
+ function matchesShape(self, input) {
190
+ // Check that input is an object
191
+ if (!isObject(input)) {
192
+ return false;
193
+ }
194
+ if (self[Properties] === undefined)
195
+ return false;
196
+ // Check for unknown properties
197
+ if (!self[AllowUnknownProperties]) {
198
+ for (var inputProperty in input) {
199
+ if (!(inputProperty in self[Properties])) {
278
200
  return false;
279
201
  }
280
- // Check for unknown properties
281
- if (!_this[AllowUnknownProperties]) {
282
- for (var inputProperty in input) {
283
- if (!(inputProperty in _this[Properties])) {
284
- return false;
285
- }
286
- }
287
- }
288
- // Check required properties and their types
289
- for (var property in _this[Properties]) {
290
- var field = input[property];
291
- var propertyShape = _this[Properties][property];
292
- if (isUndefined(propertyShape))
293
- return false;
294
- // Property presence check
295
- if (!(property in input) && !propertyShape.check(undefined)) {
296
- return false;
297
- }
298
- // Property type check
299
- if (!propertyShape.check(field)) {
300
- return false;
301
- }
302
- }
303
- return true;
304
- };
305
- return matchesShape(x) &&
306
- this[Predicates].every(function (p) { return p.predicate(x); });
307
- },
308
- _a[Properties] = __assign(__assign({}, properties), options === null || options === void 0 ? void 0 : options.additionalPermittedProperties),
309
- _a[Predicates] = [],
310
- _a.where = function (predicate, description) {
311
- var _a;
312
- return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
313
- },
314
- _a.and = function (other) {
315
- return makeIntersection(this, other);
316
- },
317
- _a.or = function (other) {
318
- return makeUnion(this, other);
319
- },
320
- _a;
202
+ }
203
+ }
204
+ // Check required properties and their types
205
+ for (var property in self[Properties]) {
206
+ var field = input[property];
207
+ var propertyShape = self[Properties][property];
208
+ if (isUndefined(propertyShape))
209
+ return false;
210
+ // Property presence check
211
+ if (!(property in input) && !propertyShape.check(undefined)) {
212
+ return false;
213
+ }
214
+ // Property type check
215
+ if (!propertyShape.check(field)) {
216
+ return false;
217
+ }
218
+ }
219
+ return true;
220
+ }
221
+ return __assign(__assign({}, base()), (_a = { typename: typename !== null && typename !== void 0 ? typename : "object" }, _a[AllowUnknownProperties] = allowUnknownProperties, _a.check = function (x) {
222
+ return matchesShape(this, x) && tryPredicates(this, x);
223
+ }, _a[Properties] = __assign(__assign({}, properties), options === null || options === void 0 ? void 0 : options.additionalPermittedProperties), _a));
321
224
  }
322
225
  /**
323
226
  * Creates a shape representing a tuple type, with an optional rest
@@ -326,17 +229,11 @@ function object(properties, options) {
326
229
  * Shapes.tuple([Shapes.number()], Shapes.string()) is equivalent to TS type [number, ...string]
327
230
  */
328
231
  function tuple(shapes, rest) {
329
- var _a;
330
- var typename = "[".concat(shapes.map(function (s) { return s.typename; }).join(", "), "]");
331
- return _a = {
332
- typename: typename
333
- },
334
- _a[Predicates] = [],
335
- _a.check = function (x) {
232
+ return __assign(__assign({}, base()), { typename: "[".concat(shapes.map(function (s) { return s.typename; }).join(", ")).concat(rest === undefined ? "" : ", ...".concat(rest.typename, "[]"), "]"), check: function (x) {
336
233
  if (!isArray(x))
337
234
  return false;
338
235
  if (x.length > shapes.length) {
339
- // Oversized x and no rest shape can't be valid
236
+ // Oversized x and no rest shape can't be valid
340
237
  if (rest === undefined)
341
238
  return false;
342
239
  for (var idx = shapes.length; idx < x.length; idx++) {
@@ -344,46 +241,22 @@ function tuple(shapes, rest) {
344
241
  return false;
345
242
  }
346
243
  }
347
- return shapes.every(function (shape, idx) { return shape.check(x[idx]); }) && this[Predicates].every(function (p) { return p.predicate(x); });
348
- },
349
- _a.where = function (predicate, description) {
350
- var _a;
351
- return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
352
- },
353
- _a.and = function (other) {
354
- return makeIntersection(this, other);
355
- },
356
- _a.or = function (other) {
357
- return makeUnion(this, other);
358
- },
359
- _a;
244
+ return (shapes.every(function (shape, idx) { return shape.check(x[idx]); }) &&
245
+ tryPredicates(this, x));
246
+ } });
360
247
  }
361
248
  /**
362
- * Creates a shape representing an enum type
249
+ * Creates a shape representing an enum type.
363
250
  * (Not an actual enum as made using the enum keyword)
364
251
  *
365
252
  * `Shapes.enum(["a", "b", "c"])` is equivalent to `"a" | "b" | "c"`
366
253
  */
367
254
  function enumOf(values) {
368
- var _a;
369
- return _a = {
370
- typename: "".concat(values.map(function (v) { return JSON.stringify(v); }).join(" | "))
371
- },
372
- _a[Predicates] = [],
373
- _a.check = function (x) {
374
- return (isNumber(x) || isString(x)) && values.includes(x) && this[Predicates].every(function (p) { return p.predicate(x); });
375
- },
376
- _a.where = function (predicate, description) {
377
- var _a;
378
- return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [{ predicate: predicate, description: description }], false), _a));
379
- },
380
- _a.and = function (other) {
381
- return makeIntersection(this, other);
382
- },
383
- _a.or = function (other) {
384
- return makeUnion(this, other);
385
- },
386
- _a;
255
+ return __assign(__assign({}, base()), { typename: "".concat(values.map(function (v) { return JSON.stringify(v); }).join(" | ")), check: function (x) {
256
+ return ((isNumber(x) || isString(x)) &&
257
+ values.includes(x) &&
258
+ tryPredicates(this, x));
259
+ } });
387
260
  }
388
261
  /// TYPE MODIFIERS
389
262
  /**
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "homepage": "https://codeberg.org/jakobkg/shapes-ts#readme",
8
8
  "license": "BSD-3-Clause",
9
- "version": "0.3.1",
9
+ "version": "0.4.0",
10
10
  "private": false,
11
11
  "main": "dist/index.js",
12
12
  "scripts": {