@maravilla-labs/functions 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -0
- package/bin/cli.js +89 -0
- package/dist/dev.d.ts +7 -0
- package/dist/dev.d.ts.map +1 -0
- package/dist/dev.js +70 -0
- package/dist/dev.js.map +1 -0
- package/dist/discover.d.ts +3 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +144 -0
- package/dist/discover.js.map +1 -0
- package/dist/generator.d.ts +3 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +147 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +155 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# @maravilla-labs/functions
|
|
2
|
+
|
|
3
|
+
Maravilla Edge Functions bundler and development tools. This package provides esbuild-based bundling for edge functions, transforming multiple JavaScript function files into a single optimized bundle for WASM execution.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install --save-dev @maravilla-labs/functions
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### CLI Commands
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Build functions for production
|
|
17
|
+
npx maravilla-functions build
|
|
18
|
+
|
|
19
|
+
# Build with options
|
|
20
|
+
npx maravilla-functions build --output dist --minify --sourcemap
|
|
21
|
+
|
|
22
|
+
# Start development mode with file watching
|
|
23
|
+
npx maravilla-functions dev
|
|
24
|
+
|
|
25
|
+
# Development mode with custom output
|
|
26
|
+
npx maravilla-functions dev --output build
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Package.json Scripts
|
|
30
|
+
|
|
31
|
+
Add to your `functions/package.json`:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "maravilla-functions build",
|
|
37
|
+
"dev": "maravilla-functions dev",
|
|
38
|
+
"build:prod": "maravilla-functions build --minify"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@maravilla-labs/functions": "latest"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Function Structure
|
|
47
|
+
|
|
48
|
+
Functions should be organized in a flat or nested structure:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
functions/
|
|
52
|
+
├── package.json
|
|
53
|
+
├── hello.js
|
|
54
|
+
├── user-profile.js
|
|
55
|
+
└── auth/
|
|
56
|
+
└── login.js
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Each function file should export HTTP method handlers:
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
// hello.js
|
|
63
|
+
export const GET = (request, response) => {
|
|
64
|
+
response.json({ message: 'Hello World!' });
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const POST = (request, response) => {
|
|
68
|
+
const body = JSON.parse(request.body || '{}');
|
|
69
|
+
response.json({ received: body });
|
|
70
|
+
};
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Route Mapping
|
|
74
|
+
|
|
75
|
+
Functions are automatically mapped to API routes:
|
|
76
|
+
|
|
77
|
+
- `hello.js` → `/api/hello`
|
|
78
|
+
- `user-profile.js` → `/api/user-profile`
|
|
79
|
+
- `auth/login.js` → `/api/auth/login`
|
|
80
|
+
|
|
81
|
+
### HTTP Methods
|
|
82
|
+
|
|
83
|
+
Supported export patterns:
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// Named method exports
|
|
87
|
+
export const GET = (request, response) => { /* ... */ };
|
|
88
|
+
export const POST = (request, response) => { /* ... */ };
|
|
89
|
+
export const PUT = (request, response) => { /* ... */ };
|
|
90
|
+
export const DELETE = (request, response) => { /* ... */ };
|
|
91
|
+
|
|
92
|
+
// Default export handles all methods
|
|
93
|
+
export default (request, response) => {
|
|
94
|
+
// Handle based on request.method
|
|
95
|
+
};
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Request Object
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
{
|
|
102
|
+
method: 'GET', // HTTP method
|
|
103
|
+
url: 'http://...', // Full URL
|
|
104
|
+
path: '/api/hello', // Path part
|
|
105
|
+
query: { id: '123' }, // Query parameters as object
|
|
106
|
+
headers: { ... }, // Headers as object
|
|
107
|
+
body: '...' // Raw body string
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Response Object
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
response.status(200) // Set status code
|
|
115
|
+
response.setHeader('key', 'value') // Set header
|
|
116
|
+
response.json({ data: 'value' }) // JSON response
|
|
117
|
+
response.text('plain text') // Text response
|
|
118
|
+
response.html('<h1>HTML</h1>') // HTML response
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Build Output
|
|
122
|
+
|
|
123
|
+
The bundler generates:
|
|
124
|
+
|
|
125
|
+
- `dist/functions.js` - Single bundled JavaScript file
|
|
126
|
+
- Source maps (if enabled)
|
|
127
|
+
- Minified output (if enabled)
|
|
128
|
+
|
|
129
|
+
The bundle includes:
|
|
130
|
+
|
|
131
|
+
- All function modules with proper ES6 imports
|
|
132
|
+
- Runtime helpers (Request/Response classes)
|
|
133
|
+
- Route registry for path matching
|
|
134
|
+
- Global `handleRequest` function for WASM integration
|
|
135
|
+
|
|
136
|
+
## Integration with Maravilla CLI
|
|
137
|
+
|
|
138
|
+
The Maravilla CLI automatically detects and uses the bundled output:
|
|
139
|
+
|
|
140
|
+
1. Looks for `functions/dist/functions.js`
|
|
141
|
+
2. Compiles to QuickJS bytecode
|
|
142
|
+
3. Embeds in WASM runtime
|
|
143
|
+
4. Serves via HTTP with automatic routing
|
|
144
|
+
|
|
145
|
+
## Development Workflow
|
|
146
|
+
|
|
147
|
+
1. **Setup functions directory:**
|
|
148
|
+
```bash
|
|
149
|
+
mkdir functions
|
|
150
|
+
cd functions
|
|
151
|
+
npm init -y
|
|
152
|
+
npm install --save-dev @maravilla-labs/functions
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
2. **Add build scripts:**
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"scripts": {
|
|
159
|
+
"build": "maravilla-functions build",
|
|
160
|
+
"dev": "maravilla-functions dev"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
3. **Create function files:**
|
|
166
|
+
```javascript
|
|
167
|
+
// hello.js
|
|
168
|
+
export const GET = (request, response) => {
|
|
169
|
+
response.json({ message: 'Hello from Maravilla!' });
|
|
170
|
+
};
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
4. **Build and serve:**
|
|
174
|
+
```bash
|
|
175
|
+
npm run build
|
|
176
|
+
maravilla serve --dev --framework-port 5173
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Features
|
|
180
|
+
|
|
181
|
+
- ✅ **esbuild-powered** - Fast, reliable bundling
|
|
182
|
+
- ✅ **ES6 modules** - Native import/export support
|
|
183
|
+
- ✅ **File watching** - Automatic rebuilds in dev mode
|
|
184
|
+
- ✅ **Source maps** - Debug support
|
|
185
|
+
- ✅ **Minification** - Production optimization
|
|
186
|
+
- ✅ **Route mapping** - Automatic API route generation
|
|
187
|
+
- ✅ **Method detection** - HTTP method analysis
|
|
188
|
+
- ✅ **WASM integration** - Seamless CLI integration
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
Proprietary. © 2025 SOLUTAS GmbH, Switzerland. All rights reserved.
|
|
193
|
+
Use is governed by the root LICENSE file or a separate written agreement
|
|
194
|
+
with SOLUTAS GmbH.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { buildFunctions, developmentServer } from '../dist/index.js';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8'));
|
|
12
|
+
|
|
13
|
+
const command = process.argv[2];
|
|
14
|
+
const args = process.argv.slice(3);
|
|
15
|
+
|
|
16
|
+
function parseArgs(args) {
|
|
17
|
+
const options = {};
|
|
18
|
+
for (let i = 0; i < args.length; i++) {
|
|
19
|
+
if (args[i].startsWith('--')) {
|
|
20
|
+
const key = args[i].slice(2);
|
|
21
|
+
const value = args[i + 1] && !args[i + 1].startsWith('--') ? args[i + 1] : true;
|
|
22
|
+
options[key] = value;
|
|
23
|
+
if (value !== true) i++;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return options;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (command === 'build') {
|
|
30
|
+
const options = parseArgs(args);
|
|
31
|
+
const buildOptions = {
|
|
32
|
+
functionsDir: options.dir || process.env.FUNCTIONS_DIR || 'functions',
|
|
33
|
+
outputDir: options.output || process.env.OUTPUT_DIR || '.maravilla',
|
|
34
|
+
production: options.production || process.env.NODE_ENV === 'production',
|
|
35
|
+
minify: options.minify || process.env.NODE_ENV === 'production',
|
|
36
|
+
sourcemap: options.sourcemap === true || process.env.SOURCEMAP === 'true',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
console.log('🚀 Building Maravilla functions...');
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const manifest = await buildFunctions(buildOptions);
|
|
43
|
+
if (manifest) {
|
|
44
|
+
console.log(`✅ Built ${manifest.functions} functions successfully`);
|
|
45
|
+
process.exit(0);
|
|
46
|
+
} else {
|
|
47
|
+
console.log('ℹ️ No functions found to build');
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('❌ Build failed:', error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
} else if (command === 'dev') {
|
|
55
|
+
const options = parseArgs(args);
|
|
56
|
+
const devOptions = {
|
|
57
|
+
functionsDir: options.dir || process.env.FUNCTIONS_DIR || 'functions',
|
|
58
|
+
outputDir: options.output || process.env.OUTPUT_DIR || '.maravilla',
|
|
59
|
+
watch: options.watch !== 'false',
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
console.log('🚀 Starting Maravilla functions development server...');
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
await developmentServer(devOptions);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error('❌ Dev server failed:', error);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
} else if (command === '--version' || command === '-v') {
|
|
71
|
+
console.log(packageJson.version);
|
|
72
|
+
process.exit(0);
|
|
73
|
+
} else {
|
|
74
|
+
console.log('Maravilla Functions CLI v' + packageJson.version);
|
|
75
|
+
console.log('\nUsage:');
|
|
76
|
+
console.log(' @maravilla/functions build [options] Build functions for production');
|
|
77
|
+
console.log(' @maravilla/functions dev [options] Start development server with hot reload');
|
|
78
|
+
console.log('\nBuild Options:');
|
|
79
|
+
console.log(' --dir <path> Functions directory (default: functions)');
|
|
80
|
+
console.log(' --output <path> Output directory (default: .maravilla)');
|
|
81
|
+
console.log(' --minify Minify output');
|
|
82
|
+
console.log(' --sourcemap Generate sourcemaps');
|
|
83
|
+
console.log(' --production Production build');
|
|
84
|
+
console.log('\nDev Options:');
|
|
85
|
+
console.log(' --dir <path> Functions directory (default: functions)');
|
|
86
|
+
console.log(' --output <path> Output directory (default: .maravilla)');
|
|
87
|
+
console.log(' --watch <bool> Watch for changes (default: true)');
|
|
88
|
+
process.exit(command ? 1 : 0);
|
|
89
|
+
}
|
package/dist/dev.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BuildOptions } from './types.js';
|
|
2
|
+
export interface DevServerOptions extends BuildOptions {
|
|
3
|
+
watch?: boolean;
|
|
4
|
+
onRebuild?: () => void;
|
|
5
|
+
}
|
|
6
|
+
export declare function developmentServer(options?: DevServerOptions): Promise<(() => void) | undefined>;
|
|
7
|
+
//# sourceMappingURL=dev.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,gBAAqB,qCAoFrE"}
|
package/dist/dev.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { watch } from 'chokidar';
|
|
2
|
+
import { buildFunctions } from './index.js';
|
|
3
|
+
export async function developmentServer(options = {}) {
|
|
4
|
+
const { functionsDir = 'functions', outputDir = '.maravilla', watch: watchFiles = true, onRebuild, ...buildOptions } = options;
|
|
5
|
+
console.log('🚀 Starting functions development server...');
|
|
6
|
+
// Initial build
|
|
7
|
+
await buildFunctions({
|
|
8
|
+
functionsDir,
|
|
9
|
+
outputDir,
|
|
10
|
+
...buildOptions,
|
|
11
|
+
production: false,
|
|
12
|
+
});
|
|
13
|
+
if (!watchFiles) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
// Watch for changes
|
|
17
|
+
const watcher = watch(functionsDir, {
|
|
18
|
+
ignored: [
|
|
19
|
+
'**/node_modules/**',
|
|
20
|
+
'**/.git/**',
|
|
21
|
+
'**/dist/**',
|
|
22
|
+
'**/.maravilla/**'
|
|
23
|
+
],
|
|
24
|
+
persistent: true,
|
|
25
|
+
ignoreInitial: true,
|
|
26
|
+
});
|
|
27
|
+
let buildTimeout = null;
|
|
28
|
+
const rebuild = async () => {
|
|
29
|
+
if (buildTimeout) {
|
|
30
|
+
clearTimeout(buildTimeout);
|
|
31
|
+
}
|
|
32
|
+
buildTimeout = setTimeout(async () => {
|
|
33
|
+
console.log('\n🔄 Rebuilding functions...');
|
|
34
|
+
try {
|
|
35
|
+
await buildFunctions({
|
|
36
|
+
functionsDir,
|
|
37
|
+
outputDir,
|
|
38
|
+
...buildOptions,
|
|
39
|
+
production: false,
|
|
40
|
+
});
|
|
41
|
+
if (onRebuild) {
|
|
42
|
+
onRebuild();
|
|
43
|
+
}
|
|
44
|
+
console.log('✅ Functions rebuilt successfully');
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error('❌ Failed to rebuild functions:', error);
|
|
48
|
+
}
|
|
49
|
+
}, 100);
|
|
50
|
+
};
|
|
51
|
+
watcher
|
|
52
|
+
.on('add', path => {
|
|
53
|
+
console.log(` Added: ${path}`);
|
|
54
|
+
rebuild();
|
|
55
|
+
})
|
|
56
|
+
.on('change', path => {
|
|
57
|
+
console.log(` Changed: ${path}`);
|
|
58
|
+
rebuild();
|
|
59
|
+
})
|
|
60
|
+
.on('unlink', path => {
|
|
61
|
+
console.log(` Removed: ${path}`);
|
|
62
|
+
rebuild();
|
|
63
|
+
});
|
|
64
|
+
console.log(`👀 Watching for changes in ${functionsDir}...`);
|
|
65
|
+
// Return cleanup function
|
|
66
|
+
return () => {
|
|
67
|
+
watcher.close();
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=dev.js.map
|
package/dist/dev.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQ5C,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAA4B,EAAE;IACpE,MAAM,EACJ,YAAY,GAAG,WAAW,EAC1B,SAAS,GAAG,YAAY,EACxB,KAAK,EAAE,UAAU,GAAG,IAAI,EACxB,SAAS,EACT,GAAG,YAAY,EAChB,GAAG,OAAO,CAAC;IAEZ,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAE3D,gBAAgB;IAChB,MAAM,cAAc,CAAC;QACnB,YAAY;QACZ,SAAS;QACT,GAAG,YAAY;QACf,UAAU,EAAE,KAAK;KAClB,CAAC,CAAC;IAEH,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;IACT,CAAC;IAED,oBAAoB;IACpB,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,EAAE;QAClC,OAAO,EAAE;YACP,oBAAoB;YACpB,YAAY;YACZ,YAAY;YACZ,kBAAkB;SACnB;QACD,UAAU,EAAE,IAAI;QAChB,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC;IAEH,IAAI,YAAY,GAA0B,IAAI,CAAC;IAE/C,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,IAAI,YAAY,EAAE,CAAC;YACjB,YAAY,CAAC,YAAY,CAAC,CAAC;QAC7B,CAAC;QAED,YAAY,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;YACnC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAE5C,IAAI,CAAC;gBACH,MAAM,cAAc,CAAC;oBACnB,YAAY;oBACZ,SAAS;oBACT,GAAG,YAAY;oBACf,UAAU,EAAE,KAAK;iBAClB,CAAC,CAAC;gBAEH,IAAI,SAAS,EAAE,CAAC;oBACd,SAAS,EAAE,CAAC;gBACd,CAAC;gBAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;YAClD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;YACzD,CAAC;QACH,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC,CAAC;IAEF,OAAO;SACJ,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE;QAChB,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;SACD,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE;QACnB,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAClC,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;SACD,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE;QACnB,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAClC,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IAEL,OAAO,CAAC,GAAG,CAAC,8BAA8B,YAAY,KAAK,CAAC,CAAC;IAE7D,0BAA0B;IAC1B,OAAO,GAAG,EAAE;QACV,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../src/discover.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEpE,wBAAsB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAO1F"}
|
package/dist/discover.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import { join, relative } from 'node:path';
|
|
3
|
+
export async function discoverFunctions(functionsDir) {
|
|
4
|
+
const functions = {};
|
|
5
|
+
const routes = {};
|
|
6
|
+
await walkDirectory(functionsDir, functionsDir, functions, routes);
|
|
7
|
+
return { functions, routes };
|
|
8
|
+
}
|
|
9
|
+
async function walkDirectory(baseDir, currentDir, functions, routes) {
|
|
10
|
+
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
11
|
+
for (const entry of entries) {
|
|
12
|
+
const fullPath = join(currentDir, entry.name);
|
|
13
|
+
if (entry.isDirectory()) {
|
|
14
|
+
// Skip dist and node_modules
|
|
15
|
+
if (entry.name === 'dist' || entry.name === 'node_modules' || entry.name.startsWith('.')) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
// Check if this is a function directory with package.json
|
|
19
|
+
const packageJsonPath = join(fullPath, 'package.json');
|
|
20
|
+
const hasPackageJson = await fs.access(packageJsonPath).then(() => true).catch(() => false);
|
|
21
|
+
if (hasPackageJson) {
|
|
22
|
+
// This is a function package - look for src directory
|
|
23
|
+
const srcPath = join(fullPath, 'src');
|
|
24
|
+
const hasSrc = await fs.access(srcPath).then(() => true).catch(() => false);
|
|
25
|
+
if (hasSrc) {
|
|
26
|
+
// Walk the src directory for this function
|
|
27
|
+
await walkDirectory(baseDir, srcPath, functions, routes);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// Fallback to the function directory itself
|
|
31
|
+
await walkDirectory(baseDir, fullPath, functions, routes);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Regular directory, continue walking
|
|
36
|
+
await walkDirectory(baseDir, fullPath, functions, routes);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else if (entry.isFile() && (entry.name.endsWith('.js') || entry.name.endsWith('.ts'))) {
|
|
40
|
+
// Skip test files and type definition files
|
|
41
|
+
if (entry.name.includes('.test.') || entry.name.includes('.spec.') || entry.name.endsWith('.d.ts')) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const relativePath = relative(baseDir, fullPath);
|
|
45
|
+
const functionInfo = await analyzeFunction(fullPath, relativePath);
|
|
46
|
+
if (functionInfo) {
|
|
47
|
+
functions[functionInfo.name] = functionInfo;
|
|
48
|
+
routes[functionInfo.route] = functionInfo;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function analyzeFunction(filePath, relativePath) {
|
|
54
|
+
try {
|
|
55
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
56
|
+
// Generate function name from file path
|
|
57
|
+
const name = generateFunctionName(relativePath);
|
|
58
|
+
// Generate route from file path
|
|
59
|
+
const route = generateRoute(relativePath);
|
|
60
|
+
// Analyze supported HTTP methods
|
|
61
|
+
const methods = analyzeMethods(content);
|
|
62
|
+
// Skip files that don't export any HTTP methods
|
|
63
|
+
if (methods.length === 0) {
|
|
64
|
+
console.log(` Skipping ${relativePath} - no HTTP methods detected`);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
name,
|
|
69
|
+
route,
|
|
70
|
+
methods,
|
|
71
|
+
filePath,
|
|
72
|
+
relativePath,
|
|
73
|
+
importPath: filePath,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.warn(` Failed to analyze function ${relativePath}:`, error);
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function generateFunctionName(relativePath) {
|
|
82
|
+
// Convert path to camelCase function name
|
|
83
|
+
// e.g., "auth/login.js" -> "authLogin"
|
|
84
|
+
const pathWithoutExt = relativePath.replace(/\.(js|ts)$/, '');
|
|
85
|
+
const parts = pathWithoutExt.split(/[\/\\]/);
|
|
86
|
+
return parts
|
|
87
|
+
.map((part, index) => {
|
|
88
|
+
// Remove index suffix from filenames
|
|
89
|
+
if (part === 'index') {
|
|
90
|
+
return '';
|
|
91
|
+
}
|
|
92
|
+
// Convert kebab-case to camelCase
|
|
93
|
+
const camelCased = part.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
94
|
+
// Capitalize first letter of each part except the first
|
|
95
|
+
return index === 0 ? camelCased : camelCased.charAt(0).toUpperCase() + camelCased.slice(1);
|
|
96
|
+
})
|
|
97
|
+
.filter(Boolean)
|
|
98
|
+
.join('');
|
|
99
|
+
}
|
|
100
|
+
function generateRoute(relativePath) {
|
|
101
|
+
// Convert path to API route
|
|
102
|
+
// e.g., "auth/login.js" -> "/api/auth/login"
|
|
103
|
+
// e.g., "index.js" -> "/api"
|
|
104
|
+
let pathWithoutExt = relativePath.replace(/\.(js|ts)$/, '');
|
|
105
|
+
// Handle index files
|
|
106
|
+
if (pathWithoutExt === 'index') {
|
|
107
|
+
return '/api';
|
|
108
|
+
}
|
|
109
|
+
// Remove index from path parts
|
|
110
|
+
const parts = pathWithoutExt.split(/[\/\\]/).filter(part => part !== 'index');
|
|
111
|
+
// Convert to kebab-case
|
|
112
|
+
const routeParts = parts.map(part => part.replace(/([A-Z])/g, '-$1').toLowerCase());
|
|
113
|
+
return '/api/' + routeParts.join('/');
|
|
114
|
+
}
|
|
115
|
+
function analyzeMethods(content) {
|
|
116
|
+
const methods = [];
|
|
117
|
+
const httpMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
|
|
118
|
+
// Look for exported HTTP method handlers
|
|
119
|
+
for (const method of httpMethods) {
|
|
120
|
+
// Check for named exports
|
|
121
|
+
if (content.includes(`export const ${method}`) ||
|
|
122
|
+
content.includes(`export function ${method}`) ||
|
|
123
|
+
content.includes(`export async function ${method}`)) {
|
|
124
|
+
methods.push(method);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Check for default export that handles all methods
|
|
128
|
+
if (methods.length === 0) {
|
|
129
|
+
const hasDefaultExport = content.includes('export default');
|
|
130
|
+
if (hasDefaultExport) {
|
|
131
|
+
// Check if it looks like a request handler
|
|
132
|
+
const looksLikeHandler = content.includes('request') ||
|
|
133
|
+
content.includes('Request') ||
|
|
134
|
+
content.includes('req.method') ||
|
|
135
|
+
content.includes('request.method');
|
|
136
|
+
if (looksLikeHandler) {
|
|
137
|
+
// Default export handles all methods
|
|
138
|
+
methods.push(...httpMethods);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return methods;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=discover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../src/discover.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GACnC,MAAM,CAsJR"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
export function generateEntryFile(functions, routes) {
|
|
2
|
+
let code = `// Maravilla Edge Functions Entry Point
|
|
3
|
+
// Auto-generated file - do not edit
|
|
4
|
+
|
|
5
|
+
`;
|
|
6
|
+
// Import all functions
|
|
7
|
+
for (const [name, func] of Object.entries(functions)) {
|
|
8
|
+
code += `import * as ${name}_exports from '${func.importPath}';\n`;
|
|
9
|
+
}
|
|
10
|
+
code += `
|
|
11
|
+
// Route registry
|
|
12
|
+
const ROUTE_REGISTRY = ${JSON.stringify(routes, null, 2)};
|
|
13
|
+
|
|
14
|
+
// Function registry - map function names to their exports
|
|
15
|
+
const FUNCTION_REGISTRY = {
|
|
16
|
+
`;
|
|
17
|
+
for (const [name] of Object.entries(functions)) {
|
|
18
|
+
code += ` '${name}': ${name}_exports,\n`;
|
|
19
|
+
}
|
|
20
|
+
code += `};
|
|
21
|
+
|
|
22
|
+
// Main request handler for functions
|
|
23
|
+
export async function handleFunctionRequest(request) {
|
|
24
|
+
const url = new URL(request.url);
|
|
25
|
+
const path = url.pathname;
|
|
26
|
+
|
|
27
|
+
// Find matching function
|
|
28
|
+
let functionInfo = ROUTE_REGISTRY[path];
|
|
29
|
+
if (!functionInfo) {
|
|
30
|
+
// Try to match with trailing slash removed
|
|
31
|
+
const pathWithoutSlash = path.replace(/\\/$/, '');
|
|
32
|
+
functionInfo = ROUTE_REGISTRY[pathWithoutSlash];
|
|
33
|
+
|
|
34
|
+
if (!functionInfo) {
|
|
35
|
+
return new Response(
|
|
36
|
+
JSON.stringify({ error: 'Function not found', path }),
|
|
37
|
+
{
|
|
38
|
+
status: 404,
|
|
39
|
+
headers: { 'content-type': 'application/json' }
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Get function exports
|
|
46
|
+
const functionExports = FUNCTION_REGISTRY[functionInfo.name];
|
|
47
|
+
if (!functionExports) {
|
|
48
|
+
return new Response(
|
|
49
|
+
JSON.stringify({ error: 'Function not registered', function: functionInfo.name }),
|
|
50
|
+
{
|
|
51
|
+
status: 500,
|
|
52
|
+
headers: { 'content-type': 'application/json' }
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Find the appropriate handler
|
|
58
|
+
let handler = null;
|
|
59
|
+
const method = request.method.toUpperCase();
|
|
60
|
+
|
|
61
|
+
// Check for specific method handler
|
|
62
|
+
if (functionExports[method]) {
|
|
63
|
+
handler = functionExports[method];
|
|
64
|
+
} else if (functionExports.default) {
|
|
65
|
+
// Use default export as fallback
|
|
66
|
+
handler = functionExports.default;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!handler) {
|
|
70
|
+
return new Response(
|
|
71
|
+
JSON.stringify({
|
|
72
|
+
error: 'Method not allowed',
|
|
73
|
+
method: request.method,
|
|
74
|
+
allowed: functionInfo.methods
|
|
75
|
+
}),
|
|
76
|
+
{
|
|
77
|
+
status: 405,
|
|
78
|
+
headers: {
|
|
79
|
+
'content-type': 'application/json',
|
|
80
|
+
'allow': functionInfo.methods.join(', ')
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
// Call the handler - await the result
|
|
88
|
+
const response = await handler(request);
|
|
89
|
+
|
|
90
|
+
// If handler returns a Response object, use it directly
|
|
91
|
+
if (response instanceof Response) {
|
|
92
|
+
return response;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Otherwise, wrap the result in a Response
|
|
96
|
+
return new Response(
|
|
97
|
+
JSON.stringify(response),
|
|
98
|
+
{
|
|
99
|
+
status: 200,
|
|
100
|
+
headers: { 'content-type': 'application/json' }
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('Function execution error:', error);
|
|
105
|
+
|
|
106
|
+
return new Response(
|
|
107
|
+
JSON.stringify({
|
|
108
|
+
error: 'Function execution failed',
|
|
109
|
+
message: error.message,
|
|
110
|
+
stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
|
|
111
|
+
}),
|
|
112
|
+
{
|
|
113
|
+
status: 500,
|
|
114
|
+
headers: { 'content-type': 'application/json' }
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Export route matcher for runtime integration
|
|
121
|
+
export function matchFunctionRoute(path) {
|
|
122
|
+
// Direct match
|
|
123
|
+
if (ROUTE_REGISTRY[path]) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Try without trailing slash
|
|
128
|
+
const pathWithoutSlash = path.replace(/\\/$/, '');
|
|
129
|
+
if (ROUTE_REGISTRY[pathWithoutSlash]) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Export function metadata
|
|
137
|
+
export const functionMetadata = {
|
|
138
|
+
routes: Object.keys(ROUTE_REGISTRY),
|
|
139
|
+
functions: Object.keys(FUNCTION_REGISTRY),
|
|
140
|
+
count: Object.keys(FUNCTION_REGISTRY).length,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
console.log(\`✅ Edge functions router initialized with \${functionMetadata.count} functions\`);
|
|
144
|
+
`;
|
|
145
|
+
return code;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,iBAAiB,CAC/B,SAAuC,EACvC,MAAoC;IAEpC,IAAI,IAAI,GAAG;;;CAGZ,CAAC;IAEA,uBAAuB;IACvB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,IAAI,IAAI,eAAe,IAAI,kBAAkB,IAAI,CAAC,UAAU,MAAM,CAAC;IACrE,CAAC;IAED,IAAI,IAAI;;yBAEe,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;;;;CAIvD,CAAC;IAEA,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/C,IAAI,IAAI,MAAM,IAAI,MAAM,IAAI,aAAa,CAAC;IAC5C,CAAC;IAED,IAAI,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4HT,CAAC;IAEA,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FunctionManifest, BuildOptions } from './types.js';
|
|
2
|
+
export { discoverFunctions } from './discover.js';
|
|
3
|
+
export { developmentServer } from './dev.js';
|
|
4
|
+
export type { FunctionManifest, FunctionRoute, BuildOptions } from './types.js';
|
|
5
|
+
export declare function buildFunctions(options?: BuildOptions): Promise<FunctionManifest | null>;
|
|
6
|
+
export declare function integrateWithManifest(manifestPath: string, functionsManifest: FunctionManifest | null): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhF,wBAAsB,cAAc,CAAC,OAAO,GAAE,YAAiB,oCAwG9D;AAwCD,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,gBAAgB,GAAG,IAAI,iBAyC3C"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import * as esbuild from 'esbuild';
|
|
4
|
+
import { discoverFunctions } from './discover.js';
|
|
5
|
+
import { generateEntryFile } from './generator.js';
|
|
6
|
+
export { discoverFunctions } from './discover.js';
|
|
7
|
+
export { developmentServer } from './dev.js';
|
|
8
|
+
export async function buildFunctions(options = {}) {
|
|
9
|
+
const { functionsDir = 'functions', outputDir = '.maravilla', minify = false, sourcemap = false, production = false, } = options;
|
|
10
|
+
const resolvedFunctionsDir = resolve(functionsDir);
|
|
11
|
+
const resolvedOutputDir = resolve(outputDir);
|
|
12
|
+
console.log('🔨 Building edge functions...');
|
|
13
|
+
console.log(` Functions directory: ${resolvedFunctionsDir}`);
|
|
14
|
+
console.log(` Output directory: ${resolvedOutputDir}`);
|
|
15
|
+
// Check if functions directory exists
|
|
16
|
+
const hasFunctions = await fs.access(resolvedFunctionsDir).then(() => true).catch(() => false);
|
|
17
|
+
if (!hasFunctions) {
|
|
18
|
+
console.log(' No functions directory found, skipping functions build');
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
// Check for and install function dependencies if needed
|
|
22
|
+
await installFunctionDependencies(resolvedFunctionsDir);
|
|
23
|
+
// Discover all functions
|
|
24
|
+
const { functions, routes } = await discoverFunctions(resolvedFunctionsDir);
|
|
25
|
+
if (Object.keys(functions).length === 0) {
|
|
26
|
+
console.log(' No functions found in directory');
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
console.log(`📦 Found ${Object.keys(functions).length} functions:`);
|
|
30
|
+
for (const [route, func] of Object.entries(routes)) {
|
|
31
|
+
console.log(` ${route} → ${func.name} (${func.methods.join(', ')})`);
|
|
32
|
+
}
|
|
33
|
+
// Create output directory
|
|
34
|
+
await fs.mkdir(resolvedOutputDir, { recursive: true });
|
|
35
|
+
// Create temp directory for build
|
|
36
|
+
const tempDir = join(resolvedOutputDir, '.temp');
|
|
37
|
+
await fs.mkdir(tempDir, { recursive: true });
|
|
38
|
+
// Generate entry file
|
|
39
|
+
const entryContent = generateEntryFile(functions, routes);
|
|
40
|
+
const entryPath = join(tempDir, 'functions-entry.js');
|
|
41
|
+
await fs.writeFile(entryPath, entryContent);
|
|
42
|
+
// Bundle with esbuild
|
|
43
|
+
const result = await esbuild.build({
|
|
44
|
+
entryPoints: [entryPath],
|
|
45
|
+
bundle: true,
|
|
46
|
+
outfile: join(resolvedOutputDir, 'functions.js'),
|
|
47
|
+
format: 'esm',
|
|
48
|
+
platform: 'neutral',
|
|
49
|
+
target: 'es2022',
|
|
50
|
+
minify: minify || production,
|
|
51
|
+
sourcemap: sourcemap,
|
|
52
|
+
external: [
|
|
53
|
+
// Platform APIs are provided by runtime
|
|
54
|
+
'@maravilla/platform',
|
|
55
|
+
],
|
|
56
|
+
define: {
|
|
57
|
+
'process.env.NODE_ENV': production ? '"production"' : '"development"'
|
|
58
|
+
},
|
|
59
|
+
metafile: true,
|
|
60
|
+
});
|
|
61
|
+
// Clean up temp directory
|
|
62
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
63
|
+
// Generate functions manifest
|
|
64
|
+
const functionsManifest = {
|
|
65
|
+
version: 1,
|
|
66
|
+
functions: Object.keys(functions).length,
|
|
67
|
+
routes: Object.entries(routes).map(([path, func]) => ({
|
|
68
|
+
path,
|
|
69
|
+
name: func.name,
|
|
70
|
+
methods: func.methods,
|
|
71
|
+
file: func.relativePath,
|
|
72
|
+
})),
|
|
73
|
+
bundle: 'functions.js',
|
|
74
|
+
buildTime: new Date().toISOString(),
|
|
75
|
+
};
|
|
76
|
+
// Write functions manifest
|
|
77
|
+
await fs.writeFile(join(resolvedOutputDir, 'functions.json'), JSON.stringify(functionsManifest, null, 2));
|
|
78
|
+
if (result.metafile) {
|
|
79
|
+
const analysis = await esbuild.analyzeMetafile(result.metafile);
|
|
80
|
+
console.log('\nBundle analysis:');
|
|
81
|
+
console.log(analysis);
|
|
82
|
+
}
|
|
83
|
+
console.log('✅ Functions build completed successfully!');
|
|
84
|
+
return functionsManifest;
|
|
85
|
+
}
|
|
86
|
+
async function installFunctionDependencies(functionsDir) {
|
|
87
|
+
try {
|
|
88
|
+
const entries = await fs.readdir(functionsDir, { withFileTypes: true });
|
|
89
|
+
for (const entry of entries) {
|
|
90
|
+
if (entry.isDirectory()) {
|
|
91
|
+
const funcDir = join(functionsDir, entry.name);
|
|
92
|
+
const packageJsonPath = join(funcDir, 'package.json');
|
|
93
|
+
// Check if function has package.json
|
|
94
|
+
const hasPackageJson = await fs.access(packageJsonPath).then(() => true).catch(() => false);
|
|
95
|
+
if (hasPackageJson) {
|
|
96
|
+
// Check if node_modules exists
|
|
97
|
+
const nodeModulesPath = join(funcDir, 'node_modules');
|
|
98
|
+
const hasNodeModules = await fs.access(nodeModulesPath).then(() => true).catch(() => false);
|
|
99
|
+
if (!hasNodeModules) {
|
|
100
|
+
console.log(` 📦 Installing dependencies for function: ${entry.name}`);
|
|
101
|
+
const { exec } = await import('child_process');
|
|
102
|
+
const { promisify } = await import('util');
|
|
103
|
+
const execAsync = promisify(exec);
|
|
104
|
+
try {
|
|
105
|
+
// Try npm first, then pnpm if available
|
|
106
|
+
await execAsync('npm install', { cwd: funcDir });
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.warn(` Warning: Failed to install dependencies for ${entry.name}:`, error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.warn(' Warning: Could not check for function dependencies:', error);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export async function integrateWithManifest(manifestPath, functionsManifest) {
|
|
121
|
+
if (!functionsManifest) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// Read existing manifest
|
|
125
|
+
const manifestContent = await fs.readFile(manifestPath, 'utf-8');
|
|
126
|
+
const manifest = JSON.parse(manifestContent);
|
|
127
|
+
// Add functions section to manifest
|
|
128
|
+
manifest.functions = {
|
|
129
|
+
enabled: true,
|
|
130
|
+
bundle: functionsManifest.bundle,
|
|
131
|
+
routes: functionsManifest.routes.map(route => ({
|
|
132
|
+
...route,
|
|
133
|
+
// Ensure all function routes start with /api
|
|
134
|
+
path: route.path.startsWith('/api') ? route.path : `/api${route.path}`,
|
|
135
|
+
})),
|
|
136
|
+
metadata: {
|
|
137
|
+
count: functionsManifest.functions,
|
|
138
|
+
buildTime: functionsManifest.buildTime,
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
// Update routing to include functions
|
|
142
|
+
if (!manifest.routing) {
|
|
143
|
+
manifest.routing = {};
|
|
144
|
+
}
|
|
145
|
+
// Add functions routes to routing configuration
|
|
146
|
+
manifest.routing.functions = functionsManifest.routes.map(route => ({
|
|
147
|
+
path: route.path.startsWith('/api') ? route.path : `/api${route.path}`,
|
|
148
|
+
methods: route.methods,
|
|
149
|
+
handler: 'function',
|
|
150
|
+
}));
|
|
151
|
+
// Write updated manifest
|
|
152
|
+
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
153
|
+
console.log('📝 Updated manifest.json with functions configuration');
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface FunctionInfo {
|
|
2
|
+
name: string;
|
|
3
|
+
route: string;
|
|
4
|
+
methods: string[];
|
|
5
|
+
filePath: string;
|
|
6
|
+
relativePath: string;
|
|
7
|
+
importPath: string;
|
|
8
|
+
}
|
|
9
|
+
export interface FunctionRoute {
|
|
10
|
+
path: string;
|
|
11
|
+
name: string;
|
|
12
|
+
methods: string[];
|
|
13
|
+
file: string;
|
|
14
|
+
}
|
|
15
|
+
export interface FunctionManifest {
|
|
16
|
+
version: number;
|
|
17
|
+
functions: number;
|
|
18
|
+
routes: FunctionRoute[];
|
|
19
|
+
bundle: string;
|
|
20
|
+
buildTime: string;
|
|
21
|
+
}
|
|
22
|
+
export interface BuildOptions {
|
|
23
|
+
functionsDir?: string;
|
|
24
|
+
outputDir?: string;
|
|
25
|
+
minify?: boolean;
|
|
26
|
+
sourcemap?: boolean;
|
|
27
|
+
production?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface DiscoveredFunctions {
|
|
30
|
+
functions: Record<string, FunctionInfo>;
|
|
31
|
+
routes: Record<string, FunctionInfo>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACtC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@maravilla-labs/functions",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Maravilla Edge Functions bundler and development tools",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"bin"
|
|
17
|
+
],
|
|
18
|
+
"bin": {
|
|
19
|
+
"maravilla-functions": "./bin/cli.js"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"dev": "tsc --watch",
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"prepack": "pnpm build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"edge-functions",
|
|
29
|
+
"serverless",
|
|
30
|
+
"bundler",
|
|
31
|
+
"maravilla",
|
|
32
|
+
"runtime"
|
|
33
|
+
],
|
|
34
|
+
"author": "SOLUTAS GmbH",
|
|
35
|
+
"license": "Proprietary",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/solutas/maravilla-runtime.git",
|
|
39
|
+
"directory": "packages/functions"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"esbuild": "^0.25.8",
|
|
46
|
+
"chokidar": "^3.5.3"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^20.10.5",
|
|
50
|
+
"typescript": "^5.3.3"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=18.0.0"
|
|
54
|
+
}
|
|
55
|
+
}
|