@devlusoft/devix 0.4.0 → 0.4.1-beta.10

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 (93) hide show
  1. package/dist/cli/build.js +88 -9
  2. package/dist/cli/build.js.map +4 -4
  3. package/dist/cli/dev-server.d.ts +1 -0
  4. package/dist/cli/dev-server.js +234 -0
  5. package/dist/cli/dev-server.js.map +7 -0
  6. package/dist/cli/dev.js +1 -154
  7. package/dist/cli/dev.js.map +4 -4
  8. package/dist/cli/devix-dev-server.js +155 -0
  9. package/dist/cli/devix-dev-server.js.map +7 -0
  10. package/dist/cli/generate.js +88 -9
  11. package/dist/cli/generate.js.map +4 -4
  12. package/dist/cli/index.js +89 -12
  13. package/dist/cli/index.js.map +4 -4
  14. package/dist/cli/start.js +1 -1
  15. package/dist/cli/start.js.map +3 -3
  16. package/dist/runtime/head.js +1 -1
  17. package/dist/runtime/head.js.map +3 -3
  18. package/dist/runtime/index.d.ts +1 -1
  19. package/dist/runtime/index.js +1 -1
  20. package/dist/runtime/index.js.map +3 -3
  21. package/dist/runtime/link.js +1 -1
  22. package/dist/runtime/link.js.map +2 -2
  23. package/dist/runtime/router-provider.js +1 -1
  24. package/dist/runtime/router-provider.js.map +3 -3
  25. package/dist/runtime/server-app.js +1 -1
  26. package/dist/runtime/server-app.js.map +3 -3
  27. package/dist/server/collect-css.js +1 -1
  28. package/dist/server/collect-css.js.map +2 -2
  29. package/dist/server/render.js +1 -1
  30. package/dist/server/render.js.map +3 -3
  31. package/dist/src/cli/build.d.ts +1 -0
  32. package/dist/src/cli/dev-server.d.ts +1 -0
  33. package/dist/src/cli/dev.d.ts +1 -0
  34. package/dist/src/cli/devix-dev-server.d.ts +1 -0
  35. package/dist/src/cli/generate.d.ts +1 -0
  36. package/dist/src/cli/index.d.ts +2 -0
  37. package/dist/src/cli/start.d.ts +1 -0
  38. package/dist/src/config.d.ts +22 -0
  39. package/dist/src/runtime/api-context.d.ts +24 -0
  40. package/dist/src/runtime/client-router.d.ts +13 -0
  41. package/dist/src/runtime/context.d.ts +32 -0
  42. package/dist/src/runtime/create-handler.d.ts +10 -0
  43. package/dist/src/runtime/error-boundary.d.ts +19 -0
  44. package/dist/src/runtime/fetch.d.ts +39 -0
  45. package/dist/src/runtime/head.d.ts +7 -0
  46. package/dist/src/runtime/index.d.ts +14 -0
  47. package/dist/src/runtime/link.d.ts +8 -0
  48. package/dist/src/runtime/metadata.d.ts +10 -0
  49. package/dist/src/runtime/router-provider.d.ts +25 -0
  50. package/dist/src/runtime/server-app.d.ts +15 -0
  51. package/dist/src/server/api-router.d.ts +22 -0
  52. package/dist/src/server/api.d.ts +2 -0
  53. package/dist/src/server/collect-css.d.ts +2 -0
  54. package/dist/src/server/handler-store.d.ts +10 -0
  55. package/dist/src/server/index.d.ts +6 -0
  56. package/dist/src/server/pages-router.d.ts +21 -0
  57. package/dist/src/server/public-index.d.ts +1 -0
  58. package/dist/src/server/render.d.ts +62 -0
  59. package/dist/src/server/routes.d.ts +11 -0
  60. package/dist/src/server/types.d.ts +52 -0
  61. package/dist/src/types.d.ts +42 -0
  62. package/dist/src/utils/async.d.ts +1 -0
  63. package/dist/src/utils/banner.d.ts +1 -0
  64. package/dist/src/utils/cookies.d.ts +12 -0
  65. package/dist/src/utils/duration.d.ts +1 -0
  66. package/dist/src/utils/env.d.ts +1 -0
  67. package/dist/src/utils/html.d.ts +2 -0
  68. package/dist/src/utils/patterns.d.ts +1 -0
  69. package/dist/src/utils/response.d.ts +19 -0
  70. package/dist/src/vite/codegen/api.d.ts +6 -0
  71. package/dist/src/vite/codegen/client-routes.d.ts +6 -0
  72. package/dist/src/vite/codegen/context.d.ts +1 -0
  73. package/dist/src/vite/codegen/entry-client.d.ts +5 -0
  74. package/dist/src/vite/codegen/extract-methods.d.ts +4 -0
  75. package/dist/src/vite/codegen/render.d.ts +6 -0
  76. package/dist/src/vite/codegen/routes-dts.d.ts +10 -0
  77. package/dist/src/vite/codegen/scan-api.d.ts +2 -0
  78. package/dist/src/vite/codegen/write-routes-dts.d.ts +1 -0
  79. package/dist/src/vite/index.d.ts +3 -0
  80. package/dist/types.d.ts +7 -0
  81. package/dist/utils/banner.js +1 -1
  82. package/dist/utils/banner.js.map +1 -1
  83. package/dist/utils/load-config.d.ts +2 -0
  84. package/dist/utils/load-config.js +2 -0
  85. package/dist/utils/load-config.js.map +7 -0
  86. package/dist/vite/codegen/entry-client.js +11 -3
  87. package/dist/vite/codegen/entry-client.js.map +2 -2
  88. package/dist/vite/codegen/server-entry.d.ts +6 -0
  89. package/dist/vite/codegen/server-entry.js +73 -0
  90. package/dist/vite/codegen/server-entry.js.map +7 -0
  91. package/dist/vite/index.js +90 -11
  92. package/dist/vite/index.js.map +4 -4
  93. package/package.json +3 -2
@@ -0,0 +1,21 @@
1
+ export interface Page {
2
+ path: string;
3
+ key: string;
4
+ params: string[];
5
+ regex: RegExp;
6
+ }
7
+ export interface Layout {
8
+ dir: string;
9
+ key: string;
10
+ }
11
+ export interface PagesResult {
12
+ pages: Page[];
13
+ layouts: Layout[];
14
+ }
15
+ export declare function invalidatePagesCache(): void;
16
+ export declare function buildPages(pageKeys: string[], layoutKeys: string[], pagesDir: string): PagesResult;
17
+ export declare function collectLayoutChain(pageKey: string, layouts: Layout[]): Layout[];
18
+ export declare function matchPage(pathname: string, pages: Page[]): {
19
+ page: Page;
20
+ params: Record<string, string>;
21
+ } | null;
@@ -0,0 +1 @@
1
+ export { useRequest, useCtx, useParams } from './handler-store';
@@ -0,0 +1,62 @@
1
+ import type { PageGlob } from './types';
2
+ import type { Manifest } from "vite";
3
+ export declare function runLoader(url: string, request: Request, glob: PageGlob, options?: {
4
+ loaderTimeout?: number;
5
+ }): Promise<{
6
+ error: true;
7
+ loaderData: null;
8
+ params: {};
9
+ layouts: never[];
10
+ metadata: null;
11
+ viewport: undefined;
12
+ redirect?: undefined;
13
+ redirectStatus?: undefined;
14
+ redirectReplace?: undefined;
15
+ } | {
16
+ loaderData: null;
17
+ params: {};
18
+ layouts: never[];
19
+ metadata: null;
20
+ viewport: undefined;
21
+ error?: undefined;
22
+ redirect?: undefined;
23
+ redirectStatus?: undefined;
24
+ redirectReplace?: undefined;
25
+ } | {
26
+ redirect: string | undefined;
27
+ redirectStatus: number | undefined;
28
+ redirectReplace: boolean | undefined;
29
+ error?: undefined;
30
+ loaderData?: undefined;
31
+ params?: undefined;
32
+ layouts?: undefined;
33
+ metadata?: undefined;
34
+ viewport?: undefined;
35
+ } | {
36
+ loaderData: unknown;
37
+ params: Record<string, string>;
38
+ layouts: {
39
+ loaderData: unknown;
40
+ }[];
41
+ metadata: import("../types").Metadata;
42
+ viewport: import("../types").Viewport | undefined;
43
+ error?: undefined;
44
+ redirect?: undefined;
45
+ redirectStatus?: undefined;
46
+ redirectReplace?: undefined;
47
+ }>;
48
+ export declare function render(url: string, request: Request, glob: PageGlob, options?: {
49
+ manifest?: Manifest;
50
+ loaderTimeout?: number;
51
+ }): Promise<{
52
+ html: string;
53
+ statusCode: number | undefined;
54
+ headers: {
55
+ Location: string | undefined;
56
+ };
57
+ } | {
58
+ html: string;
59
+ statusCode: number;
60
+ headers: Record<string, string>;
61
+ }>;
62
+ export declare function getStaticRoutes(glob: PageGlob): Promise<string[]>;
@@ -0,0 +1,11 @@
1
+ import type { Hono } from 'hono';
2
+ import type { Manifest } from 'vite';
3
+ interface ServerOptions {
4
+ renderModule: any;
5
+ apiModule: any;
6
+ manifest?: Manifest;
7
+ loaderTimeout?: number;
8
+ }
9
+ export declare function registerApiRoutes(app: Hono, { apiModule, renderModule, loaderTimeout }: ServerOptions): void;
10
+ export declare function registerSsrRoute(app: Hono, { renderModule, manifest, loaderTimeout }: ServerOptions): void;
11
+ export {};
@@ -0,0 +1,52 @@
1
+ import type React from "react";
2
+ import { LoaderContext, Metadata, Viewport } from "../types";
3
+ import type { Redirect } from "../utils/response";
4
+ type InferLoaderData<T> = T extends (...args: any[]) => infer R ? [Awaited<R>] extends [void | undefined | Redirect] ? undefined : Exclude<Awaited<R>, Redirect> : T;
5
+ type IsParams<T> = [T] extends [Record<string, string>] ? true : false;
6
+ export interface PageProps<TDataOrParams = unknown, TParams = Record<string, string>> {
7
+ data: IsParams<TDataOrParams> extends true ? unknown : InferLoaderData<TDataOrParams>;
8
+ params: IsParams<TDataOrParams> extends true ? TDataOrParams extends Record<string, string> ? TDataOrParams : Record<string, string> : TParams;
9
+ url: string;
10
+ }
11
+ export interface LayoutProps<TDataOrParams = unknown, TParams = Record<string, string>> {
12
+ children: React.ReactNode;
13
+ data: IsParams<TDataOrParams> extends true ? unknown : InferLoaderData<TDataOrParams>;
14
+ params: IsParams<TDataOrParams> extends true ? TDataOrParams extends Record<string, string> ? TDataOrParams : Record<string, string> : TParams;
15
+ }
16
+ export interface ErrorProps {
17
+ statusCode: number;
18
+ message?: string;
19
+ }
20
+ export interface PageGlob {
21
+ pages: Record<string, () => Promise<unknown>>;
22
+ layouts: Record<string, () => Promise<unknown>>;
23
+ pagesDir: string;
24
+ }
25
+ export interface ApiGlob {
26
+ routes: Record<string, () => Promise<unknown>>;
27
+ middlewares: Record<string, () => Promise<unknown>>;
28
+ apiDir: string;
29
+ }
30
+ interface BaseModule<TData, TParams> {
31
+ loader?: (ctx: LoaderContext<TParams>) => Promise<TData | Redirect | void> | TData | Redirect | void;
32
+ guard?: (ctx: LoaderContext<TParams>) => Promise<string | Redirect | Record<string, unknown> | null> | string | Redirect | Record<string, unknown> | null;
33
+ metadata?: Metadata;
34
+ generateMetadata?: (ctx: LoaderContext<TParams> & {
35
+ loaderData: TData;
36
+ }) => Promise<Metadata> | Metadata;
37
+ viewport?: Viewport;
38
+ generateViewport?: (ctx: LoaderContext<TParams>) => Promise<Viewport> | Viewport;
39
+ headers?: Record<string, string>;
40
+ }
41
+ export interface PageModule<TData = unknown, TParams = Record<string, string>> extends BaseModule<TData, TParams> {
42
+ default: React.ComponentType<PageProps<TData, TParams>>;
43
+ generateStaticParams?: () => Promise<Record<string, string>[]> | Record<string, string>[];
44
+ }
45
+ export interface LayoutModule<TData = unknown, TParams = Record<string, string>> extends BaseModule<TData, TParams> {
46
+ default: React.ComponentType<LayoutProps<TData, TParams>>;
47
+ lang?: string;
48
+ generateLang?: (ctx: LoaderContext<TParams> & {
49
+ loaderData: TData;
50
+ }) => Promise<string> | string;
51
+ }
52
+ export {};
@@ -0,0 +1,42 @@
1
+ export interface Metadata {
2
+ title?: string;
3
+ description?: string;
4
+ keywords?: string[];
5
+ og?: {
6
+ title?: string;
7
+ description?: string;
8
+ image?: string;
9
+ type?: 'website' | 'article' | 'product';
10
+ url?: string;
11
+ };
12
+ twitter?: {
13
+ card?: 'summary' | 'summary_large_image';
14
+ title?: string;
15
+ description?: string;
16
+ image?: string;
17
+ creator?: string;
18
+ };
19
+ canonical?: string;
20
+ robots?: string;
21
+ alternates?: Record<string, string>;
22
+ }
23
+ export interface Viewport {
24
+ width?: string | number;
25
+ initialScale?: number;
26
+ maximumScale?: number;
27
+ userScalable?: boolean;
28
+ themeColor?: string;
29
+ }
30
+ export interface LoaderContext<TParams = Record<string, string>> {
31
+ params: TParams;
32
+ request: Request;
33
+ guardData: unknown;
34
+ }
35
+ import type { Redirect } from './utils/response';
36
+ export type LoaderFunction<TData = unknown, TParams = Record<string, string>> = (ctx: LoaderContext<TParams>) => Promise<TData | Redirect | void> | TData | Redirect | void;
37
+ export type GuardFunction<TParams = Record<string, string>> = (ctx: LoaderContext<TParams>) => Promise<string | Redirect | Record<string, unknown> | null> | string | Redirect | Record<string, unknown> | null;
38
+ type GuardData<TGuard> = TGuard extends (...args: any[]) => infer R ? Exclude<Awaited<R>, string | Redirect | null | undefined> : unknown;
39
+ export type LoaderContextWithGuard<TGuard extends GuardFunction | undefined = undefined, TParams = Record<string, string>> = LoaderContext<TParams> & {
40
+ guardData: GuardData<TGuard>;
41
+ };
42
+ export {};
@@ -0,0 +1 @@
1
+ export declare function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T>;
@@ -0,0 +1 @@
1
+ export declare function printDevBanner(port: number): void;
@@ -0,0 +1,12 @@
1
+ export interface CookieOptions {
2
+ httpOnly?: boolean;
3
+ secure?: boolean;
4
+ sameSite?: 'Strict' | 'Lax' | 'None';
5
+ maxAge?: number;
6
+ expires?: Date;
7
+ path?: string;
8
+ domain?: string;
9
+ }
10
+ export declare function getCookie(req: Request, name: string): string | undefined;
11
+ export declare function setCookie(headers: Headers, name: string, value: string, options?: CookieOptions): void;
12
+ export declare function deleteCookie(headers: Headers, name: string, options?: Pick<CookieOptions, 'path' | 'domain'>): void;
@@ -0,0 +1 @@
1
+ export declare function parseDuration(value: number | string): number;
@@ -0,0 +1 @@
1
+ export declare function loadDotenv(mode: string): void;
@@ -0,0 +1,2 @@
1
+ export declare function safeJsonStringify(value: unknown): string;
2
+ export declare function escapeAttr(value: string): string;
@@ -0,0 +1 @@
1
+ export declare function routePattern(rel: string): string;
@@ -0,0 +1,19 @@
1
+ export type JsonResponse<T = unknown> = Response & {
2
+ readonly __body: T;
3
+ };
4
+ export declare const json: <const T>(data: T, status?: number) => JsonResponse<T>;
5
+ export declare const text: (body: string, status?: number) => Response;
6
+ declare const REDIRECT_BRAND: unique symbol;
7
+ export interface RedirectOptions {
8
+ status?: number;
9
+ replace?: boolean;
10
+ }
11
+ export interface Redirect {
12
+ readonly [REDIRECT_BRAND]: true;
13
+ readonly url: string;
14
+ readonly status: number;
15
+ readonly replace: boolean;
16
+ }
17
+ export declare function redirect(url: string, statusOrOptions?: number | RedirectOptions): Redirect;
18
+ export declare function isRedirect(value: unknown): value is Redirect;
19
+ export {};
@@ -0,0 +1,6 @@
1
+ interface ApiOptions {
2
+ apiPath: string;
3
+ appDir: string;
4
+ }
5
+ export declare function generateApi({ apiPath, appDir }: ApiOptions): string;
6
+ export {};
@@ -0,0 +1,6 @@
1
+ interface ClientRoutesOptions {
2
+ pagesDir: string;
3
+ matcherPath: string;
4
+ }
5
+ export declare function generateClientRoutes({ pagesDir, matcherPath }: ClientRoutesOptions): string;
6
+ export {};
@@ -0,0 +1 @@
1
+ export declare function generateContext(): string;
@@ -0,0 +1,5 @@
1
+ interface EntryClientOptions {
2
+ cssUrls: string[];
3
+ }
4
+ export declare function generateEntryClient({ cssUrls }: EntryClientOptions): string;
5
+ export {};
@@ -0,0 +1,4 @@
1
+ declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
2
+ export type HttpMethod = (typeof HTTP_METHODS)[number];
3
+ export declare function extractHttpMethods(content: string): HttpMethod[];
4
+ export {};
@@ -0,0 +1,6 @@
1
+ interface RenderOptions {
2
+ pagesDir: string;
3
+ renderPath: string;
4
+ }
5
+ export declare function generateRender({ pagesDir, renderPath }: RenderOptions): string;
6
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { HttpMethod } from './extract-methods';
2
+ export interface RouteEntry {
3
+ filePath: string;
4
+ urlPattern: string;
5
+ identifier: string;
6
+ methods: HttpMethod[];
7
+ }
8
+ export declare function filePathToIdentifier(filePath: string, apiDir: string): string;
9
+ export declare function buildRouteEntry(filePath: string, apiDir: string, methods: HttpMethod[]): RouteEntry;
10
+ export declare function generateRoutesDts(entries: RouteEntry[], apiDir: string): string;
@@ -0,0 +1,2 @@
1
+ import type { RouteEntry } from './routes-dts';
2
+ export declare function scanApiFiles(appDir: string, projectRoot: string): RouteEntry[];
@@ -0,0 +1 @@
1
+ export declare function writeRoutesDts(content: string, projectRoot: string): boolean;
@@ -0,0 +1,3 @@
1
+ import { UserConfig } from 'vite';
2
+ import type { DevixConfig } from '../config';
3
+ export declare function devix(config: DevixConfig): UserConfig;
package/dist/types.d.ts CHANGED
@@ -1,3 +1,9 @@
1
+ export interface MetadataIcon {
2
+ href: string;
3
+ rel?: string;
4
+ type?: string;
5
+ sizes?: string;
6
+ }
1
7
  export interface Metadata {
2
8
  title?: string;
3
9
  description?: string;
@@ -19,6 +25,7 @@ export interface Metadata {
19
25
  canonical?: string;
20
26
  robots?: string;
21
27
  alternates?: Record<string, string>;
28
+ icons?: string | MetadataIcon | MetadataIcon[];
22
29
  }
23
30
  export interface Viewport {
24
31
  width?: string | number;
@@ -1,2 +1,2 @@
1
- import o from"picocolors";import{networkInterfaces as r}from"node:os";function s(e){let l=r();for(let n of Object.values(l))for(let t of n??[])if(t.family==="IPv4"&&!t.internal)return`http://${t.address}:${e}/`;return null}function $(e){let l="0.4.0",n=s(e);console.log(),console.log(` ${o.bold(o.yellow("devix"))} ${o.dim(`v${l}`)}`),console.log(),console.log(` ${o.green("\u279C")} ${o.bold("Local:")} ${o.cyan(`http://localhost:${e}/`)}`),console.log(n?` ${o.green("\u279C")} ${o.bold("Network:")} ${o.cyan(n)}`:` ${o.green("\u279C")} ${o.bold("Network:")} ${o.dim("use --host to expose")}`),console.log()}export{$ as printDevBanner};
1
+ import o from"picocolors";import{networkInterfaces as r}from"node:os";function s(e){let l=r();for(let n of Object.values(l))for(let t of n??[])if(t.family==="IPv4"&&!t.internal)return`http://${t.address}:${e}/`;return null}function $(e){let l="0.4.1-beta.10",n=s(e);console.log(),console.log(` ${o.bold(o.yellow("devix"))} ${o.dim(`v${l}`)}`),console.log(),console.log(` ${o.green("\u279C")} ${o.bold("Local:")} ${o.cyan(`http://localhost:${e}/`)}`),console.log(n?` ${o.green("\u279C")} ${o.bold("Network:")} ${o.cyan(n)}`:` ${o.green("\u279C")} ${o.bold("Network:")} ${o.dim("use --host to expose")}`),console.log()}export{$ as printDevBanner};
2
2
  //# sourceMappingURL=banner.js.map
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/banner.ts"],
4
4
  "sourcesContent": ["import pc from 'picocolors'\nimport {networkInterfaces} from 'node:os'\n\ndeclare const __DEVIX_VERSION__: string\n\nfunction getNetworkUrl(port: number): string | null {\n const nets = networkInterfaces()\n for (const interfaces of Object.values(nets)) {\n for (const net of interfaces ?? []) {\n if (net.family === 'IPv4' && !net.internal) {\n return `http://${net.address}:${port}/`\n }\n }\n }\n return null\n}\n\nexport function printDevBanner(port: number) {\n const version = __DEVIX_VERSION__\n const networkUrl = getNetworkUrl(port)\n\n console.log()\n console.log(` ${pc.bold(pc.yellow('devix'))} ${pc.dim(`v${version}`)}`)\n console.log()\n console.log(` ${pc.green('\u279C')} ${pc.bold('Local:')} ${pc.cyan(`http://localhost:${port}/`)}`)\n if (networkUrl) {\n console.log(` ${pc.green('\u279C')} ${pc.bold('Network:')} ${pc.cyan(networkUrl)}`)\n } else {\n console.log(` ${pc.green('\u279C')} ${pc.bold('Network:')} ${pc.dim('use --host to expose')}`)\n }\n console.log()\n}"],
5
- "mappings": "AAAA,OAAOA,MAAQ,aACf,OAAQ,qBAAAC,MAAwB,UAIhC,SAASC,EAAcC,EAA6B,CAChD,IAAMC,EAAOH,EAAkB,EAC/B,QAAWI,KAAc,OAAO,OAAOD,CAAI,EACvC,QAAWE,KAAOD,GAAc,CAAC,EAC7B,GAAIC,EAAI,SAAW,QAAU,CAACA,EAAI,SAC9B,MAAO,UAAUA,EAAI,OAAO,IAAIH,CAAI,IAIhD,OAAO,IACX,CAEO,SAASI,EAAeJ,EAAc,CACzC,IAAMK,EAAU,QACVC,EAAaP,EAAcC,CAAI,EAErC,QAAQ,IAAI,EACZ,QAAQ,IAAI,KAAKH,EAAG,KAAKA,EAAG,OAAO,OAAO,CAAC,CAAC,IAAIA,EAAG,IAAI,IAAIQ,CAAO,EAAE,CAAC,EAAE,EACvE,QAAQ,IAAI,EACZ,QAAQ,IAAI,KAAKR,EAAG,MAAM,QAAG,CAAC,KAAKA,EAAG,KAAK,QAAQ,CAAC,MAAMA,EAAG,KAAK,oBAAoBG,CAAI,GAAG,CAAC,EAAE,EAE5F,QAAQ,IADRM,EACY,KAAKT,EAAG,MAAM,QAAG,CAAC,KAAKA,EAAG,KAAK,UAAU,CAAC,IAAIA,EAAG,KAAKS,CAAU,CAAC,GAEjE,KAAKT,EAAG,MAAM,QAAG,CAAC,KAAKA,EAAG,KAAK,UAAU,CAAC,IAAIA,EAAG,IAAI,sBAAsB,CAAC,EAFT,EAInF,QAAQ,IAAI,CAChB",
5
+ "mappings": "AAAA,OAAOA,MAAQ,aACf,OAAQ,qBAAAC,MAAwB,UAIhC,SAASC,EAAcC,EAA6B,CAChD,IAAMC,EAAOH,EAAkB,EAC/B,QAAWI,KAAc,OAAO,OAAOD,CAAI,EACvC,QAAWE,KAAOD,GAAc,CAAC,EAC7B,GAAIC,EAAI,SAAW,QAAU,CAACA,EAAI,SAC9B,MAAO,UAAUA,EAAI,OAAO,IAAIH,CAAI,IAIhD,OAAO,IACX,CAEO,SAASI,EAAeJ,EAAc,CACzC,IAAMK,EAAU,gBACVC,EAAaP,EAAcC,CAAI,EAErC,QAAQ,IAAI,EACZ,QAAQ,IAAI,KAAKH,EAAG,KAAKA,EAAG,OAAO,OAAO,CAAC,CAAC,IAAIA,EAAG,IAAI,IAAIQ,CAAO,EAAE,CAAC,EAAE,EACvE,QAAQ,IAAI,EACZ,QAAQ,IAAI,KAAKR,EAAG,MAAM,QAAG,CAAC,KAAKA,EAAG,KAAK,QAAQ,CAAC,MAAMA,EAAG,KAAK,oBAAoBG,CAAI,GAAG,CAAC,EAAE,EAE5F,QAAQ,IADRM,EACY,KAAKT,EAAG,MAAM,QAAG,CAAC,KAAKA,EAAG,KAAK,UAAU,CAAC,IAAIA,EAAG,KAAKS,CAAU,CAAC,GAEjE,KAAKT,EAAG,MAAM,QAAG,CAAC,KAAKA,EAAG,KAAK,UAAU,CAAC,IAAIA,EAAG,IAAI,sBAAsB,CAAC,EAFT,EAInF,QAAQ,IAAI,CAChB",
6
6
  "names": ["pc", "networkInterfaces", "getNetworkUrl", "port", "nets", "interfaces", "net", "printDevBanner", "version", "networkUrl"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ import type { DevixConfig } from "../config";
2
+ export declare function loadConfig(cwd: string): Promise<DevixConfig>;
@@ -0,0 +1,2 @@
1
+ import{build as n}from"esbuild";import{join as i}from"node:path";import{unlinkSync as r,writeFileSync as m}from"node:fs";import{pathToFileURL as f}from"node:url";async function u(o){let e=await n({entryPoints:[i(o,"devix.config.ts")],bundle:!0,write:!1,format:"esm",platform:"node",packages:"external"}),t=i(o,`.devix-config-${Date.now()}.mjs`);m(t,e.outputFiles[0].text);try{return(await import(f(t).href)).default}finally{r(t)}}export{u as loadConfig};
2
+ //# sourceMappingURL=load-config.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/load-config.ts"],
4
+ "sourcesContent": ["import {build} from 'esbuild'\nimport type {DevixConfig} from \"../config\"\nimport {join} from \"node:path\"\nimport {unlinkSync, writeFileSync} from \"node:fs\";\nimport {pathToFileURL} from \"node:url\";\n\nexport async function loadConfig(cwd: string): Promise<DevixConfig> {\n const result = await build({\n entryPoints: [join(cwd, 'devix.config.ts')],\n bundle: true,\n write: false,\n format: 'esm',\n platform: 'node',\n packages: 'external',\n })\n\n const tmpFile = join(cwd, `.devix-config-${Date.now()}.mjs`)\n writeFileSync(tmpFile, result.outputFiles[0].text)\n\n try {\n const mod = await import(pathToFileURL(tmpFile).href)\n return mod.default\n } finally {\n unlinkSync(tmpFile)\n }\n}"],
5
+ "mappings": "AAAA,OAAQ,SAAAA,MAAY,UAEpB,OAAQ,QAAAC,MAAW,YACnB,OAAQ,cAAAC,EAAY,iBAAAC,MAAoB,UACxC,OAAQ,iBAAAC,MAAoB,WAE5B,eAAsBC,EAAWC,EAAmC,CAChE,IAAMC,EAAS,MAAMP,EAAM,CACvB,YAAa,CAACC,EAAKK,EAAK,iBAAiB,CAAC,EAC1C,OAAQ,GACR,MAAO,GACP,OAAQ,MACR,SAAU,OACV,SAAU,UACd,CAAC,EAEKE,EAAUP,EAAKK,EAAK,iBAAiB,KAAK,IAAI,CAAC,MAAM,EAC3DH,EAAcK,EAASD,EAAO,YAAY,CAAC,EAAE,IAAI,EAEjD,GAAI,CAEA,OADY,MAAM,OAAOH,EAAcI,CAAO,EAAE,OACrC,OACf,QAAE,CACEN,EAAWM,CAAO,CACtB,CACJ",
6
+ "names": ["build", "join", "unlinkSync", "writeFileSync", "pathToFileURL", "loadConfig", "cwd", "result", "tmpFile"]
7
+ }
@@ -1,5 +1,5 @@
1
- function r({cssUrls:t}){return`
2
- ${t.map(a=>`import '${a}'`).join(`
1
+ function o({cssUrls:t}){return`
2
+ ${t.map(e=>`import '${e}'`).join(`
3
3
  `)}
4
4
  import "@vitejs/plugin-react/preamble"
5
5
  import React from "react"
@@ -37,6 +37,14 @@ if (!window.__DEVIX__) {
37
37
  initialViewport: viewport,
38
38
  })
39
39
  )
40
+
41
+ if (window.location.hash) {
42
+ const id = window.location.hash.slice(1)
43
+ const scrollBehavior = getComputedStyle(document.documentElement).scrollBehavior
44
+ requestAnimationFrame(() => {
45
+ document.getElementById(id)?.scrollIntoView({ behavior: scrollBehavior })
46
+ })
47
+ }
40
48
  } else {
41
49
  const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()
42
50
  createRoot(root).render(
@@ -54,5 +62,5 @@ if (!window.__DEVIX__) {
54
62
  )
55
63
  }
56
64
  }
57
- `}export{r as generateEntryClient};
65
+ `}export{o as generateEntryClient};
58
66
  //# sourceMappingURL=entry-client.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/vite/codegen/entry-client.ts"],
4
- "sourcesContent": ["interface EntryClientOptions {\n cssUrls: string[]\n}\n\nexport function generateEntryClient({cssUrls}: EntryClientOptions): string {\n const cssImports = cssUrls.map(u => `import '${u}'`).join('\\n')\n\n return `\n${cssImports}\nimport \"@vitejs/plugin-react/preamble\"\nimport React from \"react\"\nimport {hydrateRoot, createRoot} from 'react-dom/client'\nimport {matchClientRoute, loadErrorPage, getDefaultErrorPage} from 'virtual:devix/client-routes'\nimport {RouterProvider} from '@devlusoft/devix'\n\nconst root = document.getElementById('devix-root')\n\nif (!window.__DEVIX__) {\n const ErrorPage = getDefaultErrorPage()\n createRoot(root).render(React.createElement(ErrorPage, {statusCode: 500, message: 'Server error'}))\n} else {\n const {metadata, viewport, clientEntry} = window.__DEVIX__\n const loaderData = window.__LOADER_DATA__\n const layoutsData = window.__LAYOUTS_DATA__ ?? []\n\n const matched = matchClientRoute(window.location.pathname)\n\n if (matched) {\n const [pageMod, ...layoutMods] = await Promise.all([\n matched.load(),\n ...matched.loadLayouts.map(l => l()),\n ])\n hydrateRoot(\n root,\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: loaderData,\n initialParams: matched.params,\n initialPage: pageMod.default,\n initialLayouts: layoutMods.map(m => m.default),\n initialLayoutsData: layoutsData,\n initialMeta: metadata,\n initialViewport: viewport,\n })\n )\n } else {\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n createRoot(root).render(\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: null,\n initialParams: {},\n initialPage: () => null,\n initialLayouts: [],\n initialLayoutsData: [],\n initialMeta: null,\n initialError: {statusCode: 404, message: 'Not found'},\n initialErrorPage: ErrorPage,\n })\n )\n }\n}\n`\n}"],
5
- "mappings": "AAIO,SAASA,EAAoB,CAAC,QAAAC,CAAO,EAA+B,CAGvE,MAAO;AAAA,EAFYA,EAAQ,IAAIC,GAAK,WAAWA,CAAC,GAAG,EAAE,KAAK;AAAA,CAAI,CAGtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAuDZ",
4
+ "sourcesContent": ["interface EntryClientOptions {\n cssUrls: string[]\n}\n\nexport function generateEntryClient({ cssUrls }: EntryClientOptions): string {\n const cssImports = cssUrls.map(u => `import '${u}'`).join('\\n')\n\n return `\n${cssImports}\nimport \"@vitejs/plugin-react/preamble\"\nimport React from \"react\"\nimport {hydrateRoot, createRoot} from 'react-dom/client'\nimport {matchClientRoute, loadErrorPage, getDefaultErrorPage} from 'virtual:devix/client-routes'\nimport {RouterProvider} from '@devlusoft/devix'\n\nconst root = document.getElementById('devix-root')\n\nif (!window.__DEVIX__) {\n const ErrorPage = getDefaultErrorPage()\n createRoot(root).render(React.createElement(ErrorPage, {statusCode: 500, message: 'Server error'}))\n} else {\n const {metadata, viewport, clientEntry} = window.__DEVIX__\n const loaderData = window.__LOADER_DATA__\n const layoutsData = window.__LAYOUTS_DATA__ ?? []\n\n const matched = matchClientRoute(window.location.pathname)\n\n if (matched) {\n const [pageMod, ...layoutMods] = await Promise.all([\n matched.load(),\n ...matched.loadLayouts.map(l => l()),\n ])\n hydrateRoot(\n root,\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: loaderData,\n initialParams: matched.params,\n initialPage: pageMod.default,\n initialLayouts: layoutMods.map(m => m.default),\n initialLayoutsData: layoutsData,\n initialMeta: metadata,\n initialViewport: viewport,\n })\n )\n\n if (window.location.hash) { \n const id = window.location.hash.slice(1) \n const scrollBehavior = getComputedStyle(document.documentElement).scrollBehavior \n requestAnimationFrame(() => { \n document.getElementById(id)?.scrollIntoView({ behavior: scrollBehavior }) \n }) \n } \n } else {\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n createRoot(root).render(\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: null,\n initialParams: {},\n initialPage: () => null,\n initialLayouts: [],\n initialLayoutsData: [],\n initialMeta: null,\n initialError: {statusCode: 404, message: 'Not found'},\n initialErrorPage: ErrorPage,\n })\n )\n }\n}\n`\n}"],
5
+ "mappings": "AAIO,SAASA,EAAoB,CAAE,QAAAC,CAAQ,EAA+B,CAGzE,MAAO;AAAA,EAFYA,EAAQ,IAAIC,GAAK,WAAWA,CAAC,GAAG,EAAE,KAAK;AAAA,CAAI,CAGtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA+DZ",
6
6
  "names": ["generateEntryClient", "cssUrls", "u"]
7
7
  }
@@ -0,0 +1,6 @@
1
+ interface ServerEntryOptions {
2
+ routesPath: string;
3
+ envPath: string;
4
+ }
5
+ export declare function generateServerEntry({ routesPath, envPath }: ServerEntryOptions): string;
6
+ export {};
@@ -0,0 +1,73 @@
1
+ function t({routesPath:e,envPath:o}){return`
2
+ import { readFileSync } from 'node:fs'
3
+ import { serve } from '@hono/node-server'
4
+ import { serveStatic } from '@hono/node-server/serve-static'
5
+ import { Hono } from 'hono'
6
+ import { resolve, join, dirname } from 'node:path'
7
+ import { fileURLToPath, pathToFileURL } from 'node:url'
8
+ import { registerApiRoutes, registerSsrRoute } from '${e}'
9
+ import { loadDotenv } from '${o}'
10
+
11
+ loadDotenv('production')
12
+
13
+ const __dir = dirname(fileURLToPath(import.meta.url))
14
+
15
+ let renderModule, apiModule, manifest, runtimeConfig
16
+
17
+ try {
18
+ runtimeConfig = JSON.parse(readFileSync(resolve(__dir, '../devix.config.json'), 'utf-8'))
19
+ if (runtimeConfig.output !== 'static') {
20
+ renderModule = await import(pathToFileURL(resolve(__dir, 'render.js')).href)
21
+ apiModule = await import(pathToFileURL(resolve(__dir, 'api.js')).href)
22
+ }
23
+ manifest = JSON.parse(readFileSync(resolve(__dir, '../client/.vite/manifest.json'), 'utf-8'))
24
+ } catch {
25
+ console.error('[devix] Build not found. Run "devix build" first.')
26
+ process.exit(1)
27
+ }
28
+
29
+ const port = Number(process.env.PORT) || runtimeConfig.port || 3000
30
+ const host = typeof runtimeConfig.host === 'string'
31
+ ? runtimeConfig.host
32
+ : runtimeConfig.host ? '0.0.0.0' : (process.env.HOST || '0.0.0.0')
33
+
34
+ const clientRoot = resolve(__dir, '../client')
35
+ const app = new Hono()
36
+
37
+ if (runtimeConfig.output === 'static') {
38
+ app.get('/_data/*', (c) => {
39
+ const pathname = c.req.path.replace(/^\\\\/_data/, '') || '/'
40
+ const filePath = pathname === '/'
41
+ ? join(clientRoot, '_data/index.json')
42
+ : join(clientRoot, '_data', pathname + '.json')
43
+ try {
44
+ return c.json(JSON.parse(readFileSync(filePath, 'utf-8')))
45
+ } catch {
46
+ return c.json({ error: 'not found' }, 404)
47
+ }
48
+ })
49
+ }
50
+
51
+ app.use('/*', serveStatic({
52
+ root: clientRoot,
53
+ onFound: (_path, c) => {
54
+ c.header('Cache-Control', _path.includes('/assets/')
55
+ ? 'public, immutable, max-age=31536000'
56
+ : 'no-cache')
57
+ }
58
+ }))
59
+
60
+ if (runtimeConfig.output === 'static') {
61
+ console.log('[devix] Static mode \u2014 serving pre-generated files from dist/client')
62
+ } else {
63
+ registerApiRoutes(app, { renderModule, apiModule, manifest })
64
+ registerSsrRoute(app, { renderModule, apiModule, manifest, loaderTimeout: runtimeConfig.loaderTimeout })
65
+ }
66
+
67
+ const server = serve({ fetch: app.fetch, port, hostname: host }, (info) =>
68
+ console.log(\`http://\${info.address}:\${info.port}\`))
69
+
70
+ process.on('SIGTERM', () => server.close())
71
+ process.on('SIGINT', () => server.close())
72
+ `}export{t as generateServerEntry};
73
+ //# sourceMappingURL=server-entry.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/vite/codegen/server-entry.ts"],
4
+ "sourcesContent": ["interface ServerEntryOptions {\n routesPath: string\n envPath: string\n}\n\nexport function generateServerEntry({ routesPath, envPath }: ServerEntryOptions): string {\n return `\nimport { readFileSync } from 'node:fs'\n import { serve } from '@hono/node-server' \n import { serveStatic } from '@hono/node-server/serve-static'\n import { Hono } from 'hono' \n import { resolve, join, dirname } from 'node:path' \n import { fileURLToPath, pathToFileURL } from 'node:url'\n import { registerApiRoutes, registerSsrRoute } from '${routesPath}' \n import { loadDotenv } from '${envPath}'\n \n loadDotenv('production')\n \n const __dir = dirname(fileURLToPath(import.meta.url))\n\n let renderModule, apiModule, manifest, runtimeConfig \n \n try { \n runtimeConfig = JSON.parse(readFileSync(resolve(__dir, '../devix.config.json'), 'utf-8'))\n if (runtimeConfig.output !== 'static') { \n renderModule = await import(pathToFileURL(resolve(__dir, 'render.js')).href)\n apiModule = await import(pathToFileURL(resolve(__dir, 'api.js')).href) \n } \n manifest = JSON.parse(readFileSync(resolve(__dir, '../client/.vite/manifest.json'), 'utf-8')) \n } catch { \n console.error('[devix] Build not found. Run \"devix build\" first.')\n process.exit(1) \n } \n \n const port = Number(process.env.PORT) || runtimeConfig.port || 3000 \n const host = typeof runtimeConfig.host === 'string'\n ? runtimeConfig.host \n : runtimeConfig.host ? '0.0.0.0' : (process.env.HOST || '0.0.0.0') \n \n const clientRoot = resolve(__dir, '../client') \n const app = new Hono()\n \n if (runtimeConfig.output === 'static') {\n app.get('/_data/*', (c) => {\n const pathname = c.req.path.replace(/^\\\\\\\\/_data/, '') || '/' \n const filePath = pathname === '/' \n ? join(clientRoot, '_data/index.json') \n : join(clientRoot, '_data', pathname + '.json') \n try { \n return c.json(JSON.parse(readFileSync(filePath, 'utf-8')))\n } catch { \n return c.json({ error: 'not found' }, 404)\n } \n }) \n }\n\n app.use('/*', serveStatic({ \n root: clientRoot,\n onFound: (_path, c) => { \n c.header('Cache-Control', _path.includes('/assets/') \n ? 'public, immutable, max-age=31536000'\n : 'no-cache') \n } \n })) \n \n if (runtimeConfig.output === 'static') {\n console.log('[devix] Static mode \u2014 serving pre-generated files from dist/client')\n } else { \n registerApiRoutes(app, { renderModule, apiModule, manifest })\n registerSsrRoute(app, { renderModule, apiModule, manifest, loaderTimeout: runtimeConfig.loaderTimeout })\n } \n \n const server = serve({ fetch: app.fetch, port, hostname: host }, (info) => \n console.log(\\`http://\\${info.address}:\\${info.port}\\`))\n\nprocess.on('SIGTERM', () => server.close())\nprocess.on('SIGINT', () => server.close())\n`\n}"],
5
+ "mappings": "AAKO,SAASA,EAAoB,CAAE,WAAAC,EAAY,QAAAC,CAAQ,EAA+B,CACrF,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yDAO8CD,CAAU;AAAA,gCACnCC,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAgEvC",
6
+ "names": ["generateServerEntry", "routesPath", "envPath"]
7
+ }