shiply-cli 0.18.0 → 0.18.2
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/dist/bundle.js +41 -43
- package/dist/ssr-adapters.js +52 -49
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -1,58 +1,56 @@
|
|
|
1
1
|
import { cp, mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { tmpdir } from 'node:os';
|
|
3
|
-
import {
|
|
3
|
+
import { isAbsolute, join, relative } from 'node:path';
|
|
4
4
|
import { build } from 'esbuild';
|
|
5
5
|
const BUNDLE_COMPAT_DATE = '2025-05-05';
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
/** Cloudflare runtime built-ins (`cloudflare:workers`, …) and `node:*` (provided
|
|
7
|
+
* by `nodejs_compat`) resolve at the edge — they must stay external. Everything
|
|
8
|
+
* else, including the framework server code that an adapter's `_worker.js`
|
|
9
|
+
* imports from OUTSIDE its output dir, gets inlined. */
|
|
10
|
+
const WORKER_EXTERNALS = ['cloudflare:*', 'node:*'];
|
|
11
|
+
/** esbuild-bundle a worker entry into one self-contained ESM module. */
|
|
12
|
+
async function bundleWorker(entryAbs) {
|
|
13
|
+
const result = await build({
|
|
14
|
+
entryPoints: [entryAbs],
|
|
15
|
+
bundle: true,
|
|
16
|
+
format: 'esm',
|
|
17
|
+
platform: 'neutral',
|
|
18
|
+
target: 'es2022',
|
|
19
|
+
external: WORKER_EXTERNALS,
|
|
20
|
+
write: false,
|
|
21
|
+
logLevel: 'silent',
|
|
22
|
+
});
|
|
23
|
+
return result.outputFiles[0].text;
|
|
24
|
+
}
|
|
25
|
+
/** Stage a temp publish dir: a single bundled worker under `.shiply/bundle/`,
|
|
26
|
+
* static assets at the root, plus `.shiply/bundle.json`. Returns the dir; the
|
|
27
|
+
* caller removes it after publish. The existing publish pipeline handles the rest.
|
|
28
|
+
*
|
|
29
|
+
* BOTH tiers esbuild-bundle the entry. Adapter output (SvelteKit, Astro) is NOT
|
|
30
|
+
* self-contained — `_worker.js` imports server code from sibling dirs
|
|
31
|
+
* (`../output/server`, `../cloudflare-tmp`) — so we bundle it exactly as
|
|
32
|
+
* `wrangler deploy` would, rather than upload it as-is. */
|
|
9
33
|
export async function prepareBundle(sourceDir, ssr) {
|
|
10
34
|
const out = await mkdtemp(join(tmpdir(), 'shiply-bundle-'));
|
|
11
35
|
const bundleDir = join(out, '.shiply', 'bundle');
|
|
12
36
|
await mkdir(bundleDir, { recursive: true });
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
await writeFile(join(bundleDir, 'index.js'), result.outputFiles[0].text);
|
|
25
|
-
if (ssr.staticDir) {
|
|
26
|
-
await cp(join(sourceDir, ssr.staticDir), out, { recursive: true });
|
|
37
|
+
// Bundle the worker entry into one self-contained ESM module.
|
|
38
|
+
await writeFile(join(bundleDir, 'index.js'), await bundleWorker(join(sourceDir, ssr.workerEntry)));
|
|
39
|
+
// Copy static assets, if any. The worker entry may live inside the assets dir
|
|
40
|
+
// (SvelteKit, Astro) or in a sibling (Nitro's .output/server vs .output/public);
|
|
41
|
+
// when inside, drop it so it isn't double-served.
|
|
42
|
+
if (ssr.assetsDir) {
|
|
43
|
+
const assetsAbs = join(sourceDir, ssr.assetsDir);
|
|
44
|
+
await cp(assetsAbs, out, { recursive: true });
|
|
45
|
+
const entryRel = relative(assetsAbs, join(sourceDir, ssr.workerEntry));
|
|
46
|
+
if (entryRel && !entryRel.startsWith('..') && !isAbsolute(entryRel)) {
|
|
47
|
+
await rm(join(out, entryRel.split(/[\\/]/)[0]), { recursive: true, force: true });
|
|
27
48
|
}
|
|
28
|
-
await writeManifest(out, {
|
|
29
|
-
framework: ssr.framework,
|
|
30
|
-
entry: 'index.js',
|
|
31
|
-
modules: ['index.js'],
|
|
32
|
-
compatibilityDate: ssr.compatibilityDate ?? BUNDLE_COMPAT_DATE,
|
|
33
|
-
compatibilityFlags: ssr.compatibilityFlags,
|
|
34
|
-
});
|
|
35
|
-
return out;
|
|
36
|
-
}
|
|
37
|
-
// Tier 1: copy the whole assets dir, then RELOCATE worker modules into
|
|
38
|
-
// .shiply/bundle/ so they aren't double-served as static assets.
|
|
39
|
-
await cp(ssr.assetsDir, out, { recursive: true });
|
|
40
|
-
for (const m of ssr.modules) {
|
|
41
|
-
const from = join(out, m);
|
|
42
|
-
const to = join(bundleDir, m);
|
|
43
|
-
await mkdir(dirname(to), { recursive: true });
|
|
44
|
-
await cp(from, to, { recursive: true });
|
|
45
|
-
await rm(from, { recursive: true, force: true });
|
|
46
|
-
}
|
|
47
|
-
// If the entry lived in a worker subdir (Astro's _worker.js/), drop the
|
|
48
|
-
// original subdir entirely so no leftover files are served as assets.
|
|
49
|
-
if (ssr.entry.includes('/')) {
|
|
50
|
-
await rm(join(out, ssr.entry.split('/')[0]), { recursive: true, force: true });
|
|
51
49
|
}
|
|
52
50
|
await writeManifest(out, {
|
|
53
51
|
framework: ssr.framework,
|
|
54
|
-
entry:
|
|
55
|
-
modules:
|
|
52
|
+
entry: 'index.js',
|
|
53
|
+
modules: ['index.js'],
|
|
56
54
|
compatibilityDate: ssr.compatibilityDate ?? BUNDLE_COMPAT_DATE,
|
|
57
55
|
compatibilityFlags: ssr.compatibilityFlags,
|
|
58
56
|
});
|
package/dist/ssr-adapters.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFile,
|
|
2
|
-
import { join
|
|
1
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
3
|
import { parse as parseToml } from 'smol-toml';
|
|
4
4
|
const NODE_COMPAT = ['nodejs_compat'];
|
|
5
5
|
const exists = (p) => stat(p).then(() => true, () => false);
|
|
@@ -12,55 +12,60 @@ async function deps(dir) {
|
|
|
12
12
|
return {};
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
for (const e of await readdir(root, { withFileTypes: true })) {
|
|
19
|
-
const abs = join(root, e.name);
|
|
20
|
-
if (e.isDirectory())
|
|
21
|
-
out.push(...(await listFiles(abs, base)));
|
|
22
|
-
else
|
|
23
|
-
out.push(relative(base, abs).split('\\').join('/'));
|
|
24
|
-
}
|
|
25
|
-
return out;
|
|
26
|
-
}
|
|
27
|
-
/** Detect a built SSR project (Cloudflare-adapter output or a wrangler worker)
|
|
28
|
-
* in `dir`. Returns null for plain static dirs. */
|
|
15
|
+
/** Detect a built SSR project in `dir` (framework adapter output or a wrangler
|
|
16
|
+
* worker). Returns null for plain static dirs. Framework-specific detectors
|
|
17
|
+
* run before the generic wrangler one. */
|
|
29
18
|
export async function detectSsr(dir) {
|
|
30
19
|
const d = await deps(dir);
|
|
31
|
-
//
|
|
32
|
-
if ('@sveltejs/adapter-cloudflare' in d) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
modules: ['_worker.js'],
|
|
40
|
-
compatibilityFlags: NODE_COMPAT,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
20
|
+
// SvelteKit — adapter-cloudflare: `_worker.js` + sibling assets.
|
|
21
|
+
if ('@sveltejs/adapter-cloudflare' in d && (await exists(join(dir, '.svelte-kit/cloudflare/_worker.js')))) {
|
|
22
|
+
return {
|
|
23
|
+
framework: 'sveltekit',
|
|
24
|
+
workerEntry: '.svelte-kit/cloudflare/_worker.js',
|
|
25
|
+
assetsDir: '.svelte-kit/cloudflare',
|
|
26
|
+
compatibilityFlags: NODE_COMPAT,
|
|
27
|
+
};
|
|
43
28
|
}
|
|
44
|
-
//
|
|
45
|
-
if ('@astrojs/cloudflare' in d) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
framework: 'astro',
|
|
54
|
-
assetsDir: out,
|
|
55
|
-
entry: '_worker.js/index.js',
|
|
56
|
-
modules,
|
|
57
|
-
compatibilityFlags: NODE_COMPAT,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
29
|
+
// Astro — @astrojs/cloudflare: `dist/_worker.js/index.js` + dist assets.
|
|
30
|
+
if ('@astrojs/cloudflare' in d && (await exists(join(dir, 'dist/_worker.js/index.js')))) {
|
|
31
|
+
return {
|
|
32
|
+
framework: 'astro',
|
|
33
|
+
workerEntry: 'dist/_worker.js/index.js',
|
|
34
|
+
assetsDir: 'dist',
|
|
35
|
+
compatibilityFlags: NODE_COMPAT,
|
|
36
|
+
};
|
|
60
37
|
}
|
|
61
|
-
//
|
|
38
|
+
// Nitro (Nuxt, SolidStart, Analog, TanStack, …) — cloudflare preset:
|
|
39
|
+
// `.output/server/index.mjs` worker + `.output/public/` assets (separate dir).
|
|
40
|
+
const nitro = await detectNitro(dir);
|
|
41
|
+
if (nitro)
|
|
42
|
+
return nitro;
|
|
43
|
+
// Generic Cloudflare Worker via a wrangler config (Hono, itty, raw fetch).
|
|
62
44
|
return detectWrangler(dir);
|
|
63
45
|
}
|
|
46
|
+
async function detectNitro(dir) {
|
|
47
|
+
const nitroJson = join(dir, '.output', 'nitro.json');
|
|
48
|
+
if (!(await exists(nitroJson)))
|
|
49
|
+
return null;
|
|
50
|
+
let preset = '';
|
|
51
|
+
try {
|
|
52
|
+
preset = String(JSON.parse(await readFile(nitroJson, 'utf8')).preset ?? '');
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
// 'cloudflare-module' / 'cloudflare_module' / 'cloudflare-pages' all start with it.
|
|
58
|
+
if (!preset.startsWith('cloudflare'))
|
|
59
|
+
return null;
|
|
60
|
+
if (!(await exists(join(dir, '.output/server/index.mjs'))))
|
|
61
|
+
return null;
|
|
62
|
+
return {
|
|
63
|
+
framework: 'nitro',
|
|
64
|
+
workerEntry: '.output/server/index.mjs',
|
|
65
|
+
assetsDir: '.output/public',
|
|
66
|
+
compatibilityFlags: NODE_COMPAT,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
64
69
|
async function detectWrangler(dir) {
|
|
65
70
|
let cfg = null;
|
|
66
71
|
if (await exists(join(dir, 'wrangler.toml'))) {
|
|
@@ -79,10 +84,8 @@ async function detectWrangler(dir) {
|
|
|
79
84
|
const staticDir = cfg.assets?.directory ?? cfg.site?.bucket;
|
|
80
85
|
return {
|
|
81
86
|
framework: 'cloudflare-worker',
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
workerMain: cfg.main,
|
|
85
|
-
staticDir: typeof staticDir === 'string' ? staticDir : undefined,
|
|
87
|
+
workerEntry: cfg.main,
|
|
88
|
+
assetsDir: typeof staticDir === 'string' ? staticDir : undefined,
|
|
86
89
|
compatibilityDate: typeof cfg.compatibility_date === 'string' ? cfg.compatibility_date : undefined,
|
|
87
90
|
compatibilityFlags: Array.isArray(cfg.compatibility_flags) && cfg.compatibility_flags.length
|
|
88
91
|
? cfg.compatibility_flags
|