Skip to content

Commit

Permalink
More docs
Browse files Browse the repository at this point in the history
  • Loading branch information
JadenSimon committed Jun 24, 2024
1 parent 91cbef5 commit 254d60b
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 3 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ irm https://synap.sh/install.ps1 | iex

See [Quick Start](./docs/getting-started.md#quick-start) for basic instructions.

For help with specific features:
* [Custom Resources](./docs/custom-resources.md)
* [Environments](./docs/environments.md)
* [Packages](./docs/packages.md)
* [Tests](./docs/testing.md)

## Attributions

Expand Down
73 changes: 73 additions & 0 deletions docs/packages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
## Overview

A "package" is a collection of code that is meant to be shared. Packages allow you to build and/or deploy software without knowing exactly how other packages are implemented.

### `package.json`

Synapse follows in the footsteps of `npm`, and so it uses `package.json` to determine which directories are packages. [The documentation from `npm`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json) also applies to Synapse except for the following fields:
* `files` *
* `directories`
* `man`
* `config`
* `publishConfig`
* `overrides` *
* `scripts` **
* `bundleDependencies`

Legend:
- \* Under consideration
- ** Partial support

Package `scripts` can be executed with `synapse run` but are otherwise ignored. This includes "install" scripts, which means packages that rely on building from source on install do not work yet.

### Publishing

Publishing packages is currently limited to the following destinations:

* A local repository via `synapse publish --local`
* An archive using `synapse publish --archive <name>`

Support for publishing directly to `npm` is planned in addition to a repository specifically for Synapse.

### "Deployed" Packages

Code produced by Synapse can be shared _after_ running `synapse deploy`. The shared code is no longer 1:1 with the source code but rather a reduced form of it.

A good example of this is an SDK for an API. See [this directory](../examples/sdk-and-cli/) for a mini project that creates an SDK + CLI tool.

### Best Practices

It is ***incredibly important*** to understand that "deployed" packages are _not_ always isolated from changes you make to the original package. This is because the package might reference resources that you can change.

***If you were to run `synapse destroy`, all consumers of the package might immediately break if you delete referenced resources!***

Fortunately, Synapse has safeguards to prevent someone from accidentally doing this. But we still need solutions for stopping more subtle problems.

#### Environments

[Environments](./environments.md) are a great way to test changes in isolation. Future improvements will make packages more "environment-aware".

<!-- #### Pipelines (Experimental)
The potentially high-stakes involved with changing deployed packages often warrants more sophisticated automation.
Pipelines are a form of automation that splits things up into stages connected in sequence. Changes are only moved ("promoted") to the next changes after passing an arbitrary set of checks (tests, manual approval, etc.).
This setup means you can test changes in total isolation before sending them out to the world. -->

#### Rollbacks (Experimental)

A deployment can be changed back to its previous configuration through several mechanisms:

* Manually with `synapse rollback`
* When tests fails via `synapse test --rollback-if-failed`
* When deploying fails via `synapse deploy --rollback-if-failed`

Rollbacks are best-effort. Their success (or failure) is dependent on which resources were changed. In particular, resources that cause side-effects are less likely to be safely rolled back.

#### Immutable Deployments (Planned)

Many resources, particularly stateless ones, do not need to be updated in-place. Instead, each deploy operation can create a new resource with the changes and swap out the references.

This ensures that existing code behaves _exactly_ the same, bugs and all. The downside is that there are, more often than not, practical limitations to constantly creating new resources. But we believe these can be addressed over time.

51 changes: 51 additions & 0 deletions examples/sdk-and-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
## SDK + CLI

This example shows how you can use Synapse to:
* Configure and deploy backend infrastructure
* Create an "SDK" for that infrastructure
* Build a CLI tool that uses the SDK

Because our client-side code doesn't use anything specific to `node`, the SDK would work in a browser too!

### Project Structure

We've split up the code into two packages:
* `cli` - Feeds input from the command line into the client from `sdk`
* `sdk` - Creates a bucket + public service to use the bucket. We export a function to create our client.

Note that all of this code can be placed into a single package instead. This may be preferred for small projects.

### Building

First navigate to `sdk` and run the following:

```shell
synapse deploy
synapse publish --local
```

This will deploy the necessary infrastructure + expose our `createClient` function.

Now navigate to `cli`. Because `main.ts` doesn't specify any infrastructure, we can immediately try things out:

```shell
synapse run -- put foo bar
# Put object foo
synapse run -- get foo
# bar
```

We can also use `synapse build` to create a standalone executable:

```shell
synapse build
./out/bin/cli get foo # or cli.exe on Windows
```

Or if we just want an executable JavaScript bundle:

```shell
synapse build --no-sea
./out/main.js get foo # or `[synapse|node|bun|deno] ./out/main.js get foo` on Windows
```

24 changes: 24 additions & 0 deletions examples/sdk-and-cli/cli/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { createClient } from 'sdk'

const client = createClient()

export async function main(command: string, key: string, val?: string) {
switch (command) {
case 'get':
const obj = await client.getObject(key)
console.log(obj)
break

case 'put':
if (val === undefined) {
throw new Error('Expected a value for the "put" command')
}

await client.putObject(key, val)
console.log('Put object', key)
break

default:
throw new Error(`Invalid command: ${command}`)
}
}
7 changes: 7 additions & 0 deletions examples/sdk-and-cli/cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "cli",
"bin": "./main.ts",
"dependencies": {
"sdk": "spr:#sdk"
}
}
28 changes: 28 additions & 0 deletions examples/sdk-and-cli/sdk/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { HttpService } from 'synapse:srl/compute'
import { Bucket } from 'synapse:srl/storage'
import { fetch } from 'synapse:http'

const bucket = new Bucket()
const service = new HttpService({ auth: 'none' })

const getRoute = service.addRoute('GET /{key+}', async req => {
const { key } = req.pathParameters
return bucket.get(key, 'utf-8')
})

const putRoute = service.addRoute('PUT /{key+}', async (req, body: string) => {
const { key } = req.pathParameters
await bucket.put(key, body)
})

export function createClient() {
async function getObject(key: string): Promise<string> {
return fetch(getRoute, key)
}

async function putObject(key: string, obj: string): Promise<void> {
await fetch(putRoute, key, obj)
}

return { getObject, putObject }
}
4 changes: 4 additions & 0 deletions examples/sdk-and-cli/sdk/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "sdk",
"exports": "./main.ts"
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "synapse",
"version": "0.0.6",
"version": "0.0.7",
"bin": "./src/cli/index.ts",
"dependencies": {
"esbuild": "^0.20.2",
"typescript": "~5.4.5"
"typescript": "~5.4.5",
"postject": "github:Cohesible/postject"
},
"devDependencies": {
"@types/node": "^20.11.27",
"postject": "github:Cohesible/postject",
"@cohesible/auth": "file:packages/auth.tgz",
"@cohesible/quotes": "file:packages/quotes.tgz",
"@cohesible/resources": "file:packages/resources.tgz"
Expand Down

0 comments on commit 254d60b

Please sign in to comment.