@devlusoft/devix 0.2.0 → 0.2.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 (85) hide show
  1. package/dist/cli/build.js +31 -308
  2. package/dist/cli/build.js.map +3 -3
  3. package/dist/cli/dev.js +33 -395
  4. package/dist/cli/dev.js.map +3 -3
  5. package/dist/cli/generate.js +31 -434
  6. package/dist/cli/generate.js.map +3 -3
  7. package/dist/cli/index.js +34 -698
  8. package/dist/cli/index.js.map +3 -3
  9. package/dist/cli/start.js +1 -89
  10. package/dist/cli/start.js.map +2 -2
  11. package/dist/config.js +1 -16
  12. package/dist/config.js.map +2 -2
  13. package/dist/runtime/api-context.js +1 -17
  14. package/dist/runtime/api-context.js.map +2 -2
  15. package/dist/runtime/client-router.js +1 -58
  16. package/dist/runtime/client-router.js.map +2 -2
  17. package/dist/runtime/context.js +1 -14
  18. package/dist/runtime/context.js.map +2 -2
  19. package/dist/runtime/error-boundary.js +1 -36
  20. package/dist/runtime/error-boundary.js.map +2 -2
  21. package/dist/runtime/fetch.js +1 -34
  22. package/dist/runtime/fetch.js.map +2 -2
  23. package/dist/runtime/head.js +1 -68
  24. package/dist/runtime/head.js.map +2 -2
  25. package/dist/runtime/index.d.ts +1 -0
  26. package/dist/runtime/index.js +1 -367
  27. package/dist/runtime/index.js.map +3 -3
  28. package/dist/runtime/link.js +1 -42
  29. package/dist/runtime/link.js.map +2 -2
  30. package/dist/runtime/metadata.js +1 -21
  31. package/dist/runtime/metadata.js.map +2 -2
  32. package/dist/runtime/router-provider.js +1 -258
  33. package/dist/runtime/router-provider.js.map +2 -2
  34. package/dist/server/api-router.js +1 -64
  35. package/dist/server/api-router.js.map +2 -2
  36. package/dist/server/api.js +1 -123
  37. package/dist/server/api.js.map +2 -2
  38. package/dist/server/collect-css.js +1 -14
  39. package/dist/server/collect-css.js.map +2 -2
  40. package/dist/server/index.js +1 -132
  41. package/dist/server/index.js.map +2 -2
  42. package/dist/server/pages-router.js +1 -63
  43. package/dist/server/pages-router.js.map +2 -2
  44. package/dist/server/render.js +1 -305
  45. package/dist/server/render.js.map +2 -2
  46. package/dist/server/routes.js +1 -41
  47. package/dist/server/routes.js.map +2 -2
  48. package/dist/utils/async.js +1 -13
  49. package/dist/utils/async.js.map +2 -2
  50. package/dist/utils/banner.js +1 -33
  51. package/dist/utils/banner.js.map +2 -2
  52. package/dist/utils/cookies.js +1 -28
  53. package/dist/utils/cookies.js.map +2 -2
  54. package/dist/utils/duration.js +1 -21
  55. package/dist/utils/duration.js.map +2 -2
  56. package/dist/utils/env.js +1 -13
  57. package/dist/utils/env.js.map +2 -2
  58. package/dist/utils/html.js +1 -11
  59. package/dist/utils/html.js.map +2 -2
  60. package/dist/utils/patterns.js +1 -7
  61. package/dist/utils/patterns.js.map +2 -2
  62. package/dist/utils/response.d.ts +4 -1
  63. package/dist/utils/response.js +1 -9
  64. package/dist/utils/response.js.map +3 -3
  65. package/dist/vite/codegen/api.js +6 -12
  66. package/dist/vite/codegen/api.js.map +2 -2
  67. package/dist/vite/codegen/client-routes.js +6 -12
  68. package/dist/vite/codegen/client-routes.js.map +2 -2
  69. package/dist/vite/codegen/context.js +2 -8
  70. package/dist/vite/codegen/context.js.map +2 -2
  71. package/dist/vite/codegen/entry-client.js +4 -10
  72. package/dist/vite/codegen/entry-client.js.map +2 -2
  73. package/dist/vite/codegen/extract-methods.js +1 -15
  74. package/dist/vite/codegen/extract-methods.js.map +2 -2
  75. package/dist/vite/codegen/render.js +6 -12
  76. package/dist/vite/codegen/render.js.map +2 -2
  77. package/dist/vite/codegen/routes-dts.js +12 -49
  78. package/dist/vite/codegen/routes-dts.js.map +3 -3
  79. package/dist/vite/codegen/scan-api.js +1 -77
  80. package/dist/vite/codegen/scan-api.js.map +3 -3
  81. package/dist/vite/codegen/write-routes-dts.js +1 -16
  82. package/dist/vite/codegen/write-routes-dts.js.map +2 -2
  83. package/dist/vite/index.js +31 -247
  84. package/dist/vite/index.js.map +3 -3
  85. package/package.json +2 -2
@@ -1,37 +1,2 @@
1
- // src/runtime/error-boundary.tsx
2
- import { Component } from "react";
3
- import { jsx } from "react/jsx-runtime";
4
- var DevixErrorBoundary = class extends Component {
5
- state = { error: null };
6
- static getDerivedStateFromError(err) {
7
- if (err instanceof DevixError) {
8
- return {
9
- error: { statusCode: err.statusCode, message: err.message }
10
- };
11
- }
12
- return {
13
- error: { statusCode: 500, message: err instanceof Error ? err.message : "Unknown error" }
14
- };
15
- }
16
- render() {
17
- if (this.state.error && this.props.ErrorPage) {
18
- return /* @__PURE__ */ jsx(this.props.ErrorPage, { ...this.state.error });
19
- }
20
- if (this.state.error) {
21
- return /* @__PURE__ */ jsx("h1", { children: this.state.error.statusCode });
22
- }
23
- return this.props.children;
24
- }
25
- };
26
- var DevixError = class extends Error {
27
- statusCode;
28
- constructor(statusCode, message) {
29
- super(message);
30
- this.statusCode = statusCode;
31
- }
32
- };
33
- export {
34
- DevixError,
35
- DevixErrorBoundary
36
- };
1
+ import{Component as a}from"react";import{jsx as s}from"react/jsx-runtime";var t=class extends a{state={error:null};static getDerivedStateFromError(r){return r instanceof e?{error:{statusCode:r.statusCode,message:r.message}}:{error:{statusCode:500,message:r instanceof Error?r.message:"Unknown error"}}}render(){return this.state.error&&this.props.ErrorPage?s(this.props.ErrorPage,{...this.state.error}):this.state.error?s("h1",{children:this.state.error.statusCode}):this.props.children}},e=class extends Error{statusCode;constructor(r,n){super(n),this.statusCode=r}};export{e as DevixError,t as DevixErrorBoundary};
37
2
  //# sourceMappingURL=error-boundary.js.map
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/runtime/error-boundary.tsx"],
4
4
  "sourcesContent": ["import {Component, ComponentType, ReactNode} from \"react\";\nimport {ErrorProps} from \"../server/types\";\n\ninterface Props {\n ErrorPage?: ComponentType<ErrorProps>\n children: ReactNode\n}\n\ninterface State {\n error: ErrorProps | null\n}\n\nexport class DevixErrorBoundary extends Component<Props, State> {\n state: State = { error: null }\n\n static getDerivedStateFromError(err: unknown): State {\n if (err instanceof DevixError) {\n return {\n error: {statusCode: err.statusCode, message: err.message}\n }\n }\n return {\n error: {statusCode: 500, message: err instanceof Error ? err.message : 'Unknown error'}\n }\n }\n\n render() {\n if (this.state.error && this.props.ErrorPage) {\n return <this.props.ErrorPage {...this.state.error} />\n }\n if (this.state.error) {\n return <h1>{this.state.error.statusCode}</h1>\n }\n return this.props.children\n }\n}\n\nexport class DevixError extends Error {\n statusCode: number\n constructor(statusCode: number, message: string) {\n super(message)\n this.statusCode = statusCode\n }\n}\n"],
5
- "mappings": ";AAAA,SAAQ,iBAA0C;AA4B/B;AAhBZ,IAAM,qBAAN,cAAiC,UAAwB;AAAA,EAC5D,QAAe,EAAE,OAAO,KAAK;AAAA,EAE7B,OAAO,yBAAyB,KAAqB;AACjD,QAAI,eAAe,YAAY;AAC3B,aAAO;AAAA,QACH,OAAO,EAAC,YAAY,IAAI,YAAY,SAAS,IAAI,QAAO;AAAA,MAC5D;AAAA,IACJ;AACA,WAAQ;AAAA,MACJ,OAAO,EAAC,YAAY,KAAK,SAAS,eAAe,QAAQ,IAAI,UAAU,gBAAe;AAAA,IAC1F;AAAA,EACJ;AAAA,EAEA,SAAS;AACL,QAAI,KAAK,MAAM,SAAS,KAAK,MAAM,WAAW;AAC1C,aAAO,oBAAC,KAAK,MAAM,WAAX,EAAsB,GAAG,KAAK,MAAM,OAAO;AAAA,IACvD;AACA,QAAI,KAAK,MAAM,OAAO;AAClB,aAAO,oBAAC,QAAI,eAAK,MAAM,MAAM,YAAW;AAAA,IAC5C;AACA,WAAO,KAAK,MAAM;AAAA,EACtB;AACJ;AAEO,IAAM,aAAN,cAAyB,MAAM;AAAA,EAClC;AAAA,EACA,YAAY,YAAoB,SAAiB;AAC7C,UAAM,OAAO;AACb,SAAK,aAAa;AAAA,EACtB;AACJ;",
6
- "names": []
5
+ "mappings": "AAAA,OAAQ,aAAAA,MAA0C,QA4B/B,cAAAC,MAAA,oBAhBZ,IAAMC,EAAN,cAAiCF,CAAwB,CAC5D,MAAe,CAAE,MAAO,IAAK,EAE7B,OAAO,yBAAyBG,EAAqB,CACjD,OAAIA,aAAeC,EACR,CACH,MAAO,CAAC,WAAYD,EAAI,WAAY,QAASA,EAAI,OAAO,CAC5D,EAEI,CACJ,MAAO,CAAC,WAAY,IAAK,QAASA,aAAe,MAAQA,EAAI,QAAU,eAAe,CAC1F,CACJ,CAEA,QAAS,CACL,OAAI,KAAK,MAAM,OAAS,KAAK,MAAM,UACxBF,EAAC,KAAK,MAAM,UAAX,CAAsB,GAAG,KAAK,MAAM,MAAO,EAEnD,KAAK,MAAM,MACJA,EAAC,MAAI,cAAK,MAAM,MAAM,WAAW,EAErC,KAAK,MAAM,QACtB,CACJ,EAEaG,EAAN,cAAyB,KAAM,CAClC,WACA,YAAYC,EAAoBC,EAAiB,CAC7C,MAAMA,CAAO,EACb,KAAK,WAAaD,CACtB,CACJ",
6
+ "names": ["Component", "jsx", "DevixErrorBoundary", "err", "DevixError", "statusCode", "message"]
7
7
  }
@@ -1,35 +1,2 @@
1
- // src/runtime/fetch.ts
2
- var FetchError = class extends Error {
3
- constructor(status, statusText, response) {
4
- super(`HTTP ${status}: ${statusText}`);
5
- this.status = status;
6
- this.statusText = statusText;
7
- this.response = response;
8
- this.name = "FetchError";
9
- }
10
- };
11
- async function $fetch(path, options) {
12
- const method = options?.method ?? "GET";
13
- const headers = new Headers(options?.headers);
14
- let body;
15
- if (options?.body !== void 0) {
16
- body = JSON.stringify(options.body);
17
- if (!headers.has("Content-Type")) {
18
- headers.set("Content-Type", "application/json");
19
- }
20
- }
21
- const response = await fetch(path, { method, headers, body, signal: options?.signal });
22
- if (!response.ok) {
23
- throw new FetchError(response.status, response.statusText, response);
24
- }
25
- const contentType = response.headers.get("Content-Type") ?? "";
26
- if (contentType.includes("application/json")) {
27
- return response.json();
28
- }
29
- return response.text();
30
- }
31
- export {
32
- $fetch,
33
- FetchError
34
- };
1
+ var r=class extends Error{constructor(s,n,o){super(`HTTP ${s}: ${n}`);this.status=s;this.statusText=n;this.response=o;this.name="FetchError"}};async function p(i,t){let s=t?.method??"GET",n=new Headers(t?.headers),o;t?.body!==void 0&&(o=JSON.stringify(t.body),n.has("Content-Type")||n.set("Content-Type","application/json"));let e=await fetch(i,{method:s,headers:n,body:o,signal:t?.signal});if(!e.ok)throw new r(e.status,e.statusText,e);return(e.headers.get("Content-Type")??"").includes("application/json")?e.json():e.text()}export{p as $fetch,r as FetchError};
35
2
  //# sourceMappingURL=fetch.js.map
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/runtime/fetch.ts"],
4
4
  "sourcesContent": ["export interface ApiRoutes {}\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'\n\nexport interface FetchOptions<M extends HttpMethod = 'GET'> {\n method?: M\n body?: unknown\n headers?: HeadersInit\n signal?: AbortSignal\n}\n\ntype ApiKey<M extends HttpMethod, P extends string> = `${M} ${P}`\n\ntype InferResult<M extends HttpMethod, P extends string> =\n ApiKey<M, P> extends keyof ApiRoutes\n ? ApiRoutes[ApiKey<M, P>]\n : unknown\n\nexport class FetchError extends Error {\n constructor(\n public readonly status: number,\n public readonly statusText: string,\n public readonly response: Response,\n ) {\n super(`HTTP ${status}: ${statusText}`)\n this.name = 'FetchError'\n }\n}\n\nexport async function $fetch<\n P extends string,\n M extends HttpMethod = 'GET',\n>(path: P, options?: FetchOptions<M>): Promise<InferResult<M, P>> {\n const method = (options?.method ?? 'GET') as string\n const headers = new Headers(options?.headers)\n\n let body: BodyInit | undefined\n if (options?.body !== undefined) {\n body = JSON.stringify(options.body)\n if (!headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n }\n\n const response = await fetch(path, {method, headers, body, signal: options?.signal})\n\n if (!response.ok) {\n throw new FetchError(response.status, response.statusText, response)\n }\n\n const contentType = response.headers.get('Content-Type') ?? ''\n if (contentType.includes('application/json')) {\n return response.json() as Promise<InferResult<M, P>>\n }\n\n return response.text() as unknown as Promise<InferResult<M, P>>\n}\n"],
5
- "mappings": ";AAkBO,IAAM,aAAN,cAAyB,MAAM;AAAA,EAClC,YACoB,QACA,YACA,UAClB;AACE,UAAM,QAAQ,MAAM,KAAK,UAAU,EAAE;AAJrB;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EAChB;AACJ;AAEA,eAAsB,OAGpB,MAAS,SAAuD;AAC9D,QAAM,SAAU,SAAS,UAAU;AACnC,QAAM,UAAU,IAAI,QAAQ,SAAS,OAAO;AAE5C,MAAI;AACJ,MAAI,SAAS,SAAS,QAAW;AAC7B,WAAO,KAAK,UAAU,QAAQ,IAAI;AAClC,QAAI,CAAC,QAAQ,IAAI,cAAc,GAAG;AAC9B,cAAQ,IAAI,gBAAgB,kBAAkB;AAAA,IAClD;AAAA,EACJ;AAEA,QAAM,WAAW,MAAM,MAAM,MAAM,EAAC,QAAQ,SAAS,MAAM,QAAQ,SAAS,OAAM,CAAC;AAEnF,MAAI,CAAC,SAAS,IAAI;AACd,UAAM,IAAI,WAAW,SAAS,QAAQ,SAAS,YAAY,QAAQ;AAAA,EACvE;AAEA,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,MAAI,YAAY,SAAS,kBAAkB,GAAG;AAC1C,WAAO,SAAS,KAAK;AAAA,EACzB;AAEA,SAAO,SAAS,KAAK;AACzB;",
6
- "names": []
5
+ "mappings": "AAkBO,IAAMA,EAAN,cAAyB,KAAM,CAClC,YACoBC,EACAC,EACAC,EAClB,CACE,MAAM,QAAQF,CAAM,KAAKC,CAAU,EAAE,EAJrB,YAAAD,EACA,gBAAAC,EACA,cAAAC,EAGhB,KAAK,KAAO,YAChB,CACJ,EAEA,eAAsBC,EAGpBC,EAASC,EAAuD,CAC9D,IAAMC,EAAUD,GAAS,QAAU,MAC7BE,EAAU,IAAI,QAAQF,GAAS,OAAO,EAExCG,EACAH,GAAS,OAAS,SAClBG,EAAO,KAAK,UAAUH,EAAQ,IAAI,EAC7BE,EAAQ,IAAI,cAAc,GAC3BA,EAAQ,IAAI,eAAgB,kBAAkB,GAItD,IAAML,EAAW,MAAM,MAAME,EAAM,CAAC,OAAAE,EAAQ,QAAAC,EAAS,KAAAC,EAAM,OAAQH,GAAS,MAAM,CAAC,EAEnF,GAAI,CAACH,EAAS,GACV,MAAM,IAAIH,EAAWG,EAAS,OAAQA,EAAS,WAAYA,CAAQ,EAIvE,OADoBA,EAAS,QAAQ,IAAI,cAAc,GAAK,IAC5C,SAAS,kBAAkB,EAChCA,EAAS,KAAK,EAGlBA,EAAS,KAAK,CACzB",
6
+ "names": ["FetchError", "status", "statusText", "response", "$fetch", "path", "options", "method", "headers", "body"]
7
7
  }
@@ -1,69 +1,2 @@
1
- // src/runtime/head.tsx
2
- import { Fragment, jsx } from "react/jsx-runtime";
3
- function collectTags(metadata, viewport) {
4
- const tags = [];
5
- if (metadata.title)
6
- tags.push({ tag: "title", children: metadata.title });
7
- if (metadata.description)
8
- tags.push({ tag: "meta", name: "description", content: metadata.description });
9
- if (metadata.keywords?.length)
10
- tags.push({ tag: "meta", name: "keywords", content: metadata.keywords.join(", ") });
11
- const ogTitle = metadata.og?.title ?? metadata.title;
12
- if (ogTitle) tags.push({ tag: "meta", property: "og:title", content: ogTitle });
13
- const ogDesc = metadata.og?.description ?? metadata.description;
14
- if (ogDesc) tags.push({ tag: "meta", property: "og:description", content: ogDesc });
15
- if (metadata.og?.image) tags.push({ tag: "meta", property: "og:image", content: metadata.og.image });
16
- if (metadata.og?.type) tags.push({ tag: "meta", property: "og:type", content: metadata.og.type });
17
- if (metadata.og?.url) tags.push({ tag: "meta", property: "og:url", content: metadata.og.url });
18
- const twTitle = metadata.twitter?.title ?? metadata.title;
19
- if (twTitle) tags.push({ tag: "meta", name: "twitter:title", content: twTitle });
20
- const twDesc = metadata.twitter?.description ?? metadata.description;
21
- if (twDesc) tags.push({ tag: "meta", name: "twitter:description", content: twDesc });
22
- if (metadata.twitter?.card) tags.push({
23
- tag: "meta",
24
- name: "twitter:card",
25
- content: metadata.twitter.card
26
- });
27
- if (metadata.twitter?.image) tags.push({
28
- tag: "meta",
29
- name: "twitter:image",
30
- content: metadata.twitter.image
31
- });
32
- if (metadata.twitter?.creator) tags.push({
33
- tag: "meta",
34
- name: "twitter:creator",
35
- content: metadata.twitter.creator
36
- });
37
- if (metadata.canonical) tags.push({ tag: "link", rel: "canonical", href: metadata.canonical });
38
- if (metadata.robots) tags.push({ tag: "meta", name: "robots", content: metadata.robots });
39
- if (metadata.alternates) {
40
- for (const [lang, href] of Object.entries(metadata.alternates))
41
- tags.push({ tag: "link", rel: "alternate", href, hrefLang: lang });
42
- }
43
- if (viewport) {
44
- const parts = [];
45
- if (viewport.width !== void 0) parts.push(`width=${viewport.width}`);
46
- if (viewport.initialScale !== void 0) parts.push(`initial-scale=${viewport.initialScale}`);
47
- if (viewport.maximumScale !== void 0) parts.push(`maximum-scale=${viewport.maximumScale}`);
48
- if (viewport.userScalable !== void 0) parts.push(`user-scalable=${viewport.userScalable ? "yes" : "no"}`);
49
- if (parts.length) tags.push({ tag: "meta", name: "viewport", content: parts.join(", ") });
50
- if (viewport.themeColor) tags.push({
51
- tag: "meta",
52
- name: "theme-color",
53
- content: viewport.themeColor
54
- });
55
- }
56
- return tags;
57
- }
58
- function buildHeadNodes(metadata, viewport) {
59
- const tags = collectTags(metadata, viewport);
60
- return /* @__PURE__ */ jsx(Fragment, { children: tags.map((t, i) => {
61
- if (t.tag === "title") return /* @__PURE__ */ jsx("title", { children: t.children }, i);
62
- if (t.tag === "link") return /* @__PURE__ */ jsx("link", { rel: t.rel, href: t.href, hrefLang: t.hrefLang }, i);
63
- return /* @__PURE__ */ jsx("meta", { name: t.name, property: t.property, content: t.content }, i);
64
- }) });
65
- }
66
- export {
67
- buildHeadNodes
68
- };
1
+ import{Fragment as f,jsx as s}from"react/jsx-runtime";function p(t,n){let e=[];t.title&&e.push({tag:"title",children:t.title}),t.description&&e.push({tag:"meta",name:"description",content:t.description}),t.keywords?.length&&e.push({tag:"meta",name:"keywords",content:t.keywords.join(", ")});let i=t.og?.title??t.title;i&&e.push({tag:"meta",property:"og:title",content:i});let o=t.og?.description??t.description;o&&e.push({tag:"meta",property:"og:description",content:o}),t.og?.image&&e.push({tag:"meta",property:"og:image",content:t.og.image}),t.og?.type&&e.push({tag:"meta",property:"og:type",content:t.og.type}),t.og?.url&&e.push({tag:"meta",property:"og:url",content:t.og.url});let c=t.twitter?.title??t.title;c&&e.push({tag:"meta",name:"twitter:title",content:c});let g=t.twitter?.description??t.description;if(g&&e.push({tag:"meta",name:"twitter:description",content:g}),t.twitter?.card&&e.push({tag:"meta",name:"twitter:card",content:t.twitter.card}),t.twitter?.image&&e.push({tag:"meta",name:"twitter:image",content:t.twitter.image}),t.twitter?.creator&&e.push({tag:"meta",name:"twitter:creator",content:t.twitter.creator}),t.canonical&&e.push({tag:"link",rel:"canonical",href:t.canonical}),t.robots&&e.push({tag:"meta",name:"robots",content:t.robots}),t.alternates)for(let[r,l]of Object.entries(t.alternates))e.push({tag:"link",rel:"alternate",href:l,hrefLang:r});if(n){let r=[];n.width!==void 0&&r.push(`width=${n.width}`),n.initialScale!==void 0&&r.push(`initial-scale=${n.initialScale}`),n.maximumScale!==void 0&&r.push(`maximum-scale=${n.maximumScale}`),n.userScalable!==void 0&&r.push(`user-scalable=${n.userScalable?"yes":"no"}`),r.length&&e.push({tag:"meta",name:"viewport",content:r.join(", ")}),n.themeColor&&e.push({tag:"meta",name:"theme-color",content:n.themeColor})}return e}function h(t,n){let e=p(t,n);return s(f,{children:e.map((i,o)=>i.tag==="title"?s("title",{children:i.children},o):i.tag==="link"?s("link",{rel:i.rel,href:i.href,hrefLang:i.hrefLang},o):s("meta",{name:i.name,property:i.property,content:i.content},o))})}export{h as buildHeadNodes};
69
2
  //# sourceMappingURL=head.js.map
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/runtime/head.tsx"],
4
4
  "sourcesContent": ["import {Metadata, Viewport} from \"../types\";\nimport {ReactNode} from \"react\";\n\ntype MetaTag =\n | { tag: 'title'; children: string }\n | { tag: 'meta'; name?: string; property?: string; content: string }\n | { tag: 'link'; rel: string; href: string; hrefLang?: string }\n\nfunction collectTags(metadata: Metadata, viewport?: Viewport): MetaTag[] {\n const tags: MetaTag[] = []\n\n if (metadata.title)\n tags.push({tag: 'title', children: metadata.title})\n if (metadata.description)\n tags.push({tag: 'meta', name: 'description', content: metadata.description})\n if (metadata.keywords?.length)\n tags.push({tag: 'meta', name: 'keywords', content: metadata.keywords.join(', ')})\n\n const ogTitle = metadata.og?.title ?? metadata.title\n if (ogTitle) tags.push({tag: 'meta', property: 'og:title', content: ogTitle})\n const ogDesc = metadata.og?.description ?? metadata.description\n if (ogDesc) tags.push({tag: 'meta', property: 'og:description', content: ogDesc})\n if (metadata.og?.image) tags.push({tag: 'meta', property: 'og:image', content: metadata.og.image})\n if (metadata.og?.type) tags.push({tag: 'meta', property: 'og:type', content: metadata.og.type})\n if (metadata.og?.url) tags.push({tag: 'meta', property: 'og:url', content: metadata.og.url})\n\n const twTitle = metadata.twitter?.title ?? metadata.title\n if (twTitle) tags.push({tag: 'meta', name: 'twitter:title', content: twTitle})\n const twDesc = metadata.twitter?.description ?? metadata.description\n if (twDesc) tags.push({tag: 'meta', name: 'twitter:description', content: twDesc})\n if (metadata.twitter?.card) tags.push({\n tag: 'meta', name: 'twitter:card', content:\n metadata.twitter.card\n })\n if (metadata.twitter?.image) tags.push({\n tag: 'meta', name: 'twitter:image', content:\n metadata.twitter.image\n })\n if (metadata.twitter?.creator) tags.push({\n tag: 'meta', name: 'twitter:creator', content:\n metadata.twitter.creator\n })\n\n if (metadata.canonical) tags.push({tag: 'link', rel: 'canonical', href: metadata.canonical})\n if (metadata.robots) tags.push({tag: 'meta', name: 'robots', content: metadata.robots})\n if (metadata.alternates) {\n for (const [lang, href] of Object.entries(metadata.alternates))\n tags.push({tag: 'link', rel: 'alternate', href, hrefLang: lang})\n }\n\n if (viewport) {\n const parts: string[] = []\n if (viewport.width !== undefined) parts.push(`width=${viewport.width}`)\n if (viewport.initialScale !== undefined) parts.push(`initial-scale=${viewport.initialScale}`)\n if (viewport.maximumScale !== undefined) parts.push(`maximum-scale=${viewport.maximumScale}`)\n if (viewport.userScalable !== undefined) parts.push(`user-scalable=${viewport.userScalable ? 'yes' :\n 'no'}`)\n if (parts.length) tags.push({tag: 'meta', name: 'viewport', content: parts.join(', ')})\n if (viewport.themeColor) tags.push({\n tag: 'meta', name: 'theme-color', content: viewport.themeColor\n })\n }\n\n return tags\n}\n\nexport function buildHeadNodes(metadata: Metadata, viewport?: Viewport): ReactNode {\n const tags = collectTags(metadata, viewport)\n\n return <>\n {tags.map((t, i) => {\n if (t.tag === 'title') return <title key={i}>{t.children}</title>\n if (t.tag === 'link') return <link key={i} rel={t.rel} href={t.href} hrefLang={t.hrefLang}/>\n return <meta key={i} name={t.name} property={t.property} content={t.content}/>\n })}\n </>\n}"],
5
- "mappings": "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",
6
- "names": []
5
+ "mappings": "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",
6
+ "names": ["Fragment", "jsx", "collectTags", "metadata", "viewport", "tags", "ogTitle", "ogDesc", "twTitle", "twDesc", "lang", "href", "parts", "buildHeadNodes", "t", "i"]
7
7
  }
@@ -6,5 +6,6 @@ export type { RouteHandler, RouteResult } from './api-context';
6
6
  export { getCookie, setCookie, deleteCookie } from '../utils/cookies';
7
7
  export type { CookieOptions } from '../utils/cookies';
8
8
  export { json, text, redirect } from '../utils/response';
9
+ export type { JsonResponse } from '../utils/response';
9
10
  export { $fetch, FetchError } from './fetch';
10
11
  export type { ApiRoutes, FetchOptions } from './fetch';
@@ -1,368 +1,2 @@
1
- // src/runtime/router-provider.tsx
2
- import { useCallback, useContext, useEffect, useRef, useState } from "react";
3
- import { RouterContext as RouterContext2 } from "virtual:devix/context";
4
- import { getDefaultErrorPage, loadErrorPage, matchClientRoute } from "virtual:devix/client-routes";
5
-
6
- // src/runtime/head.tsx
7
- import { Fragment, jsx } from "react/jsx-runtime";
8
- function collectTags(metadata, viewport) {
9
- const tags = [];
10
- if (metadata.title)
11
- tags.push({ tag: "title", children: metadata.title });
12
- if (metadata.description)
13
- tags.push({ tag: "meta", name: "description", content: metadata.description });
14
- if (metadata.keywords?.length)
15
- tags.push({ tag: "meta", name: "keywords", content: metadata.keywords.join(", ") });
16
- const ogTitle = metadata.og?.title ?? metadata.title;
17
- if (ogTitle) tags.push({ tag: "meta", property: "og:title", content: ogTitle });
18
- const ogDesc = metadata.og?.description ?? metadata.description;
19
- if (ogDesc) tags.push({ tag: "meta", property: "og:description", content: ogDesc });
20
- if (metadata.og?.image) tags.push({ tag: "meta", property: "og:image", content: metadata.og.image });
21
- if (metadata.og?.type) tags.push({ tag: "meta", property: "og:type", content: metadata.og.type });
22
- if (metadata.og?.url) tags.push({ tag: "meta", property: "og:url", content: metadata.og.url });
23
- const twTitle = metadata.twitter?.title ?? metadata.title;
24
- if (twTitle) tags.push({ tag: "meta", name: "twitter:title", content: twTitle });
25
- const twDesc = metadata.twitter?.description ?? metadata.description;
26
- if (twDesc) tags.push({ tag: "meta", name: "twitter:description", content: twDesc });
27
- if (metadata.twitter?.card) tags.push({
28
- tag: "meta",
29
- name: "twitter:card",
30
- content: metadata.twitter.card
31
- });
32
- if (metadata.twitter?.image) tags.push({
33
- tag: "meta",
34
- name: "twitter:image",
35
- content: metadata.twitter.image
36
- });
37
- if (metadata.twitter?.creator) tags.push({
38
- tag: "meta",
39
- name: "twitter:creator",
40
- content: metadata.twitter.creator
41
- });
42
- if (metadata.canonical) tags.push({ tag: "link", rel: "canonical", href: metadata.canonical });
43
- if (metadata.robots) tags.push({ tag: "meta", name: "robots", content: metadata.robots });
44
- if (metadata.alternates) {
45
- for (const [lang, href] of Object.entries(metadata.alternates))
46
- tags.push({ tag: "link", rel: "alternate", href, hrefLang: lang });
47
- }
48
- if (viewport) {
49
- const parts = [];
50
- if (viewport.width !== void 0) parts.push(`width=${viewport.width}`);
51
- if (viewport.initialScale !== void 0) parts.push(`initial-scale=${viewport.initialScale}`);
52
- if (viewport.maximumScale !== void 0) parts.push(`maximum-scale=${viewport.maximumScale}`);
53
- if (viewport.userScalable !== void 0) parts.push(`user-scalable=${viewport.userScalable ? "yes" : "no"}`);
54
- if (parts.length) tags.push({ tag: "meta", name: "viewport", content: parts.join(", ") });
55
- if (viewport.themeColor) tags.push({
56
- tag: "meta",
57
- name: "theme-color",
58
- content: viewport.themeColor
59
- });
60
- }
61
- return tags;
62
- }
63
- function buildHeadNodes(metadata, viewport) {
64
- const tags = collectTags(metadata, viewport);
65
- return /* @__PURE__ */ jsx(Fragment, { children: tags.map((t, i) => {
66
- if (t.tag === "title") return /* @__PURE__ */ jsx("title", { children: t.children }, i);
67
- if (t.tag === "link") return /* @__PURE__ */ jsx("link", { rel: t.rel, href: t.href, hrefLang: t.hrefLang }, i);
68
- return /* @__PURE__ */ jsx("meta", { name: t.name, property: t.property, content: t.content }, i);
69
- }) });
70
- }
71
-
72
- // src/runtime/context.tsx
73
- import { createContext } from "react";
74
- var g = globalThis;
75
- g.__devix_RouterContext__ ??= createContext(null);
76
- var RouterContext = g.__devix_RouterContext__;
77
- g.__devix_PageMetaContext__ ??= createContext(null);
78
- g.__devix_RouteDataContext__ ??= createContext(null);
79
- var PageMetaContext = g.__devix_PageMetaContext__;
80
- var RouteDataContext = g.__devix_RouteDataContext__;
81
-
82
- // src/runtime/error-boundary.tsx
83
- import { Component } from "react";
84
- import { jsx as jsx2 } from "react/jsx-runtime";
85
- var DevixErrorBoundary = class extends Component {
86
- state = { error: null };
87
- static getDerivedStateFromError(err) {
88
- if (err instanceof DevixError) {
89
- return {
90
- error: { statusCode: err.statusCode, message: err.message }
91
- };
92
- }
93
- return {
94
- error: { statusCode: 500, message: err instanceof Error ? err.message : "Unknown error" }
95
- };
96
- }
97
- render() {
98
- if (this.state.error && this.props.ErrorPage) {
99
- return /* @__PURE__ */ jsx2(this.props.ErrorPage, { ...this.state.error });
100
- }
101
- if (this.state.error) {
102
- return /* @__PURE__ */ jsx2("h1", { children: this.state.error.statusCode });
103
- }
104
- return this.props.children;
105
- }
106
- };
107
- var DevixError = class extends Error {
108
- statusCode;
109
- constructor(statusCode, message) {
110
- super(message);
111
- this.statusCode = statusCode;
112
- }
113
- };
114
-
115
- // src/runtime/router-provider.tsx
116
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
117
- function useRouter() {
118
- return useContext(RouterContext2);
119
- }
120
- function useNavigate() {
121
- const ctx = useContext(RouterContext2);
122
- if (!ctx) throw new Error("useNavigate must be used within a RouterProvider");
123
- return ctx.navigate;
124
- }
125
- function useParams() {
126
- const ctx = useContext(RouteDataContext);
127
- if (!ctx) throw new Error("useParams must be used within a route or layout");
128
- return ctx.params;
129
- }
130
- function useLoaderData() {
131
- const ctx = useContext(RouteDataContext);
132
- if (!ctx) throw new Error("useLoaderData must be used within a route or layout");
133
- return ctx.loaderData;
134
- }
135
- function RouterProvider({
136
- initialData,
137
- initialParams,
138
- initialPage,
139
- initialLayouts = [],
140
- initialLayoutsData = [],
141
- initialMeta,
142
- initialViewport,
143
- initialError,
144
- initialErrorPage,
145
- clientEntry
146
- }) {
147
- const [state, setState] = useState({
148
- pathname: window.location.pathname,
149
- params: initialParams,
150
- loaderData: initialData,
151
- layoutsData: initialLayoutsData,
152
- Page: initialPage,
153
- layouts: initialLayouts,
154
- metadata: initialMeta ?? null,
155
- viewport: initialViewport,
156
- pendingError: initialError,
157
- ErrorPage: initialErrorPage
158
- });
159
- const navigatingRef = useRef(null);
160
- const [isNavigating, setIsNavigating] = useState(false);
161
- const loadRoute = useCallback(async (to, controller) => {
162
- const pathname = to.split("?")[0];
163
- const matched = matchClientRoute(pathname);
164
- if (!matched) {
165
- const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage();
166
- setState((prev) => ({
167
- ...prev,
168
- pathname,
169
- pendingError: { statusCode: 404, message: "Not found" },
170
- ErrorPage: ErrorPage ?? void 0
171
- }));
172
- return;
173
- }
174
- const [pageMod, ...layoutMods] = await Promise.all([
175
- matched.load(),
176
- ...matched.loadLayouts.map((l) => l())
177
- ]);
178
- if (controller.signal.aborted) return;
179
- if (!pageMod.default) return;
180
- const dataRes = await fetch(`/_data${to}`, {
181
- headers: { Accept: "application/json" },
182
- signal: controller.signal
183
- });
184
- if (controller.signal.aborted) return;
185
- if (!dataRes.ok) {
186
- if (dataRes.status === 404) {
187
- window.location.href = to;
188
- return;
189
- }
190
- console.error(`/_data${to} returned ${dataRes.status}`);
191
- return;
192
- }
193
- const data = await dataRes.json();
194
- window.scrollTo(0, 0);
195
- setState({
196
- pathname,
197
- params: data.params ?? {},
198
- loaderData: data.loaderData,
199
- layoutsData: (data.layouts ?? []).map((l) => l.loaderData),
200
- Page: pageMod.default,
201
- layouts: layoutMods.map((m) => m.default),
202
- metadata: data.metadata ?? null,
203
- viewport: data.viewport
204
- });
205
- }, []);
206
- const navigate = useCallback(async (to) => {
207
- navigatingRef.current?.abort();
208
- const controller = new AbortController();
209
- navigatingRef.current = controller;
210
- setIsNavigating(true);
211
- try {
212
- window.history.pushState(null, "", to);
213
- await loadRoute(to, controller);
214
- } finally {
215
- if (!controller.signal.aborted) setIsNavigating(false);
216
- }
217
- }, [loadRoute]);
218
- useEffect(() => {
219
- const handlePop = () => {
220
- navigatingRef.current?.abort();
221
- const controller = new AbortController();
222
- navigatingRef.current = controller;
223
- const to = window.location.pathname + window.location.search;
224
- loadRoute(to, controller).catch((err) => {
225
- if (err.name !== "AbortError") console.error("[router] popstate error:", err);
226
- });
227
- };
228
- window.addEventListener("popstate", handlePop);
229
- return () => window.removeEventListener("popstate", handlePop);
230
- }, [loadRoute]);
231
- let content;
232
- if (state.pendingError) {
233
- content = state.ErrorPage ? /* @__PURE__ */ jsx3(state.ErrorPage, { ...state.pendingError }) : /* @__PURE__ */ jsx3("h1", { children: state.pendingError.statusCode });
234
- } else {
235
- let tree = /* @__PURE__ */ jsx3(RouteDataContext, { value: { loaderData: state.loaderData, params: state.params }, children: /* @__PURE__ */ jsx3(state.Page, { data: state.loaderData, params: state.params, url: state.pathname }) });
236
- for (let i = state.layouts.length - 1; i >= 0; i--) {
237
- const Layout = state.layouts[i];
238
- const layoutData = state.layoutsData[i];
239
- tree = /* @__PURE__ */ jsx3(RouteDataContext, { value: { loaderData: layoutData, params: state.params }, children: /* @__PURE__ */ jsx3(Layout, { data: layoutData, params: state.params, children: tree }) });
240
- }
241
- content = /* @__PURE__ */ jsx3(DevixErrorBoundary, { ErrorPage: state.ErrorPage, children: tree }, state.pathname);
242
- }
243
- return /* @__PURE__ */ jsxs(PageMetaContext, { value: {
244
- metadata: state.metadata,
245
- viewport: state.viewport,
246
- clientEntry
247
- }, children: [
248
- state.metadata && buildHeadNodes(state.metadata, state.viewport),
249
- /* @__PURE__ */ jsx3(RouterContext2, { value: { ...state, isNavigating, navigate }, children: content })
250
- ] });
251
- }
252
-
253
- // src/runtime/link.tsx
254
- import { useCallback as useCallback2, useContext as useContext2 } from "react";
255
- import { matchClientRoute as matchClientRoute2 } from "virtual:devix/client-routes";
256
- import { RouterContext as RouterContext3 } from "virtual:devix/context";
257
- import { jsx as jsx4 } from "react/jsx-runtime";
258
- function resolveHref(href) {
259
- if (href.startsWith("/") || href.startsWith("http")) return href;
260
- const base = window.location.pathname.endsWith("/") ? window.location.href : window.location.href + "/";
261
- const resolved = new URL(href, base).pathname;
262
- return resolved.length > 1 ? resolved.replace(/\/$/, "") : resolved;
263
- }
264
- function Link({ href, prefetch = false, viewTransition = false, children, ...props }) {
265
- const router = useContext2(RouterContext3);
266
- const handleMouseEnter = useCallback2(() => {
267
- if (!prefetch) return;
268
- const resolved = resolveHref(href);
269
- const pathname = resolved.split("?")[0];
270
- const matched = matchClientRoute2(pathname);
271
- if (matched) {
272
- matched.load().catch(() => {
273
- });
274
- fetch(`/_data${resolved}`, { headers: { Accept: "application/json" } }).catch(() => {
275
- });
276
- }
277
- }, [href, prefetch]);
278
- const handleClick = (e) => {
279
- if (!router) return;
280
- if (!e.ctrlKey && !e.metaKey && !e.shiftKey && e.button === 0) {
281
- e.preventDefault();
282
- const resolved = resolveHref(href);
283
- if (viewTransition && typeof document.startViewTransition === "function") {
284
- document.startViewTransition(() => router.navigate(resolved));
285
- } else {
286
- router.navigate(resolved);
287
- }
288
- }
289
- };
290
- return /* @__PURE__ */ jsx4("a", { href, onClick: handleClick, onMouseEnter: handleMouseEnter, ...props, children });
291
- }
292
-
293
- // src/utils/cookies.ts
294
- function getCookie(req, name) {
295
- const header = req.headers.get("cookie");
296
- if (!header) return void 0;
297
- for (const part of header.split(";")) {
298
- const [key, ...rest] = part.trim().split("=");
299
- if (key.trim() === name) return decodeURIComponent(rest.join("="));
300
- }
301
- return void 0;
302
- }
303
- function setCookie(headers, name, value, options = {}) {
304
- let cookie = `${name}=${encodeURIComponent(value)}; Path=${options.path ?? "/"}`;
305
- if (options.domain) cookie += `; Domain=${options.domain}`;
306
- if (options.maxAge !== void 0) cookie += `; Max-Age=${options.maxAge}`;
307
- if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
308
- if (options.httpOnly) cookie += `; HttpOnly`;
309
- if (options.secure) cookie += `; Secure`;
310
- if (options.sameSite) cookie += `; SameSite=${options.sameSite}`;
311
- headers.append("Set-Cookie", cookie);
312
- }
313
- function deleteCookie(headers, name, options = {}) {
314
- setCookie(headers, name, "", { ...options, maxAge: 0, expires: /* @__PURE__ */ new Date(0) });
315
- }
316
-
317
- // src/utils/response.ts
318
- var json = (data, status = 200) => Response.json(data, { status });
319
- var text = (body, status = 200) => new Response(body, { status, headers: { "Content-Type": "text/plain; charset=utf-8" } });
320
- var redirect = (url, status = 302) => new Response(null, { status, headers: { Location: url } });
321
-
322
- // src/runtime/fetch.ts
323
- var FetchError = class extends Error {
324
- constructor(status, statusText, response) {
325
- super(`HTTP ${status}: ${statusText}`);
326
- this.status = status;
327
- this.statusText = statusText;
328
- this.response = response;
329
- this.name = "FetchError";
330
- }
331
- };
332
- async function $fetch(path, options) {
333
- const method = options?.method ?? "GET";
334
- const headers = new Headers(options?.headers);
335
- let body;
336
- if (options?.body !== void 0) {
337
- body = JSON.stringify(options.body);
338
- if (!headers.has("Content-Type")) {
339
- headers.set("Content-Type", "application/json");
340
- }
341
- }
342
- const response = await fetch(path, { method, headers, body, signal: options?.signal });
343
- if (!response.ok) {
344
- throw new FetchError(response.status, response.statusText, response);
345
- }
346
- const contentType = response.headers.get("Content-Type") ?? "";
347
- if (contentType.includes("application/json")) {
348
- return response.json();
349
- }
350
- return response.text();
351
- }
352
- export {
353
- $fetch,
354
- FetchError,
355
- Link,
356
- RouterProvider,
357
- deleteCookie,
358
- getCookie,
359
- json,
360
- redirect,
361
- setCookie,
362
- text,
363
- useLoaderData,
364
- useNavigate,
365
- useParams,
366
- useRouter
367
- };
1
+ import{useCallback as N,useContext as k,useEffect as q,useRef as z,useState as O}from"react";import{RouterContext as L}from"virtual:devix/context";import{getDefaultErrorPage as Q,loadErrorPage as X,matchClientRoute as Y}from"virtual:devix/client-routes";import{Fragment as W,jsx as T}from"react/jsx-runtime";function J(e,t){let o=[];e.title&&o.push({tag:"title",children:e.title}),e.description&&o.push({tag:"meta",name:"description",content:e.description}),e.keywords?.length&&o.push({tag:"meta",name:"keywords",content:e.keywords.join(", ")});let r=e.og?.title??e.title;r&&o.push({tag:"meta",property:"og:title",content:r});let a=e.og?.description??e.description;a&&o.push({tag:"meta",property:"og:description",content:a}),e.og?.image&&o.push({tag:"meta",property:"og:image",content:e.og.image}),e.og?.type&&o.push({tag:"meta",property:"og:type",content:e.og.type}),e.og?.url&&o.push({tag:"meta",property:"og:url",content:e.og.url});let s=e.twitter?.title??e.title;s&&o.push({tag:"meta",name:"twitter:title",content:s});let g=e.twitter?.description??e.description;if(g&&o.push({tag:"meta",name:"twitter:description",content:g}),e.twitter?.card&&o.push({tag:"meta",name:"twitter:card",content:e.twitter.card}),e.twitter?.image&&o.push({tag:"meta",name:"twitter:image",content:e.twitter.image}),e.twitter?.creator&&o.push({tag:"meta",name:"twitter:creator",content:e.twitter.creator}),e.canonical&&o.push({tag:"link",rel:"canonical",href:e.canonical}),e.robots&&o.push({tag:"meta",name:"robots",content:e.robots}),e.alternates)for(let[l,u]of Object.entries(e.alternates))o.push({tag:"link",rel:"alternate",href:u,hrefLang:l});if(t){let l=[];t.width!==void 0&&l.push(`width=${t.width}`),t.initialScale!==void 0&&l.push(`initial-scale=${t.initialScale}`),t.maximumScale!==void 0&&l.push(`maximum-scale=${t.maximumScale}`),t.userScalable!==void 0&&l.push(`user-scalable=${t.userScalable?"yes":"no"}`),l.length&&o.push({tag:"meta",name:"viewport",content:l.join(", ")}),t.themeColor&&o.push({tag:"meta",name:"theme-color",content:t.themeColor})}return o}function H(e,t){let o=J(e,t);return T(W,{children:o.map((r,a)=>r.tag==="title"?T("title",{children:r.children},a):r.tag==="link"?T("link",{rel:r.rel,href:r.href,hrefLang:r.hrefLang},a):T("meta",{name:r.name,property:r.property,content:r.content},a))})}import{createContext as v}from"react";var y=globalThis;y.__devix_RouterContext__??=v(null);var Re=y.__devix_RouterContext__;y.__devix_PageMetaContext__??=v(null);y.__devix_RouteDataContext__??=v(null);var V=y.__devix_PageMetaContext__,w=y.__devix_RouteDataContext__;import{Component as B}from"react";import{jsx as $}from"react/jsx-runtime";var E=class extends B{state={error:null};static getDerivedStateFromError(t){return t instanceof D?{error:{statusCode:t.statusCode,message:t.message}}:{error:{statusCode:500,message:t instanceof Error?t.message:"Unknown error"}}}render(){return this.state.error&&this.props.ErrorPage?$(this.props.ErrorPage,{...this.state.error}):this.state.error?$("h1",{children:this.state.error.statusCode}):this.props.children}},D=class extends Error{statusCode;constructor(t,o){super(o),this.statusCode=t}};import{jsx as d,jsxs as ne}from"react/jsx-runtime";function Z(){return k(L)}function ee(){let e=k(L);if(!e)throw new Error("useNavigate must be used within a RouterProvider");return e.navigate}function te(){let e=k(w);if(!e)throw new Error("useParams must be used within a route or layout");return e.params}function oe(){let e=k(w);if(!e)throw new Error("useLoaderData must be used within a route or layout");return e.loaderData}function re({initialData:e,initialParams:t,initialPage:o,initialLayouts:r=[],initialLayoutsData:a=[],initialMeta:s,initialViewport:g,initialError:l,initialErrorPage:u,clientEntry:h}){let[n,_]=O({pathname:window.location.pathname,params:t,loaderData:e,layoutsData:a,Page:o,layouts:r,metadata:s??null,viewport:g,pendingError:l,ErrorPage:u}),P=z(null),[F,S]=O(!1),C=N(async(p,i)=>{let f=p.split("?")[0],c=Y(f);if(!c){let m=await X()??Q();_(G=>({...G,pathname:f,pendingError:{statusCode:404,message:"Not found"},ErrorPage:m??void 0}));return}let[A,...U]=await Promise.all([c.load(),...c.loadLayouts.map(m=>m())]);if(i.signal.aborted||!A.default)return;let R=await fetch(`/_data${p}`,{headers:{Accept:"application/json"},signal:i.signal});if(i.signal.aborted)return;if(!R.ok){if(R.status===404){window.location.href=p;return}console.error(`/_data${p} returned ${R.status}`);return}let x=await R.json();window.scrollTo(0,0),_({pathname:f,params:x.params??{},loaderData:x.loaderData,layoutsData:(x.layouts??[]).map(m=>m.loaderData),Page:A.default,layouts:U.map(m=>m.default),metadata:x.metadata??null,viewport:x.viewport})},[]),K=N(async p=>{P.current?.abort();let i=new AbortController;P.current=i,S(!0);try{window.history.pushState(null,"",p),await C(p,i)}finally{i.signal.aborted||S(!1)}},[C]);q(()=>{let p=()=>{P.current?.abort();let i=new AbortController;P.current=i;let f=window.location.pathname+window.location.search;C(f,i).catch(c=>{c.name!=="AbortError"&&console.error("[router] popstate error:",c)})};return window.addEventListener("popstate",p),()=>window.removeEventListener("popstate",p)},[C]);let b;if(n.pendingError)b=n.ErrorPage?d(n.ErrorPage,{...n.pendingError}):d("h1",{children:n.pendingError.statusCode});else{let p=d(w,{value:{loaderData:n.loaderData,params:n.params},children:d(n.Page,{data:n.loaderData,params:n.params,url:n.pathname})});for(let i=n.layouts.length-1;i>=0;i--){let f=n.layouts[i],c=n.layoutsData[i];p=d(w,{value:{loaderData:c,params:n.params},children:d(f,{data:c,params:n.params,children:p})})}b=d(E,{ErrorPage:n.ErrorPage,children:p},n.pathname)}return ne(V,{value:{metadata:n.metadata,viewport:n.viewport,clientEntry:h},children:[n.metadata&&H(n.metadata,n.viewport),d(L,{value:{...n,isNavigating:F,navigate:K},children:b})]})}import{useCallback as ae,useContext as se}from"react";import{matchClientRoute as ie}from"virtual:devix/client-routes";import{RouterContext as pe}from"virtual:devix/context";import{jsx as le}from"react/jsx-runtime";function I(e){if(e.startsWith("/")||e.startsWith("http"))return e;let t=window.location.pathname.endsWith("/")?window.location.href:window.location.href+"/",o=new URL(e,t).pathname;return o.length>1?o.replace(/\/$/,""):o}function ue({href:e,prefetch:t=!1,viewTransition:o=!1,children:r,...a}){let s=se(pe),g=ae(()=>{if(!t)return;let u=I(e),h=u.split("?")[0],n=ie(h);n&&(n.load().catch(()=>{}),fetch(`/_data${u}`,{headers:{Accept:"application/json"}}).catch(()=>{}))},[e,t]);return le("a",{href:e,onClick:u=>{if(s&&!u.ctrlKey&&!u.metaKey&&!u.shiftKey&&u.button===0){u.preventDefault();let h=I(e);o&&typeof document.startViewTransition=="function"?document.startViewTransition(()=>s.navigate(h)):s.navigate(h)}},onMouseEnter:g,...a,children:r})}function ce(e,t){let o=e.headers.get("cookie");if(o)for(let r of o.split(";")){let[a,...s]=r.trim().split("=");if(a.trim()===t)return decodeURIComponent(s.join("="))}}function j(e,t,o,r={}){let a=`${t}=${encodeURIComponent(o)}; Path=${r.path??"/"}`;r.domain&&(a+=`; Domain=${r.domain}`),r.maxAge!==void 0&&(a+=`; Max-Age=${r.maxAge}`),r.expires&&(a+=`; Expires=${r.expires.toUTCString()}`),r.httpOnly&&(a+="; HttpOnly"),r.secure&&(a+="; Secure"),r.sameSite&&(a+=`; SameSite=${r.sameSite}`),e.append("Set-Cookie",a)}function de(e,t,o={}){j(e,t,"",{...o,maxAge:0,expires:new Date(0)})}var ge=(e,t=200)=>Response.json(e,{status:t}),fe=(e,t=200)=>new Response(e,{status:t,headers:{"Content-Type":"text/plain; charset=utf-8"}}),me=(e,t=302)=>new Response(null,{status:t,headers:{Location:e}});var M=class extends Error{constructor(o,r,a){super(`HTTP ${o}: ${r}`);this.status=o;this.statusText=r;this.response=a;this.name="FetchError"}};async function he(e,t){let o=t?.method??"GET",r=new Headers(t?.headers),a;t?.body!==void 0&&(a=JSON.stringify(t.body),r.has("Content-Type")||r.set("Content-Type","application/json"));let s=await fetch(e,{method:o,headers:r,body:a,signal:t?.signal});if(!s.ok)throw new M(s.status,s.statusText,s);return(s.headers.get("Content-Type")??"").includes("application/json")?s.json():s.text()}export{he as $fetch,M as FetchError,ue as Link,re as RouterProvider,de as deleteCookie,ce as getCookie,ge as json,me as redirect,j as setCookie,fe as text,oe as useLoaderData,ee as useNavigate,te as useParams,Z as useRouter};
368
2
  //# sourceMappingURL=index.js.map