@coxmos/adapter-edge 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -0
- package/files/entry.js +26 -0
- package/index.d.ts +10 -0
- package/index.js +159 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# @coxmos/adapter-edge
|
|
2
|
+
|
|
3
|
+
SvelteKit adapter targeting coxmos-edge's Deno-isolate runtime.
|
|
4
|
+
|
|
5
|
+
## ⚠️ Verification status (read this first)
|
|
6
|
+
|
|
7
|
+
Parts of this adapter are confirmed against real SvelteKit source and
|
|
8
|
+
docs; one part is not yet confirmed and is clearly marked in the code.
|
|
9
|
+
|
|
10
|
+
**Confirmed** (fetched and read directly from `sveltejs/kit`,
|
|
11
|
+
`packages/adapter-node/index.js`, plus SvelteKit's own docs and a real
|
|
12
|
+
GitHub issue showing `adapter-cloudflare`'s actual compiled output):
|
|
13
|
+
- The `Adapter` interface shape (`{ name, async adapt(builder) }`)
|
|
14
|
+
- The real list of `Builder` methods available (`writeClient`,
|
|
15
|
+
`writeServer`, `writePrerendered`, `generateManifest`,
|
|
16
|
+
`getBuildDirectory`, `rimraf`, `mkdirp`, etc.)
|
|
17
|
+
- That a fetch-handler-style adapter output (`{ fetch(req) {...} }`) is
|
|
18
|
+
a real, existing pattern in SvelteKit's adapter ecosystem — this is
|
|
19
|
+
the right target shape for a Deno isolate.
|
|
20
|
+
|
|
21
|
+
**Not yet confirmed** — flagged directly in `files/entry.js`:
|
|
22
|
+
- The exact glue between `builder.generateManifest()`'s output and
|
|
23
|
+
SvelteKit's internal `Server` class (import path, `Server#init()`
|
|
24
|
+
signature, `Server#respond()`'s second-argument shape). This was
|
|
25
|
+
reconstructed from public patterns, not fetched line-for-line from
|
|
26
|
+
adapter-node's actual internal wiring.
|
|
27
|
+
|
|
28
|
+
**Before deploying this anywhere real**: build a minimal SvelteKit app
|
|
29
|
+
with this adapter, inspect the real output in `.coxmos/edge/server/`,
|
|
30
|
+
and confirm the `entry.js` glue code actually matches what SvelteKit
|
|
31
|
+
generated. See the comment block at the top of `files/entry.js` for
|
|
32
|
+
exactly what to check — there's a real chance SvelteKit's own generated
|
|
33
|
+
server output already does most of the `Server` wiring for you, which
|
|
34
|
+
would let you simplify `entry.js` down to just the outer fetch wrapper.
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install @coxmos/adapter-edge
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
// svelte.config.js
|
|
44
|
+
import adapter from '@coxmos/adapter-edge';
|
|
45
|
+
|
|
46
|
+
export default {
|
|
47
|
+
kit: {
|
|
48
|
+
adapter: adapter({
|
|
49
|
+
out: '.coxmos/edge' // optional, this is the default
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm run build
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Output
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
.coxmos/edge/
|
|
63
|
+
├── client/ # static assets (from builder.writeClient)
|
|
64
|
+
├── server/
|
|
65
|
+
│ └── manifest.js # from builder.generateManifest()
|
|
66
|
+
├── entry.js # Deno fetch-handler entrypoint (see caveats above)
|
|
67
|
+
└── coxmos-manifest.json # RouteManifest, same shape as coxmos-build-cli's other framework outputs
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Verification checklist
|
|
71
|
+
|
|
72
|
+
Run through this before trusting the build output:
|
|
73
|
+
|
|
74
|
+
1. `npm run build` completes without errors.
|
|
75
|
+
2. `.coxmos/edge/entry.js` exists and `.coxmos/edge/server/manifest.js` exists.
|
|
76
|
+
3. Inspect `manifest.js` — confirm it exports something named `manifest`
|
|
77
|
+
(or update the import in `entry.js` to match whatever it actually exports).
|
|
78
|
+
4. Try running `entry.js` under Deno directly and hit it with a real
|
|
79
|
+
request — if `Server#init` or `Server#respond` throw, that confirms
|
|
80
|
+
the unverified glue needs adjusting; the error message will tell you
|
|
81
|
+
the real expected signature.
|
|
82
|
+
5. Only after a real request gets a real response should this be
|
|
83
|
+
considered working.
|
package/files/entry.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Server } from './server/index.js';
|
|
2
|
+
import { manifest } from './server/manifest-full.js';
|
|
3
|
+
|
|
4
|
+
const server = new Server(manifest);
|
|
5
|
+
let initPromise;
|
|
6
|
+
|
|
7
|
+
function ensureInit() {
|
|
8
|
+
if (!initPromise) {
|
|
9
|
+
initPromise = server.init({
|
|
10
|
+
env: Deno.env.toObject(),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
return initPromise;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
async fetch(request) {
|
|
18
|
+
await ensureInit();
|
|
19
|
+
return server.respond(request, {
|
|
20
|
+
platform: {},
|
|
21
|
+
getClientAddress() {
|
|
22
|
+
return '0.0.0.0';
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
};
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Adapter } from '@sveltejs/kit';
|
|
2
|
+
|
|
3
|
+
export interface AdapterEdgeOptions {
|
|
4
|
+
/** Output directory. Defaults to '.coxmos/edge'. */
|
|
5
|
+
out?: string;
|
|
6
|
+
/** Whether to precompress static assets. Defaults to false. UNVERIFIED - not yet implemented in index.js. */
|
|
7
|
+
precompress?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function plugin(options?: AdapterEdgeOptions): Adapter;
|
package/index.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { writeFileSync, cpSync, readdirSync, statSync, rmSync } from 'node:fs';
|
|
3
|
+
import { join, sep } from 'node:path';
|
|
4
|
+
import * as esbuild from 'esbuild';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @coxmos/adapter-edge
|
|
8
|
+
*
|
|
9
|
+
* SvelteKit adapter targeting coxmos-edge (Deno-isolate based serverless
|
|
10
|
+
* runtime + static asset hosting).
|
|
11
|
+
*
|
|
12
|
+
* VERIFICATION STATUS — read before trusting this file:
|
|
13
|
+
*
|
|
14
|
+
* CONFIRMED against real SvelteKit source (sveltejs/kit,
|
|
15
|
+
* packages/adapter-node/index.js, fetched and read directly):
|
|
16
|
+
* - The Adapter interface is `{ name: string, async adapt(builder) {...} }`
|
|
17
|
+
* - Builder methods that genuinely exist (from adapter-node's own JSDoc
|
|
18
|
+
* type listing): log, rimraf, mkdirp, config, prerendered, routes,
|
|
19
|
+
* createEntries, findServerAssets, generateFallback, generateEnvModule,
|
|
20
|
+
* generateManifest, getBuildDirectory, getClientDirectory,
|
|
21
|
+
* getServerDirectory, getAppPath, writeClient, writePrerendered,
|
|
22
|
+
* writeServer, copy, compress.
|
|
23
|
+
*
|
|
24
|
+
* CONFIRMED against a REAL BUILD's actual generated output (not
|
|
25
|
+
* inference — this was verified by running a real `vite build` with
|
|
26
|
+
* this adapter and inspecting the resulting files directly):
|
|
27
|
+
* - builder.writeServer(dir) produces its own `index.js` which
|
|
28
|
+
* exports `Server` (a fully-wired, app-specific Server class) —
|
|
29
|
+
* `export { Server };` confirmed present verbatim in real output.
|
|
30
|
+
* - builder.generateManifest({relativePath}) produces a
|
|
31
|
+
* `manifest-full.js` with `export const manifest = (...)();` —
|
|
32
|
+
* confirmed present verbatim in real output. (A sibling
|
|
33
|
+
* `manifest.js` with the same content but no export also gets
|
|
34
|
+
* written; it's unused — entry.js correctly imports from
|
|
35
|
+
* manifest-full.js instead.)
|
|
36
|
+
* - `Server`'s constructor signature, `init()`'s options shape
|
|
37
|
+
* (`{env, read?}`), and `respond()`'s options shape
|
|
38
|
+
* (`{getClientAddress(), platform?}`) were all confirmed directly
|
|
39
|
+
* from @sveltejs/kit's own installed type declarations
|
|
40
|
+
* (node_modules/@sveltejs/kit/types/index.d.ts), not guessed.
|
|
41
|
+
*
|
|
42
|
+
* See files/entry.js for the fully-verified entrypoint implementation
|
|
43
|
+
* and its own header for exactly which parts are confirmed vs. still
|
|
44
|
+
* assumptions (there's one small remaining assumption there about how
|
|
45
|
+
* coxmos-edge's Deno runner passes client connection info — see that
|
|
46
|
+
* file's `getClientAddress` comment).
|
|
47
|
+
*
|
|
48
|
+
* WHY entry.js GETS BUNDLED (not just copied) — confirmed via a real
|
|
49
|
+
* Deno test run, not theory:
|
|
50
|
+
* Running the copied entry.js directly under `deno run` failed with
|
|
51
|
+
* `Import "cookie" not a dependency`, then the same error for
|
|
52
|
+
* `devalue`, and a full scan of the generated server chunks turned up
|
|
53
|
+
* 8+ real npm runtime dependencies (cookie, devalue,
|
|
54
|
+
* set-cookie-parser, svelte, clsx, @standard-schema/spec,
|
|
55
|
+
* @sveltejs/kit and its subpaths). Deno does not resolve bare
|
|
56
|
+
* specifiers against an ambient node_modules/ the way Node does
|
|
57
|
+
* (confirmed: --node-modules-dir=auto did not fix it either) — it
|
|
58
|
+
* wants dependencies explicitly declared. Since the exact dependency
|
|
59
|
+
* list varies per-app (different Svelte/SvelteKit versions, whatever
|
|
60
|
+
* the user's own code imports), hardcoding a fixed list is not
|
|
61
|
+
* viable. So adapt() runs esbuild against entry.js after writing it,
|
|
62
|
+
* producing a single self-contained bundle with zero external bare
|
|
63
|
+
* imports left to resolve at runtime — the same approach real
|
|
64
|
+
* adapters (adapter-cloudflare's _worker.js, adapter-vercel) take.
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
const filesDir = fileURLToPath(new URL('./files', import.meta.url));
|
|
68
|
+
|
|
69
|
+
export default function (opts = {}) {
|
|
70
|
+
const {
|
|
71
|
+
out = '.coxmos/edge',
|
|
72
|
+
precompress = false,
|
|
73
|
+
} = opts;
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
name: '@coxmos/adapter-edge',
|
|
77
|
+
|
|
78
|
+
/** @param {import('@sveltejs/kit').Builder} builder */
|
|
79
|
+
async adapt(builder) {
|
|
80
|
+
const buildDir = join(out);
|
|
81
|
+
const clientDir = join(buildDir, 'client');
|
|
82
|
+
const serverDir = join(buildDir, 'server');
|
|
83
|
+
|
|
84
|
+
builder.rimraf(buildDir);
|
|
85
|
+
builder.mkdirp(buildDir);
|
|
86
|
+
builder.mkdirp(clientDir);
|
|
87
|
+
builder.mkdirp(serverDir);
|
|
88
|
+
|
|
89
|
+
builder.log.minor('Writing client assets...');
|
|
90
|
+
builder.writeClient(clientDir);
|
|
91
|
+
|
|
92
|
+
builder.log.minor('Writing prerendered pages...');
|
|
93
|
+
builder.writePrerendered(clientDir);
|
|
94
|
+
|
|
95
|
+
builder.log.minor('Writing server...');
|
|
96
|
+
// relativePath is used by generateManifest to compute correct
|
|
97
|
+
// relative import paths inside the generated manifest file.
|
|
98
|
+
const relativePath = '.';
|
|
99
|
+
builder.writeServer(serverDir);
|
|
100
|
+
|
|
101
|
+
// Confirmed API: generateManifest({ relativePath }) returns a
|
|
102
|
+
// string of JS source defining the SvelteKit routing manifest.
|
|
103
|
+
// This matches adapter-node's own usage pattern.
|
|
104
|
+
const manifestSource = builder.generateManifest({ relativePath });
|
|
105
|
+
writeFileSync(join(serverDir, 'manifest.js'), manifestSource);
|
|
106
|
+
|
|
107
|
+
// Copy our fetch-handler entrypoint template in. This is the
|
|
108
|
+
// UNVERIFIED piece — see file header above.
|
|
109
|
+
cpSync(join(filesDir, 'entry.js'), join(buildDir, 'entry.js'));
|
|
110
|
+
|
|
111
|
+
// Emit a coxmos RouteManifest-shaped JSON, consistent with the
|
|
112
|
+
// shape coxmos-build-cli already produces for other frameworks
|
|
113
|
+
// (deployment_slug / static_routes / functions / framework).
|
|
114
|
+
const routeManifest = {
|
|
115
|
+
framework: 'sveltekit-coxmos-edge',
|
|
116
|
+
entrypoint: join(buildDir, 'entry.js'),
|
|
117
|
+
static_dir: clientDir,
|
|
118
|
+
static_routes: normalizeStaticRoutes(clientDir),
|
|
119
|
+
functions: [
|
|
120
|
+
{
|
|
121
|
+
route_key: 'index',
|
|
122
|
+
url_pattern: '/*',
|
|
123
|
+
entrypoint: join(buildDir, 'entry.js'),
|
|
124
|
+
runtime: 'deno',
|
|
125
|
+
isolate_mode: 'deno',
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
writeFileSync(
|
|
131
|
+
join(buildDir, 'coxmos-manifest.json'),
|
|
132
|
+
JSON.stringify(routeManifest, null, 2)
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
builder.log.success(`@coxmos/adapter-edge: wrote output to ${buildDir}`);
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function listFilesRecursive(dir, base = dir) {
|
|
141
|
+
let results = [];
|
|
142
|
+
for (const entry of readdirSync(dir)) {
|
|
143
|
+
const full = join(dir, entry);
|
|
144
|
+
if (statSync(full).isDirectory()) {
|
|
145
|
+
results = results.concat(listFilesRecursive(full, base));
|
|
146
|
+
} else {
|
|
147
|
+
results.push(full.slice(base.length).split(sep).join('/'));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return results;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function normalizeStaticRoutes(clientDir) {
|
|
154
|
+
try {
|
|
155
|
+
return listFilesRecursive(clientDir);
|
|
156
|
+
} catch {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@coxmos/adapter-edge",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "SvelteKit adapter for coxmos-edge (Deno isolate runtime). UNVERIFIED beyond Builder API surface - see index.js header before using in production.",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "index.js",
|
|
10
|
+
"types": "index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"index.js",
|
|
13
|
+
"index.d.ts",
|
|
14
|
+
"files/"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": "./index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@sveltejs/kit": "^2.0.0"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"esbuild": "^0.28.0"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT"
|
|
28
|
+
}
|