Skip to content

Commit

Permalink
Added set, fixed update
Browse files Browse the repository at this point in the history
  • Loading branch information
alexiglesias93 committed Oct 25, 2023
1 parent 2bc2f2d commit 945dc3c
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 2 deletions.
10 changes: 10 additions & 0 deletions .changeset/sharp-guests-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'fireworkers': minor
---

**This release deliberately contains backwards-incompatible changes**. To avoid automatically picking up releases like this, you should either be pinning the exact version of `fireworkers` in your `package.json` file (recommended) or be using a version range syntax that only accepts patch upgrades such as `^0.2.0` or `~0.2.0`. See npm's documentation about [semver](https://docs.npmjs.com/cli/v6/using-npm/semver/) for more information.

- feat: add new `Firestore.set()` method that matches the behavior of the SDK's [setDoc](https://firebase.google.com/docs/reference/js/firestore_.md#setdoc).
- fix: update `Firestore.update()` to match the behavior of the SDK's [updateDoc](https://firebase.google.com/docs/reference/js/firestore_.md#updatedoc):
- Fields will be merged instead of overriding the entire document.
- Operations will fail if the document doesn't exist.
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ const newTodo = await Firestore.create(db, 'todos', {

### update(db, ...document_path, fields)

Updates or inserts a document.
Updates fields in a document. The update will fail if applied to a document that does not exist.

Implements the same functionality as Firestore's [updateDoc](https://firebase.google.com/docs/reference/js/firestore_.md#updatedoc).

#### db

Expand Down Expand Up @@ -187,6 +189,48 @@ const updatedTodo = await Firestore.update(db, 'todos', 'aDyjLiTViX1G7HyF74Ax',

---

### set(db, ...document_path, fields, options?)

Writes to a document. If the document does not yet exist, it will be created. If you provide `merge`, the provided data can be merged into an existing document.

Implements the same functionality as Firestore's [setDoc](https://firebase.google.com/docs/reference/js/firestore_.md#setdoc_2).

#### db

Type: `DB`

The DB instance.

#### document_path

Type: `string`

The document path, defined like in [get](#document_path).

#### fields

Type: `Record<string, any>`

The fields to update.

#### (Optional) options.merge

Type: `boolean`

If set to `true`, the provided data will be merged into an existing document instead of overwriting.

```typescript
const updatedTodo = await Firestore.update(
db,
'todos',
'aDyjLiTViX1G7HyF74Ax',
{ completed: false },
{ merge: true }
);
```

---

### remove(db, ...document_path)

Removes a document.
Expand Down
61 changes: 61 additions & 0 deletions src/set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { create_document_from_fields, extract_fields_from_document } from './fields';
import type * as Firestore from './types';
import { get_firestore_endpoint } from './utils';

type Options = {
merge?: boolean;
};

/**
* Writes to a document. If the document does not yet exist, it will be created.
* Similar to the SDK's [setDoc](https://firebase.google.com/docs/reference/js/firestore_.md#setdoc).
*
* Reference: {@link https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents/patch}
*
* @param firestore
* @param document_path
* @param fields
*/
export const set = async <Fields extends Record<string, any>>(
{ jwt, project_id }: Firestore.DB,
...args: [...string[], Fields] | [...string[], Fields, Options]
) => {
let paths;
let fields;
let options;

if (typeof args.at(-2) === 'object') {
paths = args.slice(0, -2) as string[];
fields = args.at(-2) as Fields;
options = args.at(-1) as Options;
} else {
paths = args.slice(0, -1) as string[];
fields = args.at(-1) as Fields;
}

const payload = create_document_from_fields(fields);
const endpoint = get_firestore_endpoint(project_id, paths);

if (options?.merge) {
// Ensure that the fields are updated without overwriting the rest of the document
for (const key in fields) {
endpoint.searchParams.append('updateMask.fieldPaths', key);
}
}

const response = await fetch(endpoint, {
method: 'PATCH',
body: JSON.stringify(payload),
headers: {
Authorization: `Bearer ${jwt}`,
},
});

const data: Firestore.GetResponse = await response.json();

if ('error' in data) throw new Error(data.error.message);

const document = extract_fields_from_document<Fields>(data);
return document;
};
12 changes: 11 additions & 1 deletion src/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { get_firestore_endpoint } from './utils';

/**
* Updates a document.
* Similar to the SDK's [updateDoc](https://firebase.google.com/docs/reference/js/firestore_.md#updatedoc).
*
* Reference: {@link https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents/patch}
*
* @param firestore
Expand All @@ -18,8 +20,16 @@ export const update = async <Fields extends Record<string, any>>(
const paths = args.slice(0, -1) as string[];
const fields = args.at(-1) as Fields;

const endpoint = get_firestore_endpoint(project_id, paths);
const payload = create_document_from_fields(fields);
const endpoint = get_firestore_endpoint(project_id, paths);

// Fail if the document doesn't exist, similar to the SDK's [updateDoc](https://firebase.google.com/docs/reference/js/firestore_.md#updatedoc)
endpoint.searchParams.set('currentDocument.exists', 'true');

// Ensure that the fields are updated without overwriting the rest of the document
for (const key in fields) {
endpoint.searchParams.append('updateMask.fieldPaths', key);
}

const response = await fetch(endpoint, {
method: 'PATCH',
Expand Down

0 comments on commit 945dc3c

Please sign in to comment.