acrylblends 0.6.4 → 0.7.0

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.
Files changed (43) hide show
  1. package/README.md +2 -2
  2. package/docs/framework/UPSTREAM.md +1 -1
  3. package/docs/framework/guides/jsx.md +51 -25
  4. package/docs/framework/upstream.json +2 -2
  5. package/lib/{base-ddiVmiE7.js → base-NSN_SNv-.js} +1 -0
  6. package/lib/{components-DdI7-ns7.js → components-JXVm45kK.js} +1 -1
  7. package/lib/{components-0o0CBYNv.js → components-cEW3ovK0.js} +3 -3
  8. package/lib/{hooks-BMw6BAyP.js → hooks-w72iLeFR.js} +1 -1
  9. package/lib/jsx/dom/client.js +1 -1
  10. package/lib/jsx/dom/jsx-dev-runtime.js +1 -1
  11. package/lib/jsx/dom/jsx-runtime.js +1 -1
  12. package/lib/jsx/dom/server.js +2 -2
  13. package/lib/jsx/dom.js +4 -4
  14. package/lib/jsx/jsx-dev-runtime.js +1 -1
  15. package/lib/jsx/jsx-runtime.js +1 -1
  16. package/lib/jsx/streaming.js +1 -1
  17. package/lib/{jsx-dev-runtime-D18Y35TI.js → jsx-dev-runtime-CWLRA2F3.js} +2 -2
  18. package/lib/jsx-renderer.js +2 -2
  19. package/lib/jsx.js +4 -4
  20. package/lib/node-server/register.d.ts +1 -0
  21. package/lib/node-server/register.js +73 -0
  22. package/package.json +5 -1
  23. package/plugins/acryl-inspect/upstream.json +1 -1
  24. package/plugins/acryl-node-server/src/register.ts +86 -0
  25. package/plugins/acryl-node-server/upstream.json +5 -3
  26. package/plugins/acryl-router/upstream.json +1 -1
  27. package/plugins/acryl-router-http/upstream.json +1 -1
  28. package/plugins/acryl-state/upstream.json +1 -1
  29. package/plugins/desktop/main.ts +4 -1
  30. package/plugins/desktop/upstream.json +1 -1
  31. package/plugins/desktop-web/main.ts +3 -1
  32. package/plugins/desktop-web/upstream.json +1 -1
  33. package/shared/AGENTS.core.md +1 -2
  34. package/templates/agent/package.json +7 -3
  35. package/templates/agent/tsconfig.json +3 -1
  36. package/templates/blank/package.json +7 -3
  37. package/templates/blank/src/about.tsx +14 -0
  38. package/templates/blank/src/routes.ts +2 -0
  39. package/templates/blank/test/app.test.ts +15 -0
  40. package/templates/blank/tsconfig.json +3 -1
  41. package/templates/todo/package.json +7 -3
  42. package/templates/todo/tsconfig.json +3 -1
  43. package/templates/todo/upstream.json +1 -1
package/README.md CHANGED
@@ -275,10 +275,10 @@ See [Node.js](https://github.com/acryldev/acryl/blob/main/docs/framework/getting
275
275
  | `acrylblends/cache`, `acrylblends/mount` | the cache middleware and mounting another framework's fetch handler |
276
276
  | `acrylblends/ssg` | static site generation: `toSSG` writes every route as a file ([SSG helper](https://github.com/acryldev/acryl/blob/main/docs/framework/helpers/ssg.md)) |
277
277
  | `acrylblends/proxy`, `acrylblends/dev` | the proxy helper and the dev helpers (`showRoutes`, `inspectRoutes`, `getRouterName`) |
278
- | `acrylblends/jsx` | JSX on the server: `jsxImportSource: 'acrylblends/jsx'`, with `jsx/streaming`, and `acrylblends/jsx-renderer` for a layout behind `c.render` ([JSX guide](https://github.com/acryldev/acryl/blob/main/docs/framework/guides/jsx.md)) |
278
+ | `acrylblends/jsx` | JSX on the server: `jsxImportSource: 'acrylblends/jsx'`, `.tsx` files run on Node with `node --import acrylblends/node-server/register`, with `jsx/streaming`, and `acrylblends/jsx-renderer` for a layout behind `c.render` ([JSX guide](https://github.com/acryldev/acryl/blob/main/docs/framework/guides/jsx.md)) |
279
279
  | `acrylblends/jsx/dom` | JSX in the browser: hooks and `render` (needs the DOM library) ([client components](https://github.com/acryldev/acryl/blob/main/docs/framework/guides/jsx-dom.md)) |
280
280
  | `acrylblends/css` | CSS in JSX: `css`, `cx`, `keyframes`, `Style` ([CSS helper](https://github.com/acryldev/acryl/blob/main/docs/framework/helpers/css.md)) |
281
- | `acrylblends/node-server` | `serve`, `createAdaptorServer`, `getRequestListener`; with `node-server/serve-static` and `node-server/conninfo` |
281
+ | `acrylblends/node-server` | `serve`, `createAdaptorServer`, `getRequestListener`; with `node-server/serve-static`, `node-server/conninfo`, and `node-server/register` (compiles `.tsx` with the app's `typescript`) |
282
282
 
283
283
  Every subpath is listed in the package's `exports`. The adapters of other runtimes are being ported. The docs mark them "not yet available" until they ship
284
284
  ([FAQ](https://github.com/acryldev/acryl/blob/main/docs/framework/guides/faq.md)).
@@ -1,3 +1,3 @@
1
1
  # Generated copy
2
2
 
3
- This folder is a copy of `docs/framework` of acryldev/acryl at commit `fd1f7dcaaff8b757c0562294002c0d32d6e0a893`, made by `scripts/sync-framework.mjs`. Do not edit it here: change the text in ACRYL and sync again. `pnpm run verify:framework` fails when a page differs from the recorded digest.
3
+ This folder is a copy of `docs/framework` of acryldev/acryl at commit `7bba3ed0420d87e61d8256fa60614d22af734c8f`, made by `scripts/sync-framework.mjs`. Do not edit it here: change the text in ACRYL and sync again. `pnpm run verify:framework` fails when a page differs from the recorded digest.
@@ -4,30 +4,6 @@ You can write HTML with JSX syntax with `acrylblends/jsx`.
4
4
 
5
5
  Although `acrylblends/jsx` works on the client, you will probably use it most often when rendering content on the server side. Here are some things related to JSX that are common to both server and client.
6
6
 
7
- ## Node.js runs `jsx()`, not JSX syntax
8
-
9
- The apps `npm create acrylblends@latest` makes run their TypeScript on Node.js by stripping the types (no build step). That does **not** compile JSX: a `.tsx` file does not load. Either compile the file first (`tsc`
10
- or a bundler, with the settings below), or write the call that JSX compiles to. `jsx(tag, props, ...children)` takes the children after the props, and a node renders with `toString()`:
11
-
12
- ```ts
13
- import { Acryl } from 'acrylblends'
14
- import { jsx } from 'acrylblends/jsx'
15
- import type { PropsWithChildren } from 'acrylblends/jsx'
16
-
17
- const Layout = (props: PropsWithChildren<{ title: string }>) =>
18
- jsx('html', { lang: 'en' }, jsx('head', null, jsx('title', null, props.title)), jsx('body', null, props.children))
19
-
20
- const About = () =>
21
- jsx(Layout, { title: 'About' }, jsx('h1', null, 'About'), jsx('p', { class: 'lead' }, 'Rendered on the server.'))
22
-
23
- const app = new Acryl()
24
- app.get('/about', (c) => c.html(jsx(About, null).toString()))
25
-
26
- export default app
27
- ```
28
-
29
- Pass the children as arguments after the props. A `children` entry inside the props object is not rendered by this form.
30
-
31
7
  ## Settings
32
8
 
33
9
  To use JSX, modify the `tsconfig.json`:
@@ -50,9 +26,34 @@ Alternatively, use the pragma directives:
50
26
  /** @jsxImportSource acrylblends/jsx */
51
27
  ```
52
28
 
29
+ ## Run `.tsx` on Node.js
30
+
31
+ Node.js strips TypeScript's types but does not compile JSX, so a `.tsx` file needs one flag: `--import acrylblends/node-server/register`.
32
+ It compiles each `.tsx` (and `.jsx`) module as Node.js loads it, with your app's own `typescript` (a development dependency) and the
33
+ `jsxImportSource` of your `tsconfig.json` (`acrylblends/jsx` without one); every other module runs exactly as before. Stack traces point at
34
+ the `.tsx` lines.
35
+
36
+ `package.json`:
37
+
38
+ ```json
39
+ {
40
+ "scripts": {
41
+ "dev": "node --watch --import acrylblends/node-server/register src/index.tsx",
42
+ "start": "node --import acrylblends/node-server/register src/index.tsx",
43
+ "test": "node --import acrylblends/node-server/register --test \"src/**/*.test.{ts,tsx}\""
44
+ },
45
+ "devDependencies": {
46
+ "typescript": "^6.0.3"
47
+ }
48
+ }
49
+ ```
50
+
51
+ `node --test` looks only for `.js` and `.ts` test files on its own, so the `test` script names the `.tsx` ones with a pattern. Without `typescript` in the app, the first `.tsx` module stops with a message that says to install it. Bun compiles JSX itself and needs
52
+ no flag.
53
+
53
54
  ## Usage
54
55
 
55
- > **Note.** If you are coming straight from the [Quick Start](../README.md#quick-start), the main file has a `.ts` extension - you need to change it to `.tsx` - otherwise you will not be able to run the application at all. You should additionally modify the `package.json` (or `deno.json` if you are using Deno) to reflect that change (e.g. instead of having `bun run --hot src/index.ts` in dev script, you should have `bun run --hot src/index.tsx`).
56
+ > **Note.** If you are coming straight from the [Quick Start](../README.md#quick-start), the main file has a `.ts` extension - you need to change it to `.tsx` - otherwise you will not be able to run the application at all. Change the scripts in `package.json` to match: on Node.js, as [above](#run-tsx-on-nodejs); on Bun, `bun run --hot src/index.tsx` instead of `bun run --hot src/index.ts`.
56
57
 
57
58
  `index.tsx`:
58
59
 
@@ -93,6 +94,31 @@ app.get('/', (c) => {
93
94
  export default app
94
95
  ```
95
96
 
97
+ ## Without compiling: `jsx()`
98
+
99
+ A `.ts` file can build the same nodes without JSX syntax and without the register flag: write the call that JSX compiles to.
100
+ `jsx(tag, props, ...children)` takes the children after the props, and a node renders with `toString()`. The `` html`...` `` template
101
+ from `acrylblends/html` is the other build-free choice.
102
+
103
+ ```ts
104
+ import { Acryl } from 'acrylblends'
105
+ import { jsx } from 'acrylblends/jsx'
106
+ import type { PropsWithChildren } from 'acrylblends/jsx'
107
+
108
+ const Layout = (props: PropsWithChildren<{ title: string }>) =>
109
+ jsx('html', { lang: 'en' }, jsx('head', null, jsx('title', null, props.title)), jsx('body', null, props.children))
110
+
111
+ const About = () =>
112
+ jsx(Layout, { title: 'About' }, jsx('h1', null, 'About'), jsx('p', { class: 'lead' }, 'Rendered on the server.'))
113
+
114
+ const app = new Acryl()
115
+ app.get('/about', (c) => c.html(jsx(About, null).toString()))
116
+
117
+ export default app
118
+ ```
119
+
120
+ Pass the children as arguments after the props. A `children` entry inside the props object is not rendered by this form.
121
+
96
122
  ## Metadata hoisting
97
123
 
98
124
  You can write document metadata tags such as `<title>`, `<link>`, and `<meta>` directly inside your components. These tags will be automatically hoisted to the `<head>` section of the document. This is especially useful when the `<head>` element is rendered far from the component that determines the appropriate metadata.
@@ -2,8 +2,8 @@
2
2
  "source": {
3
3
  "repo": "acryldev/acryl",
4
4
  "path": "docs/framework",
5
- "commit": "fd1f7dcaaff8b757c0562294002c0d32d6e0a893"
5
+ "commit": "7bba3ed0420d87e61d8256fa60614d22af734c8f"
6
6
  },
7
7
  "files": 88,
8
- "digest": "sha256:5e6989c7fe1b3006f8917926d8cc3e84e14c2af03440682c18d22bec0045c3d2"
8
+ "digest": "sha256:1f7e213ee1fd287a98b5bead17a0b197311fcd75013ddf5912ca4a476657cece"
9
9
  }
@@ -1,5 +1,6 @@
1
1
  import { escapeToBuffer, raw, resolveCallbackSync, stringBufferToString } from "./utils/html.js";
2
2
  import { i as DOM_RENDERER, n as DOM_INTERNAL_TAG, o as PERMALINK, r as DOM_MEMO, t as DOM_ERROR_HANDLER } from "./constants-BR9jM9BC.js";
3
+ import "node:module";
3
4
  //#region \0rolldown/runtime.js
4
5
  var __defProp = Object.defineProperty;
5
6
  var __exportAll = (all, no_symbols) => {
@@ -1,5 +1,5 @@
1
1
  import { t as DOM_ERROR_HANDLER } from "./constants-BR9jM9BC.js";
2
- import { t as Fragment } from "./jsx-dev-runtime-D18Y35TI.js";
2
+ import { t as Fragment } from "./jsx-dev-runtime-CWLRA2F3.js";
3
3
  import "./jsx/dom/jsx-runtime.js";
4
4
  //#region ../../plugins/acryl-router/src/core/jsx/dom/components.ts
5
5
  const ErrorBoundary = (({ children, fallback, fallbackRender, onError }) => {
@@ -1,8 +1,8 @@
1
- import { C as captureRenderContext, E as useContext, d as renderUntrustedObject, i as isUntrustedObject, n as JSXNode, o as jsx, t as Fragment, u as renderChildren, w as createContext } from "./base-ddiVmiE7.js";
1
+ import { C as captureRenderContext, E as useContext, d as renderUntrustedObject, i as isUntrustedObject, n as JSXNode, o as jsx, t as Fragment, u as renderChildren, w as createContext } from "./base-NSN_SNv-.js";
2
2
  import { HtmlEscapedCallbackPhase, raw, resolveCallback } from "./utils/html.js";
3
3
  import { a as DOM_STASH, i as DOM_RENDERER } from "./constants-BR9jM9BC.js";
4
- import { x as buildDataStack } from "./hooks-BMw6BAyP.js";
5
- import { n as Suspense$1, t as ErrorBoundary$1 } from "./components-DdI7-ns7.js";
4
+ import { x as buildDataStack } from "./hooks-w72iLeFR.js";
5
+ import { n as Suspense$1, t as ErrorBoundary$1 } from "./components-JXVm45kK.js";
6
6
  //#region ../../plugins/acryl-router/src/core/jsx/streaming.ts
7
7
  /**
8
8
  * @module
@@ -1,4 +1,4 @@
1
- import { D as createContext, E as useContext, T as globalContexts, _ as toArray, h as styleObjectForEach, m as normalizeIntrinsicElementKey } from "./base-ddiVmiE7.js";
1
+ import { D as createContext, E as useContext, T as globalContexts, _ as toArray, h as styleObjectForEach, m as normalizeIntrinsicElementKey } from "./base-NSN_SNv-.js";
2
2
  import { a as DOM_STASH, i as DOM_RENDERER, n as DOM_INTERNAL_TAG, r as DOM_MEMO, t as DOM_ERROR_HANDLER } from "./constants-BR9jM9BC.js";
3
3
  //#region ../../plugins/acryl-router/src/core/jsx/dom/render.ts
4
4
  const ACRYL_PORTAL_ELEMENT = "_hp";
@@ -1,4 +1,4 @@
1
- import { D as renderNode, S as buildNode, _ as useState } from "../../hooks-BMw6BAyP.js";
1
+ import { D as renderNode, S as buildNode, _ as useState } from "../../hooks-w72iLeFR.js";
2
2
  //#region ../../plugins/acryl-router/src/core/jsx/dom/client.ts
3
3
  /**
4
4
  * Create a root object for rendering
@@ -1,2 +1,2 @@
1
- import { n as jsxDEV, t as Fragment } from "../../jsx-dev-runtime-D18Y35TI.js";
1
+ import { n as jsxDEV, t as Fragment } from "../../jsx-dev-runtime-CWLRA2F3.js";
2
2
  export { Fragment, jsxDEV };
@@ -1,2 +1,2 @@
1
- import { n as jsxDEV, t as Fragment } from "../../jsx-dev-runtime-D18Y35TI.js";
1
+ import { n as jsxDEV, t as Fragment } from "../../jsx-dev-runtime-CWLRA2F3.js";
2
2
  export { Fragment, jsxDEV as jsx, jsxDEV as jsxs };
@@ -1,5 +1,5 @@
1
- import { u as renderChildren } from "../../base-ddiVmiE7.js";
2
- import { i as renderToReadableStream$1 } from "../../components-0o0CBYNv.js";
1
+ import { u as renderChildren } from "../../base-NSN_SNv-.js";
2
+ import { i as renderToReadableStream$1 } from "../../components-cEW3ovK0.js";
3
3
  import dom_default from "../dom.js";
4
4
  //#region ../../plugins/acryl-router/src/core/jsx/dom/server.ts
5
5
  const prepareRoot = (element) => typeof element === "string" || Array.isArray(element) ? renderChildren([element]) : element;
package/lib/jsx/dom.js CHANGED
@@ -1,9 +1,9 @@
1
- import { D as createContext, E as useContext, a as isValidElement, f as shallowEqual, g as Children, l as reactAPICompatVersion } from "../base-ddiVmiE7.js";
1
+ import { D as createContext, E as useContext, a as isValidElement, f as shallowEqual, g as Children, l as reactAPICompatVersion } from "../base-NSN_SNv-.js";
2
2
  import { r as DOM_MEMO } from "../constants-BR9jM9BC.js";
3
- import { C as createPortal, E as render, _ as useState, a as use, b as useViewTransition, c as useDeferredValue, d as useImperativeHandle, f as useInsertionEffect, g as useRef, h as useReducer, i as startViewTransition, l as useEffect, m as useMemo, n as forwardRef, o as useCallback, p as useLayoutEffect, r as startTransition, s as useDebugValue, t as createRef, u as useId, v as useSyncExternalStore, w as flushSync, y as useTransition } from "../hooks-BMw6BAyP.js";
4
- import { a as useOptimistic, i as useFormStatus, n as jsxDEV, r as useActionState, t as Fragment } from "../jsx-dev-runtime-D18Y35TI.js";
3
+ import { C as createPortal, E as render, _ as useState, a as use, b as useViewTransition, c as useDeferredValue, d as useImperativeHandle, f as useInsertionEffect, g as useRef, h as useReducer, i as startViewTransition, l as useEffect, m as useMemo, n as forwardRef, o as useCallback, p as useLayoutEffect, r as startTransition, s as useDebugValue, t as createRef, u as useId, v as useSyncExternalStore, w as flushSync, y as useTransition } from "../hooks-w72iLeFR.js";
4
+ import { a as useOptimistic, i as useFormStatus, n as jsxDEV, r as useActionState, t as Fragment } from "../jsx-dev-runtime-CWLRA2F3.js";
5
5
  import "./dom/jsx-runtime.js";
6
- import { n as Suspense, t as ErrorBoundary } from "../components-DdI7-ns7.js";
6
+ import { n as Suspense, t as ErrorBoundary } from "../components-JXVm45kK.js";
7
7
  //#region ../../plugins/acryl-router/src/core/jsx/dom/index.ts
8
8
  /**
9
9
  * @module
@@ -1,4 +1,4 @@
1
- import { s as jsxFn, t as Fragment } from "../base-ddiVmiE7.js";
1
+ import { s as jsxFn, t as Fragment } from "../base-NSN_SNv-.js";
2
2
  //#region ../../plugins/acryl-router/src/core/jsx/jsx-dev-runtime.ts
3
3
  function jsxDEV(tag, props, key) {
4
4
  let node;
@@ -1,4 +1,4 @@
1
- import { h as styleObjectForEach, p as isValidAttributeName, t as Fragment } from "../base-ddiVmiE7.js";
1
+ import { h as styleObjectForEach, p as isValidAttributeName, t as Fragment } from "../base-NSN_SNv-.js";
2
2
  import { escapeToBuffer, raw, stringBufferToString } from "../utils/html.js";
3
3
  import { html } from "../html.js";
4
4
  import { jsxDEV } from "./jsx-dev-runtime.js";
@@ -1,2 +1,2 @@
1
- import { i as renderToReadableStream, n as StreamingContext, r as Suspense } from "../components-0o0CBYNv.js";
1
+ import { i as renderToReadableStream, n as StreamingContext, r as Suspense } from "../components-cEW3ovK0.js";
2
2
  export { StreamingContext, Suspense, renderToReadableStream };
@@ -1,6 +1,6 @@
1
- import { D as createContext, E as useContext, O as __exportAll, S as shouldDeDupeByKey, b as domRenderers, v as dataPrecedenceAttr, x as isStylesheetLinkWithPrecedence, y as deDupeKeyMap } from "./base-ddiVmiE7.js";
1
+ import { D as createContext, E as useContext, O as __exportAll, S as shouldDeDupeByKey, b as domRenderers, v as dataPrecedenceAttr, x as isStylesheetLinkWithPrecedence, y as deDupeKeyMap } from "./base-NSN_SNv-.js";
2
2
  import { o as PERMALINK } from "./constants-BR9jM9BC.js";
3
- import { C as createPortal, T as getNameSpaceContext, _ as useState, a as use, m as useMemo, o as useCallback } from "./hooks-BMw6BAyP.js";
3
+ import { C as createPortal, T as getNameSpaceContext, _ as useState, a as use, m as useMemo, o as useCallback } from "./hooks-w72iLeFR.js";
4
4
  //#region ../../plugins/acryl-router/src/core/jsx/dom/hooks/index.ts
5
5
  /**
6
6
  * Provide hooks used only in jsx/dom
@@ -1,7 +1,7 @@
1
- import { E as useContext, o as jsx, t as Fragment, w as createContext } from "./base-ddiVmiE7.js";
1
+ import { E as useContext, o as jsx, t as Fragment, w as createContext } from "./base-NSN_SNv-.js";
2
2
  import { raw } from "./utils/html.js";
3
3
  import { html } from "./html.js";
4
- import { i as renderToReadableStream } from "./components-0o0CBYNv.js";
4
+ import { i as renderToReadableStream } from "./components-cEW3ovK0.js";
5
5
  import "./jsx.js";
6
6
  //#region ../../plugins/acryl-router/src/core/middleware/jsx-renderer/index.ts
7
7
  const RequestContext = createContext(null);
package/lib/jsx.js CHANGED
@@ -1,7 +1,7 @@
1
- import { E as useContext, a as isValidElement, c as memo, g as Children, l as reactAPICompatVersion, o as jsx, r as cloneElement, t as Fragment, w as createContext } from "./base-ddiVmiE7.js";
2
- import { _ as useState, a as use, b as useViewTransition, c as useDeferredValue, d as useImperativeHandle, f as useInsertionEffect, g as useRef, h as useReducer, i as startViewTransition, l as useEffect, m as useMemo, n as forwardRef, o as useCallback, p as useLayoutEffect, r as startTransition, s as useDebugValue, t as createRef, u as useId, v as useSyncExternalStore, y as useTransition } from "./hooks-BMw6BAyP.js";
3
- import { a as useOptimistic, r as useActionState } from "./jsx-dev-runtime-D18Y35TI.js";
4
- import { r as Suspense, t as ErrorBoundary } from "./components-0o0CBYNv.js";
1
+ import { E as useContext, a as isValidElement, c as memo, g as Children, l as reactAPICompatVersion, o as jsx, r as cloneElement, t as Fragment, w as createContext } from "./base-NSN_SNv-.js";
2
+ import { _ as useState, a as use, b as useViewTransition, c as useDeferredValue, d as useImperativeHandle, f as useInsertionEffect, g as useRef, h as useReducer, i as startViewTransition, l as useEffect, m as useMemo, n as forwardRef, o as useCallback, p as useLayoutEffect, r as startTransition, s as useDebugValue, t as createRef, u as useId, v as useSyncExternalStore, y as useTransition } from "./hooks-w72iLeFR.js";
3
+ import { a as useOptimistic, r as useActionState } from "./jsx-dev-runtime-CWLRA2F3.js";
4
+ import { r as Suspense, t as ErrorBoundary } from "./components-cEW3ovK0.js";
5
5
  //#region ../../plugins/acryl-router/src/core/jsx/index.ts
6
6
  /**
7
7
  * @module
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,73 @@
1
+ import { createRequire, registerHooks } from "node:module";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ //#region ../../plugins/acryl-node-server/src/register.ts
6
+ /**
7
+ * JSX files on Node: `node --import acrylblends/node-server/register src/index.ts`. Node strips TypeScript's types but does not compile JSX, so a
8
+ * `.tsx` (or `.jsx`) module does not load on its own. This module registers a load hook that compiles exactly those files with the app's own
9
+ * `typescript` (react-jsx, the `jsxImportSource` of the app's nearest tsconfig.json, `acrylblends/jsx` without one) and leaves every other
10
+ * module to Node untouched. The output carries an inline source map and source maps are switched on, so a stack trace names the `.tsx` line.
11
+ *
12
+ * `typescript` is loaded from the app, on the first JSX file only; the framework itself has no dependencies.
13
+ */
14
+ /** The JSX runtime the docs set up; an app's tsconfig.json (or a file's own `@jsxImportSource` pragma) chooses another. */
15
+ const DEFAULT_IMPORT_SOURCE = "acrylblends/jsx";
16
+ const JSX_FILE = /\.[jt]sx$/u;
17
+ const compilers = /* @__PURE__ */ new Map();
18
+ const importSources = /* @__PURE__ */ new Map();
19
+ /** The app's own `typescript`, resolved from the JSX file, so each app compiles with the version it pinned. */
20
+ function compilerFor(file) {
21
+ let path;
22
+ try {
23
+ path = createRequire(file).resolve("typescript");
24
+ } catch {
25
+ throw new Error(`acrylblends: ${file} contains JSX, and compiling it needs the typescript package in this app: npm install --save-dev typescript`);
26
+ }
27
+ let compiler = compilers.get(path);
28
+ if (compiler === void 0) {
29
+ compiler = createRequire(path)(path);
30
+ compilers.set(path, compiler);
31
+ }
32
+ return compiler;
33
+ }
34
+ /** `jsxImportSource` of the tsconfig.json nearest to the file (following `extends`), read once per config. */
35
+ function importSourceFor(file, ts) {
36
+ const config = ts.findConfigFile(dirname(file), (path) => existsSync(path));
37
+ if (config === void 0) return DEFAULT_IMPORT_SOURCE;
38
+ let source = importSources.get(config);
39
+ if (source === void 0) {
40
+ const { config: json } = ts.readConfigFile(config, (path) => ts.sys.readFile(path));
41
+ source = ts.parseJsonConfigFileContent(json ?? {}, ts.sys, dirname(config)).options.jsxImportSource ?? DEFAULT_IMPORT_SOURCE;
42
+ importSources.set(config, source);
43
+ }
44
+ return source;
45
+ }
46
+ /** A JSX module compiled to JavaScript, with its source map inline. */
47
+ function compileJsx(file, text) {
48
+ const ts = compilerFor(file);
49
+ return ts.transpileModule(text, {
50
+ fileName: file,
51
+ compilerOptions: {
52
+ module: "esnext",
53
+ target: "es2022",
54
+ jsx: "react-jsx",
55
+ jsxImportSource: importSourceFor(file, ts),
56
+ allowImportingTsExtensions: true,
57
+ inlineSourceMap: true,
58
+ inlineSources: true
59
+ }
60
+ }).outputText;
61
+ }
62
+ process.setSourceMapsEnabled(true);
63
+ registerHooks({ load(url, context, nextLoad) {
64
+ if (!url.startsWith("file:") || !JSX_FILE.test(new URL(url).pathname)) return nextLoad(url, context);
65
+ const file = fileURLToPath(url);
66
+ return {
67
+ format: "module",
68
+ source: compileJsx(file, readFileSync(file, "utf8")),
69
+ shortCircuit: true
70
+ };
71
+ } });
72
+ //#endregion
73
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acrylblends",
3
- "version": "0.6.4",
3
+ "version": "0.7.0",
4
4
  "description": "The Acryl web framework (import { Acryl } from \"acrylblends\") and the acrylblends command that scaffolds Cordis apps.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -382,6 +382,10 @@
382
382
  "types": "./lib/node-server/conninfo.d.ts",
383
383
  "default": "./lib/node-server/conninfo.js"
384
384
  },
385
+ "./node-server/register": {
386
+ "types": "./lib/node-server/register.d.ts",
387
+ "default": "./lib/node-server/register.js"
388
+ },
385
389
  "./package.json": "./package.json",
386
390
  "./cli": {
387
391
  "types": "./dist/index.d.ts",
@@ -2,7 +2,7 @@
2
2
  "source": {
3
3
  "repo": "acryldev/acryl",
4
4
  "path": "plugins/acryl-inspect",
5
- "commit": "fd1f7dcaaff8b757c0562294002c0d32d6e0a893"
5
+ "commit": "7bba3ed0420d87e61d8256fa60614d22af734c8f"
6
6
  },
7
7
  "vendored": [
8
8
  "src",
@@ -0,0 +1,86 @@
1
+ /**
2
+ * JSX files on Node: `node --import acrylblends/node-server/register src/index.ts`. Node strips TypeScript's types but does not compile JSX, so a
3
+ * `.tsx` (or `.jsx`) module does not load on its own. This module registers a load hook that compiles exactly those files with the app's own
4
+ * `typescript` (react-jsx, the `jsxImportSource` of the app's nearest tsconfig.json, `acrylblends/jsx` without one) and leaves every other
5
+ * module to Node untouched. The output carries an inline source map and source maps are switched on, so a stack trace names the `.tsx` line.
6
+ *
7
+ * `typescript` is loaded from the app, on the first JSX file only; the framework itself has no dependencies.
8
+ */
9
+
10
+ import { createRequire, registerHooks } from 'node:module'
11
+ import { existsSync, readFileSync } from 'node:fs'
12
+ import { dirname } from 'node:path'
13
+ import { fileURLToPath } from 'node:url'
14
+
15
+ /** The JSX runtime the docs set up; an app's tsconfig.json (or a file's own `@jsxImportSource` pragma) chooses another. */
16
+ const DEFAULT_IMPORT_SOURCE = 'acrylblends/jsx'
17
+ const JSX_FILE = /\.[jt]sx$/u
18
+
19
+ /** The part of the TypeScript compiler API the hook uses. */
20
+ interface Compiler {
21
+ transpileModule(input: string, options: { fileName: string, compilerOptions: Record<string, unknown> }): { outputText: string }
22
+ findConfigFile(searchPath: string, fileExists: (path: string) => boolean): string | undefined
23
+ readConfigFile(path: string, readFile: (path: string) => string | undefined): { config?: unknown }
24
+ parseJsonConfigFileContent(json: unknown, host: unknown, basePath: string): { options: { jsxImportSource?: string } }
25
+ sys: { fileExists(path: string): boolean, readFile(path: string): string | undefined }
26
+ }
27
+
28
+ const compilers = new Map<string, Compiler>()
29
+ const importSources = new Map<string, string>()
30
+
31
+ /** The app's own `typescript`, resolved from the JSX file, so each app compiles with the version it pinned. */
32
+ function compilerFor(file: string): Compiler {
33
+ let path: string
34
+ try {
35
+ path = createRequire(file).resolve('typescript')
36
+ } catch {
37
+ throw new Error(`acrylblends: ${file} contains JSX, and compiling it needs the typescript package in this app: npm install --save-dev typescript`)
38
+ }
39
+ let compiler = compilers.get(path)
40
+ if (compiler === undefined) {
41
+ compiler = createRequire(path)(path) as Compiler
42
+ compilers.set(path, compiler)
43
+ }
44
+ return compiler
45
+ }
46
+
47
+ /** `jsxImportSource` of the tsconfig.json nearest to the file (following `extends`), read once per config. */
48
+ function importSourceFor(file: string, ts: Compiler): string {
49
+ const config = ts.findConfigFile(dirname(file), path => existsSync(path))
50
+ if (config === undefined) return DEFAULT_IMPORT_SOURCE
51
+ let source = importSources.get(config)
52
+ if (source === undefined) {
53
+ const { config: json } = ts.readConfigFile(config, path => ts.sys.readFile(path))
54
+ source = ts.parseJsonConfigFileContent(json ?? {}, ts.sys, dirname(config)).options.jsxImportSource ?? DEFAULT_IMPORT_SOURCE
55
+ importSources.set(config, source)
56
+ }
57
+ return source
58
+ }
59
+
60
+ /** A JSX module compiled to JavaScript, with its source map inline. */
61
+ function compileJsx(file: string, text: string): string {
62
+ const ts = compilerFor(file)
63
+ return ts.transpileModule(text, {
64
+ fileName: file,
65
+ compilerOptions: {
66
+ module: 'esnext',
67
+ target: 'es2022',
68
+ jsx: 'react-jsx',
69
+ jsxImportSource: importSourceFor(file, ts),
70
+ allowImportingTsExtensions: true,
71
+ inlineSourceMap: true,
72
+ inlineSources: true,
73
+ },
74
+ }).outputText
75
+ }
76
+
77
+ process.setSourceMapsEnabled(true)
78
+
79
+ registerHooks({
80
+ load(url, context, nextLoad) {
81
+ // Every other module goes straight to Node: the hook's whole cost for them is this test.
82
+ if (!url.startsWith('file:') || !JSX_FILE.test(new URL(url).pathname)) return nextLoad(url, context)
83
+ const file = fileURLToPath(url)
84
+ return { format: 'module', source: compileJsx(file, readFileSync(file, 'utf8')), shortCircuit: true }
85
+ },
86
+ })
@@ -2,7 +2,7 @@
2
2
  "source": {
3
3
  "repo": "acryldev/acryl",
4
4
  "path": "plugins/acryl-node-server",
5
- "commit": "fd1f7dcaaff8b757c0562294002c0d32d6e0a893"
5
+ "commit": "7bba3ed0420d87e61d8256fa60614d22af734c8f"
6
6
  },
7
7
  "vendored": [
8
8
  "src",
@@ -10,8 +10,10 @@
10
10
  "LICENSE"
11
11
  ],
12
12
  "rewrittenSpecifiers": 28,
13
- "digest": "sha256:2adaa64028c1f2a40ed94c0eacf64d32c8c3b8171b52338cb02bfae2fd56ab7c",
14
- "testsNotRun": {},
13
+ "digest": "sha256:9dc4cca51f5a3d8416750c0392135128a0787947f473cff2e00bdb12fe5a63e1",
14
+ "testsNotRun": {
15
+ "tests/register.spec.ts": "links typescript from the plugin's own node_modules (ACRYL's workspace layout); the hook is exercised here by the templates' own .tsx tests and verify:scaffolder"
16
+ },
15
17
  "notice": [
16
18
  "LICENSE"
17
19
  ]
@@ -2,7 +2,7 @@
2
2
  "source": {
3
3
  "repo": "acryldev/acryl",
4
4
  "path": "plugins/acryl-router",
5
- "commit": "fd1f7dcaaff8b757c0562294002c0d32d6e0a893"
5
+ "commit": "7bba3ed0420d87e61d8256fa60614d22af734c8f"
6
6
  },
7
7
  "vendored": [
8
8
  "src",
@@ -2,7 +2,7 @@
2
2
  "source": {
3
3
  "repo": "acryldev/acryl",
4
4
  "path": "plugins/acryl-router-http",
5
- "commit": "fd1f7dcaaff8b757c0562294002c0d32d6e0a893"
5
+ "commit": "7bba3ed0420d87e61d8256fa60614d22af734c8f"
6
6
  },
7
7
  "vendored": [
8
8
  "src",
@@ -2,7 +2,7 @@
2
2
  "source": {
3
3
  "repo": "acryldev/acryl",
4
4
  "path": "plugins/acryl-state",
5
- "commit": "fd1f7dcaaff8b757c0562294002c0d32d6e0a893"
5
+ "commit": "7bba3ed0420d87e61d8256fa60614d22af734c8f"
6
6
  },
7
7
  "vendored": [
8
8
  "src",
@@ -10,7 +10,8 @@ import { mkdirSync, readFileSync } from 'node:fs'
10
10
  import { join } from 'node:path'
11
11
  import { fileURLToPath } from 'node:url'
12
12
  import { app, BrowserWindow, shell } from 'electron'
13
- import { type App, createApp } from '../../app.ts'
13
+ import type { App } from '../../app.ts'
14
+ import '../acryl-node-server/src/register.ts'
14
15
  import { selectInstance } from '../instance/index.ts'
15
16
  import { createDesktopShutdown, installShutdownRequests } from './shutdown.ts'
16
17
  import { resolveDesktopUserDataOverride } from './user-data.ts'
@@ -63,6 +64,8 @@ if (!app.requestSingleInstanceLock()) {
63
64
  })
64
65
 
65
66
  void app.whenReady().then(async () => {
67
+ // The hook above is registered before the app's modules are loaded, so the app may have .tsx pages: they are loaded here, not as a static import.
68
+ const { createApp } = await import('../../app.ts')
66
69
  running = await createApp(chosen)
67
70
  const origin = new URL(running.url).origin
68
71
  window = new BrowserWindow(windowOptions({ title: chosen.name }))
@@ -5,7 +5,7 @@
5
5
  "apps/acryl-desktop/src/shell/desktop-user-data.ts": "user-data.ts",
6
6
  "apps/acryl-desktop/src/shell/shutdown.ts": "shutdown.ts"
7
7
  },
8
- "commit": "fd1f7dcaaff8b757c0562294002c0d32d6e0a893"
8
+ "commit": "7bba3ed0420d87e61d8256fa60614d22af734c8f"
9
9
  },
10
10
  "rewrittenSpecifiers": 0,
11
11
  "digest": "sha256:7dfe960a8bbb476c35540d2202a7aaa62b33492c2ac3e34314e2ecfca45f32f2"
@@ -12,7 +12,7 @@ import { join } from 'node:path'
12
12
  import { fileURLToPath } from 'node:url'
13
13
  import { serve } from 'acrylblends/node-server'
14
14
  import { app, BrowserWindow, shell } from 'electron'
15
- import acrylApp from '../../app.ts'
15
+ import 'acrylblends/node-server/register'
16
16
  import { createDesktopShutdown, installShutdownRequests } from './shutdown.ts'
17
17
  import { resolveDesktopUserDataOverride } from './user-data.ts'
18
18
  import { windowOptions } from './window.ts'
@@ -66,6 +66,8 @@ if (!app.requestSingleInstanceLock()) {
66
66
  })
67
67
 
68
68
  void app.whenReady().then(async () => {
69
+ // The hook above is registered before the app's modules are loaded, so the app may have .tsx pages: they are loaded here, not as a static import.
70
+ const { default: acrylApp } = await import('../../app.ts')
69
71
  const port = await new Promise<number>((resolve) => {
70
72
  server = serve(
71
73
  { fetch: acrylApp.fetch, port: 0, hostname: '127.0.0.1' },
@@ -5,7 +5,7 @@
5
5
  "apps/acryl-desktop/src/shell/desktop-user-data.ts": "user-data.ts",
6
6
  "apps/acryl-desktop/src/shell/shutdown.ts": "shutdown.ts"
7
7
  },
8
- "commit": "fd1f7dcaaff8b757c0562294002c0d32d6e0a893"
8
+ "commit": "7bba3ed0420d87e61d8256fa60614d22af734c8f"
9
9
  },
10
10
  "rewrittenSpecifiers": 0,
11
11
  "digest": "sha256:7dfe960a8bbb476c35540d2202a7aaa62b33492c2ac3e34314e2ecfca45f32f2"
@@ -17,8 +17,7 @@ The docs write `import { Acryl } from 'acrylblends'` and `from 'acrylblends/<sub
17
17
  - `./plugins/acryl-router/src/helpers/index.ts` for the helpers and validators (`streamSSE`, `schemaValidator`, `validator`, cookies, `testClient`, ...).
18
18
  - `./plugins/acryl-router/src/core/jsx/index.ts` for `acrylblends/jsx` (`jsx`, `Fragment`, the types), and `.../core/jsx/streaming.ts` for `acrylblends/jsx/streaming`.
19
19
 
20
- **JSX syntax does not run here.** Node runs this app by stripping TypeScript types, which does not compile JSX (a `.tsx` file will not load). Write the call JSX compiles to instead: `jsx('h1', { class: 'title' }, 'Hello')`, children after the props as further arguments
21
- (`jsx(tag, props, ...children)`); render with `.toString()` and return it with `c.html(...)`. A component is a function from props to a `jsx(...)` node.
20
+ **JSX: write `.tsx`.** The scripts in `package.json` run Node.js with `--import ./src/plugins/acryl-node-server/src/register.ts`, which compiles `.tsx` files with this app's own `typescript`; `tsconfig.json` sets `jsx: react-jsx` and `jsxImportSource: #acryl-jsx`, which `package.json`'s `imports` maps to the vendored runtime in `src/plugins/acryl-router`. See `src/about.tsx` (blank template) for a page and `test/app.test.ts` for how it is tested. Render a component with `.toString()` and return it with `c.html(...)`; import `jsx`, `Fragment` and the types from `./plugins/acryl-router/src/core/jsx/index.ts` when you need them. A command that starts the app without those scripts (a bare `node src/main.ts`) cannot load a `.tsx` file. Without a build step you can write the call JSX compiles to instead: `jsx('h1', { class: 'title' }, 'Hello')`, children after the props.
22
21
 
23
22
  A plugin written into `extensions/` while the app runs may use the docs' own names instead: `acrylblends` and `acrylblends/<subpath>` resolve to the same files. `App` is the
24
23
  deprecated name of `Acryl`.
@@ -3,13 +3,17 @@
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
5
  "type": "module",
6
+ "imports": {
7
+ "#acryl-jsx/jsx-runtime": "./src/plugins/acryl-router/src/core/jsx/jsx-runtime.ts",
8
+ "#acryl-jsx/jsx-dev-runtime": "./src/plugins/acryl-router/src/core/jsx/jsx-dev-runtime.ts"
9
+ },
6
10
  "engines": {
7
11
  "node": ">=22.19.0"
8
12
  },
9
13
  "scripts": {
10
- "start": "node src/main.ts",
11
- "dev": "node --watch src/main.ts",
12
- "test": "node --test",
14
+ "start": "node --import ./src/plugins/acryl-node-server/src/register.ts src/main.ts",
15
+ "dev": "node --watch --import ./src/plugins/acryl-node-server/src/register.ts src/main.ts",
16
+ "test": "node --import ./src/plugins/acryl-node-server/src/register.ts --test \"test/**/*.test.{ts,tsx}\"",
13
17
  "check": "tsc --noEmit",
14
18
  "lock": "node src/plugins/manifest/lock.ts",
15
19
  "save": "node src/plugins/save/cli.ts",
@@ -62,7 +62,9 @@
62
62
  "./src/plugins/acryl-router/src/core/jsx/jsx-dev-runtime.ts"
63
63
  ],
64
64
  "acrylblends/jsx/streaming": ["./src/plugins/acryl-router/src/core/jsx/streaming.ts"]
65
- }
65
+ },
66
+ "jsx": "react-jsx",
67
+ "jsxImportSource": "#acryl-jsx"
66
68
  },
67
69
  "include": ["src", "test", "extensions"]
68
70
  }
@@ -3,13 +3,17 @@
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
5
  "type": "module",
6
+ "imports": {
7
+ "#acryl-jsx/jsx-runtime": "./src/plugins/acryl-router/src/core/jsx/jsx-runtime.ts",
8
+ "#acryl-jsx/jsx-dev-runtime": "./src/plugins/acryl-router/src/core/jsx/jsx-dev-runtime.ts"
9
+ },
6
10
  "engines": {
7
11
  "node": ">=22.19.0"
8
12
  },
9
13
  "scripts": {
10
- "start": "node src/main.ts",
11
- "dev": "node --watch src/main.ts",
12
- "test": "node --test",
14
+ "start": "node --import ./src/plugins/acryl-node-server/src/register.ts src/main.ts",
15
+ "dev": "node --watch --import ./src/plugins/acryl-node-server/src/register.ts src/main.ts",
16
+ "test": "node --import ./src/plugins/acryl-node-server/src/register.ts --test \"test/**/*.test.{ts,tsx}\"",
13
17
  "check": "tsc --noEmit",
14
18
  "lock": "node src/plugins/manifest/lock.ts",
15
19
  "save": "node src/plugins/save/cli.ts",
@@ -0,0 +1,14 @@
1
+ /** A page written in JSX: the scripts in package.json run Node.js with the vendored register hook (src/plugins/acryl-node-server/src/register.ts), which compiles .tsx with this app's own typescript. */
2
+ const About = () => (
3
+ <main>
4
+ <h1>About</h1>
5
+ <p>Rendered on the server with the JSX runtime in src/plugins/acryl-router.</p>
6
+ </main>
7
+ )
8
+
9
+ export const aboutPage = (): string => (<About />).toString()
10
+
11
+ /** Throws on purpose: the template's test checks that the stack names this file, so a failure in your own pages points at the .tsx line. */
12
+ export const failingPage = (): string => {
13
+ throw new Error('a page failed')
14
+ }
@@ -1,4 +1,5 @@
1
1
  import type { Context } from '@deepseek-ai/cordis'
2
+ import { aboutPage } from './about.tsx'
2
3
  import { Acryl } from './plugins/acryl-router/src/index.ts'
3
4
 
4
5
  export const APP_NAME = '__APP_NAME__'
@@ -11,6 +12,7 @@ export const routes = {
11
12
  const app = new Acryl()
12
13
  .get('/', (c) => c.json({ app: APP_NAME, ok: true }))
13
14
  .get('/health', (c) => c.json({ ok: true }))
15
+ .get('/about', (c) => c.html(aboutPage()))
14
16
  ctx.router.route('/', app)
15
17
  },
16
18
  }
@@ -29,6 +29,21 @@ test('serves the index route', () =>
29
29
  assert.deepEqual(await response.json(), { app: APP_NAME, ok: true })
30
30
  }))
31
31
 
32
+ test('renders a .tsx page, and an error in it names the .tsx line', () =>
33
+ withApp(async (app) => {
34
+ const response = await fetch(`${app.url}/about`)
35
+ assert.equal(response.status, 200)
36
+ assert.match(await response.text(), /<main><h1>About<\/h1>/)
37
+ const { failingPage } = await import('../src/about.tsx')
38
+ let stack = ''
39
+ try {
40
+ failingPage()
41
+ } catch (error) {
42
+ stack = String((error as Error).stack)
43
+ }
44
+ assert.match(stack, /about\.tsx:\d+/)
45
+ }))
46
+
32
47
  test('answers health checks and 404 for unknown paths', () =>
33
48
  withApp(async (app) => {
34
49
  assert.equal((await fetch(`${app.url}/health`)).status, 200)
@@ -11,7 +11,9 @@
11
11
  "allowImportingTsExtensions": true,
12
12
  "noEmit": true,
13
13
  "skipLibCheck": true,
14
- "types": ["node"]
14
+ "types": ["node"],
15
+ "jsx": "react-jsx",
16
+ "jsxImportSource": "#acryl-jsx"
15
17
  },
16
18
  "include": ["src", "test"]
17
19
  }
@@ -3,13 +3,17 @@
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
5
  "type": "module",
6
+ "imports": {
7
+ "#acryl-jsx/jsx-runtime": "./src/plugins/acryl-router/src/core/jsx/jsx-runtime.ts",
8
+ "#acryl-jsx/jsx-dev-runtime": "./src/plugins/acryl-router/src/core/jsx/jsx-dev-runtime.ts"
9
+ },
6
10
  "engines": {
7
11
  "node": ">=22.19.0"
8
12
  },
9
13
  "scripts": {
10
- "start": "node src/main.ts",
11
- "dev": "node --watch src/main.ts",
12
- "test": "node --test",
14
+ "start": "node --import ./src/plugins/acryl-node-server/src/register.ts src/main.ts",
15
+ "dev": "node --watch --import ./src/plugins/acryl-node-server/src/register.ts src/main.ts",
16
+ "test": "node --import ./src/plugins/acryl-node-server/src/register.ts --test \"test/**/*.test.{ts,tsx}\"",
13
17
  "check": "tsc --noEmit",
14
18
  "lock": "node src/plugins/manifest/lock.ts",
15
19
  "save": "node src/plugins/save/cli.ts",
@@ -11,7 +11,9 @@
11
11
  "allowImportingTsExtensions": true,
12
12
  "noEmit": true,
13
13
  "skipLibCheck": true,
14
- "types": ["node"]
14
+ "types": ["node"],
15
+ "jsx": "react-jsx",
16
+ "jsxImportSource": "#acryl-jsx"
15
17
  },
16
18
  "include": ["src", "test"]
17
19
  }
@@ -5,7 +5,7 @@
5
5
  "examples/acryl-todo/src/index.ts": "src/todo.ts",
6
6
  "examples/acryl-todo/src/page.ts": "src/page.ts"
7
7
  },
8
- "commit": "fd1f7dcaaff8b757c0562294002c0d32d6e0a893"
8
+ "commit": "7bba3ed0420d87e61d8256fa60614d22af734c8f"
9
9
  },
10
10
  "rewrittenSpecifiers": 4,
11
11
  "digest": "sha256:9093704776563001f7f472f94cc5c2fdd79206342c1cb59c11fce62aa74df3ed"