@sigil-dev/grimoire 0.8.0 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -6
- package/server.ts +1 -0
- package/src/client/router.ts +291 -291
- package/src/dev/compile-module.ts +4 -13
- package/src/dev/hmr-server.ts +11 -11
- package/src/dev/runtime-bundle.ts +8 -5
- package/src/integrations/vite.ts +1 -1
- package/src/logger/index.ts +6 -0
- package/src/logger/instance.ts +6 -0
- package/src/logger/logger.ts +113 -0
- package/src/logger/request-middleware.ts +24 -0
- package/src/logger/transports.ts +117 -0
- package/src/logger/types.ts +39 -0
- package/src/rendering/hydrate.ts +119 -119
- package/src/rendering/index.ts +1 -1
- package/src/rendering/ssrPlugin.ts +4 -2
- package/src/routing/router.ts +2 -2
- package/src/routing/scanner.ts +1 -1
- package/src/routing/transform-routes.ts +1 -1
- package/src/server/build.ts +3 -3
- package/src/server/coordinator.ts +4 -5
- package/src/server/index.ts +9 -11
- package/src/server/worker.ts +0 -1
- package/test/context.test.ts +2 -2
- package/test/hydration.test.ts +1 -1
- package/test/middleware.test.ts +1 -1
- package/test/rendering.test.ts +3 -3
- package/test/scanning.test.ts +3 -3
- package/test/server.test.ts +3 -3
- package/test/transform-routes.test.ts +3 -3
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { transformSync } from "@babel/core";
|
|
3
3
|
import sigilPlugin from "@sigil-dev/compiler/babel";
|
|
4
|
+
import { log } from "../logger/instance";
|
|
4
5
|
import type { GrimoirePlugin } from "../types";
|
|
5
6
|
|
|
7
|
+
const logger = log.scope("scope");
|
|
6
8
|
let registered = false;
|
|
7
9
|
|
|
8
10
|
export function registerSSRPlugin(plugins: GrimoirePlugin[] = []) {
|
|
@@ -27,7 +29,7 @@ export function registerSSRPlugin(plugins: GrimoirePlugin[] = []) {
|
|
|
27
29
|
|
|
28
30
|
build.onLoad({ filter: /\.tsx?$/ }, async ({ path }) => {
|
|
29
31
|
if (path.includes("index.tsx"))
|
|
30
|
-
|
|
32
|
+
logger.debug("[ssr-plugin] onLoad:", path);
|
|
31
33
|
const source = await Bun.file(path).text();
|
|
32
34
|
|
|
33
35
|
// node_modules and .grimoire files are plain TypeScript (no sigil JSX).
|
|
@@ -40,7 +42,7 @@ export function registerSSRPlugin(plugins: GrimoirePlugin[] = []) {
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
if (process.env.SIGIL_VERBOSE) {
|
|
43
|
-
|
|
45
|
+
logger.debug("[sigil-ssr] XFORM:", path);
|
|
44
46
|
}
|
|
45
47
|
const hash = createHash("md5").update(path).digest("hex").slice(0, 8);
|
|
46
48
|
const result = transformSync(source, {
|
package/src/routing/router.ts
CHANGED
|
@@ -34,7 +34,7 @@ export function matchRoute(tree: RouteTree, url: URL): MatchedRoute | null {
|
|
|
34
34
|
const layoutMatches = (l: RouteFile) =>
|
|
35
35
|
l.path === "/" ||
|
|
36
36
|
route.path === l.path ||
|
|
37
|
-
route.path.startsWith(l.path
|
|
37
|
+
route.path.startsWith(`${l.path}/`);
|
|
38
38
|
|
|
39
39
|
const layouts = tree.layouts
|
|
40
40
|
.filter((l) => l.type === "layout" && layoutMatches(l))
|
|
@@ -64,7 +64,7 @@ export function findClosestError(
|
|
|
64
64
|
while (segments.length >= 0) {
|
|
65
65
|
const prefix = `/${segments.join("/")}`;
|
|
66
66
|
const error = errors.find(
|
|
67
|
-
(e) => e.path === prefix || e.path === prefix
|
|
67
|
+
(e) => e.path === prefix || e.path === `${prefix}/`,
|
|
68
68
|
);
|
|
69
69
|
if (error) return error;
|
|
70
70
|
if (segments.length === 0) break;
|
package/src/routing/scanner.ts
CHANGED
|
@@ -81,7 +81,7 @@ export async function scanRoutes(
|
|
|
81
81
|
else if (name === "+error") type = "error";
|
|
82
82
|
else type = "simple";
|
|
83
83
|
|
|
84
|
-
const clientPath =
|
|
84
|
+
const clientPath = `/${relative(viteRoot, filePath).replace(/\\/g, "/")}`;
|
|
85
85
|
|
|
86
86
|
const routeFile: RouteFile = {
|
|
87
87
|
path: pattern,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
1
2
|
import { transformSync } from "@babel/core";
|
|
2
3
|
import sigilPlugin from "@sigil-dev/compiler/babel";
|
|
3
|
-
import { basename, dirname, join, relative, resolve } from "path";
|
|
4
4
|
import type { GrimoirePlugin } from "../types";
|
|
5
5
|
import type { RouteFile } from "./scanner";
|
|
6
6
|
|
package/src/server/build.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute, join } from "node:path";
|
|
3
|
+
import { cwd } from "node:process";
|
|
1
4
|
import { sigil } from "@sigil-dev/compiler/bun";
|
|
2
|
-
import { mkdir } from "fs/promises";
|
|
3
|
-
import { isAbsolute, join } from "path";
|
|
4
|
-
import { cwd } from "process";
|
|
5
5
|
import { normalizePath } from "../dev/paths";
|
|
6
6
|
import { generateManifest } from "../routing/manifest-gen";
|
|
7
7
|
import type { RouteTree } from "../routing/scanner";
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
1
2
|
import { type Subprocess, spawn } from "bun";
|
|
2
|
-
import { join } from "path";
|
|
3
3
|
import { matchRoute } from "../routing/router";
|
|
4
4
|
import { type RouteFile, type RouteTree, scanRoutes } from "../routing/scanner";
|
|
5
5
|
import type {
|
|
6
6
|
CoordinatorContext,
|
|
7
7
|
GrimoireConfig,
|
|
8
8
|
GrimoirePlugin,
|
|
9
|
-
Route,
|
|
10
9
|
WorkerDescriptor,
|
|
11
10
|
WorkerMode,
|
|
12
11
|
} from "../types";
|
|
@@ -194,7 +193,7 @@ export async function startCoordinator(options: CoordinatorOptions) {
|
|
|
194
193
|
runHook(plugins, "onWorkerReady", descriptor);
|
|
195
194
|
}
|
|
196
195
|
},
|
|
197
|
-
onExit(
|
|
196
|
+
onExit(_proc, exitCode) {
|
|
198
197
|
const intentional = stopping;
|
|
199
198
|
runHook(
|
|
200
199
|
plugins,
|
|
@@ -204,7 +203,7 @@ export async function startCoordinator(options: CoordinatorOptions) {
|
|
|
204
203
|
);
|
|
205
204
|
if (!intentional) {
|
|
206
205
|
console.error(
|
|
207
|
-
`[grimoire] worker ${descriptor.name ?? descriptor.mode
|
|
206
|
+
`[grimoire] worker ${descriptor.name ?? `${descriptor.mode}-${descriptor.index}`} crashed (exit ${exitCode}), respawning...`,
|
|
208
207
|
);
|
|
209
208
|
// respawn: same descriptor, same port
|
|
210
209
|
// (simplified — plugin-scale can override this behavior)
|
|
@@ -296,7 +295,7 @@ function defaultSerialize(locals: App.Locals, secret: string): string {
|
|
|
296
295
|
return Buffer.from(JSON.stringify({ payload, sig })).toString("base64");
|
|
297
296
|
}
|
|
298
297
|
|
|
299
|
-
function
|
|
298
|
+
function _defaultDeserialize(raw: string, secret: string): App.Locals {
|
|
300
299
|
const { payload, sig } = JSON.parse(Buffer.from(raw, "base64").toString());
|
|
301
300
|
const expected = new Bun.CryptoHasher("sha256")
|
|
302
301
|
.update(secret + payload)
|
package/src/server/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { HMR_CLIENT_SOURCE } from "../dev/hmr-client.ts";
|
|
|
6
6
|
import { HmrServer, handleChange } from "../dev/hmr-server.ts";
|
|
7
7
|
import { makeDevLoader } from "../dev/loader.ts";
|
|
8
8
|
import { startWatcher } from "../dev/watcher.ts";
|
|
9
|
+
import { log } from "../logger/instance.ts";
|
|
9
10
|
import { renderRoute } from "../rendering";
|
|
10
11
|
import { registerSSRPlugin } from "../rendering/ssrPlugin";
|
|
11
12
|
import { findClosestError, matchRoute } from "../routing/router";
|
|
@@ -13,7 +14,7 @@ import { isErrorResult } from "../sentinels/error.ts";
|
|
|
13
14
|
import { isFailResult } from "../sentinels/fail.ts";
|
|
14
15
|
import { isRedirectResult } from "../sentinels/redirect.ts";
|
|
15
16
|
import type { GrimoireConfig, WsRouteHandler } from "../types";
|
|
16
|
-
import { buildProject
|
|
17
|
+
import { buildProject } from "./build";
|
|
17
18
|
import { createCookies } from "./cookie-utils";
|
|
18
19
|
import type {
|
|
19
20
|
Handle,
|
|
@@ -25,6 +26,7 @@ import type {
|
|
|
25
26
|
} from "./hooks";
|
|
26
27
|
import { runDeserializeLocals, runHook, runRequestHooks } from "./plugins";
|
|
27
28
|
|
|
29
|
+
const logger = log.scope("server");
|
|
28
30
|
/**
|
|
29
31
|
* Try to load hooks.server.ts from the project root.
|
|
30
32
|
*/
|
|
@@ -226,33 +228,29 @@ export async function createServer(config: GrimoireConfig = {}) {
|
|
|
226
228
|
|
|
227
229
|
const depsDir = join(process.cwd(), ".grimoire/deps");
|
|
228
230
|
mkdirSync(depsDir, { recursive: true });
|
|
229
|
-
const outFile = join(depsDir, depName
|
|
231
|
+
const outFile = join(depsDir, `${depName}.js`);
|
|
230
232
|
|
|
231
233
|
if (!(await Bun.file(outFile).exists())) {
|
|
232
|
-
|
|
234
|
+
logger.debug("bundling dep:", pkgName);
|
|
233
235
|
try {
|
|
234
236
|
const entry = Bun.resolveSync(pkgName, process.cwd());
|
|
235
237
|
const result = await Bun.build({
|
|
236
238
|
entrypoints: [entry],
|
|
237
239
|
outdir: depsDir,
|
|
238
|
-
naming: depName
|
|
240
|
+
naming: `${depName}.js`,
|
|
239
241
|
target: "browser",
|
|
240
242
|
format: "esm",
|
|
241
243
|
minify: false,
|
|
242
244
|
external: ["@sigil-dev/runtime"],
|
|
243
245
|
});
|
|
244
246
|
if (!result.success) {
|
|
245
|
-
|
|
246
|
-
"[sigil hmr] dep bundle failed:",
|
|
247
|
-
pkgName,
|
|
248
|
-
result.logs,
|
|
249
|
-
);
|
|
247
|
+
logger.error("dep bundle failed:", pkgName, result.logs);
|
|
250
248
|
return new Response(
|
|
251
249
|
`throw new Error("failed to bundle dep: ${pkgName}")`,
|
|
252
250
|
{ headers: { "Content-Type": "application/javascript" } },
|
|
253
251
|
);
|
|
254
252
|
}
|
|
255
|
-
|
|
253
|
+
logger.debug("bundled dep:", pkgName);
|
|
256
254
|
} catch (e: any) {
|
|
257
255
|
return new Response(
|
|
258
256
|
`throw new Error("dep not found: ${pkgName}: ${e.message}")`,
|
|
@@ -648,6 +646,6 @@ export async function createServer(config: GrimoireConfig = {}) {
|
|
|
648
646
|
hostname: server.hostname,
|
|
649
647
|
stop: () => server.stop(),
|
|
650
648
|
});
|
|
651
|
-
console.log(`Grimoire running at http://${host}:${port}`);
|
|
649
|
+
// console.log(`Grimoire running at http://${host}:${port}`);
|
|
652
650
|
return server;
|
|
653
651
|
}
|
package/src/server/worker.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import type { GrimoireConfig, GrimoirePlugin, WorkerMode } from "../types";
|
|
3
3
|
import { createServer } from "./index";
|
|
4
|
-
import { runDeserializeLocals } from "./plugins";
|
|
5
4
|
|
|
6
5
|
export interface WorkerOptions {
|
|
7
6
|
config: GrimoireConfig;
|
package/test/context.test.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// packages/grimoire/src/context.test.ts
|
|
2
|
-
import {
|
|
2
|
+
import { expect, test } from "bun:test";
|
|
3
3
|
import { createContext, getContext, setContext } from "@sigil-dev/runtime";
|
|
4
4
|
import { runWithContext } from "../src/server/context";
|
|
5
5
|
|
|
6
6
|
const UserKey = createContext<string>();
|
|
7
|
-
const
|
|
7
|
+
const _ThemeKey = createContext<string>();
|
|
8
8
|
|
|
9
9
|
// 1. Basic: does it work at all
|
|
10
10
|
test("getContext returns value set in same context", async () => {
|
package/test/hydration.test.ts
CHANGED
|
@@ -40,7 +40,7 @@ function runHydrate(routes: Record<string, (props: any) => any>) {
|
|
|
40
40
|
|
|
41
41
|
// simulate initRouter (same logic as router.ts)
|
|
42
42
|
let clickHandlerAttached = false;
|
|
43
|
-
function initRouter(
|
|
43
|
+
function initRouter(_routes: Record<string, (props: any) => any>) {
|
|
44
44
|
document.addEventListener("click", () => {});
|
|
45
45
|
clickHandlerAttached = true;
|
|
46
46
|
}
|
package/test/middleware.test.ts
CHANGED
|
@@ -42,7 +42,7 @@ describe("sequence()", () => {
|
|
|
42
42
|
const handler = sequence(a, b);
|
|
43
43
|
const res = await handler({
|
|
44
44
|
event: fakeEvent(),
|
|
45
|
-
resolve: async (
|
|
45
|
+
resolve: async (_evt) => new Response("OK"),
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
expect(order).toEqual(["a-before", "b-before", "b-after", "a-after"]);
|
package/test/rendering.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
|
-
import { mkdir, rm, writeFile } from "fs/promises";
|
|
3
|
-
import { tmpdir as osTmpDir } from "os";
|
|
4
|
-
import { join } from "path";
|
|
2
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir as osTmpDir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
5
|
import { renderRoute } from "../src/rendering";
|
|
6
6
|
import { matchRoute } from "../src/routing/router";
|
|
7
7
|
import { scanRoutes } from "../src/routing/scanner";
|
package/test/scanning.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
|
-
import { mkdir, rm, writeFile } from "fs/promises";
|
|
3
|
-
import { tmpdir } from "os";
|
|
4
|
-
import { join } from "path";
|
|
2
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
5
|
import { filePathToRoutePath, scanRoutes } from "../src/routing/scanner";
|
|
6
6
|
|
|
7
7
|
describe("File scanning", () => {
|
package/test/server.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
3
|
-
import { tmpdir } from "os";
|
|
4
|
-
import { join } from "path";
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
5
|
import { createServer } from "../src/server";
|
|
6
6
|
|
|
7
7
|
// ── Sandbox note ─────────────────────────────────────────────────────────────
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { mkdir, mkdtemp, readFile, rm, writeFile } from "fs/promises";
|
|
3
|
-
import { tmpdir } from "os";
|
|
4
|
-
import { join } from "path";
|
|
2
|
+
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
5
|
import type { RouteFile } from "../src/routing/scanner";
|
|
6
6
|
import { transformRoutes } from "../src/routing/transform-routes";
|
|
7
7
|
|