netjes 0.0.0-stage → 0.0.2

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 (222) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +54 -2
  3. package/bin/netjes.mjs +13 -0
  4. package/cli/agents.mjs +66 -0
  5. package/cli/commands.mjs +467 -0
  6. package/cli/help.mjs +89 -0
  7. package/cli/info.mjs +454 -0
  8. package/cli/main.mjs +167 -0
  9. package/cli/packages.mjs +19 -0
  10. package/cli/process-io.mjs +163 -0
  11. package/cli/routes.mjs +31 -0
  12. package/cli/scaffold.mjs +193 -0
  13. package/cli/suggest.mjs +50 -0
  14. package/cli/terminal.mjs +40 -0
  15. package/dist/actions.d.ts +98 -0
  16. package/dist/actions.d.ts.map +1 -0
  17. package/dist/actions.js +176 -0
  18. package/dist/actions.js.map +1 -0
  19. package/dist/client-entry.d.ts +2 -0
  20. package/dist/client-entry.d.ts.map +1 -0
  21. package/dist/client-entry.js +126 -0
  22. package/dist/client-entry.js.map +1 -0
  23. package/dist/deferred.d.ts +39 -0
  24. package/dist/deferred.d.ts.map +1 -0
  25. package/dist/deferred.js +123 -0
  26. package/dist/deferred.js.map +1 -0
  27. package/dist/define-page.d.ts +15 -0
  28. package/dist/define-page.d.ts.map +1 -0
  29. package/dist/define-page.js +27 -0
  30. package/dist/define-page.js.map +1 -0
  31. package/dist/document.d.ts +19 -0
  32. package/dist/document.d.ts.map +1 -0
  33. package/dist/document.js +17 -0
  34. package/dist/document.js.map +1 -0
  35. package/dist/draft-mode.d.ts +5 -0
  36. package/dist/draft-mode.d.ts.map +1 -0
  37. package/dist/draft-mode.js +6 -0
  38. package/dist/draft-mode.js.map +1 -0
  39. package/dist/dynamic.d.ts +20 -0
  40. package/dist/dynamic.d.ts.map +1 -0
  41. package/dist/dynamic.js +37 -0
  42. package/dist/dynamic.js.map +1 -0
  43. package/dist/form-data.d.ts +10 -0
  44. package/dist/form-data.d.ts.map +1 -0
  45. package/dist/form-data.js +10 -0
  46. package/dist/form-data.js.map +1 -0
  47. package/dist/form.d.ts +35 -0
  48. package/dist/form.d.ts.map +1 -0
  49. package/dist/form.js +80 -0
  50. package/dist/form.js.map +1 -0
  51. package/dist/href.d.ts +25 -0
  52. package/dist/href.d.ts.map +1 -0
  53. package/dist/href.js +71 -0
  54. package/dist/href.js.map +1 -0
  55. package/dist/image.d.ts +36 -0
  56. package/dist/image.d.ts.map +1 -0
  57. package/dist/image.js +60 -0
  58. package/dist/image.js.map +1 -0
  59. package/dist/index.d.ts +18 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +14 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/link.d.ts +17 -0
  64. package/dist/link.d.ts.map +1 -0
  65. package/dist/link.js +46 -0
  66. package/dist/link.js.map +1 -0
  67. package/dist/locale.d.ts +3 -0
  68. package/dist/locale.d.ts.map +1 -0
  69. package/dist/locale.js +6 -0
  70. package/dist/locale.js.map +1 -0
  71. package/dist/metadata.d.ts +83 -0
  72. package/dist/metadata.d.ts.map +1 -0
  73. package/dist/metadata.js +100 -0
  74. package/dist/metadata.js.map +1 -0
  75. package/dist/modules.d.ts +74 -0
  76. package/dist/modules.d.ts.map +1 -0
  77. package/dist/modules.js +85 -0
  78. package/dist/modules.js.map +1 -0
  79. package/dist/nonce.d.ts +8 -0
  80. package/dist/nonce.d.ts.map +1 -0
  81. package/dist/nonce.js +12 -0
  82. package/dist/nonce.js.map +1 -0
  83. package/dist/payload.d.ts +171 -0
  84. package/dist/payload.d.ts.map +1 -0
  85. package/dist/payload.js +273 -0
  86. package/dist/payload.js.map +1 -0
  87. package/dist/public-config.d.ts +11 -0
  88. package/dist/public-config.d.ts.map +1 -0
  89. package/dist/public-config.js +10 -0
  90. package/dist/public-config.js.map +1 -0
  91. package/dist/query.d.ts +22 -0
  92. package/dist/query.d.ts.map +1 -0
  93. package/dist/query.js +68 -0
  94. package/dist/query.js.map +1 -0
  95. package/dist/render-cleanup.d.ts +6 -0
  96. package/dist/render-cleanup.d.ts.map +1 -0
  97. package/dist/render-cleanup.js +7 -0
  98. package/dist/render-cleanup.js.map +1 -0
  99. package/dist/root.d.ts +12 -0
  100. package/dist/root.d.ts.map +1 -0
  101. package/dist/root.js +26 -0
  102. package/dist/root.js.map +1 -0
  103. package/dist/route-tree.d.ts +56 -0
  104. package/dist/route-tree.d.ts.map +1 -0
  105. package/dist/route-tree.js +86 -0
  106. package/dist/route-tree.js.map +1 -0
  107. package/dist/router.d.ts +118 -0
  108. package/dist/router.d.ts.map +1 -0
  109. package/dist/router.js +938 -0
  110. package/dist/router.js.map +1 -0
  111. package/dist/schema.d.ts +35 -0
  112. package/dist/schema.d.ts.map +1 -0
  113. package/dist/schema.js +74 -0
  114. package/dist/schema.js.map +1 -0
  115. package/dist/script.d.ts +23 -0
  116. package/dist/script.d.ts.map +1 -0
  117. package/dist/script.js +89 -0
  118. package/dist/script.js.map +1 -0
  119. package/dist/server-entry.d.ts +2 -0
  120. package/dist/server-entry.d.ts.map +1 -0
  121. package/dist/server-entry.js +4 -0
  122. package/dist/server-entry.js.map +1 -0
  123. package/dist/server-render.d.ts +19 -0
  124. package/dist/server-render.d.ts.map +1 -0
  125. package/dist/server-render.js +193 -0
  126. package/dist/server-render.js.map +1 -0
  127. package/dist/testing-setup.d.ts +2 -0
  128. package/dist/testing-setup.d.ts.map +1 -0
  129. package/dist/testing-setup.js +8 -0
  130. package/dist/testing-setup.js.map +1 -0
  131. package/dist/testing.d.ts +76 -0
  132. package/dist/testing.d.ts.map +1 -0
  133. package/dist/testing.js +106 -0
  134. package/dist/testing.js.map +1 -0
  135. package/dist/vitals-config.d.ts +4 -0
  136. package/dist/vitals-config.d.ts.map +1 -0
  137. package/dist/vitals-config.js +5 -0
  138. package/dist/vitals-config.js.map +1 -0
  139. package/dist/vitals.d.ts +13 -0
  140. package/dist/vitals.d.ts.map +1 -0
  141. package/dist/vitals.js +60 -0
  142. package/dist/vitals.js.map +1 -0
  143. package/dist/zod.d.ts +19 -0
  144. package/dist/zod.d.ts.map +1 -0
  145. package/dist/zod.js +65 -0
  146. package/dist/zod.js.map +1 -0
  147. package/package.json +147 -4
  148. package/sidecar/server.mjs +325 -0
  149. package/skills/netjes/SKILL.md +93 -0
  150. package/skills/netjes/references/caching-and-streaming.md +68 -0
  151. package/skills/netjes/references/data-and-actions.md +98 -0
  152. package/skills/netjes/references/deployment.md +57 -0
  153. package/skills/netjes/references/routing.md +65 -0
  154. package/skills/netjes/references/testing.md +57 -0
  155. package/src/actions.tsx +241 -0
  156. package/src/client-entry.tsx +126 -0
  157. package/src/deferred.ts +134 -0
  158. package/src/define-page.tsx +41 -0
  159. package/src/document.tsx +49 -0
  160. package/src/draft-mode.ts +6 -0
  161. package/src/dynamic.tsx +64 -0
  162. package/src/form-data.ts +10 -0
  163. package/src/form.tsx +122 -0
  164. package/src/href.ts +79 -0
  165. package/src/image.tsx +91 -0
  166. package/src/index.ts +40 -0
  167. package/src/link.tsx +73 -0
  168. package/src/locale.ts +6 -0
  169. package/src/metadata.tsx +181 -0
  170. package/src/modules.ts +133 -0
  171. package/src/nonce.tsx +14 -0
  172. package/src/payload.ts +405 -0
  173. package/src/public-config.tsx +19 -0
  174. package/src/query.tsx +82 -0
  175. package/src/render-cleanup.ts +7 -0
  176. package/src/root.tsx +39 -0
  177. package/src/route-tree.tsx +139 -0
  178. package/src/router.tsx +1188 -0
  179. package/src/schema.ts +98 -0
  180. package/src/script.tsx +103 -0
  181. package/src/server-entry.tsx +4 -0
  182. package/src/server-render.tsx +223 -0
  183. package/src/testing-setup.ts +8 -0
  184. package/src/testing.tsx +177 -0
  185. package/src/virtual.d.ts +12 -0
  186. package/src/vitals-config.ts +6 -0
  187. package/src/vitals.tsx +68 -0
  188. package/src/zod.ts +72 -0
  189. package/template/.dockerignore +11 -0
  190. package/template/Dockerfile +58 -0
  191. package/template/Features/Home/HomePage.cs +32 -0
  192. package/template/Program.cs +28 -0
  193. package/template/Properties/launchSettings.json +13 -0
  194. package/template/README.md +24 -0
  195. package/template/SiteProps.cs +4 -0
  196. package/template/_AGENTS.md +64 -0
  197. package/template/_CLAUDE.md +1 -0
  198. package/template/__NAME__.csproj +11 -0
  199. package/template/_gitattributes +2 -0
  200. package/template/_gitignore +11 -0
  201. package/template/app/about/page.tsx +17 -0
  202. package/template/app/error.tsx +15 -0
  203. package/template/app/layout.tsx +33 -0
  204. package/template/app/not-found.tsx +14 -0
  205. package/template/app/page.tsx +14 -0
  206. package/template/appsettings.Development.json +3 -0
  207. package/template/appsettings.json +9 -0
  208. package/template/components/Greeting.test.tsx +25 -0
  209. package/template/components/Greeting.tsx +26 -0
  210. package/template/components/HelloForm.test.tsx +27 -0
  211. package/template/components/HelloForm.tsx +34 -0
  212. package/template/docker-compose.override.yml +15 -0
  213. package/template/docker-compose.prod.yml +26 -0
  214. package/template/docker-compose.yml +16 -0
  215. package/template/generated/netjes.ts +73 -0
  216. package/template/package.json +36 -0
  217. package/template/public/favicon.svg +6 -0
  218. package/template/styles/global.css +7 -0
  219. package/template/tsconfig.json +19 -0
  220. package/template/vite.config.ts +7 -0
  221. package/vite/plugin.d.ts +29 -0
  222. package/vite/plugin.mjs +291 -0
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { parseWith } from './schema.js';
3
+ /**
4
+ * Declares a page whose props (sent by the C# loader) are validated with a Standard Schema before rendering,
5
+ * so the component receives parsed, typed props instead of trusting the server's JSON.
6
+ */
7
+ export function definePage(schema, Page) {
8
+ function ValidatedPage(props) {
9
+ const parsed = parseWith(schema, props, 'props');
10
+ return _jsx(Page, { ...parsed });
11
+ }
12
+ ValidatedPage.displayName = `definePage(${Page.displayName ?? Page.name ?? 'Page'})`;
13
+ return ValidatedPage;
14
+ }
15
+ /**
16
+ * Declares a layout whose loader props (from `MapLayoutLoader` in C#) are validated with a Standard Schema. The
17
+ * component gets the parsed props next to `children` and `params`.
18
+ */
19
+ export function defineLayout(schema, Layout) {
20
+ function ValidatedLayout({ children, params, ...props }) {
21
+ const parsed = parseWith(schema, props, 'layout props');
22
+ return (_jsx(Layout, { ...parsed, params: params, children: children }));
23
+ }
24
+ ValidatedLayout.displayName = `defineLayout(${Layout.displayName ?? Layout.name ?? 'Layout'})`;
25
+ return ValidatedLayout;
26
+ }
27
+ //# sourceMappingURL=define-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-page.js","sourceRoot":"","sources":["../src/define-page.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAyB,SAAS,EAAE,MAAM,aAAa,CAAC;AAI/D;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,MAAc,EACd,IAAyD;IAEzD,SAAS,aAAa,CAAC,KAA8B;QACnD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAkD,CAAC;QAClG,OAAO,KAAC,IAAI,OAAK,MAAM,GAAI,CAAC;IAC9B,CAAC;IACD,aAAa,CAAC,WAAW,GAAG,cAAc,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,GAAG,CAAC;IACrF,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,MAAyE;IAEzE,SAAS,eAAe,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,EAAyC;QAC5F,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,cAAc,CAAkD,CAAC;QACzG,OAAO,CACL,KAAC,MAAM,OAAK,MAAM,EAAE,MAAM,EAAE,MAAM,YAC/B,QAAQ,GACF,CACV,CAAC;IACJ,CAAC;IACD,eAAe,CAAC,WAAW,GAAG,gBAAgB,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,IAAI,QAAQ,GAAG,CAAC;IAC/F,OAAO,eAAe,CAAC;AACzB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type DocumentInfo } from './payload.ts';
3
+ type DocumentProps = {
4
+ info: DocumentInfo;
5
+ dataJson: string;
6
+ children: ReactNode;
7
+ };
8
+ /**
9
+ * The `<html>` shell around every page. React renders and hydrates the whole document, so `<title>`, `<meta>`
10
+ * and `<link>` rendered by pages and layouts end up in the head.
11
+ *
12
+ * Documents stream, so the client entry is `async`: it hydrates the shell as soon as the shell is in, not once the
13
+ * last Suspense boundary has arrived. Everything it reads comes before the content: the deferred-values bootstrap in
14
+ * the head, the payload first in the body. The empty element at the end of the body is the last thing in the shell,
15
+ * which the client entry waits for before it hydrates: a cached entry can run long before the parser gets there.
16
+ */
17
+ export declare function Document({ info, dataJson, children }: DocumentProps): import("react").JSX.Element;
18
+ export {};
19
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAmB,KAAK,YAAY,EAAgB,MAAM,cAAc,CAAC;AAEhF,KAAK,aAAa,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,CAAC;AAEnF;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,aAAa,+BAiCnE"}
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { DEFERRED_BOOTSTRAP } from './deferred.js';
3
+ import { DATA_ELEMENT_ID, SHELL_END_ID } from './payload.js';
4
+ /**
5
+ * The `<html>` shell around every page. React renders and hydrates the whole document, so `<title>`, `<meta>`
6
+ * and `<link>` rendered by pages and layouts end up in the head.
7
+ *
8
+ * Documents stream, so the client entry is `async`: it hydrates the shell as soon as the shell is in, not once the
9
+ * last Suspense boundary has arrived. Everything it reads comes before the content: the deferred-values bootstrap in
10
+ * the head, the payload first in the body. The empty element at the end of the body is the last thing in the shell,
11
+ * which the client entry waits for before it hydrates: a cached entry can run long before the parser gets there.
12
+ */
13
+ export function Document({ info, dataJson, children }) {
14
+ const { nonce } = info;
15
+ return (_jsxs("html", { lang: info.lang, children: [_jsxs("head", { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), nonce && _jsx("meta", { property: "csp-nonce", nonce: nonce }), !info.clientRender && _jsx("script", { nonce: nonce, dangerouslySetInnerHTML: { __html: DEFERRED_BOOTSTRAP } }), info.assets.stylesheets.map((href) => (_jsx("link", { rel: "stylesheet", href: href, nonce: nonce }, href))), info.devStyles?.map((style) => (_jsx("style", { "data-vite-dev-id": style.id, nonce: nonce, dangerouslySetInnerHTML: { __html: style.css } }, style.id))), info.assets.modulePreloads.map((href) => (_jsx("link", { rel: "modulepreload", href: href, nonce: nonce }, href))), info.assets.scripts.map((src) => (_jsx("script", { type: "module", src: src, async: true, nonce: nonce }, src)))] }), _jsxs("body", { children: [_jsx("script", { id: DATA_ELEMENT_ID, type: "application/json", nonce: nonce, dangerouslySetInnerHTML: { __html: dataJson } }), children, _jsx("template", { id: SHELL_END_ID })] })] }));
16
+ }
17
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../src/document.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,eAAe,EAAqB,YAAY,EAAE,MAAM,cAAc,CAAC;AAIhF;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAiB;IAClE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IACvB,OAAO,CACL,gBAAM,IAAI,EAAE,IAAI,CAAC,IAAI,aACnB,2BACE,eAAM,OAAO,EAAC,OAAO,GAAG,EACxB,eAAM,IAAI,EAAC,UAAU,EAAC,OAAO,EAAC,qCAAqC,GAAG,EAErE,KAAK,IAAI,eAAM,QAAQ,EAAC,WAAW,EAAC,KAAK,EAAE,KAAK,GAAI,EAGpD,CAAC,IAAI,CAAC,YAAY,IAAI,iBAAQ,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAI,EACvG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACrC,eAAiB,GAAG,EAAC,YAAY,EAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,IAA/C,IAAI,CAA+C,CAC/D,CAAC,EACD,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAC9B,oCAAwC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,IAAlG,KAAK,CAAC,EAAE,CAA8F,CACnH,CAAC,EACD,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACxC,eAAiB,GAAG,EAAC,eAAe,EAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,IAAlD,IAAI,CAAkD,CAClE,CAAC,EACD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAChC,iBAAkB,IAAI,EAAC,QAAQ,EAAC,GAAG,EAAE,GAAG,EAAE,KAAK,QAAC,KAAK,EAAE,KAAK,IAA/C,GAAG,CAAgD,CACjE,CAAC,IACG,EACP,2BAEE,iBAAQ,EAAE,EAAE,eAAe,EAAE,IAAI,EAAC,kBAAkB,EAAC,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAI,EACnH,QAAQ,EACT,mBAAU,EAAE,EAAE,YAAY,GAAI,IACzB,IACF,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Whether this page was rendered in draft mode (`IDraftMode.Enable()` on the server), like Next.js's `draftMode()`. */
2
+ export declare function useDraftMode(): {
3
+ isEnabled: boolean;
4
+ };
5
+ //# sourceMappingURL=draft-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft-mode.d.ts","sourceRoot":"","sources":["../src/draft-mode.ts"],"names":[],"mappings":"AAEA,wHAAwH;AACxH,wBAAgB,YAAY,IAAI;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,CAErD"}
@@ -0,0 +1,6 @@
1
+ import { usePagePayload } from './router.js';
2
+ /** Whether this page was rendered in draft mode (`IDraftMode.Enable()` on the server), like Next.js's `draftMode()`. */
3
+ export function useDraftMode() {
4
+ return { isEnabled: usePagePayload().draftMode === true };
5
+ }
6
+ //# sourceMappingURL=draft-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft-mode.js","sourceRoot":"","sources":["../src/draft-mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAc,CAAC;AAE9C,wHAAwH;AACxH,MAAM,UAAU,YAAY;IAC1B,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { type ComponentType, type ReactNode } from 'react';
2
+ /** Options for `dynamic`. */
3
+ export type DynamicOptions = {
4
+ /** Server-render the component (default), or only render it in the browser (`false`), e.g. for code that needs `window`. */
5
+ ssr?: boolean;
6
+ /** Shown while the module loads, and on the server when `ssr` is false. */
7
+ loading?: ComponentType;
8
+ };
9
+ /**
10
+ * Like `next/dynamic`: a component whose module loads on demand, in its own chunk.
11
+ * `dynamic(() => import('./Chart.tsx'), { loading: Spinner })`.
12
+ */
13
+ export declare function dynamic<P extends object>(load: () => Promise<{
14
+ default: ComponentType<P>;
15
+ } | ComponentType<P>>, options?: DynamicOptions): ComponentType<P>;
16
+ /** A component that renders only in the browser, after hydration; `fallback` (default nothing) until then and on the server. */
17
+ export declare function clientOnly<P extends object>(Component: ComponentType<P>, options?: {
18
+ fallback?: ReactNode;
19
+ }): ComponentType<P>;
20
+ //# sourceMappingURL=dynamic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic.d.ts","sourceRoot":"","sources":["../src/dynamic.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAwC,MAAM,OAAO,CAAC;AAiBjG,6BAA6B;AAC7B,MAAM,MAAM,cAAc,GAAG;IAC3B,4HAA4H;IAC5H,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,2EAA2E;IAC3E,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,EACtC,IAAI,EAAE,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;CAAE,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,EACrE,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAAC,CAAC,CAAC,CAkBlB;AAED,gIAAgI;AAChI,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAO,GAAG,aAAa,CAAC,CAAC,CAAC,CAUlI"}
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Suspense, lazy, useSyncExternalStore } from 'react';
3
+ const subscribe = () => () => { };
4
+ /** False on the server and while hydrating, true afterwards (and for client-only renders): hydration-safe. */
5
+ function useHydrated() {
6
+ return useSyncExternalStore(subscribe, () => true, () => false);
7
+ }
8
+ function ClientOnly({ fallback, children }) {
9
+ return useHydrated() ? children : fallback;
10
+ }
11
+ /**
12
+ * Like `next/dynamic`: a component whose module loads on demand, in its own chunk.
13
+ * `dynamic(() => import('./Chart.tsx'), { loading: Spinner })`.
14
+ */
15
+ export function dynamic(load, options = {}) {
16
+ const Lazy = lazy(async () => {
17
+ const module = await load();
18
+ return { default: typeof module === 'function' ? module : module.default };
19
+ });
20
+ const Loading = options.loading;
21
+ function Dynamic(props) {
22
+ const fallback = Loading ? _jsx(Loading, {}) : null;
23
+ const content = (_jsx(Suspense, { fallback: fallback, children: _jsx(Lazy, { ...props }) }));
24
+ return options.ssr === false ? _jsx(ClientOnly, { fallback: fallback, children: content }) : content;
25
+ }
26
+ Dynamic.displayName = 'Dynamic';
27
+ return Dynamic;
28
+ }
29
+ /** A component that renders only in the browser, after hydration; `fallback` (default nothing) until then and on the server. */
30
+ export function clientOnly(Component, options = {}) {
31
+ function ClientOnlyComponent(props) {
32
+ return (_jsx(ClientOnly, { fallback: options.fallback ?? null, children: _jsx(Component, { ...props }) }));
33
+ }
34
+ ClientOnlyComponent.displayName = `clientOnly(${Component.displayName ?? Component.name ?? 'Component'})`;
35
+ return ClientOnlyComponent;
36
+ }
37
+ //# sourceMappingURL=dynamic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic.js","sourceRoot":"","sources":["../src/dynamic.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAsC,QAAQ,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAEjG,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;AAEjC,8GAA8G;AAC9G,SAAS,WAAW;IAClB,OAAO,oBAAoB,CACzB,SAAS,EACT,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACZ,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAgD;IACtF,OAAO,WAAW,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC7C,CAAC;AAUD;;;GAGG;AACH,MAAM,UAAU,OAAO,CACrB,IAAqE,EACrE,OAAO,GAAmB,EAAE;IAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE;QAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IAC7E,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,SAAS,OAAO,CAAC,KAAQ;QACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,KAAC,OAAO,KAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9C,MAAM,OAAO,GAAG,CACd,KAAC,QAAQ,IAAC,QAAQ,EAAE,QAAQ,YAC1B,KAAC,IAAI,OAAK,KAAK,GAAI,GACV,CACZ,CAAC;QACF,OAAO,OAAO,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,KAAC,UAAU,IAAC,QAAQ,EAAE,QAAQ,YAAG,OAAO,GAAc,CAAC,CAAC,CAAC,OAAO,CAAC;IAClG,CAAC;IACD,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAChC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gIAAgI;AAChI,MAAM,UAAU,UAAU,CAAmB,SAA2B,EAAE,OAAO,GAA6B,EAAE;IAC9G,SAAS,mBAAmB,CAAC,KAAQ;QACnC,OAAO,CACL,KAAC,UAAU,IAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI,YAC5C,KAAC,SAAS,OAAK,KAAK,GAAI,GACb,CACd,CAAC;IACJ,CAAC;IACD,mBAAmB,CAAC,WAAW,GAAG,cAAc,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,IAAI,IAAI,WAAW,GAAG,CAAC;IAC1G,OAAO,mBAAmB,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /** A form's fields as a request body: URL-encoded, or multipart when there are files or the form asks for it. */
2
+ export type EncodedForm = {
3
+ body: string;
4
+ contentType: string;
5
+ } | {
6
+ body: FormData;
7
+ contentType: null;
8
+ };
9
+ export declare function encodeForm(data: FormData, multipart?: boolean): EncodedForm;
10
+ //# sourceMappingURL=form-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-data.d.ts","sourceRoot":"","sources":["../src/form-data.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,IAAI,CAAA;CAAE,CAAC;AAExG,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,UAAQ,GAAG,WAAW,CAMzE"}
@@ -0,0 +1,10 @@
1
+ export function encodeForm(data, multipart = false) {
2
+ const entries = [...data.entries()];
3
+ if (multipart || entries.some(([, value]) => typeof value !== 'string'))
4
+ return { body: data, contentType: null };
5
+ const params = new URLSearchParams();
6
+ for (const [name, value] of entries)
7
+ params.append(name, String(value));
8
+ return { body: params.toString(), contentType: 'application/x-www-form-urlencoded;charset=UTF-8' };
9
+ }
10
+ //# sourceMappingURL=form-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-data.js","sourceRoot":"","sources":["../src/form-data.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,SAAS,GAAG,KAAK;IAC1D,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACpC,IAAI,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAClH,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO;QAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACxE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;AACrG,CAAC"}
package/dist/form.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ import type { ButtonHTMLAttributes, FormHTMLAttributes } from 'react';
2
+ /** A React form action, e.g. the `formAction` from `useAction(serverAction('name'))`. */
3
+ export type FormAction = (formData: FormData) => void | Promise<void>;
4
+ /** The props of `<Form>`: a form's own, with client navigation and server action support. */
5
+ export type FormProps = Omit<FormHTMLAttributes<HTMLFormElement>, 'method' | 'action'> & {
6
+ method?: 'get' | 'post';
7
+ /**
8
+ * Where to submit. Default: the current URL, which is where `MapPageAction` handlers for this page listen. Or a
9
+ * form action function: a server action from `useAction` (a real form post without JavaScript), or any function.
10
+ */
11
+ action?: string | FormAction;
12
+ replace?: boolean;
13
+ /**
14
+ * Let the browser submit it the classic way, with a full page load: for responses that are not pages, such as
15
+ * large file downloads, which the browser then streams to disk instead of Netjes buffering them.
16
+ */
17
+ reloadDocument?: boolean;
18
+ };
19
+ /**
20
+ * A `<form>` that submits without a full page load and handles the page action's result like a navigation:
21
+ * a redirect is followed, re-rendered props replace the page. Without JavaScript it is a normal form post.
22
+ * POST forms include the antiforgery token when the server has antiforgery enabled.
23
+ *
24
+ * With a function `action` React runs it (so `useFormStatus` works). For server actions the server renders a real
25
+ * `action`/`method`, the token and the return URL, so the same form also posts without JavaScript.
26
+ */
27
+ export declare function Form({ method, action, replace, reloadDocument, onSubmit, children, ...rest }: FormProps): import("react").JSX.Element;
28
+ /** The props of `<SubmitButton>`: a button's own, except `type`. */
29
+ export type SubmitButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'>;
30
+ /**
31
+ * A submit button whose `formAction` is rendered under the base path, so it posts to the right place with and
32
+ * without JavaScript (a plain `<button formAction="/x">` would miss the base without JavaScript).
33
+ */
34
+ export declare function SubmitButton({ formAction, ...rest }: SubmitButtonProps): import("react").JSX.Element;
35
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAe,MAAM,OAAO,CAAC;AAMnF,yFAAyF;AACzF,MAAM,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEtE,6FAA6F;AAC7F,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC,GAAG;IACvF,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAYF;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,EAAE,MAAc,EAAE,MAAM,EAAE,OAAe,EAAE,cAAsB,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,+BAiE/H;AAED,oEAAoE;AACpE,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC;AAEtF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,EAAE,iBAAiB,+BAItE"}
package/dist/form.js ADDED
@@ -0,0 +1,80 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { RETURN_FIELD, actionMetaOf } from './actions.js';
3
+ import { encodeForm } from './form-data.js';
4
+ import { useBasePath, useInternalRouter, usePagePayload, withBasePath } from './router.js';
5
+ function formDataOf(form, submitter) {
6
+ try {
7
+ return new FormData(form, submitter);
8
+ }
9
+ catch {
10
+ const data = new FormData(form);
11
+ if (submitter instanceof HTMLButtonElement && submitter.name)
12
+ data.append(submitter.name, submitter.value);
13
+ return data;
14
+ }
15
+ }
16
+ /**
17
+ * A `<form>` that submits without a full page load and handles the page action's result like a navigation:
18
+ * a redirect is followed, re-rendered props replace the page. Without JavaScript it is a normal form post.
19
+ * POST forms include the antiforgery token when the server has antiforgery enabled.
20
+ *
21
+ * With a function `action` React runs it (so `useFormStatus` works). For server actions the server renders a real
22
+ * `action`/`method`, the token and the return URL, so the same form also posts without JavaScript.
23
+ */
24
+ export function Form({ method = 'get', action, replace = false, reloadDocument = false, onSubmit, children, ...rest }) {
25
+ const router = useInternalRouter();
26
+ const payload = usePagePayload();
27
+ const basePath = useBasePath();
28
+ const isFunction = typeof action === 'function';
29
+ const serverAction = actionMetaOf(action);
30
+ const actionUrl = typeof action === 'string' ? withBasePath(action, basePath) : undefined;
31
+ const token = method === 'post' || serverAction ? payload.antiforgery : undefined;
32
+ const hidden = (_jsxs(_Fragment, { children: [token?.requestToken && _jsx("input", { type: "hidden", name: token.formFieldName, value: token.requestToken }), serverAction && _jsx("input", { type: "hidden", name: RETURN_FIELD, value: payload.url })] }));
33
+ if (isFunction) {
34
+ // React renders function actions as an inert placeholder on the server; a server action gets its real URL
35
+ // there instead. React keeps the server's attributes when hydrating a function action.
36
+ const onServer = typeof document === 'undefined';
37
+ return (_jsxs("form", { ...rest, action: onServer && serverAction ? withBasePath(serverAction.url, basePath) : action, method: onServer && serverAction ? 'post' : undefined, onSubmit: onSubmit, children: [hidden, children] }));
38
+ }
39
+ function handleSubmit(event) {
40
+ onSubmit?.(event);
41
+ if (event.defaultPrevented || reloadDocument)
42
+ return;
43
+ const form = event.currentTarget;
44
+ const submitter = event.submitter;
45
+ const target = submitter?.getAttribute('formtarget') ?? form.getAttribute('target');
46
+ if (target && target !== '_self')
47
+ return;
48
+ const formAction = submitter?.getAttribute('formaction');
49
+ const url = new URL(formAction ? withBasePath(formAction, basePath) : (actionUrl ?? window.location.href), window.location.href);
50
+ if (url.origin !== window.location.origin)
51
+ return;
52
+ event.preventDefault();
53
+ const data = formDataOf(form, submitter);
54
+ const submitMethod = (submitter?.getAttribute('formmethod') ?? method).toLowerCase();
55
+ if (submitMethod === 'post') {
56
+ void router.submit(url, encodeForm(data, form.enctype === 'multipart/form-data'));
57
+ return;
58
+ }
59
+ const query = new URLSearchParams();
60
+ for (const [name, value] of data.entries())
61
+ if (typeof value === 'string')
62
+ query.append(name, value);
63
+ url.search = query.toString();
64
+ url.hash = '';
65
+ // Built from the form's own action, which is not one of the app's typed routes.
66
+ const href = url.href;
67
+ void (replace ? router.replace(href) : router.push(href));
68
+ }
69
+ return (_jsxs("form", { method: method, action: actionUrl, ...rest, onSubmit: handleSubmit, children: [hidden, children] }));
70
+ }
71
+ /**
72
+ * A submit button whose `formAction` is rendered under the base path, so it posts to the right place with and
73
+ * without JavaScript (a plain `<button formAction="/x">` would miss the base without JavaScript).
74
+ */
75
+ export function SubmitButton({ formAction, ...rest }) {
76
+ const basePath = useBasePath();
77
+ const action = typeof formAction === 'string' ? withBasePath(formAction, basePath) : formAction;
78
+ return _jsx("button", { type: "submit", formAction: action, ...rest });
79
+ }
80
+ //# sourceMappingURL=form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.tsx"],"names":[],"mappings":"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"}
package/dist/href.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Apps register their generated route type here (the file `netjes generate` writes does it), which types the
3
+ * `href` of `<Link>` and `router.push`: `declare module 'netjes' { interface Register { href: Href } }`.
4
+ */
5
+ export interface Register {
6
+ }
7
+ /** A URL `<Link>` and the router accept: the app's routes once registered, any string before that. */
8
+ export type Href = Register extends {
9
+ href: infer H extends string;
10
+ } ? H : string;
11
+ /** One value of a query string: `null` and `undefined` leave the key out. */
12
+ export type SearchValue = string | number | boolean | null | undefined;
13
+ /** A query string as an object: a value per key, or a list of values for a key that repeats. */
14
+ export type SearchParamsInput = Record<string, SearchValue | readonly SearchValue[]>;
15
+ /**
16
+ * Whether a URL is one of the app's pages (by route pattern), a link within the page (`?…`, `#…`), or another
17
+ * site. The generated `isHref()` and `Href` schema call this to check URLs that come from data.
18
+ */
19
+ export declare function isRouteHref(value: string, patterns: readonly string[]): boolean;
20
+ /**
21
+ * Builds the URL for a route pattern written in file-name syntax (`/blog/[slug]`, `/docs/[...path]`,
22
+ * `/shop/[[...filters]]`), encoding every segment value. The generated `route()` helper calls this with typed params.
23
+ */
24
+ export declare function buildHref(pattern: string, params: Record<string, unknown>, search?: SearchParamsInput): string;
25
+ //# sourceMappingURL=href.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"href.d.ts","sourceRoot":"","sources":["../src/href.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,QAAQ;CAAG;AAE5B,sGAAsG;AACtG,MAAM,MAAM,IAAI,GAAG,QAAQ,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;CAAE,GAAG,CAAC,GAAG,MAAM,CAAC;AAElF,6EAA6E;AAC7E,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AACvE,gGAAgG;AAChG,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,WAAW,EAAE,CAAC,CAAC;AAarF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAM/E;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAoC9G"}
package/dist/href.js ADDED
@@ -0,0 +1,71 @@
1
+ function matches(pattern, path) {
2
+ for (let i = 0; i < pattern.length; i++) {
3
+ const segment = pattern[i];
4
+ if (segment.startsWith('[[...'))
5
+ return true;
6
+ if (segment.startsWith('[...'))
7
+ return path.length > i;
8
+ if (i >= path.length)
9
+ return false;
10
+ if (!segment.startsWith('[') && segment !== path[i])
11
+ return false;
12
+ }
13
+ return pattern.length === path.length;
14
+ }
15
+ /**
16
+ * Whether a URL is one of the app's pages (by route pattern), a link within the page (`?…`, `#…`), or another
17
+ * site. The generated `isHref()` and `Href` schema call this to check URLs that come from data.
18
+ */
19
+ export function isRouteHref(value, patterns) {
20
+ if (/^(https?:|mailto:|tel:)/i.test(value) || value.startsWith('?') || value.startsWith('#'))
21
+ return true;
22
+ // "//host" and "/\host" are other hosts as far as browsers are concerned.
23
+ if (!value.startsWith('/') || value.startsWith('//') || value.startsWith('/\\'))
24
+ return false;
25
+ const path = (value.split(/[?#]/, 1)[0] ?? '').split('/').filter(Boolean);
26
+ return patterns.some((pattern) => matches(pattern.split('/').filter(Boolean), path));
27
+ }
28
+ /**
29
+ * Builds the URL for a route pattern written in file-name syntax (`/blog/[slug]`, `/docs/[...path]`,
30
+ * `/shop/[[...filters]]`), encoding every segment value. The generated `route()` helper calls this with typed params.
31
+ */
32
+ export function buildHref(pattern, params, search) {
33
+ const missing = (name) => {
34
+ throw new Error(`netjes: route '${pattern}' needs the parameter '${name}'`);
35
+ };
36
+ const segments = pattern
37
+ .split('/')
38
+ .filter(Boolean)
39
+ .flatMap((segment) => {
40
+ const optional = /^\[\[\.\.\.(\w+)\]\]$/.exec(segment)?.[1];
41
+ if (optional) {
42
+ const values = params[optional];
43
+ return Array.isArray(values) ? values.map((v) => encodeURIComponent(String(v))) : [];
44
+ }
45
+ const catchAll = /^\[\.\.\.(\w+)\]$/.exec(segment)?.[1];
46
+ if (catchAll) {
47
+ const values = params[catchAll];
48
+ if (!Array.isArray(values) || values.length === 0)
49
+ return missing(catchAll);
50
+ return values.map((v) => encodeURIComponent(String(v)));
51
+ }
52
+ const single = /^\[(\w+)\]$/.exec(segment)?.[1];
53
+ if (single) {
54
+ const value = params[single];
55
+ if (value === undefined || value === null || value === '')
56
+ return missing(single);
57
+ return [encodeURIComponent(String(value))];
58
+ }
59
+ return [segment];
60
+ });
61
+ const query = new URLSearchParams();
62
+ for (const [key, value] of Object.entries(search ?? {})) {
63
+ for (const item of Array.isArray(value) ? value : [value]) {
64
+ if (item !== undefined && item !== null)
65
+ query.append(key, String(item));
66
+ }
67
+ }
68
+ const queryString = query.toString();
69
+ return `/${segments.join('/')}${queryString ? `?${queryString}` : ''}`;
70
+ }
71
+ //# sourceMappingURL=href.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"href.js","sourceRoot":"","sources":["../src/href.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { type ImgHTMLAttributes } from 'react';
2
+ /**
3
+ * Where the optimizer lives, and the widths and qualities it serves: Netjes:Images on the server, sent with the first
4
+ * document. Without `qualities`, any quality is requested as given.
5
+ */
6
+ export type ImageConfig = {
7
+ path: string;
8
+ widths: readonly number[];
9
+ qualities?: readonly number[];
10
+ basePath?: string;
11
+ };
12
+ export declare const ImageConfigProvider: import("react").Provider<ImageConfig>;
13
+ /** The props of `<Image>`: an `<img>`'s own, with a required size and `alt`, and the optimizer's options. */
14
+ export type ImageProps = Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'srcSet' | 'width' | 'height' | 'loading' | 'alt'> & {
15
+ /** A path in `public/` (`/img/hero.png`) or a URL on a host in Netjes:Images:RemoteHosts. */
16
+ src: string;
17
+ /** Required, as for any image; `""` for decorative ones. */
18
+ alt: string;
19
+ /** The intrinsic size in CSS pixels; reserves space so the page does not shift as it loads. */
20
+ width: number;
21
+ height: number;
22
+ /** For responsive layouts, e.g. `(max-width: 768px) 100vw, 50vw`: the browser then picks from every width. */
23
+ sizes?: string;
24
+ /** 1–100. Default 75. Rounded to the nearest of Netjes:Images:Qualities. */
25
+ quality?: number;
26
+ /** Above the fold: load eagerly with high priority, and preload it from the document head. */
27
+ priority?: boolean;
28
+ /** Serve `src` as is. SVGs and data URLs always are. */
29
+ unoptimized?: boolean;
30
+ };
31
+ /**
32
+ * Like `next/image`: an `<img>` with width and height (no layout shift), lazy loading, and a `srcset` of resized
33
+ * copies from the `/_netjes/image` endpoint, so each screen downloads only what it needs.
34
+ */
35
+ export declare function Image({ src, alt, width, height, sizes, quality, priority, unoptimized, ...rest }: ImageProps): import("react").JSX.Element;
36
+ //# sourceMappingURL=image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAA6B,MAAM,OAAO,CAAC;AAG1E;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAUxH,eAAO,MAAM,mBAAmB,uCAA8B,CAAC;AAE/D,6GAA6G;AAC7G,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC,GAAG;IAC9H,6FAA6F;IAC7F,GAAG,EAAE,MAAM,CAAC;IACZ,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,+FAA+F;IAC/F,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,8GAA8G;IAC9G,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAyBF;;;GAGG;AACH,wBAAgB,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAY,EAAE,QAAgB,EAAE,WAAmB,EAAE,GAAG,IAAI,EAAE,EAAE,UAAU,+BAyBjI"}
package/dist/image.js ADDED
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from 'react';
3
+ import { preload } from 'react-dom';
4
+ /** Next.js's device and image sizes; the server's Netjes:Images:Widths default to the same. */
5
+ const DEFAULT_CONFIG = {
6
+ path: '/_netjes/image',
7
+ widths: [16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840],
8
+ };
9
+ const ImageConfigContext = createContext(DEFAULT_CONFIG);
10
+ export const ImageConfigProvider = ImageConfigContext.Provider;
11
+ function optimizerUrl(config, src, width, quality) {
12
+ return `${config.path}?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`;
13
+ }
14
+ /** The accepted quality nearest to the one asked for (the higher one on a tie). */
15
+ function qualityFor(qualities, wanted) {
16
+ if (!qualities?.length)
17
+ return wanted;
18
+ return qualities.reduce((best, q) => (Math.abs(q - wanted) < Math.abs(best - wanted) || (Math.abs(q - wanted) === Math.abs(best - wanted) && q > best) ? q : best));
19
+ }
20
+ /** The smallest configured width that covers `target`, or the largest there is. */
21
+ function widthFor(widths, target) {
22
+ return widths.find((w) => w >= target) ?? widths[widths.length - 1] ?? target;
23
+ }
24
+ function underBasePath(src, basePath) {
25
+ return basePath && src.startsWith('/') && !src.startsWith('//') && !src.startsWith(`${basePath}/`) ? basePath + src : src;
26
+ }
27
+ function isUnoptimizable(src) {
28
+ return src.startsWith('data:') || src.startsWith('blob:') || /\.svg($|[?#])/i.test(src);
29
+ }
30
+ /**
31
+ * Like `next/image`: an `<img>` with width and height (no layout shift), lazy loading, and a `srcset` of resized
32
+ * copies from the `/_netjes/image` endpoint, so each screen downloads only what it needs.
33
+ */
34
+ export function Image({ src, alt, width, height, sizes, quality = 75, priority = false, unoptimized = false, ...rest }) {
35
+ const config = useContext(ImageConfigContext);
36
+ const common = {
37
+ ...rest,
38
+ alt,
39
+ width,
40
+ height,
41
+ decoding: 'async',
42
+ loading: priority ? 'eager' : 'lazy',
43
+ ...(priority ? { fetchPriority: 'high' } : {}),
44
+ };
45
+ // Served as is, from public/: under the app's base path. (The optimizer's `url` stays a public/ path.)
46
+ if (unoptimized || isUnoptimizable(src))
47
+ return _jsx("img", { ...common, src: underBasePath(src, config.basePath) });
48
+ const widths = [...config.widths].sort((a, b) => a - b);
49
+ const q = qualityFor(config.qualities, quality);
50
+ // Responsive: every width, the browser picks by `sizes`. Fixed: 1x and 2x, each once.
51
+ const chosen = sizes ? widths : [...new Set([widthFor(widths, width), widthFor(widths, width * 2)])];
52
+ const srcSet = chosen
53
+ .map((w, i) => `${optimizerUrl(config, src, w, q)} ${sizes ? `${w}w` : `${i + 1}x`}`)
54
+ .join(', ');
55
+ const fallback = optimizerUrl(config, src, chosen[chosen.length - 1] ?? width, q);
56
+ if (priority)
57
+ preload(fallback, { as: 'image', imageSrcSet: srcSet, ...(sizes ? { imageSizes: sizes } : {}), fetchPriority: 'high' });
58
+ return _jsx("img", { ...common, sizes: sizes, srcSet: srcSet, src: fallback });
59
+ }
60
+ //# sourceMappingURL=image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export { type ActionState, type PageActionFailure, type ServerAction, ServerActionError, type UseActionOptions, serverAction, useAction, usePageActionState, } from './actions.tsx';
2
+ export { defineLayout, definePage } from './define-page.tsx';
3
+ export { useDraftMode } from './draft-mode.ts';
4
+ export { type DynamicOptions, clientOnly, dynamic } from './dynamic.tsx';
5
+ export { Form, type FormAction, type FormProps, SubmitButton, type SubmitButtonProps } from './form.tsx';
6
+ export { type Href, type Register, type SearchParamsInput, type SearchValue, buildHref, isRouteHref } from './href.ts';
7
+ export { Image, type ImageProps } from './image.tsx';
8
+ export { Link, type LinkProps } from './link.tsx';
9
+ export { useLocale } from './locale.ts';
10
+ export type { ErrorPageProps, LayoutProps } from './modules.ts';
11
+ export { useNonce } from './nonce.tsx';
12
+ export type { PageKind, Params, SeededQuery, SegmentRef } from './payload.ts';
13
+ export { usePublicConfig } from './public-config.tsx';
14
+ export { Script, type ScriptProps, type ScriptStrategy } from './script.tsx';
15
+ export { type NavigationState, type SubmitError, type Router, useBasePath, useHref, useNavigation, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useSharedProps, } from './router.tsx';
16
+ export type { StandardSchemaV1 } from './schema.ts';
17
+ export type { Metadata, MetadataImage, MetadataTitle } from './metadata.tsx';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,YAAY,EACZ,SAAS,EACT,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,KAAK,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,IAAI,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACzG,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,KAAK,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACvH,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,WAAW,EACX,OAAO,EACP,aAAa,EACb,SAAS,EACT,WAAW,EACX,SAAS,EACT,eAAe,EACf,wBAAwB,EACxB,yBAAyB,EACzB,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ export { ServerActionError, serverAction, useAction, usePageActionState, } from './actions.js';
2
+ export { defineLayout, definePage } from './define-page.js';
3
+ export { useDraftMode } from './draft-mode.js';
4
+ export { clientOnly, dynamic } from './dynamic.js';
5
+ export { Form, SubmitButton } from './form.js';
6
+ export { buildHref, isRouteHref } from './href.js';
7
+ export { Image } from './image.js';
8
+ export { Link } from './link.js';
9
+ export { useLocale } from './locale.js';
10
+ export { useNonce } from './nonce.js';
11
+ export { usePublicConfig } from './public-config.js';
12
+ export { Script } from './script.js';
13
+ export { useBasePath, useHref, useNavigation, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useSharedProps, } from './router.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,iBAAiB,EAEjB,YAAY,EACZ,SAAS,EACT,kBAAkB,GACnB,MAAM,cAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAmB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAuB,UAAU,EAAE,OAAO,EAAE,MAAM,cAAe,CAAC;AACzE,OAAO,EAAE,IAAI,EAAmC,YAAY,EAA0B,MAAM,WAAY,CAAC;AACzG,OAAO,EAAsE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACvH,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAa,CAAC;AACrD,OAAO,EAAE,IAAI,EAAkB,MAAM,WAAY,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAa,CAAC;AAEvC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAqB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAyC,MAAM,aAAc,CAAC;AAC7E,OAAO,EAIL,WAAW,EACX,OAAO,EACP,aAAa,EACb,SAAS,EACT,WAAW,EACX,SAAS,EACT,eAAe,EACf,wBAAwB,EACxB,yBAAyB,EACzB,cAAc,GACf,MAAM,aAAc,CAAC"}