From 9d257e54ad04f7ec94a69acd718ac9254a758e20 Mon Sep 17 00:00:00 2001 From: bluwy Date: Tue, 1 Nov 2022 23:24:20 +0800 Subject: [PATCH 01/19] wip envKey --- packages/astro/src/core/config/schema.ts | 12 ++++ packages/astro/src/vite-plugin-env/index.ts | 67 ++++++++------------- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts index f9cddbf40623..cce0e4769893 100644 --- a/packages/astro/src/core/config/schema.ts +++ b/packages/astro/src/core/config/schema.ts @@ -113,6 +113,12 @@ export const AstroConfigSchema = z.object({ .default(ASTRO_CONFIG_DEFAULTS.build.server) .transform((val) => new URL(val)), serverEntry: z.string().optional().default(ASTRO_CONFIG_DEFAULTS.build.serverEntry), + envKey: z + .function() + .args(z.string()) + .returns(z.string()) + .optional() + .default(() => (key: string) => `process.env.${key}`), }) .optional() .default({}), @@ -266,6 +272,12 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: URL) { .default(ASTRO_CONFIG_DEFAULTS.build.server) .transform((val) => new URL(val, fileProtocolRoot)), serverEntry: z.string().optional().default(ASTRO_CONFIG_DEFAULTS.build.serverEntry), + envKey: z + .function() + .args(z.string()) + .returns(z.string()) + .optional() + .default(() => (key: string) => `process.env.${key}`), }) .optional() .default({}), diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 08332d717b2b..5f20c0e27af6 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -34,8 +34,7 @@ function getPrivateEnv(viteConfig: vite.ResolvedConfig, astroConfig: AstroConfig } return Object.fromEntries( privateKeys.map((key) => { - if (typeof process.env[key] !== 'undefined') return [key, `process.env.${key}`]; - return [key, JSON.stringify(fullEnv[key])]; + return [key, JSON.stringify(process.env[key] ?? fullEnv[key])]; }) ); } @@ -51,9 +50,8 @@ function getReferencedPrivateKeys(source: string, privateEnv: Record | null; + let privateEnv: Record; let config: vite.ResolvedConfig; - let replacements: Record; let pattern: RegExp | undefined; const { config: astroConfig } = settings; return { @@ -74,44 +72,28 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug } if (typeof privateEnv === 'undefined') { - privateEnv = getPrivateEnv(config, astroConfig); - if (privateEnv) { - privateEnv.SITE = astroConfig.site ? `'${astroConfig.site}'` : 'undefined'; - privateEnv.SSR = JSON.stringify(true); - privateEnv.BASE_URL = astroConfig.base ? `'${astroConfig.base}'` : undefined; - const entries = Object.entries(privateEnv).map(([key, value]) => [ - `import.meta.env.${key}`, - value, - ]); - replacements = Object.fromEntries(entries); - // These additional replacements are needed to match Vite - replacements = Object.assign(replacements, { - 'import.meta.env.SITE': astroConfig.site ? `'${astroConfig.site}'` : 'undefined', - 'import.meta.env.SSR': JSON.stringify(true), - 'import.meta.env.BASE_URL': astroConfig.base ? `'${astroConfig.base}'` : undefined, - // This catches destructed `import.meta.env` calls, - // BUT we only want to inject private keys referenced in the file. - // We overwrite this value on a per-file basis. - 'import.meta.env': `({})`, - }); - pattern = new RegExp( - // Do not allow preceding '.', but do allow preceding '...' for spread operations - '(? { - return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); - }) - .join('|') + - // prevent trailing assignments - ')\\b(?!\\s*?=[^=])', - 'g' - ); - } + privateEnv = getPrivateEnv(config, astroConfig) || {}; + privateEnv.SITE = astroConfig.site ? `'${astroConfig.site}'` : 'undefined'; + privateEnv.SSR = JSON.stringify(true); + privateEnv.BASE_URL = astroConfig.base ? `'${astroConfig.base}'` : undefined; } - if (!privateEnv || !pattern) return; - const references = getReferencedPrivateKeys(source, privateEnv); - if (references.size === 0) return; + pattern ??= new RegExp( + // Do not allow preceding '.', but do allow preceding '...' for spread operations + '(?; // Find matches for *private* env and do our own replacement. const s = new MagicString(source); @@ -120,14 +102,17 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug while ((match = pattern.exec(source))) { const start = match.index; const end = start + match[0].length; - let replacement = '' + replacements[match[1]]; + let replacement: string; // If we match exactly `import.meta.env`, define _only_ referenced private variables if (match[0] === 'import.meta.env') { + references ??= getReferencedPrivateKeys(source, privateEnv); replacement = `(Object.assign(import.meta.env,{`; for (const key of references.values()) { replacement += `${key}:${privateEnv[key]},`; } replacement += '}))'; + } else { + replacement = privateEnv[match[2]] ?? astroConfig.build.envKey(match[2]); } s.overwrite(start, end, replacement); } From 785f94606d512cf7ea6cd941de5376cb7ea77eaf Mon Sep 17 00:00:00 2001 From: bluwy Date: Wed, 2 Nov 2022 20:50:20 +0800 Subject: [PATCH 02/19] wip: env 2 --- packages/astro/src/vite-plugin-env/index.ts | 75 +++++++++++---------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 5f20c0e27af6..e549e017e66e 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -8,35 +8,26 @@ interface EnvPluginOptions { settings: AstroSettings; } -function getPrivateEnv(viteConfig: vite.ResolvedConfig, astroConfig: AstroConfig) { - let envPrefixes: string[] = ['PUBLIC_']; - if (viteConfig.envPrefix) { - envPrefixes = Array.isArray(viteConfig.envPrefix) - ? viteConfig.envPrefix - : [viteConfig.envPrefix]; - } +function getPrivateEnv( + viteConfig: vite.ResolvedConfig, + astroConfig: AstroConfig, + isPublicEnv: (str: string) => boolean +) { const fullEnv = loadEnv( viteConfig.mode, viteConfig.envDir ?? fileURLToPath(astroConfig.root), '' ); - const privateKeys = Object.keys(fullEnv).filter((key) => { - // don't inject `PUBLIC_` variables, Vite handles that for us - for (const envPrefix of envPrefixes) { - if (key.startsWith(envPrefix)) return false; + const privateEnv: Record = {}; + for (const key in fullEnv) { + if (!isPublicEnv(key)) { + privateEnv[key] = JSON.stringify(process.env[key] ?? fullEnv[key]); } - - // Otherwise, this is a private variable defined in an `.env` file - return true; - }); - if (privateKeys.length === 0) { - return null; } - return Object.fromEntries( - privateKeys.map((key) => { - return [key, JSON.stringify(process.env[key] ?? fullEnv[key])]; - }) - ); + privateEnv.SITE = astroConfig.site ? `'${astroConfig.site}'` : 'undefined'; + privateEnv.SSR = JSON.stringify(true); + privateEnv.BASE_URL = astroConfig.base ? `'${astroConfig.base}'` : 'undefined'; + return privateEnv; } function getReferencedPrivateKeys(source: string, privateEnv: Record): Set { @@ -52,13 +43,20 @@ function getReferencedPrivateKeys(source: string, privateEnv: Record; let config: vite.ResolvedConfig; - let pattern: RegExp | undefined; + let isPublicEnv: (str: string) => boolean; const { config: astroConfig } = settings; return { name: 'astro:vite-plugin-env', enforce: 'pre', configResolved(resolvedConfig) { config = resolvedConfig; + let envPrefixes: string[] = ['PUBLIC_']; + if (resolvedConfig.envPrefix) { + envPrefixes = Array.isArray(resolvedConfig.envPrefix) + ? resolvedConfig.envPrefix + : [resolvedConfig.envPrefix]; + } + isPublicEnv = (str: string) => envPrefixes.some((prefix) => str.startsWith(prefix)); }, async transform(source, id, options) { const ssr = options?.ssr === true; @@ -72,13 +70,12 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug } if (typeof privateEnv === 'undefined') { - privateEnv = getPrivateEnv(config, astroConfig) || {}; - privateEnv.SITE = astroConfig.site ? `'${astroConfig.site}'` : 'undefined'; - privateEnv.SSR = JSON.stringify(true); - privateEnv.BASE_URL = astroConfig.base ? `'${astroConfig.base}'` : undefined; + privateEnv = getPrivateEnv(config, astroConfig, isPublicEnv); } - pattern ??= new RegExp( + // Find matches for *private* env and do our own replacement. + const s = new MagicString(source); + const pattern = new RegExp( // Do not allow preceding '.', but do allow preceding '...' for spread operations '(?; - - // Find matches for *private* env and do our own replacement. - const s = new MagicString(source); let match: RegExpExecArray | null; while ((match = pattern.exec(source))) { - const start = match.index; - const end = start + match[0].length; - let replacement: string; + let replacement: string | undefined; // If we match exactly `import.meta.env`, define _only_ referenced private variables if (match[0] === 'import.meta.env') { + privateEnv ??= getPrivateEnv(config, astroConfig, isPublicEnv); references ??= getReferencedPrivateKeys(source, privateEnv); replacement = `(Object.assign(import.meta.env,{`; for (const key of references.values()) { replacement += `${key}:${privateEnv[key]},`; } replacement += '}))'; - } else { + } + // If we match `import.meta.emv.*`, make sure this isn't referecing a public env. + // For private env, we replace with the value from the `.env` file, or otherwise + // convert to runtime resolve with `envKey`, e.g. `process.env.*`. + else if (match[2] && !isPublicEnv(match[2])) { + privateEnv ??= getPrivateEnv(config, astroConfig, isPublicEnv); replacement = privateEnv[match[2]] ?? astroConfig.build.envKey(match[2]); } - s.overwrite(start, end, replacement); + if (replacement) { + const start = match.index; + const end = start + match[0].length; + s.overwrite(start, end, replacement); + } } return { From b1e95e142b614f34e7691e0f6409151d79e353f2 Mon Sep 17 00:00:00 2001 From: bluwy Date: Thu, 3 Nov 2022 23:25:15 +0800 Subject: [PATCH 03/19] Simplify implementation --- packages/astro/src/vite-plugin-env/index.ts | 79 ++++++++++----------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index e549e017e66e..0096b4f20d04 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -10,18 +10,32 @@ interface EnvPluginOptions { function getPrivateEnv( viteConfig: vite.ResolvedConfig, - astroConfig: AstroConfig, - isPublicEnv: (str: string) => boolean -) { + astroConfig: AstroConfig +): Record { + let envPrefixes: string[] = ['PUBLIC_']; + if (viteConfig.envPrefix) { + envPrefixes = Array.isArray(viteConfig.envPrefix) + ? viteConfig.envPrefix + : [viteConfig.envPrefix]; + } + + // Loads environment variables from `.env` files and `process.env` const fullEnv = loadEnv( viteConfig.mode, viteConfig.envDir ?? fileURLToPath(astroConfig.root), '' ); + const privateEnv: Record = {}; for (const key in fullEnv) { - if (!isPublicEnv(key)) { - privateEnv[key] = JSON.stringify(process.env[key] ?? fullEnv[key]); + // Ignore public env var + if (envPrefixes.every((prefix) => !key.startsWith(prefix))) { + if (typeof process.env[key] !== 'undefined') { + // If value is from `process.env`, convert to runtime value, e.g. `process.env.FOO` + privateEnv[key] = astroConfig.build.envKey(fullEnv[key]); + } else { + privateEnv[key] = JSON.stringify(fullEnv[key]); + } } } privateEnv.SITE = astroConfig.site ? `'${astroConfig.site}'` : 'undefined'; @@ -32,7 +46,7 @@ function getPrivateEnv( function getReferencedPrivateKeys(source: string, privateEnv: Record): Set { const references = new Set(); - for (const key of Object.keys(privateEnv)) { + for (const key in privateEnv) { if (source.includes(key)) { references.add(key); } @@ -41,44 +55,26 @@ function getReferencedPrivateKeys(source: string, privateEnv: Record; - let config: vite.ResolvedConfig; - let isPublicEnv: (str: string) => boolean; + let privateEnv: Record; + let viteConfig: vite.ResolvedConfig; const { config: astroConfig } = settings; return { name: 'astro:vite-plugin-env', enforce: 'pre', configResolved(resolvedConfig) { - config = resolvedConfig; - let envPrefixes: string[] = ['PUBLIC_']; - if (resolvedConfig.envPrefix) { - envPrefixes = Array.isArray(resolvedConfig.envPrefix) - ? resolvedConfig.envPrefix - : [resolvedConfig.envPrefix]; - } - isPublicEnv = (str: string) => envPrefixes.some((prefix) => str.startsWith(prefix)); + viteConfig = resolvedConfig; }, async transform(source, id, options) { - const ssr = options?.ssr === true; - - if (!ssr) { + if (!options?.ssr || !source.includes('import.meta.env')) { return; } - if (!source.includes('import.meta') || !/\benv\b/.test(source)) { - return; - } - - if (typeof privateEnv === 'undefined') { - privateEnv = getPrivateEnv(config, astroConfig, isPublicEnv); - } - // Find matches for *private* env and do our own replacement. - const s = new MagicString(source); + let s: MagicString | undefined; const pattern = new RegExp( // Do not allow preceding '.', but do allow preceding '...' for spread operations '(? Date: Fri, 4 Nov 2022 01:44:55 +0800 Subject: [PATCH 04/19] Fix cloudflare process.env shim --- .../cloudflare/src/server.advanced.ts | 4 ++++ .../cloudflare/src/server.directory.ts | 4 ++++ packages/integrations/cloudflare/src/util.ts | 15 +++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 packages/integrations/cloudflare/src/util.ts diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index 502700e0be97..a3f4738464cb 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -2,6 +2,7 @@ import './shim.js'; import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; +import { getProcessEnvProxy } from './util.js'; type Env = { ASSETS: { fetch: (req: Request) => Promise }; @@ -9,9 +10,12 @@ type Env = { }; export function createExports(manifest: SSRManifest) { + process.env = getProcessEnvProxy(); const app = new App(manifest, false); const fetch = async (request: Request, env: Env, context: any) => { + process.env = env as any; + const { origin, pathname } = new URL(request.url); // static assets diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index d31e2189fde6..08502d99b431 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -2,8 +2,10 @@ import './shim.js'; import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; +import { getProcessEnvProxy } from './util.js'; export function createExports(manifest: SSRManifest) { + process.env = getProcessEnvProxy(); const app = new App(manifest, false); const onRequest = async ({ @@ -14,6 +16,8 @@ export function createExports(manifest: SSRManifest) { request: Request; next: (request: Request) => void; } & Record) => { + process.env = runtimeEnv.env as any; + const { origin, pathname } = new URL(request.url); // static assets if (manifest.assets.has(pathname)) { diff --git a/packages/integrations/cloudflare/src/util.ts b/packages/integrations/cloudflare/src/util.ts new file mode 100644 index 000000000000..0137fa93fee2 --- /dev/null +++ b/packages/integrations/cloudflare/src/util.ts @@ -0,0 +1,15 @@ +export function getProcessEnvProxy() { + return new Proxy( + {}, + { + get: (target, prop) => { + console.warn( + `Unable to access \`import.meta.env.${prop.toString()}\` on initialization ` + + `as the Cloudflare platform only provides the environment variables per request. ` + + `Please move the environment variable access inside a function ` + + `that's only called after a request has been received.` + ); + }, + } + ); +} From b64bd3a5ef080a54e23a762b89c03f957828a412 Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 4 Nov 2022 15:57:54 +0800 Subject: [PATCH 05/19] Remove envKey --- packages/astro/src/core/config/schema.ts | 12 ------------ packages/astro/src/vite-plugin-env/index.ts | 3 +-- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts index cce0e4769893..f9cddbf40623 100644 --- a/packages/astro/src/core/config/schema.ts +++ b/packages/astro/src/core/config/schema.ts @@ -113,12 +113,6 @@ export const AstroConfigSchema = z.object({ .default(ASTRO_CONFIG_DEFAULTS.build.server) .transform((val) => new URL(val)), serverEntry: z.string().optional().default(ASTRO_CONFIG_DEFAULTS.build.serverEntry), - envKey: z - .function() - .args(z.string()) - .returns(z.string()) - .optional() - .default(() => (key: string) => `process.env.${key}`), }) .optional() .default({}), @@ -272,12 +266,6 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: URL) { .default(ASTRO_CONFIG_DEFAULTS.build.server) .transform((val) => new URL(val, fileProtocolRoot)), serverEntry: z.string().optional().default(ASTRO_CONFIG_DEFAULTS.build.serverEntry), - envKey: z - .function() - .args(z.string()) - .returns(z.string()) - .optional() - .default(() => (key: string) => `process.env.${key}`), }) .optional() .default({}), diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 0096b4f20d04..9f127f7cc7c9 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -31,8 +31,7 @@ function getPrivateEnv( // Ignore public env var if (envPrefixes.every((prefix) => !key.startsWith(prefix))) { if (typeof process.env[key] !== 'undefined') { - // If value is from `process.env`, convert to runtime value, e.g. `process.env.FOO` - privateEnv[key] = astroConfig.build.envKey(fullEnv[key]); + privateEnv[key] = `process.env.${key}`; } else { privateEnv[key] = JSON.stringify(fullEnv[key]); } From e7cdfe78171af4feadd9ada1bf342d074a2d456a Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 4 Nov 2022 16:53:26 +0800 Subject: [PATCH 06/19] Fix proxy order --- packages/integrations/cloudflare/src/server.advanced.ts | 3 ++- packages/integrations/cloudflare/src/server.directory.ts | 3 ++- packages/integrations/cloudflare/src/util.ts | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index a3f4738464cb..a14b98a346d6 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -4,13 +4,14 @@ import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; import { getProcessEnvProxy } from './util.js'; +process.env = getProcessEnvProxy(); + type Env = { ASSETS: { fetch: (req: Request) => Promise }; name: string; }; export function createExports(manifest: SSRManifest) { - process.env = getProcessEnvProxy(); const app = new App(manifest, false); const fetch = async (request: Request, env: Env, context: any) => { diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 08502d99b431..4f0a70da4e6d 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -4,8 +4,9 @@ import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; import { getProcessEnvProxy } from './util.js'; +process.env = getProcessEnvProxy(); + export function createExports(manifest: SSRManifest) { - process.env = getProcessEnvProxy(); const app = new App(manifest, false); const onRequest = async ({ diff --git a/packages/integrations/cloudflare/src/util.ts b/packages/integrations/cloudflare/src/util.ts index 0137fa93fee2..a19967061c52 100644 --- a/packages/integrations/cloudflare/src/util.ts +++ b/packages/integrations/cloudflare/src/util.ts @@ -4,7 +4,8 @@ export function getProcessEnvProxy() { { get: (target, prop) => { console.warn( - `Unable to access \`import.meta.env.${prop.toString()}\` on initialization ` + + `Unable to access \`import.meta` + + `.env.${prop.toString()}\` on initialization ` + `as the Cloudflare platform only provides the environment variables per request. ` + `Please move the environment variable access inside a function ` + `that's only called after a request has been received.` From d043e59f30722aa355bcfc13e5632839909a1c95 Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 4 Nov 2022 17:01:32 +0800 Subject: [PATCH 07/19] Fix netlify edge functions --- packages/integrations/netlify/src/integration-edge-functions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/netlify/src/integration-edge-functions.ts b/packages/integrations/netlify/src/integration-edge-functions.ts index f9e5f449d00a..8e16e059570f 100644 --- a/packages/integrations/netlify/src/integration-edge-functions.ts +++ b/packages/integrations/netlify/src/integration-edge-functions.ts @@ -14,7 +14,7 @@ interface BuildConfig { const SHIM = `globalThis.process = { argv: [], - env: {}, + env: Deno.env.toObject(), };`; export function getAdapter(): AstroAdapter { From c24d46b54cc23b5706c9c5052429589f713003c9 Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 4 Nov 2022 17:08:07 +0800 Subject: [PATCH 08/19] Add changeset --- .changeset/hungry-coats-mix.md | 5 +++++ .changeset/orange-melons-roll.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/hungry-coats-mix.md create mode 100644 .changeset/orange-melons-roll.md diff --git a/.changeset/hungry-coats-mix.md b/.changeset/hungry-coats-mix.md new file mode 100644 index 000000000000..afab5229ef8c --- /dev/null +++ b/.changeset/hungry-coats-mix.md @@ -0,0 +1,5 @@ +--- +'@astrojs/cloudflare': patch +--- + +Fix environment variables usage in worker output and warn if environment variables are accessedd too early diff --git a/.changeset/orange-melons-roll.md b/.changeset/orange-melons-roll.md new file mode 100644 index 000000000000..7cba7f40e0f7 --- /dev/null +++ b/.changeset/orange-melons-roll.md @@ -0,0 +1,5 @@ +--- +'@astrojs/netlify': patch +--- + +Fix environment variables usage in edge functions From 6619124f572e6afd0b9dc608e7eb475820846f04 Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 4 Nov 2022 17:09:29 +0800 Subject: [PATCH 09/19] Fix warning message --- packages/integrations/cloudflare/src/util.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/integrations/cloudflare/src/util.ts b/packages/integrations/cloudflare/src/util.ts index a19967061c52..a44780863f91 100644 --- a/packages/integrations/cloudflare/src/util.ts +++ b/packages/integrations/cloudflare/src/util.ts @@ -4,8 +4,8 @@ export function getProcessEnvProxy() { { get: (target, prop) => { console.warn( - `Unable to access \`import.meta` + - `.env.${prop.toString()}\` on initialization ` + + // NOTE: \0 prevents Vite replacement + `Unable to access \`import.meta\0.env.${prop.toString()}\` on initialization ` + `as the Cloudflare platform only provides the environment variables per request. ` + `Please move the environment variable access inside a function ` + `that's only called after a request has been received.` From 909ac48800c32fa75ab36cc89abeaff7761e9b17 Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 4 Nov 2022 17:35:23 +0800 Subject: [PATCH 10/19] Fix env regex --- packages/astro/src/vite-plugin-env/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index 9f127f7cc7c9..fdde4b59e5ee 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -74,7 +74,7 @@ export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plug // Do not allow preceding '.', but do allow preceding '...' for spread operations '(? Date: Fri, 4 Nov 2022 18:41:46 +0800 Subject: [PATCH 11/19] Add netlify edge test --- .../netlify/test/edge-functions/edge-basic.test.ts | 6 ++++++ .../edge-functions/fixtures/edge-basic/astro.config.mjs | 3 +++ .../fixtures/edge-basic/src/pages/index.astro | 1 + 3 files changed, 10 insertions(+) diff --git a/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts b/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts index 5cce36c7fb72..8283fe579bf6 100644 --- a/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts +++ b/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts @@ -3,6 +3,9 @@ import { runBuild } from './test-utils.ts'; // @ts-ignore import { assertEquals, assert, DOMParser } from './deps.ts'; +// @ts-ignore +Deno.env.set('SECRET_STUFF', 'secret'); + // @ts-ignore Deno.test({ // TODO: debug why build cannot be found in "await import" @@ -23,6 +26,9 @@ Deno.test({ const div = doc.querySelector('#react'); assert(div, 'div exists'); + const envDiv = doc.querySelector('#env'); + assertEquals(envDiv?.innerText, 'secret'); + await close(); }, }); diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs index a08e8e89d382..310088c88618 100644 --- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs +++ b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs @@ -2,6 +2,9 @@ import { defineConfig } from 'astro/config'; import { netlifyEdgeFunctions } from '@astrojs/netlify'; import react from "@astrojs/react"; +// test env var +process.env.SECRET_STUFF = 'secret' + export default defineConfig({ adapter: netlifyEdgeFunctions({ dist: new URL('./dist/', import.meta.url), diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro index 80d2eed75b60..1247ba8f6403 100644 --- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro +++ b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro @@ -10,5 +10,6 @@ import ReactComponent from '../components/React.jsx';
  • Two
  • +
    {import.meta.env.SECRET_STUFF}
    From 64b659bb15b60c354e754cdb8fa764a01a24287a Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 4 Nov 2022 21:57:58 +0800 Subject: [PATCH 12/19] Add cloudflare test --- packages/integrations/cloudflare/test/basics.test.js | 3 ++- .../cloudflare/test/fixtures/basics/astro.config.mjs | 3 +++ .../cloudflare/test/fixtures/basics/src/pages/index.astro | 1 + packages/integrations/cloudflare/test/wrangler.toml | 4 ++++ 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 packages/integrations/cloudflare/test/wrangler.toml diff --git a/packages/integrations/cloudflare/test/basics.test.js b/packages/integrations/cloudflare/test/basics.test.js index 7127a3f68430..e9cc3ba4aab0 100644 --- a/packages/integrations/cloudflare/test/basics.test.js +++ b/packages/integrations/cloudflare/test/basics.test.js @@ -2,7 +2,7 @@ import { loadFixture, runCLI } from './test-utils.js'; import { expect } from 'chai'; import * as cheerio from 'cheerio'; -describe.skip('Basic app', () => { +describe('Basic app', () => { /** @type {import('./test-utils').Fixture} */ let fixture; @@ -24,6 +24,7 @@ describe.skip('Basic app', () => { let html = await res.text(); let $ = cheerio.load(html); expect($('h1').text()).to.equal('Testing'); + expect($('#env').text()).to.equal('secret'); } finally { stop(); } diff --git a/packages/integrations/cloudflare/test/fixtures/basics/astro.config.mjs b/packages/integrations/cloudflare/test/fixtures/basics/astro.config.mjs index bf47a0a330b4..105247b1bded 100644 --- a/packages/integrations/cloudflare/test/fixtures/basics/astro.config.mjs +++ b/packages/integrations/cloudflare/test/fixtures/basics/astro.config.mjs @@ -1,6 +1,9 @@ import { defineConfig } from 'astro/config'; import cloudflare from '@astrojs/cloudflare'; +// test env var +process.env.SECRET_STUFF = 'secret' + export default defineConfig({ adapter: cloudflare(), output: 'server', diff --git a/packages/integrations/cloudflare/test/fixtures/basics/src/pages/index.astro b/packages/integrations/cloudflare/test/fixtures/basics/src/pages/index.astro index 9c077e2a381b..8d372399c923 100644 --- a/packages/integrations/cloudflare/test/fixtures/basics/src/pages/index.astro +++ b/packages/integrations/cloudflare/test/fixtures/basics/src/pages/index.astro @@ -4,5 +4,6 @@

    Testing

    +
    {import.meta.env.SECRET_STUFF}
    diff --git a/packages/integrations/cloudflare/test/wrangler.toml b/packages/integrations/cloudflare/test/wrangler.toml new file mode 100644 index 000000000000..6e2d864b0c4e --- /dev/null +++ b/packages/integrations/cloudflare/test/wrangler.toml @@ -0,0 +1,4 @@ +# for tests only + +[vars] +SECRET_STUFF = "secret" From 3976513f6079ff25de9c3fc4d50ab998e6a4a5de Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 4 Nov 2022 22:01:06 +0800 Subject: [PATCH 13/19] Add changeset --- .changeset/cold-needles-heal.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/cold-needles-heal.md diff --git a/.changeset/cold-needles-heal.md b/.changeset/cold-needles-heal.md new file mode 100644 index 000000000000..c8a8a4ef877d --- /dev/null +++ b/.changeset/cold-needles-heal.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Improve environment variable handling performance From 17869591d0f1c641d7f6c33f846dfaba9ef503c3 Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 4 Nov 2022 22:25:13 +0800 Subject: [PATCH 14/19] Skip cloudflare test like before --- packages/integrations/cloudflare/test/basics.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/cloudflare/test/basics.test.js b/packages/integrations/cloudflare/test/basics.test.js index e9cc3ba4aab0..a6229bbb249f 100644 --- a/packages/integrations/cloudflare/test/basics.test.js +++ b/packages/integrations/cloudflare/test/basics.test.js @@ -2,7 +2,7 @@ import { loadFixture, runCLI } from './test-utils.js'; import { expect } from 'chai'; import * as cheerio from 'cheerio'; -describe('Basic app', () => { +describe.skip('Basic app', () => { /** @type {import('./test-utils').Fixture} */ let fixture; From 8083f3049a4c0ce6a1956fe001f2d706c3dca64b Mon Sep 17 00:00:00 2001 From: bluwy Date: Mon, 7 Nov 2022 17:09:23 +0800 Subject: [PATCH 15/19] Update docs --- packages/integrations/cloudflare/README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/integrations/cloudflare/README.md b/packages/integrations/cloudflare/README.md index 21891c05358f..7c176d3d2e6b 100644 --- a/packages/integrations/cloudflare/README.md +++ b/packages/integrations/cloudflare/README.md @@ -92,16 +92,17 @@ To do this: ## Environment Variables -As Cloudflare Pages Functions [provides environment variables differently](https://developers.cloudflare.com/pages/platform/functions/#adding-environment-variables-locally), private environment variables needs to be set through [`vite.define`](https://vitejs.dev/config/shared-options.html#define) to work in builds. +As Cloudflare Pages Functions [provides environment variables per request](https://developers.cloudflare.com/pages/platform/functions/#adding-environment-variables-locally), private environment variables should only be accessed when a request has happened. Usually, this means moving environment variable access inside a function. ```js -// astro.config.mjs -export default { - vite: { - define: { - 'process.env.MY_SECRET': JSON.stringify(process.env.MY_SECRET), - }, - }, +// util.js + +// ❌ Do not access environment variables on initialization +const serverUrl = import.meta.env.SERVER_URL; + +export function fetchData() { + // ✅ Access inside a function instead + return fetch(import.meta.env.SERVER_URL + "/api/data"); } ``` From 9da8e8283c0aa3f02288cff935d3c51a0478d597 Mon Sep 17 00:00:00 2001 From: bluwy Date: Mon, 7 Nov 2022 17:11:43 +0800 Subject: [PATCH 16/19] Remove double shims --- packages/integrations/cloudflare/src/server.advanced.ts | 2 -- packages/integrations/cloudflare/src/server.directory.ts | 2 -- packages/integrations/cloudflare/src/shim.ts | 4 ---- 3 files changed, 8 deletions(-) delete mode 100644 packages/integrations/cloudflare/src/shim.ts diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index a14b98a346d6..e9192f945c95 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -1,5 +1,3 @@ -import './shim.js'; - import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; import { getProcessEnvProxy } from './util.js'; diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 4f0a70da4e6d..b73766ef5d57 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -1,5 +1,3 @@ -import './shim.js'; - import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; import { getProcessEnvProxy } from './util.js'; diff --git a/packages/integrations/cloudflare/src/shim.ts b/packages/integrations/cloudflare/src/shim.ts deleted file mode 100644 index 1a4a6ee9be4c..000000000000 --- a/packages/integrations/cloudflare/src/shim.ts +++ /dev/null @@ -1,4 +0,0 @@ -(globalThis as any).process = { - argv: [], - env: {}, -}; From 43303e36990d4261bda67b6bc88ed3bbb6cb6214 Mon Sep 17 00:00:00 2001 From: bluwy Date: Mon, 7 Nov 2022 23:23:03 +0800 Subject: [PATCH 17/19] Use endpoint example --- packages/integrations/cloudflare/README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/integrations/cloudflare/README.md b/packages/integrations/cloudflare/README.md index 7c176d3d2e6b..096af9a71c4a 100644 --- a/packages/integrations/cloudflare/README.md +++ b/packages/integrations/cloudflare/README.md @@ -95,14 +95,15 @@ To do this: As Cloudflare Pages Functions [provides environment variables per request](https://developers.cloudflare.com/pages/platform/functions/#adding-environment-variables-locally), private environment variables should only be accessed when a request has happened. Usually, this means moving environment variable access inside a function. ```js -// util.js - -// ❌ Do not access environment variables on initialization -const serverUrl = import.meta.env.SERVER_URL; - -export function fetchData() { - // ✅ Access inside a function instead - return fetch(import.meta.env.SERVER_URL + "/api/data"); +// pages/[id].json.js + +export function get({ params }) { + // Access environment variables inside a function + const serverUrl = import.meta.env.SERVER_URL; + const result = await fetch(serverUrl + "/user/" + params.id); + return { + body: await result.text(), + }; } ``` From 158879616d6954117b7bf53e3af8429110e9c4d2 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Tue, 8 Nov 2022 15:47:20 +0800 Subject: [PATCH 18/19] Update packages/integrations/cloudflare/README.md Co-authored-by: Sarah Rainsberger --- packages/integrations/cloudflare/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/cloudflare/README.md b/packages/integrations/cloudflare/README.md index 096af9a71c4a..4bbd214eb40d 100644 --- a/packages/integrations/cloudflare/README.md +++ b/packages/integrations/cloudflare/README.md @@ -98,7 +98,7 @@ As Cloudflare Pages Functions [provides environment variables per request](https // pages/[id].json.js export function get({ params }) { - // Access environment variables inside a function + // Access environment variables per request inside a function const serverUrl = import.meta.env.SERVER_URL; const result = await fetch(serverUrl + "/user/" + params.id); return { From 1216d9c1c5ef79ab53f53bbb8fee3b00954a1486 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Tue, 8 Nov 2022 15:52:49 +0800 Subject: [PATCH 19/19] Update packages/integrations/cloudflare/README.md --- packages/integrations/cloudflare/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/cloudflare/README.md b/packages/integrations/cloudflare/README.md index 4bbd214eb40d..0a8012b1cfbb 100644 --- a/packages/integrations/cloudflare/README.md +++ b/packages/integrations/cloudflare/README.md @@ -92,7 +92,7 @@ To do this: ## Environment Variables -As Cloudflare Pages Functions [provides environment variables per request](https://developers.cloudflare.com/pages/platform/functions/#adding-environment-variables-locally), private environment variables should only be accessed when a request has happened. Usually, this means moving environment variable access inside a function. +As Cloudflare Pages Functions [provides environment variables per request](https://developers.cloudflare.com/pages/platform/functions/#adding-environment-variables-locally), you can only access private environment variables when a request has happened. Usually, this means moving environment variable access inside a function. ```js // pages/[id].json.js