ionbeam 1.0.0-alpha.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.
Files changed (46) hide show
  1. package/README.md +81 -0
  2. package/bin/ionbeam.js +47 -0
  3. package/dist/build/index.d.ts +18 -0
  4. package/dist/build/index.d.ts.map +1 -0
  5. package/dist/build/index.js +181 -0
  6. package/dist/build/index.js.map +1 -0
  7. package/dist/cli/build.d.ts +2 -0
  8. package/dist/cli/build.d.ts.map +1 -0
  9. package/dist/cli/build.js +17 -0
  10. package/dist/cli/build.js.map +1 -0
  11. package/dist/cli/dev.d.ts +2 -0
  12. package/dist/cli/dev.d.ts.map +1 -0
  13. package/dist/cli/dev.js +58 -0
  14. package/dist/cli/dev.js.map +1 -0
  15. package/dist/cli/start.d.ts +2 -0
  16. package/dist/cli/start.d.ts.map +1 -0
  17. package/dist/cli/start.js +20 -0
  18. package/dist/cli/start.js.map +1 -0
  19. package/dist/components/Page/index.d.ts +7 -0
  20. package/dist/components/Page/index.d.ts.map +1 -0
  21. package/dist/components/Page/index.js +7 -0
  22. package/dist/components/Page/index.js.map +1 -0
  23. package/dist/components/Page/page.css +35 -0
  24. package/dist/components-bundle.js +10 -0
  25. package/dist/index.d.ts +8 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +8 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/ioncore.css +1 -0
  30. package/dist/server/index.d.ts +26 -0
  31. package/dist/server/index.d.ts.map +1 -0
  32. package/dist/server/index.js +42 -0
  33. package/dist/server/index.js.map +1 -0
  34. package/dist/types.d.ts +6 -0
  35. package/dist/types.d.ts.map +1 -0
  36. package/dist/types.js +2 -0
  37. package/dist/types.js.map +1 -0
  38. package/dist/utils/assets-context.d.ts +8 -0
  39. package/dist/utils/assets-context.d.ts.map +1 -0
  40. package/dist/utils/assets-context.js +8 -0
  41. package/dist/utils/assets-context.js.map +1 -0
  42. package/dist/utils/manifest.d.ts +3 -0
  43. package/dist/utils/manifest.d.ts.map +1 -0
  44. package/dist/utils/manifest.js +24 -0
  45. package/dist/utils/manifest.js.map +1 -0
  46. package/package.json +69 -0
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # IonBeam
2
+
3
+ A pure React SSR framework with automatic asset hashing, CSS modules, and zero configuration.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Server-Side Rendering** - Built-in SSR with React 19
8
+ - 🎨 **CSS Modules** - Scoped styles with automatic class name hashing
9
+ - 📦 **Asset Hashing** - Automatic content-based hashing for cache busting
10
+ - 🔧 **Zero Config** - Works out of the box with sensible defaults
11
+ - ⚡ **Fast Development** - Hot reload with file watching
12
+ - 📝 **TypeScript First** - Full TypeScript support
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install ionbeam react react-dom
18
+ # or
19
+ pnpm add ionbeam react react-dom
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ 1. Create your server (`src/server.tsx`):
25
+
26
+ ```tsx
27
+ import { createServer, IonCoreRequest } from 'ioncore';
28
+ import { Request, Response } from 'express';
29
+ import { HomePage } from './pages/HomePage/index.js';
30
+
31
+ const app = createServer();
32
+
33
+ // Define routes with full Express flexibility
34
+ app.get('/', async (req: Request, res: Response) => {
35
+ await req.ioncore?.render(<HomePage />);
36
+ });
37
+
38
+ app.listen(3000, () => {
39
+ console.log('Server running on http://localhost:3000');
40
+ });
41
+ ```
42
+
43
+ 2. Create a page using the built-in `Page` component (`src/pages/HomePage/index.tsx`):
44
+
45
+ ```tsx
46
+ import { JSX } from "react";
47
+ import { Page } from "ioncore";
48
+
49
+ export const HomePage = (): JSX.Element => {
50
+ return (
51
+ <Page title="Home">
52
+ <h1>Welcome to IonBeam!</h1>
53
+ <p>A flexible React SSR framework</p>
54
+ </Page>
55
+ );
56
+ };
57
+ ```
58
+
59
+ 3. Add scripts to your `package.json`:
60
+
61
+ ```json
62
+ {
63
+ "scripts": {
64
+ "dev": "ioncore dev",
65
+ "build": "ioncore build",
66
+ "start": "ioncore start"
67
+ }
68
+ }
69
+ ```
70
+
71
+ 4. Run your app:
72
+
73
+ ```bash
74
+ npm run dev
75
+ ```
76
+
77
+ ## CLI Commands
78
+
79
+ - `ioncore dev` - Start development server with watch mode
80
+ - `ioncore build` - Build for production
81
+ - `ioncore start` - Start production server
package/bin/ionbeam.js ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { dirname, join } from 'node:path';
6
+ import { readFileSync } from 'node:fs';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+
11
+ // Read package.json for version
12
+ const packageJson = JSON.parse(
13
+ readFileSync(join(__dirname, '../package.json'), 'utf-8')
14
+ );
15
+
16
+ const program = new Command();
17
+
18
+ program
19
+ .name('ionbeam')
20
+ .description('IonBeam - Pure React SSR Framework')
21
+ .version(packageJson.version);
22
+
23
+ program
24
+ .command('build')
25
+ .description('Build the application for production')
26
+ .action(async () => {
27
+ const { build } = await import('../dist/cli/build.js');
28
+ await build();
29
+ });
30
+
31
+ program
32
+ .command('dev')
33
+ .description('Start development server with watch mode')
34
+ .action(async () => {
35
+ const { dev } = await import('../dist/cli/dev.js');
36
+ await dev();
37
+ });
38
+
39
+ program
40
+ .command('start')
41
+ .description('Start production server')
42
+ .action(async () => {
43
+ const { start } = await import('../dist/cli/start.js');
44
+ await start();
45
+ });
46
+
47
+ program.parse();
@@ -0,0 +1,18 @@
1
+ interface BuildOptions {
2
+ rootDir: string;
3
+ outDir: string;
4
+ }
5
+ export declare class Builder {
6
+ private cssFileName;
7
+ private clientFileName;
8
+ private options;
9
+ constructor(options: BuildOptions);
10
+ buildServer(): Promise<void>;
11
+ buildClient(): Promise<void>;
12
+ generateManifest(): Promise<void>;
13
+ copyStaticFiles(): Promise<void>;
14
+ clean(): Promise<void>;
15
+ build(): Promise<void>;
16
+ }
17
+ export {};
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/build/index.ts"],"names":[],"mappings":"AASA,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,OAAO;IAClB,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,OAAO,CAAe;gBAEX,OAAO,EAAE,YAAY;IAI3B,WAAW;IAsElB,WAAW;IA2DX,gBAAgB;IAsBhB,eAAe;IAuBf,KAAK;IAKL,KAAK;CAOZ"}
@@ -0,0 +1,181 @@
1
+ import { rollup } from 'rollup';
2
+ import typescript from '@rollup/plugin-typescript';
3
+ import { nodeResolve } from '@rollup/plugin-node-resolve';
4
+ import postcss from 'rollup-plugin-postcss';
5
+ import fs from 'node:fs/promises';
6
+ import { glob } from 'glob';
7
+ import crypto from 'node:crypto';
8
+ import path from 'node:path';
9
+ export class Builder {
10
+ cssFileName = null;
11
+ clientFileName = null;
12
+ options;
13
+ constructor(options) {
14
+ this.options = options;
15
+ }
16
+ async buildServer() {
17
+ const { rootDir, outDir } = this.options;
18
+ try {
19
+ const bundle = await rollup({
20
+ input: path.join(rootDir, 'src/server.tsx'),
21
+ external: (id) => {
22
+ // External all node_modules
23
+ return !id.startsWith('.') && !id.startsWith('/');
24
+ },
25
+ plugins: [
26
+ // @ts-expect-error --- IGNORE ---
27
+ postcss({
28
+ modules: {
29
+ generateScopedName: '[local]-[hash:6]',
30
+ localsConvention: 'camelCaseOnly',
31
+ },
32
+ extract: true,
33
+ inject: false,
34
+ }),
35
+ // Custom plugin to hash and track CSS file
36
+ {
37
+ name: 'css-hash',
38
+ generateBundle: (_options, bundle) => {
39
+ // Find the CSS file in the bundle
40
+ for (const [fileName, asset] of Object.entries(bundle)) {
41
+ if (fileName.endsWith('.css') && asset.type === 'asset') {
42
+ // Generate hash from CSS content
43
+ const hash = crypto
44
+ .createHash('sha256')
45
+ .update(asset.source)
46
+ .digest('hex')
47
+ .substring(0, 8);
48
+ // Create new filename with hash
49
+ const newFileName = `static/server-${hash}.css`;
50
+ this.cssFileName = `server-${hash}.css`;
51
+ // Update the asset's fileName
52
+ asset.fileName = newFileName;
53
+ }
54
+ }
55
+ },
56
+ },
57
+ nodeResolve({
58
+ extensions: ['.ts', '.tsx'],
59
+ }),
60
+ // @ts-expect-error --- IGNORE ---
61
+ typescript({
62
+ tsconfig: path.join(rootDir, 'tsconfig.json'),
63
+ declaration: false,
64
+ sourceMap: true,
65
+ }),
66
+ ],
67
+ });
68
+ await bundle.write({
69
+ dir: outDir,
70
+ entryFileNames: 'server.js',
71
+ format: 'esm',
72
+ sourcemap: true,
73
+ });
74
+ await bundle.close();
75
+ }
76
+ catch (error) {
77
+ console.error('Server build failed:', error);
78
+ throw error;
79
+ }
80
+ }
81
+ async buildClient() {
82
+ const { rootDir, outDir } = this.options;
83
+ try {
84
+ const clientFiles = await glob('src/**/client.ts', { cwd: rootDir, absolute: true });
85
+ if (clientFiles.length === 0) {
86
+ console.log('No client files found, skipping client bundle');
87
+ return;
88
+ }
89
+ const bundle = await rollup({
90
+ input: clientFiles,
91
+ plugins: [
92
+ postcss.default({
93
+ modules: {
94
+ generateScopedName: '[local]-[hash:8]',
95
+ localsConvention: 'camelCaseOnly',
96
+ },
97
+ inject: true,
98
+ }),
99
+ nodeResolve({
100
+ extensions: ['.ts', '.tsx'],
101
+ browser: true,
102
+ }),
103
+ typescript.default({
104
+ tsconfig: path.join(rootDir, 'tsconfig.json'),
105
+ declaration: false,
106
+ declarationMap: false,
107
+ sourceMap: true,
108
+ outDir: path.join(outDir, 'static'),
109
+ compilerOptions: {
110
+ lib: ['ES2022', 'DOM'],
111
+ },
112
+ }),
113
+ ],
114
+ });
115
+ const { output } = await bundle.write({
116
+ dir: path.join(outDir, 'static'),
117
+ entryFileNames: 'client-[hash:8].js',
118
+ format: 'iife',
119
+ sourcemap: true,
120
+ });
121
+ // Store client JS filename
122
+ for (const chunk of output) {
123
+ if (chunk.type === 'chunk' && chunk.isEntry) {
124
+ this.clientFileName = chunk.fileName;
125
+ }
126
+ }
127
+ await bundle.close();
128
+ }
129
+ catch (error) {
130
+ console.error('Client build failed:', error);
131
+ throw error;
132
+ }
133
+ }
134
+ async generateManifest() {
135
+ const { outDir } = this.options;
136
+ const manifest = {};
137
+ // Add client JS to manifest
138
+ if (this.clientFileName) {
139
+ manifest['client.js'] = this.clientFileName;
140
+ }
141
+ // Add CSS filename from server build to manifest
142
+ if (this.cssFileName) {
143
+ manifest['server.css'] = this.cssFileName;
144
+ }
145
+ await fs.mkdir(path.join(outDir, 'static'), { recursive: true });
146
+ await fs.writeFile(path.join(outDir, 'static/manifest.json'), JSON.stringify(manifest, null, 2));
147
+ }
148
+ async copyStaticFiles() {
149
+ const { rootDir, outDir } = this.options;
150
+ const staticDir = path.join(rootDir, 'src/static');
151
+ const targetDir = path.join(outDir, 'static');
152
+ try {
153
+ await fs.mkdir(targetDir, { recursive: true });
154
+ const files = await glob('**/*', { cwd: staticDir, nodir: true });
155
+ for (const file of files) {
156
+ const srcFile = path.join(staticDir, file);
157
+ const destFile = path.join(targetDir, file);
158
+ await fs.mkdir(path.dirname(destFile), { recursive: true });
159
+ await fs.copyFile(srcFile, destFile);
160
+ }
161
+ }
162
+ catch (error) {
163
+ // Static directory might not exist, that's okay
164
+ if (error.code !== 'ENOENT') {
165
+ throw error;
166
+ }
167
+ }
168
+ }
169
+ async clean() {
170
+ const { outDir } = this.options;
171
+ await fs.rm(outDir, { recursive: true, force: true });
172
+ }
173
+ async build() {
174
+ await this.clean();
175
+ await this.buildServer();
176
+ await this.buildClient();
177
+ await this.copyStaticFiles();
178
+ await this.generateManifest();
179
+ }
180
+ }
181
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/build/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function build(): Promise<void>;
2
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAGA,wBAAsB,KAAK,kBAe1B"}
@@ -0,0 +1,17 @@
1
+ import { Builder } from '../build/index.js';
2
+ import path from 'node:path';
3
+ export async function build() {
4
+ const rootDir = process.cwd();
5
+ const outDir = path.join(rootDir, 'dist');
6
+ console.log('Building application...');
7
+ const builder = new Builder({ rootDir, outDir });
8
+ try {
9
+ await builder.build();
10
+ console.log('✓ Build completed successfully!');
11
+ }
12
+ catch (error) {
13
+ console.error('✗ Build failed:', error);
14
+ process.exit(1);
15
+ }
16
+ }
17
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAE1C,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAEvC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function dev(): Promise<void>;
2
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAmBA,wBAAsB,GAAG,kBA+CxB"}
@@ -0,0 +1,58 @@
1
+ import { Builder } from '../build/index.js';
2
+ import path from 'node:path';
3
+ import { watch } from 'chokidar';
4
+ import { spawn } from 'node:child_process';
5
+ let serverProcess = null;
6
+ function startServer() {
7
+ if (serverProcess) {
8
+ serverProcess.kill();
9
+ }
10
+ const serverPath = path.join(process.cwd(), 'dist/server.js');
11
+ serverProcess = spawn('node', [serverPath], {
12
+ stdio: 'inherit',
13
+ env: { ...process.env, NODE_ENV: 'development' },
14
+ });
15
+ }
16
+ export async function dev() {
17
+ const rootDir = process.cwd();
18
+ const outDir = path.join(rootDir, 'dist');
19
+ console.log('Starting development server...');
20
+ const builder = new Builder({ rootDir, outDir });
21
+ // Initial build
22
+ try {
23
+ await builder.build();
24
+ console.log('✓ Initial build completed!');
25
+ startServer();
26
+ }
27
+ catch (error) {
28
+ console.error('✗ Build failed:', error);
29
+ process.exit(1);
30
+ }
31
+ // Watch for changes
32
+ const watcher = watch('src/**/*.{ts,tsx,css}', {
33
+ cwd: rootDir,
34
+ ignoreInitial: true,
35
+ });
36
+ watcher.on('change', async (filePath) => {
37
+ console.log(`\nFile changed: ${filePath}`);
38
+ console.log('Rebuilding...');
39
+ try {
40
+ await builder.build();
41
+ console.log('✓ Rebuild completed!');
42
+ startServer();
43
+ }
44
+ catch (error) {
45
+ console.error('✗ Rebuild failed:', error);
46
+ }
47
+ });
48
+ // Handle process termination
49
+ process.on('SIGINT', () => {
50
+ if (serverProcess) {
51
+ serverProcess.kill();
52
+ }
53
+ watcher.close();
54
+ process.exit(0);
55
+ });
56
+ console.log('\n👀 Watching for changes...\n');
57
+ }
58
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,IAAI,aAAa,GAAoC,IAAI,CAAC;AAE1D,SAAS,WAAW;IAClB,IAAI,aAAa,EAAE,CAAC;QAClB,aAAa,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAC9D,aAAa,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE;QAC1C,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE;KACjD,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG;IACvB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAE1C,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAE9C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAEjD,gBAAgB;IAChB,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,WAAW,EAAE,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,oBAAoB;IACpB,MAAM,OAAO,GAAG,KAAK,CAAC,uBAAuB,EAAE;QAC7C,GAAG,EAAE,OAAO;QACZ,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;QACtC,OAAO,CAAC,GAAG,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAE7B,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACpC,WAAW,EAAE,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,IAAI,aAAa,EAAE,CAAC;YAClB,aAAa,CAAC,IAAI,EAAE,CAAC;QACvB,CAAC;QACD,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function start(): Promise<void>;
2
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"AAGA,wBAAsB,KAAK,kBAoB1B"}
@@ -0,0 +1,20 @@
1
+ import { spawn } from 'node:child_process';
2
+ import path from 'node:path';
3
+ export async function start() {
4
+ const serverPath = path.join(process.cwd(), 'dist/server.js');
5
+ console.log('Starting production server...');
6
+ const serverProcess = spawn('node', [serverPath], {
7
+ stdio: 'inherit',
8
+ env: { ...process.env, NODE_ENV: 'production' },
9
+ });
10
+ serverProcess.on('error', (error) => {
11
+ console.error('Failed to start server:', error);
12
+ process.exit(1);
13
+ });
14
+ // Handle process termination
15
+ process.on('SIGINT', () => {
16
+ serverProcess.kill();
17
+ process.exit(0);
18
+ });
19
+ }
20
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAE9D,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAE7C,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE;QAChD,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE;KAChD,CAAC,CAAC;IAEH,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAClC,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,aAAa,CAAC,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { JSX } from "react";
2
+ export interface PageProps {
3
+ title: string;
4
+ children: React.ReactNode;
5
+ }
6
+ export declare const Page: ({ children, title }: PageProps) => JSX.Element;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Page/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,IAAI,GAAI,qBAAqB,SAAS,KAAG,GAAG,CAAC,OAkBzD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAssets } from "../../utils/assets-context.js";
3
+ export const Page = ({ children, title }) => {
4
+ const { styleSheet, clientScript } = useAssets();
5
+ return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charSet: "UTF-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), _jsx("title", { children: title }), styleSheet && _jsx("link", { rel: "stylesheet", href: `/${styleSheet}` }), clientScript && _jsx("script", { src: `/${clientScript}`, defer: true })] }), _jsx("body", { children: children })] }));
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Page/index.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAO1D,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAa,EAAe,EAAE;IAClE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,SAAS,EAAE,CAAC;IAEjD,OAAO,CACL,gBAAM,IAAI,EAAC,IAAI,aACb,2BACE,eAAM,OAAO,EAAC,OAAO,GAAG,EACxB,eAAM,IAAI,EAAC,UAAU,EAAC,OAAO,EAAC,uCAAuC,GAAG,EACxE,0BAAQ,KAAK,GAAS,EACrB,UAAU,IAAI,eAAM,GAAG,EAAC,YAAY,EAAC,IAAI,EAAE,IAAI,UAAU,EAAE,GAAI,EAC/D,YAAY,IAAI,iBAAQ,GAAG,EAAE,IAAI,YAAY,EAAE,EAAE,KAAK,SAAG,IACrD,EAEP,yBACG,QAAQ,GACJ,IACF,CACR,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,35 @@
1
+ :root {
2
+ --bg-primary: #1C1C1C;
3
+ --text-primary: #F5E8D8;
4
+
5
+ --spacing-md: 1rem;
6
+ }
7
+
8
+ *,
9
+ *::before,
10
+ *::after {
11
+ box-sizing: border-box;
12
+ margin: 0;
13
+ padding: 0;
14
+ }
15
+
16
+ html {
17
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
18
+ font-size: 16px;
19
+ scroll-behavior: smooth;
20
+ }
21
+
22
+ body {
23
+ min-height: 100dvh;
24
+ line-height: 1.5;
25
+ color: var(--text-primary);
26
+ background-color: var(--bg-primary);
27
+ -webkit-font-smoothing: antialiased;
28
+ -moz-osx-font-smoothing: grayscale;
29
+ }
30
+
31
+ .container {
32
+ max-width: 1200px;
33
+ margin: 0 auto;
34
+ padding: 0 var(--spacing-md);
35
+ }
@@ -0,0 +1,10 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+
3
+ const Page = ({ children, title = "IonCore", description, request }) => {
4
+ const clientScript = request.ioncore.clientScript;
5
+ const styleSheet = request.ioncore.styleSheet;
6
+ const ionCoreCSS = request.ioncore.assets.get('ioncore.css');
7
+ return (jsxs("html", { lang: "en", children: [jsxs("head", { children: [jsx("meta", { charSet: "UTF-8" }), jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), description && jsx("meta", { name: "description", content: description }), jsx("title", { children: title }), ionCoreCSS && jsx("link", { rel: "stylesheet", href: `/${ionCoreCSS}` }), styleSheet && jsx("link", { rel: "stylesheet", href: `/${styleSheet}` }), clientScript && jsx("script", { src: `/${clientScript}`, defer: true })] }), jsx("body", { children: children })] }));
8
+ };
9
+
10
+ export { Page };
@@ -0,0 +1,8 @@
1
+ export { createServer, ionBeamMiddleware } from './server/index.js';
2
+ export type { ServerOptions, IonBeam } from './server/index.js';
3
+ export { Page } from './components/Page/index.js';
4
+ export type { PageProps } from './components/Page/index.js';
5
+ export type { IonBeamRequest } from './types.js';
6
+ export { getAsset, getManifest } from './utils/manifest.js';
7
+ export { Builder } from './build/index.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACpE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAClD,YAAY,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAG5D,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // Server exports
2
+ export { createServer, ionBeamMiddleware } from './server/index.js';
3
+ export { Page } from './components/Page/index.js';
4
+ // Utility exports
5
+ export { getAsset, getManifest } from './utils/manifest.js';
6
+ // Build exports (for advanced users)
7
+ export { Builder } from './build/index.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iBAAiB;AACjB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAMlD,kBAAkB;AAClB,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE5D,qCAAqC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1 @@
1
+ :root{--bg-primary:#1c1c1c;--text-primary:#f5e8d8;--spacing-md:1rem}*,:after,:before{box-sizing:border-box;margin:0;padding:0}html{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:16px;scroll-behavior:smooth}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:var(--bg-primary);color:var(--text-primary);line-height:1.5;min-height:100dvh}.container{margin:0 auto;max-width:1200px;padding:0 var(--spacing-md)}
@@ -0,0 +1,26 @@
1
+ import { JSX } from 'react/jsx-runtime';
2
+ import { Express, Request, Response, NextFunction } from 'express';
3
+ declare global {
4
+ namespace Express {
5
+ interface Request {
6
+ ionbeam: IonBeam;
7
+ }
8
+ }
9
+ }
10
+ export interface IonBeam {
11
+ render: (component: JSX.Element) => Promise<void>;
12
+ }
13
+ export interface ServerOptions {
14
+ staticDir?: string;
15
+ }
16
+ /**
17
+ * Middleware that adds IonBeam context to request object
18
+ * This allows route handlers to access assets and rendering utilities
19
+ */
20
+ export declare function ionBeamMiddleware(options?: ServerOptions): (req: Request, res: Response, next: NextFunction) => void;
21
+ /**
22
+ * Create an Express server with IonBeam defaults
23
+ * Returns a configured Express app that you can customize
24
+ */
25
+ export declare function createServer(options?: ServerOptions): Express;
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAO5E,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,OAAO,EAAE,OAAO,CAAC;SAClB;KACF;CACF;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,aAAkB,IACnD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAqBxD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAajE"}
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import express from 'express';
3
+ import { prerenderToNodeStream } from 'react-dom/static';
4
+ import { getAsset } from '../utils/manifest.js';
5
+ import { AssetsProvider } from '../utils/assets-context.js';
6
+ import path from 'node:path';
7
+ /**
8
+ * Middleware that adds IonBeam context to request object
9
+ * This allows route handlers to access assets and rendering utilities
10
+ */
11
+ export function ionBeamMiddleware(options = {}) {
12
+ return (req, res, next) => {
13
+ const clientScript = getAsset('client.js');
14
+ const styleSheet = getAsset('server.css');
15
+ console.log('IonBeam Middleware: Attaching IonBeam context to request');
16
+ console.log(` - Client Script: ${clientScript}`);
17
+ console.log(` - Style Sheet: ${styleSheet}`);
18
+ req.ionbeam = {
19
+ render: async (element) => {
20
+ const { prelude } = await prerenderToNodeStream(_jsx(AssetsProvider, { value: { clientScript, styleSheet }, children: element }));
21
+ prelude.pipe(res);
22
+ },
23
+ };
24
+ next();
25
+ };
26
+ }
27
+ /**
28
+ * Create an Express server with IonBeam defaults
29
+ * Returns a configured Express app that you can customize
30
+ */
31
+ export function createServer(options = {}) {
32
+ const app = express();
33
+ const staticDir = options.staticDir || path.join(process.cwd(), 'dist', 'static');
34
+ // Default middleware
35
+ app.use(express.static(staticDir));
36
+ app.use(express.urlencoded({ extended: true }));
37
+ app.use(express.json());
38
+ // Add IonBeam context to all requests
39
+ app.use(ionBeamMiddleware(options));
40
+ return app;
41
+ }
42
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.tsx"],"names":[],"mappings":";AACA,OAAO,OAAqD,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,IAAI,MAAM,WAAW,CAAC;AAmB7B;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAyB,EAAE;IAC3D,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,MAAM,YAAY,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;QAE1C,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,qBAAqB,YAAY,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,mBAAmB,UAAU,EAAE,CAAC,CAAC;QAE7C,GAAG,CAAC,OAAO,GAAG;YACZ,MAAM,EAAE,KAAK,EAAE,OAAwB,EAAE,EAAE;gBACzC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,qBAAqB,CAC7C,KAAC,cAAc,IAAC,KAAK,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,YAChD,OAAO,GACO,CAClB,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;SACF,CAAC;QAEF,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,UAAyB,EAAE;IACtD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAElF,qBAAqB;IACrB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExB,sCAAsC;IACtC,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;IAEpC,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Request as ExpressRequest } from 'express';
2
+ import { IonBeam } from './server/index.js';
3
+ export interface IonBeamRequest extends ExpressRequest {
4
+ ionbeam: IonBeam;
5
+ }
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,OAAO,EAAE,OAAO,CAAC;CAClB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export interface AssetsContextValue {
2
+ styleSheet: string | null;
3
+ clientScript: string | null;
4
+ }
5
+ export declare const AssetsContext: import("react").Context<AssetsContextValue>;
6
+ export declare const AssetsProvider: import("react").Provider<AssetsContextValue>;
7
+ export declare const useAssets: () => AssetsContextValue;
8
+ //# sourceMappingURL=assets-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets-context.d.ts","sourceRoot":"","sources":["../../src/utils/assets-context.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,eAAO,MAAM,aAAa,6CAGxB,CAAC;AAEH,eAAO,MAAM,cAAc,8CAAyB,CAAC;AAErD,eAAO,MAAM,SAAS,QAAO,kBAA+C,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { createContext, useContext } from "react";
2
+ export const AssetsContext = createContext({
3
+ styleSheet: null,
4
+ clientScript: null,
5
+ });
6
+ export const AssetsProvider = AssetsContext.Provider;
7
+ export const useAssets = () => useContext(AssetsContext);
8
+ //# sourceMappingURL=assets-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets-context.js","sourceRoot":"","sources":["../../src/utils/assets-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAOlD,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAqB;IAC7D,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,IAAI;CACnB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC;AAErD,MAAM,CAAC,MAAM,SAAS,GAAG,GAAuB,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const getManifest: () => Record<string, string>;
2
+ export declare const getAsset: (assetName: string) => string | null;
3
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW,QAAO,MAAM,CAAC,MAAM,EAAE,MAAM,CAenD,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,WAAW,MAAM,KAAG,MAAM,GAAG,IAGrD,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ let manifestCache = null;
4
+ export const getManifest = () => {
5
+ if (manifestCache !== null) {
6
+ return manifestCache;
7
+ }
8
+ try {
9
+ const manifestPath = join(process.cwd(), 'dist', 'static', 'manifest.json');
10
+ const manifestContent = readFileSync(manifestPath, 'utf-8');
11
+ const manifest = JSON.parse(manifestContent);
12
+ manifestCache = manifest;
13
+ return manifest;
14
+ }
15
+ catch (error) {
16
+ console.warn('Could not read manifest.json, client scripts may not be available');
17
+ return {};
18
+ }
19
+ };
20
+ export const getAsset = (assetName) => {
21
+ const manifest = getManifest();
22
+ return manifest[assetName] ?? null;
23
+ };
24
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,IAAI,aAAa,GAAkC,IAAI,CAAC;AAExD,MAAM,CAAC,MAAM,WAAW,GAAG,GAA2B,EAAE;IACtD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;QAC5E,MAAM,eAAe,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC7C,aAAa,GAAG,QAAQ,CAAC;QACzB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;QAClF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,SAAiB,EAAiB,EAAE;IAC3D,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,OAAO,QAAQ,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;AACrC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "ionbeam",
3
+ "version": "1.0.0-alpha.1",
4
+ "description": "A pure React SSR framework with automatic asset hashing and CSS modules",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "ionbeam": "./bin/ionbeam.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ },
16
+ "./server": {
17
+ "types": "./dist/server/index.d.ts",
18
+ "import": "./dist/server/index.js"
19
+ },
20
+ "./utils": {
21
+ "types": "./dist/utils/manifest.d.ts",
22
+ "import": "./dist/utils/manifest.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "bin"
28
+ ],
29
+ "scripts": {
30
+ "build": "tsc",
31
+ "prepublishOnly": "npm run build"
32
+ },
33
+ "keywords": [
34
+ "react",
35
+ "ssr",
36
+ "framework",
37
+ "server-side-rendering",
38
+ "css-modules"
39
+ ],
40
+ "author": {
41
+ "name": "Martin Podloucký",
42
+ "email": "podlouckymartin@gmail.com"
43
+ },
44
+ "license": "MIT",
45
+ "peerDependencies": {
46
+ "react": "^19.0.0",
47
+ "react-dom": "^19.0.0"
48
+ },
49
+ "dependencies": {
50
+ "@rollup/plugin-node-resolve": "^16.0.3",
51
+ "@rollup/plugin-typescript": "^12.3.0",
52
+ "chokidar": "^4.0.3",
53
+ "commander": "^12.1.0",
54
+ "express": "^5.2.1",
55
+ "glob": "^13.0.0",
56
+ "postcss": "^8.5.6",
57
+ "postcss-modules": "^6.0.1",
58
+ "rollup": "^4.54.0",
59
+ "rollup-plugin-postcss": "^4.0.2",
60
+ "tslib": "^2.8.1",
61
+ "typescript": "^5.9.3"
62
+ },
63
+ "devDependencies": {
64
+ "@types/express": "^5.0.6",
65
+ "@types/node": "^20.4.2",
66
+ "@types/react": "^19.2.7",
67
+ "@types/react-dom": "^19.2.3"
68
+ }
69
+ }