Skip to content

Commit

Permalink
rip macro
Browse files Browse the repository at this point in the history
  • Loading branch information
actualwitch committed Jan 15, 2025
1 parent 7cf7510 commit 934d23c
Show file tree
Hide file tree
Showing 16 changed files with 78 additions and 70 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ concurrency:
cancel-in-progress: false

env:
BUILD_PATH: spa
BUILD_PATH: static

jobs:
build:
Expand All @@ -30,11 +30,11 @@ jobs:
id: pages
uses: actions/configure-pages@v5
- run: BASE_URL="/experiment" bun run build:spa
- run: cp ./spa/index.html ./spa/404.html
- run: cp ./static/index.html ./static/404.html
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: spa
path: static

deploy:
environment:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.DS_Store
node_modules
build
spa
static
*.bun-build
magick

Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Architecture

This project uses custom architecture I refer to as `entangled atoms` which extends [jōtai](https://jotai.org/) atoms to synchronize state across different [realms](https://262.ecma-international.org/#realm). This allows for end-to-end isomorphic state management where same primitives are used to manage state everywhere. Unconventional nature of this approach led me to design my own boilerplate; after trying out different runtimes I decided to make use of [Bun](https://bun.sh/) which is very fast and offers neat features like macros and programmatically accessible bundler.
This project uses custom architecture I refer to as `entangled atoms` which extends [jōtai](https://jotai.org/) atoms to synchronize state across different [realms](https://262.ecma-international.org/#realm). This allows for end-to-end isomorphic state management where same primitives are used to manage state everywhere. Unconventional nature of this approach led me to design my own boilerplate; after trying out different runtimes I decided to make use of [Bun](https://bun.sh/) which is very fast.

There is no Next.js, Remix, Vite, Webpack or Babel here; my aim is simplicity and minimalism in terms of requirements and general architecture. Currently, boilerplate implements full streaming Server-Side Rendering(SSR) with transparent bundling, hydration and Server-Sent Events(SSE) for state sync.

Expand Down
16 changes: 6 additions & 10 deletions scripts/build.bin.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { $ } from "bun";
import { VERSION } from "../src/const/dynamic";

const TARGETS = ["linux-x64", "linux-arm64", "windows-x64", "darwin-x64", "darwin-arm64"];
import { revisionAtom } from "../src/atoms/common";
import { store } from "../src/store";

$`rm -rf ./build`;

// Build all targets
await Promise.all(
TARGETS.map(
(target) =>
$`bun build --compile --minify --target=bun-${target}-modern ./src/entry/server.tsx --outfile ./build/experiment-${VERSION}-${target}`,
),
);
const revision = await store.get(revisionAtom);

for (const target of ["linux-x64", "linux-arm64", "windows-x64", "darwin-x64", "darwin-arm64"]) {
await $`bun build --compile --minify --target=bun-${target}-modern ./src/entry/server.tsx --outfile ./build/experiment-${revision}-${target}`;
}
10 changes: 5 additions & 5 deletions scripts/build.spa.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { $ } from "bun";
import { name, description, iconResolutions } from "../src/const";
import { name, description, iconResolutions, staticDir } from "../src/const";
import { getHtml } from "../src/entry/_handlers";
import { getManifest } from "../src/feature/pwa/manifest";
import { ROUTES } from "../src/feature/router";
import { assignToWindow } from "../src/utils/hydration";

// why does this work but running it from Bun.build fails? #justbunthings
await $`bun build ./src/entry/client.tsx --outdir ./spa --minify`;
await $`bun build ./src/entry/client.tsx --outdir ./${staticDir} --minify`;
// const buildResult = await Bun.build({
// entrypoints: ["./src/entry/client.tsx"],
// outdir: "./spa",
Expand All @@ -29,14 +29,14 @@ for (const route of ROUTES) {
baseUrl,
);

await Bun.write(`./spa/${pathname}.html`, html);
await Bun.write(`./${staticDir}/${pathname}.html`, html);
}

await Bun.write(
"./spa/manifest.json",
`./${staticDir}/manifest.json`,
JSON.stringify(getManifest(name, description, iconResolutions, baseUrl), null, 2),
);

for (const res of iconResolutions) {
await $`cp ./.github/assets/experiment-${res}.png ./spa`;
await $`cp ./.github/assets/experiment-${res}.png ./${staticDir}`;
}
20 changes: 19 additions & 1 deletion src/atoms/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Result } from "true-myth";
import { createFileStorage, getStoragePath, resolve, spawn } from "../utils";
import { divergentAtom, entangledAtom } from "../utils/entanglement";
import { getRealm, hasBackend } from "../utils/realm";
import { author } from "../const";
import { author, version } from "../const";
import type { _Message, SerialExperiment, ExperimentWithMeta, Message } from "../types";
import { modelLabels, type ProviderType } from "../feature/inference/types";

Expand Down Expand Up @@ -257,3 +257,21 @@ export const localCertAndKeyAtom = atom(async () => {
}
return Result.ok({ key: `${getStoragePath()}/cert.key`, cert: `${getStoragePath()}/key.cert` });
});

export const revisionAtom = entangledAtom(
"revision",
atom(async (get) => {
const result = await spawn("git", ["rev-parse", "HEAD"]);
const hash = result.map((hash) => hash.slice(0, 4));
const revision = [version, hash.unwrapOr(undefined)].filter(Boolean).join("-");
return revision;
}),
);

export const debugAtom = entangledAtom(
"debug",
atom(() => {
if (getRealm() !== "server") return false;
return process.env.DEBUG === "true";
}),
);
21 changes: 21 additions & 0 deletions src/atoms/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { atom } from "jotai";
import { getRealm } from "../utils/realm";
import { Maybe } from "true-myth";
import { resolve, spawn } from "../utils";
import { clientFile, staticDir } from "../const";

export const clientScriptAtom = atom(async () => {
if (getRealm() !== "server") return Maybe.nothing();
const result = await spawn("bun", ["build", "./src/entry/client.tsx", "--outdir", `./${staticDir}`, "--minify"]);
if (result.isErr) {
console.error(result.error);
return Maybe.nothing();
}
const fs = await resolve("fs/promises");
const readFile = fs.map((fs) => fs.readFile);
if (readFile.isOk) {
const file = await readFile.value(`./${staticDir}/${clientFile}`, "utf8");
return Maybe.just(file);
}
return Maybe.nothing();
});
10 changes: 0 additions & 10 deletions src/const/_macro.ts

This file was deleted.

9 changes: 0 additions & 9 deletions src/const/dynamic.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/const/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import project from "../../package.json";

export const clientFile = "/client.js";
export const staticDir = "static";

export const schema = "http";
export const hostname = "localhost";
Expand Down
11 changes: 6 additions & 5 deletions src/entry/_handlers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import { log } from "../utils/logger";
import { Shell } from "../root";
import { publish, subscribe, type Update } from "../utils/æther";
import { eventStream } from "../utils/eventStream";
import { getClientAsString } from "./_macro" with { type: "macro" };
import { getManifest } from "../feature/pwa/manifest";
import { clientFile, description, iconResolutions, name } from "../const";
import type { Nullish } from "../types";
import { clientScriptAtom } from "../atoms/server";
import { store } from "../store";

export const getHtml = (location: string, additionalScripts?: Array<string | Nullish>, baseUrl?: string) => {
const html = renderToString(
Expand All @@ -34,10 +35,10 @@ export const doStatic = async (request: Request) => {
});
}
if (url.pathname === clientFile) {
response = new Response(await getClientAsString(), {
headers: {
"Content-Type": "application/javascript",
},
const clientScript = await store.get(clientScriptAtom);
response = clientScript.match({
Just: (script) => new Response(script, { headers: { "Content-Type": "application/javascript" } }),
Nothing: () => new Response("KO", { status: 500 }),
});
}
if (response) {
Expand Down
13 changes: 0 additions & 13 deletions src/entry/_macro.ts

This file was deleted.

9 changes: 6 additions & 3 deletions src/entry/server.spa.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { clientFile, hostname, port } from "../const";
import { FIXTURES, isFixture } from "./_fixtures";
import { assignToWindow, createHydrationScript } from "../utils/hydration";
import { getHtml } from "./_handlers";
import { getClientAsString } from "./_macro" with { type: "macro" };
import { setRealm } from "../utils/realm";
import { store } from "../store";
import { clientScriptAtom } from "../atoms/server";

export default {
development: true,
Expand All @@ -14,8 +15,10 @@ export default {
const url = new URL(req.url);
console.log(url.pathname, clientFile);
if (url.pathname === clientFile) {
return new Response(await getClientAsString(), {
headers: { "Content-Type": "application/javascript" },
const clientScript = await store.get(clientScriptAtom);
return clientScript.match({
Just: (script) => new Response(script, { headers: { "Content-Type": "application/javascript" } }),
Nothing: () => new Response("KO", { status: 500 }),
});
}
const fixture = url.searchParams.get("fixture");
Expand Down
5 changes: 2 additions & 3 deletions src/entry/server.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { $, type Serve } from "bun";
import { hostname, port } from "../const";
import { DEBUG } from "../const/dynamic";
import { createFetch } from "../utils/handler";
import { doPOST, doSSE, doStatic, doStreamingSSR } from "./_handlers";
import { store } from "../store";
import { localCertAndKeyAtom } from "../atoms/common";
import { debugAtom, localCertAndKeyAtom } from "../atoms/common";

process.env.REALM = "ssr";

Expand All @@ -13,7 +12,7 @@ const tls = (await store.get(localCertAndKeyAtom))
.unwrapOr(undefined);

export default {
development: DEBUG,
development: store.get(debugAtom),
hostname,
port,
fetch: createFetch(doSSE, doPOST, doStatic, doStreamingSSR),
Expand Down
8 changes: 4 additions & 4 deletions src/feature/router/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import styled from "@emotion/styled";
import { atom, useAtom } from "jotai";
import { NavLink, useLocation } from "react-router";

import { TRIANGLE } from "../../const";
import { TRIANGLE, version } from "../../const";
import { experimentsSidebarAtom, ROUTES } from ".";
import { bs } from "../../style";
import { nonInteractive, widthAvailable } from "../../style/mixins";
import { portalIO } from "../../utils/portal";
import { templatesAtom } from "../../atoms/common";
import { VERSION } from "../../const/dynamic";
import { revisionAtom, templatesAtom } from "../../atoms/common";
import { increaseSpecificity } from "../../style/utils";

export const [SidebarInput, SidebarOutput] = portalIO();
Expand Down Expand Up @@ -83,6 +82,7 @@ const SidebarComponent = () => {
export const NavigationSidebar = () => {
const [routes] = useAtom(routesAtom);
const location = useLocation();
const [revision] = useAtom(revisionAtom);
return (
<Navigation>
<header>
Expand All @@ -100,7 +100,7 @@ export const NavigationSidebar = () => {
{(location.pathname === "/" || location.pathname.startsWith("/experiment")) && <SidebarComponent />}
</GrowBox>
<Footer>
© ∞ {TRIANGLE} {VERSION}
© ∞ {TRIANGLE} {revision}
</Footer>
</Navigation>
);
Expand Down
5 changes: 3 additions & 2 deletions src/utils/logger.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { DEBUG } from "../const/dynamic";
import { store } from "../store";
import { debugAtom } from "../atoms/common";

export const log = (...args: any[]) => {
if (DEBUG) {
if (store.get(debugAtom)) {
const timestamp = new Date().toISOString();
console.log(timestamp, ...args);
}
Expand Down

0 comments on commit 934d23c

Please sign in to comment.