Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs page update #4

Merged
merged 2 commits into from
Apr 13, 2024
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"label": "Tutorial - Extras",
"label": "Core Concepts",
"position": 3,
"link": {
"type": "generated-index"
Expand Down
13 changes: 13 additions & 0 deletions docs/core-concepts/mutators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Mutators

**Mutators** are Javascript functions, defined by the developer, that define logic to transform the shared application state. A key feature of mutators is that *they run twice*:
- Mutators are first run on the client against the client's local state, and the client's user interface updates almost immediately. The mutation does not wait for a server response. This is intentional, and is also vital in keeping the client's perceived response times low and the user experience smooth. Because these mutators have not yet been confirmed by the authoritative server, the mutations made by this first run of mutators are known as optimistic mutations. 

- Mutators are then run by the server against the server's state, which is the authoritative state. Although the defined mutators are the same, because the mutators are now run against the server's state instead of the client's state, the result of the mutation may be different. This occurrence is a normal part of the syncing process. When the server broadcasts its authoritative updates and if the client state with applied optimistic mutations is different than the authoritative state sent by the server, Syncosaurus will automatically roll back its applied optimistic mutations and apply updates to match the server's authoritative state.

Because mutators are just high-level Javascript functions, the developer gains a high level of flexibility and control in how and when updates should be mutated. Mutators can be used to not only modify the shared state of a collaborative application. These mutators can also be used to selectively aggregate, merge, and delete different pieces of the shared state, as well as to implement custom application logic or fine-grained authorization.

my list

- hello
- world
5 changes: 5 additions & 0 deletions docs/core-concepts/presence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Presence

As its name implies, **presence** allows for information on connected clients to be broadcast. Data like who is currently connected in a room, where each client's cursor is in the app, or the latest status update for each client are "ephemeral", *lasting only as long as that client is connected.* Thus, since this data is by definition temporary, these updates should be treated differently from client updates that may affect the shared application state. Presence data is effectively received, possibly transformed, and then immediately broadcasted.

A key feature of collaborative applications is presence data which lets each user know who is collaborating on the document and their intent. In many web applications, this is often implemented by displaying avatars indicating who is currently looking at the document and/or displaying the cursors of other clients. Because the data for these features is ephemeral and inconsequential to the state of the application, it is treated differently than other state-related data in the Syncosaurus Framework.
3 changes: 3 additions & 0 deletions docs/core-concepts/rooms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Rooms

The primary unit of collaboration within a Syncosaurus application is the **room**, a central coordination point and data store location. Much like a physical meeting room may serve as a hub for multiple individuals to communicate and exchange information and ideas, a room in Syncosaurus serves as a hub for users of a collaborative application (known as *clients*) to share updates and access the same data. In both scenarios, any update sent by any individual within a room may be received by all individuals present within the room, and any individual in the room also has access to the room's shared data (assuming they have permission to do so.) As with an individual moving in the physical world, a client in a collaborative web application can also move between different rooms, which often has its own features and rules. The application developer is ultimately responsible for determining these room attributes and how they align with the attributes of clients entering, collaborating, and leaving those rooms.
17 changes: 17 additions & 0 deletions docs/core-concepts/subscriptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Subscriptions

A **subscription** is what allows clients to monitor if and when changes occur to the shared state of a room, regardless if the source of a change is local or from the authoritative server. **Queries** work hand-in-hand with subscriptions, allowing for a customization of what state changes are being monitored. Queries are able to filter, aggregate and transform the shared state, or only portions of the shared state, to enable more granular application behavior and logic. These abilities are non-mutating and do not affect the shared application state, as it is only the server that can dictate final changes to shared state.

A subscription is a custom React hook (`useSubscribe`) that uses the React `useState` hook under the hood to read data from the local store and re-render components when updates to the value(s) for a specific key or set of keys in the local storage occur. The key or set of keys that a subscription watches for updates to their values (aka a watchlist, ) and are defined in the query argument of the `useSubscribe` hook. A query is a developer-defined function that defines the set of keys in the watchlist and it can also perform additional logic to transform the data before it is returned and re-rendered by the React code. When a query is executed, a `readTransaction` is created so any key provided to `has` or `get` or any of the keys returned by the `scan` method end up in the watchlist. Note that `useSubscribe` takes two additional arguments, the `syncosaurus` instance and an initial state for the value (like the one provided to `useState` when using it directly in a React application).

Here is an example mutator definition for the same counter above:

```javascript
const count = useSubscribe(synco, (tx) => tx.get('count'), 0)
```

## <a name="deltaupdates"></a>Delta Updates

Delta updates are a list of idempotent updates run by each client to bring it up to date with the server. Delta updates have two forms that correspond to the `WriteTransaction` write methods `set` and `delete`:
- `put` which informs a client to update the value of a certain key in its local store
- `del` which informs a client to remove the key (and therefore value) from its local store
7 changes: 7 additions & 0 deletions docs/getting-started/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"label": "Getting Started",
"position": 2,
"link": {
"type": "generated-index"
}
}
79 changes: 79 additions & 0 deletions docs/getting-started/add-to-existing-project.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Add to an Existing Project

To add Syncosaurus to an existing React-based project:

1. Navigate to the root directory of your application
2. Run the command `npx syncosaurus setup`

That's it! Make sure to correctly configure your Syncosaurus application before deployment - see here for details.

Note that Syncosaurus currently only supports applications built with either React or a React-based framework.

## Spin up a local development environment

A local development environment makes it significantly easier to rapidly iterate, test, and debug your application in a consistent, controlled setting. Syncosaurus comes built-in with a local Syncosaurus server.

If you added Syncosaurus to an existing project and are not using Vite as your build tool, run the same command with the `-b` or `-backendOnly` flag enabled:

```shell
npx syncosaurus dev -b
```

If your file structure adheres to Syncosaurus rules, and your configuration settings are correct, the localhost address with your designated port to your local Syncosaurus server will be displayed in the terminal output:

```shell
❯ npx syncosaurus dev -b
Checking for Syncosaurus installation...... found
Initializing local dev environment...... done!

--------------------------------------------------
🦖 Your local Syncosaurus dev server is ready at http://localhost:8787
Press 'x' to gracefully shut down the server
```

Make sure to update your `server` value in your Syncosaurus constructor calls in your application code:

```javascript
import { v4 as uuidv4 } from 'uuid';
import mutators from './mutators.js';

const synco = new Syncosaurus({
// update this value to the local Syncosaurus server URL
server: "http://localhost:8787",
userID: uuidv4(),
auth: "4fJbGOWma=QEebX6H1X6AAe3/yok1R-fwKMqot5XOvxPU0YwI!sm8nQ!"
mutators,
});
```

## Deploy your Syncosaurus project

When you are ready to deploy your Syncosaurus application, make sure the following requirements are first met:

1. Make sure that you are logged in to Cloudflare.
1. You can check your login status with `syncosaurus whoami`
2. If you are not logged in, run `syncosaurus login` and provide your Cloudflare credentials via OAuth or API token.
2. Navigate to your root directory of your project, which needs to have a `syncosaurus.json` configuration file.
3. Make sure your mutators are correctly defined in your `mutators.js` file, and your `mutators.js` file is located in the `src` sub-directory.
4. Make sure your authentication handler is correctly defined in your `authHandler.js` file, and your `authHandler.js` file is located in the `src` sub-directory.

Once the above requirements have been fulfilled, run the following command in your terminal:

```shell
npx syncosaurus deploy
```

If your application was configured correctly, the URL to your deployed application should be displayed in your terminal output, which will look akin to the output displayed below:

```shell
❯ npx syncosaurus deploy
🦖 syncosaurus 0.7.1
--------------------------------------------------

Evolving your Syncosaurus server... done!

✅ Success! Your Syncosaurus server is available at
https://kitten.josephliang.workers.dev
```

For instructions on deploying your frontend, see here YOU NEED TO LINK HERE
91 changes: 91 additions & 0 deletions docs/getting-started/start-a-new-project.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Start a New Project

## Setup

To create a new Syncosaurus application, simply run the following command in your terminal:

```shell
npx syncosaurus init
```

That's it! Follow the prompts to set up your new Syncosaurus project.

## Spin up a local development environment

A local development environment makes it significantly easier to rapidly iterate, test, and debug your application in a consistent, controlled setting. Syncosaurus comes built-in with both a local Syncosaurus server. If you are building a Syncosaurus project from scratch using `syncosaurus init`, Syncosaurus includes a local Vite UI server as well!

To start both the Syncosaurus server and the Vite UI server, run the following command in your terminal:

```shell
npx syncosaurus dev
```

If your file structure adheres to Syncosaurus rules, and your configuration settings are correct, two localhost addresses will be displayed in your terminal output:
- a localhost address for your local Syncosaurus server
- The port used will be the port you designated in the `syncosaurus.json` file. If one is not specified there, the local Syncosaurus server will default to port 3001.
- a localhost address for your local Vite UI server
- The port used will be determined by Vite. Vite's default port is port 5173. If that port is being used, Vite will find and designate the next available port.

Your output will look something like the following:

```shell
my-projects/my-synco-app via ⬢ v21.7.1
❯ npx syncosaurus dev
Checking for Syncosaurus installation...... found
Initializing local dev environment...... done!

--------------------------------------------------
🦖 Your local Syncosaurus dev server is ready at http://localhost:8787
🚀 Your local Vite UI server is ready at http://localhost:5173

Press 'x' to gracefully shut down both servers
```

Make sure to update your `server` value in your Syncosaurus constructor calls in your application code:

```javascript
import { v4 as uuidv4 } from 'uuid';
import mutators from './mutators.js';

const synco = new Syncosaurus({
// update this value to the local Syncosaurus server URL
server: "http://localhost:8787",
userID: uuidv4(),
auth: "4fJbGOWma=QEebX6H1X6AAe3/yok1R-fwKMqot5XOvxPU0YwI!sm8nQ!"
mutators,
});
```

Now you're all set - freely iterate on your application, and see your code changes live!

## Deploy your Syncosaurus application

When you are ready to deploy your Syncosaurus application, make sure the following requirements are first met:

1. Make sure that you are logged in to Cloudflare.
1. You can check your login status with `syncosaurus whoami`
2. If you are not logged in, run `syncosaurus login` and provide your Cloudflare credentials via OAuth or API token.
2. Navigate to your root directory of your project, which needs to have a `syncosaurus.json` configuration file.
3. Make sure your mutators are correctly defined in your `mutators.js` file, and your `mutators.js` file is located in the `src` sub-directory.
4. Make sure your authentication handler is correctly defined in your `authHandler.js` file, and your `authHandler.js` file is located in the `src` sub-directory.

Once the above requirements have been fulfilled, run the following command in your terminal:

```shell
npx syncosaurus deploy
```

If your application was configured correctly, the URL to your deployed application should be displayed in your terminal output, which will look akin to the output displayed below:

```shell
❯ npx syncosaurus deploy
🦖 syncosaurus 0.7.1
--------------------------------------------------

Evolving your Syncosaurus server... done!

✅ Success! Your Syncosaurus server is available at
https://kitten.josephliang.workers.dev
```

For instructions on deploying your frontend, see here.
3 changes: 3 additions & 0 deletions docs/getting-started/synco-walkthrough.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Complete Tutorial

work-in-progress
7 changes: 7 additions & 0 deletions docs/guides/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"label": "Guides",
"position": 4,
"link": {
"type": "generated-index"
}
}
27 changes: 27 additions & 0 deletions docs/guides/analytics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Analytics

Syncosaurus includes an application analytics tool to easily view and analyze aggregate and single-room metrics for your Syncosaurus application.

For setup and basic usage of the Syncosaurus application, see [here](https://github.com/syncosaurus/syncosaurus-dashboard?tab=readme-ov-file#syncosaurus-dashboard)

### Metrics Info

All metrics are grouped and organized against time, by the hour, over 24 hours (a full day). The timezone for all metrics is GMT.

The following statistics are provided for the aggregated 'All Rooms Metrics' option:
- Total \# of active rooms per hour
- Max \# of websocket connections per hour
- Average \# of connections per active room per hour
- Total \# of inbound websocket messages per hour
- Total \# of outbound websocket messages per hour
- Total \# of exceeded CPU errors per hour
- Total \# of exceeded memory errors per hour
- Total \# of fatal internal errors per hour

The following metrics are provided for 'Individual Room Metrics' option:
- Max \# of websocket connections per hour
- Total \# of inbound websocket messages per hour
- Total \# of outbound websocket messages per hour
- Total \# of exceeded CPU errors per hour
- Total \# of exceeded memory errors per hour
- Total \# of fatal internal errors per hour
37 changes: 37 additions & 0 deletions docs/guides/authentication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Authentication

## Authentication

The Syncosaurus framework supports token-based authentication. JWTs are commonly utilized, but other types of token-based authentication like OAuth can be used as well.

### Setup

In order to implement authentication, you need two components:

- a token(s) or preferably a library or service that can generate new tokens
- an authentication service that verifies the validity of tokens

#### `auth` token

To use a token, pass it to the `auth` parameter of the `Syncosaurus` constructor:

IMAGE WAS HERE

#### `authHandler.js`

Next, an `authHandler` function needs to be defined:

IMAGE WAS HERE

Note that in order for your Syncosaurus server to correctly read, access, and verify your authentication tokens, the authentication handler function `authHandler` must adhere to the following requirements:
- The function must be named `authHandler`
- The function must be placed in the `src` subdirectory of your Syncosaurus project. Do not place `authHandler.js` in a subdirectory of the `src` directory.
- `authHandler.js` must be a module that exports the `authHandler` function as its default export.

Both the `auth` token and the `authHandler` function need to be correctly defined and appropriately handle errors in order for Syncosaurus to correctly implement authentication in your application.

By default, the Syncosaurus server will reject a request if the `authHandler` throws any type of error.

For an example of authentication implemented in a Syncosaurus application, see here.

WIP
28 changes: 28 additions & 0 deletions docs/guides/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Configuration (`syncosaurus.json`)

Configuration options for Syncosaurus are set with the `syncosaurus.json` file in the root directory of your Syncosaurus project.

Running `syncosaurus init` to scaffold a new project or `syncosaurus setup` to add Syncosaurus to an existing project will automatically add a `syncosaurus.json` configuration file to the root directory of your project.

## `syncosaurus.json` configuration options

### `projectName`

This is the name of your Syncosaurus project. This value will be used when deploying your Syncosaurus project to Cloudflare. Though Syncosaurus will also conduct a check, make sure there are no conflicts of this value with any of your deployed workers.

### `msgFrequency`

This is the amount of time (in milliseconds) that subsequent message broadcast of app updates should be delayed.
The default value of `msgFrequency` is `16` (ms), which equates to approximately 62.5 broadcasted updates per second.

### `useStorage`

This value determines whether your application persists data to the Syncosaurus server using [Cloudflare's Transactional Storage API] (https://developers.cloudflare.com/durable-objects/api/transactional-storage-api/)

The default value of `useStorage` is `false`.

### `autosaveInterval`

This is the amount of time (in milliseconds) that subsequent saves of your application's authoritative state's to persistence should be delayed. If the value of `useStorage` is `false`, this value will be ignored.

The default value of `autosaveInterval` is `30000` (ms), so a "save" will occur once every 30 seconds.
3 changes: 3 additions & 0 deletions docs/guides/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Deployment

WIP
17 changes: 17 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
slug: /
sidebar_position: 1
---

# Syncosaurus Introduction

Syncosaurus is a performant, collaborative, real-time Javascript framework that enables developers to focus on their application's features and business logic instead of the complexities of state synchronization and conflict resolution.

Built with Cloudflare's [Durable Objects](https://developers.cloudflare.com/durable-objects/).

## Features

- An synchronization engine based on server reconciliation (which is completely compatible with CRDTs!)
- The ability to automatically persist state on a per-room basis
- A convenient CLI tool to seamlessly create, configure, manage, and deploy your collaborative application.
- An analytics dashboard to monitor your collaborative application's usage and error metrics
Loading