Description
This is a rough outline for what sorts of features are being thought about for Synapse. Broader goals like improved error messages, UI tweaks, and bug fixes are not included. They are in no particular order. It's highly unlikely that many of these will be implemented without significant help.
The Goals
-
Broader integrations
- Azure
- GCP
- Docker
- Kubernetes
- CloudFlare
- Fly.io
- GitHub
- Let's Encrypt
-
Richer "buildtime" features
- Top-tier support for containers
- Bundling native modules
- Importing files other than TS/JSON
- Improved custom resources (e.g. proper serialization of state)
- CSS-like API for per-vendor customization of resources
- More operations during synthesis such as addition with deferred values e.g.
<resource>.foo + 5
- Type reification (extremely useful for code generation beyond just TypeScript)
- Investigate TypeSpec as an alternative
- Support QuickJS as a target runtime for latency-sensitive applications
- We can probably use heuristics to determine which JS engine (V8 vs. JSC vs. QuickJS vs. SpiderMonkey) would work best for different code
-
Performance
- Minify built-in
node:*
modules - Automatically prune unused
node:*
modules to reduce binary size & startup time - Investigate compiling TS files on multiple threads
- Continue modifying Node.js to improve perf (maybe startup snapshot code can be optimized)
- Periodically collect garbage in
$SYNAPSE_INSTALL/build
in a forked process watch
or "daemon" modes to keep more things in memory
- Minify built-in
-
User code optimization
- Extremely aggressive code elimination
- Prune code blocks that will never execute e.g.
const foo = false; if (foo) { ... }
- De-dupe equivalent functions/classes through normalization and usage analysis
- Prune code blocks that will never execute e.g.
- Automatic polymorphism reduction
- Extremely aggressive code elimination
-
ECMAScript features
- ESM including TLA (already partially supported)
- Serialization of decorators
-
TypeScript features
baseUrl
andpaths
resolutionconfigDir
substitution- Possibly
rootDirs
(need to see more use-cases) - Embed
tsconfig
inpackage.json
(need to patch the TS language server with a VFS)
-
Package manager
- Respect
.npmrc
(partially implemented) - Support install scripts
- Many scripts are used to build from source. Can we simplify this somehow?
- "Environment aware" package lock
- Respect
-
Make sure various frontend libraries/frameworks work well
- Lit
- Vue
- Possibly more depending on feasibility
-
Seamless Zig/TypeScript integration
- This is already partially implemented but only exposed internally
- Compile to WASM for browser, dynamic libs otherwise
- Improved C fastcall ergonomics
-
Improve
synapse:*
APIsynapse:test
is incompletesynapse:http
is not as web-friendly as it could be- Use more standard interfaces like
Blob
insynapse:srl/*
-
Enhancements to
deploy
- Support for moving resources in state when renaming/moving resources in code
- Experience will be similar to
git merge
i.e. automatic for simple cases, manual intervention otherwise
- Experience will be similar to
- Prefer "create before delete" for replacements (can be used for blue/green deploys)
- Rework state format to uniquely identify resource instances
- Deterministic serialization
- Put resources created by
test
in a completely separate deployment to improve robustness - Generate schemas for custom resources to improve the output of
deploy --dry-run
- Support for moving resources in state when renaming/moving resources in code
-
Observing and operating deployed applications
synapse repl
(done but marked internal)- Inspecting deployment state via
synapse show
(done but marked internal) - Simple commands to inspect logs (by app, resource, etc.)
- API for monitoring, possibly under
synapse:srl/monitor
?- Make exporting logs from resources easy, additional features can come later
Sustainability
Implementing all of these things under a single project can quickly lead to a complicated mess, both for users and developers. Our goal is to implement improvements without impeding future progress. Which means:
- Leverage powerful but simple abstractions.
- Design by experimentation. We don't want something that works "in theory", we want something that works.
- Spend more time on frequently-used interfaces, less on implementation details.
- Start with fewer, goal-orientated tests. More detailed tests can be added as the implementation is used, iterated on, and refined.
- Avoid significant refactors unless it's clear and obvious that doing so will improve functionality.
- De-dupe patterns, not necessarily code. Excessive abstractions are far more frustrating than a bit of duplication.
- Progressive disclosure applies to designing a good UX just as much as creating libraries, APIs, and protocols. Of course, be pragmatic. A marginally better DX is probably not worth significant performance penalties. Code deeper in a system should treat other code as its users, not developers.