arcanajs 2.1.5 → 2.1.6
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.
- package/framework/cli/index.js +16 -21
- package/framework/cli/webpack.config.js +33 -41
- package/framework/lib/client/index.js +6 -10
- package/framework/lib/index.js +17 -33
- package/framework/lib/server/ArcanaJSMiddleware.js +10 -17
- package/framework/lib/server/ArcanaJSServer.js +29 -36
- package/framework/lib/server/ControllerBinder.js +1 -4
- package/framework/lib/server/CsrfMiddleware.js +3 -10
- package/framework/lib/server/DynamicRouter.js +1 -5
- package/framework/lib/server/ResponseHandlerMiddleware.js +1 -5
- package/framework/lib/server/Router.js +7 -15
- package/framework/lib/server.js +6 -28
- package/framework/lib/shared/components/Body.js +3 -7
- package/framework/lib/shared/components/Head.js +10 -47
- package/framework/lib/shared/components/Link.js +5 -9
- package/framework/lib/shared/components/NavLink.js +6 -10
- package/framework/lib/shared/components/Page.js +5 -9
- package/framework/lib/shared/context/HeadContext.js +2 -5
- package/framework/lib/shared/context/PageContext.js +2 -5
- package/framework/lib/shared/context/RouterContext.js +5 -9
- package/framework/lib/shared/core/ArcanaJSApp.js +14 -18
- package/framework/lib/shared/hooks/useDynamicComponents.js +4 -8
- package/framework/lib/shared/hooks/useHead.d.ts +1 -1
- package/framework/lib/shared/hooks/useHead.js +3 -7
- package/framework/lib/shared/hooks/useLocation.js +3 -7
- package/framework/lib/shared/hooks/usePage.js +3 -7
- package/framework/lib/shared/hooks/useParams.js +4 -8
- package/framework/lib/shared/hooks/useQuery.js +3 -7
- package/framework/lib/shared/hooks/useRouter.d.ts +1 -1
- package/framework/lib/shared/hooks/useRouter.js +4 -8
- package/framework/lib/shared/utils/createSingletonContext.js +3 -6
- package/package.json +2 -2
package/framework/cli/index.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const child_process_1 = require("child_process");
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const webpack_1 = __importDefault(require("webpack"));
|
|
9
|
-
const webpack_config_1 = require("./webpack.config");
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import webpack from "webpack";
|
|
4
|
+
import { createClientConfig, createServerConfig } from "./webpack.config";
|
|
10
5
|
const args = process.argv.slice(2);
|
|
11
6
|
const command = args[0];
|
|
12
7
|
if (!command) {
|
|
@@ -34,8 +29,8 @@ const startDevServer = () => {
|
|
|
34
29
|
if (serverProcess) {
|
|
35
30
|
serverProcess.kill();
|
|
36
31
|
}
|
|
37
|
-
const serverPath =
|
|
38
|
-
serverProcess =
|
|
32
|
+
const serverPath = path.resolve(process.cwd(), "dist/server.js");
|
|
33
|
+
serverProcess = spawn("node", [serverPath], { stdio: "inherit" });
|
|
39
34
|
serverProcess.on("close", (code) => {
|
|
40
35
|
if (code !== 0 && code !== null) {
|
|
41
36
|
console.error(`Dev server exited with code ${code}`);
|
|
@@ -57,11 +52,11 @@ const watchCompiler = (compiler, onBuildComplete) => {
|
|
|
57
52
|
const build = async () => {
|
|
58
53
|
process.env.NODE_ENV = "production";
|
|
59
54
|
console.log("Building for production...");
|
|
60
|
-
const clientConfig =
|
|
61
|
-
const serverConfig =
|
|
55
|
+
const clientConfig = createClientConfig();
|
|
56
|
+
const serverConfig = createServerConfig();
|
|
62
57
|
try {
|
|
63
|
-
await runCompiler((
|
|
64
|
-
await runCompiler((
|
|
58
|
+
await runCompiler(webpack(clientConfig));
|
|
59
|
+
await runCompiler(webpack(serverConfig));
|
|
65
60
|
console.log("Build complete.");
|
|
66
61
|
}
|
|
67
62
|
catch (error) {
|
|
@@ -72,21 +67,21 @@ const build = async () => {
|
|
|
72
67
|
const dev = async () => {
|
|
73
68
|
process.env.NODE_ENV = "development";
|
|
74
69
|
console.log("Starting development server...");
|
|
75
|
-
const clientConfig =
|
|
76
|
-
const serverConfig =
|
|
70
|
+
const clientConfig = createClientConfig();
|
|
71
|
+
const serverConfig = createServerConfig();
|
|
77
72
|
// Watch client
|
|
78
|
-
watchCompiler((
|
|
73
|
+
watchCompiler(webpack(clientConfig));
|
|
79
74
|
// Watch server and restart on build
|
|
80
|
-
watchCompiler((
|
|
75
|
+
watchCompiler(webpack(serverConfig), () => {
|
|
81
76
|
console.log("Server build complete. Restarting server...");
|
|
82
77
|
startDevServer();
|
|
83
78
|
});
|
|
84
79
|
};
|
|
85
80
|
const start = () => {
|
|
86
81
|
process.env.NODE_ENV = "production";
|
|
87
|
-
const serverPath =
|
|
82
|
+
const serverPath = path.resolve(process.cwd(), "dist/server.js");
|
|
88
83
|
console.log(`Starting server at ${serverPath}...`);
|
|
89
|
-
const child =
|
|
84
|
+
const child = spawn("node", [serverPath], { stdio: "inherit" });
|
|
90
85
|
child.on("close", (code) => {
|
|
91
86
|
process.exit(code || 0);
|
|
92
87
|
});
|
|
@@ -1,47 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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"));
|
|
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";
|
|
12
6
|
const cwd = process.cwd();
|
|
13
7
|
// Helper to resolve loaders from the framework's node_modules
|
|
14
8
|
const resolveLoader = (loader) => require.resolve(loader);
|
|
15
|
-
|
|
9
|
+
import fs from "fs";
|
|
16
10
|
// Helper to find entry file with supported extensions
|
|
17
11
|
const findEntry = (searchPaths) => {
|
|
18
12
|
const extensions = [".ts", ".tsx", ".js", ".jsx"];
|
|
19
13
|
for (const basePath of searchPaths) {
|
|
20
14
|
for (const ext of extensions) {
|
|
21
|
-
const fullPath =
|
|
22
|
-
if (
|
|
15
|
+
const fullPath = path.resolve(cwd, basePath + ext);
|
|
16
|
+
if (fs.existsSync(fullPath)) {
|
|
23
17
|
return fullPath;
|
|
24
18
|
}
|
|
25
19
|
// Also check for index files in directories
|
|
26
|
-
const indexPath =
|
|
27
|
-
if (
|
|
20
|
+
const indexPath = path.resolve(cwd, basePath, "index" + ext);
|
|
21
|
+
if (fs.existsSync(indexPath)) {
|
|
28
22
|
return indexPath;
|
|
29
23
|
}
|
|
30
24
|
}
|
|
31
25
|
}
|
|
32
26
|
// Fallback to example if not found (for internal framework dev) or throw error
|
|
33
27
|
// For now, we'll try the example paths as a last resort before failing
|
|
34
|
-
const exampleClient =
|
|
35
|
-
const exampleServer =
|
|
28
|
+
const exampleClient = path.resolve(cwd, "src/example/client/index.tsx");
|
|
29
|
+
const exampleServer = path.resolve(cwd, "src/example/server/index.ts");
|
|
36
30
|
if (searchPaths.some((p) => p.includes("client")) &&
|
|
37
|
-
|
|
31
|
+
fs.existsSync(exampleClient))
|
|
38
32
|
return exampleClient;
|
|
39
33
|
if (searchPaths.some((p) => p.includes("server")) &&
|
|
40
|
-
|
|
34
|
+
fs.existsSync(exampleServer))
|
|
41
35
|
return exampleServer;
|
|
42
36
|
throw new Error(`Could not find entry point. Searched in: ${searchPaths.join(", ")}`);
|
|
43
37
|
};
|
|
44
|
-
const createClientConfig = () => {
|
|
38
|
+
export const createClientConfig = () => {
|
|
45
39
|
const isProduction = process.env.NODE_ENV === "production";
|
|
46
40
|
const clientEntry = findEntry([
|
|
47
41
|
"src/client",
|
|
@@ -56,7 +50,7 @@ const createClientConfig = () => {
|
|
|
56
50
|
client: clientEntry,
|
|
57
51
|
},
|
|
58
52
|
output: {
|
|
59
|
-
path:
|
|
53
|
+
path: path.resolve(cwd, "dist/public"),
|
|
60
54
|
filename: isProduction
|
|
61
55
|
? "[name].[contenthash].bundle.js"
|
|
62
56
|
: "[name].bundle.js",
|
|
@@ -67,7 +61,7 @@ const createClientConfig = () => {
|
|
|
67
61
|
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
68
62
|
},
|
|
69
63
|
resolveLoader: {
|
|
70
|
-
modules: ["node_modules",
|
|
64
|
+
modules: ["node_modules", path.resolve(__dirname, "../../node_modules")],
|
|
71
65
|
},
|
|
72
66
|
module: {
|
|
73
67
|
rules: [
|
|
@@ -92,7 +86,7 @@ const createClientConfig = () => {
|
|
|
92
86
|
test: /\.css$/,
|
|
93
87
|
use: [
|
|
94
88
|
isProduction
|
|
95
|
-
?
|
|
89
|
+
? MiniCssExtractPlugin.loader
|
|
96
90
|
: resolveLoader("style-loader"),
|
|
97
91
|
resolveLoader("css-loader"),
|
|
98
92
|
resolveLoader("postcss-loader"),
|
|
@@ -105,9 +99,9 @@ const createClientConfig = () => {
|
|
|
105
99
|
],
|
|
106
100
|
},
|
|
107
101
|
plugins: [
|
|
108
|
-
new
|
|
109
|
-
new
|
|
110
|
-
template:
|
|
102
|
+
new CleanWebpackPlugin(),
|
|
103
|
+
new HtmlWebpackPlugin({
|
|
104
|
+
template: path.resolve(__dirname, "../lib/server/default-index.html"),
|
|
111
105
|
filename: "index.html",
|
|
112
106
|
inject: "body",
|
|
113
107
|
minify: isProduction
|
|
@@ -125,7 +119,7 @@ const createClientConfig = () => {
|
|
|
125
119
|
}
|
|
126
120
|
: false,
|
|
127
121
|
}),
|
|
128
|
-
new
|
|
122
|
+
new MiniCssExtractPlugin({
|
|
129
123
|
filename: isProduction ? "[name].[contenthash].css" : "[name].css",
|
|
130
124
|
}),
|
|
131
125
|
],
|
|
@@ -144,8 +138,7 @@ const createClientConfig = () => {
|
|
|
144
138
|
devtool: isProduction ? "source-map" : "eval-source-map",
|
|
145
139
|
};
|
|
146
140
|
};
|
|
147
|
-
|
|
148
|
-
const createServerConfig = () => {
|
|
141
|
+
export const createServerConfig = () => {
|
|
149
142
|
const isProduction = process.env.NODE_ENV === "production";
|
|
150
143
|
const serverEntry = findEntry([
|
|
151
144
|
"src/server",
|
|
@@ -153,29 +146,29 @@ const createServerConfig = () => {
|
|
|
153
146
|
"src/server/main",
|
|
154
147
|
]);
|
|
155
148
|
// View Injection Logic
|
|
156
|
-
const viewsDir =
|
|
157
|
-
const hasViews =
|
|
158
|
-
const viewsLoaderPath =
|
|
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");
|
|
159
152
|
// Ensure cache directory exists
|
|
160
|
-
const cacheDir =
|
|
161
|
-
if (!
|
|
162
|
-
|
|
153
|
+
const cacheDir = path.dirname(viewsLoaderPath);
|
|
154
|
+
if (!fs.existsSync(cacheDir)) {
|
|
155
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
163
156
|
}
|
|
164
157
|
// Generate the loader file
|
|
165
158
|
const loaderContent = hasViews
|
|
166
159
|
? `module.exports = require.context('${viewsDir}', true, /\\.(tsx|jsx)$/);`
|
|
167
160
|
: `module.exports = null;`;
|
|
168
|
-
|
|
161
|
+
fs.writeFileSync(viewsLoaderPath, loaderContent);
|
|
169
162
|
return {
|
|
170
163
|
mode: isProduction ? "production" : "development",
|
|
171
164
|
target: "node",
|
|
172
165
|
entry: serverEntry,
|
|
173
166
|
output: {
|
|
174
|
-
path:
|
|
167
|
+
path: path.resolve(cwd, "dist"),
|
|
175
168
|
filename: "server.js",
|
|
176
169
|
},
|
|
177
170
|
externals: [
|
|
178
|
-
(
|
|
171
|
+
nodeExternals({
|
|
179
172
|
allowlist: [/^arcanajs/],
|
|
180
173
|
}),
|
|
181
174
|
],
|
|
@@ -186,7 +179,7 @@ const createServerConfig = () => {
|
|
|
186
179
|
},
|
|
187
180
|
},
|
|
188
181
|
resolveLoader: {
|
|
189
|
-
modules: ["node_modules",
|
|
182
|
+
modules: ["node_modules", path.resolve(__dirname, "../../node_modules")],
|
|
190
183
|
},
|
|
191
184
|
module: {
|
|
192
185
|
rules: [
|
|
@@ -223,4 +216,3 @@ const createServerConfig = () => {
|
|
|
223
216
|
// devtool: isProduction ? "source-map" : "eval-source-map",
|
|
224
217
|
};
|
|
225
218
|
};
|
|
226
|
-
exports.createServerConfig = createServerConfig;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const HeadContext_1 = require("../shared/context/HeadContext");
|
|
7
|
-
const ArcanaJSApp_1 = require("../shared/core/ArcanaJSApp");
|
|
8
|
-
const hydrateArcanaJS = (viewsOrContext, layout) => {
|
|
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) => {
|
|
9
6
|
let views = {};
|
|
10
7
|
if (viewsOrContext.keys && typeof viewsOrContext.keys === "function") {
|
|
11
8
|
viewsOrContext.keys().forEach((key) => {
|
|
@@ -26,11 +23,10 @@ const hydrateArcanaJS = (viewsOrContext, layout) => {
|
|
|
26
23
|
if (container && dataScript) {
|
|
27
24
|
try {
|
|
28
25
|
const { page, data, params, csrfToken } = JSON.parse(dataScript.textContent || "{}");
|
|
29
|
-
|
|
26
|
+
hydrateRoot(container, _jsx(HeadContext.Provider, { value: headManager, children: _jsx(ArcanaJSApp, { initialPage: page, initialData: data, initialParams: params, csrfToken: csrfToken, views: views, layout: layout }) }));
|
|
30
27
|
}
|
|
31
28
|
catch (e) {
|
|
32
29
|
console.error("Failed to parse initial data", e);
|
|
33
30
|
}
|
|
34
31
|
}
|
|
35
32
|
};
|
|
36
|
-
exports.hydrateArcanaJS = hydrateArcanaJS;
|
package/framework/lib/index.js
CHANGED
|
@@ -1,33 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
__exportStar(require("./shared/components/Body"), exports);
|
|
19
|
-
__exportStar(require("./shared/components/Head"), exports);
|
|
20
|
-
__exportStar(require("./shared/components/Link"), exports);
|
|
21
|
-
__exportStar(require("./shared/components/NavLink"), exports);
|
|
22
|
-
__exportStar(require("./shared/components/Page"), exports);
|
|
23
|
-
__exportStar(require("./shared/context/HeadContext"), exports);
|
|
24
|
-
__exportStar(require("./shared/context/PageContext"), exports);
|
|
25
|
-
__exportStar(require("./shared/context/RouterContext"), exports);
|
|
26
|
-
__exportStar(require("./shared/core/ArcanaJSApp"), exports);
|
|
27
|
-
__exportStar(require("./shared/hooks/useDynamicComponents"), exports);
|
|
28
|
-
__exportStar(require("./shared/hooks/useHead"), exports);
|
|
29
|
-
__exportStar(require("./shared/hooks/useLocation"), exports);
|
|
30
|
-
__exportStar(require("./shared/hooks/usePage"), exports);
|
|
31
|
-
__exportStar(require("./shared/hooks/useParams"), exports);
|
|
32
|
-
__exportStar(require("./shared/hooks/useQuery"), exports);
|
|
33
|
-
__exportStar(require("./shared/hooks/useRouter"), exports);
|
|
1
|
+
export * from "./client";
|
|
2
|
+
export * from "./shared/components/Body";
|
|
3
|
+
export * from "./shared/components/Head";
|
|
4
|
+
export * from "./shared/components/Link";
|
|
5
|
+
export * from "./shared/components/NavLink";
|
|
6
|
+
export * from "./shared/components/Page";
|
|
7
|
+
export * from "./shared/context/HeadContext";
|
|
8
|
+
export * from "./shared/context/PageContext";
|
|
9
|
+
export * from "./shared/context/RouterContext";
|
|
10
|
+
export * from "./shared/core/ArcanaJSApp";
|
|
11
|
+
export * from "./shared/hooks/useDynamicComponents";
|
|
12
|
+
export * from "./shared/hooks/useHead";
|
|
13
|
+
export * from "./shared/hooks/useLocation";
|
|
14
|
+
export * from "./shared/hooks/usePage";
|
|
15
|
+
export * from "./shared/hooks/useParams";
|
|
16
|
+
export * from "./shared/hooks/useQuery";
|
|
17
|
+
export * from "./shared/hooks/useRouter";
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
exports.createArcanaJSMiddleware = void 0;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const react_1 = __importDefault(require("react"));
|
|
9
|
-
const server_1 = require("react-dom/server");
|
|
10
|
-
const HeadContext_1 = require("../shared/context/HeadContext");
|
|
11
|
-
const ArcanaJSApp_1 = require("../shared/core/ArcanaJSApp");
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { renderToString } from "react-dom/server";
|
|
4
|
+
import { HeadContext } from "../shared/context/HeadContext";
|
|
5
|
+
import { ArcanaJSApp } from "../shared/core/ArcanaJSApp";
|
|
12
6
|
const DEFAULT_HTML_TEMPLATE = `<!DOCTYPE html>
|
|
13
7
|
<html lang="en">
|
|
14
8
|
<head>
|
|
@@ -25,15 +19,15 @@ const DEFAULT_HTML_TEMPLATE = `<!DOCTYPE html>
|
|
|
25
19
|
const safeStringify = (obj) => {
|
|
26
20
|
return JSON.stringify(obj).replace(/</g, "\\u003c");
|
|
27
21
|
};
|
|
28
|
-
const createArcanaJSMiddleware = (options) => {
|
|
22
|
+
export const createArcanaJSMiddleware = (options) => {
|
|
29
23
|
const { views, indexFile, layout } = options;
|
|
30
24
|
let cachedIndexHtml = null;
|
|
31
25
|
const getIndexHtml = (callback) => {
|
|
32
26
|
if (process.env.NODE_ENV === "production" && cachedIndexHtml) {
|
|
33
27
|
return callback(null, cachedIndexHtml);
|
|
34
28
|
}
|
|
35
|
-
if (indexFile &&
|
|
36
|
-
|
|
29
|
+
if (indexFile && fs.existsSync(indexFile)) {
|
|
30
|
+
fs.readFile(indexFile, "utf8", (err, htmlData) => {
|
|
37
31
|
if (!err && process.env.NODE_ENV === "production") {
|
|
38
32
|
cachedIndexHtml = htmlData;
|
|
39
33
|
}
|
|
@@ -59,7 +53,7 @@ const createArcanaJSMiddleware = (options) => {
|
|
|
59
53
|
tags: headTags,
|
|
60
54
|
push: (nodes) => headTags.push(nodes),
|
|
61
55
|
};
|
|
62
|
-
const appHtml =
|
|
56
|
+
const appHtml = renderToString(React.createElement(HeadContext.Provider, { value: headManager }, React.createElement(ArcanaJSApp, {
|
|
63
57
|
initialPage: page,
|
|
64
58
|
initialData: data,
|
|
65
59
|
initialParams: params,
|
|
@@ -68,7 +62,7 @@ const createArcanaJSMiddleware = (options) => {
|
|
|
68
62
|
views: views,
|
|
69
63
|
layout: layout,
|
|
70
64
|
})));
|
|
71
|
-
const headHtml =
|
|
65
|
+
const headHtml = renderToString(React.createElement(React.Fragment, null, ...headTags));
|
|
72
66
|
getIndexHtml((err, htmlData) => {
|
|
73
67
|
if (err) {
|
|
74
68
|
console.error("Error reading index.html", err);
|
|
@@ -96,4 +90,3 @@ const createArcanaJSMiddleware = (options) => {
|
|
|
96
90
|
next();
|
|
97
91
|
};
|
|
98
92
|
};
|
|
99
|
-
exports.createArcanaJSMiddleware = createArcanaJSMiddleware;
|
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const path_1 = __importDefault(require("path"));
|
|
13
|
-
const ArcanaJSMiddleware_1 = require("./ArcanaJSMiddleware");
|
|
14
|
-
const CsrfMiddleware_1 = require("./CsrfMiddleware");
|
|
15
|
-
const DynamicRouter_1 = require("./DynamicRouter");
|
|
16
|
-
const ResponseHandlerMiddleware_1 = require("./ResponseHandlerMiddleware");
|
|
17
|
-
class ArcanaJSServer {
|
|
1
|
+
import compression from "compression";
|
|
2
|
+
import cookieParser from "cookie-parser";
|
|
3
|
+
import express from "express";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import helmet from "helmet";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { createArcanaJSMiddleware } from "./ArcanaJSMiddleware";
|
|
8
|
+
import { createCsrfMiddleware } from "./CsrfMiddleware";
|
|
9
|
+
import { createDynamicRouter } from "./DynamicRouter";
|
|
10
|
+
import { responseHandler } from "./ResponseHandlerMiddleware";
|
|
11
|
+
export class ArcanaJSServer {
|
|
18
12
|
constructor(config) {
|
|
19
13
|
this.config = config;
|
|
20
|
-
this.app = (
|
|
14
|
+
this.app = express();
|
|
21
15
|
this.initialize();
|
|
22
16
|
}
|
|
23
17
|
initialize() {
|
|
@@ -52,26 +46,26 @@ class ArcanaJSServer {
|
|
|
52
46
|
views = {};
|
|
53
47
|
}
|
|
54
48
|
// Security and Performance
|
|
55
|
-
this.app.use((
|
|
49
|
+
this.app.use(helmet({
|
|
56
50
|
contentSecurityPolicy: false,
|
|
57
51
|
}));
|
|
58
|
-
this.app.use((
|
|
59
|
-
this.app.use((
|
|
60
|
-
this.app.use(
|
|
61
|
-
this.app.use(
|
|
52
|
+
this.app.use(compression());
|
|
53
|
+
this.app.use(cookieParser());
|
|
54
|
+
this.app.use(createCsrfMiddleware());
|
|
55
|
+
this.app.use(responseHandler);
|
|
62
56
|
// Static files
|
|
63
|
-
this.app.use(
|
|
57
|
+
this.app.use(express.static(path.resolve(process.cwd(), distDir), {
|
|
64
58
|
index: false,
|
|
65
59
|
maxAge: "1y",
|
|
66
60
|
}));
|
|
67
|
-
this.app.use(
|
|
61
|
+
this.app.use(express.static(path.resolve(process.cwd(), staticDir), {
|
|
68
62
|
index: false,
|
|
69
63
|
maxAge: "1d",
|
|
70
64
|
}));
|
|
71
65
|
// ArcanaJS Middleware
|
|
72
|
-
this.app.use(
|
|
66
|
+
this.app.use(createArcanaJSMiddleware({
|
|
73
67
|
views,
|
|
74
|
-
indexFile:
|
|
68
|
+
indexFile: path.resolve(process.cwd(), indexFile),
|
|
75
69
|
layout,
|
|
76
70
|
}));
|
|
77
71
|
// Custom Routes
|
|
@@ -84,7 +78,7 @@ class ArcanaJSServer {
|
|
|
84
78
|
}
|
|
85
79
|
}
|
|
86
80
|
// Dynamic Router
|
|
87
|
-
this.app.use(
|
|
81
|
+
this.app.use(createDynamicRouter(views));
|
|
88
82
|
// 404 Fallback
|
|
89
83
|
this.app.use((req, res) => {
|
|
90
84
|
res.status(404).renderPage("NotFoundPage");
|
|
@@ -101,20 +95,20 @@ class ArcanaJSServer {
|
|
|
101
95
|
discoverViews() {
|
|
102
96
|
const views = {};
|
|
103
97
|
const viewsDir = this.config.viewsDir
|
|
104
|
-
?
|
|
105
|
-
:
|
|
98
|
+
? path.resolve(process.cwd(), this.config.viewsDir)
|
|
99
|
+
: path.resolve(process.cwd(), "src/views");
|
|
106
100
|
const traverse = (dir) => {
|
|
107
|
-
if (!
|
|
101
|
+
if (!fs.existsSync(dir))
|
|
108
102
|
return;
|
|
109
|
-
const files =
|
|
103
|
+
const files = fs.readdirSync(dir);
|
|
110
104
|
files.forEach((file) => {
|
|
111
|
-
const fullPath =
|
|
112
|
-
const stat =
|
|
105
|
+
const fullPath = path.join(dir, file);
|
|
106
|
+
const stat = fs.statSync(fullPath);
|
|
113
107
|
if (stat.isDirectory()) {
|
|
114
108
|
traverse(fullPath);
|
|
115
109
|
}
|
|
116
110
|
else if (file.endsWith(".tsx") || file.endsWith(".jsx")) {
|
|
117
|
-
const relativePath =
|
|
111
|
+
const relativePath = path.relative(viewsDir, fullPath);
|
|
118
112
|
const viewName = relativePath.replace(/\.(tsx|jsx)$/, "");
|
|
119
113
|
try {
|
|
120
114
|
// Use __non_webpack_require__ if available to avoid Webpack bundling issues
|
|
@@ -151,4 +145,3 @@ class ArcanaJSServer {
|
|
|
151
145
|
});
|
|
152
146
|
}
|
|
153
147
|
}
|
|
154
|
-
exports.ArcanaJSServer = ArcanaJSServer;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
class ControllerBinder {
|
|
1
|
+
export default class ControllerBinder {
|
|
4
2
|
static handle(controller, method) {
|
|
5
3
|
// Instantiate the controller once (Singleton pattern) for performance
|
|
6
4
|
// This assumes controllers are stateless, which is best practice.
|
|
@@ -29,4 +27,3 @@ class ControllerBinder {
|
|
|
29
27
|
};
|
|
30
28
|
}
|
|
31
29
|
}
|
|
32
|
-
exports.default = ControllerBinder;
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
|
|
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.createCsrfMiddleware = void 0;
|
|
7
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
1
|
+
import crypto from "crypto";
|
|
8
2
|
const CSRF_COOKIE_NAME = "_csrf";
|
|
9
|
-
const createCsrfMiddleware = () => {
|
|
3
|
+
export const createCsrfMiddleware = () => {
|
|
10
4
|
return (req, res, next) => {
|
|
11
5
|
// 1. Generate or retrieve token
|
|
12
6
|
let token = req.cookies[CSRF_COOKIE_NAME];
|
|
13
7
|
if (!token) {
|
|
14
|
-
token =
|
|
8
|
+
token = crypto.randomBytes(32).toString("hex");
|
|
15
9
|
res.cookie(CSRF_COOKIE_NAME, token, {
|
|
16
10
|
httpOnly: true,
|
|
17
11
|
secure: process.env.NODE_ENV === "production",
|
|
@@ -31,4 +25,3 @@ const createCsrfMiddleware = () => {
|
|
|
31
25
|
next();
|
|
32
26
|
};
|
|
33
27
|
};
|
|
34
|
-
exports.createCsrfMiddleware = createCsrfMiddleware;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createDynamicRouter = void 0;
|
|
4
|
-
const createDynamicRouter = (views) => {
|
|
1
|
+
export const createDynamicRouter = (views) => {
|
|
5
2
|
return (req, res, next) => {
|
|
6
3
|
// Remove leading slash
|
|
7
4
|
let path = req.path.substring(1);
|
|
@@ -47,4 +44,3 @@ const createDynamicRouter = (views) => {
|
|
|
47
44
|
next();
|
|
48
45
|
};
|
|
49
46
|
};
|
|
50
|
-
exports.createDynamicRouter = createDynamicRouter;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.responseHandler = void 0;
|
|
4
|
-
const responseHandler = (req, res, next) => {
|
|
1
|
+
export const responseHandler = (req, res, next) => {
|
|
5
2
|
res.success = (data = {}, message = "Success", status = 200) => {
|
|
6
3
|
return res.status(status).json({
|
|
7
4
|
success: true,
|
|
@@ -27,4 +24,3 @@ const responseHandler = (req, res, next) => {
|
|
|
27
24
|
};
|
|
28
25
|
next();
|
|
29
26
|
};
|
|
30
|
-
exports.responseHandler = responseHandler;
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Route = exports.Router = void 0;
|
|
7
|
-
const express_1 = __importDefault(require("express"));
|
|
8
|
-
const ControllerBinder_1 = __importDefault(require("./ControllerBinder"));
|
|
1
|
+
import express from "express";
|
|
2
|
+
import ControllerBinder from "./ControllerBinder";
|
|
9
3
|
/**
|
|
10
4
|
* Provides Routing syntax for defining routes with prefixes, middlewares, and groups
|
|
11
5
|
*/
|
|
12
|
-
class Router {
|
|
6
|
+
export class Router {
|
|
13
7
|
constructor() {
|
|
14
|
-
this.router =
|
|
8
|
+
this.router = express.Router();
|
|
15
9
|
this.middlewareStack = [];
|
|
16
10
|
this.prefixStack = [];
|
|
17
11
|
}
|
|
@@ -148,16 +142,15 @@ class Router {
|
|
|
148
142
|
}
|
|
149
143
|
if (Array.isArray(action) && action.length === 2) {
|
|
150
144
|
const [controller, method] = action;
|
|
151
|
-
return
|
|
145
|
+
return ControllerBinder.handle(controller, method);
|
|
152
146
|
}
|
|
153
147
|
throw new Error('Action must be a function or array [Controller, "method"]');
|
|
154
148
|
}
|
|
155
149
|
}
|
|
156
|
-
exports.Router = Router;
|
|
157
150
|
/**
|
|
158
151
|
* Static Route class for Laravel-like syntax
|
|
159
152
|
*/
|
|
160
|
-
class Route {
|
|
153
|
+
export class Route {
|
|
161
154
|
static create() {
|
|
162
155
|
return Router.create();
|
|
163
156
|
}
|
|
@@ -198,6 +191,5 @@ class Route {
|
|
|
198
191
|
this._router = new Router();
|
|
199
192
|
}
|
|
200
193
|
}
|
|
201
|
-
exports.Route = Route;
|
|
202
194
|
Route._router = new Router();
|
|
203
|
-
|
|
195
|
+
export default Route;
|
package/framework/lib/server.js
CHANGED
|
@@ -1,28 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
-
};
|
|
19
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.Route = exports.ControllerBinder = void 0;
|
|
21
|
-
__exportStar(require("./server/ArcanaJSMiddleware"), exports);
|
|
22
|
-
__exportStar(require("./server/ArcanaJSServer"), exports);
|
|
23
|
-
var ControllerBinder_1 = require("./server/ControllerBinder");
|
|
24
|
-
Object.defineProperty(exports, "ControllerBinder", { enumerable: true, get: function () { return __importDefault(ControllerBinder_1).default; } });
|
|
25
|
-
__exportStar(require("./server/DynamicRouter"), exports);
|
|
26
|
-
__exportStar(require("./server/Router"), exports);
|
|
27
|
-
var Router_1 = require("./server/Router");
|
|
28
|
-
Object.defineProperty(exports, "Route", { enumerable: true, get: function () { return __importDefault(Router_1).default; } });
|
|
1
|
+
export * from "./server/ArcanaJSMiddleware";
|
|
2
|
+
export * from "./server/ArcanaJSServer";
|
|
3
|
+
export { default as ControllerBinder } from "./server/ControllerBinder";
|
|
4
|
+
export * from "./server/DynamicRouter";
|
|
5
|
+
export * from "./server/Router";
|
|
6
|
+
export { default as Route } from "./server/Router";
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const Body = ({ children }) => {
|
|
6
|
-
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const Body = ({ children }) => {
|
|
3
|
+
return _jsx(_Fragment, { children: children });
|
|
7
4
|
};
|
|
8
|
-
exports.Body = Body;
|
|
@@ -1,58 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.Head = void 0;
|
|
37
|
-
const react_1 = __importStar(require("react"));
|
|
38
|
-
const useHead_1 = require("../hooks/useHead");
|
|
39
|
-
const Head = ({ children }) => {
|
|
40
|
-
const headManager = (0, useHead_1.useHead)();
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import { useHead } from "../hooks/useHead";
|
|
3
|
+
export const Head = ({ children }) => {
|
|
4
|
+
const headManager = useHead();
|
|
41
5
|
// Server-side: Push tags to context
|
|
42
6
|
if (typeof window === "undefined" && headManager) {
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
headManager.push(
|
|
7
|
+
React.Children.forEach(children, (child) => {
|
|
8
|
+
if (React.isValidElement(child)) {
|
|
9
|
+
headManager.push(React.cloneElement(child, {
|
|
46
10
|
"data-arcanajs-head": "true",
|
|
47
11
|
}));
|
|
48
12
|
}
|
|
49
13
|
});
|
|
50
14
|
}
|
|
51
15
|
// Client-side: Update DOM
|
|
52
|
-
|
|
16
|
+
useEffect(() => {
|
|
53
17
|
const managedElements = [];
|
|
54
|
-
|
|
55
|
-
if (
|
|
18
|
+
React.Children.forEach(children, (child) => {
|
|
19
|
+
if (React.isValidElement(child)) {
|
|
56
20
|
const reactElement = child;
|
|
57
21
|
if (reactElement.type === "title") {
|
|
58
22
|
document.title = reactElement.props.children;
|
|
@@ -122,4 +86,3 @@ const Head = ({ children }) => {
|
|
|
122
86
|
}, [children]);
|
|
123
87
|
return null;
|
|
124
88
|
};
|
|
125
|
-
exports.Head = Head;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const useRouter_1 = require("../hooks/useRouter");
|
|
6
|
-
const Link = ({ href, children, ...props }) => {
|
|
7
|
-
const { navigateTo } = (0, useRouter_1.useRouter)();
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRouter } from "../hooks/useRouter";
|
|
3
|
+
export const Link = ({ href, children, ...props }) => {
|
|
4
|
+
const { navigateTo } = useRouter();
|
|
8
5
|
const handleClick = (e) => {
|
|
9
6
|
e.preventDefault();
|
|
10
7
|
navigateTo(href);
|
|
11
8
|
};
|
|
12
|
-
return ((
|
|
9
|
+
return (_jsx("a", { href: href, onClick: handleClick, ...props, children: children }));
|
|
13
10
|
};
|
|
14
|
-
exports.Link = Link;
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const useRouter_1 = require("../hooks/useRouter");
|
|
7
|
-
const NavLink = ({ href, activeClassName = "active", className = "", exact = false, children, ...props }) => {
|
|
8
|
-
const { currentUrl } = (0, useRouter_1.useRouter)();
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Link } from "./Link";
|
|
3
|
+
import { useRouter } from "../hooks/useRouter";
|
|
4
|
+
export const NavLink = ({ href, activeClassName = "active", className = "", exact = false, children, ...props }) => {
|
|
5
|
+
const { currentUrl } = useRouter();
|
|
9
6
|
const isActive = exact ? currentUrl === href : currentUrl.startsWith(href);
|
|
10
7
|
const combinedClassName = `${className} ${isActive ? activeClassName : ""}`.trim();
|
|
11
|
-
return ((
|
|
8
|
+
return (_jsx(Link, { href: href, className: combinedClassName, ...props, children: children }));
|
|
12
9
|
};
|
|
13
|
-
exports.NavLink = NavLink;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
const Head_1 = require("./Head");
|
|
7
|
-
const Page = ({ data, title, children }) => {
|
|
8
|
-
return ((0, jsx_runtime_1.jsxs)(PageContext_1.PageContext.Provider, { value: data, children: [title && ((0, jsx_runtime_1.jsx)(Head_1.Head, { children: (0, jsx_runtime_1.jsx)("title", { children: title }) })), children] }));
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { PageContext } from "../context/PageContext";
|
|
3
|
+
import { Head } from "./Head";
|
|
4
|
+
export const Page = ({ data, title, children }) => {
|
|
5
|
+
return (_jsxs(PageContext.Provider, { value: data, children: [title && (_jsx(Head, { children: _jsx("title", { children: title }) })), children] }));
|
|
9
6
|
};
|
|
10
|
-
exports.Page = Page;
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.HeadContext = void 0;
|
|
4
|
-
const createSingletonContext_1 = require("../utils/createSingletonContext");
|
|
5
|
-
exports.HeadContext = (0, createSingletonContext_1.createSingletonContext)("HeadContext", null);
|
|
1
|
+
import { createSingletonContext } from "../utils/createSingletonContext";
|
|
2
|
+
export const HeadContext = createSingletonContext("HeadContext", null);
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.PageContext = void 0;
|
|
4
|
-
const createSingletonContext_1 = require("../utils/createSingletonContext");
|
|
5
|
-
exports.PageContext = (0, createSingletonContext_1.createSingletonContext)("PageContext", null);
|
|
1
|
+
import { createSingletonContext } from "../utils/createSingletonContext";
|
|
2
|
+
export const PageContext = createSingletonContext("PageContext", null);
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
exports.RouterContext = (0, createSingletonContext_1.createSingletonContext)("RouterContext", null);
|
|
7
|
-
const RouterProvider = ({ value, children }) => {
|
|
8
|
-
return ((0, jsx_runtime_1.jsx)(exports.RouterContext.Provider, { value: value, children: children }));
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createSingletonContext } from "../utils/createSingletonContext";
|
|
3
|
+
export const RouterContext = createSingletonContext("RouterContext", null);
|
|
4
|
+
export const RouterProvider = ({ value, children }) => {
|
|
5
|
+
return (_jsx(RouterContext.Provider, { value: value, children: children }));
|
|
9
6
|
};
|
|
10
|
-
exports.RouterProvider = RouterProvider;
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const [
|
|
10
|
-
const [data, setData] = (0, react_1.useState)(initialData);
|
|
11
|
-
const [params, setParams] = (0, react_1.useState)(initialParams);
|
|
12
|
-
const [url, setUrl] = (0, react_1.useState)(initialUrl ||
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { Page } from "../components/Page";
|
|
4
|
+
import { RouterProvider } from "../context/RouterContext";
|
|
5
|
+
export const ArcanaJSApp = ({ initialPage, initialData, initialParams = {}, initialUrl, csrfToken, views, layout: Layout, }) => {
|
|
6
|
+
const [page, setPage] = useState(initialPage);
|
|
7
|
+
const [data, setData] = useState(initialData);
|
|
8
|
+
const [params, setParams] = useState(initialParams);
|
|
9
|
+
const [url, setUrl] = useState(initialUrl ||
|
|
13
10
|
(typeof window !== "undefined" ? window.location.pathname : "/"));
|
|
14
|
-
|
|
11
|
+
useEffect(() => {
|
|
15
12
|
const handlePopState = (event) => {
|
|
16
13
|
if (event.state) {
|
|
17
14
|
setPage(event.state.page);
|
|
@@ -50,16 +47,15 @@ const ArcanaJSApp = ({ initialPage, initialData, initialParams = {}, initialUrl,
|
|
|
50
47
|
}
|
|
51
48
|
};
|
|
52
49
|
const renderPage = () => {
|
|
53
|
-
const Component = views[page] || views["NotFoundPage"] || (() => (
|
|
54
|
-
return ((
|
|
50
|
+
const Component = views[page] || views["NotFoundPage"] || (() => _jsx("div", { children: "404 Not Found" }));
|
|
51
|
+
return (_jsx(Page, { data: data, children: _jsx(Component, { data: data, navigateTo: navigateTo, params: params }) }));
|
|
55
52
|
};
|
|
56
53
|
const content = renderPage();
|
|
57
|
-
return ((
|
|
54
|
+
return (_jsx(RouterProvider, { value: {
|
|
58
55
|
navigateTo,
|
|
59
56
|
currentPage: page,
|
|
60
57
|
currentUrl: url,
|
|
61
58
|
params,
|
|
62
59
|
csrfToken,
|
|
63
|
-
}, children: Layout ? (
|
|
60
|
+
}, children: Layout ? _jsx(Layout, { children: content }) : _jsx(_Fragment, { children: content }) }));
|
|
64
61
|
};
|
|
65
|
-
exports.ArcanaJSApp = ArcanaJSApp;
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const useDynamicComponents = (loader) => {
|
|
6
|
-
const [component, setComponent] = (0, react_1.useState)(null);
|
|
7
|
-
(0, react_1.useEffect)(() => {
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
export const useDynamicComponents = (loader) => {
|
|
3
|
+
const [component, setComponent] = useState(null);
|
|
4
|
+
useEffect(() => {
|
|
8
5
|
let mounted = true;
|
|
9
6
|
loader().then((mod) => {
|
|
10
7
|
if (mounted) {
|
|
@@ -17,4 +14,3 @@ const useDynamicComponents = (loader) => {
|
|
|
17
14
|
}, []); // loader dependency omitted to avoid loops if loader is inline
|
|
18
15
|
return component;
|
|
19
16
|
};
|
|
20
|
-
exports.useDynamicComponents = useDynamicComponents;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const useHead: () => import("
|
|
1
|
+
export declare const useHead: () => import("../..").HeadManager | null;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const react_1 = require("react");
|
|
5
|
-
const HeadContext_1 = require("../context/HeadContext");
|
|
6
|
-
const useHead = () => (0, react_1.useContext)(HeadContext_1.HeadContext);
|
|
7
|
-
exports.useHead = useHead;
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { HeadContext } from "../context/HeadContext";
|
|
3
|
+
export const useHead = () => useContext(HeadContext);
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const useRouter_1 = require("./useRouter");
|
|
5
|
-
const useLocation = () => {
|
|
6
|
-
const { currentUrl } = (0, useRouter_1.useRouter)();
|
|
1
|
+
import { useRouter } from "./useRouter";
|
|
2
|
+
export const useLocation = () => {
|
|
3
|
+
const { currentUrl } = useRouter();
|
|
7
4
|
return {
|
|
8
5
|
pathname: currentUrl,
|
|
9
6
|
search: typeof window !== "undefined" ? window.location.search : "",
|
|
10
7
|
hash: typeof window !== "undefined" ? window.location.hash : "",
|
|
11
8
|
};
|
|
12
9
|
};
|
|
13
|
-
exports.useLocation = useLocation;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const react_1 = require("react");
|
|
5
|
-
const PageContext_1 = require("../context/PageContext");
|
|
6
|
-
const usePage = () => (0, react_1.useContext)(PageContext_1.PageContext);
|
|
7
|
-
exports.usePage = usePage;
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { PageContext } from "../context/PageContext";
|
|
3
|
+
export const usePage = () => useContext(PageContext);
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const RouterContext_1 = require("../context/RouterContext");
|
|
6
|
-
const useParams = () => {
|
|
7
|
-
const context = (0, react_1.useContext)(RouterContext_1.RouterContext);
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { RouterContext } from "../context/RouterContext";
|
|
3
|
+
export const useParams = () => {
|
|
4
|
+
const context = useContext(RouterContext);
|
|
8
5
|
if (!context) {
|
|
9
6
|
throw new Error("useParams must be used within an ArcanaJSApp");
|
|
10
7
|
}
|
|
11
8
|
return context.params;
|
|
12
9
|
};
|
|
13
|
-
exports.useParams = useParams;
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const useLocation_1 = require("./useLocation");
|
|
5
|
-
const useQuery = () => {
|
|
6
|
-
const { search } = (0, useLocation_1.useLocation)();
|
|
1
|
+
import { useLocation } from "./useLocation";
|
|
2
|
+
export const useQuery = () => {
|
|
3
|
+
const { search } = useLocation();
|
|
7
4
|
return new URLSearchParams(search);
|
|
8
5
|
};
|
|
9
|
-
exports.useQuery = useQuery;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const useRouter: () => import("
|
|
1
|
+
export declare const useRouter: () => import("../..").RouterContextType;
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const RouterContext_1 = require("../context/RouterContext");
|
|
6
|
-
const useRouter = () => {
|
|
7
|
-
const context = (0, react_1.useContext)(RouterContext_1.RouterContext);
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { RouterContext } from "../context/RouterContext";
|
|
3
|
+
export const useRouter = () => {
|
|
4
|
+
const context = useContext(RouterContext);
|
|
8
5
|
if (!context) {
|
|
9
6
|
throw new Error("useRouter must be used within an ArcanaJSApp");
|
|
10
7
|
}
|
|
11
8
|
return context;
|
|
12
9
|
};
|
|
13
|
-
exports.useRouter = useRouter;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createSingletonContext = createSingletonContext;
|
|
4
|
-
const react_1 = require("react");
|
|
1
|
+
import { createContext } from "react";
|
|
5
2
|
/**
|
|
6
3
|
* Creates a React Context that persists across multiple module loads (Webpack bundles vs Node require).
|
|
7
4
|
* This is essential for SSR applications where the server bundle and dynamically loaded views
|
|
@@ -11,11 +8,11 @@ const react_1 = require("react");
|
|
|
11
8
|
* @param defaultValue The default value for the context
|
|
12
9
|
* @returns A React Context instance (singleton)
|
|
13
10
|
*/
|
|
14
|
-
function createSingletonContext(key, defaultValue) {
|
|
11
|
+
export function createSingletonContext(key, defaultValue) {
|
|
15
12
|
const globalAny = global;
|
|
16
13
|
const symbolKey = Symbol.for(`ARCANAJS_CONTEXT_${key}`);
|
|
17
14
|
if (!globalAny[symbolKey]) {
|
|
18
|
-
globalAny[symbolKey] =
|
|
15
|
+
globalAny[symbolKey] = createContext(defaultValue);
|
|
19
16
|
}
|
|
20
17
|
return globalAny[symbolKey];
|
|
21
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arcanajs",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.6",
|
|
4
4
|
"description": "ArcanaJS Framework",
|
|
5
5
|
"main": "framework/lib/index.js",
|
|
6
6
|
"types": "framework/lib/index.d.ts",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"bin"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "tsc -p tsconfig.
|
|
19
|
+
"build": "tsc -p tsconfig.json && cp src/lib/server/default-index.html framework/lib/server/ && cp src/lib/global.d.ts framework/lib/",
|
|
20
20
|
"build:app": "node bin/arcanajs.js build",
|
|
21
21
|
"dev:app": "node bin/arcanajs.js dev",
|
|
22
22
|
"start:app": "node bin/arcanajs.js start",
|