arcanajs 2.1.4 → 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 +42 -44
- package/framework/lib/client/index.js +6 -14
- 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 -10
- package/framework/lib/shared/components/Head.js +10 -47
- package/framework/lib/shared/components/Link.js +5 -12
- package/framework/lib/shared/components/NavLink.js +6 -13
- package/framework/lib/shared/components/Page.js +5 -15
- 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 -12
- package/framework/lib/shared/core/ArcanaJSApp.js +14 -51
- 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: [
|
|
@@ -79,7 +73,10 @@ const createClientConfig = () => {
|
|
|
79
73
|
options: {
|
|
80
74
|
presets: [
|
|
81
75
|
resolveLoader("@babel/preset-env"),
|
|
82
|
-
|
|
76
|
+
[
|
|
77
|
+
resolveLoader("@babel/preset-react"),
|
|
78
|
+
{ runtime: "automatic" },
|
|
79
|
+
],
|
|
83
80
|
resolveLoader("@babel/preset-typescript"),
|
|
84
81
|
],
|
|
85
82
|
},
|
|
@@ -89,7 +86,7 @@ const createClientConfig = () => {
|
|
|
89
86
|
test: /\.css$/,
|
|
90
87
|
use: [
|
|
91
88
|
isProduction
|
|
92
|
-
?
|
|
89
|
+
? MiniCssExtractPlugin.loader
|
|
93
90
|
: resolveLoader("style-loader"),
|
|
94
91
|
resolveLoader("css-loader"),
|
|
95
92
|
resolveLoader("postcss-loader"),
|
|
@@ -102,9 +99,9 @@ const createClientConfig = () => {
|
|
|
102
99
|
],
|
|
103
100
|
},
|
|
104
101
|
plugins: [
|
|
105
|
-
new
|
|
106
|
-
new
|
|
107
|
-
template:
|
|
102
|
+
new CleanWebpackPlugin(),
|
|
103
|
+
new HtmlWebpackPlugin({
|
|
104
|
+
template: path.resolve(__dirname, "../lib/server/default-index.html"),
|
|
108
105
|
filename: "index.html",
|
|
109
106
|
inject: "body",
|
|
110
107
|
minify: isProduction
|
|
@@ -122,7 +119,7 @@ const createClientConfig = () => {
|
|
|
122
119
|
}
|
|
123
120
|
: false,
|
|
124
121
|
}),
|
|
125
|
-
new
|
|
122
|
+
new MiniCssExtractPlugin({
|
|
126
123
|
filename: isProduction ? "[name].[contenthash].css" : "[name].css",
|
|
127
124
|
}),
|
|
128
125
|
],
|
|
@@ -141,8 +138,7 @@ const createClientConfig = () => {
|
|
|
141
138
|
devtool: isProduction ? "source-map" : "eval-source-map",
|
|
142
139
|
};
|
|
143
140
|
};
|
|
144
|
-
|
|
145
|
-
const createServerConfig = () => {
|
|
141
|
+
export const createServerConfig = () => {
|
|
146
142
|
const isProduction = process.env.NODE_ENV === "production";
|
|
147
143
|
const serverEntry = findEntry([
|
|
148
144
|
"src/server",
|
|
@@ -150,30 +146,30 @@ const createServerConfig = () => {
|
|
|
150
146
|
"src/server/main",
|
|
151
147
|
]);
|
|
152
148
|
// View Injection Logic
|
|
153
|
-
const viewsDir =
|
|
154
|
-
const hasViews =
|
|
155
|
-
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");
|
|
156
152
|
// Ensure cache directory exists
|
|
157
|
-
const cacheDir =
|
|
158
|
-
if (!
|
|
159
|
-
|
|
153
|
+
const cacheDir = path.dirname(viewsLoaderPath);
|
|
154
|
+
if (!fs.existsSync(cacheDir)) {
|
|
155
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
160
156
|
}
|
|
161
157
|
// Generate the loader file
|
|
162
158
|
const loaderContent = hasViews
|
|
163
159
|
? `module.exports = require.context('${viewsDir}', true, /\\.(tsx|jsx)$/);`
|
|
164
160
|
: `module.exports = null;`;
|
|
165
|
-
|
|
161
|
+
fs.writeFileSync(viewsLoaderPath, loaderContent);
|
|
166
162
|
return {
|
|
167
163
|
mode: isProduction ? "production" : "development",
|
|
168
164
|
target: "node",
|
|
169
165
|
entry: serverEntry,
|
|
170
166
|
output: {
|
|
171
|
-
path:
|
|
167
|
+
path: path.resolve(cwd, "dist"),
|
|
172
168
|
filename: "server.js",
|
|
173
169
|
},
|
|
174
170
|
externals: [
|
|
175
|
-
(
|
|
176
|
-
allowlist: [
|
|
171
|
+
nodeExternals({
|
|
172
|
+
allowlist: [/^arcanajs/],
|
|
177
173
|
}),
|
|
178
174
|
],
|
|
179
175
|
resolve: {
|
|
@@ -183,7 +179,7 @@ const createServerConfig = () => {
|
|
|
183
179
|
},
|
|
184
180
|
},
|
|
185
181
|
resolveLoader: {
|
|
186
|
-
modules: ["node_modules",
|
|
182
|
+
modules: ["node_modules", path.resolve(__dirname, "../../node_modules")],
|
|
187
183
|
},
|
|
188
184
|
module: {
|
|
189
185
|
rules: [
|
|
@@ -195,7 +191,10 @@ const createServerConfig = () => {
|
|
|
195
191
|
options: {
|
|
196
192
|
presets: [
|
|
197
193
|
resolveLoader("@babel/preset-env"),
|
|
198
|
-
|
|
194
|
+
[
|
|
195
|
+
resolveLoader("@babel/preset-react"),
|
|
196
|
+
{ runtime: "automatic" },
|
|
197
|
+
],
|
|
199
198
|
resolveLoader("@babel/preset-typescript"),
|
|
200
199
|
],
|
|
201
200
|
},
|
|
@@ -217,4 +216,3 @@ const createServerConfig = () => {
|
|
|
217
216
|
// devtool: isProduction ? "source-map" : "eval-source-map",
|
|
218
217
|
};
|
|
219
218
|
};
|
|
220
|
-
exports.createServerConfig = createServerConfig;
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
exports.hydrateArcanaJS = void 0;
|
|
7
|
-
const react_1 = __importDefault(require("react"));
|
|
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 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) => {
|
|
12
6
|
let views = {};
|
|
13
7
|
if (viewsOrContext.keys && typeof viewsOrContext.keys === "function") {
|
|
14
8
|
viewsOrContext.keys().forEach((key) => {
|
|
@@ -29,12 +23,10 @@ const hydrateArcanaJS = (viewsOrContext, layout) => {
|
|
|
29
23
|
if (container && dataScript) {
|
|
30
24
|
try {
|
|
31
25
|
const { page, data, params, csrfToken } = JSON.parse(dataScript.textContent || "{}");
|
|
32
|
-
|
|
33
|
-
react_1.default.createElement(ArcanaJSApp_1.ArcanaJSApp, { initialPage: page, initialData: data, initialParams: params, csrfToken: csrfToken, views: views, layout: layout })));
|
|
26
|
+
hydrateRoot(container, _jsx(HeadContext.Provider, { value: headManager, children: _jsx(ArcanaJSApp, { initialPage: page, initialData: data, initialParams: params, csrfToken: csrfToken, views: views, layout: layout }) }));
|
|
34
27
|
}
|
|
35
28
|
catch (e) {
|
|
36
29
|
console.error("Failed to parse initial data", e);
|
|
37
30
|
}
|
|
38
31
|
}
|
|
39
32
|
};
|
|
40
|
-
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,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const Body = ({ children }) => {
|
|
3
|
+
return _jsx(_Fragment, { children: children });
|
|
4
4
|
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Body = void 0;
|
|
7
|
-
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const Body = ({ children }) => {
|
|
9
|
-
return react_1.default.createElement(react_1.default.Fragment, null, children);
|
|
10
|
-
};
|
|
11
|
-
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,17 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Link = void 0;
|
|
7
|
-
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const useRouter_1 = require("../hooks/useRouter");
|
|
9
|
-
const Link = ({ href, children, ...props }) => {
|
|
10
|
-
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();
|
|
11
5
|
const handleClick = (e) => {
|
|
12
6
|
e.preventDefault();
|
|
13
7
|
navigateTo(href);
|
|
14
8
|
};
|
|
15
|
-
return (
|
|
9
|
+
return (_jsx("a", { href: href, onClick: handleClick, ...props, children: children }));
|
|
16
10
|
};
|
|
17
|
-
exports.Link = Link;
|
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
exports.NavLink = void 0;
|
|
7
|
-
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const Link_1 = require("./Link");
|
|
9
|
-
const useRouter_1 = require("../hooks/useRouter");
|
|
10
|
-
const NavLink = ({ href, activeClassName = "active", className = "", exact = false, children, ...props }) => {
|
|
11
|
-
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();
|
|
12
6
|
const isActive = exact ? currentUrl === href : currentUrl.startsWith(href);
|
|
13
7
|
const combinedClassName = `${className} ${isActive ? activeClassName : ""}`.trim();
|
|
14
|
-
return (
|
|
8
|
+
return (_jsx(Link, { href: href, className: combinedClassName, ...props, children: children }));
|
|
15
9
|
};
|
|
16
|
-
exports.NavLink = NavLink;
|
|
@@ -1,16 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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] }));
|
|
4
6
|
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Page = void 0;
|
|
7
|
-
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const PageContext_1 = require("../context/PageContext");
|
|
9
|
-
const Head_1 = require("./Head");
|
|
10
|
-
const Page = ({ data, title, children }) => {
|
|
11
|
-
return (react_1.default.createElement(PageContext_1.PageContext.Provider, { value: data },
|
|
12
|
-
title && (react_1.default.createElement(Head_1.Head, null,
|
|
13
|
-
react_1.default.createElement("title", null, title))),
|
|
14
|
-
children));
|
|
15
|
-
};
|
|
16
|
-
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,13 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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 }));
|
|
4
6
|
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.RouterProvider = exports.RouterContext = void 0;
|
|
7
|
-
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const createSingletonContext_1 = require("../utils/createSingletonContext");
|
|
9
|
-
exports.RouterContext = (0, createSingletonContext_1.createSingletonContext)("RouterContext", null);
|
|
10
|
-
const RouterProvider = ({ value, children }) => {
|
|
11
|
-
return (react_1.default.createElement(exports.RouterContext.Provider, { value: value }, children));
|
|
12
|
-
};
|
|
13
|
-
exports.RouterProvider = RouterProvider;
|
|
@@ -1,49 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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.ArcanaJSApp = void 0;
|
|
37
|
-
const react_1 = __importStar(require("react"));
|
|
38
|
-
const Page_1 = require("../components/Page");
|
|
39
|
-
const RouterContext_1 = require("../context/RouterContext");
|
|
40
|
-
const ArcanaJSApp = ({ initialPage, initialData, initialParams = {}, initialUrl, csrfToken, views, layout: Layout, }) => {
|
|
41
|
-
const [page, setPage] = (0, react_1.useState)(initialPage);
|
|
42
|
-
const [data, setData] = (0, react_1.useState)(initialData);
|
|
43
|
-
const [params, setParams] = (0, react_1.useState)(initialParams);
|
|
44
|
-
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 ||
|
|
45
10
|
(typeof window !== "undefined" ? window.location.pathname : "/"));
|
|
46
|
-
|
|
11
|
+
useEffect(() => {
|
|
47
12
|
const handlePopState = (event) => {
|
|
48
13
|
if (event.state) {
|
|
49
14
|
setPage(event.state.page);
|
|
@@ -82,17 +47,15 @@ const ArcanaJSApp = ({ initialPage, initialData, initialParams = {}, initialUrl,
|
|
|
82
47
|
}
|
|
83
48
|
};
|
|
84
49
|
const renderPage = () => {
|
|
85
|
-
const Component = views[page] || views["NotFoundPage"] || (() =>
|
|
86
|
-
return (
|
|
87
|
-
react_1.default.createElement(Component, { data: data, navigateTo: navigateTo, params: params })));
|
|
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 }) }));
|
|
88
52
|
};
|
|
89
53
|
const content = renderPage();
|
|
90
|
-
return (
|
|
54
|
+
return (_jsx(RouterProvider, { value: {
|
|
91
55
|
navigateTo,
|
|
92
56
|
currentPage: page,
|
|
93
57
|
currentUrl: url,
|
|
94
58
|
params,
|
|
95
59
|
csrfToken,
|
|
96
|
-
}
|
|
60
|
+
}, children: Layout ? _jsx(Layout, { children: content }) : _jsx(_Fragment, { children: content }) }));
|
|
97
61
|
};
|
|
98
|
-
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",
|