-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
367 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# observer() HOC | ||
|
||
The `observer()` Higher-Order Component (HOC) is used to make React components reactive to changes in TeamPlay signals. | ||
|
||
## Syntax | ||
|
||
```javascript | ||
observer(Component) | ||
``` | ||
|
||
## Parameters | ||
|
||
- `Component`: The React component to be made reactive. | ||
|
||
## Return Value | ||
|
||
Returns a new component that is reactive to TeamPlay signals. | ||
|
||
## Example | ||
|
||
```javascript | ||
import { observer, $ } from 'teamplay' | ||
|
||
const UserProfile = observer(({ userId }) => { | ||
const $user = $.users[userId] | ||
return <div>{$user.name.get()}</div> | ||
}) | ||
``` | ||
|
||
## Features | ||
|
||
1. **Reactivity**: Components wrapped with `observer()` will automatically re-render when any TeamPlay signal they use changes. | ||
|
||
2. **Suspense Integration**: `observer()` automatically wraps the component in a Suspense boundary, handling loading states for asynchronous operations. | ||
|
||
## Notes | ||
|
||
- Always wrap components that use TeamPlay signals with `observer()` to ensure they update when data changes. | ||
- `observer()` optimizes re-renders by only updating when the specific data used in the component changes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# Query Signals | ||
|
||
Query signals in TeamPlay represent the result of a query on a collection. They are created using the `sub()` function or `useSub()` hook with query parameters. | ||
|
||
## Creating a Query Signal | ||
|
||
```javascript | ||
const $activeUsers = await sub($.users, { status: 'active' }) | ||
``` | ||
|
||
## Properties and Methods | ||
|
||
### ids | ||
|
||
A signal containing an array of IDs for the documents in the query result. | ||
|
||
```javascript | ||
const userIds = $activeUsers.ids.get() | ||
``` | ||
|
||
### map(callback) | ||
|
||
Maps over the documents in the query result. | ||
|
||
```javascript | ||
const userNames = $activeUsers.map($user => $user.name.get()) | ||
``` | ||
|
||
### reduce(callback, initialValue) | ||
|
||
Reduces the documents in the query result to a single value. | ||
|
||
```javascript | ||
const totalAge = $activeUsers.reduce(($user, total) => total + $user.age.get(), 0) | ||
``` | ||
|
||
### find(predicate) | ||
|
||
Finds the first document in the query result that satisfies the predicate. | ||
|
||
```javascript | ||
const $firstAdminUser = $activeUsers.find($user => $user.role.get() === 'admin') | ||
``` | ||
|
||
## Iteration | ||
|
||
Query signals are iterable, allowing you to use them in `for...of` loops: | ||
|
||
```javascript | ||
for (const $user of $activeUsers) { | ||
console.log($user.name.get()) | ||
} | ||
``` | ||
|
||
## Notes | ||
|
||
- Query signals are reactive. Changes to the underlying data or to the query result will automatically update components using the query signal. | ||
- The documents within a query signal are themselves signals, allowing for nested reactivity. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Server-side API | ||
|
||
TeamPlay provides a server-side API for setting up the backend and handling connections. This API is typically used in your server setup code. | ||
|
||
## createBackend() | ||
|
||
Creates a new TeamPlay backend instance. | ||
|
||
```javascript | ||
import { createBackend } from 'teamplay/server' | ||
|
||
const backend = createBackend() | ||
``` | ||
|
||
## initConnection(backend, options) | ||
|
||
Initializes the connection handler for WebSocket connections. | ||
|
||
```javascript | ||
import { initConnection } from 'teamplay/server' | ||
|
||
const { upgrade } = initConnection(backend, options) | ||
``` | ||
|
||
### Parameters | ||
|
||
- `backend`: The TeamPlay backend instance created with `createBackend()`. | ||
- `options` (optional): An object with the following properties: | ||
- `fetchOnly` (default: `true`): If true, server-side subscriptions are not reactive. | ||
|
||
### Return Value | ||
|
||
Returns an object with an `upgrade` function to be used with a Node.js HTTP server. | ||
|
||
## Usage Example | ||
|
||
```javascript | ||
import http from 'http' | ||
import { createBackend, initConnection } from 'teamplay/server' | ||
|
||
const server = http.createServer() | ||
const backend = createBackend() | ||
const { upgrade } = initConnection(backend) | ||
|
||
server.on('upgrade', upgrade) | ||
|
||
server.listen(3000, () => { | ||
console.log('Server started on port 3000') | ||
}) | ||
``` | ||
|
||
## Additional Exports | ||
|
||
TeamPlay's server module also re-exports some utilities: | ||
|
||
- `ShareDB`: The underlying ShareDB library. | ||
- `mongo`, `mongoClient`, `createMongoIndex`: MongoDB utilities. | ||
- `redis`, `redlock`: Redis utilities. | ||
- `sqlite`: SQLite utility. | ||
|
||
These can be imported from `teamplay/server` if needed for advanced configurations. | ||
|
||
## Notes | ||
|
||
- The server-side API is designed to work with Node.js HTTP servers. | ||
- For production use, it's recommended to use MongoDB by setting the `MONGO_URL` environment variable. | ||
- When deploying to a cluster with multiple instances, set the `REDIS_URL` environment variable for proper scaling. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# Signal Methods | ||
|
||
TeamPlay signals come with a set of methods for interacting with the data they represent. These methods are available on all signals, whether they're created using `$()`, accessed through the root signal `$`, or returned by `sub()` or `useSub()`. | ||
|
||
## get() | ||
|
||
Retrieves the current value of the signal. | ||
|
||
```javascript | ||
const value = $signal.get() | ||
``` | ||
|
||
## set(value) | ||
|
||
Updates the value of the signal. | ||
|
||
```javascript | ||
await $signal.set(newValue) | ||
``` | ||
|
||
Note: `set()` is asynchronous and returns a Promise. | ||
|
||
## del() | ||
|
||
Deletes the value of the signal or removes an item from an array. | ||
|
||
```javascript | ||
await $signal.del() | ||
``` | ||
|
||
Note: `del()` is asynchronous and returns a Promise. | ||
|
||
## push(value) | ||
|
||
Adds a value to the end of an array signal. | ||
|
||
```javascript | ||
await $signal.push(newItem) | ||
``` | ||
|
||
## pop() | ||
|
||
Removes and returns the last item from an array signal. | ||
|
||
```javascript | ||
const lastItem = await $signal.pop() | ||
``` | ||
|
||
## increment(value) | ||
|
||
Increments a numeric signal by the specified value (or by 1 if no value is provided). | ||
|
||
```javascript | ||
await $signal.increment(5) | ||
``` | ||
|
||
## add(value) | ||
|
||
Adds a new item to a collection signal, automatically generating a unique ID. | ||
|
||
```javascript | ||
const newId = await $signal.add({ name: 'New Item' }) | ||
``` | ||
|
||
## Notes | ||
|
||
- All methods that modify data (`set()`, `del()`, `push()`, `pop()`, `increment()`, `add()`) are asynchronous and return Promises. This ensures data consistency with the server. | ||
- The `get()` method is synchronous and returns the current local value of the signal. | ||
- These methods can be chained on nested signals, e.g., `$.users[userId].name.set('New Name')`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# sub() Function | ||
|
||
The `sub()` function is used to subscribe to data from the server in TeamPlay. It can be used to subscribe to individual documents or to query multiple documents. | ||
|
||
## Syntax | ||
|
||
```javascript | ||
sub(signal, [queryParams]) | ||
``` | ||
|
||
## Parameters | ||
|
||
- `signal`: A signal representing the collection or document to subscribe to. | ||
- `queryParams` (optional): An object containing query parameters when subscribing to multiple documents. | ||
|
||
## Return Value | ||
|
||
Returns a Promise that resolves to a signal representing the subscribed data. | ||
|
||
## Examples | ||
|
||
### Subscribing to a single document | ||
|
||
```javascript | ||
const $user = await sub($.users[userId]) | ||
console.log($user.name.get()) | ||
``` | ||
|
||
### Subscribing to a query (multiple documents) | ||
|
||
```javascript | ||
const $activeUsers = await sub($.users, { status: 'active' }) | ||
``` | ||
|
||
## Notes | ||
|
||
- The `sub()` function is asynchronous and returns a Promise. | ||
- When used in React components, it's recommended to use the `useSub()` hook instead, which handles the asynchronous nature of subscriptions in a React-friendly way. | ||
- Subscribed data is automatically kept in sync with the server. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# useSub() Hook | ||
|
||
The `useSub()` hook is a React hook that combines the functionality of the `sub()` function with React's component lifecycle. It's used to subscribe to TeamPlay data within React components. | ||
|
||
## Syntax | ||
|
||
```javascript | ||
const $data = useSub(signal, [queryParams]) | ||
``` | ||
|
||
## Parameters | ||
|
||
- `signal`: A signal representing the collection or document to subscribe to. | ||
- `queryParams` (optional): An object containing query parameters when subscribing to multiple documents. | ||
|
||
## Return Value | ||
|
||
Returns a signal representing the subscribed data. | ||
|
||
## Example | ||
|
||
```javascript | ||
import { observer, $, useSub } from 'teamplay' | ||
|
||
const UserProfile = observer(({ userId }) => { | ||
const $user = useSub($.users[userId]) | ||
return <div>{$user.name.get()}</div> | ||
}) | ||
``` | ||
|
||
## Features | ||
|
||
1. **Automatic Subscription Management**: `useSub()` handles subscribing when the component mounts and unsubscribing when it unmounts. | ||
|
||
2. **Suspense Integration**: It works seamlessly with React Suspense, automatically handling loading states. | ||
|
||
3. **Reactivity**: Changes to the subscribed data will cause the component to re-render. | ||
|
||
## Notes | ||
|
||
- `useSub()` should be used within components wrapped with `observer()` to ensure proper reactivity. | ||
- It's designed to work with React's rules of hooks, so it should not be used in conditional statements. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.