@jxsuite/compiler 0.13.0 → 0.14.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/dist/compiler.js +64 -52
- package/package.json +1 -1
- package/src/compiler.js +6 -1
- package/src/site/site-build.js +36 -11
- package/src/site/site-loader.js +9 -0
- package/src/targets/compile-server.js +42 -1
package/package.json
CHANGED
package/src/compiler.js
CHANGED
|
@@ -22,7 +22,11 @@ import {
|
|
|
22
22
|
DEFAULT_REACTIVITY_SRC,
|
|
23
23
|
DEFAULT_LIT_HTML_SRC,
|
|
24
24
|
} from "./shared.js";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
compileServer,
|
|
27
|
+
compileSiteServer,
|
|
28
|
+
compilePagesFunctions,
|
|
29
|
+
} from "./targets/compile-server.js";
|
|
26
30
|
import {
|
|
27
31
|
compileElement,
|
|
28
32
|
compileElementPage,
|
|
@@ -36,6 +40,7 @@ export {
|
|
|
36
40
|
isDynamic,
|
|
37
41
|
compileServer,
|
|
38
42
|
compileSiteServer,
|
|
43
|
+
compilePagesFunctions,
|
|
39
44
|
compileElement,
|
|
40
45
|
compileElementPage,
|
|
41
46
|
compileClient,
|
package/src/site/site-build.js
CHANGED
|
@@ -25,7 +25,7 @@ import { discoverPages, expandDynamicRoutes } from "./pages-discovery.js";
|
|
|
25
25
|
import { resolveLayout } from "./layout-resolver.js";
|
|
26
26
|
import { mergeHead, renderHead } from "./head-merger.js";
|
|
27
27
|
import { injectContext } from "./context-injection.js";
|
|
28
|
-
import { compile, compileServer, compileSiteServer } from "../compiler.js";
|
|
28
|
+
import { compile, compileServer, compileSiteServer, compilePagesFunctions } from "../compiler.js";
|
|
29
29
|
import { compileElement } from "../targets/compile-element.js";
|
|
30
30
|
import {
|
|
31
31
|
buildInitialScope,
|
|
@@ -177,7 +177,7 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
177
177
|
for (const [, doc] of componentDefs) {
|
|
178
178
|
const entries = collectServerEntries(doc);
|
|
179
179
|
for (const entry of entries) {
|
|
180
|
-
const resolvedSrc = "./" +
|
|
180
|
+
const resolvedSrc = "./components/" + entry.src.replace(/^\.\//, "");
|
|
181
181
|
siteServerEntries.push({ exportName: entry.exportName, src: resolvedSrc });
|
|
182
182
|
}
|
|
183
183
|
}
|
|
@@ -269,6 +269,7 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
269
269
|
|
|
270
270
|
// ── 6c. Generate site-wide server worker ────────────────────────────────
|
|
271
271
|
if (projectConfig.build.adapter) {
|
|
272
|
+
const adapter = projectConfig.build.adapter;
|
|
272
273
|
log("Generating site-wide server worker...");
|
|
273
274
|
|
|
274
275
|
const deduped = new Map();
|
|
@@ -276,18 +277,19 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
276
277
|
if (!deduped.has(entry.exportName)) deduped.set(entry.exportName, entry);
|
|
277
278
|
}
|
|
278
279
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
});
|
|
280
|
+
if (adapter === "cloudflare-pages") {
|
|
281
|
+
const functions = compilePagesFunctions([...deduped.values()]);
|
|
282
282
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
283
|
+
for (const [filePath, source] of functions) {
|
|
284
|
+
const fullPath = resolve(outDir, filePath);
|
|
285
|
+
mkdirSync(resolve(fullPath, ".."), { recursive: true });
|
|
286
|
+
writeFileSync(fullPath, source, "utf8");
|
|
287
|
+
fileCount++;
|
|
288
|
+
}
|
|
288
289
|
|
|
289
|
-
// Copy server source files
|
|
290
|
+
// Copy server source files so function imports resolve
|
|
290
291
|
const distComponentsDir = resolve(outDir, "components");
|
|
292
|
+
mkdirSync(distComponentsDir, { recursive: true });
|
|
291
293
|
for (const { src } of deduped.values()) {
|
|
292
294
|
const srcFile = resolve(projectRoot, src.replace(/^\.\//, ""));
|
|
293
295
|
const destFile = resolve(distComponentsDir, src.replace(/^\.\/components\//, ""));
|
|
@@ -295,6 +297,29 @@ export async function buildSite(projectRoot, options = {}) {
|
|
|
295
297
|
copyFileSync(srcFile, destFile);
|
|
296
298
|
}
|
|
297
299
|
}
|
|
300
|
+
|
|
301
|
+
if (functions.size > 0) {
|
|
302
|
+
log(` Generated ${functions.size} Pages function(s) in dist/functions/`);
|
|
303
|
+
}
|
|
304
|
+
} else {
|
|
305
|
+
const workerSource = compileSiteServer([...deduped.values()], { adapter });
|
|
306
|
+
|
|
307
|
+
if (workerSource) {
|
|
308
|
+
const workerPath = resolve(outDir, "worker.js");
|
|
309
|
+
writeFileSync(workerPath, workerSource, "utf8");
|
|
310
|
+
fileCount++;
|
|
311
|
+
log(` Generated dist/worker.js (${deduped.size} server function(s))`);
|
|
312
|
+
|
|
313
|
+
// Copy server source files into dist/components/ so worker imports resolve
|
|
314
|
+
const distComponentsDir = resolve(outDir, "components");
|
|
315
|
+
for (const { src } of deduped.values()) {
|
|
316
|
+
const srcFile = resolve(projectRoot, src.replace(/^\.\//, ""));
|
|
317
|
+
const destFile = resolve(distComponentsDir, src.replace(/^\.\/components\//, ""));
|
|
318
|
+
if (existsSync(srcFile)) {
|
|
319
|
+
copyFileSync(srcFile, destFile);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
298
323
|
}
|
|
299
324
|
}
|
|
300
325
|
|
package/src/site/site-loader.js
CHANGED
|
@@ -87,6 +87,15 @@ export function loadProjectConfig(projectRoot) {
|
|
|
87
87
|
if (raw.imports) config.imports = raw.imports;
|
|
88
88
|
if (raw.contentTypes) config.contentTypes = raw.contentTypes;
|
|
89
89
|
|
|
90
|
+
// Validate adapter
|
|
91
|
+
const VALID_ADAPTERS = ["cloudflare-workers", "cloudflare-pages", "node", "bun"];
|
|
92
|
+
if (config.build.adapter && !VALID_ADAPTERS.includes(config.build.adapter)) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Unknown build adapter "${config.build.adapter}" in project.json. ` +
|
|
95
|
+
`Valid adapters: ${VALID_ADAPTERS.join(", ")}`,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
90
99
|
return {
|
|
91
100
|
config,
|
|
92
101
|
configPath,
|
|
@@ -69,7 +69,9 @@ export function compileSiteServer(entries, opts = {}) {
|
|
|
69
69
|
const routes = entries.map(({ exportName }) => buildRoute(exportName, baseUrl)).join("\n");
|
|
70
70
|
|
|
71
71
|
const adapterBlock =
|
|
72
|
-
adapter === "cloudflare"
|
|
72
|
+
adapter === "cloudflare-workers"
|
|
73
|
+
? "\napp.all('*', (c) => c.env.ASSETS.fetch(c.req.raw))\n"
|
|
74
|
+
: "\n";
|
|
73
75
|
|
|
74
76
|
return `// Generated by @jxsuite/compiler — do not edit manually
|
|
75
77
|
import { Hono } from 'hono'
|
|
@@ -94,3 +96,42 @@ app.post('${baseUrl}/${exportName}', async (c) => {
|
|
|
94
96
|
}
|
|
95
97
|
})`;
|
|
96
98
|
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Generate Cloudflare Pages Functions from pre-collected server entries. Returns a Map of relative
|
|
102
|
+
* file paths (under `functions/`) to source strings.
|
|
103
|
+
*
|
|
104
|
+
* @param {{ exportName: string; src: string }[]} entries - Resolved server entries
|
|
105
|
+
* @param {object} [opts]
|
|
106
|
+
* @param {string} [opts.baseUrl] - Base path prefix. Default is `'/_jx/server'`
|
|
107
|
+
* @returns {Map<string, string>} Map of output path → source (e.g.
|
|
108
|
+
* `"functions/_jx/server/sendEmail.js"` → source)
|
|
109
|
+
*/
|
|
110
|
+
export function compilePagesFunctions(entries, opts = {}) {
|
|
111
|
+
const { baseUrl = "/_jx/server" } = opts;
|
|
112
|
+
const files = new Map();
|
|
113
|
+
|
|
114
|
+
for (const { exportName, src } of entries) {
|
|
115
|
+
const relativeSrc = src.startsWith("./") ? src : `./${src}`;
|
|
116
|
+
const funcPath = `functions${baseUrl}/${exportName}.js`;
|
|
117
|
+
const depth = funcPath.split("/").length - 1;
|
|
118
|
+
const importPath = "../".repeat(depth) + relativeSrc.replace(/^\.\//, "");
|
|
119
|
+
|
|
120
|
+
const source = `// Generated by @jxsuite/compiler — do not edit manually
|
|
121
|
+
import { ${exportName} } from '${importPath}'
|
|
122
|
+
|
|
123
|
+
export async function onRequestPost(context) {
|
|
124
|
+
const args = await context.request.json().catch(() => ({}))
|
|
125
|
+
try {
|
|
126
|
+
const result = await ${exportName}(args, context.env)
|
|
127
|
+
return Response.json(result)
|
|
128
|
+
} catch (e) {
|
|
129
|
+
return Response.json({ ok: false, error: e?.message ?? 'Server error' }, { status: 500 })
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
`;
|
|
133
|
+
files.set(funcPath, source);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return files;
|
|
137
|
+
}
|