rasengan 1.0.0-beta.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/LICENSE +21 -0
- package/lib/cli/dirname.d.ts +2 -0
- package/lib/cli/dirname.js +6 -0
- package/lib/cli/dirname.js.map +1 -0
- package/lib/cli/index.d.ts +2 -0
- package/lib/cli/index.js +101 -0
- package/lib/cli/index.js.map +1 -0
- package/lib/config/index.d.ts +39 -0
- package/lib/config/index.js +57 -0
- package/lib/config/index.js.map +1 -0
- package/lib/config/type.d.ts +68 -0
- package/lib/config/type.js +2 -0
- package/lib/config/type.js.map +1 -0
- package/lib/core/components/index.d.ts +26 -0
- package/lib/core/components/index.js +72 -0
- package/lib/core/components/index.js.map +1 -0
- package/lib/core/index.d.ts +2 -0
- package/lib/core/index.js +2 -0
- package/lib/core/index.js.map +1 -0
- package/lib/core/interfaces.d.ts +76 -0
- package/lib/core/interfaces.js +91 -0
- package/lib/core/interfaces.js.map +1 -0
- package/lib/core/types.d.ts +45 -0
- package/lib/core/types.js +2 -0
- package/lib/core/types.js.map +1 -0
- package/lib/decorators/index.d.ts +2 -0
- package/lib/decorators/index.js +3 -0
- package/lib/decorators/index.js.map +1 -0
- package/lib/decorators/route.d.ts +7 -0
- package/lib/decorators/route.js +25 -0
- package/lib/decorators/route.js.map +1 -0
- package/lib/decorators/router.d.ts +7 -0
- package/lib/decorators/router.js +24 -0
- package/lib/decorators/router.js.map +1 -0
- package/lib/decorators/types.d.ts +47 -0
- package/lib/decorators/types.js +2 -0
- package/lib/decorators/types.js.map +1 -0
- package/lib/entries/entry-client.d.ts +1 -0
- package/lib/entries/entry-client.js +15 -0
- package/lib/entries/entry-client.js.map +1 -0
- package/lib/entries/entry-server.d.ts +6 -0
- package/lib/entries/entry-server.js +20 -0
- package/lib/entries/entry-server.js.map +1 -0
- package/lib/hooks/index.d.ts +0 -0
- package/lib/hooks/index.js +1 -0
- package/lib/hooks/index.js.map +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +10 -0
- package/lib/index.js.map +1 -0
- package/lib/routing/components/index.d.ts +32 -0
- package/lib/routing/components/index.js +69 -0
- package/lib/routing/components/index.js.map +1 -0
- package/lib/routing/index.d.ts +3 -0
- package/lib/routing/index.js +4 -0
- package/lib/routing/index.js.map +1 -0
- package/lib/routing/interfaces.d.ts +67 -0
- package/lib/routing/interfaces.js +88 -0
- package/lib/routing/interfaces.js.map +1 -0
- package/lib/routing/types.d.ts +4 -0
- package/lib/routing/types.js +2 -0
- package/lib/routing/types.js.map +1 -0
- package/lib/routing/utils/index.d.ts +40 -0
- package/lib/routing/utils/index.js +256 -0
- package/lib/routing/utils/index.js.map +1 -0
- package/lib/server/functions/vercel/api/index.d.ts +2 -0
- package/lib/server/functions/vercel/api/index.js +91 -0
- package/lib/server/functions/vercel/api/index.js.map +1 -0
- package/lib/server/functions/vercel/vercel.json +12 -0
- package/lib/server/utils/createFetchRequest.d.ts +5 -0
- package/lib/server/utils/createFetchRequest.js +34 -0
- package/lib/server/utils/createFetchRequest.js.map +1 -0
- package/lib/server/utils/getIp.d.ts +1 -0
- package/lib/server/utils/getIp.js +30 -0
- package/lib/server/utils/getIp.js.map +1 -0
- package/lib/server/utils/handleError.d.ts +2 -0
- package/lib/server/utils/handleError.js +28 -0
- package/lib/server/utils/handleError.js.map +1 -0
- package/lib/server/utils/index.d.ts +5 -0
- package/lib/server/utils/index.js +8 -0
- package/lib/server/utils/index.js.map +1 -0
- package/lib/server/utils/log.d.ts +6 -0
- package/lib/server/utils/log.js +69 -0
- package/lib/server/utils/log.js.map +1 -0
- package/package.json +75 -0
- package/server.js +229 -0
- package/src/cli/dirname.ts +7 -0
- package/src/cli/index.ts +134 -0
- package/src/config/index.ts +67 -0
- package/src/config/type.ts +76 -0
- package/src/core/components/index.tsx +111 -0
- package/src/core/index.ts +14 -0
- package/src/core/interfaces.tsx +129 -0
- package/src/core/types.ts +43 -0
- package/src/decorators/index.ts +2 -0
- package/src/decorators/route.ts +32 -0
- package/src/decorators/router.ts +30 -0
- package/src/decorators/types.ts +54 -0
- package/src/entries/entry-client.tsx +33 -0
- package/src/entries/entry-server.tsx +50 -0
- package/src/hooks/index.ts +0 -0
- package/src/index.ts +11 -0
- package/src/routing/components/index.tsx +125 -0
- package/src/routing/index.ts +23 -0
- package/src/routing/interfaces.ts +105 -0
- package/src/routing/types.ts +3 -0
- package/src/routing/utils/index.tsx +342 -0
- package/src/server/functions/vercel/api/index.ts +122 -0
- package/src/server/functions/vercel/vercel.json +12 -0
- package/src/server/utils/createFetchRequest.ts +40 -0
- package/src/server/utils/getIp.ts +37 -0
- package/src/server/utils/handleError.ts +36 -0
- package/src/server/utils/index.ts +15 -0
- package/src/server/utils/log.ts +115 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +30 -0
- package/tsconfig.lib.json +41 -0
- package/tsconfig.node.json +11 -0
- package/vite.config.ts +45 -0
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rasengan",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "1.0.0-beta.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"rasengan": "./lib/cli/index.js"
|
|
9
|
+
},
|
|
10
|
+
"author": {
|
|
11
|
+
"name": "dilane3",
|
|
12
|
+
"email": "komboudilane125@gmail.com",
|
|
13
|
+
"url": "https://dilane3.com",
|
|
14
|
+
"twitter": "https://twitter.com/dilanekombou",
|
|
15
|
+
"github": "https://github.com/dilane3"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/rasengan/rasengan.git",
|
|
20
|
+
"issues": "https://github.com/rasengan/rasengan/issues"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"dev": "node server",
|
|
24
|
+
"build": "npm run build:client && npm run build:server",
|
|
25
|
+
"build:client": "vite build --ssrManifest --outDir dist/client",
|
|
26
|
+
"build:server": "vite build --ssr node_modules/rasengan/lib/entries/entry-server.js --outDir dist/server",
|
|
27
|
+
"build:lib": "tsc -p tsconfig.lib.json",
|
|
28
|
+
"preview": "cross-env NODE_ENV=production node server",
|
|
29
|
+
"deploy": "npm publish --access public",
|
|
30
|
+
"pack": "npm pack --pack-destination ./../packages/rasengan/"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@vercel/node": "^3.0.14",
|
|
34
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
35
|
+
"chalk": "^5.3.0",
|
|
36
|
+
"commander": "^11.1.0",
|
|
37
|
+
"compression": "^1.7.4",
|
|
38
|
+
"cross-spawn": "^7.0.3",
|
|
39
|
+
"execa": "^8.0.1",
|
|
40
|
+
"express": "^4.18.2",
|
|
41
|
+
"inquirer": "^9.2.12",
|
|
42
|
+
"keypress": "^0.2.1",
|
|
43
|
+
"node-fetch": "^3.3.2",
|
|
44
|
+
"ora": "^7.0.1",
|
|
45
|
+
"react-helmet": "^6.1.0",
|
|
46
|
+
"react-helmet-async": "^2.0.4",
|
|
47
|
+
"react-router-dom": "^6.20.1",
|
|
48
|
+
"sirv": "^2.0.3",
|
|
49
|
+
"vite": "^5.0.7",
|
|
50
|
+
"vite-plugin-css": "^1.0.4"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"react": "^18.2.0",
|
|
54
|
+
"react-dom": "^18.2.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/compression": "^1.7.4",
|
|
58
|
+
"@types/cross-spawn": "^6.0.4",
|
|
59
|
+
"@types/express": "^4.17.19",
|
|
60
|
+
"@types/node": "^20.8.6",
|
|
61
|
+
"@types/react": "^18.2.28",
|
|
62
|
+
"@types/react-dom": "^18.2.13",
|
|
63
|
+
"@types/react-helmet": "^6.1.8",
|
|
64
|
+
"cross-env": "^7.0.3",
|
|
65
|
+
"typescript": "^5.2.2"
|
|
66
|
+
},
|
|
67
|
+
"resolutions": {
|
|
68
|
+
"@vitejs/plugin-react": "^4.2.1"
|
|
69
|
+
},
|
|
70
|
+
"license": "MIT",
|
|
71
|
+
"engines": {
|
|
72
|
+
"node": ">=16.0.0",
|
|
73
|
+
"npm": ">=7.0.0"
|
|
74
|
+
}
|
|
75
|
+
}
|
package/server.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import express from "express";
|
|
3
|
+
import { dirname, join } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import {
|
|
6
|
+
createStaticHandler,
|
|
7
|
+
createStaticRouter,
|
|
8
|
+
} from "react-router-dom/server.js";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import inquirer from "inquirer";
|
|
11
|
+
|
|
12
|
+
// Get config
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
import config from "./../../rasengan.config.js";
|
|
15
|
+
|
|
16
|
+
// Load utils
|
|
17
|
+
import {
|
|
18
|
+
createFetchRequest,
|
|
19
|
+
logServerInfo,
|
|
20
|
+
fix404,
|
|
21
|
+
} from "./lib/server/utils/index.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* This function is responsible for creating a server for the development environment.
|
|
25
|
+
* @param {boolean} isProduction - Whether the server is in production mode or not.
|
|
26
|
+
* @param {number} port - The port to run the server on.
|
|
27
|
+
* @param {string} base - The base path for the server.
|
|
28
|
+
*/
|
|
29
|
+
async function createServer({
|
|
30
|
+
isProduction,
|
|
31
|
+
port,
|
|
32
|
+
base = "/",
|
|
33
|
+
enableSearchingPort = false,
|
|
34
|
+
}) {
|
|
35
|
+
// Get directory name
|
|
36
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
37
|
+
|
|
38
|
+
// Get app path
|
|
39
|
+
const appPath = join(__dirname, "./../../");
|
|
40
|
+
|
|
41
|
+
// Cached production assets
|
|
42
|
+
const templateHtml = isProduction
|
|
43
|
+
? await fs.readFile(join(appPath, "dist/client/index.html"), "utf-8")
|
|
44
|
+
: "";
|
|
45
|
+
const ssrManifest = isProduction
|
|
46
|
+
? await fs.readFile(
|
|
47
|
+
join(appPath, "dist/client/.vite/ssr-manifest.json"),
|
|
48
|
+
"utf-8"
|
|
49
|
+
)
|
|
50
|
+
: undefined;
|
|
51
|
+
|
|
52
|
+
// Create http server
|
|
53
|
+
const app = express();
|
|
54
|
+
|
|
55
|
+
// Add Vite or respective production middlewares
|
|
56
|
+
let vite;
|
|
57
|
+
if (!isProduction) {
|
|
58
|
+
const { createServer } = await import("vite");
|
|
59
|
+
vite = await createServer({
|
|
60
|
+
server: { middlewareMode: true },
|
|
61
|
+
appType: "custom",
|
|
62
|
+
base,
|
|
63
|
+
});
|
|
64
|
+
app.use(vite.middlewares);
|
|
65
|
+
} else {
|
|
66
|
+
const compression = (await import("compression")).default;
|
|
67
|
+
const sirv = (await import("sirv")).default;
|
|
68
|
+
app.use(compression());
|
|
69
|
+
app.use(base, sirv(join(appPath, "dist/client"), { extensions: [] }));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Serve HTML
|
|
73
|
+
app.use("*", async (req, res) => {
|
|
74
|
+
try {
|
|
75
|
+
// ! 404 Fix related to some files not being found
|
|
76
|
+
fix404(req.originalUrl, res, appPath);
|
|
77
|
+
|
|
78
|
+
// ! Service Worker Fix
|
|
79
|
+
|
|
80
|
+
const url = req.originalUrl.replace(base, "");
|
|
81
|
+
|
|
82
|
+
let template;
|
|
83
|
+
let render;
|
|
84
|
+
let staticRoutes;
|
|
85
|
+
if (!isProduction) {
|
|
86
|
+
// Always read fresh template in development
|
|
87
|
+
template = await fs.readFile(join(appPath, "index.html"), "utf-8");
|
|
88
|
+
template = await vite.transformIndexHtml(url, template);
|
|
89
|
+
|
|
90
|
+
const entry = await vite.ssrLoadModule(
|
|
91
|
+
join(appPath, "node_modules/rasengan/lib/entries/entry-server.js")
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
render = entry.render;
|
|
95
|
+
staticRoutes = entry.staticRoutes;
|
|
96
|
+
} else {
|
|
97
|
+
template = templateHtml;
|
|
98
|
+
const entry = await import(
|
|
99
|
+
join(appPath, "dist/server/entry-server.js")
|
|
100
|
+
);
|
|
101
|
+
render = entry.render;
|
|
102
|
+
staticRoutes = entry.staticRoutes;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Create static handler
|
|
106
|
+
let handler = createStaticHandler(staticRoutes);
|
|
107
|
+
|
|
108
|
+
// Create fetch request for static routing
|
|
109
|
+
let fetchRequest = createFetchRequest(req, req.get("host"));
|
|
110
|
+
let context = await handler.query(fetchRequest);
|
|
111
|
+
|
|
112
|
+
// Handle redirects
|
|
113
|
+
const status = context.status;
|
|
114
|
+
|
|
115
|
+
if (status === 302) {
|
|
116
|
+
const redirect = context.headers.get("Location");
|
|
117
|
+
|
|
118
|
+
return res.redirect(redirect);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Helmet context
|
|
122
|
+
const helmetContext = {};
|
|
123
|
+
|
|
124
|
+
// Create static router
|
|
125
|
+
let router = createStaticRouter(handler.dataRoutes, context);
|
|
126
|
+
|
|
127
|
+
// const rendered = await render(url, ssrManifest);
|
|
128
|
+
const rendered = await render(router, context, helmetContext);
|
|
129
|
+
|
|
130
|
+
// Get metadata
|
|
131
|
+
const helmet = helmetContext.helmet;
|
|
132
|
+
|
|
133
|
+
const head = `
|
|
134
|
+
${helmet.title.toString()}
|
|
135
|
+
${helmet.meta.toString()}
|
|
136
|
+
`;
|
|
137
|
+
|
|
138
|
+
let html = template
|
|
139
|
+
.replace(`<!--app-head-->`, head ?? "")
|
|
140
|
+
.replace(`<!--app-html-->`, rendered.html ?? "");
|
|
141
|
+
|
|
142
|
+
res
|
|
143
|
+
.status(200)
|
|
144
|
+
.set({
|
|
145
|
+
"Content-Type": "text/html",
|
|
146
|
+
"Cache-Control": "max-age=31536000",
|
|
147
|
+
})
|
|
148
|
+
.end(html);
|
|
149
|
+
} catch (e) {
|
|
150
|
+
vite?.ssrFixStacktrace(e);
|
|
151
|
+
// console.log(e.stack);
|
|
152
|
+
res.status(500).end(e.stack);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Start http server
|
|
157
|
+
const server = app.listen(port, () => {
|
|
158
|
+
setTimeout(() => {
|
|
159
|
+
logServerInfo(port, isProduction);
|
|
160
|
+
}, 100);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Handle errors
|
|
164
|
+
server.on("error", async (err) => {
|
|
165
|
+
const multiplicationSymbol = "\u00D7";
|
|
166
|
+
|
|
167
|
+
// Handle PORT in use error
|
|
168
|
+
if (err.code === "EADDRINUSE") {
|
|
169
|
+
const newPort = port + 1;
|
|
170
|
+
|
|
171
|
+
console.error(
|
|
172
|
+
chalk.red(
|
|
173
|
+
`${chalk.bold.red(
|
|
174
|
+
multiplicationSymbol
|
|
175
|
+
)} Port ${port} is already in use. \n\n`
|
|
176
|
+
)
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
// Check if user wants to use a different port
|
|
180
|
+
if (!enableSearchingPort) {
|
|
181
|
+
// Ask user if they want to use a different port
|
|
182
|
+
const { useDifferentPort } = await inquirer.prompt([
|
|
183
|
+
{
|
|
184
|
+
type: "confirm",
|
|
185
|
+
name: "useDifferentPort",
|
|
186
|
+
message: `Do you want to use a different port?`,
|
|
187
|
+
},
|
|
188
|
+
]);
|
|
189
|
+
|
|
190
|
+
if (!useDifferentPort) {
|
|
191
|
+
console.log(chalk.blue("Closing server... \n\n"));
|
|
192
|
+
process.exit(0);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
console.log(chalk.blue(`Trying port ${newPort}... \n\n`));
|
|
196
|
+
|
|
197
|
+
await createServer({
|
|
198
|
+
isProduction,
|
|
199
|
+
port: newPort,
|
|
200
|
+
base,
|
|
201
|
+
enableSearchingPort: true,
|
|
202
|
+
});
|
|
203
|
+
} else {
|
|
204
|
+
console.log(chalk.blue(`Trying port ${newPort}... \n\n`));
|
|
205
|
+
|
|
206
|
+
await createServer({
|
|
207
|
+
isProduction,
|
|
208
|
+
port: newPort,
|
|
209
|
+
base,
|
|
210
|
+
enableSearchingPort,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Constants
|
|
218
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
219
|
+
const port = !isProduction
|
|
220
|
+
? (process.env.PORT && Number(process.env.PORT)) ||
|
|
221
|
+
config.server?.development?.port ||
|
|
222
|
+
5320
|
|
223
|
+
: process.env.PORT || 4320;
|
|
224
|
+
const base = process.env.BASE || "/";
|
|
225
|
+
|
|
226
|
+
// Launch server
|
|
227
|
+
(async function launchServer() {
|
|
228
|
+
await createServer({ isProduction, port, base });
|
|
229
|
+
})();
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import __dirname from "./dirname.js";
|
|
5
|
+
import { execa } from "execa";
|
|
6
|
+
|
|
7
|
+
// Config
|
|
8
|
+
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
import config from "../../../../rasengan.config.js";
|
|
11
|
+
|
|
12
|
+
const program = new Command();
|
|
13
|
+
|
|
14
|
+
program
|
|
15
|
+
.name(chalk.blue("rasengan"))
|
|
16
|
+
.version("1.0.0", "-v, --version", "Output the current version number");
|
|
17
|
+
|
|
18
|
+
// Handle the dev command
|
|
19
|
+
program
|
|
20
|
+
.command("dev")
|
|
21
|
+
.option("-p <port>")
|
|
22
|
+
.description("Start development server")
|
|
23
|
+
.action(async ({ p: port }: { p: number }) => {
|
|
24
|
+
const convertedPort = Number(port);
|
|
25
|
+
|
|
26
|
+
// Checking port
|
|
27
|
+
if (
|
|
28
|
+
port &&
|
|
29
|
+
(isNaN(convertedPort) || convertedPort < 0 || convertedPort > 65535)
|
|
30
|
+
) {
|
|
31
|
+
console.log("");
|
|
32
|
+
console.log(
|
|
33
|
+
chalk.red("Please provide a valid port number between 0-65535")
|
|
34
|
+
);
|
|
35
|
+
console.log("");
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
execa("node", ["node_modules/rasengan/server"], {
|
|
40
|
+
stdio: "inherit",
|
|
41
|
+
env: {
|
|
42
|
+
...process.env,
|
|
43
|
+
PORT: convertedPort ? convertedPort.toString() : undefined,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Handle the build command
|
|
49
|
+
program
|
|
50
|
+
.command("build")
|
|
51
|
+
.description("Build the project")
|
|
52
|
+
.action(() => {
|
|
53
|
+
// const childProcess = exec("npm --prefix node_modules/rasengan run build");
|
|
54
|
+
execa("npm", ["run", "build"], {
|
|
55
|
+
cwd: "node_modules/rasengan",
|
|
56
|
+
stdio: "inherit", // Pipe child process output to the parent process
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Handle the prebuild command
|
|
61
|
+
program
|
|
62
|
+
.command("prebuild")
|
|
63
|
+
.description("Prebuild the project")
|
|
64
|
+
.action(() => {
|
|
65
|
+
// Displaying the message
|
|
66
|
+
console.log("");
|
|
67
|
+
console.log(chalk.blue("Prebuilding your project..."));
|
|
68
|
+
console.log("");
|
|
69
|
+
|
|
70
|
+
// Checking the config file in order to know about hosting strategy
|
|
71
|
+
const { server } = config;
|
|
72
|
+
|
|
73
|
+
const hostingStrategy = server?.production?.hosting ?? "custom";
|
|
74
|
+
|
|
75
|
+
if (hostingStrategy === "vercel") {
|
|
76
|
+
// Displaying the message
|
|
77
|
+
console.log(
|
|
78
|
+
`Your project is configured to be hosted on ${chalk.bold.blue(
|
|
79
|
+
hostingStrategy
|
|
80
|
+
)}\n`
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Copying the api folder to the root directory
|
|
84
|
+
execa(
|
|
85
|
+
"cp",
|
|
86
|
+
["-r", "node_modules/rasengan/lib/server/functions/vercel/api", "."],
|
|
87
|
+
{
|
|
88
|
+
stdio: "inherit",
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
// Copying the vercel.json file to the root directory
|
|
93
|
+
execa(
|
|
94
|
+
"cp",
|
|
95
|
+
["node_modules/rasengan/src/server/functions/vercel/vercel.json", "."],
|
|
96
|
+
{
|
|
97
|
+
stdio: "inherit",
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Removing index.d.ts and index.js.map files from the api folder
|
|
102
|
+
execa("rm", ["api/index.d.ts", "api/index.js.map"], {
|
|
103
|
+
stdio: "inherit",
|
|
104
|
+
});
|
|
105
|
+
} else if (hostingStrategy === "netlify") {
|
|
106
|
+
// Copying the netlify.toml file to the root directory
|
|
107
|
+
// execa(
|
|
108
|
+
// "cp",
|
|
109
|
+
// ["node_modules/rasengan/src/server/functions/netlify/netlify.toml", "."],
|
|
110
|
+
// {
|
|
111
|
+
// stdio: "inherit",
|
|
112
|
+
// }
|
|
113
|
+
// );
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Handle the start command
|
|
118
|
+
program
|
|
119
|
+
.command("start")
|
|
120
|
+
.description("Start the project in production mode")
|
|
121
|
+
.action(async () => {
|
|
122
|
+
const childProcess = execa("npm", ["run", "preview"], {
|
|
123
|
+
cwd: "node_modules/rasengan",
|
|
124
|
+
stdio: "inherit", // Pipe child process output to the parent process
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
childProcess.on("close", (code) => {
|
|
128
|
+
if (code === 0) {
|
|
129
|
+
process.stdout.write("Project started Succesfully");
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type AppConfig } from "./type.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Function to define the config for the app
|
|
5
|
+
* It will be used by vite.config.ts and other files in other to configure the app
|
|
6
|
+
* @param {AppConfig} loadedConfig
|
|
7
|
+
*/
|
|
8
|
+
export const defineConfig = (loadedConfig: AppConfig) => {
|
|
9
|
+
const { reactStrictMode, server, vite } = loadedConfig;
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const config = {
|
|
13
|
+
reactStrictMode: reactStrictMode === undefined ? true : reactStrictMode,
|
|
14
|
+
server,
|
|
15
|
+
vite: {
|
|
16
|
+
plugins: vite?.plugins || [],
|
|
17
|
+
|
|
18
|
+
optimizeDeps: {
|
|
19
|
+
exclude: [
|
|
20
|
+
"node:http",
|
|
21
|
+
"node-fetch",
|
|
22
|
+
...(vite?.optimizeDeps?.exclude || []),
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
css: {
|
|
27
|
+
postcss: vite?.css?.postcss || undefined,
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
build: {
|
|
31
|
+
external: vite?.build?.external || [],
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
appType: "custom",
|
|
35
|
+
},
|
|
36
|
+
// More config options...
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return config;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error(error);
|
|
42
|
+
return {
|
|
43
|
+
reactStrictMode: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Function to adapt the path for dev and prod
|
|
50
|
+
* @param {string | Array<string>} paths
|
|
51
|
+
*/
|
|
52
|
+
export const adaptPath = (paths: string | Array<string>) => {
|
|
53
|
+
// Check if we are in dev mode or prod
|
|
54
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
55
|
+
const prefix = isProduction ? "./../../" : "";
|
|
56
|
+
|
|
57
|
+
// Chech if the path is an array
|
|
58
|
+
const isArray = Array.isArray(paths);
|
|
59
|
+
|
|
60
|
+
// If the path is an array
|
|
61
|
+
if (isArray) {
|
|
62
|
+
return paths.map((path) => `${prefix}${path}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// If the path is a string
|
|
66
|
+
return `${prefix}${paths}`;
|
|
67
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export type AppConfig = {
|
|
2
|
+
/**
|
|
3
|
+
* Enable strict mode
|
|
4
|
+
* @default true
|
|
5
|
+
*/
|
|
6
|
+
reactStrictMode?: boolean;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Configure server both in development and production
|
|
10
|
+
*/
|
|
11
|
+
server?: {
|
|
12
|
+
/**
|
|
13
|
+
* Configure server in development
|
|
14
|
+
*/
|
|
15
|
+
development?: {
|
|
16
|
+
/**
|
|
17
|
+
* Port to listen on
|
|
18
|
+
* @default 3000
|
|
19
|
+
*/
|
|
20
|
+
port?: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Configure server in production
|
|
25
|
+
*/
|
|
26
|
+
production?: {
|
|
27
|
+
/**
|
|
28
|
+
* Set the hosting strategy
|
|
29
|
+
* @default "custom"
|
|
30
|
+
*/
|
|
31
|
+
hosting?: HostingStrategy;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Configure Vite
|
|
37
|
+
*/
|
|
38
|
+
vite?: {
|
|
39
|
+
/**
|
|
40
|
+
* Configure Vite plugins
|
|
41
|
+
*/
|
|
42
|
+
plugins?: any[];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Optimize dependencies
|
|
46
|
+
*/
|
|
47
|
+
optimizeDeps?: {
|
|
48
|
+
exclude?: string[];
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Configure css options
|
|
53
|
+
*/
|
|
54
|
+
css?: {
|
|
55
|
+
postcss?: {
|
|
56
|
+
plugins?: any[];
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Configure build options
|
|
62
|
+
*/
|
|
63
|
+
build?: {
|
|
64
|
+
/**
|
|
65
|
+
* Configure external dependencies
|
|
66
|
+
*/
|
|
67
|
+
external?: string[];
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
// More config options...
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Hosting strategy
|
|
75
|
+
*/
|
|
76
|
+
export type HostingStrategy = "vercel" | "netlify" | "heroku" | "custom";
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ComponentProps, PageToRenderProps } from "../types.js";
|
|
3
|
+
import { getRouter } from "../../routing/utils/index.js";
|
|
4
|
+
import * as pkg from "react-helmet-async";
|
|
5
|
+
import { useRouteError } from "react-router-dom";
|
|
6
|
+
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
const { Helmet } = pkg.default || pkg;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* App component that represent the entry point of the application
|
|
12
|
+
*/
|
|
13
|
+
export const Component = ({ router: AppRouter }: ComponentProps) => {
|
|
14
|
+
const Router = getRouter(AppRouter);
|
|
15
|
+
|
|
16
|
+
return <Router />;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Page component that defines title and description to a page
|
|
21
|
+
*/
|
|
22
|
+
export const PageToRender = ({ page, data }: PageToRenderProps) => {
|
|
23
|
+
// Get the page component
|
|
24
|
+
const Page = page.render;
|
|
25
|
+
|
|
26
|
+
// Get the page props
|
|
27
|
+
const props = data.props || {};
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<React.Fragment>
|
|
31
|
+
<Helmet>
|
|
32
|
+
<title>{page.title}</title>
|
|
33
|
+
<meta name="description" content={page.description} />
|
|
34
|
+
</Helmet>
|
|
35
|
+
|
|
36
|
+
<Page {...props} />
|
|
37
|
+
</React.Fragment>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Error fallback component that will be displayed if an error occurs
|
|
43
|
+
*/
|
|
44
|
+
export class ErrorBoundary extends React.Component {
|
|
45
|
+
state = { hasError: false, error: null, info: null };
|
|
46
|
+
|
|
47
|
+
componentDidCatch(error: any, info: any) {
|
|
48
|
+
this.setState({ hasError: true, error, info });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
render() {
|
|
52
|
+
const { error, info } = this.state;
|
|
53
|
+
|
|
54
|
+
if (this.state.hasError) {
|
|
55
|
+
return <ErrorFallbackComponent error={error} info={info} />;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
return <RouteErrorBoundary>{this.props.children}</RouteErrorBoundary>;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Error fallback component that will be displayed if an error occurs during a routing
|
|
65
|
+
*/
|
|
66
|
+
export const RouteErrorBoundary = ({ children }: any) => {
|
|
67
|
+
const error = useRouteError();
|
|
68
|
+
|
|
69
|
+
console.log({ error });
|
|
70
|
+
|
|
71
|
+
if (error) {
|
|
72
|
+
return <ErrorFallbackComponent error={error} info={null} />;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return children;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Error fallback component that will be displayed if an error occurs
|
|
80
|
+
*/
|
|
81
|
+
const ErrorFallbackComponent = ({ error, info }: any) => {
|
|
82
|
+
console.log({ error, info });
|
|
83
|
+
return (
|
|
84
|
+
<div
|
|
85
|
+
style={{
|
|
86
|
+
width: "calc(100% - 80px)",
|
|
87
|
+
height: "calc(100vh - 80px)",
|
|
88
|
+
padding: "40px",
|
|
89
|
+
backgroundColor: "#fff",
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
<div>
|
|
93
|
+
<h1 style={{ fontSize: "2rem" }}>Something went wrong</h1>
|
|
94
|
+
<p>{error.toString()}</p>
|
|
95
|
+
|
|
96
|
+
<div
|
|
97
|
+
style={{
|
|
98
|
+
width: "100%",
|
|
99
|
+
height: "auto",
|
|
100
|
+
borderRadius: 10,
|
|
101
|
+
padding: "20px",
|
|
102
|
+
marginTop: "10px",
|
|
103
|
+
backgroundColor: "#f0f0f0",
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
<p>{info.componentStack}</p>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
};
|