Let's create a "hello, world!" program with a twist: the message might come from a different process (like inside an AWS Lambda function) than the one printing it out.
You can run synapse init
in an empty directory to start or just copy-paste the below code into a .ts
file:
import { Function } from 'synapse:srl/compute'
const hello = new Function(() => {
return { message: 'hello, world!' }
})
export async function main(...args: string[]) {
console.log(await hello())
}
For quick testing, this can be deployed to the "local" target (no cloud required):
synapse deploy --target local
And now we can execute our program:
synapse run
# { message: 'hello, world!' }
Synapse applications continue to exist until we explicitly delete them. This can be done with the destroy
command:
synapse destroy
Local deployments are nice and all, but what if you want something a little more scalable? Assuming you have valid credentials (this is dependent on your cloud provider), then moving to the cloud is as simple as changing the target:
synapse deploy --target aws
Everything else still works the same. We can run our program just like before:
synapse run
Synapse contains built-in interfaces for common cloud resources. These are split into broad categories and are found within synapse:srl/*
modules.
Everything involving running/executing code:
Function
- simplest unit of compute; a "serverless" functionHttpService
- creates an HTTP(S) endpoint. Routes can be added via the methodroute
. The first argument is the HTTP method/verb and second is the path-pattern e.g.GET
and/hello/{name}
will match a GET request to/hello/world
. Path parameters can be accessed using the first parameter of the route callbackreq.pathParameters
:
import { HttpService } from 'synapse:srl/compute'
const service = new HttpService()
service.route('GET', '/hello/{name}', req => {
return new Response(`hello, ${req.pathParameters.name}`)
})
export async function main() {
const resp = await fetch(`${service.invokeUrl}/hello/world`).then(r => r.text())
console.log(resp)
}
Resources for holding state:
Bucket
- most basic form of storage; a blob storeTable
- a simple database table, can mostly be used likeMap
Queue
- LIFO queueCounter
- atomic integer store
Resources specific to networking. Currently only contains HostedZone
for describing DNS zones.
Applies your code to the current target, creating or updating a deployment as-needed.
The default target is your current machine i.e. the "local" target. You can change the destination using the --target
option like so:
synapse deploy --target aws
Currently, this always uses the default credentials configured for a given cloud target.
Subsequent deployments for the same program use the currently deployed target. You must teardown the existing deployment before you can change the target.
You can view the changes Synapse will make without applying them by providing the --dry-run
flag:
synapse deploy --dry-run
These changes always represnt the "worst-case" scenario. Some changes may not be required, however, it's not always possible to know that ahead of time.
The deploy view uses the following colors/characters to represent different actions:
+
(green) - create-
(red) - delete~
(blue) - update±
(yellow) - replace
Only "top-level" names are displayed in this view. For example:
function createBucketClosure() {
const bucket = new Bucket()
return new Function(async (key: string) => bucket.get(key))
}
const myFn = createBucketClosure()
Will only show myFn
and not bucket
.
Deletes all resources in the current deployment, if any.
This command does not complete until all resources in a deployment are either deleted or were attempted to delete.
Any failures are reported on completion, which may require manual intervention to fix. destroy
can be ran again after fixing any issues.
Runs an "executable" in the current application.
Executables are any TypeScript file that exports a "main" function:
export function main() {
console.log('hello, world!')
}
synapse run main.ts
# hello, world!
You can omit the file if it's unambiguous e.g. there's only 1 executable file:
synapse run
# hello, world!
Arguments can be passed using the --
switch:
export function main(name: string) {
console.log('hello, ${name}!')
}
synapse run -- alice
# hello, alice!
Enters an interactive REPL session, optionally using a target file. The target file's exports are placed in the global scope.
export function foo() {
return 'foo'
}
synapse repl main.ts
> foo()
# 'foo'
Prints a motivational quote fetched from a public Synapse application.
These commands expose lower-level functionality that you might find useful.
Deletes all cached data for the current application.
The best cache is one you don't know about, but sometimes things break! If you're running into obscure errors and nothing seems to be working, run synapse clean
before trying again.
If that fixes your problem, it would be incredibly helpful to open an issue with the following information:
- The error/problem you were seeing
- Any details/specifics about the code you're working on that you're comfortable with sharing (exact source code is best)
- Commands you ran before seeing the issue (it's ok if you don't know exactly)
Caching bugs are frustrating to experience, so these issues are given a high priority.
Note that the package cache is not cleaned by default. Use the following to clear the package cache as well:
synapse clean --packages
Writes out the current build artifacts to disk.
By default, this will write to outDir
from tsconfig.json
if found, otherwise ./out
. You can change the destination using the --outDir
option:
synapse emit --outDir dist