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 +74 -34
- package/dist/{FireTenderDoc.d.ts → FiretenderDoc.d.ts} +9 -9
- package/dist/{FireTenderDoc.js → FiretenderDoc.js} +14 -14
- package/dist/{FireTenderDoc.js.map → FiretenderDoc.js.map} +1 -1
- package/dist/Timestamps.js +0 -2
- package/dist/Timestamps.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Firetender
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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,
|
|
15
|
-
|
|
14
|
+
To illustrate, let's run through the basics of defining, creating, modifying,
|
|
15
|
+
and copying a Firestore document.
|
|
16
16
|
|
|
17
|
-
###
|
|
17
|
+
### Initialize Cloud Firestore
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
[
|
|
21
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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 {
|
|
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 =
|
|
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()`
|
|
58
|
-
|
|
59
|
-
by calling
|
|
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
|
|
72
|
-
(
|
|
73
|
-
|
|
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
|
|
78
|
-
`.
|
|
79
|
-
|
|
80
|
-
(
|
|
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.
|
|
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.
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
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
|
|
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?:
|
|
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?:
|
|
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?:
|
|
29
|
-
wrapExistingDoc: (ref: DocumentReference | CollectionReference, options?:
|
|
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?:
|
|
33
|
+
copy(dest?: DocumentReference | CollectionReference | string | undefined, options?: FiretenderDocOptions): FiretenderDoc<SchemaType, DataType>;
|
|
34
34
|
load(force?: boolean): Promise<this>;
|
|
35
|
-
get
|
|
36
|
-
get
|
|
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.
|
|
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
|
|
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("
|
|
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
|
|
38
|
+
return new FiretenderDoc(schema, ref, mergedOptions);
|
|
39
39
|
}
|
|
40
40
|
static makeClassFactoryFor(schema) {
|
|
41
41
|
return {
|
|
42
|
-
createNewDoc: (ref, initialData, options = {}) =>
|
|
43
|
-
wrapExistingDoc: (ref, options = {}) => new
|
|
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
|
|
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
|
|
94
|
+
get r() {
|
|
95
95
|
if (!this.data) {
|
|
96
|
-
throw Error("
|
|
96
|
+
throw Error("load() must be called before reading the document.");
|
|
97
97
|
}
|
|
98
98
|
return this.data;
|
|
99
99
|
}
|
|
100
|
-
get
|
|
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("
|
|
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.
|
|
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.
|
|
142
|
-
//# sourceMappingURL=
|
|
141
|
+
exports.FiretenderDoc = FiretenderDoc;
|
|
142
|
+
//# sourceMappingURL=FiretenderDoc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"FiretenderDoc.js","sourceRoot":"","sources":["../src/FiretenderDoc.ts"],"names":[],"mappings":"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"}
|
package/dist/Timestamps.js
CHANGED
|
@@ -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
|
}
|
package/dist/Timestamps.js.map
CHANGED
|
@@ -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,
|
|
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 {
|
|
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.
|
|
18
|
-
var
|
|
19
|
-
Object.defineProperty(exports, "
|
|
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": "
|
|
3
|
+
"displayName": "Firetender",
|
|
4
4
|
"description": "Typescript wrapper for Firestore documents",
|
|
5
|
-
"version": "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",
|