@maravilla-labs/adapter-sveltekit 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 ADDED
@@ -0,0 +1,432 @@
1
+ # @maravilla-labs/adapter-sveltekit
2
+
3
+ SvelteKit adapter for Maravilla Runtime - deploy your SvelteKit applications to the edge with built-in KV, Database, and platform services.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -D @solutas/adapter-sveltekit
9
+ # or
10
+ pnpm add -D @solutas/adapter-sveltekit
11
+ # or
12
+ yarn add -D @solutas/adapter-sveltekit
13
+ ```
14
+
15
+ Also install the platform client and Vite plugin:
16
+
17
+ ```bash
18
+ pnpm add @maravilla/platform
19
+ pnpm add -D @solutas/vite-plugin
20
+ ```
21
+
22
+ ## Setup
23
+
24
+ ### 1. Configure the Adapter
25
+
26
+ Update your `svelte.config.js`:
27
+
28
+ ```javascript
29
+ import adapter from '@solutas/adapter-sveltekit';
30
+
31
+ const config = {
32
+ kit: {
33
+ adapter: adapter({
34
+ // Optional configuration
35
+ out: '.maravilla', // Output directory (default: .maravilla)
36
+ precompress: false, // Pre-compress static assets (default: false)
37
+ polyfill: true // Include polyfills (default: true)
38
+ }),
39
+ },
40
+ };
41
+
42
+ export default config;
43
+ ```
44
+
45
+ ### 2. Enable the Vite plugin
46
+
47
+ Add `@solutas/vite-plugin` in `vite.config.ts` to wire the dev server and inject the platform during development:
48
+
49
+ ```ts
50
+ import { defineConfig } from 'vite';
51
+ import { sveltekit } from '@sveltejs/kit/vite';
52
+ import { maravilla, maravillaFunctions } from '@solutas/vite-plugin';
53
+
54
+ export default defineConfig({
55
+ plugins: [
56
+ sveltekit(),
57
+ maravilla({
58
+ devServerUrl: 'http://localhost:3001',
59
+ tenant: 'demo-tenant'
60
+ }),
61
+ // Optional: hot-reload local edge functions
62
+ maravillaFunctions({
63
+ functionsDir: './functions',
64
+ watch: true
65
+ })
66
+ ]
67
+ });
68
+ ```
69
+
70
+ ### 3. Use Platform Services
71
+
72
+ Use the platform client in your SvelteKit routes:
73
+
74
+ ```typescript
75
+ // src/routes/+page.server.ts
76
+ import { getPlatform } from '@maravilla/platform';
77
+ import type { PageServerLoad } from './$types';
78
+
79
+ export const load: PageServerLoad = async () => {
80
+ const platform = getPlatform();
81
+
82
+ // Use KV store
83
+ // Namespaced example from the demo
84
+ const cachedData = await platform.env.KV.demo.get('homepage:data');
85
+
86
+ // Use database
87
+ const users = await platform.env.DB.find('users', { active: true });
88
+
89
+ return {
90
+ data: cachedData ?? null,
91
+ users,
92
+ };
93
+ };
94
+ ```
95
+
96
+ ## Development Workflow
97
+
98
+ ### 1. Install Dependencies
99
+
100
+ ```bash
101
+ pnpm install
102
+ ```
103
+
104
+ ### 2. Development Mode
105
+
106
+ Pick one of the flows below.
107
+
108
+ Option A — All-in-one (CLI orchestrates platform and Vite):
109
+ ```bash
110
+ maravilla dev
111
+ ```
112
+
113
+ Option B — Manual (start platform and Vite separately):
114
+ ```bash
115
+ pnpm dev:platform # starts platform dev server on :3001 (see demo package.json)
116
+ pnpm dev
117
+ ```
118
+
119
+ Your app will run on http://localhost:5173 with platform services proxied to http://localhost:3001.
120
+
121
+ ### 3. Production Build
122
+
123
+ ```bash
124
+ # Build the application
125
+ pnpm build
126
+
127
+ # Preview the production build
128
+ maravilla preview .maravilla
129
+ ```
130
+
131
+ This creates a `.maravilla/` directory with:
132
+ - `manifest.json` - Platform configuration
133
+ - `server.js` - Server-side application bundle
134
+ - `server.js.map` - Source maps
135
+ - `static/` - Pre-rendered pages and static assets
136
+
137
+ ## Build Output
138
+
139
+ The adapter generates an optimized bundle structure:
140
+
141
+ ```
142
+ .maravilla/
143
+ ├── manifest.json # Platform configuration (runtime v2)
144
+ ├── server.js # Main server bundle
145
+ ├── server.js.map # Source maps
146
+ └── static/ # Static assets + prerendered pages
147
+ ├── _app/ # Client-side JS/CSS
148
+ ├── favicon.svg
149
+ └── index.html # Pre-rendered pages
150
+ ```
151
+
152
+ ### Manifest Configuration
153
+
154
+ The generated `manifest.json` (v2) includes:
155
+
156
+ ```json
157
+ {
158
+ "version": 2,
159
+ "runtime": "maravilla",
160
+ "entrypoint": "server.js",
161
+ "static": "static",
162
+ "routing": {
163
+ "prerendered": ["/index.html"],
164
+ "assets": ["/_app/...", "/favicon.svg", "/robots.txt"],
165
+ "dynamic": { "api": "/api/*", "serverRoutes": "/*" }
166
+ },
167
+ "routes": { "include": ["/*"], "exclude": [] },
168
+ "env": { "prefix": "PUBLIC_" },
169
+ "features": { "ssr": true, "polyfill": true, "compression": false }
170
+ }
171
+ ```
172
+
173
+ ## Platform Services
174
+
175
+ ### KV Store
176
+
177
+ Perfect for caching, session storage, and simple key-value data (demo-style namespace shown):
178
+
179
+ ```typescript
180
+ // src/routes/api/cache/+server.ts
181
+ import { getPlatform } from '@maravilla/platform';
182
+ import { json } from '@sveltejs/kit';
183
+
184
+ export async function GET({ params }) {
185
+ const platform = getPlatform();
186
+ const value = await platform.env.KV.demo.get(`cache:${params.key}`);
187
+
188
+ return json({ value });
189
+ }
190
+
191
+ export async function PUT({ params, request }) {
192
+ const platform = getPlatform();
193
+ const data = await request.json();
194
+
195
+ await platform.env.KV.demo.put(
196
+ `cache:${params.key}`,
197
+ data,
198
+ { expirationTtl: 3600 } // 1 hour TTL
199
+ );
200
+
201
+ return json({ success: true });
202
+ }
203
+ ```
204
+
205
+ ### Database (MongoDB-style)
206
+
207
+ Document database with rich query capabilities:
208
+
209
+ ```typescript
210
+ // src/routes/users/+page.server.ts
211
+ import { getPlatform } from '@maravilla/platform';
212
+ import type { Actions, PageServerLoad } from './$types';
213
+
214
+ export const load: PageServerLoad = async () => {
215
+ const platform = getPlatform();
216
+
217
+ const users = await platform.env.DB.find('users', {
218
+ active: true,
219
+ }, {
220
+ sort: { createdAt: -1 },
221
+ limit: 20,
222
+ });
223
+
224
+ return { users };
225
+ };
226
+
227
+ export const actions: Actions = {
228
+ create: async ({ request }) => {
229
+ const platform = getPlatform();
230
+ const formData = await request.formData();
231
+
232
+ const result = await platform.env.DB.insertOne('users', {
233
+ name: formData.get('name'),
234
+ email: formData.get('email'),
235
+ active: true,
236
+ createdAt: new Date(),
237
+ });
238
+
239
+ return { success: true, id: result.insertedId };
240
+ },
241
+
242
+ toggle: async ({ request }) => {
243
+ const platform = getPlatform();
244
+ const formData = await request.formData();
245
+ const userId = formData.get('id');
246
+
247
+ await platform.env.DB.updateOne('users',
248
+ { _id: userId },
249
+ { $set: { active: formData.get('active') === 'true' } }
250
+ );
251
+
252
+ return { success: true };
253
+ },
254
+ };
255
+ ```
256
+
257
+ ## Environment Variables
258
+
259
+ The adapter respects these environment variables:
260
+
261
+ - `MARAVILLA_ENV` - Set to 'production' for production builds
262
+ - `MARAVILLA_DEV_SERVER` - Dev server URL (development only)
263
+ - `MARAVILLA_TENANT` - Tenant ID (development only)
264
+
265
+ ## TypeScript Support
266
+
267
+ Add global platform types to your app:
268
+
269
+ ```typescript
270
+ // app.d.ts
271
+ import type { KVNamespace, Database } from '@maravilla/platform';
272
+
273
+ declare global {
274
+ namespace App {
275
+ interface Platform {
276
+ env: {
277
+ KV: KVNamespace;
278
+ DB: Database;
279
+ };
280
+ }
281
+ }
282
+ }
283
+
284
+ export {};
285
+ ```
286
+
287
+ ## Configuration Options
288
+
289
+ ### `out`
290
+ - **Type**: `string`
291
+ - **Default**: `'.maravilla'`
292
+ - **Description**: Output directory for the build
293
+
294
+ ### `precompress`
295
+ - **Type**: `boolean`
296
+ - **Default**: `false`
297
+ - **Description**: Pre-compress static assets with gzip/brotli
298
+
299
+ ### `polyfill`
300
+ - **Type**: `boolean`
301
+ - **Default**: `true`
302
+ - **Description**: Include runtime polyfills for compatibility
303
+
304
+ ### `envPrefix`
305
+ - **Type**: `string`
306
+ - **Default**: `'PUBLIC_'`
307
+ - **Description**: Prefix for environment variables to expose to the client
308
+
309
+ ### `include` / `exclude`
310
+ - **Type**: `string[]`
311
+ - **Default**: `include: ['/*']`, `exclude: []`
312
+ - **Description**: Route include/exclude patterns recorded in the manifest
313
+
314
+ ### `external`
315
+ - **Type**: `string[]`
316
+ - **Default**: `[]`
317
+ - **Description**: Extra dependencies to exclude from the server bundle (esbuild external)
318
+
319
+ ## Example Application
320
+
321
+ Check out the demo application in `examples/demo/`:
322
+
323
+ ```bash
324
+ cd packages/adapter-sveltekit/examples/demo
325
+ pnpm install
326
+ pnpm dev
327
+ ```
328
+
329
+ The demo includes:
330
+ - **KV Playground** (`/kv`) - Interactive KV store operations
331
+ - **Users Directory** (`/users`) - Full CRUD with MongoDB-style database
332
+ - **Sverdle Game** (`/sverdle`) - Wordle clone demonstrating SSR
333
+ - **About Page** (`/about`) - Static page example
334
+
335
+ ## Edge Functions (optional)
336
+
337
+ Place functions in a top-level `functions/` folder. The adapter will build and integrate them into `.maravilla/manifest.json` during `pnpm build`. For dev HMR, add the `maravillaFunctions()` plugin as shown above.
338
+
339
+ ## Deployment
340
+
341
+ ### Local Preview
342
+
343
+ ```bash
344
+ # Build your app
345
+ pnpm build
346
+
347
+ # Preview with Maravilla runtime
348
+ maravilla preview .maravilla
349
+ ```
350
+
351
+ ### Production Deployment
352
+
353
+ ```bash
354
+ # Build for production
355
+ NODE_ENV=production pnpm build
356
+
357
+ # Deploy (coming soon)
358
+ maravilla deploy .maravilla
359
+ ```
360
+
361
+ ## Performance
362
+
363
+ The adapter optimizes for edge deployment:
364
+
365
+ - **Code Splitting**: Automatic chunking for optimal loading
366
+ - **Tree Shaking**: Removes unused code
367
+ - **Minification**: Compressed JavaScript output
368
+ - **Static Optimization**: Pre-rendered pages served from CDN
369
+ - **Asset Compression**: Brotli/gzip pre-compression
370
+
371
+ ## Troubleshooting
372
+
373
+ ### Build Errors
374
+
375
+ If you encounter build errors:
376
+
377
+ 1. Clear the build cache:
378
+ ```bash
379
+ rm -rf .svelte-kit .maravilla
380
+ ```
381
+
382
+ 2. Reinstall dependencies:
383
+ ```bash
384
+ pnpm install
385
+ ```
386
+
387
+ 3. Rebuild:
388
+ ```bash
389
+ pnpm build
390
+ ```
391
+
392
+ ### Platform Services Not Available
393
+
394
+ Ensure the dev server is running:
395
+ ```bash
396
+ maravilla dev
397
+ ```
398
+
399
+ ### Type Errors
400
+
401
+ Install type definitions:
402
+ ```bash
403
+ pnpm add @maravilla/platform
404
+ ```
405
+
406
+ ## Migration from Other Adapters
407
+
408
+ ### From `@sveltejs/adapter-node`
409
+
410
+ 1. Replace the adapter import
411
+ 2. Remove Node.js-specific code
412
+ 3. Replace database calls with `platform.env.DB`
413
+ 4. Replace Redis/cache with `platform.env.KV`
414
+
415
+ ### From `@sveltejs/adapter-vercel`
416
+
417
+ 1. Replace the adapter import
418
+ 2. Update environment variable access
419
+ 3. Replace Vercel KV with `platform.env.KV`
420
+ 4. Update API routes to use platform services
421
+
422
+ ## Related Packages
423
+
424
+ - [`@maravilla/platform`](../platform) - Platform client library
425
+ - [`@solutas/vite-plugin`](../vite-plugin) - Vite plugin for development
426
+ - [`@solutas/cli`](../../crates/cli) - Command-line interface
427
+
428
+ ## License
429
+
430
+ Proprietary. Copyright © 2025 SOLUTAS GmbH, Switzerland. All rights
431
+ reserved. Use is subject to the terms in the root LICENSE file or a
432
+ separate written agreement with SOLUTAS GmbH.
@@ -0,0 +1,12 @@
1
+ import type { Adapter } from '@sveltejs/kit';
2
+ export interface AdapterOptions {
3
+ out?: string;
4
+ precompress?: boolean;
5
+ envPrefix?: string;
6
+ polyfill?: boolean;
7
+ include?: string[];
8
+ exclude?: string[];
9
+ external?: string[];
10
+ }
11
+ export default function adapter(options?: AdapterOptions): Adapter;
12
+ //# 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,OAAO,EAAW,MAAM,eAAe,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAQD,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAkOrE"}
package/dist/index.js ADDED
@@ -0,0 +1,194 @@
1
+ import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { dirname, join, resolve } from 'node:path';
4
+ import * as esbuild from 'esbuild';
5
+ import { buildFunctions, integrateWithManifest } from '@maravilla-labs/functions';
6
+ function get_files_path() {
7
+ const currentModulePath = fileURLToPath(import.meta.url);
8
+ const currentDir = dirname(currentModulePath);
9
+ return resolve(currentDir);
10
+ }
11
+ export default function adapter(options = {}) {
12
+ const { out = '.maravilla', precompress = false, envPrefix = 'PUBLIC_', polyfill = true, include = [], exclude = [], external = [] } = options;
13
+ return {
14
+ name: '@solutas/adapter-sveltekit',
15
+ async adapt(builder) {
16
+ const tmp = builder.getBuildDirectory('adapter-maravilla');
17
+ // Clean output directories
18
+ builder.rimraf(out);
19
+ builder.rimraf(tmp);
20
+ builder.mkdirp(tmp);
21
+ // Log build start
22
+ builder.log.minor('Building Maravilla Runtime bundle...');
23
+ // Write client assets
24
+ const static_directory = `${out}/static`;
25
+ builder.log.minor('Copying static assets');
26
+ builder.writeClient(static_directory);
27
+ builder.writePrerendered(static_directory);
28
+ // Optionally compress assets
29
+ if (precompress) {
30
+ builder.log.minor('Compressing assets');
31
+ await Promise.all([
32
+ builder.compress(static_directory)
33
+ ]);
34
+ }
35
+ // Write server
36
+ builder.log.minor('Building server');
37
+ builder.writeServer(tmp);
38
+ // Generate manifest
39
+ writeFileSync(`${tmp}/manifest.js`, [
40
+ `export const manifest = ${builder.generateManifest({ relativePath: './' })};`,
41
+ `export const prerendered = new Set(${JSON.stringify(builder.prerendered.paths)});`,
42
+ `export const base = ${JSON.stringify(builder.config.kit.paths.base)};`
43
+ ].join('\n\n'));
44
+ // Create the worker entry point
45
+ const files_path = get_files_path();
46
+ const worker_template = readFileSync(join(files_path, 'worker.js'), 'utf-8');
47
+ const worker_code = worker_template
48
+ .replace('__SERVER__', './index.js')
49
+ .replace('__MANIFEST__', './manifest.js');
50
+ writeFileSync(`${tmp}/worker.js`, worker_code);
51
+ // Bundle with esbuild
52
+ builder.log.minor('Bundling with esbuild');
53
+ const result = await esbuild.build({
54
+ entryPoints: [`${tmp}/worker.js`],
55
+ outfile: `${out}/server.js`,
56
+ bundle: true,
57
+ platform: 'neutral',
58
+ format: 'esm',
59
+ target: 'es2022',
60
+ conditions: ['worker', 'webworker'],
61
+ external: [
62
+ ...external,
63
+ // Don't bundle platform APIs - they're provided by the runtime
64
+ '@maravilla/platform'
65
+ ],
66
+ define: {
67
+ 'process.env.NODE_ENV': '"production"'
68
+ },
69
+ minify: true,
70
+ sourcemap: true,
71
+ metafile: true,
72
+ logLevel: 'info'
73
+ });
74
+ if (result.metafile) {
75
+ const analysis = await esbuild.analyzeMetafile(result.metafile);
76
+ builder.log.minor(analysis);
77
+ }
78
+ // Collect all static assets that were written
79
+ const staticAssets = [];
80
+ const collectAssets = (dir, prefix = '') => {
81
+ if (!existsSync(dir))
82
+ return;
83
+ const files = readdirSync(dir);
84
+ for (const file of files) {
85
+ const fullPath = join(dir, file);
86
+ const relativePath = prefix ? `${prefix}/${file}` : file;
87
+ if (statSync(fullPath).isDirectory()) {
88
+ collectAssets(fullPath, relativePath);
89
+ }
90
+ else {
91
+ staticAssets.push(`/${relativePath}`);
92
+ }
93
+ }
94
+ };
95
+ collectAssets(static_directory);
96
+ // Check for functions directory and build if present
97
+ // Look for functions in the project root
98
+ const functionsDir = join(process.cwd(), 'functions');
99
+ let functionsManifest = null;
100
+ if (existsSync(functionsDir)) {
101
+ builder.log.minor('Building edge functions from: ' + functionsDir);
102
+ try {
103
+ functionsManifest = await buildFunctions({
104
+ functionsDir,
105
+ outputDir: out,
106
+ production: true,
107
+ minify: true,
108
+ });
109
+ }
110
+ catch (error) {
111
+ builder.log.error('Failed to build functions: ' + (error?.message || error));
112
+ }
113
+ }
114
+ else {
115
+ builder.log.minor('No functions directory found, skipping functions build');
116
+ }
117
+ // Generate comprehensive platform manifest
118
+ const platformManifest = {
119
+ version: 2,
120
+ runtime: 'maravilla',
121
+ entrypoint: 'server.js',
122
+ static: 'static',
123
+ // Routing information for the runtime
124
+ routing: {
125
+ // Prerendered pages that should be served from static
126
+ prerendered: builder.prerendered.paths.map(path => {
127
+ // Convert paths to their HTML file locations
128
+ if (path === '/') {
129
+ return '/index.html';
130
+ }
131
+ // Remove trailing slash and add .html
132
+ return path.replace(/\/$/, '') + '.html';
133
+ }),
134
+ // Client-side assets that should always be served from static
135
+ assets: staticAssets.filter(path => path.startsWith('/_app/') ||
136
+ path.startsWith('/favicon') ||
137
+ path.endsWith('.txt') ||
138
+ path.endsWith('.svg') ||
139
+ path.endsWith('.png') ||
140
+ path.endsWith('.jpg') ||
141
+ path.endsWith('.webp')),
142
+ // Everything else is handled dynamically by the server
143
+ dynamic: {
144
+ api: '/api/*', // API routes
145
+ serverRoutes: '/*' // All other routes handled by server
146
+ }
147
+ },
148
+ // Original routes config for compatibility
149
+ routes: {
150
+ include: include.length > 0 ? include : ['/*'],
151
+ exclude: exclude.length > 0 ? exclude : []
152
+ },
153
+ env: {
154
+ prefix: envPrefix
155
+ },
156
+ features: {
157
+ ssr: true,
158
+ prerendering: builder.prerendered.paths.length > 0,
159
+ polyfill,
160
+ // Additional feature flags
161
+ streaming: true,
162
+ compression: precompress
163
+ },
164
+ // Build metadata
165
+ metadata: {
166
+ adapter: '@maravilla/adapter-sveltekit',
167
+ kit_version: builder.config.kit.version || 'unknown',
168
+ build_date: new Date().toISOString(),
169
+ prerendered_count: builder.prerendered.paths.length,
170
+ asset_count: staticAssets.length
171
+ }
172
+ };
173
+ writeFileSync(`${out}/manifest.json`, JSON.stringify(platformManifest, null, 2));
174
+ // Integrate functions into manifest if they exist
175
+ if (functionsManifest) {
176
+ await integrateWithManifest(`${out}/manifest.json`, functionsManifest);
177
+ // Merge functions bundle into server bundle for unified execution
178
+ const { mergeFunctions } = await import('./merge-functions.js');
179
+ mergeFunctions(out);
180
+ }
181
+ builder.log.minor(`Build complete. Output written to ${out}`);
182
+ builder.log.minor('');
183
+ builder.log.minor('Deploy with:');
184
+ builder.log.minor(` maravilla deploy ${out}`);
185
+ builder.log.minor('');
186
+ builder.log.minor('Preview locally with:');
187
+ builder.log.minor(` maravilla preview ${out}`);
188
+ },
189
+ supports: {
190
+ read: () => true
191
+ }
192
+ };
193
+ }
194
+ //# 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/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@maravilla-labs/adapter-sveltekit",
3
+ "version": "0.1.0",
4
+ "description": "SvelteKit adapter for Maravilla Runtime",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "src/worker.js"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsc --watch",
15
+ "test": "vitest"
16
+ },
17
+ "keywords": [
18
+ "sveltekit",
19
+ "adapter",
20
+ "maravilla",
21
+ "edge",
22
+ "runtime"
23
+ ],
24
+ "author": "SOLUTAS GmbH",
25
+ "license": "Proprietary",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/solutas/maravilla-runtime.git",
29
+ "directory": "packages/adapter-sveltekit"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "peerDependencies": {
35
+ "@sveltejs/kit": "^2.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@sveltejs/kit": "^2.0.0",
39
+ "@types/node": "^20.0.0",
40
+ "typescript": "^5.0.0",
41
+ "vitest": "^1.0.0"
42
+ },
43
+ "dependencies": {
44
+ "@maravilla-labs/functions": "workspace:*",
45
+ "esbuild": "^0.19.0"
46
+ }
47
+ }
package/src/worker.js ADDED
@@ -0,0 +1,157 @@
1
+ // Maravilla Runtime Worker for SvelteKit
2
+ // This runs inside the Deno isolate with access to platform APIs
3
+
4
+ import { Server } from '__SERVER__';
5
+ import { manifest, prerendered, base } from '__MANIFEST__';
6
+
7
+ // Initialize the SvelteKit server
8
+ const server = new Server(manifest);
9
+
10
+ // Initialize server with platform-specific read function
11
+ const initialized = server.init({
12
+ env: globalThis.platform?.env || {},
13
+ read: async (file) => {
14
+ // For now, return empty stream for any file read attempts
15
+ // This is a placeholder until we implement proper static file serving
16
+ console.log('Read function called for file:', file);
17
+
18
+ // Return an empty ReadableStream to prevent errors
19
+ return new ReadableStream({
20
+ start(controller) {
21
+ // Just close the stream immediately
22
+ controller.close();
23
+ }
24
+ });
25
+ }
26
+ });
27
+
28
+ /**
29
+ * Main request handler for the Maravilla runtime
30
+ * This function is called by the runtime for each incoming request
31
+ */
32
+ async function handleRequest(request) {
33
+ // Ensure server is initialized
34
+ await initialized;
35
+
36
+ // Convert the incoming request object to a standard Request
37
+ const url = new URL(request.url, 'http://localhost');
38
+
39
+ // Prepare the body - handle different types
40
+ let requestBody = undefined;
41
+ if (request.body !== null && request.body !== undefined) {
42
+ // If body is already a string, use it directly
43
+ if (typeof request.body === 'string') {
44
+ requestBody = request.body;
45
+ } else {
46
+ // Otherwise stringify it
47
+ requestBody = JSON.stringify(request.body);
48
+ }
49
+ }
50
+
51
+ // Create a standard Request object
52
+ const webRequest = new Request(url.toString(), {
53
+ method: request.method,
54
+ headers: request.headers || {},
55
+ body: requestBody
56
+ });
57
+
58
+ // Check if this is a static asset request
59
+ const pathname = url.pathname;
60
+ const stripped_pathname = pathname.replace(/\/$/, '');
61
+
62
+ // Debug: verify URL.pathname setter works for data requests
63
+ if (pathname.endsWith('/__data.json') || pathname.endsWith('.html__data.json')) {
64
+ try {
65
+ const test = new URL(url.toString());
66
+ const before = test.pathname;
67
+ const candidate = pathname.endsWith('/__data.json')
68
+ ? pathname.slice(0, -'/__data.json'.length)
69
+ : pathname.slice(0, -'.html__data.json'.length) + '.html';
70
+ test.pathname = candidate;
71
+ console.log('Data URL normalization test', { before, candidate, after: test.pathname, href: test.href });
72
+ } catch (e) {
73
+ console.error('Data URL normalization error', e);
74
+ }
75
+ }
76
+
77
+ // Check if path is prerendered
78
+ if (prerendered.has(pathname)) {
79
+ // For prerendered pages, we could serve from static storage
80
+ // but for now, let SvelteKit handle it
81
+ }
82
+
83
+ // Handle trailing slash redirects for prerendered pages
84
+ const location = pathname.at(-1) === '/' ? stripped_pathname : pathname + '/';
85
+ if (location && prerendered.has(location)) {
86
+ return new Response('', {
87
+ status: 308,
88
+ headers: {
89
+ location: location + url.search
90
+ }
91
+ });
92
+ }
93
+
94
+ // Let SvelteKit handle the request
95
+ try {
96
+ console.log('SvelteKit server.respond called with:', {
97
+ url: webRequest.url,
98
+ method: webRequest.method,
99
+ hasBody: requestBody !== undefined,
100
+ platform: {
101
+ hasEnv: !!globalThis.platform?.env,
102
+ hasKv: !!globalThis.platform?.kv,
103
+ hasDb: !!globalThis.platform?.db
104
+ }
105
+ });
106
+
107
+ const response = await server.respond(webRequest, {
108
+ platform: {
109
+ // Expose Maravilla platform APIs to SvelteKit
110
+ env: globalThis.platform?.env || {},
111
+ context: {
112
+ waitUntil: (promise) => {
113
+ // In Maravilla, we can queue background work
114
+ if (globalThis.platform?.queue) {
115
+ globalThis.platform.queue.send({ type: 'background', promise });
116
+ }
117
+ },
118
+ passThroughOnException: () => {
119
+ // Not applicable in Maravilla runtime
120
+ }
121
+ },
122
+ // Expose platform services
123
+ kv: globalThis.platform?.kv,
124
+ db: globalThis.platform?.db,
125
+ storage: globalThis.platform?.storage,
126
+ queue: globalThis.platform?.queue
127
+ },
128
+ getClientAddress: () => {
129
+ // Get client IP from request headers
130
+ const forwarded = webRequest.headers.get('x-forwarded-for');
131
+ if (forwarded) {
132
+ return forwarded.split(',')[0].trim();
133
+ }
134
+ return request.headers?.['x-real-ip'] || '127.0.0.1';
135
+ }
136
+ });
137
+
138
+ // Log response details
139
+ if (response.status >= 400) {
140
+ console.error('SvelteKit returned error:', {
141
+ status: response.status,
142
+ statusText: response.statusText,
143
+ url: webRequest.url
144
+ });
145
+ }
146
+
147
+ // Return the response in a format the runtime expects
148
+ return response;
149
+ } catch (error) {
150
+ console.error('Error in server.respond:', error);
151
+ console.error('Error stack:', error.stack);
152
+ throw error;
153
+ }
154
+ }
155
+
156
+ // Export for the Maravilla runtime
157
+ globalThis.handleRequest = handleRequest;