rwsdk 0.1.14 → 0.1.15

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.
@@ -1,8 +1,7 @@
1
1
  import { Plugin } from "vite";
2
2
  export declare const cloudflareBuiltInModules: string[];
3
3
  export declare const externalModules: string[];
4
- export declare const configPlugin: ({ mode, silent, projectRootDir, clientEntryPathnames, workerEntryPathname, }: {
5
- mode: "development" | "production";
4
+ export declare const configPlugin: ({ silent, projectRootDir, clientEntryPathnames, workerEntryPathname, }: {
6
5
  silent: boolean;
7
6
  projectRootDir: string;
8
7
  clientEntryPathnames: string[];
@@ -1,7 +1,7 @@
1
1
  import path, { resolve } from "node:path";
2
+ import { builtinModules } from "node:module";
2
3
  import enhancedResolve from "enhanced-resolve";
3
4
  import { SSR_BRIDGE_PATH } from "../lib/constants.mjs";
4
- import { builtinModules } from "node:module";
5
5
  // port(justinvdm, 09 Jun 2025):
6
6
  // https://github.com/cloudflare/workers-sdk/blob/d533f5ee7da69c205d8d5e2a5f264d2370fc612b/packages/vite-plugin-cloudflare/src/cloudflare-environment.ts#L123-L128
7
7
  export const cloudflareBuiltInModules = [
@@ -15,9 +15,10 @@ export const externalModules = [
15
15
  ...builtinModules,
16
16
  ...builtinModules.map((m) => `node:${m}`),
17
17
  ];
18
- export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathnames, workerEntryPathname, }) => ({
18
+ export const configPlugin = ({ silent, projectRootDir, clientEntryPathnames, workerEntryPathname, }) => ({
19
19
  name: "rwsdk:config",
20
- config: (_, { command }) => {
20
+ config: async (_) => {
21
+ const mode = process.env.NODE_ENV;
21
22
  const baseConfig = {
22
23
  appType: "custom",
23
24
  mode,
@@ -78,6 +79,9 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
78
79
  jsx: "automatic",
79
80
  jsxImportSource: "react",
80
81
  plugins: [],
82
+ define: {
83
+ "process.env.NODE_ENV": JSON.stringify(mode),
84
+ },
81
85
  },
82
86
  },
83
87
  build: {
@@ -121,6 +125,9 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
121
125
  esbuildOptions: {
122
126
  jsx: "automatic",
123
127
  jsxImportSource: "react",
128
+ define: {
129
+ "process.env.NODE_ENV": JSON.stringify(mode),
130
+ },
124
131
  },
125
132
  },
126
133
  build: {
@@ -9,7 +9,6 @@ import { getSrcPaths } from "../lib/getSrcPaths.js";
9
9
  import { hasDirective } from "./hasDirective.mjs";
10
10
  export const findFilesContainingDirective = async ({ projectRootDir, files, directive, debugNamespace, }) => {
11
11
  const log = debug(debugNamespace);
12
- const verboseLog = debug(`verbose:${debugNamespace}`);
13
12
  log("Starting search for '%s' files in projectRootDir=%s", directive, projectRootDir);
14
13
  const filesToScan = await getSrcPaths(projectRootDir);
15
14
  log("Found %d files to scan for '%s' directive", filesToScan.length, directive);
@@ -17,10 +16,10 @@ export const findFilesContainingDirective = async ({ projectRootDir, files, dire
17
16
  try {
18
17
  const stats = await stat(file);
19
18
  if (!stats.isFile()) {
20
- verboseLog("Skipping %s (not a file)", file);
19
+ process.env.VERBOSE && log("Skipping %s (not a file)", file);
21
20
  continue;
22
21
  }
23
- verboseLog("Scanning file: %s", file);
22
+ process.env.VERBOSE && log("Scanning file: %s", file);
24
23
  const content = await readFile(file, "utf-8");
25
24
  if (hasDirective(content, directive)) {
26
25
  const normalizedPath = normalizeModulePath(projectRootDir, file);
@@ -33,11 +32,11 @@ export const findFilesContainingDirective = async ({ projectRootDir, files, dire
33
32
  }
34
33
  }
35
34
  log("Completed scan. Found %d %s files total", files.size, directive);
36
- verboseLog("Found files for %s: %j", directive, Array.from(files));
35
+ process.env.VERBOSE &&
36
+ log("Found files for %s: %j", directive, Array.from(files));
37
37
  };
38
38
  const resolveOptimizedDep = async (projectRootDir, id, environment, debugNamespace) => {
39
39
  const log = debug(debugNamespace);
40
- const verboseLog = debug(`verbose:${debugNamespace}`);
41
40
  try {
42
41
  const depsDir = environment === "client" ? "deps" : `deps_${environment}`;
43
42
  const nodeModulesDepsDirPath = path.join("node_modules", ".vite", depsDir);
@@ -57,25 +56,26 @@ const resolveOptimizedDep = async (projectRootDir, id, environment, debugNamespa
57
56
  log("Found optimized dependency: filePath=%s, optimizedPath=%s", id, optimizedPath);
58
57
  return optimizedPath;
59
58
  }
60
- verboseLog("File not found in optimized dependencies: id=%s", id);
59
+ process.env.VERBOSE &&
60
+ log("File not found in optimized dependencies: id=%s", id);
61
61
  return undefined;
62
62
  }
63
63
  catch (error) {
64
- verboseLog("Error resolving optimized dependency for id=%s: %s", id, error);
64
+ process.env.VERBOSE &&
65
+ log("Error resolving optimized dependency for id=%s: %s", id, error);
65
66
  return undefined;
66
67
  }
67
68
  };
68
69
  const addOptimizedDepsEntries = async ({ projectRootDir, directive, environment, debugNamespace, files, }) => {
69
70
  const log = debug(debugNamespace);
70
- const verboseLog = debug(`verbose:${debugNamespace}`);
71
71
  try {
72
72
  const depsDir = environment === "client" ? "deps" : `deps_${environment}`;
73
73
  const depsDirPath = path.join(projectRootDir, "node_modules", ".vite", depsDir);
74
74
  const manifestPath = path.join(depsDirPath, "_metadata.json");
75
- verboseLog("Checking for manifest at: %s", manifestPath);
75
+ process.env.VERBOSE && log("Checking for manifest at: %s", manifestPath);
76
76
  const manifestExists = await pathExists(manifestPath);
77
77
  if (!manifestExists) {
78
- verboseLog("Manifest not found at %s", manifestPath);
78
+ process.env.VERBOSE && log("Manifest not found at %s", manifestPath);
79
79
  return;
80
80
  }
81
81
  const manifestContent = await readFile(manifestPath, "utf-8");
@@ -89,7 +89,8 @@ const addOptimizedDepsEntries = async ({ projectRootDir, directive, environment,
89
89
  contents = await readFile(resolvedSrcPath, "utf-8");
90
90
  }
91
91
  catch (error) {
92
- verboseLog("Error reading file %s: %s", resolvedSrcPath, error);
92
+ process.env.VERBOSE &&
93
+ log("Error reading file %s: %s", resolvedSrcPath, error);
93
94
  continue;
94
95
  }
95
96
  if (hasDirective(contents, directive)) {
@@ -103,13 +104,13 @@ const addOptimizedDepsEntries = async ({ projectRootDir, directive, environment,
103
104
  }
104
105
  }
105
106
  catch (error) {
106
- verboseLog("Error adding optimized deps entries: %s", error);
107
+ process.env.VERBOSE &&
108
+ log("Error adding optimized deps entries: %s", error);
107
109
  }
108
110
  };
109
111
  export const createDirectiveLookupPlugin = async ({ projectRootDir, files, config, }) => {
110
112
  const debugNamespace = `rwsdk:vite:${config.pluginName}`;
111
113
  const log = debug(debugNamespace);
112
- const verboseLog = debug(`verbose:${debugNamespace}`);
113
114
  let isDev = false;
114
115
  log("Initializing %s plugin with projectRootDir=%s", config.pluginName, projectRootDir);
115
116
  await findFilesContainingDirective({
@@ -151,7 +152,8 @@ export const createDirectiveLookupPlugin = async ({ projectRootDir, files, confi
151
152
  build.onResolve({
152
153
  filter: new RegExp(`^(${escapedVirtualModuleName}|${escapedPrefixedModuleName})$`),
153
154
  }, () => {
154
- verboseLog("Esbuild onResolve: marking %s as external", config.virtualModuleName);
155
+ process.env.VERBOSE &&
156
+ log("Esbuild onResolve: marking %s as external", config.virtualModuleName);
155
157
  return {
156
158
  path: config.virtualModuleName,
157
159
  external: true,
@@ -166,7 +168,8 @@ export const createDirectiveLookupPlugin = async ({ projectRootDir, files, confi
166
168
  viteConfig.optimizeDeps.include ??= [];
167
169
  for (const file of files) {
168
170
  const actualFilePath = path.join(projectRootDir, file);
169
- verboseLog("Adding to optimizeDeps.entries: %s", actualFilePath);
171
+ process.env.VERBOSE &&
172
+ log("Adding to optimizeDeps.entries: %s", actualFilePath);
170
173
  const entries = Array.isArray(viteConfig.optimizeDeps.entries)
171
174
  ? viteConfig.optimizeDeps.entries
172
175
  : [].concat(viteConfig.optimizeDeps.entries ?? []);
@@ -180,19 +183,19 @@ export const createDirectiveLookupPlugin = async ({ projectRootDir, files, confi
180
183
  }
181
184
  },
182
185
  resolveId(source) {
183
- verboseLog("Resolving id=%s", source);
186
+ process.env.VERBOSE && log("Resolving id=%s", source);
184
187
  if (source === config.virtualModuleName ||
185
188
  source === `/@id/${config.virtualModuleName}` ||
186
189
  source === `/@id/${config.virtualModuleName}.js`) {
187
190
  log("Resolving %s module", config.virtualModuleName);
188
191
  // context(justinvdm, 16 Jun 2025): Include .js extension
189
192
  // so it goes through vite processing chain
190
- return config.virtualModuleName + ".js";
193
+ return `${config.virtualModuleName}.js`;
191
194
  }
192
- verboseLog("No resolution for id=%s", source);
195
+ process.env.VERBOSE && log("No resolution for id=%s", source);
193
196
  },
194
197
  async load(id) {
195
- verboseLog("Loading id=%s", id);
198
+ process.env.VERBOSE && log("Loading id=%s", id);
196
199
  if (id === config.virtualModuleName + ".js") {
197
200
  log("Loading %s module with %d files", config.virtualModuleName, files.size);
198
201
  const environment = this.environment?.name || "client";
@@ -218,13 +221,13 @@ export const ${config.exportName} = {
218
221
  const code = s.toString();
219
222
  const map = s.generateMap();
220
223
  log("Generated virtual module code length: %d", code.length);
221
- verboseLog("Generated virtual module code: %s", code);
224
+ process.env.VERBOSE && log("Generated virtual module code: %s", code);
222
225
  return {
223
226
  code,
224
227
  map,
225
228
  };
226
229
  }
227
- verboseLog("No load handling for id=%s", id);
230
+ process.env.VERBOSE && log("No load handling for id=%s", id);
228
231
  },
229
232
  };
230
233
  };
@@ -5,7 +5,6 @@ import { transformClientComponents } from "./transformClientComponents.mjs";
5
5
  import { transformServerFunctions } from "./transformServerFunctions.mjs";
6
6
  import { normalizeModulePath } from "./normalizeModulePath.mjs";
7
7
  const log = debug("rwsdk:vite:rsc-directives-plugin");
8
- const verboseLog = debug("verbose:rwsdk:vite:rsc-directives-plugin");
9
8
  const getLoader = (filePath) => {
10
9
  const ext = path.extname(filePath).slice(1);
11
10
  switch (ext) {
@@ -76,7 +75,8 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
76
75
  });
77
76
  },
78
77
  async transform(code, id) {
79
- verboseLog("Transform called for id=%s, environment=%s", id, this.environment.name);
78
+ process.env.VERBOSE &&
79
+ log("Transform called for id=%s, environment=%s", id, this.environment.name);
80
80
  const normalizedId = normalizeModulePath(projectRootDir, id);
81
81
  const clientResult = await transformClientComponents(code, normalizedId, {
82
82
  environmentName: this.environment.name,
@@ -98,7 +98,7 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
98
98
  map: serverResult.map,
99
99
  };
100
100
  }
101
- verboseLog("No transformation applied for id=%s", id);
101
+ process.env.VERBOSE && log("No transformation applied for id=%s", id);
102
102
  },
103
103
  configEnvironment(env, config) {
104
104
  log("Configuring environment: env=%s", env);
@@ -110,7 +110,8 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
110
110
  setup(build) {
111
111
  log("Setting up esbuild plugin for environment: %s", env);
112
112
  build.onLoad({ filter: /\.(js|ts|jsx|tsx|mts|mjs|cjs)$/ }, async (args) => {
113
- verboseLog("Esbuild onLoad called for environment=%s, path=%s", env, args.path);
113
+ process.env.VERBOSE &&
114
+ log("Esbuild onLoad called for environment=%s, path=%s", env, args.path);
114
115
  const normalizedPath = normalizeModulePath(projectRootDir, args.path);
115
116
  // context(justinvdm,2025-06-15): If we're in app code,
116
117
  // we will be doing the transform work in the vite plugin hooks,
@@ -161,7 +162,8 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
161
162
  code = await fs.readFile(args.path, "utf-8");
162
163
  }
163
164
  catch {
164
- verboseLog("Failed to read file: %s, environment=%s", args.path, env);
165
+ process.env.VERBOSE &&
166
+ log("Failed to read file: %s, environment=%s", args.path, env);
165
167
  return undefined;
166
168
  }
167
169
  const clientResult = await transformClientComponents(code, normalizedPath, {
@@ -172,7 +174,8 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
172
174
  });
173
175
  if (clientResult) {
174
176
  log("Esbuild client component transformation successful for environment=%s, path=%s", env, args.path);
175
- verboseLog("Esbuild client component transformation for environment=%s, path=%s, code: %j", env, args.path, clientResult.code);
177
+ process.env.VERBOSE &&
178
+ log("Esbuild client component transformation for environment=%s, path=%s, code: %j", env, args.path, clientResult.code);
176
179
  return {
177
180
  contents: clientResult.code,
178
181
  loader: getLoader(args.path),
@@ -186,7 +189,8 @@ export const directivesPlugin = ({ projectRootDir, clientFiles, serverFiles, })
186
189
  loader: getLoader(args.path),
187
190
  };
188
191
  }
189
- verboseLog("Esbuild no transformation applied for environment=%s, path=%s", env, args.path);
192
+ process.env.VERBOSE &&
193
+ log("Esbuild no transformation applied for environment=%s, path=%s", env, args.path);
190
194
  });
191
195
  },
192
196
  });
@@ -52,7 +52,7 @@ export const EXPORT_PATTERNS = [
52
52
  export function findImportSpecifiers(id, code, ignoredImportPatterns, log) {
53
53
  const ext = path.extname(id).toLowerCase();
54
54
  const lang = ext === ".tsx" || ext === ".jsx" ? Lang.Tsx : SgLang.TypeScript;
55
- const logger = log ?? (() => { });
55
+ const logger = process.env.VERBOSE ? (log ?? (() => { })) : () => { };
56
56
  const results = [];
57
57
  try {
58
58
  // sgParse and lang must be provided by the consumer
@@ -101,7 +101,7 @@ export function findImportSpecifiers(id, code, ignoredImportPatterns, log) {
101
101
  export function findExports(id, code, log) {
102
102
  const ext = path.extname(id).toLowerCase();
103
103
  const lang = ext === ".tsx" || ext === ".jsx" ? Lang.Tsx : SgLang.TypeScript;
104
- const logger = log ?? (() => { });
104
+ const logger = process.env.VERBOSE ? (log ?? (() => { })) : () => { };
105
105
  const results = [];
106
106
  const seen = new Set(); // Track seen exports to avoid duplicates
107
107
  try {
@@ -10,7 +10,7 @@ import path from "path";
10
10
  export function findSsrImportSpecifiers(id, code, log) {
11
11
  const ext = path.extname(id).toLowerCase();
12
12
  const lang = ext === ".tsx" || ext === ".jsx" ? Lang.Tsx : SgLang.TypeScript;
13
- const logger = log ?? (() => { });
13
+ const logger = process.env.VERBOSE ? (log ?? (() => { })) : () => { };
14
14
  const imports = [];
15
15
  const dynamicImports = [];
16
16
  try {
@@ -1,5 +1,4 @@
1
1
  import { type Plugin } from "vite";
2
- export declare const injectVitePreamble: ({ clientEntryPathnames, mode, }: {
2
+ export declare const injectVitePreamble: ({ clientEntryPathnames, }: {
3
3
  clientEntryPathnames: string[];
4
- mode: "development" | "production";
5
4
  }) => Plugin;
@@ -1,5 +1,5 @@
1
1
  import MagicString from "magic-string";
2
- export const injectVitePreamble = ({ clientEntryPathnames, mode, }) => ({
2
+ export const injectVitePreamble = ({ clientEntryPathnames, }) => ({
3
3
  name: "rwsdk:inject-vite-preamble",
4
4
  apply: "serve",
5
5
  transform(code, id) {
@@ -10,7 +10,7 @@ export const injectVitePreamble = ({ clientEntryPathnames, mode, }) => ({
10
10
  return;
11
11
  }
12
12
  // Only inject preamble in development mode
13
- if (mode !== "development") {
13
+ if (process.env.NODE_ENV !== "development") {
14
14
  return;
15
15
  }
16
16
  const s = new MagicString(code);
@@ -8,7 +8,7 @@ import { hasDirective as sourceHasDirective } from "./hasDirective.mjs";
8
8
  import { isJsFile } from "./isJsFile.mjs";
9
9
  import { invalidateModule } from "./invalidateModule.mjs";
10
10
  import { getShortName } from "../lib/getShortName.mjs";
11
- const verboseLog = debug("verbose:rwsdk:vite:hmr-plugin");
11
+ const log = debug("rwsdk:vite:hmr-plugin");
12
12
  const hasDirective = async (filepath, directive) => {
13
13
  if (!isJsFile(filepath)) {
14
14
  return false;
@@ -37,7 +37,9 @@ export const miniflareHMRPlugin = (givenOptions) => [
37
37
  name: "rwsdk:miniflare-hmr",
38
38
  async hotUpdate(ctx) {
39
39
  const { clientFiles, serverFiles, viteEnvironment: { name: environment }, workerEntryPathname: entry, } = givenOptions;
40
- verboseLog("Hot update: (env=%s) %s\nModule graph:\n\n%s", this.environment.name, ctx.file, dumpFullModuleGraph(ctx.server, this.environment.name));
40
+ if (process.env.VERBOSE) {
41
+ this.environment.logger.info(`Hot update: (env=${this.environment.name}) ${ctx.file}\nModule graph:\n\n${dumpFullModuleGraph(ctx.server, this.environment.name)}`);
42
+ }
41
43
  if (!["client", environment].includes(this.environment.name)) {
42
44
  return [];
43
45
  }
@@ -0,0 +1,5 @@
1
+ import { ConfigEnv } from "vite";
2
+ type Mode = "development" | "production";
3
+ export declare const resolveMode: (env: ConfigEnv) => Mode;
4
+ export declare const ensureMode: () => Mode;
5
+ export {};
@@ -0,0 +1,25 @@
1
+ import debug from "debug";
2
+ const log = debug("rwsdk:vite:mode");
3
+ const initialNodeEnv = process.env.NODE_ENV;
4
+ let mode;
5
+ export const resolveMode = (env) => {
6
+ if (mode) {
7
+ return mode;
8
+ }
9
+ if (initialNodeEnv) {
10
+ mode = initialNodeEnv === "development" ? "development" : "production";
11
+ log(`Resolved mode: %s (from initial NODE_ENV=%s)`, mode, initialNodeEnv);
12
+ }
13
+ else {
14
+ mode =
15
+ env.command === "serve" || env.isPreview ? "development" : "production";
16
+ log(`Resolved mode: %s (env.command=%s, env.isPreview=%s)`, mode, env.isPreview, env.command);
17
+ }
18
+ return mode;
19
+ };
20
+ export const ensureMode = () => {
21
+ if (mode === undefined) {
22
+ throw new Error("RedwoodSDK: mode is not resolved yet");
23
+ }
24
+ return mode;
25
+ };
@@ -0,0 +1,2 @@
1
+ import { Plugin } from "vite";
2
+ export declare function modePlugin(): Plugin;
@@ -0,0 +1,10 @@
1
+ import { resolveMode } from "./mode.mjs";
2
+ export function modePlugin() {
3
+ return {
4
+ name: "rwsdk:mode",
5
+ enforce: "pre",
6
+ config(_, env) {
7
+ resolveMode(env);
8
+ },
9
+ };
10
+ }
@@ -3,7 +3,6 @@ import { ROOT_DIR } from "../lib/constants.mjs";
3
3
  import enhancedResolve from "enhanced-resolve";
4
4
  import { ensureAliasArray } from "./ensureAliasArray.mjs";
5
5
  const log = debug("rwsdk:vite:react-conditions-resolver-plugin");
6
- const verboseLog = debug("verbose:rwsdk:vite:react-conditions-resolver-plugin");
7
6
  export const ENV_REACT_IMPORTS = {
8
7
  worker: [
9
8
  "react",
@@ -47,18 +46,22 @@ export const ENV_IMPORT_MAPPINGS = Object.fromEntries(Object.keys(ENV_RESOLVERS)
47
46
  resolveEnvImportMappings(env),
48
47
  ]));
49
48
  function resolveEnvImportMappings(env) {
50
- verboseLog("Resolving environment import mappings for env=%s", env);
49
+ process.env.VERBOSE &&
50
+ log("Resolving environment import mappings for env=%s", env);
51
51
  const mappings = new Map();
52
52
  const reactImports = ENV_REACT_IMPORTS[env];
53
53
  for (const importRequest of reactImports) {
54
- verboseLog("Resolving import request=%s for env=%s", importRequest, env);
54
+ process.env.VERBOSE &&
55
+ log("Resolving import request=%s for env=%s", importRequest, env);
55
56
  let resolved = false;
56
57
  try {
57
58
  resolved = ENV_RESOLVERS[env](ROOT_DIR, importRequest);
58
- verboseLog("Successfully resolved %s to %s for env=%s", importRequest, resolved, env);
59
+ process.env.VERBOSE &&
60
+ log("Successfully resolved %s to %s for env=%s", importRequest, resolved, env);
59
61
  }
60
62
  catch {
61
- verboseLog("Failed to resolve %s for env=%s", importRequest, env);
63
+ process.env.VERBOSE &&
64
+ log("Failed to resolve %s for env=%s", importRequest, env);
62
65
  }
63
66
  if (resolved) {
64
67
  mappings.set(importRequest, resolved);
@@ -77,10 +80,12 @@ function createEsbuildResolverPlugin(envName) {
77
80
  name: `rwsdk:react-conditions-resolver-esbuild-${envName}`,
78
81
  setup(build) {
79
82
  build.onResolve({ filter: /.*/ }, (args) => {
80
- verboseLog("ESBuild resolving %s for env=%s, args=%O", args.path, envName, args);
83
+ process.env.VERBOSE &&
84
+ log("ESBuild resolving %s for env=%s, args=%O", args.path, envName, args);
81
85
  const resolved = mappings.get(args.path);
82
86
  if (resolved && args.importer !== "") {
83
- verboseLog("ESBuild resolving %s -> %s for env=%s", args.path, resolved, envName);
87
+ process.env.VERBOSE &&
88
+ log("ESBuild resolving %s -> %s for env=%s", args.path, resolved, envName);
84
89
  if (args.path === "react-server-dom-webpack/client.edge") {
85
90
  return;
86
91
  }
@@ -89,7 +94,8 @@ function createEsbuildResolverPlugin(envName) {
89
94
  };
90
95
  }
91
96
  else {
92
- verboseLog("ESBuild no resolution found for %s for env=%s", args.path, envName);
97
+ process.env.VERBOSE &&
98
+ log("ESBuild no resolution found for %s for env=%s", args.path, envName);
93
99
  }
94
100
  });
95
101
  },
@@ -124,7 +130,7 @@ export const reactConditionsResolverPlugin = () => {
124
130
  envConfig.optimizeDeps ??= {};
125
131
  envConfig.optimizeDeps.esbuildOptions ??= {};
126
132
  envConfig.optimizeDeps.esbuildOptions.define ??= {};
127
- envConfig.optimizeDeps.esbuildOptions.define["process.env.NODE_ENV"] = JSON.stringify(process.env.NODE_ENV ?? "production");
133
+ envConfig.optimizeDeps.esbuildOptions.define["process.env.NODE_ENV"] = JSON.stringify(process.env.NODE_ENV);
128
134
  envConfig.optimizeDeps.esbuildOptions.plugins ??= [];
129
135
  envConfig.optimizeDeps.esbuildOptions.plugins.push(esbuildPlugin);
130
136
  envConfig.optimizeDeps.include ??= [];
@@ -152,10 +158,12 @@ export const reactConditionsResolverPlugin = () => {
152
158
  if (!envName) {
153
159
  return;
154
160
  }
155
- verboseLog("Resolving id=%s, environment=%s, importer=%s", id, envName, importer);
161
+ process.env.VERBOSE &&
162
+ log("Resolving id=%s, environment=%s, importer=%s", id, envName, importer);
156
163
  const mappings = ENV_IMPORT_MAPPINGS[envName];
157
164
  if (!mappings) {
158
- verboseLog("No mappings found for environment: %s", envName);
165
+ process.env.VERBOSE &&
166
+ log("No mappings found for environment: %s", envName);
159
167
  return;
160
168
  }
161
169
  const resolved = mappings.get(id);
@@ -163,7 +171,8 @@ export const reactConditionsResolverPlugin = () => {
163
171
  log("Resolved %s -> %s for env=%s", id, resolved, envName);
164
172
  return resolved;
165
173
  }
166
- verboseLog("No resolution found for id=%s in env=%s", id, envName);
174
+ process.env.VERBOSE &&
175
+ log("No resolution found for id=%s in env=%s", id, envName);
167
176
  },
168
177
  },
169
178
  ];
@@ -2,7 +2,6 @@ import { InlineConfig } from "vite";
2
2
  export type RedwoodPluginOptions = {
3
3
  silent?: boolean;
4
4
  rootDir?: string;
5
- mode?: "development" | "production";
6
5
  includeCloudflarePlugin?: boolean;
7
6
  configPath?: string;
8
7
  entry?: {
@@ -30,8 +30,6 @@ const determineWorkerEntryPathname = async (projectRootDir, workerConfigPath, op
30
30
  };
31
31
  export const redwoodPlugin = async (options = {}) => {
32
32
  const projectRootDir = process.cwd();
33
- const mode = options.mode ??
34
- (process.env.NODE_ENV === "development" ? "development" : "production");
35
33
  const workerConfigPath = options.configPath ?? (await findWranglerConfig(projectRootDir));
36
34
  const workerEntryPathname = await determineWorkerEntryPathname(projectRootDir, workerConfigPath, options);
37
35
  const clientEntryPathnames = (Array.isArray(options.entry?.client)
@@ -57,7 +55,6 @@ export const redwoodPlugin = async (options = {}) => {
57
55
  return [
58
56
  devServerTimingPlugin(),
59
57
  configPlugin({
60
- mode,
61
58
  silent: options.silent ?? false,
62
59
  projectRootDir,
63
60
  clientEntryPathnames,
@@ -90,7 +87,7 @@ export const redwoodPlugin = async (options = {}) => {
90
87
  serverFiles,
91
88
  }),
92
89
  vitePreamblePlugin(),
93
- injectVitePreamble({ clientEntryPathnames, mode }),
90
+ injectVitePreamble({ clientEntryPathnames }),
94
91
  useClientLookupPlugin({
95
92
  projectRootDir,
96
93
  clientFiles,
@@ -2,7 +2,6 @@ import debug from "debug";
2
2
  import { SSR_BRIDGE_PATH } from "../lib/constants.mjs";
3
3
  import { findSsrImportSpecifiers } from "./findSsrSpecifiers.mjs";
4
4
  const log = debug("rwsdk:vite:ssr-bridge-plugin");
5
- const verboseLog = debug("verbose:rwsdk:vite:ssr-bridge-plugin");
6
5
  export const VIRTUAL_SSR_PREFIX = "virtual:rwsdk:ssr:";
7
6
  export const ssrBridgePlugin = ({ clientFiles, serverFiles, }) => {
8
7
  log("Initializing SSR bridge plugin with SSR_BRIDGE_PATH=%s", SSR_BRIDGE_PATH);
@@ -33,7 +32,8 @@ export const ssrBridgePlugin = ({ clientFiles, serverFiles, }) => {
33
32
  setup(build) {
34
33
  log("Setting up esbuild plugin to mark rwsdk/__ssr paths as external for worker");
35
34
  build.onResolve({ filter: /.*$/ }, (args) => {
36
- verboseLog("Esbuild onResolve called for path=%s, args=%O", args.path, args);
35
+ process.env.VERBOSE &&
36
+ log("Esbuild onResolve called for path=%s, args=%O", args.path, args);
37
37
  if (args.path === "rwsdk/__ssr_bridge") {
38
38
  log("Marking as external: %s", args.path);
39
39
  return {
@@ -48,7 +48,8 @@ export const ssrBridgePlugin = ({ clientFiles, serverFiles, }) => {
48
48
  }
49
49
  },
50
50
  async resolveId(id) {
51
- verboseLog("Resolving id=%s, environment=%s, isDev=%s", id, this.environment?.name, isDev);
51
+ process.env.VERBOSE &&
52
+ log("Resolving id=%s, environment=%s, isDev=%s", id, this.environment?.name, isDev);
52
53
  if (isDev) {
53
54
  // context(justinvdm, 27 May 2025): In dev, we need to dynamically load
54
55
  // SSR modules, so we return the virtual id so that the dynamic loading
@@ -77,10 +78,11 @@ export const ssrBridgePlugin = ({ clientFiles, serverFiles, }) => {
77
78
  return SSR_BRIDGE_PATH;
78
79
  }
79
80
  }
80
- verboseLog("No resolution for id=%s", id);
81
+ process.env.VERBOSE && log("No resolution for id=%s", id);
81
82
  },
82
83
  async load(id) {
83
- verboseLog("Loading id=%s, isDev=%s, environment=%s", id, isDev, this.environment.name);
84
+ process.env.VERBOSE &&
85
+ log("Loading id=%s, isDev=%s, environment=%s", id, isDev, this.environment.name);
84
86
  if (id.startsWith(VIRTUAL_SSR_PREFIX) &&
85
87
  this.environment.name === "worker") {
86
88
  const realId = id.slice(VIRTUAL_SSR_PREFIX.length);
@@ -88,10 +90,11 @@ export const ssrBridgePlugin = ({ clientFiles, serverFiles, }) => {
88
90
  if (isDev) {
89
91
  log("Dev mode: fetching SSR module for realPath=%s", realId);
90
92
  const result = await devServer?.environments.ssr.fetchModule(realId);
91
- verboseLog("Fetch module result: id=%s, result=%O", realId, result);
93
+ process.env.VERBOSE &&
94
+ log("Fetch module result: id=%s, result=%O", realId, result);
92
95
  const code = "code" in result ? result.code : undefined;
93
96
  log("Fetched SSR module code length: %d", code?.length || 0);
94
- const { imports, dynamicImports } = findSsrImportSpecifiers(realId, code || "", verboseLog);
97
+ const { imports, dynamicImports } = findSsrImportSpecifiers(realId, code || "", log);
95
98
  const allSpecifiers = [...new Set([...imports, ...dynamicImports])];
96
99
  const switchCases = allSpecifiers
97
100
  .map((specifier) => ` case "${specifier}": return import("${VIRTUAL_SSR_PREFIX}${specifier}");`)
@@ -109,11 +112,12 @@ ${switchCases}
109
112
  }
110
113
  `;
111
114
  log("Transformed SSR module code length: %d", transformedCode.length);
112
- verboseLog("Transformed SSR module code for realId=%s: %s", realId, transformedCode);
115
+ process.env.VERBOSE &&
116
+ log("Transformed SSR module code for realId=%s: %s", realId, transformedCode);
113
117
  return transformedCode;
114
118
  }
115
119
  }
116
- verboseLog("No load handling for id=%s", id);
120
+ process.env.VERBOSE && log("No load handling for id=%s", id);
117
121
  },
118
122
  };
119
123
  return ssrBridgePlugin;
@@ -4,21 +4,19 @@ import { hasDirective } from "./hasDirective.mjs";
4
4
  import { findExports } from "./findSpecifiers.mjs";
5
5
  const logVite = debug("rwsdk:vite:transform-client-components:vite");
6
6
  const logEsbuild = debug("rwsdk:vite:transform-client-components:esbuild");
7
- const verboseLogVite = debug("verbose:rwsdk:vite:transform-client-components:vite");
8
- const verboseLogEsbuild = debug("verbose:rwsdk:vite:transform-client-components:esbuild");
9
7
  export async function transformClientComponents(code, normalizedId, ctx) {
10
8
  const log = ctx.isEsbuild ? logEsbuild : logVite;
11
- const verboseLog = ctx.isEsbuild ? verboseLogEsbuild : verboseLogVite;
12
9
  log("Called transformClientComponents for id: id=%s", normalizedId);
13
10
  if (!hasDirective(code, "use client")) {
14
11
  log("Skipping: no 'use client' directive in id=%s", normalizedId);
15
- verboseLog(":VERBOSE: Returning code unchanged for id=%s:\n%s", normalizedId, code);
12
+ process.env.VERBOSE &&
13
+ log(":VERBOSE: Returning code unchanged for id=%s:\n%s", normalizedId, code);
16
14
  return;
17
15
  }
18
16
  log("Processing 'use client' module: id=%s", normalizedId);
19
17
  ctx.addClientModule?.(ctx.environmentName, normalizedId);
20
18
  // Parse exports using the findExports helper
21
- const exportInfos = findExports(normalizedId, code, verboseLog);
19
+ const exportInfos = findExports(normalizedId, code, log);
22
20
  const processedExports = [];
23
21
  let defaultExportInfo;
24
22
  // Helper to get the computed local name (with alias suffix if present)
@@ -62,7 +60,8 @@ export async function transformClientComponents(code, normalizedId, ctx) {
62
60
  const start = match.index;
63
61
  const end = match.index + match[0].length;
64
62
  s.remove(start, end);
65
- verboseLog("Removed 'use client' directive from normalizedId=%s", normalizedId);
63
+ process.env.VERBOSE &&
64
+ log("Removed 'use client' directive from normalizedId=%s", normalizedId);
66
65
  break; // Only remove the first one
67
66
  }
68
67
  const sourceMap = s.generateMap({
@@ -70,7 +69,8 @@ export async function transformClientComponents(code, normalizedId, ctx) {
70
69
  includeContent: true,
71
70
  hires: true,
72
71
  });
73
- verboseLog(":VERBOSE: SSR transformed code for %s:\n%s", normalizedId, s.toString());
72
+ process.env.VERBOSE &&
73
+ log(":VERBOSE: SSR transformed code for %s:\n%s", normalizedId, s.toString());
74
74
  return {
75
75
  code: s.toString(),
76
76
  map: sourceMap,
@@ -107,7 +107,8 @@ export async function transformClientComponents(code, normalizedId, ctx) {
107
107
  hires: true,
108
108
  });
109
109
  const finalResult = s.toString();
110
- verboseLog(":VERBOSE: Transformed code (env=%s, normalizedId=%s):\n%s", normalizedId, ctx.environmentName, finalResult);
110
+ process.env.VERBOSE &&
111
+ log(":VERBOSE: Transformed code (env=%s, normalizedId=%s):\n%s", normalizedId, ctx.environmentName, finalResult);
111
112
  return {
112
113
  code: finalResult,
113
114
  map: sourceMap,
@@ -5,15 +5,14 @@ import { findExports } from "./findSpecifiers.mjs";
5
5
  import { parse as sgParse, Lang as SgLang, Lang } from "@ast-grep/napi";
6
6
  import path from "path";
7
7
  const log = debug("rwsdk:vite:transform-server-functions");
8
- const verboseLog = debug("verbose:rwsdk:vite:transform-server-functions");
9
8
  export const findExportedFunctions = (code, normalizedId) => {
10
9
  return findExportInfo(code, normalizedId).localFunctions;
11
10
  };
12
11
  export const findExportInfo = (code, normalizedId) => {
13
- verboseLog("Finding exported functions in source file");
12
+ process.env.VERBOSE && log("Finding exported functions in source file");
14
13
  const localFunctions = new Set();
15
14
  const reExports = [];
16
- const exportInfos = findExports(normalizedId || "file.ts", code, verboseLog);
15
+ const exportInfos = findExports(normalizedId || "file.ts", code, log);
17
16
  for (const exportInfo of exportInfos) {
18
17
  if (exportInfo.isReExport && exportInfo.moduleSpecifier) {
19
18
  // For re-exports, we need to determine the original name by parsing the code
@@ -29,11 +28,13 @@ export const findExportInfo = (code, normalizedId) => {
29
28
  originalName: originalName,
30
29
  moduleSpecifier: exportInfo.moduleSpecifier,
31
30
  });
32
- verboseLog("Found re-exported function: %s (original: %s) from %s", exportInfo.name, originalName, exportInfo.moduleSpecifier);
31
+ process.env.VERBOSE &&
32
+ log("Found re-exported function: %s (original: %s) from %s", exportInfo.name, originalName, exportInfo.moduleSpecifier);
33
33
  }
34
34
  else {
35
35
  localFunctions.add(exportInfo.name);
36
- verboseLog("Found exported function: %s", exportInfo.name);
36
+ process.env.VERBOSE &&
37
+ log("Found exported function: %s", exportInfo.name);
37
38
  }
38
39
  }
39
40
  log("Found %d local functions: %O", localFunctions.size, Array.from(localFunctions));
@@ -55,7 +56,7 @@ function findDefaultFunctionName(code, normalizedId) {
55
56
  }
56
57
  }
57
58
  catch (err) {
58
- verboseLog("Error finding default function name: %O", err);
59
+ process.env.VERBOSE && log("Error finding default function name: %O", err);
59
60
  }
60
61
  return null;
61
62
  }
@@ -79,15 +80,17 @@ function hasDefaultExport(code, normalizedId) {
79
80
  }
80
81
  }
81
82
  catch (err) {
82
- verboseLog("Error checking for default export: %O", err);
83
+ process.env.VERBOSE && log("Error checking for default export: %O", err);
83
84
  }
84
85
  return false;
85
86
  }
86
87
  export const transformServerFunctions = (code, normalizedId, environment, serverFiles, addServerModule) => {
87
- verboseLog("Transform server functions called for normalizedId=%s, environment=%s", normalizedId, environment);
88
+ process.env.VERBOSE &&
89
+ log("Transform server functions called for normalizedId=%s, environment=%s", normalizedId, environment);
88
90
  if (!hasDirective(code, "use server")) {
89
91
  log("Skipping: no 'use server' directive in id=%s", normalizedId);
90
- verboseLog(":VERBOSE: Returning code unchanged for id=%s:\n%s", normalizedId, code);
92
+ process.env.VERBOSE &&
93
+ log(":VERBOSE: Returning code unchanged for id=%s:\n%s", normalizedId, code);
91
94
  return;
92
95
  }
93
96
  log("Processing 'use server' module: normalizedId=%s, environment=%s", normalizedId, environment);
@@ -144,7 +147,8 @@ export const transformServerFunctions = (code, normalizedId, environment, server
144
147
  const start = match.index;
145
148
  const end = match.index + match[0].length;
146
149
  s.remove(start, end);
147
- verboseLog("Removed 'use server' directive from normalizedId=%s", normalizedId);
150
+ process.env.VERBOSE &&
151
+ log("Removed 'use server' directive from normalizedId=%s", normalizedId);
148
152
  break; // Only remove the first one
149
153
  }
150
154
  // Add imports at the very beginning
@@ -239,7 +243,8 @@ export const transformServerFunctions = (code, normalizedId, environment, server
239
243
  }
240
244
  }
241
245
  catch (err) {
242
- verboseLog("Error processing default function: %O", err);
246
+ process.env.VERBOSE &&
247
+ log("Error processing default function: %O", err);
243
248
  }
244
249
  }
245
250
  // Add registration calls at the end
@@ -286,5 +291,6 @@ export const transformServerFunctions = (code, normalizedId, environment, server
286
291
  }),
287
292
  };
288
293
  }
289
- verboseLog("No transformation applied for environment=%s, normalizedId=%s", environment, normalizedId);
294
+ process.env.VERBOSE &&
295
+ log("No transformation applied for environment=%s, normalizedId=%s", environment, normalizedId);
290
296
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rwsdk",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime",
5
5
  "type": "module",
6
6
  "bin": {