Add Declarative Web Framework Design

Michael Zhang 2024-10-17 23:49:01 +00:00
parent 181849d640
commit ae5ece7c13

@ -0,0 +1,127 @@
# Declarative Web Framework
The eventual goal of this is to create a language that compiles down to files, in a very similar way to Nix. The idea is to have a pure language that describes an impure computation.
* Some kind of type that represents "files" on disk. This is the compile output
* Need a way of saying "generate me a path during compile-time" in a way that all of the downstreams still refer to the same path
* Could be a hash based on the file:span of the invocation?
* Lots of tools for performing string parsing and editing
* A higher-level "resource" that may compile to files.
* A resource consists of:
* Arbitrary attribute set, that can include other sub-resources
* Recommended to only have one of the following two:
* A set of "default" sub-resources to include
* A set of files to emit
* A function that operates over and modifies other resources
* Example: a database schema may be a higher-level resource. Compiling this should result in some database files
* To perform migrations, the migration CLI tool that's generated would write a file indicating the new state of the database it just learned back into the source repo to be checked in.
* I think the type signature should look something like this:
* ```
DatabaseTable : {
name: String,
files: Set<File>,
// Resources is essentially a set of files along with some particular fields of interest
// Here, apply is allowed to assume that all the files in the files field exist
apply: Resources -> Resources
}
```
* A concept of a "singleton" resource
* I think this would mostly be for the post-compilation step, where including for example any DocumentationResource should trigger a post-compilation collection of all documentation resources
* Quoting for various source code languages like Javascript
## Stages of compilation
1. A non-Turing complete step is used to collect everything into a flat set of resources
2. An optional post-compilation step is run, consisting of all the PostCompilationResource
## Example components
### Auth plugin
```
let db : SQLDatabase<Sqlite> = ...
let adaptor : SQLWithDb<_> = Adaptor({ db })
let authPlugin = AuthPlugin({
backend: ... // some kind of config for a database adaptor
// one example would be "SQL db w/ password"
// another could be "SQL db w/ magic link"
clientStrategy: ... // some config like session cookie or jwt
allowGuests: true,
})
authPlugin would be {
base: Resource,
usersTable: SQLTableResource,
loginRoute: (LoginRouteOpts) -> EndpointResource,
loginComponent: (LoginComponentOpts) -> WebComponentResource,
registerRoute: (RegisterRouteOpts) -> EndpointResource,
registerComponent: (RegisterComponentOpts) -> WebComponentResource,
}
```
### Comments plugin
```
let commentsPlugin = CommentsPlugin({
})
result {
base: Resource,
component: (CommentComponentOpts) -> WebComponentResource,
}
```
### Example endpoint
```
let submitFlagComponent = ({}) => {
let endpoint = EndpointResource({
guards: {
user: UserAuthGuard(),
flags: DbTableGuard(flagTable),
flagChecker: FlagCheckerGuard(user),
submittedFlag: PostJsonFieldGuard("flag", "string"),
},
// This entire next part emits an AST, it does NOT actually run this code
action: do {
result <- flagChecker(submittedFlag);
flags.insert({
userId: user.id,
flag: submittedFlag,
correct: result.correct,
});
return result;
}
})
let inputBox = WebComponentResource(jsxQuote!(
({ postSubmit }) => {
const error = useState();
const onSubmit = () => {
const result = await fetch(#{endpoint.url}, { method: "POST" });
};
return <form onSubmit={onSubmit}>
<input placeholder="Submit flag..." />
</form>;
}
))
Resource.bundle([ endpoint, inputBox ])
}
```
### Deploy to kubernetes plugin
This would be a function that takes a resource consisting of a bunch of endpoints, database tables, etc. and produces a deploy script
### Deploy to docker compose plugin
Run a post-compile script that produces a docker image with a particular image name, as well as a `docker-compose.yml` file
### Documentation
There should be a "documentation resource" type, which gets collected all together with a search index
## Open questions
* Need something like multi-stage programs? Functions annotated with @stage(n). Can't imagine a situation needing this yet
*