rasengan 1.0.0-beta.6 → 1.0.0-beta.60
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/CHANGELOG.md +19 -0
- package/README.md +36 -0
- package/bin.js +13 -0
- package/lib/esm/cli/index.js +40 -0
- package/lib/esm/client.js +2 -0
- package/lib/esm/core/config/index.js +3 -0
- package/lib/esm/core/config/type.js +6 -0
- package/lib/esm/core/config/utils/define-config.js +80 -0
- package/lib/esm/core/config/utils/load-modules.js +78 -0
- package/lib/esm/core/config/utils/path.js +16 -0
- package/lib/esm/core/config/vite/defaults.js +93 -0
- package/lib/esm/core/dynamic/index.js +21 -0
- package/lib/esm/core/index.js +2 -0
- package/lib/esm/core/middlewares/index.js +1 -0
- package/lib/esm/core/middlewares/logger.js +6 -0
- package/lib/esm/core/plugins/index.js +167 -0
- package/lib/esm/core/utils/log.js +9 -0
- package/lib/esm/entries/client/render.js +28 -0
- package/lib/esm/entries/server/entry.server.js +30 -0
- package/lib/esm/entries/server/index.js +31 -0
- package/lib/esm/index.js +5 -0
- package/lib/esm/plugin.js +2 -0
- package/lib/esm/routing/components/index.js +104 -0
- package/lib/esm/routing/components/template.js +64 -0
- package/lib/esm/routing/index.js +5 -0
- package/lib/{routing → esm/routing}/interfaces.js +19 -2
- package/lib/esm/routing/utils/define-router.js +78 -0
- package/lib/esm/routing/utils/define-routes-group.js +44 -0
- package/lib/esm/routing/utils/generate-metadata.js +83 -0
- package/lib/esm/routing/utils/generate-routes.js +301 -0
- package/lib/esm/routing/utils/index.js +4 -0
- package/lib/esm/scripts/build-command.js +17 -0
- package/lib/esm/scripts/generate-package-json.js +23 -0
- package/lib/esm/scripts/utils/check-os.js +7 -0
- package/lib/esm/scripts/utils/copy.js +16 -0
- package/lib/esm/server/build/index.js +11 -0
- package/lib/esm/server/build/manifest.js +91 -0
- package/lib/esm/server/build/rendering.js +18 -0
- package/lib/esm/server/dev/handlers.js +125 -0
- package/lib/esm/server/dev/server.js +174 -0
- package/lib/esm/server/dev/utils.js +192 -0
- package/lib/esm/server/node/index.js +69 -0
- package/lib/esm/server/node/rendering.js +44 -0
- package/lib/esm/server/node/stream.js +129 -0
- package/lib/esm/server/node/utils.js +91 -0
- package/lib/esm/server/runtime/mode.js +14 -0
- package/lib/esm/server/runtime/utils.js +5 -0
- package/lib/esm/server/virtual/index.js +8 -0
- package/lib/esm/server.js +4 -0
- package/lib/tsconfig.esm.tsbuildinfo +1 -0
- package/lib/tsconfig.types.tsbuildinfo +1 -0
- package/lib/types/client.d.ts +2 -0
- package/lib/types/core/config/index.d.ts +3 -0
- package/lib/types/core/config/type.d.ts +66 -0
- package/lib/types/core/config/utils/define-config.d.ts +7 -0
- package/lib/types/core/config/utils/load-modules.d.ts +19 -0
- package/lib/types/core/config/utils/path.d.ts +7 -0
- package/lib/types/core/config/vite/defaults.d.ts +3 -0
- package/lib/types/core/dynamic/index.d.ts +13 -0
- package/lib/types/core/index.d.ts +1 -0
- package/lib/types/core/middlewares/index.d.ts +1 -0
- package/lib/types/core/middlewares/logger.d.ts +2 -0
- package/lib/types/core/plugins/index.d.ts +18 -0
- package/lib/types/core/types.d.ts +15 -0
- package/lib/types/core/utils/log.d.ts +2 -0
- package/lib/types/entries/client/render.d.ts +5 -0
- package/lib/types/entries/server/entry.server.d.ts +20 -0
- package/lib/types/entries/server/index.d.ts +14 -0
- package/lib/types/index.d.ts +6 -0
- package/lib/types/plugin.d.ts +3 -0
- package/lib/types/routing/components/index.d.ts +22 -0
- package/lib/types/routing/components/template.d.ts +41 -0
- package/lib/types/routing/index.d.ts +6 -0
- package/lib/{routing → types/routing}/interfaces.d.ts +18 -6
- package/lib/types/routing/types.d.ts +213 -0
- package/lib/types/routing/utils/define-router.d.ts +8 -0
- package/lib/types/routing/utils/define-routes-group.d.ts +7 -0
- package/lib/types/routing/utils/generate-metadata.d.ts +7 -0
- package/lib/types/routing/utils/generate-routes.d.ts +13 -0
- package/lib/types/routing/utils/index.d.ts +4 -0
- package/lib/types/scripts/utils/check-os.d.ts +1 -0
- package/lib/types/scripts/utils/copy.d.ts +1 -0
- package/lib/types/server/build/index.d.ts +13 -0
- package/lib/types/server/build/manifest.d.ts +27 -0
- package/lib/types/server/build/rendering.d.ts +7 -0
- package/lib/types/server/dev/handlers.d.ts +27 -0
- package/lib/types/server/dev/server.d.ts +1 -0
- package/lib/types/server/dev/utils.d.ts +39 -0
- package/lib/types/server/node/index.d.ts +9 -0
- package/lib/types/server/node/rendering.d.ts +9 -0
- package/lib/types/server/node/stream.d.ts +7 -0
- package/lib/types/server/node/utils.d.ts +18 -0
- package/lib/types/server/runtime/mode.d.ts +9 -0
- package/lib/types/server/runtime/utils.d.ts +4 -0
- package/lib/types/server/virtual/index.d.ts +5 -0
- package/lib/types/server.d.ts +4 -0
- package/package.json +97 -47
- package/{tsconfig.json → tsconfig.base.json} +6 -16
- package/tsconfig.esm.json +8 -0
- package/tsconfig.types.json +10 -0
- package/types/client.d.ts +71 -0
- package/vite.config.ts +28 -65
- package/lib/cli/dirname.d.ts +0 -2
- package/lib/cli/dirname.js +0 -5
- package/lib/cli/index.d.ts +0 -2
- package/lib/cli/index.js +0 -99
- package/lib/config/index.d.ts +0 -58
- package/lib/config/index.js +0 -106
- package/lib/config/type.d.ts +0 -85
- package/lib/core/components/index.d.ts +0 -22
- package/lib/core/components/index.js +0 -67
- package/lib/core/index.d.ts +0 -2
- package/lib/core/index.js +0 -1
- package/lib/core/interfaces.d.ts +0 -93
- package/lib/core/interfaces.js +0 -114
- package/lib/core/types.d.ts +0 -45
- package/lib/decorators/index.d.ts +0 -2
- package/lib/decorators/index.js +0 -2
- package/lib/decorators/route.d.ts +0 -8
- package/lib/decorators/route.js +0 -20
- package/lib/decorators/router.d.ts +0 -8
- package/lib/decorators/router.js +0 -34
- package/lib/decorators/types.d.ts +0 -52
- package/lib/entries/entry-client.js +0 -14
- package/lib/entries/entry-server.d.ts +0 -6
- package/lib/entries/entry-server.js +0 -21
- package/lib/hooks/index.d.ts +0 -0
- package/lib/hooks/index.js +0 -0
- package/lib/index.d.ts +0 -6
- package/lib/index.js +0 -9
- package/lib/routing/components/index.d.ts +0 -38
- package/lib/routing/components/index.js +0 -81
- package/lib/routing/index.d.ts +0 -5
- package/lib/routing/index.js +0 -5
- package/lib/routing/types.d.ts +0 -9
- package/lib/routing/utils/index.d.ts +0 -38
- package/lib/routing/utils/index.js +0 -252
- package/lib/server/functions/vercel/_rasengan/server/index.d.ts +0 -2
- package/lib/server/functions/vercel/_rasengan/server/index.js +0 -91
- package/lib/server/functions/vercel/api/index.d.ts +0 -2
- package/lib/server/functions/vercel/api/index.js +0 -91
- package/lib/server/functions/vercel/vercel.json +0 -16
- package/lib/server/utils/createFetchRequest.d.ts +0 -5
- package/lib/server/utils/createFetchRequest.js +0 -33
- package/lib/server/utils/getIp.d.ts +0 -1
- package/lib/server/utils/getIp.js +0 -29
- package/lib/server/utils/handleError.d.ts +0 -2
- package/lib/server/utils/handleError.js +0 -27
- package/lib/server/utils/index.d.ts +0 -5
- package/lib/server/utils/index.js +0 -7
- package/lib/server/utils/log.d.ts +0 -7
- package/lib/server/utils/log.js +0 -74
- package/server.js +0 -238
- package/tsconfig.lib.json +0 -41
- package/tsconfig.node.json +0 -11
- package/types/image.d.ts +0 -44
- package/types/style.d.ts +0 -4
- /package/lib/{core → esm/core}/types.js +0 -0
- /package/lib/{decorators → esm/routing}/types.js +0 -0
- /package/lib/{config/type.js → types/cli/index.d.ts} +0 -0
- /package/lib/{entries/entry-client.d.ts → types/scripts/build-command.d.ts} +0 -0
- /package/lib/{routing/types.js → types/scripts/generate-package-json.d.ts} +0 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## Unreleased
|
|
2
|
+
|
|
3
|
+
## 1.0.0-beta.60 (2025-03-16)
|
|
4
|
+
|
|
5
|
+
## 1.0.0-beta.59 (2025-03-16)
|
|
6
|
+
|
|
7
|
+
## 1.0.0-beta.58 (2025-03-12)
|
|
8
|
+
|
|
9
|
+
## 1.0.0-beta.57 (2025-03-04)
|
|
10
|
+
|
|
11
|
+
## 1.0.0-beta.56 (2025-03-03)
|
|
12
|
+
|
|
13
|
+
## 1.0.0-beta.55 (2025-02-28)
|
|
14
|
+
|
|
15
|
+
## 1.0.0-beta.54 (2025-02-28)
|
|
16
|
+
|
|
17
|
+
## 1.0.0-beta.53 (2025-02-28)
|
|
18
|
+
|
|
19
|
+
## 1.0.0-beta.53 (2025-02-28)
|
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[](https://rasengan.dev)
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/rasengan)
|
|
4
|
+
[](https://www.npmjs.com/package/rasengan)
|
|
5
|
+
[](https://github.com/rasengan-dev/rasenganjs/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
## Getting Started
|
|
8
|
+
|
|
9
|
+
Based on modern tools, Rasengan.js will help you to create **high-quality web applications** with the benefit of React Components. It's a simple and easy-to-use framework that will help you to create a **beautiful and responsive web application**.
|
|
10
|
+
|
|
11
|
+
- Visit the [Rasengan.js Showcase](https://rasengan.dev/showcase) to see more sites built with Rasengan.js.
|
|
12
|
+
- Visit the [Rasengan.js Blog](https://rasengan.dev/blog) to get all news related to Rasengan.js.
|
|
13
|
+
|
|
14
|
+
## Documentation
|
|
15
|
+
|
|
16
|
+
Visit [https://rasengan.dev/docs](https://rasengan.dev/docs) to view the full documentation.
|
|
17
|
+
|
|
18
|
+
## Community
|
|
19
|
+
|
|
20
|
+
The Rasengan.js community can be found on [GitHub Discussions](https://github.com/rasengan-dev/rasenganjs/discussions) where you can ask questions, voice ideas, and share your projects with other people.
|
|
21
|
+
|
|
22
|
+
We also have a [Twitter](https://twitter.com/rasenganjs) account where you can follow us to get the latest news about Rasengan.js.
|
|
23
|
+
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
Rasengan.js is [MIT licensed](https://github.com/rasengan-dev/rasenganjs/blob/main/LICENSE).
|
|
27
|
+
|
|
28
|
+
## Contributing
|
|
29
|
+
|
|
30
|
+
We are open to all contributions. If you want to contribute to Rasengan.js, please read the [Contributing Guide](https://github.com/rasengan-dev/rasenganjs/blob/main/CONTRIBUTING.md) to get started.
|
|
31
|
+
|
|
32
|
+
## Authors
|
|
33
|
+
|
|
34
|
+
Here are the authors of Rasengan.js, the people who are at the origin of this great framework:
|
|
35
|
+
|
|
36
|
+
- Dilane Kombou ([**@dilanekombou**](https://twitter.com/dilanekombou))
|
package/bin.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Import `process` explicitly if needed (e.g., in certain runtime environments).
|
|
4
|
+
import process from 'process';
|
|
5
|
+
|
|
6
|
+
// If not already set, default `NODE_ENV=development`
|
|
7
|
+
process.env.NODE_ENV = process.env.NODE_ENV ?? 'development';
|
|
8
|
+
|
|
9
|
+
// Import and execute the CLI script
|
|
10
|
+
import('./lib/esm/cli/index.js').catch((err) => {
|
|
11
|
+
console.error('Failed to start the Rasengan CLI:', err);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { execa } from 'execa';
|
|
4
|
+
const program = new Command();
|
|
5
|
+
program
|
|
6
|
+
.name(chalk.blue('rasengan'))
|
|
7
|
+
.version('1.0.0', '-v, --version', 'Output the current version number');
|
|
8
|
+
// Handle the dev command
|
|
9
|
+
program
|
|
10
|
+
.command('dev')
|
|
11
|
+
.option('-p <port>')
|
|
12
|
+
.description('Start development server')
|
|
13
|
+
.action(async ({ p: port }) => {
|
|
14
|
+
const convertedPort = Number(port);
|
|
15
|
+
// Checking port
|
|
16
|
+
if (port &&
|
|
17
|
+
(isNaN(convertedPort) || convertedPort < 0 || convertedPort > 65535)) {
|
|
18
|
+
console.log('');
|
|
19
|
+
console.log(chalk.red('Please provide a valid port number between 0-65535'));
|
|
20
|
+
console.log('');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
execa('node', ['node_modules/rasengan/lib/esm/server/dev/server'], {
|
|
24
|
+
stdio: 'inherit',
|
|
25
|
+
env: {
|
|
26
|
+
...process.env,
|
|
27
|
+
PORT: convertedPort ? convertedPort.toString() : undefined,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
// Handle the build command
|
|
32
|
+
program
|
|
33
|
+
.command('build')
|
|
34
|
+
.description('Build the project')
|
|
35
|
+
.action(async () => {
|
|
36
|
+
execa('node', ['node_modules/rasengan/lib/esm/scripts/build-command'], {
|
|
37
|
+
stdio: 'inherit',
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function to define the config for the app
|
|
3
|
+
* It will be used by vite.config.ts and other files in other to configure the app
|
|
4
|
+
* @param {AppConfig | AppConfigFunction | AppConfigFunctionAsync} loadedConfig
|
|
5
|
+
*/
|
|
6
|
+
export const defineConfig = async (loadedConfig) => {
|
|
7
|
+
return async () => {
|
|
8
|
+
let config;
|
|
9
|
+
// Check if the loadedConfig is a function
|
|
10
|
+
if (typeof loadedConfig === 'function') {
|
|
11
|
+
// Call the function to get the config
|
|
12
|
+
const result = loadedConfig();
|
|
13
|
+
// Check if it's a promise (asynchronous function)
|
|
14
|
+
if (result instanceof Promise) {
|
|
15
|
+
config = await result; // Await the promise result (AppConfigFunctionAsync)
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
config = result; // Synchronous function result (AppConfigFunction)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
config = loadedConfig;
|
|
23
|
+
}
|
|
24
|
+
const { ssr, server, vite, redirects } = config;
|
|
25
|
+
// Define default values for vite config coming from loadedConfig.vite
|
|
26
|
+
const defaultViteConfig = {
|
|
27
|
+
...vite,
|
|
28
|
+
resolve: {
|
|
29
|
+
symbole: vite?.resolve?.symbole || '@',
|
|
30
|
+
alias: vite?.resolve?.alias || [],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
// Define default values for server config coming from loadedConfig.server
|
|
34
|
+
const defaultServerConfig = {
|
|
35
|
+
development: {
|
|
36
|
+
port: server?.development?.port || undefined,
|
|
37
|
+
open: server?.development?.open || false,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
// Define default values for redirects config coming from loadedConfig.redirects
|
|
41
|
+
const defaultRedirectsConfig = redirects || (() => new Promise((resolve) => resolve([])));
|
|
42
|
+
try {
|
|
43
|
+
const config = {
|
|
44
|
+
ssr: ssr ?? true,
|
|
45
|
+
server: defaultServerConfig,
|
|
46
|
+
vite: {
|
|
47
|
+
...defaultViteConfig,
|
|
48
|
+
resolve: {
|
|
49
|
+
alias: [
|
|
50
|
+
{
|
|
51
|
+
find: defaultViteConfig.resolve.symbole,
|
|
52
|
+
replacement: './src',
|
|
53
|
+
},
|
|
54
|
+
...defaultViteConfig.resolve.alias,
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
redirects: defaultRedirectsConfig,
|
|
59
|
+
};
|
|
60
|
+
return config;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return {
|
|
64
|
+
ssr: true,
|
|
65
|
+
vite: {
|
|
66
|
+
appType: 'custom',
|
|
67
|
+
resolve: {
|
|
68
|
+
alias: [
|
|
69
|
+
{
|
|
70
|
+
find: '@',
|
|
71
|
+
replacement: './src',
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
redirects: () => new Promise((resolve) => resolve([])),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { resolvePath } from './path.js';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
export const extensions = [
|
|
4
|
+
'.mjs',
|
|
5
|
+
'.js',
|
|
6
|
+
'.mts',
|
|
7
|
+
'.ts',
|
|
8
|
+
'.jsx',
|
|
9
|
+
'.tsx',
|
|
10
|
+
'.json',
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
* Asynchronously loads a module from a file path only in the server-side environment.
|
|
14
|
+
*
|
|
15
|
+
* @param path - The path to the module.
|
|
16
|
+
* @returns The loaded module.
|
|
17
|
+
*/
|
|
18
|
+
export const loadModuleSSR = async (path) => {
|
|
19
|
+
try {
|
|
20
|
+
let modulePath = path;
|
|
21
|
+
// Check if the module path has an extension
|
|
22
|
+
const moduleExtension = path.split('.').pop(); // eg: js or ts
|
|
23
|
+
if (!moduleExtension || !extensions.includes(`.${moduleExtension}`)) {
|
|
24
|
+
const { path: newPath } = await findModulePath(path);
|
|
25
|
+
modulePath = newPath;
|
|
26
|
+
}
|
|
27
|
+
const module = await import(/* @vite-ignore */ resolvePath(modulePath));
|
|
28
|
+
return module;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
throw new Error(error);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Finds the module path with the right extension.
|
|
36
|
+
*
|
|
37
|
+
* @param path - The path to the module.
|
|
38
|
+
* @returns The module path and extension.
|
|
39
|
+
*/
|
|
40
|
+
export const findModulePath = async (path) => {
|
|
41
|
+
try {
|
|
42
|
+
let modulePath = path;
|
|
43
|
+
let rightExtension = '';
|
|
44
|
+
// Check if the module path has an extension
|
|
45
|
+
const moduleExtension = path.split('.').pop(); // eg: js or ts
|
|
46
|
+
if (!moduleExtension || !extensions.includes(`.${moduleExtension}`)) {
|
|
47
|
+
for (let ext of extensions) {
|
|
48
|
+
const newModulePath = `${modulePath}${ext}`;
|
|
49
|
+
try {
|
|
50
|
+
await fs.access(newModulePath);
|
|
51
|
+
modulePath = newModulePath;
|
|
52
|
+
rightExtension = ext;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (modulePath === path) {
|
|
60
|
+
throw new Error(`Module "${path}" not found`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
path: modulePath,
|
|
65
|
+
extension: rightExtension,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
throw new Error(error);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
export const getDirname = async (url) => {
|
|
73
|
+
// Load the dirname function from the path module
|
|
74
|
+
// and return the dirname of the file URL
|
|
75
|
+
const { dirname } = await import('node:path');
|
|
76
|
+
const { fileURLToPath } = await import('node:url');
|
|
77
|
+
return dirname(fileURLToPath(url));
|
|
78
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
/**
|
|
3
|
+
* Adapts the provided file path to a valid URL format based on the operating system.
|
|
4
|
+
*
|
|
5
|
+
* @param path - The file path to be adapted.
|
|
6
|
+
* @returns The adapted file path in a valid URL format.
|
|
7
|
+
*/
|
|
8
|
+
export const resolvePath = (pathValue) => {
|
|
9
|
+
// Check the OS
|
|
10
|
+
const isWindows = process.platform === 'win32';
|
|
11
|
+
// Adapt the path
|
|
12
|
+
if (isWindows) {
|
|
13
|
+
return `file:///${path.normalize(pathValue)}`;
|
|
14
|
+
}
|
|
15
|
+
return path.normalize(pathValue);
|
|
16
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// core/config/defaults.ts
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
// Define core external packages
|
|
4
|
+
const CORE_EXTERNALS = [
|
|
5
|
+
// '@rasenganjs/mdx',
|
|
6
|
+
// '@rasenganjs/vercel',
|
|
7
|
+
// '@rasenganjs/netlify',
|
|
8
|
+
];
|
|
9
|
+
export const createDefaultViteConfig = (rootPath, __dirname, mode, config) => {
|
|
10
|
+
// Combine core externals with user-defined externals
|
|
11
|
+
const externals = [
|
|
12
|
+
...CORE_EXTERNALS,
|
|
13
|
+
...(Array.isArray(config.vite?.build?.external)
|
|
14
|
+
? config.vite.build.external
|
|
15
|
+
: []),
|
|
16
|
+
];
|
|
17
|
+
return {
|
|
18
|
+
...config.vite,
|
|
19
|
+
root: rootPath,
|
|
20
|
+
build: {
|
|
21
|
+
sourcemap: mode === 'development',
|
|
22
|
+
rollupOptions: {
|
|
23
|
+
external: externals,
|
|
24
|
+
input: './src/index',
|
|
25
|
+
output: {
|
|
26
|
+
manualChunks(id) {
|
|
27
|
+
if (id.includes('node_modules'))
|
|
28
|
+
return 'vendor';
|
|
29
|
+
if (id.includes('src/components'))
|
|
30
|
+
return 'shared-components';
|
|
31
|
+
if (config.ssr) {
|
|
32
|
+
if (id.includes('src/app') && id.includes('.page.')) {
|
|
33
|
+
const parts = id.split('src/app')[1]?.split('/');
|
|
34
|
+
if (parts?.length) {
|
|
35
|
+
const pageName = parts.pop()?.split('.')[0];
|
|
36
|
+
return pageName ? `page-${pageName}` : undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
outDir: 'dist',
|
|
45
|
+
chunkSizeWarningLimit: 1000,
|
|
46
|
+
},
|
|
47
|
+
environments: {
|
|
48
|
+
client: {
|
|
49
|
+
build: {
|
|
50
|
+
manifest: true,
|
|
51
|
+
outDir: 'dist/client',
|
|
52
|
+
rollupOptions: {
|
|
53
|
+
input: './src/index',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
ssr: {
|
|
58
|
+
build: {
|
|
59
|
+
outDir: 'dist/server',
|
|
60
|
+
rollupOptions: {
|
|
61
|
+
input: {
|
|
62
|
+
'entry.server': join(__dirname, './lib/esm/entries/server/entry.server.js'),
|
|
63
|
+
'app.router': './src/app/app.router',
|
|
64
|
+
main: './src/main',
|
|
65
|
+
template: './src/template',
|
|
66
|
+
config: './rasengan.config.js',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
ssrEmitAssets: false,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
resolve: {
|
|
74
|
+
alias: Array.isArray(config.vite?.resolve?.alias)
|
|
75
|
+
? config.vite.resolve.alias.map(({ find, replacement }) => ({
|
|
76
|
+
find,
|
|
77
|
+
replacement: join(rootPath, replacement),
|
|
78
|
+
}))
|
|
79
|
+
: [],
|
|
80
|
+
},
|
|
81
|
+
builder: {
|
|
82
|
+
buildApp: async (builder) => {
|
|
83
|
+
if (config.ssr) {
|
|
84
|
+
await builder.build(builder.environments.ssr);
|
|
85
|
+
}
|
|
86
|
+
await builder.build(builder.environments.client);
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
cacheDir: '.rasengan/',
|
|
90
|
+
envPrefix: 'RASENGAN_',
|
|
91
|
+
appType: 'custom',
|
|
92
|
+
};
|
|
93
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Suspense, lazy } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* It allows you to defer loading of Client Components,
|
|
5
|
+
* and only include them in the client bundle when they're needed
|
|
6
|
+
* @param load
|
|
7
|
+
* @param fallback
|
|
8
|
+
* @returns
|
|
9
|
+
*/
|
|
10
|
+
export function dynamicLoad(load, fallback = _jsx(_Fragment, {}) // Default pending UI element
|
|
11
|
+
) {
|
|
12
|
+
try {
|
|
13
|
+
const LazyComponent = lazy(load);
|
|
14
|
+
// Return a functional component preserving the exact props type
|
|
15
|
+
const WrappedComponent = (props) => (_jsx(Suspense, { fallback: fallback, children: _jsx(LazyComponent, { ...props }) }));
|
|
16
|
+
return WrappedComponent;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
throw new Error(error);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './logger.js';
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import path, { resolve } from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { loadModuleSSR } from '../config/utils/load-modules.js';
|
|
4
|
+
import { resolveBuildOptions } from '../../server.js';
|
|
5
|
+
import { renderIndexHTML } from '../../server/build/rendering.js';
|
|
6
|
+
function loadRasenganGlobal() {
|
|
7
|
+
return {
|
|
8
|
+
name: 'vite-plugin-rasengan-config',
|
|
9
|
+
async config(_, { command }) {
|
|
10
|
+
if (command !== 'build')
|
|
11
|
+
return;
|
|
12
|
+
const packageJsonPath = resolve(process.cwd(), 'package.json');
|
|
13
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
14
|
+
throw new Error(`Package.json file not found at: ${packageJsonPath}`);
|
|
15
|
+
}
|
|
16
|
+
const packageJsonRaw = fs.readFileSync(packageJsonPath, {
|
|
17
|
+
encoding: 'utf-8',
|
|
18
|
+
});
|
|
19
|
+
const packageJson = JSON.parse(packageJsonRaw);
|
|
20
|
+
const rasenganConfig = {
|
|
21
|
+
version: packageJson.version,
|
|
22
|
+
ssr: true,
|
|
23
|
+
};
|
|
24
|
+
// Inject the configuration as a global constant
|
|
25
|
+
return {
|
|
26
|
+
define: {
|
|
27
|
+
['Rasengan']: JSON.stringify(rasenganConfig),
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
apply: 'build',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function rasenganConfigPlugin() {
|
|
35
|
+
const virtualModuleId = 'virtual:rasengan-config';
|
|
36
|
+
const resolvedVirtualModuleId = '\0' + virtualModuleId;
|
|
37
|
+
return {
|
|
38
|
+
name: 'vite-plugin-rasengan-config',
|
|
39
|
+
resolveId(id) {
|
|
40
|
+
if (id === virtualModuleId) {
|
|
41
|
+
return resolvedVirtualModuleId;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
async load(id) {
|
|
45
|
+
if (id === resolvedVirtualModuleId) {
|
|
46
|
+
// if (command !== "build") return;
|
|
47
|
+
const configPath = resolve(process.cwd(), 'rasengan.config.js');
|
|
48
|
+
if (!fs.existsSync(configPath)) {
|
|
49
|
+
throw new Error(`Configuration file not found at: ${configPath}`);
|
|
50
|
+
}
|
|
51
|
+
const rasenganConfig = await (await loadModuleSSR(configPath)).default;
|
|
52
|
+
const partialConfig = {
|
|
53
|
+
server: rasenganConfig.server ?? {},
|
|
54
|
+
redirects: rasenganConfig.redirects
|
|
55
|
+
? await rasenganConfig.redirects()
|
|
56
|
+
: [],
|
|
57
|
+
};
|
|
58
|
+
return `
|
|
59
|
+
export const __RASENGAN_CONFIG__ = ${JSON.stringify(partialConfig)};
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function buildOutputInformation() {
|
|
66
|
+
const virtualModuleId = 'virtual:rasengan-build-info';
|
|
67
|
+
const resolvedVirtualModuleId = '\0' + virtualModuleId;
|
|
68
|
+
return {
|
|
69
|
+
name: 'vite-plugin-rasengan-build-info',
|
|
70
|
+
resolveId(id) {
|
|
71
|
+
if (id === virtualModuleId) {
|
|
72
|
+
return resolvedVirtualModuleId;
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
async load(id) {
|
|
76
|
+
if (id === resolvedVirtualModuleId) {
|
|
77
|
+
return `
|
|
78
|
+
export const resolveBuildOptions = (buildPath) => {
|
|
79
|
+
return {
|
|
80
|
+
buildDirectory: buildPath,
|
|
81
|
+
manifestPathDirectory: 'client/.vite',
|
|
82
|
+
assetPathDirectory: 'client/assets',
|
|
83
|
+
entryServerPath: 'server/entry.server.js',
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export const Adapters = {
|
|
92
|
+
VERCEL: 'vercel',
|
|
93
|
+
DEFAULT: '',
|
|
94
|
+
};
|
|
95
|
+
export function rasengan({ adapter = { name: Adapters.DEFAULT, prepare: async () => { } }, }) {
|
|
96
|
+
let config;
|
|
97
|
+
let viteConfig;
|
|
98
|
+
const templateFileRegex = /template\.(tsx|jsx)$/;
|
|
99
|
+
const buildOptions = resolveBuildOptions({});
|
|
100
|
+
return {
|
|
101
|
+
name: 'vite-plugin-rasengan',
|
|
102
|
+
async config() {
|
|
103
|
+
// load rasengan.config.js
|
|
104
|
+
const configPath = resolve(process.cwd(), 'rasengan.config.js');
|
|
105
|
+
if (!fs.existsSync(configPath)) {
|
|
106
|
+
throw new Error(`Configuration file not found at: ${configPath}`);
|
|
107
|
+
}
|
|
108
|
+
const rasenganConfigHandler = await (await loadModuleSSR(configPath)).default;
|
|
109
|
+
config = await rasenganConfigHandler();
|
|
110
|
+
},
|
|
111
|
+
async load(id) {
|
|
112
|
+
if (id === 'virtual:rasengan-config') {
|
|
113
|
+
return `
|
|
114
|
+
export const __RASENGAN_CONFIG__ = ${JSON.stringify(config)};
|
|
115
|
+
`;
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
configResolved(resolvedConfig) {
|
|
119
|
+
viteConfig = resolvedConfig;
|
|
120
|
+
},
|
|
121
|
+
async writeBundle(_) {
|
|
122
|
+
const modulePaths = ['template.jsx', 'template.tsx'].map((file) => {
|
|
123
|
+
return path.posix.join(process.cwd(), 'src', file);
|
|
124
|
+
});
|
|
125
|
+
const modulePath = modulePaths.find((modulePath) => {
|
|
126
|
+
return fs.existsSync(modulePath);
|
|
127
|
+
});
|
|
128
|
+
const module = await this.load({ id: modulePath });
|
|
129
|
+
// Generate the template.js file into the dist/assets
|
|
130
|
+
fs.writeFileSync(path.posix.join(process.cwd(), buildOptions.buildDirectory, buildOptions.clientPathDirectory, buildOptions.assetPathDirectory, 'template.js'), module.code, 'utf-8');
|
|
131
|
+
},
|
|
132
|
+
async closeBundle() {
|
|
133
|
+
// We check here if the environment is client has been built because it's the
|
|
134
|
+
// last environment to be built in the Vite build process
|
|
135
|
+
if (this.environment.name === 'client') {
|
|
136
|
+
// Check if SPA mode is enabled
|
|
137
|
+
if (!config.ssr) {
|
|
138
|
+
// Load the template.js file
|
|
139
|
+
const templatePath = path.posix.join(process.cwd(), buildOptions.buildDirectory, buildOptions.clientPathDirectory, buildOptions.assetPathDirectory, 'template.js');
|
|
140
|
+
const Template = (await import(templatePath)).default;
|
|
141
|
+
// Render the index.html file
|
|
142
|
+
await renderIndexHTML(Template, {
|
|
143
|
+
rootPath: process.cwd(),
|
|
144
|
+
config,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// Generate a config.json file into the dist/client/assets
|
|
148
|
+
fs.writeFileSync(path.posix.join(process.cwd(), buildOptions.buildDirectory, buildOptions.clientPathDirectory, buildOptions.assetPathDirectory, 'config.json'), JSON.stringify({
|
|
149
|
+
buildOptions,
|
|
150
|
+
ssr: config.ssr,
|
|
151
|
+
}), 'utf-8');
|
|
152
|
+
// Preparing app for deployment
|
|
153
|
+
switch (adapter.name) {
|
|
154
|
+
case Adapters.VERCEL: {
|
|
155
|
+
console.log('Preparing app for deployment to Vercel');
|
|
156
|
+
await adapter.prepare();
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
default:
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
apply: 'build',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
export const plugins = [loadRasenganGlobal()];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
export const logRedirection = (source, destination) => {
|
|
3
|
+
const time = new Date().toLocaleTimeString();
|
|
4
|
+
console.log(`${chalk.grey(time)} ${chalk.blue('[Rasengan]')} ${chalk.green('REDIRECT')}: ${chalk.grey(source)} ${chalk.green('->')} ${chalk.grey(destination)}`);
|
|
5
|
+
};
|
|
6
|
+
export const logGetRequest = (url) => {
|
|
7
|
+
const time = new Date().toLocaleTimeString();
|
|
8
|
+
console.log(`${chalk.grey(time)} ${chalk.blue('[Rasengan]')} ${chalk.green('GET')}: ${chalk.grey(url)}`);
|
|
9
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { hydrateRoot, createRoot } from 'react-dom/client';
|
|
3
|
+
import { StrictMode } from 'react';
|
|
4
|
+
import { RootComponent } from '../../routing/components/template.js';
|
|
5
|
+
const isSpaMode = window.__RASENGAN_SPA_MODE__;
|
|
6
|
+
export default function renderApp(App, options) {
|
|
7
|
+
const root = document.getElementById('root');
|
|
8
|
+
if (!root) {
|
|
9
|
+
throw new Error('Root element not found');
|
|
10
|
+
}
|
|
11
|
+
// If SPA mode, render the app
|
|
12
|
+
if (isSpaMode) {
|
|
13
|
+
if (options.reactStrictMode) {
|
|
14
|
+
createRoot(root).render(_jsx(StrictMode, { children: _jsx(App, { Component: RootComponent }) }));
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
createRoot(root).render(_jsx(App, { Component: RootComponent }));
|
|
18
|
+
}
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// Handling hydration
|
|
22
|
+
if (options.reactStrictMode) {
|
|
23
|
+
hydrateRoot(root, _jsx(StrictMode, { children: _jsx(App, { Component: RootComponent }) }));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
hydrateRoot(root, _jsx(App, { Component: RootComponent }));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { loadModuleSSR } from '../../core/config/utils/load-modules.js';
|
|
3
|
+
import { TemplateLayout } from './index.js';
|
|
4
|
+
import { join, posix } from 'path/posix';
|
|
5
|
+
import { renderToStream } from '../../server/node/rendering.js';
|
|
6
|
+
/**
|
|
7
|
+
* Render the app to a stream
|
|
8
|
+
* @param StaticRouterComponent
|
|
9
|
+
* @param helmetContext
|
|
10
|
+
* @param res
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
export const render = async (StaticRouterComponent, res, options) => {
|
|
14
|
+
const { metadata, assets, buildOptions } = options;
|
|
15
|
+
// Root path
|
|
16
|
+
const rootPath = process.cwd();
|
|
17
|
+
let App;
|
|
18
|
+
let Template;
|
|
19
|
+
if (buildOptions) {
|
|
20
|
+
App = (await loadModuleSSR(posix.join(buildOptions.buildDirectory, buildOptions.serverPathDirectory, 'main.js'))).default;
|
|
21
|
+
Template = (await loadModuleSSR(join(buildOptions.buildDirectory, buildOptions.serverPathDirectory, 'template.js'))).default;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
// Import Main App Component
|
|
25
|
+
App = (await loadModuleSSR(`${rootPath}/src/main`)).default;
|
|
26
|
+
// Import Template
|
|
27
|
+
Template = (await loadModuleSSR(`${rootPath}/src/template`)).default;
|
|
28
|
+
}
|
|
29
|
+
await renderToStream(_jsx(TemplateLayout, { StaticRouterComponent: StaticRouterComponent, metadata: metadata, assets: assets, App: App, Template: Template }), res);
|
|
30
|
+
};
|