firetender 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # FireTender
1
+ # Firetender
2
2
 
3
- FireTender is a wrapper for Firestore documents to make reading and writing them
4
- simpler and safer. A Firestore doc looks like any other Typescript object, and
5
- it is validated upon reading and writing.
3
+ The goal of Firetender is to make Firestore documents look (almost) like any
4
+ other Typescript objects, reducing boilerplate and conceptual overhead and
5
+ providing type safety and data validation.
6
6
 
7
7
  Querying and concurrency are not yet supported. I'm adding features as I need
8
8
  them, but contributions are most welcome. See the list of [alternative
@@ -11,23 +11,38 @@ something more mature.
11
11
 
12
12
  ## Usage
13
13
 
14
- To illustrate, let's run through the basics of defining, creating, reading,
15
- modifying, and copying a Firestore document.
14
+ To illustrate, let's run through the basics of defining, creating, modifying,
15
+ and copying a Firestore document.
16
16
 
17
- ### Define your schemas
17
+ ### Initialize Cloud Firestore
18
18
 
19
- First, we define the document schemas and their validation criteria with
20
- [Zod](https://github.com/colinhacks/zod). If you've used Joi or Yup, you will
21
- find Zod very similar. Optional collections should use `.default({})` or
22
- `.default([])` to simplify access. Here we define a schema for types of
23
- pizza, because I was hungry when I wrote this.
19
+ The first step is the usual Firestore configuration and initialization. See
20
+ the [Firestore
21
+ quickstart](https://firebase.google.com/docs/firestore/quickstart) for details.
24
22
 
25
- We use the `FireTenderDoc.makeClassFactory()` convenience method to avoid having
26
- to pass in the schema every time we instantiate a doc object.
23
+ ```javascript
24
+ import { doc, initializeApp } from "firebase/app";
25
+ import { getFirestore } from "firebase/firestore";
26
+
27
+ // TODO: Replace the following with your app's Firebase project configuration.
28
+ // See: https://firebase.google.com/docs/web/learn-more#config-object
29
+ const firebaseConfig = {
30
+ // ...
31
+ };
32
+
33
+ const app = initializeApp(firebaseConfig);
34
+ const firestore = getFirestore(app);
35
+ ```
36
+
37
+ ### Define the schema
38
+
39
+ Firetender uses [Zod](https://github.com/colinhacks/zod) to define the
40
+ document's schema and validation rules; if you've used Joi or Yup, you will find
41
+ Zod very similar. In the example below, I've defined a schema for types of
42
+ pizza. I was a little hungry when I wrote this.
27
43
 
28
44
  ```javascript
29
- import { doc } from "firebase/firestore";
30
- import { DocWrapper } from "firetender";
45
+ import { FiretenderDoc } from "firetender";
31
46
  import { z } from "zod";
32
47
 
33
48
  const pizzaSchema = z.object({
@@ -48,55 +63,68 @@ const pizzaSchema = z.object({
48
63
  tags: z.array(z.string()).default([]),
49
64
  });
50
65
 
51
- const pizzaFactory = FireTenderDoc.makeClassFactoryFor(pizzaSchema);
66
+ const pizzaFactory = FiretenderDoc.makeClassFactoryFor(pizzaSchema);
52
67
  ```
53
68
 
69
+ The static `FiretenderDoc.makeClassFactory()` method simplifies document
70
+ creation by capturing the schema.
71
+
72
+ Optional records and arrays should typically use `.default()` to provide an
73
+ empty collection when missing. That isn't required, but it makes accessing
74
+ these fields simpler because they will always be defined. The downside is that
75
+ empty collection fields are not pruned and will appear in Firestore.
76
+
54
77
  ### Add a document
55
78
 
56
- Let's add a document to the `pizzas` collection with an ID of `margherita`. We
57
- use the factory's `.createNewDoc()` method to create a validated local object
58
- representing a new document in the collection. We then add the doc to Firestore
59
- by calling its `.write()` method.
79
+ Let's add a document to the `pizzas` collection, with an ID of `margherita`. We
80
+ use the factory's `.createNewDoc()` to produce a `FiretenderDoc` representing a
81
+ new document, initialized with validated data. This object is purely local
82
+ until it is written to Firestore by calling `.write()`. Don't forget to do
83
+ that.
60
84
 
61
85
  ```javascript
62
86
  const docRef = doc(db, "pizzas", "margherita");
63
87
  const pizza = pizzaFactory.createNewDoc(docRef, {
64
88
  name: "Margherita",
89
+ description: "Neapolitan style pizza"
65
90
  toppings: { "fresh mozzarella": {}, "fresh basil": {} },
66
91
  tags: ["traditional"],
67
92
  });
68
93
  await pizza.write();
69
94
  ```
70
95
 
71
- If we don't care about the doc ID, we can also pass a collection reference
72
- (e.g., `collection(db, "pizzas")`) to `.createNewDoc()`. Firestore will assign
73
- a random ID.
96
+ If you don't care about the doc ID, pass a collection reference to
97
+ `.createNewDoc()` and Firestore will assign an ID at random. It can be read
98
+ from `.id` or `.docRef`.
74
99
 
75
100
  ### Read and modify a document
76
101
 
77
- To read or modify an existing document, we instantiate a doc wrapper using the
78
- `.wrapExistingDoc()` factory method and passing in the doc's Firestore
79
- reference. To read from it, we call `.load()` and access the data with `.ro`
80
- (read only); to write, we modify the `.rw` accessor and then call `.write()`.
81
- They can be used in combination:
102
+ To access an existing document, pass its reference to the `.wrapExistingDoc()`
103
+ factory method. To read it, call `.load()` and access its data with the `.r`
104
+ property; see the example below. To make changes, use `.w` then call
105
+ `.write()`. Reading and updating can be done in combination:
82
106
 
83
107
  ```javascript
84
108
  const meats = ["pepperoni", "chicken", "sausage"];
85
109
  const pizza = await pizzaFactory.wrapExistingDoc(docRef).load();
86
- const isMeatIncluded = Object.entries(pizza.ro.toppings).some(
110
+ const isMeatIncluded = Object.entries(pizza.r.toppings).some(
87
111
  ([name, topping]) => topping.isIncluded && name in meats
88
112
  );
89
113
  if (!isMeatIncluded) {
90
- pizza.rw.toppings.tags.push("vegetarian");
114
+ pizza.w.toppings.tags.push("vegetarian");
91
115
  }
92
116
  await pizza.write();
93
117
  ```
94
118
 
119
+ The `.r` and `.w` properties point to the same data, with the read-only accessor
120
+ typed accordingly. Reading from `.r` is more efficient, as `.w` builds a chain
121
+ of proxies to track updates.
122
+
95
123
  ### Make a copy
96
124
 
97
- Here we create a new pizza in the same collection. Alternatively, a document
98
- can be copied to elsewhere by specifying a document or collection reference
99
- for the destination.
125
+ Finally, use `.copy()` to get a deep copy of the document. If an ID is not
126
+ specified, it will be assigned randomly when the new doc is added to Firestore.
127
+ The copy is solely local until `.write()` is called.
100
128
 
101
129
  ```javascript
102
130
  const sourceRef = doc(db, "pizza", "margherita");
@@ -106,11 +134,15 @@ newPizza.name = "Meaty Margh";
106
134
  newPizza.toppings.sausage = {};
107
135
  newPizza.toppings.pepperoni = { included: false, surcharge: 1.25 };
108
136
  newPizza.toppings.chicken = { included: false, surcharge: 1.50 };
137
+ delete newPizza.description;
109
138
  delete newPizza.toppings["fresh basil"];
110
139
  delete newPizza.tags.vegetarian;
111
140
  newPizza.write();
112
141
  ```
113
142
 
143
+ Note the use of the `delete` operator to remove optional fields and record and
144
+ array items.
145
+
114
146
  ## TODO
115
147
 
116
148
  * Javadoc
@@ -124,6 +156,14 @@ newPizza.write();
124
156
  * Improved timestamp handling, tests
125
157
  * Releases
126
158
  * Minify code (esbuild?)
159
+ * Automate github & npm releases, either using semantic versioning
160
+ ([video](https://egghead.io/lessons/javascript-automating-releases-with-semantic-release),
161
+ [package](https://github.com/semantic-release/semantic-release)) or github
162
+ workflows
163
+ ([tutorial](https://writeabout.net/2021/10/15/releasing-github-npm-packages/),
164
+ [Zod's
165
+ yaml](https://github.com/colinhacks/zod/blob/master/.github/workflows/release.yml))
166
+ or some combination.
127
167
 
128
168
  ## Alternatives
129
169
 
@@ -1,14 +1,14 @@
1
1
  import { CollectionReference, DocumentReference } from "firebase/firestore";
2
2
  import { z } from "zod";
3
3
  import { DeepReadonly } from "./ts-helpers";
4
- export declare type FireTenderDocOptions = {
4
+ export declare type FiretenderDocOptions = {
5
5
  createDoc?: true;
6
6
  initialData?: any;
7
7
  };
8
8
  /**
9
9
  * Helper class for reading and writing Firestore data based on Zod schemas.
10
10
  */
11
- export declare class FireTenderDoc<SchemaType extends z.SomeZodObject, DataType extends {
11
+ export declare class FiretenderDoc<SchemaType extends z.SomeZodObject, DataType extends {
12
12
  [x: string]: any;
13
13
  } = z.infer<SchemaType>> {
14
14
  readonly schema: SchemaType;
@@ -18,22 +18,22 @@ export declare class FireTenderDoc<SchemaType extends z.SomeZodObject, DataType
18
18
  private data;
19
19
  private dataProxy;
20
20
  private updates;
21
- constructor(schema: SchemaType, ref: DocumentReference | CollectionReference, options?: FireTenderDocOptions);
21
+ constructor(schema: SchemaType, ref: DocumentReference | CollectionReference, options?: FiretenderDocOptions);
22
22
  static createNewDoc<SchemaType1 extends z.SomeZodObject, InputType extends {
23
23
  [x: string]: any;
24
- } = z.input<SchemaType1>>(schema: SchemaType1, ref: DocumentReference | CollectionReference, initialData: InputType, options?: FireTenderDocOptions): FireTenderDoc<SchemaType1, z.TypeOf<SchemaType1>>;
24
+ } = z.input<SchemaType1>>(schema: SchemaType1, ref: DocumentReference | CollectionReference, initialData: InputType, options?: FiretenderDocOptions): FiretenderDoc<SchemaType1, z.TypeOf<SchemaType1>>;
25
25
  static makeClassFactoryFor<SchemaType1 extends z.SomeZodObject, InputType extends {
26
26
  [x: string]: any;
27
27
  } = z.input<SchemaType1>>(schema: SchemaType1): {
28
- createNewDoc: (ref: DocumentReference | CollectionReference, initialData: InputType, options?: FireTenderDocOptions) => FireTenderDoc<SchemaType1, z.TypeOf<SchemaType1>>;
29
- wrapExistingDoc: (ref: DocumentReference | CollectionReference, options?: FireTenderDocOptions) => FireTenderDoc<SchemaType1, z.TypeOf<SchemaType1>>;
28
+ createNewDoc: (ref: DocumentReference | CollectionReference, initialData: InputType, options?: FiretenderDocOptions) => FiretenderDoc<SchemaType1, z.TypeOf<SchemaType1>>;
29
+ wrapExistingDoc: (ref: DocumentReference | CollectionReference, options?: FiretenderDocOptions) => FiretenderDoc<SchemaType1, z.TypeOf<SchemaType1>>;
30
30
  };
31
31
  get id(): string | undefined;
32
32
  get docRef(): DocumentReference;
33
- copy(dest?: DocumentReference | CollectionReference | string | undefined, options?: FireTenderDocOptions): FireTenderDoc<SchemaType, DataType>;
33
+ copy(dest?: DocumentReference | CollectionReference | string | undefined, options?: FiretenderDocOptions): FiretenderDoc<SchemaType, DataType>;
34
34
  load(force?: boolean): Promise<this>;
35
- get ro(): DeepReadonly<DataType>;
36
- get rw(): DataType;
35
+ get r(): DeepReadonly<DataType>;
36
+ get w(): DataType;
37
37
  write(): Promise<void>;
38
38
  private onChange;
39
39
  }
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FireTenderDoc = void 0;
3
+ exports.FiretenderDoc = void 0;
4
4
  const firestore_1 = require("firebase/firestore");
5
5
  const proxies_1 = require("./proxies");
6
6
  const ts_helpers_1 = require("./ts-helpers");
7
7
  /**
8
8
  * Helper class for reading and writing Firestore data based on Zod schemas.
9
9
  */
10
- class FireTenderDoc {
10
+ class FiretenderDoc {
11
11
  constructor(schema, ref, options = {}) {
12
12
  this.docID = undefined;
13
13
  this.data = undefined;
@@ -26,7 +26,7 @@ class FireTenderDoc {
26
26
  this.docID = this.ref.path.split("/").pop();
27
27
  }
28
28
  else if (!this.isNewDoc) {
29
- throw TypeError("FireTender can only take a collection reference when creating a new document. Use FireTender.createDoc() if this is your intent.");
29
+ throw TypeError("Firetender can only take a collection reference when creating a new document. Use Firetender.createDoc() if this is your intent.");
30
30
  }
31
31
  }
32
32
  static createNewDoc(schema, ref, initialData, options = {}) {
@@ -35,12 +35,12 @@ class FireTenderDoc {
35
35
  createDoc: true,
36
36
  initialData,
37
37
  };
38
- return new FireTenderDoc(schema, ref, mergedOptions);
38
+ return new FiretenderDoc(schema, ref, mergedOptions);
39
39
  }
40
40
  static makeClassFactoryFor(schema) {
41
41
  return {
42
- createNewDoc: (ref, initialData, options = {}) => FireTenderDoc.createNewDoc(schema, ref, initialData, options),
43
- wrapExistingDoc: (ref, options = {}) => new FireTenderDoc(schema, ref, options),
42
+ createNewDoc: (ref, initialData, options = {}) => FiretenderDoc.createNewDoc(schema, ref, initialData, options),
43
+ wrapExistingDoc: (ref, options = {}) => new FiretenderDoc(schema, ref, options),
44
44
  };
45
45
  }
46
46
  get id() {
@@ -74,7 +74,7 @@ class FireTenderDoc {
74
74
  createDoc: true,
75
75
  initialData: this.data,
76
76
  };
77
- return new FireTenderDoc(this.schema, ref, mergedOptions);
77
+ return new FiretenderDoc(this.schema, ref, mergedOptions);
78
78
  }
79
79
  async load(force = false) {
80
80
  if (this.isNewDoc || this.ref.type === "collection") {
@@ -91,20 +91,20 @@ class FireTenderDoc {
91
91
  }
92
92
  return this;
93
93
  }
94
- get ro() {
94
+ get r() {
95
95
  if (!this.data) {
96
- throw Error("You must call load() before using the .ro accessor.");
96
+ throw Error("load() must be called before reading the document.");
97
97
  }
98
98
  return this.data;
99
99
  }
100
- get rw() {
100
+ get w() {
101
101
  if (this.isNewDoc) {
102
102
  // No need to monitor changes if we're creating rather than updating.
103
103
  return this.data;
104
104
  }
105
105
  if (!this.dataProxy) {
106
106
  if (!this.data) {
107
- throw Error("You must call load() before using the .rw accessor.");
107
+ throw Error("load() must be called before updating the document.");
108
108
  }
109
109
  this.dataProxy = (0, proxies_1.watchFieldForChanges)([], this.schema, this.data, this.onChange.bind(this));
110
110
  }
@@ -125,7 +125,7 @@ class FireTenderDoc {
125
125
  else {
126
126
  if (!(this.ref.type === "document")) {
127
127
  // We should never get here.
128
- throw Error("Internal error. FireTender object should always reference a document when updating an existing doc.");
128
+ throw Error("Internal error. Firetender object should always reference a document when updating an existing doc.");
129
129
  }
130
130
  if (this.updates.size === 0) {
131
131
  return;
@@ -138,5 +138,5 @@ class FireTenderDoc {
138
138
  this.updates.set(fieldPath.join("."), newValue);
139
139
  }
140
140
  }
141
- exports.FireTenderDoc = FireTenderDoc;
142
- //# sourceMappingURL=FireTenderDoc.js.map
141
+ exports.FiretenderDoc = FiretenderDoc;
142
+ //# sourceMappingURL=FiretenderDoc.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FireTenderDoc.js","sourceRoot":"","sources":["../src/FireTenderDoc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FiretenderDoc.js","sourceRoot":"","sources":["../src/FiretenderDoc.ts"],"names":[],"mappings":"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"}
@@ -10,8 +10,6 @@ exports.timestampSchema = zod_1.z.object({
10
10
  seconds: zod_1.z.number().positive().int(),
11
11
  nanoseconds: zod_1.z.number().nonnegative().int(),
12
12
  });
13
- // TODO: probably want to move these timestamp functions into their own helper
14
- // module
15
13
  function dateFromTimestamp(timestamp) {
16
14
  return new Date(timestamp.seconds * 1e3 + timestamp.nanoseconds / 1e6);
17
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Timestamps.js","sourceRoot":"","sources":["../src/Timestamps.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAExB;;;GAGG;AACU,QAAA,eAAe,GAAG,OAAC,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE;IACpC,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE;CAC5C,CAAC,CAAC;AAGH,8EAA8E;AAC9E,SAAS;AAET,SAAgB,iBAAiB,CAAC,SAAwB;IACxD,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,GAAG,GAAG,GAAG,SAAS,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC;AACzE,CAAC;AAFD,8CAEC;AAED,SAAgB,OAAO,CAAC,WAAW,GAAG,EAAE;IACtC,sEAAsE;IACtE,OAAO,uBAAuB,CAC5B,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAC/C,CAAC;AACJ,CAAC;AALD,0BAKC;AAED,SAAgB,iBAAiB,CAAC,IAAU;IAC1C,OAAO,uBAAuB,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AACjD,CAAC;AAFD,8CAEC;AAED,SAAgB,uBAAuB,CAAC,YAAoB;IAC1D,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;QACxC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC;KACzD,CAAC;AACJ,CAAC;AALD,0DAKC;AAED,SAAgB,YAAY;IAC1B,sEAAsE;IACtE,OAAO,uBAAuB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AAC7C,CAAC;AAHD,oCAGC"}
1
+ {"version":3,"file":"Timestamps.js","sourceRoot":"","sources":["../src/Timestamps.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAExB;;;GAGG;AACU,QAAA,eAAe,GAAG,OAAC,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE;IACpC,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE;CAC5C,CAAC,CAAC;AAGH,SAAgB,iBAAiB,CAAC,SAAwB;IACxD,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,GAAG,GAAG,GAAG,SAAS,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC;AACzE,CAAC;AAFD,8CAEC;AAED,SAAgB,OAAO,CAAC,WAAW,GAAG,EAAE;IACtC,sEAAsE;IACtE,OAAO,uBAAuB,CAC5B,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAC/C,CAAC;AACJ,CAAC;AALD,0BAKC;AAED,SAAgB,iBAAiB,CAAC,IAAU;IAC1C,OAAO,uBAAuB,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AACjD,CAAC;AAFD,8CAEC;AAED,SAAgB,uBAAuB,CAAC,YAAoB;IAC1D,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;QACxC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC;KACzD,CAAC;AACJ,CAAC;AALD,0DAKC;AAED,SAAgB,YAAY;IAC1B,sEAAsE;IACtE,OAAO,uBAAuB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AAC7C,CAAC;AAHD,oCAGC"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { FireTenderDoc } from "./FireTenderDoc";
1
+ export { FiretenderDoc } from "./FiretenderDoc";
2
2
  export * from "./Timestamps";
package/dist/index.js CHANGED
@@ -14,8 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.FireTenderDoc = void 0;
18
- var FireTenderDoc_1 = require("./FireTenderDoc");
19
- Object.defineProperty(exports, "FireTenderDoc", { enumerable: true, get: function () { return FireTenderDoc_1.FireTenderDoc; } });
17
+ exports.FiretenderDoc = void 0;
18
+ var FiretenderDoc_1 = require("./FiretenderDoc");
19
+ Object.defineProperty(exports, "FiretenderDoc", { enumerable: true, get: function () { return FiretenderDoc_1.FiretenderDoc; } });
20
20
  __exportStar(require("./Timestamps"), exports);
21
21
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "firetender",
3
- "displayName": "FireTender",
3
+ "displayName": "Firetender",
4
4
  "description": "Typescript wrapper for Firestore documents",
5
- "version": "0.2.0",
5
+ "version": "0.3.1",
6
6
  "author": "Jake Hartman",
7
7
  "license": "MIT",
8
8
  "homepage": "https://github.com/jakes-space/firetender",
@@ -33,7 +33,9 @@
33
33
  "prettier:fix": "prettier --write src/*.ts src/**/*.ts",
34
34
  "check": "npm run lint:check && npm run prettier:check",
35
35
  "fix": "npm run lint:fix && npm run prettier:fix",
36
+ "emulate-db": "firebase emulators:start --project=firetender",
36
37
  "test": "jest --forceExit --detectOpenHandles",
38
+ "prepare": "husky install",
37
39
  "clean": "rm -rf dist/*",
38
40
  "build": "npm run clean && tsc && rm -rf dist/__tests__",
39
41
  "prepublishOnly": "npm run check && npm run test && npm run build"
@@ -53,6 +55,7 @@
53
55
  "eslint-import-resolver-typescript": "^3.5.2",
54
56
  "eslint-plugin-import": "^2.26.0",
55
57
  "eslint-plugin-prettier": "^4.2.1",
58
+ "husky": "^8.0.1",
56
59
  "jest": "^29.2.2",
57
60
  "prettier": "^2.7.1",
58
61
  "ts-jest": "^29.0.3",