arcanajs 2.1.6 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -3
- package/framework/cli/index.js +127 -25
- package/framework/cli/templates.d.ts +6 -0
- package/framework/cli/templates.js +41 -0
- package/framework/cli/webpack.config.js +87 -44
- package/framework/lib/client/index.js +23 -7
- package/framework/lib/index.d.ts +2 -2
- package/framework/lib/index.js +40 -17
- package/framework/lib/server/ArcanaJSMiddleware.d.ts +9 -1
- package/framework/lib/server/ArcanaJSMiddleware.js +35 -13
- package/framework/lib/server/ArcanaJSServer.d.ts +2 -0
- package/framework/lib/server/ArcanaJSServer.js +77 -59
- package/framework/lib/server/ControllerBinder.js +4 -1
- package/framework/lib/server/CsrfMiddleware.js +10 -3
- package/framework/lib/server/DynamicRouter.d.ts +1 -1
- package/framework/lib/server/DynamicRouter.js +5 -1
- package/framework/lib/server/ResponseHandlerMiddleware.js +5 -1
- package/framework/lib/server/Router.d.ts +1 -1
- package/framework/lib/server/Router.js +16 -8
- package/framework/lib/server.d.ts +10 -0
- package/framework/lib/server.js +41 -6
- package/framework/lib/shared/components/Body.js +7 -3
- package/framework/lib/shared/components/Head.js +47 -10
- package/framework/lib/shared/components/Link.js +9 -5
- package/framework/lib/shared/components/NavLink.js +10 -6
- package/framework/lib/shared/components/Page.js +9 -5
- package/framework/lib/shared/context/HeadContext.js +5 -2
- package/framework/lib/shared/context/PageContext.js +5 -2
- package/framework/lib/shared/context/RouterContext.js +9 -5
- package/framework/lib/shared/core/ArcanaJSApp.js +18 -14
- package/framework/lib/shared/hooks/useHead.d.ts +1 -1
- package/framework/lib/shared/hooks/useHead.js +7 -3
- package/framework/lib/shared/hooks/useLocation.js +7 -3
- package/framework/lib/shared/hooks/usePage.js +7 -3
- package/framework/lib/shared/hooks/useParams.js +8 -4
- package/framework/lib/shared/hooks/useQuery.js +7 -3
- package/framework/lib/shared/hooks/useRouter.d.ts +1 -1
- package/framework/lib/shared/hooks/useRouter.js +8 -4
- package/framework/lib/shared/utils/createSingletonContext.js +6 -3
- package/framework/lib/shared/views/ErrorPage.d.ts +7 -0
- package/framework/lib/shared/views/ErrorPage.js +11 -0
- package/framework/lib/shared/views/NotFoundPage.d.ts +5 -0
- package/framework/lib/shared/views/NotFoundPage.js +10 -0
- package/framework/templates/ErrorPage.tsx +137 -0
- package/framework/templates/HomePage.tsx +344 -0
- package/framework/templates/NotFoundPage.tsx +109 -0
- package/framework/templates/arcanajs.png +0 -0
- package/framework/templates/arcanajs.svg +12 -0
- package/framework/templates/client-index.tsx +7 -0
- package/framework/templates/favicon.ico +0 -0
- package/framework/templates/globals.css +198 -0
- package/framework/templates/package.json +15 -0
- package/framework/templates/postcss.config.js +6 -0
- package/framework/templates/server-controller-home.ts +7 -0
- package/framework/templates/server-index.ts +10 -0
- package/framework/templates/server-routes-web.ts +7 -0
- package/package.json +30 -25
- package/framework/lib/shared/hooks/useDynamicComponents.d.ts +0 -1
- package/framework/lib/shared/hooks/useDynamicComponents.js +0 -16
package/framework/lib/index.js
CHANGED
|
@@ -1,17 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
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 __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.NotFoundPage = exports.ErrorPage = void 0;
|
|
21
|
+
__exportStar(require("./shared/components/Body"), exports);
|
|
22
|
+
__exportStar(require("./shared/components/Head"), exports);
|
|
23
|
+
__exportStar(require("./shared/components/Link"), exports);
|
|
24
|
+
__exportStar(require("./shared/components/NavLink"), exports);
|
|
25
|
+
__exportStar(require("./shared/components/Page"), exports);
|
|
26
|
+
__exportStar(require("./shared/context/HeadContext"), exports);
|
|
27
|
+
__exportStar(require("./shared/context/PageContext"), exports);
|
|
28
|
+
__exportStar(require("./shared/context/RouterContext"), exports);
|
|
29
|
+
__exportStar(require("./shared/core/ArcanaJSApp"), exports);
|
|
30
|
+
__exportStar(require("./shared/hooks/useHead"), exports);
|
|
31
|
+
__exportStar(require("./shared/hooks/useLocation"), exports);
|
|
32
|
+
__exportStar(require("./shared/hooks/usePage"), exports);
|
|
33
|
+
__exportStar(require("./shared/hooks/useParams"), exports);
|
|
34
|
+
__exportStar(require("./shared/hooks/useQuery"), exports);
|
|
35
|
+
__exportStar(require("./shared/hooks/useRouter"), exports);
|
|
36
|
+
// Default error views
|
|
37
|
+
var ErrorPage_1 = require("./shared/views/ErrorPage");
|
|
38
|
+
Object.defineProperty(exports, "ErrorPage", { enumerable: true, get: function () { return __importDefault(ErrorPage_1).default; } });
|
|
39
|
+
var NotFoundPage_1 = require("./shared/views/NotFoundPage");
|
|
40
|
+
Object.defineProperty(exports, "NotFoundPage", { enumerable: true, get: function () { return __importDefault(NotFoundPage_1).default; } });
|
|
@@ -3,7 +3,15 @@ import React from "react";
|
|
|
3
3
|
declare global {
|
|
4
4
|
namespace Express {
|
|
5
5
|
interface Response {
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Renders a React page using ArcanaJS SSR.
|
|
8
|
+
*
|
|
9
|
+
* @param page - The name of the page component to render.
|
|
10
|
+
* @param data - Initial data to pass to the page component (default: {}).
|
|
11
|
+
* @param params - Route parameters (default: {}).
|
|
12
|
+
* @returns The Express Response object.
|
|
13
|
+
*/
|
|
14
|
+
renderPage(page: string, data?: any, params?: Record<string, string>): Response;
|
|
7
15
|
}
|
|
8
16
|
}
|
|
9
17
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.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");
|
|
6
12
|
const DEFAULT_HTML_TEMPLATE = `<!DOCTYPE html>
|
|
7
13
|
<html lang="en">
|
|
8
14
|
<head>
|
|
@@ -19,15 +25,15 @@ const DEFAULT_HTML_TEMPLATE = `<!DOCTYPE html>
|
|
|
19
25
|
const safeStringify = (obj) => {
|
|
20
26
|
return JSON.stringify(obj).replace(/</g, "\\u003c");
|
|
21
27
|
};
|
|
22
|
-
|
|
28
|
+
const createArcanaJSMiddleware = (options) => {
|
|
23
29
|
const { views, indexFile, layout } = options;
|
|
24
30
|
let cachedIndexHtml = null;
|
|
25
31
|
const getIndexHtml = (callback) => {
|
|
26
32
|
if (process.env.NODE_ENV === "production" && cachedIndexHtml) {
|
|
27
33
|
return callback(null, cachedIndexHtml);
|
|
28
34
|
}
|
|
29
|
-
if (indexFile &&
|
|
30
|
-
|
|
35
|
+
if (indexFile && fs_1.default.existsSync(indexFile)) {
|
|
36
|
+
fs_1.default.readFile(indexFile, "utf8", (err, htmlData) => {
|
|
31
37
|
if (!err && process.env.NODE_ENV === "production") {
|
|
32
38
|
cachedIndexHtml = htmlData;
|
|
33
39
|
}
|
|
@@ -53,7 +59,7 @@ export const createArcanaJSMiddleware = (options) => {
|
|
|
53
59
|
tags: headTags,
|
|
54
60
|
push: (nodes) => headTags.push(nodes),
|
|
55
61
|
};
|
|
56
|
-
const appHtml = renderToString(
|
|
62
|
+
const appHtml = (0, server_1.renderToString)(react_1.default.createElement(HeadContext_1.HeadContext.Provider, { value: headManager }, react_1.default.createElement(ArcanaJSApp_1.ArcanaJSApp, {
|
|
57
63
|
initialPage: page,
|
|
58
64
|
initialData: data,
|
|
59
65
|
initialParams: params,
|
|
@@ -62,7 +68,7 @@ export const createArcanaJSMiddleware = (options) => {
|
|
|
62
68
|
views: views,
|
|
63
69
|
layout: layout,
|
|
64
70
|
})));
|
|
65
|
-
const headHtml = renderToString(
|
|
71
|
+
const headHtml = (0, server_1.renderToString)(react_1.default.createElement(react_1.default.Fragment, null, ...headTags));
|
|
66
72
|
getIndexHtml((err, htmlData) => {
|
|
67
73
|
if (err) {
|
|
68
74
|
console.error("Error reading index.html", err);
|
|
@@ -74,19 +80,35 @@ export const createArcanaJSMiddleware = (options) => {
|
|
|
74
80
|
params,
|
|
75
81
|
csrfToken,
|
|
76
82
|
});
|
|
77
|
-
const scriptTag = `<script id="
|
|
83
|
+
const scriptTag = `<script id="__ARCANAJS_DATA__" type="application/json">${scriptContent}</script>`;
|
|
84
|
+
const hmrScript = process.env.ARCANA_HMR_PORT
|
|
85
|
+
? `
|
|
86
|
+
<script>
|
|
87
|
+
(function() {
|
|
88
|
+
const socket = new WebSocket("ws://localhost:${process.env.ARCANA_HMR_PORT}");
|
|
89
|
+
socket.onmessage = function(event) {
|
|
90
|
+
const data = JSON.parse(event.data);
|
|
91
|
+
if (data.type === "reload") {
|
|
92
|
+
window.location.reload();
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
})();
|
|
96
|
+
</script>`
|
|
97
|
+
: "";
|
|
78
98
|
const html = htmlData
|
|
79
99
|
.replace("<!--HEAD_CONTENT-->", headHtml)
|
|
80
100
|
.replace("<!--APP_CONTENT-->", appHtml)
|
|
81
|
-
.replace("<!--ARCANAJS_DATA_SCRIPT-->", scriptTag);
|
|
101
|
+
.replace("<!--ARCANAJS_DATA_SCRIPT-->", scriptTag + hmrScript);
|
|
82
102
|
res.send(html);
|
|
83
103
|
});
|
|
84
104
|
}
|
|
85
105
|
catch (error) {
|
|
86
106
|
console.error("SSR Error:", error);
|
|
87
|
-
res.status(500).send("Internal Server Error");
|
|
107
|
+
return res.status(500).send("Internal Server Error");
|
|
88
108
|
}
|
|
109
|
+
return res;
|
|
89
110
|
};
|
|
90
111
|
next();
|
|
91
112
|
};
|
|
92
113
|
};
|
|
114
|
+
exports.createArcanaJSMiddleware = createArcanaJSMiddleware;
|
|
@@ -1,71 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ArcanaJSServer = void 0;
|
|
7
|
+
const compression_1 = __importDefault(require("compression"));
|
|
8
|
+
const cookie_parser_1 = __importDefault(require("cookie-parser"));
|
|
9
|
+
const express_1 = __importDefault(require("express"));
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const helmet_1 = __importDefault(require("helmet"));
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const ErrorPage_1 = __importDefault(require("../shared/views/ErrorPage"));
|
|
14
|
+
const NotFoundPage_1 = __importDefault(require("../shared/views/NotFoundPage"));
|
|
15
|
+
const ArcanaJSMiddleware_1 = require("./ArcanaJSMiddleware");
|
|
16
|
+
const CsrfMiddleware_1 = require("./CsrfMiddleware");
|
|
17
|
+
const DynamicRouter_1 = require("./DynamicRouter");
|
|
18
|
+
const ResponseHandlerMiddleware_1 = require("./ResponseHandlerMiddleware");
|
|
19
|
+
class ArcanaJSServer {
|
|
12
20
|
constructor(config) {
|
|
13
21
|
this.config = config;
|
|
14
|
-
this.app =
|
|
22
|
+
this.app = (0, express_1.default)();
|
|
15
23
|
this.initialize();
|
|
16
24
|
}
|
|
17
25
|
initialize() {
|
|
18
26
|
let { staticDir = "public", distDir = "dist/public", indexFile = "dist/public/index.html", views, viewsContext, routes, layout, } = this.config;
|
|
27
|
+
// 1. Load views from config or context (highest priority)
|
|
19
28
|
if (!views && viewsContext) {
|
|
20
|
-
views =
|
|
21
|
-
viewsContext.keys().forEach((key) => {
|
|
22
|
-
const viewName = key.replace(/^\.\/(.*)\.tsx$/, "$1");
|
|
23
|
-
views[viewName] = viewsContext(key).default;
|
|
24
|
-
});
|
|
29
|
+
views = this.loadViewsFromContext(viewsContext);
|
|
25
30
|
}
|
|
31
|
+
// 2. Load views from injected alias (Webpack)
|
|
26
32
|
if (!views) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
views = {};
|
|
33
|
-
injectedViews.keys().forEach((key) => {
|
|
34
|
-
const viewName = key.replace(/^\.\/(.*)\.tsx$/, "$1");
|
|
35
|
-
views[viewName] = injectedViews(key).default;
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
catch (e) {
|
|
40
|
-
// Fallback to auto-discovery using fs (Server-side only, non-bundled)
|
|
41
|
-
views = this.discoverViews();
|
|
42
|
-
}
|
|
33
|
+
views = this.loadViewsFromAlias();
|
|
34
|
+
}
|
|
35
|
+
// 3. Fallback to auto-discovery (Server-side only, non-bundled)
|
|
36
|
+
if (!views) {
|
|
37
|
+
views = this.discoverViews();
|
|
43
38
|
}
|
|
44
39
|
if (!views || Object.keys(views).length === 0) {
|
|
45
40
|
console.warn("No views found. Please check your views directory.");
|
|
46
41
|
views = {};
|
|
47
42
|
}
|
|
43
|
+
// Add default error views if not already present
|
|
44
|
+
views.NotFoundPage = views.NotFoundPage || NotFoundPage_1.default;
|
|
45
|
+
views.ErrorPage = views.ErrorPage || ErrorPage_1.default;
|
|
48
46
|
// Security and Performance
|
|
49
|
-
this.app.use(
|
|
47
|
+
this.app.use((0, helmet_1.default)({
|
|
50
48
|
contentSecurityPolicy: false,
|
|
51
49
|
}));
|
|
52
|
-
this.app.use(
|
|
53
|
-
this.app.use(
|
|
54
|
-
this.app.use(createCsrfMiddleware());
|
|
55
|
-
this.app.use(responseHandler);
|
|
50
|
+
this.app.use((0, compression_1.default)());
|
|
51
|
+
this.app.use((0, cookie_parser_1.default)());
|
|
52
|
+
this.app.use((0, CsrfMiddleware_1.createCsrfMiddleware)());
|
|
53
|
+
this.app.use(ResponseHandlerMiddleware_1.responseHandler);
|
|
56
54
|
// Static files
|
|
57
|
-
|
|
55
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
56
|
+
const staticOptions = {
|
|
58
57
|
index: false,
|
|
59
|
-
maxAge: "1y",
|
|
60
|
-
}
|
|
61
|
-
this.app.use(
|
|
62
|
-
|
|
63
|
-
maxAge: "1d",
|
|
64
|
-
}));
|
|
58
|
+
maxAge: isProduction ? "1y" : "0",
|
|
59
|
+
};
|
|
60
|
+
this.app.use(express_1.default.static(path_1.default.resolve(process.cwd(), distDir), staticOptions));
|
|
61
|
+
this.app.use(express_1.default.static(path_1.default.resolve(process.cwd(), staticDir), staticOptions));
|
|
65
62
|
// ArcanaJS Middleware
|
|
66
|
-
this.app.use(createArcanaJSMiddleware({
|
|
63
|
+
this.app.use((0, ArcanaJSMiddleware_1.createArcanaJSMiddleware)({
|
|
67
64
|
views,
|
|
68
|
-
indexFile:
|
|
65
|
+
indexFile: path_1.default.resolve(process.cwd(), indexFile),
|
|
69
66
|
layout,
|
|
70
67
|
}));
|
|
71
68
|
// Custom Routes
|
|
@@ -78,7 +75,7 @@ export class ArcanaJSServer {
|
|
|
78
75
|
}
|
|
79
76
|
}
|
|
80
77
|
// Dynamic Router
|
|
81
|
-
this.app.use(createDynamicRouter(views));
|
|
78
|
+
this.app.use((0, DynamicRouter_1.createDynamicRouter)(views));
|
|
82
79
|
// 404 Fallback
|
|
83
80
|
this.app.use((req, res) => {
|
|
84
81
|
res.status(404).renderPage("NotFoundPage");
|
|
@@ -92,23 +89,44 @@ export class ArcanaJSServer {
|
|
|
92
89
|
res.status(500).renderPage("ErrorPage", { message });
|
|
93
90
|
});
|
|
94
91
|
}
|
|
92
|
+
loadViewsFromContext(context) {
|
|
93
|
+
const views = {};
|
|
94
|
+
context.keys().forEach((key) => {
|
|
95
|
+
const viewName = key.replace(/^\.\/(.*)\.tsx$/, "$1");
|
|
96
|
+
views[viewName] = context(key).default;
|
|
97
|
+
});
|
|
98
|
+
return views;
|
|
99
|
+
}
|
|
100
|
+
loadViewsFromAlias() {
|
|
101
|
+
try {
|
|
102
|
+
// @ts-ignore - This alias is injected by Webpack
|
|
103
|
+
const injectedViews = require("arcana-views");
|
|
104
|
+
if (injectedViews) {
|
|
105
|
+
return this.loadViewsFromContext(injectedViews);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
// Ignore
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
95
113
|
discoverViews() {
|
|
96
114
|
const views = {};
|
|
97
115
|
const viewsDir = this.config.viewsDir
|
|
98
|
-
?
|
|
99
|
-
:
|
|
116
|
+
? path_1.default.resolve(process.cwd(), this.config.viewsDir)
|
|
117
|
+
: path_1.default.resolve(process.cwd(), "src/views");
|
|
118
|
+
if (!fs_1.default.existsSync(viewsDir))
|
|
119
|
+
return views;
|
|
100
120
|
const traverse = (dir) => {
|
|
101
|
-
|
|
102
|
-
return;
|
|
103
|
-
const files = fs.readdirSync(dir);
|
|
121
|
+
const files = fs_1.default.readdirSync(dir);
|
|
104
122
|
files.forEach((file) => {
|
|
105
|
-
const fullPath =
|
|
106
|
-
const stat =
|
|
123
|
+
const fullPath = path_1.default.join(dir, file);
|
|
124
|
+
const stat = fs_1.default.statSync(fullPath);
|
|
107
125
|
if (stat.isDirectory()) {
|
|
108
126
|
traverse(fullPath);
|
|
109
127
|
}
|
|
110
128
|
else if (file.endsWith(".tsx") || file.endsWith(".jsx")) {
|
|
111
|
-
const relativePath =
|
|
129
|
+
const relativePath = path_1.default.relative(viewsDir, fullPath);
|
|
112
130
|
const viewName = relativePath.replace(/\.(tsx|jsx)$/, "");
|
|
113
131
|
try {
|
|
114
132
|
// Use __non_webpack_require__ if available to avoid Webpack bundling issues
|
|
@@ -116,14 +134,13 @@ export class ArcanaJSServer {
|
|
|
116
134
|
const requireFunc = typeof __non_webpack_require__ !== "undefined"
|
|
117
135
|
? __non_webpack_require__
|
|
118
136
|
: module.require;
|
|
119
|
-
//
|
|
120
|
-
// This is a simplified approach. In a real framework, we'd handle compilation.
|
|
137
|
+
// Register ts-node if needed
|
|
121
138
|
if (file.endsWith(".tsx") || file.endsWith(".ts")) {
|
|
122
139
|
try {
|
|
123
140
|
requireFunc("ts-node/register");
|
|
124
141
|
}
|
|
125
142
|
catch (e) {
|
|
126
|
-
// Ignore
|
|
143
|
+
// Ignore
|
|
127
144
|
}
|
|
128
145
|
}
|
|
129
146
|
const pageModule = requireFunc(fullPath);
|
|
@@ -145,3 +162,4 @@ export class ArcanaJSServer {
|
|
|
145
162
|
});
|
|
146
163
|
}
|
|
147
164
|
}
|
|
165
|
+
exports.ArcanaJSServer = ArcanaJSServer;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class ControllerBinder {
|
|
2
4
|
static handle(controller, method) {
|
|
3
5
|
// Instantiate the controller once (Singleton pattern) for performance
|
|
4
6
|
// This assumes controllers are stateless, which is best practice.
|
|
@@ -27,3 +29,4 @@ export default class ControllerBinder {
|
|
|
27
29
|
};
|
|
28
30
|
}
|
|
29
31
|
}
|
|
32
|
+
exports.default = ControllerBinder;
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createCsrfMiddleware = void 0;
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
2
8
|
const CSRF_COOKIE_NAME = "_csrf";
|
|
3
|
-
|
|
9
|
+
const createCsrfMiddleware = () => {
|
|
4
10
|
return (req, res, next) => {
|
|
5
11
|
// 1. Generate or retrieve token
|
|
6
12
|
let token = req.cookies[CSRF_COOKIE_NAME];
|
|
7
13
|
if (!token) {
|
|
8
|
-
token =
|
|
14
|
+
token = crypto_1.default.randomBytes(32).toString("hex");
|
|
9
15
|
res.cookie(CSRF_COOKIE_NAME, token, {
|
|
10
16
|
httpOnly: true,
|
|
11
17
|
secure: process.env.NODE_ENV === "production",
|
|
@@ -25,3 +31,4 @@ export const createCsrfMiddleware = () => {
|
|
|
25
31
|
next();
|
|
26
32
|
};
|
|
27
33
|
};
|
|
34
|
+
exports.createCsrfMiddleware = createCsrfMiddleware;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { NextFunction, Request, Response } from "express";
|
|
2
|
-
export declare const createDynamicRouter: (views: Record<string, any>) => (req: Request, res: Response, next: NextFunction) =>
|
|
2
|
+
export declare const createDynamicRouter: (views: Record<string, any>) => (req: Request, res: Response, next: NextFunction) => Express.Response | undefined;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDynamicRouter = void 0;
|
|
4
|
+
const createDynamicRouter = (views) => {
|
|
2
5
|
return (req, res, next) => {
|
|
3
6
|
// Remove leading slash
|
|
4
7
|
let path = req.path.substring(1);
|
|
@@ -44,3 +47,4 @@ export const createDynamicRouter = (views) => {
|
|
|
44
47
|
next();
|
|
45
48
|
};
|
|
46
49
|
};
|
|
50
|
+
exports.createDynamicRouter = createDynamicRouter;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.responseHandler = void 0;
|
|
4
|
+
const responseHandler = (req, res, next) => {
|
|
2
5
|
res.success = (data = {}, message = "Success", status = 200) => {
|
|
3
6
|
return res.status(status).json({
|
|
4
7
|
success: true,
|
|
@@ -24,3 +27,4 @@ export const responseHandler = (req, res, next) => {
|
|
|
24
27
|
};
|
|
25
28
|
next();
|
|
26
29
|
};
|
|
30
|
+
exports.responseHandler = responseHandler;
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Route = exports.Router = void 0;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const ControllerBinder_1 = __importDefault(require("./ControllerBinder"));
|
|
3
9
|
/**
|
|
4
10
|
* Provides Routing syntax for defining routes with prefixes, middlewares, and groups
|
|
5
11
|
*/
|
|
6
|
-
|
|
12
|
+
class Router {
|
|
7
13
|
constructor() {
|
|
8
|
-
this.router =
|
|
14
|
+
this.router = express_1.default.Router();
|
|
9
15
|
this.middlewareStack = [];
|
|
10
16
|
this.prefixStack = [];
|
|
11
17
|
}
|
|
@@ -142,15 +148,16 @@ export class Router {
|
|
|
142
148
|
}
|
|
143
149
|
if (Array.isArray(action) && action.length === 2) {
|
|
144
150
|
const [controller, method] = action;
|
|
145
|
-
return
|
|
151
|
+
return ControllerBinder_1.default.handle(controller, method);
|
|
146
152
|
}
|
|
147
153
|
throw new Error('Action must be a function or array [Controller, "method"]');
|
|
148
154
|
}
|
|
149
155
|
}
|
|
156
|
+
exports.Router = Router;
|
|
150
157
|
/**
|
|
151
|
-
* Static Route class for
|
|
158
|
+
* Static Route class for ArcanaJS Routing
|
|
152
159
|
*/
|
|
153
|
-
|
|
160
|
+
class Route {
|
|
154
161
|
static create() {
|
|
155
162
|
return Router.create();
|
|
156
163
|
}
|
|
@@ -191,5 +198,6 @@ export class Route {
|
|
|
191
198
|
this._router = new Router();
|
|
192
199
|
}
|
|
193
200
|
}
|
|
201
|
+
exports.Route = Route;
|
|
194
202
|
Route._router = new Router();
|
|
195
|
-
|
|
203
|
+
exports.default = Route;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
import { Express } from "express";
|
|
2
|
+
import { ArcanaJSConfig, ArcanaJSServer } from "./server/ArcanaJSServer";
|
|
1
3
|
export * from "./server/ArcanaJSMiddleware";
|
|
2
4
|
export * from "./server/ArcanaJSServer";
|
|
3
5
|
export { default as ControllerBinder } from "./server/ControllerBinder";
|
|
4
6
|
export * from "./server/DynamicRouter";
|
|
7
|
+
export * from "./server/ResponseHandlerMiddleware";
|
|
5
8
|
export * from "./server/Router";
|
|
6
9
|
export { default as Route } from "./server/Router";
|
|
10
|
+
/**
|
|
11
|
+
* Create an ArcanaJS server with the given Express app
|
|
12
|
+
* @param app Express application instance
|
|
13
|
+
* @param config Optional ArcanaJS configuration
|
|
14
|
+
* @returns ArcanaJSServer instance
|
|
15
|
+
*/
|
|
16
|
+
export declare function createArcanaServer(app: Express, config?: Partial<ArcanaJSConfig>): ArcanaJSServer;
|
package/framework/lib/server.js
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
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 __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
|
+
exports.createArcanaServer = createArcanaServer;
|
|
22
|
+
const ArcanaJSServer_1 = require("./server/ArcanaJSServer");
|
|
23
|
+
__exportStar(require("./server/ArcanaJSMiddleware"), exports);
|
|
24
|
+
__exportStar(require("./server/ArcanaJSServer"), exports);
|
|
25
|
+
var ControllerBinder_1 = require("./server/ControllerBinder");
|
|
26
|
+
Object.defineProperty(exports, "ControllerBinder", { enumerable: true, get: function () { return __importDefault(ControllerBinder_1).default; } });
|
|
27
|
+
__exportStar(require("./server/DynamicRouter"), exports);
|
|
28
|
+
__exportStar(require("./server/ResponseHandlerMiddleware"), exports);
|
|
29
|
+
__exportStar(require("./server/Router"), exports);
|
|
30
|
+
var Router_1 = require("./server/Router");
|
|
31
|
+
Object.defineProperty(exports, "Route", { enumerable: true, get: function () { return __importDefault(Router_1).default; } });
|
|
32
|
+
/**
|
|
33
|
+
* Create an ArcanaJS server with the given Express app
|
|
34
|
+
* @param app Express application instance
|
|
35
|
+
* @param config Optional ArcanaJS configuration
|
|
36
|
+
* @returns ArcanaJSServer instance
|
|
37
|
+
*/
|
|
38
|
+
function createArcanaServer(app, config) {
|
|
39
|
+
const server = new ArcanaJSServer_1.ArcanaJSServer({ ...config });
|
|
40
|
+
return server;
|
|
41
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Body = void 0;
|
|
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 });
|
|
4
7
|
};
|
|
8
|
+
exports.Body = Body;
|