arcanajs 2.1.6 → 2.2.1

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 (59) hide show
  1. package/README.md +45 -3
  2. package/framework/cli/index.js +127 -25
  3. package/framework/cli/templates.d.ts +6 -0
  4. package/framework/cli/templates.js +41 -0
  5. package/framework/cli/webpack.config.js +87 -44
  6. package/framework/lib/client/index.js +23 -7
  7. package/framework/lib/index.d.ts +2 -2
  8. package/framework/lib/index.js +40 -17
  9. package/framework/lib/server/ArcanaJSMiddleware.d.ts +9 -1
  10. package/framework/lib/server/ArcanaJSMiddleware.js +35 -13
  11. package/framework/lib/server/ArcanaJSServer.d.ts +2 -0
  12. package/framework/lib/server/ArcanaJSServer.js +77 -59
  13. package/framework/lib/server/ControllerBinder.js +4 -1
  14. package/framework/lib/server/CsrfMiddleware.js +10 -3
  15. package/framework/lib/server/DynamicRouter.d.ts +1 -1
  16. package/framework/lib/server/DynamicRouter.js +5 -1
  17. package/framework/lib/server/ResponseHandlerMiddleware.js +5 -1
  18. package/framework/lib/server/Router.d.ts +1 -1
  19. package/framework/lib/server/Router.js +16 -8
  20. package/framework/lib/server.d.ts +10 -0
  21. package/framework/lib/server.js +41 -6
  22. package/framework/lib/shared/components/Body.js +7 -3
  23. package/framework/lib/shared/components/Head.js +47 -10
  24. package/framework/lib/shared/components/Link.js +9 -5
  25. package/framework/lib/shared/components/NavLink.js +10 -6
  26. package/framework/lib/shared/components/Page.js +9 -5
  27. package/framework/lib/shared/context/HeadContext.js +5 -2
  28. package/framework/lib/shared/context/PageContext.js +5 -2
  29. package/framework/lib/shared/context/RouterContext.js +9 -5
  30. package/framework/lib/shared/core/ArcanaJSApp.js +18 -14
  31. package/framework/lib/shared/hooks/useHead.d.ts +1 -1
  32. package/framework/lib/shared/hooks/useHead.js +7 -3
  33. package/framework/lib/shared/hooks/useLocation.js +7 -3
  34. package/framework/lib/shared/hooks/usePage.js +7 -3
  35. package/framework/lib/shared/hooks/useParams.js +8 -4
  36. package/framework/lib/shared/hooks/useQuery.js +7 -3
  37. package/framework/lib/shared/hooks/useRouter.d.ts +1 -1
  38. package/framework/lib/shared/hooks/useRouter.js +8 -4
  39. package/framework/lib/shared/utils/createSingletonContext.js +6 -3
  40. package/framework/lib/shared/views/ErrorPage.d.ts +7 -0
  41. package/framework/lib/shared/views/ErrorPage.js +11 -0
  42. package/framework/lib/shared/views/NotFoundPage.d.ts +5 -0
  43. package/framework/lib/shared/views/NotFoundPage.js +10 -0
  44. package/framework/templates/ErrorPage.tsx +137 -0
  45. package/framework/templates/HomePage.tsx +344 -0
  46. package/framework/templates/NotFoundPage.tsx +109 -0
  47. package/framework/templates/arcanajs.png +0 -0
  48. package/framework/templates/arcanajs.svg +12 -0
  49. package/framework/templates/client-index.tsx +7 -0
  50. package/framework/templates/favicon.ico +0 -0
  51. package/framework/templates/globals.css +198 -0
  52. package/framework/templates/package.json +15 -0
  53. package/framework/templates/postcss.config.js +6 -0
  54. package/framework/templates/server-controller-home.ts +7 -0
  55. package/framework/templates/server-index.ts +10 -0
  56. package/framework/templates/server-routes-web.ts +7 -0
  57. package/package.json +30 -25
  58. package/framework/lib/shared/hooks/useDynamicComponents.d.ts +0 -1
  59. package/framework/lib/shared/hooks/useDynamicComponents.js +0 -16
package/README.md CHANGED
@@ -1,16 +1,58 @@
1
1
  # ArcanaJS Framework
2
2
 
3
- ArcanaJS is a modern React framework for building server-side rendered (SSR) applications with ease. It combines the power of Express, React, and TypeScript to provide a seamless development experience.
3
+ ArcanaJS is a modern React framework for building server-side rendered (SSR) applications with ease. It combines the power of Express, React, TypeScript, and Tailwind CSS v4 to provide a seamless development experience.
4
4
 
5
5
  ## Features
6
6
 
7
7
  - **Server-Side Rendering (SSR):** Fast initial load times and SEO-friendly pages.
8
8
  - **TypeScript Support:** Built with TypeScript for type safety and better developer experience.
9
- - **File-based Routing:** Intuitive routing based on your file structure.
9
+ - **File-Server-Based Routing:** Intuitive routing based on your server routes and file structure.
10
10
  - **Hot Module Replacement (HMR):** Fast development cycle with instant updates.
11
- - **Tailwind CSS:** Integrated support for utility-first CSS.
11
+ - **Tailwind CSS v4:** Integrated support for the latest Tailwind CSS with CSS-first configuration.
12
+ - **Zero Configuration:** Get started quickly with sensible defaults.
12
13
 
14
+ ## Quick Start
13
15
 
16
+ ### Create a new folder
17
+
18
+ ```bash
19
+ mkdir my-app
20
+ cd my-app
21
+ ```
22
+
23
+ ### Initialize a New Project
24
+
25
+ ```bash
26
+ npx arcanajs init
27
+ ```
28
+
29
+ ### Development
30
+
31
+ Install dependencies:
32
+
33
+ ```bash
34
+ npm install
35
+ ```
36
+
37
+ Start the development server:
38
+
39
+ ```bash
40
+ npm run dev
41
+ ```
42
+
43
+ Visit `http://localhost:3000` to see your application.
44
+
45
+ ### Build for Production
46
+
47
+ ```bash
48
+ npm run build
49
+ ```
50
+
51
+ ### Start Production Server
52
+
53
+ ```bash
54
+ npm start
55
+ ```
14
56
 
15
57
  ## License
16
58
 
@@ -1,11 +1,18 @@
1
- import { spawn } from "child_process";
2
- import path from "path";
3
- import webpack from "webpack";
4
- import { createClientConfig, createServerConfig } from "./webpack.config";
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const child_process_1 = require("child_process");
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const webpack_1 = __importDefault(require("webpack"));
10
+ const templates_1 = require("./templates");
11
+ const webpack_config_1 = require("./webpack.config");
5
12
  const args = process.argv.slice(2);
6
13
  const command = args[0];
7
14
  if (!command) {
8
- console.error("Please specify a command: dev, build, start");
15
+ console.error("Please specify a command: init, dev, build, start");
9
16
  process.exit(1);
10
17
  }
11
18
  const runCompiler = (compiler) => {
@@ -25,16 +32,28 @@ const runCompiler = (compiler) => {
25
32
  });
26
33
  };
27
34
  let serverProcess = null;
28
- const startDevServer = () => {
29
- if (serverProcess) {
30
- serverProcess.kill();
31
- }
32
- const serverPath = path.resolve(process.cwd(), "dist/server.js");
33
- serverProcess = spawn("node", [serverPath], { stdio: "inherit" });
34
- serverProcess.on("close", (code) => {
35
- if (code !== 0 && code !== null) {
36
- console.error(`Dev server exited with code ${code}`);
35
+ const ws_1 = require("ws");
36
+ const startDevServer = (hmrPort) => {
37
+ return new Promise((resolve) => {
38
+ if (serverProcess) {
39
+ serverProcess.kill();
37
40
  }
41
+ const serverPath = path_1.default.resolve(process.cwd(), "dist/server.js");
42
+ serverProcess = (0, child_process_1.spawn)("node", [serverPath], {
43
+ stdio: ["inherit", "pipe", "inherit"],
44
+ env: { ...process.env, ARCANA_HMR_PORT: hmrPort.toString() },
45
+ });
46
+ serverProcess.stdout?.on("data", (data) => {
47
+ process.stdout.write(data);
48
+ if (data.toString().includes("Server is running")) {
49
+ resolve();
50
+ }
51
+ });
52
+ serverProcess.on("close", (code) => {
53
+ if (code !== 0 && code !== null) {
54
+ console.error(`Dev server exited with code ${code}`);
55
+ }
56
+ });
38
57
  });
39
58
  };
40
59
  const watchCompiler = (compiler, onBuildComplete) => {
@@ -52,11 +71,11 @@ const watchCompiler = (compiler, onBuildComplete) => {
52
71
  const build = async () => {
53
72
  process.env.NODE_ENV = "production";
54
73
  console.log("Building for production...");
55
- const clientConfig = createClientConfig();
56
- const serverConfig = createServerConfig();
74
+ const clientConfig = (0, webpack_config_1.createClientConfig)();
75
+ const serverConfig = (0, webpack_config_1.createServerConfig)();
57
76
  try {
58
- await runCompiler(webpack(clientConfig));
59
- await runCompiler(webpack(serverConfig));
77
+ await runCompiler((0, webpack_1.default)(clientConfig));
78
+ await runCompiler((0, webpack_1.default)(serverConfig));
60
79
  console.log("Build complete.");
61
80
  }
62
81
  catch (error) {
@@ -67,26 +86,109 @@ const build = async () => {
67
86
  const dev = async () => {
68
87
  process.env.NODE_ENV = "development";
69
88
  console.log("Starting development server...");
70
- const clientConfig = createClientConfig();
71
- const serverConfig = createServerConfig();
89
+ // Start HMR WebSocket Server
90
+ const HMR_PORT = 3001;
91
+ const wss = new ws_1.WebSocketServer({ port: HMR_PORT });
92
+ console.log(`HMR Server running on port ${HMR_PORT}`);
93
+ const broadcastReload = () => {
94
+ wss.clients.forEach((client) => {
95
+ if (client.readyState === 1) {
96
+ client.send(JSON.stringify({ type: "reload" }));
97
+ }
98
+ });
99
+ };
100
+ const clientConfig = (0, webpack_config_1.createClientConfig)();
101
+ const serverConfig = (0, webpack_config_1.createServerConfig)();
102
+ let isServerBuilding = false;
103
+ let pendingReload = false;
104
+ const serverCompiler = (0, webpack_1.default)(serverConfig);
105
+ serverCompiler.hooks.invalid.tap("ArcanaJS", () => {
106
+ isServerBuilding = true;
107
+ });
72
108
  // Watch client
73
- watchCompiler(webpack(clientConfig));
109
+ watchCompiler((0, webpack_1.default)(clientConfig), () => {
110
+ console.log("Client build complete.");
111
+ if (isServerBuilding) {
112
+ console.log("Server is building. Waiting to reload...");
113
+ pendingReload = true;
114
+ }
115
+ else {
116
+ console.log("Reloading browsers...");
117
+ broadcastReload();
118
+ }
119
+ });
74
120
  // Watch server and restart on build
75
- watchCompiler(webpack(serverConfig), () => {
121
+ watchCompiler(serverCompiler, async () => {
76
122
  console.log("Server build complete. Restarting server...");
77
- startDevServer();
123
+ await startDevServer(HMR_PORT);
124
+ isServerBuilding = false;
125
+ if (pendingReload) {
126
+ console.log("Pending reload found. Reloading browsers...");
127
+ broadcastReload();
128
+ pendingReload = false;
129
+ }
130
+ });
131
+ };
132
+ const init = () => {
133
+ console.log("Initializing ArcanaJS project with Tailwind CSS...");
134
+ const cwd = process.cwd();
135
+ const templatesDir = path_1.default.resolve(__dirname, "../templates");
136
+ // Create necessary directories
137
+ templates_1.requiredDirs.forEach((dir) => {
138
+ const fullPath = path_1.default.resolve(cwd, dir);
139
+ if (!fs_1.default.existsSync(fullPath)) {
140
+ fs_1.default.mkdirSync(fullPath, { recursive: true });
141
+ console.log(`Created directory: ${dir}`);
142
+ }
143
+ });
144
+ // Copy configuration files
145
+ templates_1.configFiles.forEach(({ src, dest }) => {
146
+ const srcPath = path_1.default.resolve(templatesDir, src);
147
+ const destPath = path_1.default.resolve(cwd, dest);
148
+ if (!fs_1.default.existsSync(destPath)) {
149
+ if (fs_1.default.existsSync(srcPath)) {
150
+ fs_1.default.copyFileSync(srcPath, destPath);
151
+ console.log(`Created: ${dest}`);
152
+ }
153
+ else {
154
+ console.warn(`Template not found: ${src}`);
155
+ }
156
+ }
157
+ else {
158
+ console.log(`Skipped: ${dest} (already exists)`);
159
+ }
78
160
  });
161
+ // Create default error pages
162
+ templates_1.errorPages.forEach((page) => {
163
+ const viewPath = path_1.default.resolve(cwd, `src/views/${page}`);
164
+ const templatePath = path_1.default.resolve(templatesDir, page);
165
+ if (!fs_1.default.existsSync(viewPath) && fs_1.default.existsSync(templatePath)) {
166
+ fs_1.default.copyFileSync(templatePath, viewPath);
167
+ console.log(`Created: src/views/${page}`);
168
+ }
169
+ });
170
+ console.log("\n✅ ArcanaJS project initialized successfully!");
171
+ console.log("\nNext steps:");
172
+ console.log("1. Run 'npm install' to install dependencies");
173
+ console.log("2. Run 'npm run dev' to start development");
174
+ console.log("3. Visit http://localhost:3000 to see your app");
175
+ console.log("4. Edit src/views/HomePage.tsx to customize your homepage");
176
+ console.log("5. Customize your theme in src/client/globals.css");
177
+ console.log("6. Add your Tailwind classes and enjoy!");
79
178
  };
80
179
  const start = () => {
81
180
  process.env.NODE_ENV = "production";
82
- const serverPath = path.resolve(process.cwd(), "dist/server.js");
181
+ const serverPath = path_1.default.resolve(process.cwd(), "dist/server.js");
83
182
  console.log(`Starting server at ${serverPath}...`);
84
- const child = spawn("node", [serverPath], { stdio: "inherit" });
183
+ const child = (0, child_process_1.spawn)("node", [serverPath], { stdio: "inherit" });
85
184
  child.on("close", (code) => {
86
185
  process.exit(code || 0);
87
186
  });
88
187
  };
89
188
  switch (command) {
189
+ case "init":
190
+ init();
191
+ break;
90
192
  case "build":
91
193
  build();
92
194
  break;
@@ -0,0 +1,6 @@
1
+ export declare const configFiles: {
2
+ src: string;
3
+ dest: string;
4
+ }[];
5
+ export declare const errorPages: string[];
6
+ export declare const requiredDirs: string[];
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requiredDirs = exports.errorPages = exports.configFiles = void 0;
4
+ exports.configFiles = [
5
+ { src: "package.json", dest: "package.json" },
6
+ { src: "postcss.config.js", dest: "postcss.config.js" },
7
+ { src: "globals.css", dest: "src/client/globals.css" },
8
+ { src: "client-index.tsx", dest: "src/client/index.tsx" },
9
+ { src: "server-index.ts", dest: "src/server/index.ts" },
10
+ { src: "server-routes-web.ts", dest: "src/server/routes/web.ts" },
11
+ {
12
+ src: "server-controller-home.ts",
13
+ dest: "src/server/controllers/HomeController.ts",
14
+ },
15
+ {
16
+ src: "HomePage.tsx",
17
+ dest: "src/views/HomePage.tsx",
18
+ },
19
+ {
20
+ src: "arcanajs.png",
21
+ dest: "public/arcanajs.png",
22
+ },
23
+ {
24
+ src: "arcanajs.svg",
25
+ dest: "public/arcanajs.svg",
26
+ },
27
+ {
28
+ src: "favicon.ico",
29
+ dest: "public/favicon.ico",
30
+ },
31
+ ];
32
+ exports.errorPages = ["NotFoundPage.tsx", "ErrorPage.tsx"];
33
+ exports.requiredDirs = [
34
+ "public",
35
+ "src",
36
+ "src/client",
37
+ "src/server",
38
+ "src/server/routes",
39
+ "src/server/controllers",
40
+ "src/views",
41
+ ];
@@ -1,42 +1,65 @@
1
- import { CleanWebpackPlugin } from "clean-webpack-plugin";
2
- import HtmlWebpackPlugin from "html-webpack-plugin";
3
- import MiniCssExtractPlugin from "mini-css-extract-plugin";
4
- import path from "path";
5
- import nodeExternals from "webpack-node-externals";
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createServerConfig = exports.createClientConfig = void 0;
7
+ const clean_webpack_plugin_1 = require("clean-webpack-plugin");
8
+ const html_webpack_plugin_1 = __importDefault(require("html-webpack-plugin"));
9
+ const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const webpack_node_externals_1 = __importDefault(require("webpack-node-externals"));
6
12
  const cwd = process.cwd();
7
13
  // Helper to resolve loaders from the framework's node_modules
8
14
  const resolveLoader = (loader) => require.resolve(loader);
9
- import fs from "fs";
15
+ const fs_1 = __importDefault(require("fs"));
10
16
  // Helper to find entry file with supported extensions
11
17
  const findEntry = (searchPaths) => {
12
18
  const extensions = [".ts", ".tsx", ".js", ".jsx"];
13
19
  for (const basePath of searchPaths) {
14
20
  for (const ext of extensions) {
15
- const fullPath = path.resolve(cwd, basePath + ext);
16
- if (fs.existsSync(fullPath)) {
21
+ const fullPath = path_1.default.resolve(cwd, basePath + ext);
22
+ if (fs_1.default.existsSync(fullPath)) {
17
23
  return fullPath;
18
24
  }
19
25
  // Also check for index files in directories
20
- const indexPath = path.resolve(cwd, basePath, "index" + ext);
21
- if (fs.existsSync(indexPath)) {
26
+ const indexPath = path_1.default.resolve(cwd, basePath, "index" + ext);
27
+ if (fs_1.default.existsSync(indexPath)) {
22
28
  return indexPath;
23
29
  }
24
30
  }
25
31
  }
26
32
  // Fallback to example if not found (for internal framework dev) or throw error
27
33
  // For now, we'll try the example paths as a last resort before failing
28
- const exampleClient = path.resolve(cwd, "src/example/client/index.tsx");
29
- const exampleServer = path.resolve(cwd, "src/example/server/index.ts");
34
+ const exampleClient = path_1.default.resolve(cwd, "src/example/client/index.tsx");
35
+ const exampleServer = path_1.default.resolve(cwd, "src/example/server/index.ts");
30
36
  if (searchPaths.some((p) => p.includes("client")) &&
31
- fs.existsSync(exampleClient))
37
+ fs_1.default.existsSync(exampleClient))
32
38
  return exampleClient;
33
39
  if (searchPaths.some((p) => p.includes("server")) &&
34
- fs.existsSync(exampleServer))
40
+ fs_1.default.existsSync(exampleServer))
35
41
  return exampleServer;
36
42
  throw new Error(`Could not find entry point. Searched in: ${searchPaths.join(", ")}`);
37
43
  };
38
- export const createClientConfig = () => {
44
+ const getViewsLoaderPath = () => {
45
+ const viewsDir = path_1.default.resolve(cwd, "src/views");
46
+ const hasViews = fs_1.default.existsSync(viewsDir);
47
+ const viewsLoaderPath = path_1.default.resolve(__dirname, "../../node_modules/.cache/arcanajs/views-loader.js");
48
+ // Ensure cache directory exists
49
+ const cacheDir = path_1.default.dirname(viewsLoaderPath);
50
+ if (!fs_1.default.existsSync(cacheDir)) {
51
+ fs_1.default.mkdirSync(cacheDir, { recursive: true });
52
+ }
53
+ // Generate the loader file
54
+ const loaderContent = hasViews
55
+ ? `module.exports = require.context('${viewsDir}', true, /\\.(tsx|jsx)$/);`
56
+ : `module.exports = null;`;
57
+ fs_1.default.writeFileSync(viewsLoaderPath, loaderContent);
58
+ return viewsLoaderPath;
59
+ };
60
+ const createClientConfig = () => {
39
61
  const isProduction = process.env.NODE_ENV === "production";
62
+ const viewsLoaderPath = getViewsLoaderPath();
40
63
  const clientEntry = findEntry([
41
64
  "src/client",
42
65
  "src/client/index",
@@ -50,7 +73,7 @@ export const createClientConfig = () => {
50
73
  client: clientEntry,
51
74
  },
52
75
  output: {
53
- path: path.resolve(cwd, "dist/public"),
76
+ path: path_1.default.resolve(cwd, "dist/public"),
54
77
  filename: isProduction
55
78
  ? "[name].[contenthash].bundle.js"
56
79
  : "[name].bundle.js",
@@ -59,9 +82,12 @@ export const createClientConfig = () => {
59
82
  },
60
83
  resolve: {
61
84
  extensions: [".ts", ".tsx", ".js", ".jsx"],
85
+ alias: {
86
+ "arcana-views": viewsLoaderPath,
87
+ },
62
88
  },
63
89
  resolveLoader: {
64
- modules: ["node_modules", path.resolve(__dirname, "../../node_modules")],
90
+ modules: ["node_modules", path_1.default.resolve(__dirname, "../../node_modules")],
65
91
  },
66
92
  module: {
67
93
  rules: [
@@ -86,10 +112,22 @@ export const createClientConfig = () => {
86
112
  test: /\.css$/,
87
113
  use: [
88
114
  isProduction
89
- ? MiniCssExtractPlugin.loader
115
+ ? mini_css_extract_plugin_1.default.loader
90
116
  : resolveLoader("style-loader"),
91
- resolveLoader("css-loader"),
92
- resolveLoader("postcss-loader"),
117
+ {
118
+ loader: resolveLoader("css-loader"),
119
+ options: {
120
+ importLoaders: 1,
121
+ },
122
+ },
123
+ {
124
+ loader: resolveLoader("postcss-loader"),
125
+ options: {
126
+ postcssOptions: {
127
+ config: path_1.default.resolve(cwd, "postcss.config.js"),
128
+ },
129
+ },
130
+ },
93
131
  ],
94
132
  },
95
133
  {
@@ -99,9 +137,9 @@ export const createClientConfig = () => {
99
137
  ],
100
138
  },
101
139
  plugins: [
102
- new CleanWebpackPlugin(),
103
- new HtmlWebpackPlugin({
104
- template: path.resolve(__dirname, "../lib/server/default-index.html"),
140
+ new clean_webpack_plugin_1.CleanWebpackPlugin(),
141
+ new html_webpack_plugin_1.default({
142
+ template: path_1.default.resolve(__dirname, "../lib/server/default-index.html"),
105
143
  filename: "index.html",
106
144
  inject: "body",
107
145
  minify: isProduction
@@ -119,7 +157,7 @@ export const createClientConfig = () => {
119
157
  }
120
158
  : false,
121
159
  }),
122
- new MiniCssExtractPlugin({
160
+ new mini_css_extract_plugin_1.default({
123
161
  filename: isProduction ? "[name].[contenthash].css" : "[name].css",
124
162
  }),
125
163
  ],
@@ -127,48 +165,52 @@ export const createClientConfig = () => {
127
165
  splitChunks: {
128
166
  chunks: "all",
129
167
  cacheGroups: {
130
- vendor: {
168
+ defaultVendors: {
131
169
  test: /[\\/]node_modules[\\/]/,
132
- name: "vendors",
170
+ priority: -10,
171
+ reuseExistingChunk: true,
172
+ },
173
+ default: {
174
+ minChunks: 2,
175
+ priority: -20,
176
+ reuseExistingChunk: true,
177
+ },
178
+ react: {
179
+ test: /[\\/]node_modules[\\/](react|react-dom|scheduler)[\\/]/,
180
+ name: "react-vendor",
133
181
  chunks: "all",
182
+ priority: 10,
134
183
  },
135
184
  },
136
185
  },
137
186
  },
187
+ performance: {
188
+ maxEntrypointSize: 512000,
189
+ maxAssetSize: 512000,
190
+ hints: isProduction ? "warning" : false,
191
+ },
138
192
  devtool: isProduction ? "source-map" : "eval-source-map",
139
193
  };
140
194
  };
141
- export const createServerConfig = () => {
195
+ exports.createClientConfig = createClientConfig;
196
+ const createServerConfig = () => {
142
197
  const isProduction = process.env.NODE_ENV === "production";
143
198
  const serverEntry = findEntry([
144
199
  "src/server",
145
200
  "src/server/index",
146
201
  "src/server/main",
147
202
  ]);
148
- // View Injection Logic
149
- const viewsDir = path.resolve(cwd, "src/views");
150
- const hasViews = fs.existsSync(viewsDir);
151
- const viewsLoaderPath = path.resolve(__dirname, "../../node_modules/.cache/arcanajs/views-loader.js");
152
- // Ensure cache directory exists
153
- const cacheDir = path.dirname(viewsLoaderPath);
154
- if (!fs.existsSync(cacheDir)) {
155
- fs.mkdirSync(cacheDir, { recursive: true });
156
- }
157
- // Generate the loader file
158
- const loaderContent = hasViews
159
- ? `module.exports = require.context('${viewsDir}', true, /\\.(tsx|jsx)$/);`
160
- : `module.exports = null;`;
161
- fs.writeFileSync(viewsLoaderPath, loaderContent);
203
+ const viewsLoaderPath = getViewsLoaderPath();
162
204
  return {
163
205
  mode: isProduction ? "production" : "development",
164
206
  target: "node",
165
207
  entry: serverEntry,
166
208
  output: {
167
- path: path.resolve(cwd, "dist"),
209
+ path: path_1.default.resolve(cwd, "dist"),
168
210
  filename: "server.js",
169
211
  },
170
212
  externals: [
171
- nodeExternals({
213
+ (0, webpack_node_externals_1.default)({
172
214
  allowlist: [/^arcanajs/],
173
215
  }),
174
216
  ],
@@ -179,7 +221,7 @@ export const createServerConfig = () => {
179
221
  },
180
222
  },
181
223
  resolveLoader: {
182
- modules: ["node_modules", path.resolve(__dirname, "../../node_modules")],
224
+ modules: ["node_modules", path_1.default.resolve(__dirname, "../../node_modules")],
183
225
  },
184
226
  module: {
185
227
  rules: [
@@ -216,3 +258,4 @@ export const createServerConfig = () => {
216
258
  // devtool: isProduction ? "source-map" : "eval-source-map",
217
259
  };
218
260
  };
261
+ exports.createServerConfig = createServerConfig;
@@ -1,8 +1,16 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { hydrateRoot } from "react-dom/client";
3
- import { HeadContext } from "../shared/context/HeadContext";
4
- import { ArcanaJSApp } from "../shared/core/ArcanaJSApp";
5
- export const hydrateArcanaJS = (viewsOrContext, layout) => {
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.hydrateArcanaJS = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const client_1 = require("react-dom/client");
9
+ const HeadContext_1 = require("../shared/context/HeadContext");
10
+ const ArcanaJSApp_1 = require("../shared/core/ArcanaJSApp");
11
+ const ErrorPage_1 = __importDefault(require("../shared/views/ErrorPage"));
12
+ const NotFoundPage_1 = __importDefault(require("../shared/views/NotFoundPage"));
13
+ const hydrateArcanaJS = (viewsOrContext, layout) => {
6
14
  let views = {};
7
15
  if (viewsOrContext.keys && typeof viewsOrContext.keys === "function") {
8
16
  viewsOrContext.keys().forEach((key) => {
@@ -13,8 +21,15 @@ export const hydrateArcanaJS = (viewsOrContext, layout) => {
13
21
  else {
14
22
  views = viewsOrContext;
15
23
  }
24
+ // Add default error views if not present
25
+ if (!views["NotFoundPage"]) {
26
+ views["NotFoundPage"] = NotFoundPage_1.default;
27
+ }
28
+ if (!views["ErrorPage"]) {
29
+ views["ErrorPage"] = ErrorPage_1.default;
30
+ }
16
31
  const container = document.getElementById("root");
17
- const dataScript = document.getElementById("__ArcanaJS_DATA__");
32
+ const dataScript = document.getElementById("__ARCANAJS_DATA__");
18
33
  // Client-side HeadManager (noop for push, as Head handles client updates via useEffect)
19
34
  const headManager = {
20
35
  tags: [],
@@ -23,10 +38,11 @@ export const hydrateArcanaJS = (viewsOrContext, layout) => {
23
38
  if (container && dataScript) {
24
39
  try {
25
40
  const { page, data, params, csrfToken } = JSON.parse(dataScript.textContent || "{}");
26
- hydrateRoot(container, _jsx(HeadContext.Provider, { value: headManager, children: _jsx(ArcanaJSApp, { initialPage: page, initialData: data, initialParams: params, csrfToken: csrfToken, views: views, layout: layout }) }));
41
+ (0, client_1.hydrateRoot)(container, (0, jsx_runtime_1.jsx)(HeadContext_1.HeadContext.Provider, { value: headManager, children: (0, jsx_runtime_1.jsx)(ArcanaJSApp_1.ArcanaJSApp, { initialPage: page, initialData: data, initialParams: params, csrfToken: csrfToken, views: views, layout: layout }) }));
27
42
  }
28
43
  catch (e) {
29
44
  console.error("Failed to parse initial data", e);
30
45
  }
31
46
  }
32
47
  };
48
+ exports.hydrateArcanaJS = hydrateArcanaJS;
@@ -1,4 +1,3 @@
1
- export * from "./client";
2
1
  export * from "./shared/components/Body";
3
2
  export * from "./shared/components/Head";
4
3
  export * from "./shared/components/Link";
@@ -8,10 +7,11 @@ export * from "./shared/context/HeadContext";
8
7
  export * from "./shared/context/PageContext";
9
8
  export * from "./shared/context/RouterContext";
10
9
  export * from "./shared/core/ArcanaJSApp";
11
- export * from "./shared/hooks/useDynamicComponents";
12
10
  export * from "./shared/hooks/useHead";
13
11
  export * from "./shared/hooks/useLocation";
14
12
  export * from "./shared/hooks/usePage";
15
13
  export * from "./shared/hooks/useParams";
16
14
  export * from "./shared/hooks/useQuery";
17
15
  export * from "./shared/hooks/useRouter";
16
+ export { default as ErrorPage } from "./shared/views/ErrorPage";
17
+ export { default as NotFoundPage } from "./shared/views/NotFoundPage";