Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1 from satohshi/optional-expand
Browse files Browse the repository at this point in the history
update
  • Loading branch information
satohshi authored Jan 1, 2024
2 parents 7bd7f1b + fb97424 commit 7ddb89f
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 89 deletions.
7 changes: 7 additions & 0 deletions .changeset/modern-books-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"pb-option-builder": patch
---

- Better handling of situations where relation field in "expand" is optional
- Added autocomplete for "sort"
- Added support for ":excerpt" modifier
61 changes: 53 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This is how you would normally write options for the PocketBase SDK:
fields: 'id,title,expand.comments(post).user,expand.comments(post).message,expand.tags.id,expand.tags.name'
}
```
Writing options manually like this is very error-prone and hard to read/maintain.
Writing options manually like this is very error-prone, and makes the code very hard to read/maintain.

This option builder allows you to write it like this instead:
```js
Expand All @@ -22,7 +22,7 @@ This option builder allows you to write it like this instead:
]
}
```
It comes with autocomplete for `key`, `fields` and `expand` options, and also provides you a way to **type the response**.
It comes with autocomplete for `key`, `fields`, `expand` and `sort` options, and also provides you a way to **type the response**.


## Installation
Expand Down Expand Up @@ -80,8 +80,10 @@ type Relations = {

// back-relations
"posts(tags)": Array<Post>
"comments(post)": Array<Comment>
"comments(user)": Array<Comment>

// Add "?" modifier to annotate optional relation fields
"comments(post)"?: Array<Comment> // i.e. post might not have any comments
"comments(user)"?: Array<Comment> // i.e. user might not have any comments
}
```
Expand All @@ -101,7 +103,7 @@ const [optionsObj, typeObj] = optionBuilder({
expand: [
{
key: 'tags'
// returns all fields if it's not specified
// returns all fields if not specified
},
{
key: 'comments(post)',
Expand All @@ -127,7 +129,7 @@ const result = await pb.collection('posts').getOne<typeof typeObj>(optionsObj);
It's a bit hacky and not very pretty, but does the job.


### Parameter type for `optionBuilder`:
### Parameter type for the option builder:
```ts
{
// Table name as defined in "Schema"
Expand All @@ -152,7 +154,6 @@ ExpandItem {
fields?: // same as above
expand?: // same as above
}

```


Expand All @@ -161,7 +162,7 @@ ExpandItem {
You might run into a situation where you have a component that requires a specific set of fields to be passed to it, and it makes sense to fetch the item directly in one route, but in another, it makes sense to do so through `expand`.


Because of the way the argument for the option builder is structured, the `fields` array is portable.
Because of the way the parameter for the option builder is structured, the `fields` array is portable.
You can define the fields in one place, and use it either at the top level, or in the `expand` option **as is** .

Example:
Expand Down Expand Up @@ -199,6 +200,49 @@ const [optionsObj, typeObj] = optionBuilder({
})
```


### Handling of optional relation fields
Let's say you want to get a post with its comments using `expand`.
When the post doesn't have any comments, the SDK (or PocketBase itself rather) returns:

```ts
{
id: "1",
title: "Lorem ipsum",
tags: ["lorem", "ipsum"],
created: "2024-01-01T00:00:00.000Z",
updated: "2024-01-01T00:00:00.000Z"
}
```

The response won't even have

```ts
{
expand: undefined
}
// or
{
expand: {
"comments(post)": []
}
}
```

So if all the specified expands are for optional relation fields, the option builder will add `?` modifier to the expand field itself.
i.e. the return type will be:

```ts
Post & {
expand?: {
"comments(post)": Comment[]
}
}
```

If you don't need this much of type-safety and find this behaviour annoying, you can opt out by not adding `?` when defining `Relation`.


## Caveat:
In order for back-relations to work, you need to have the forward-relations defined as well.
```ts
Expand All @@ -221,6 +265,7 @@ const [optionsObj, typeObj] = optionBuilder({
})
```


## Why not just integrate this into the SDK?
- This way, you can start using this in existing projects without having to change anything. I think most of the time, you don't need to pass in any options to the SDK, so installing a new custom SDK for a very few instances where you need to seems like an overkill.
- There are many functionalities of the official SDK that I don't use or understand fully, and I don't want to maintain a fork of it just for this.
Loading

0 comments on commit 7ddb89f

Please sign in to comment.