@trullock/firebase-common 1.3.0 → 2.0.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/package.json +1 -1
- package/src/automapper.js +26 -15
- package/tests/automapper.test.js +32 -22
package/package.json
CHANGED
package/src/automapper.js
CHANGED
|
@@ -4,7 +4,7 @@ let mappings = [];
|
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
6
6
|
* @param {function} toFirestore A function of the form (key: string, value: object/primitive) => object/primitive. Return a mapped value or undefined to fallback to default mapping
|
|
7
|
-
* @param {function} fromFirestore A function of the form (key: string, value: object/primitive
|
|
7
|
+
* @param {function} fromFirestore A function of the form (key: string, value: object/primitive) => object/primitive. Return a mapped value or undefined to fallback to default mapping
|
|
8
8
|
*/
|
|
9
9
|
export function registerMapping(toFirestore, fromFirestore)
|
|
10
10
|
{
|
|
@@ -17,8 +17,8 @@ export function registerMapping(toFirestore, fromFirestore)
|
|
|
17
17
|
let migrations = []
|
|
18
18
|
/**
|
|
19
19
|
*
|
|
20
|
-
* @param {function} shouldApply A function of the form (key: string, parent: object, value: object/primitive) => true/false. Return if the migration should apply or not
|
|
21
|
-
* @param {function} apply A function of the form key: string, parent: object, value: object/primitive) => object/primitive. Migrate the value. Return undefined to disregard the value.
|
|
20
|
+
* @param {function} shouldApply A function of the form ({ key: string, parent: object, value: object/primitive, destination: object, type: class }) => true/false. Return if the migration should apply or not
|
|
21
|
+
* @param {function} apply A function of the form ({ key: string, parent: object, value: object/primitive, destination: object, type: class }) => object/primitive. Migrate the value. Return undefined to disregard the value.
|
|
22
22
|
*/
|
|
23
23
|
export function registerMigration(shouldApply, apply)
|
|
24
24
|
{
|
|
@@ -212,6 +212,7 @@ export function autoMapFromFirestore(obj)
|
|
|
212
212
|
let dest = {};
|
|
213
213
|
let mapping = null;
|
|
214
214
|
|
|
215
|
+
// does this living here mean it cant be migrated?
|
|
215
216
|
if(obj._type)
|
|
216
217
|
{
|
|
217
218
|
mapping = getClassMappingByName(obj._type)
|
|
@@ -219,28 +220,38 @@ export function autoMapFromFirestore(obj)
|
|
|
219
220
|
}
|
|
220
221
|
|
|
221
222
|
for(let [key, value] of Object.entries(obj))
|
|
222
|
-
{
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
223
|
+
{
|
|
224
|
+
let prop = {
|
|
225
|
+
key,
|
|
226
|
+
value,
|
|
227
|
+
parent: obj,
|
|
228
|
+
destination: dest,
|
|
229
|
+
type: mapping?.type
|
|
230
|
+
}
|
|
228
231
|
|
|
229
232
|
for(let migration of migrations)
|
|
230
233
|
{
|
|
231
|
-
|
|
234
|
+
// shouldApply should not mutate prop object
|
|
235
|
+
if(!migration.shouldApply(prop))
|
|
232
236
|
continue;
|
|
233
237
|
|
|
234
|
-
|
|
238
|
+
// the intention is for the migration to mutate the prop object
|
|
239
|
+
migration.apply(prop);
|
|
235
240
|
}
|
|
236
241
|
|
|
242
|
+
if(prop.key == "_type")
|
|
243
|
+
continue;
|
|
244
|
+
|
|
245
|
+
if(mapping?.getters?.indexOf(prop.key) > -1)
|
|
246
|
+
continue;
|
|
247
|
+
|
|
237
248
|
let handled = false;
|
|
238
249
|
for(let mapping of mappings)
|
|
239
250
|
{
|
|
240
|
-
let result = mapping.fromFirestore(key, value
|
|
251
|
+
let result = mapping.fromFirestore(prop.key, prop.value)
|
|
241
252
|
if(result !== undefined)
|
|
242
253
|
{
|
|
243
|
-
|
|
254
|
+
prop.destination[prop.key] = result;
|
|
244
255
|
handled = true;
|
|
245
256
|
break;
|
|
246
257
|
}
|
|
@@ -248,9 +259,9 @@ export function autoMapFromFirestore(obj)
|
|
|
248
259
|
|
|
249
260
|
if(!handled)
|
|
250
261
|
{
|
|
251
|
-
let result = autoMapFromFirestore(value);
|
|
262
|
+
let result = autoMapFromFirestore(prop.value);
|
|
252
263
|
if(result != undefined)
|
|
253
|
-
|
|
264
|
+
prop.destination[prop.key] = result;
|
|
254
265
|
}
|
|
255
266
|
}
|
|
256
267
|
|
package/tests/automapper.test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert";
|
|
3
|
-
import { autoMapFromFirestore, autoMapToFirestore, registerClassForPersistence,
|
|
3
|
+
import { autoMapFromFirestore, autoMapToFirestore, registerClassForPersistence, registerMigration } from "../src/automapper.js";
|
|
4
4
|
import { Mixins } from "../src/utils.js";
|
|
5
5
|
|
|
6
6
|
class AggregateRoot
|
|
@@ -70,10 +70,6 @@ class Baz extends Foo {
|
|
|
70
70
|
|
|
71
71
|
class Academy extends Mixins([Baz, AggregateRoot])
|
|
72
72
|
{
|
|
73
|
-
static Test = class {}
|
|
74
|
-
|
|
75
|
-
uniqueList = new Set();
|
|
76
|
-
|
|
77
73
|
changeName(name)
|
|
78
74
|
{
|
|
79
75
|
this.apply('academyNameChanged', {
|
|
@@ -90,11 +86,9 @@ class Academy extends Mixins([Baz, AggregateRoot])
|
|
|
90
86
|
{
|
|
91
87
|
super();
|
|
92
88
|
this.bar = new Baz.Bar();
|
|
93
|
-
this.uniqueList.add('a')
|
|
94
|
-
this.uniqueList.add('b')
|
|
95
|
-
this.uniqueList.add('b')
|
|
96
89
|
}
|
|
97
90
|
|
|
91
|
+
static Test = class {}
|
|
98
92
|
}
|
|
99
93
|
|
|
100
94
|
test('test', t => {
|
|
@@ -113,17 +107,6 @@ test('test', t => {
|
|
|
113
107
|
test('automapping', t => {
|
|
114
108
|
registerClassForPersistence(Academy);
|
|
115
109
|
|
|
116
|
-
registerMapping((key, value) => {
|
|
117
|
-
if(value instanceof Set)
|
|
118
|
-
return Array.from(value)
|
|
119
|
-
return undefined;
|
|
120
|
-
}, (key, value, dest) => {
|
|
121
|
-
if(dest[key] instanceof Set)
|
|
122
|
-
return new Set(value);
|
|
123
|
-
return undefined;
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
|
|
127
110
|
let a = new Academy();
|
|
128
111
|
let mapped = autoMapToFirestore(a);
|
|
129
112
|
let unmapped = autoMapFromFirestore(mapped);
|
|
@@ -137,14 +120,41 @@ test('automapping', t => {
|
|
|
137
120
|
assert.equal(unmapped.bar.a, 1)
|
|
138
121
|
|
|
139
122
|
assert.equal(a.bar.barzy(), "barzy")
|
|
140
|
-
assert.equal(unmapped.bar.barzy(), "barzy")
|
|
123
|
+
assert.equal(unmapped.bar.barzy(), "barzy")
|
|
141
124
|
|
|
142
125
|
assert.equal(a.foozzy(), "foozzy")
|
|
143
126
|
assert.equal(unmapped.foozzy(), "foozzy")
|
|
144
127
|
|
|
145
128
|
assert.equal(a.bazzy(), "bazzy")
|
|
146
129
|
assert.equal(unmapped.bazzy(), "bazzy")
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
test('migrations', t => {
|
|
134
|
+
registerClassForPersistence(Academy);
|
|
135
|
+
|
|
136
|
+
// rename oldName to name
|
|
137
|
+
registerMigration(prop => prop.type == Academy && prop.key == "oldName", prop => prop.key = "name" )
|
|
138
|
+
|
|
139
|
+
registerMigration(prop => prop.type == Academy && prop.key == "oldBar", prop => {
|
|
140
|
+
prop.key = "bar"
|
|
141
|
+
prop.value._type = "Academy.Bar";
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
// rename bar.oldA to bar.a
|
|
145
|
+
registerMigration(prop => prop.type == Baz.Bar && prop.key == "oldA", prop => prop.key = "a" )
|
|
147
146
|
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
let mapped = {
|
|
148
|
+
_type: "Academy",
|
|
149
|
+
oldName: "the name",
|
|
150
|
+
oldBar: {
|
|
151
|
+
_type: "Academy.OldBar",
|
|
152
|
+
oldA: 1337
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
let unmapped = autoMapFromFirestore(mapped);
|
|
156
|
+
|
|
157
|
+
assert.equal(unmapped.d, 4)
|
|
158
|
+
assert(unmapped.bar instanceof Baz.Bar)
|
|
159
|
+
assert.equal(unmapped.bar.a, 1337)
|
|
150
160
|
})
|