@data-weave/backend-firestore 0.7.1 → 0.7.2

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.
@@ -24,6 +24,7 @@ export declare class FirestoreDataManager<T extends FirestoreTypes.DocumentData,
24
24
  private readonly converter;
25
25
  private readonly opts?;
26
26
  private mergedConverter;
27
+ private metadataConverter;
27
28
  private collection;
28
29
  private collectionQuery;
29
30
  private managerOptions;
@@ -35,6 +36,15 @@ export declare class FirestoreDataManager<T extends FirestoreTypes.DocumentData,
35
36
  read(id: string, options?: FirestoreReadOptions): Promise<WithMetadata<T> | undefined>;
36
37
  create(data: WithFieldValue<WithoutId<T>>, options?: FirebaseCreateOptions): Promise<IdentifiableReference<WithMetadata<T>>>;
37
38
  private _update;
39
+ /**
40
+ * Update only the internal metadata fields of a document.
41
+ *
42
+ * Unlike {@link _update}, this bypasses the user-provided converter so it never re-serializes
43
+ * (and therefore never clobbers) user data. This matters because the user converter rebuilds the
44
+ * full document shape, which turns absent fields into `undefined` and can overwrite existing map
45
+ * fields with empty objects when Firestore strips the undefined values.
46
+ */
47
+ private _updateMetadata;
38
48
  update(id: string, data: WithoutId<Partial<WithFieldValue<T>>>, options?: FirestoreWriteOptions): Promise<void>;
39
49
  upsert(id: string, data: WithFieldValue<WithoutId<T>>, options?: FirestoreWriteOptions): Promise<void>;
40
50
  count(params?: QueryParams<SerializedT>): Promise<number>;
@@ -18,6 +18,7 @@ class FirestoreDataManager {
18
18
  converter;
19
19
  opts;
20
20
  mergedConverter;
21
+ metadataConverter;
21
22
  collection;
22
23
  collectionQuery;
23
24
  managerOptions;
@@ -29,8 +30,9 @@ class FirestoreDataManager {
29
30
  this.collectionPath = collectionPath;
30
31
  this.converter = converter;
31
32
  this.opts = opts;
33
+ this.metadataConverter = new FirestoreMetadata_1.FirestoreMetadataConverter();
32
34
  // @ts-expect-error - Force merge FirestoreDataConverter and InternalFirestoreDataConverter
33
- this.mergedConverter = new utils_1.MergeConverters(this.converter, new FirestoreMetadata_1.FirestoreMetadataConverter());
35
+ this.mergedConverter = new utils_1.MergeConverters(this.converter, this.metadataConverter);
34
36
  this.managerOptions = this.validateOptions({ ...defaultFirebaseDataManagerOptions, ...this.opts });
35
37
  this.refCache = this.managerOptions.refCache || new datamanager_1.MapCache(100);
36
38
  this.listCache = this.managerOptions.listCache || new datamanager_1.MapCache(100);
@@ -109,6 +111,25 @@ class FirestoreDataManager {
109
111
  }
110
112
  return this.firestore.updateDoc(ref, serializedData);
111
113
  }
114
+ /**
115
+ * Update only the internal metadata fields of a document.
116
+ *
117
+ * Unlike {@link _update}, this bypasses the user-provided converter so it never re-serializes
118
+ * (and therefore never clobbers) user data. This matters because the user converter rebuilds the
119
+ * full document shape, which turns absent fields into `undefined` and can overwrite existing map
120
+ * fields with empty objects when Firestore strips the undefined values.
121
+ */
122
+ async _updateMetadata(id, metadata, options) {
123
+ const serializedData = this.metadataConverter.toFirestore({
124
+ ...metadata,
125
+ [FirestoreMetadata_1.FIRESTORE_KEYS.UPDATED_AT]: this.firestore.serverTimestamp(),
126
+ });
127
+ const ref = this.firestore.doc(this.collection, id);
128
+ if (options?.transaction) {
129
+ return options.transaction.update(ref, serializedData);
130
+ }
131
+ return this.firestore.updateDoc(ref, serializedData);
132
+ }
112
133
  async update(id, data, options) {
113
134
  await this._update(id, data, options);
114
135
  }
@@ -183,10 +204,7 @@ class FirestoreDataManager {
183
204
  }
184
205
  async delete(id, options) {
185
206
  if (this.managerOptions.deleteMode === 'soft') {
186
- await this._update(id, {
187
- ...{},
188
- [FirestoreMetadata_1.FIRESTORE_KEYS.DELETED]: true,
189
- }, options);
207
+ await this._updateMetadata(id, { [FirestoreMetadata_1.FIRESTORE_KEYS.DELETED]: true }, options);
190
208
  return;
191
209
  }
192
210
  if (options?.transaction) {
@@ -16,8 +16,8 @@ export type FirestoreSerializedMetadata = {
16
16
  [FIRESTORE_INTERAL_KEYS.UPDATED_AT]: FirestoreTypes.Timestamp;
17
17
  };
18
18
  export declare class FirestoreMetadataConverter implements InternalFirestoreDataConverter<Metadata, FirestoreSerializedMetadata> {
19
- toFirestore(data: WithFieldValue<WithoutId<Metadata>>): {
20
- __deleted: FirestoreTypes.FieldValue | FirestoreTypes.WithFieldValue<boolean>;
19
+ toFirestore(data: Partial<WithFieldValue<WithoutId<Metadata>>>): {
20
+ __deleted: boolean;
21
21
  __createdAt: FirestoreTypes.Timestamp;
22
22
  __updatedAt: FirestoreTypes.Timestamp;
23
23
  };
@@ -16,6 +16,7 @@ var FIRESTORE_KEYS;
16
16
  class FirestoreMetadataConverter {
17
17
  toFirestore(data) {
18
18
  return {
19
+ // Cast: value may be absent on partial metadata writes; Firestore strips undefined fields
19
20
  [FIRESTORE_INTERAL_KEYS.DELETED]: data[FIRESTORE_KEYS.DELETED],
20
21
  // Cast: Firestore handles conversion from Date to Timestamp internally
21
22
  [FIRESTORE_INTERAL_KEYS.CREATED_AT]: data[FIRESTORE_KEYS.CREATED_AT],
@@ -70,7 +70,8 @@ class FirestoreReference extends datamanager_1.LiveReference {
70
70
  if (!(0, utils_1.checkIfReferenceExists)(docSnapshot))
71
71
  throw new Error(`Document does not exist ${this.docRef.path}`);
72
72
  const data = docSnapshot.data(this.options?.snapshotOptions);
73
- if (this.options?.filterDeleted && data?.deleted === true) {
73
+ const deletedFlag = data?.[FirestoreMetadata_1.FIRESTORE_KEYS.DELETED];
74
+ if (this.options?.filterDeleted && deletedFlag === true) {
74
75
  return undefined;
75
76
  }
76
77
  return data;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@data-weave/backend-firestore",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "author": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "registry": "https://registry.npmjs.org/"
24
24
  },
25
25
  "devDependencies": {
26
- "@data-weave/datamanager": "~0.7.1",
26
+ "@data-weave/datamanager": "~0.7.2",
27
27
  "@firebase/firestore": "^4.7.8",
28
28
  "@firebase/functions-types": "^0.6.3",
29
29
  "@google-cloud/firestore": "^7.11.1",