@cloudwerk/vite-plugin 0.6.0 → 0.6.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.
Files changed (2) hide show
  1. package/dist/index.js +115 -3
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -57,6 +57,7 @@ function generateServerEntry(manifest, scanResult, options, entryOptions) {
57
57
  let middlewareIndex = 0;
58
58
  let errorIndex = 0;
59
59
  let notFoundIndex = 0;
60
+ const ssgPageInfo = [];
60
61
  for (const err of scanResult.errors) {
61
62
  if (!importedModules.has(err.absolutePath)) {
62
63
  const varName = `error_${errorIndex++}`;
@@ -109,6 +110,10 @@ function generateServerEntry(manifest, scanResult, options, entryOptions) {
109
110
  if (route.fileType === "page") {
110
111
  const varName = `page_${pageIndex++}`;
111
112
  imports.push(`import * as ${varName} from '${route.absolutePath}'`);
113
+ const hasDynamicSegments = route.segments.some(
114
+ (s) => s.type === "dynamic" || s.type === "catchAll" || s.type === "optionalCatchAll"
115
+ );
116
+ ssgPageInfo.push({ varName, urlPattern: route.urlPattern, hasDynamicSegments });
112
117
  const layoutChain = route.layouts.map((p) => layoutModules.get(p)).join(", ");
113
118
  const middlewareChain = route.middleware.map((p) => middlewareModules.get(p)).join(", ");
114
119
  const errorModule = route.errorBoundary ? errorModules.get(route.errorBoundary) : null;
@@ -140,6 +145,7 @@ function generateServerEntry(manifest, scanResult, options, entryOptions) {
140
145
  */
141
146
 
142
147
  import { Hono } from 'hono'
148
+ import { ssgParams } from 'hono/ssg'
143
149
  import { contextMiddleware, createHandlerAdapter, createMiddlewareAdapter, setRouteConfig, NotFoundError, RedirectError } from '@cloudwerk/core/runtime'
144
150
  import { setActiveRenderer } from '@cloudwerk/ui'
145
151
 
@@ -310,6 +316,11 @@ function registerPage(app, pattern, pageModule, layoutModules, middlewareModules
310
316
  })
311
317
  }
312
318
 
319
+ // Apply SSG params middleware if page has generateStaticParams (for static generation)
320
+ if (typeof pageModule.generateStaticParams === 'function') {
321
+ app.use(pattern, ssgParams(pageModule.generateStaticParams))
322
+ }
323
+
313
324
  // Register GET handler for page
314
325
  app.get(pattern, async (c) => {
315
326
  const params = c.req.param()
@@ -474,6 +485,13 @@ app.use('*', async (c, next) => {
474
485
  ${pageRegistrations.join("\n")}
475
486
  ${routeRegistrations.join("\n")}
476
487
 
488
+ // SSG routes endpoint - returns all static routes for build-time generation
489
+ app.get('/__ssg/routes', async (c) => {
490
+ const routes = []
491
+ ${generateSSGRouteChecks(ssgPageInfo)}
492
+ return c.json({ routes })
493
+ })
494
+
477
495
  // 404 handler
478
496
  app.notFound(async (c) => {
479
497
  const path = c.req.path
@@ -545,6 +563,36 @@ ${generateQueueExports(queueManifest)}
545
563
  ${generateServiceRegistration(serviceManifest)}
546
564
  `;
547
565
  }
566
+ function generateSSGRouteChecks(pages) {
567
+ const lines = [];
568
+ for (const page of pages) {
569
+ if (page.hasDynamicSegments) {
570
+ lines.push(` // ${page.urlPattern}`);
571
+ lines.push(` if (typeof ${page.varName}.generateStaticParams === 'function') {`);
572
+ lines.push(` try {`);
573
+ lines.push(` const params = await ${page.varName}.generateStaticParams()`);
574
+ lines.push(` if (Array.isArray(params)) {`);
575
+ lines.push(` for (const p of params) {`);
576
+ lines.push(` let url = '${page.urlPattern}'`);
577
+ lines.push(` for (const [key, value] of Object.entries(p)) {`);
578
+ lines.push(` url = url.replace(':' + key, String(value))`);
579
+ lines.push(` }`);
580
+ lines.push(` routes.push(url)`);
581
+ lines.push(` }`);
582
+ lines.push(` }`);
583
+ lines.push(` } catch (e) {`);
584
+ lines.push(` console.error('SSG: Failed to get params for ${page.urlPattern}:', e)`);
585
+ lines.push(` }`);
586
+ lines.push(` }`);
587
+ } else {
588
+ lines.push(` // ${page.urlPattern}`);
589
+ lines.push(` if ('config' in ${page.varName} && ${page.varName}.config?.rendering === 'static') {`);
590
+ lines.push(` routes.push('${page.urlPattern}')`);
591
+ lines.push(` }`);
592
+ }
593
+ }
594
+ return lines.join("\n");
595
+ }
548
596
  function generateQueueExports(queueManifest) {
549
597
  if (!queueManifest || queueManifest.queues.length === 0) {
550
598
  return "";
@@ -1919,13 +1967,71 @@ function cloudwerkPlugin(options = {}) {
1919
1967
  return null;
1920
1968
  },
1921
1969
  /**
1922
- * Transform hook to detect and wrap client components.
1970
+ * Transform hook to detect and wrap client components,
1971
+ * and rewrite binding imports to use the bindings proxy.
1923
1972
  */
1924
1973
  transform(code, id) {
1925
1974
  if (!state) return null;
1926
1975
  if (id.includes("node_modules")) return null;
1927
1976
  if (!id.endsWith(".tsx") && !id.endsWith(".ts")) return null;
1928
- if (hasUseClientDirective(code)) {
1977
+ let transformedCode = code;
1978
+ let wasTransformed = false;
1979
+ const bindingsImportRegex = /import\s*\{([^}]+)\}\s*from\s*['"]@cloudwerk\/core\/bindings['"]/g;
1980
+ if (bindingsImportRegex.test(code)) {
1981
+ bindingsImportRegex.lastIndex = 0;
1982
+ transformedCode = code.replace(bindingsImportRegex, (match, imports) => {
1983
+ const importNames = imports.split(",").map((s) => s.trim()).filter(Boolean);
1984
+ const knownExports = [
1985
+ "bindings",
1986
+ "getBinding",
1987
+ "hasBinding",
1988
+ "getBindingNames",
1989
+ "queues",
1990
+ "getQueue",
1991
+ "hasQueue",
1992
+ "getQueueNames",
1993
+ "services",
1994
+ "getService",
1995
+ "hasService",
1996
+ "getServiceNames",
1997
+ "registerLocalService",
1998
+ "unregisterLocalService",
1999
+ "clearLocalServices",
2000
+ "durableObjects",
2001
+ "getDurableObject",
2002
+ "hasDurableObject",
2003
+ "getDurableObjectNames",
2004
+ "createLazyBinding"
2005
+ ];
2006
+ const runtimeImports = [];
2007
+ const bindingImports = [];
2008
+ for (const name of importNames) {
2009
+ const [originalName] = name.split(/\s+as\s+/);
2010
+ if (knownExports.includes(originalName.trim())) {
2011
+ runtimeImports.push(name);
2012
+ } else {
2013
+ bindingImports.push(name);
2014
+ }
2015
+ }
2016
+ if (bindingImports.length === 0) {
2017
+ return match;
2018
+ }
2019
+ wasTransformed = true;
2020
+ const parts = [];
2021
+ const helperImports = runtimeImports.includes("createLazyBinding") ? runtimeImports : ["createLazyBinding", ...runtimeImports];
2022
+ parts.push(`import { ${helperImports.join(", ")} } from '@cloudwerk/core/bindings'`);
2023
+ for (const name of bindingImports) {
2024
+ const aliasMatch = name.match(/^(\w+)\s+as\s+(\w+)$/);
2025
+ if (aliasMatch) {
2026
+ parts.push(`const ${aliasMatch[2]} = createLazyBinding('${aliasMatch[1]}')`);
2027
+ } else {
2028
+ parts.push(`const ${name.trim()} = createLazyBinding('${name.trim()}')`);
2029
+ }
2030
+ }
2031
+ return parts.join("\n");
2032
+ });
2033
+ }
2034
+ if (hasUseClientDirective(transformedCode)) {
1929
2035
  const componentId = generateComponentId(id, state.options.root);
1930
2036
  const bundlePath = `${state.options.hydrationEndpoint}/${componentId}.js`;
1931
2037
  const info = {
@@ -1938,7 +2044,7 @@ function cloudwerkPlugin(options = {}) {
1938
2044
  if (state.options.verbose) {
1939
2045
  console.log(`[cloudwerk] Detected client component: ${componentId}`);
1940
2046
  }
1941
- const result = transformClientComponent(code, {
2047
+ const result = transformClientComponent(transformedCode, {
1942
2048
  componentId,
1943
2049
  bundlePath: id
1944
2050
  // Use file path for Vite to resolve in dev mode
@@ -1951,6 +2057,12 @@ function cloudwerkPlugin(options = {}) {
1951
2057
  map: null
1952
2058
  };
1953
2059
  }
2060
+ if (wasTransformed) {
2061
+ return {
2062
+ code: transformedCode,
2063
+ map: null
2064
+ };
2065
+ }
1954
2066
  return null;
1955
2067
  }
1956
2068
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudwerk/vite-plugin",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Vite plugin for Cloudwerk file-based routing with virtual entry generation",
5
5
  "repository": {
6
6
  "type": "git",
@@ -19,8 +19,8 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "@swc/core": "^1.3.100",
22
- "@cloudwerk/core": "^0.13.0",
23
- "@cloudwerk/ui": "^0.13.0"
22
+ "@cloudwerk/core": "^0.15.0",
23
+ "@cloudwerk/ui": "^0.15.0"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "vite": "^5.0.0 || ^6.0.0",