Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions docs/orm/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ head:
content: Object-Relational Mapping (ORM) | SignalDB
- - meta
- name: og:description
content: Learn how to use SignalDB for ORM-like functionality with reactive relationships, static methods, instance methods, and TypeScript support.
content: Learn how to use SignalDB for ORM-like functionality with reactive relationships, instance methods, and TypeScript support.
- - meta
- name: description
content: Learn how to use SignalDB for ORM-like functionality with reactive relationships, static methods, instance methods, and TypeScript support.
content: Learn how to use SignalDB for ORM-like functionality with reactive relationships, instance methods, and TypeScript support.
- - meta
- name: keywords
content: SignalDB, ORM, reactive database, JavaScript ORM, TypeScript ORM, object relational mapping, reactive relationships, database methods, SignalDB tutorials, SignalDB features
Expand All @@ -26,11 +26,11 @@ head:

SignalDB provides functionality to add methods to [collections](/reference/core/collection/) and item instances to enable ORM-like behavior. With this functionality, you can also reactively resolve relationships between items in different collections.

## Adding Static Methods to Collections
## Adding Instance Methods to Collections

To add new static methods to a specific collection instance, we have to create a a new class that inherits from the collection class and use it like a kind of [singleton](https://en.wikipedia.org/wiki/Singleton_pattern). With this pattern, it's also possible to directly define collection options like the name or the persistence adapter.
To add new methods to a specific collection instance, we have to create a new class that inherits from the collection class. With this approach, it's also possible to directly define collection options like the name or the persistence adapter.

In the example below, we create a new class `PostsCollection` that inherits from the `Collection` class and adds a new static method `getPublishedPosts` to the class. This method returns all published posts from the collection.
In the example below, we create a new class `PostsCollection` that inherits from the `Collection` class and add a new method `findPublishedPosts` to the class. This method returns a `Cursor` to all published posts from the collection.

```js
import { Collection } from '@signaldb/core'
Expand All @@ -44,8 +44,8 @@ class PostsCollection extends Collection {
})
}

// static method to get all published posts
static getPublishedPosts() {
// instance method to find all published posts
findPublishedPosts() {
return this.find({ published: true })
}

Expand All @@ -54,7 +54,7 @@ class PostsCollection extends Collection {
const Posts = new PostsCollection()


const publishedPosts = Posts.getPublishedPosts().fetch()
const publishedPosts = Posts.findPublishedPosts().fetch()
```

You can use this pattern to add methods to your collection that predefines queries that you use often in your application like in the example above.
Expand Down Expand Up @@ -147,7 +147,7 @@ In the example above, we create three classes `Post`, `Comment`, and `User` that

## TypeScript Support

When extending the collection class with static methods, TypeScript works seamlessly without additional setup. However, adding instance methods to item instances requires using a helper class to maintain type safety for the instance class. This is because we need to include all item properties in the class interface.
Adding instance methods to collection or item instances requires using a helper class to maintain type safety for the instance class. This is because we need to include all properties in the class interface.

```ts
declare interface BaseEntity<T extends {}> extends T {}
Expand Down
17 changes: 15 additions & 2 deletions docs/sync/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,20 +238,33 @@ syncManager.addCollection(someCollection, {

### Implementing the `pull` method

After we've added our collection to the `syncManager`, we can start implementing the `pull` method. The `pull` method is responsible for fetching the latest data from the server and applying it to the collection. The `pull` method is called whenever the `syncAll` or the `sync(name)` method are called. During sync, the `pull` method will be called for each collection that was added to the `syncManager`. It's receiving the collection options, passed to the `addCollection` method, as the first parameter and an object with additional information, like the `lastFinishedSyncStart` and `lastFinishedSyncEnd` timestamps, as the second parameter. The `pull` method must return a promise that resolves to an object with either an `items` property containing all items that should be applied to the collection or a `changes` property containing all changes `{ added: T[], modified: T[], removed: T[] }`.
After we've added our collection to the `syncManager`, we can start implementing the `pull` method. The `pull` method is responsible for fetching the latest data from the server and applying it to the collection. The `pull` method is called whenever the `syncAll` or the `sync(name)` method are called. During sync, the `pull` method will be called for each collection that was added to the `syncManager`. It's receiving the collection options, passed to the `addCollection` method, as the first parameter and an object with additional information, like the `lastFinishedSyncStart` and `lastFinishedSyncEnd` timestamps, as the second parameter. The `pull` method must return a promise that resolves to an object with either:
- an `items` property containing **_all items_** from the server, without limiting the result set (`syncManager` will internally do a snapshot comparison between the local and the fetched items to determine and apply the changes to the collection):
```ts
const syncManager = new SyncManager({
// …
pull: async ({ apiPath }) => {
const data = await fetch(apiPath).then(res => res.json())

return { items: data }
},
// …
})
```
- or a `changes` property containing only changes (`{ added: T[], modified: T[], removed: T[] }`) since the last sync (this is usefull when we do not want to always fetch the full data set from the server):
```ts
const syncManager = new SyncManager({
// …
pull: async ({ apiPath }, { lastFinishedSyncStart }) => {
const data = await fetch(`${apiPath}?since=${lastFinishedSyncStart}`).then(res => res.json())

return { items: data }
return { changes: data }
},
// …
})
```


### Implementing the `push` method

The `push` method is responsible for sending the changes to the server. The `push` method is called during sync for each collection that was added to the `syncManager` if changes are present. It's receiving the collection options, passed to the `addCollection` method, as the first parameter and an object including the changes that should be sent to the server as the second parameter. The `push` method returns a promise without a resolved value.
Expand Down