@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trullock/firebase-common",
3
- "version": "1.3.0",
3
+ "version": "2.0.0",
4
4
  "description": "Collection of common firebase helpers",
5
5
  "homepage": "https://github.com/trullock/firebase#readme",
6
6
  "bugs": {
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, dest: object) => 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) => 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
- if(key == '_type')
224
- continue;
225
-
226
- if(mapping?.getters?.indexOf(key) > -1)
227
- continue;
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
- if(!migration.shouldApply(key, obj, value, dest, mapping?.type))
234
+ // shouldApply should not mutate prop object
235
+ if(!migration.shouldApply(prop))
232
236
  continue;
233
237
 
234
- value = migration.apply(key, obj, value, dest, mapping?.type);
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, dest)
251
+ let result = mapping.fromFirestore(prop.key, prop.value)
241
252
  if(result !== undefined)
242
253
  {
243
- dest[key] = result;
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
- dest[key] = result;
264
+ prop.destination[prop.key] = result;
254
265
  }
255
266
  }
256
267
 
@@ -1,6 +1,6 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert";
3
- import { autoMapFromFirestore, autoMapToFirestore, registerClassForPersistence, registerMapping } from "../src/automapper.js";
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
- assert(a.uniqueList instanceof Set)
149
- assert.equal(unmapped.uniqueList.size, 2)
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
  })