aweft
A full-stack toolkit for applications whose state is a document. An observable document is the model, the wire and the storage format at once: assign to it, and the change is a commit that a page renders, a peer receives and a store keeps. Every piece is a package with one job, and a package that does not need another does not know it exists.
Hello, three ways
A document:
import { atomic, createObject, observer } from '@aweftjs/core';
const doc = createObject({ title: 'plan', done: 0 });
const stop = observer(doc).path('title').watch(() => console.log(doc.title));
doc.title = 'plan b'; // one commit; the watcher runs once
atomic(() => { doc.title = 'plan c'; doc.done = 1; }); // one commit, however much it writes
stop();A page:
import { mutable } from '@aweftjs/core';
import { h, mount } from '@aweftjs/ui';
const Counter = () => {
const clicks = mutable(0);
return <button theme="button" onClick={() => clicks.set(clicks.get() + 1)}>clicked {clicks} times</button>;
};
mount(document.body, <Counter />);A server:
import { auth, paths } from '@aweftjs/auth';
import { fromDirectory } from '@aweftjs/modules/node';
import { createServer } from '@aweftjs/server';
import { node } from '@aweftjs/server/node';
import { createStore, memoryDriver } from '@aweftjs/store';
const store = createStore({ driver: memoryDriver(), declare: { ...paths } });
const server = createServer({ sources: [fromDirectory('./modules'), auth], store, gate: 'auth/Gate', listener: node({ port: 8080 }) });
await server.start();That is the whole boot. Everything else the server does is a module in ./modules, and the page reaches it over one socket that carries both the shared documents and the calls. recipes/full-stack/ is the two halves in one directory, with the page reaching the server in development through the dev server's proxy; its README carries the manifest and tsconfig an application starts from.
The page hello, running: the same file the block above shows.