Skip to content
This repository has been archived by the owner on Feb 10, 2025. It is now read-only.

feat(cloudflare): support astro:env #258

Merged
merged 36 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7042e2a
test out astro env
alexanderniebuhr May 8, 2024
3ac9331
chore: remove .astro
florian-lefebvre May 12, 2024
4537fd7
chore: update gitignore
florian-lefebvre May 12, 2024
efe335e
fix: typings
florian-lefebvre May 12, 2024
9d6ffc4
fix: getEnv logic
florian-lefebvre May 12, 2024
042a551
chore: format
florian-lefebvre May 12, 2024
2158ed3
feat: update to latest
florian-lefebvre May 14, 2024
57bff32
fix: getSecret
florian-lefebvre May 15, 2024
75c6603
feat: inlined system vars
florian-lefebvre May 15, 2024
cca92af
feat: update to use overrideProcessEnv
florian-lefebvre May 16, 2024
efeee02
update test script
alexanderniebuhr May 16, 2024
6992f09
reenable plugin
alexanderniebuhr May 16, 2024
2ca7caa
feat: update to latest astro env release
florian-lefebvre May 22, 2024
fc35175
Merge branch 'main' into astro_env
florian-lefebvre May 22, 2024
cb276e7
fix: vite version
florian-lefebvre May 22, 2024
f77aa41
chore: format
florian-lefebvre May 22, 2024
4aa1336
fix: astro:env/setup errors
florian-lefebvre May 22, 2024
282a1cd
feat: cleanup
florian-lefebvre Jun 6, 2024
a7e1170
chore: do not update netlify
florian-lefebvre Jun 6, 2024
b0b3ea1
chore: add changeset
florian-lefebvre Jun 6, 2024
5518e66
Cleanup
alexanderniebuhr Jun 7, 2024
b91be12
Fix types
alexanderniebuhr Jun 7, 2024
947ae3b
Format
alexanderniebuhr Jun 7, 2024
8dac283
Fix tests
alexanderniebuhr Jun 7, 2024
9bbc516
Disable getSecret
alexanderniebuhr Jun 7, 2024
2dd31e8
feat: update
florian-lefebvre Jun 8, 2024
866ae34
chore: update deps
florian-lefebvre Jun 8, 2024
7f6fc0c
Merge branch 'main' into astro_env
florian-lefebvre Jun 8, 2024
f740704
fix: lint
florian-lefebvre Jun 8, 2024
6b365ef
fix: formatting
florian-lefebvre Jun 8, 2024
c32ad2d
Update purple-trainers-drive.md
florian-lefebvre Jun 10, 2024
33f271f
Update packages/cloudflare/src/utils/non-server-chunk-detector.ts
florian-lefebvre Jun 10, 2024
ff22bfb
Update purple-trainers-drive.md
florian-lefebvre Jun 10, 2024
fc6ae9c
Merge branch 'main' into astro_env
florian-lefebvre Jun 10, 2024
e92254a
chore: update tests
florian-lefebvre Jun 10, 2024
3d9a480
Revert "chore: update tests"
florian-lefebvre Jun 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/purple-trainers-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/cloudflare': minor
---

Adds support for `astro:env` released under an experimental flag in Astro 4.10
1 change: 1 addition & 0 deletions packages/cloudflare/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
functions
.mf
.wrangler
.astro
4 changes: 2 additions & 2 deletions packages/cloudflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@
},
"devDependencies": {
"@astrojs/test-utils": "workspace:*",
"astro": "^4.5.8",
"astro": "^4.10.1",
"astro-scripts": "workspace:*",
"cheerio": "1.0.0-rc.12",
"execa": "^8.0.1",
"fast-glob": "^3.3.2",
"rollup": "^4.14.0",
"strip-ansi": "^7.1.0",
"vite": "^5.2.6"
"vite": "^5.2.12"
},
"publishConfig": {
"provenance": true
Expand Down
5 changes: 5 additions & 0 deletions packages/cloudflare/src/entrypoints/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import type {
} from '@cloudflare/workers-types';
import type { SSRManifest } from 'astro';
import { App } from 'astro/app';
import { createGetEnv } from '../utils/env.js';

type Env = {
[key: string]: unknown;
ASSETS: { fetch: (req: Request | string) => Promise<Response> };
ASTRO_STUDIO_APP_TOKEN?: string;
};
Expand Down Expand Up @@ -69,6 +71,9 @@ export function createExports(manifest: SSRManifest) {
},
},
};
// Won't throw if the virtual module is not available because it's not supported in
// the users's astro version or if astro:env is not enabled in the project
await import('astro/env/setup').then((mod) => mod.setGetEnv(createGetEnv(env))).catch(() => {});

const response = await app.render(request, { routeData, locals });

Expand Down
13 changes: 13 additions & 0 deletions packages/cloudflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
type CloudflareModulePluginExtra,
cloudflareModuleLoader,
} from './utils/cloudflare-module-loader.js';
import { createGetEnv } from './utils/env.js';
import { createRoutesFile, getParts } from './utils/generate-routes-json.js';
import { setImageConfig } from './utils/image-config.js';
import { mutateDynamicPageImportsInPlace, mutatePageMapInPlace } from './utils/index.js';
Expand Down Expand Up @@ -191,6 +192,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
isSharpCompatible: false,
isSquooshCompatible: false,
},
envGetSecret: 'experimental',
},
});
},
Expand All @@ -202,6 +204,17 @@ export default function createIntegration(args?: Options): AstroIntegration {
persist: args.platformProxy.persist ?? true,
});

const getEnv = createGetEnv(platformProxy.env);

if (_config.experimental.env?.schema) {
for (const key of Object.keys(_config.experimental.env.schema)) {
const value = getEnv(key);
if (value !== undefined) {
process.env[key] = value;
}
}
}

const clientLocalsSymbol = Symbol.for('astro.locals');

server.middlewares.use(async function middleware(req, res, next) {
Expand Down
15 changes: 15 additions & 0 deletions packages/cloudflare/src/utils/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { GetEnv } from 'astro/env/setup';

export const createGetEnv =
(env: Record<string, unknown>): GetEnv =>
(key) => {
const v = env[key];
if (typeof v === 'undefined' || typeof v === 'string') {
return v;
}
if (typeof v === 'boolean' || typeof v === 'number') {
// let astro:env handle the validation and transformation
return v.toString();
}
return undefined;
};
4 changes: 2 additions & 2 deletions packages/cloudflare/src/utils/non-server-chunk-detector.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { OutputBundle } from 'rollup';
import type { Plugin } from 'vite';
import type { Plugin, PluginOption } from 'vite';

/**
* A Vite bundle analyzer that identifies chunks that are not used for server rendering.
Expand All @@ -11,7 +11,7 @@ import type { Plugin } from 'vite';
export class NonServerChunkDetector {
private nonServerChunks?: string[];

public getPlugin(): Plugin {
public getPlugin(): PluginOption {
return {
name: 'non-server-chunk-detector',
generateBundle: (_, bundle) => {
Expand Down
65 changes: 65 additions & 0 deletions packages/cloudflare/test/astro-env.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as assert from 'node:assert/strict';
import { after, before, describe, it } from 'node:test';
import { fileURLToPath } from 'node:url';
import * as cheerio from 'cheerio';
import { astroCli, wranglerCli } from './_test-utils.js';

const root = new URL('./fixtures/astro-env/', import.meta.url);

describe('AstroEnv', () => {
let wrangler;

before(async () => {
process.env.PUBLIC_API_URL = 'https://google.de';
process.env.PUBLIC_PORT = '4322';
await astroCli(fileURLToPath(root), 'build');

wrangler = wranglerCli(fileURLToPath(root));
await new Promise((resolve) => {
wrangler.stdout.on('data', (data) => {
// console.log('[stdout]', data.toString());
if (data.toString().includes('http://127.0.0.1:8788')) resolve();
});
wrangler.stderr.on('data', (data) => {
// console.log('[stderr]', data.toString());
});
});
});

after((done) => {
wrangler.kill();
});

it('runtime', async () => {
const res = await fetch('http://127.0.0.1:8788/');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal(
$('#runtime').text().includes('https://google.de') &&
$('#runtime').text().includes('4322') &&
$('#runtime').text().includes('123456789'),
true
);
});

it('client', async () => {
const res = await fetch('http://127.0.0.1:8788/');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('#client').text().includes('https://google.de'), true);
});

it('server', async () => {
const res = await fetch('http://127.0.0.1:8788/');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('#server').text().includes('4322'), true);
});

it('secret', async () => {
const res = await fetch('http://127.0.0.1:8788/');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('#secret').text().includes('123456789'), true);
});
});
1 change: 1 addition & 0 deletions packages/cloudflare/test/fixtures/astro-env/.dev.vars
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
API_SECRET=123456789
21 changes: 21 additions & 0 deletions packages/cloudflare/test/fixtures/astro-env/astro.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import cloudflare from '@astrojs/cloudflare';
import { defineConfig, envField } from 'astro/config';

export default defineConfig({
experimental: {
rewriting: false,
env: {
schema: {
PUBLIC_API_URL: envField.string({ context: 'client', access: 'public', optional: true }),
PUBLIC_PORT: envField.number({ context: 'server', access: 'public', default: 4321 }),
// API_SECRET: envField.string({ context: 'server', access: 'secret' }),
},
},
},
adapter: cloudflare({
platformProxy: {
enabled: true,
},
}),
output: 'server',
});
12 changes: 12 additions & 0 deletions packages/cloudflare/test/fixtures/astro-env/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "@test/astro-cloudflare-astro-env",
"version": "0.0.0",
"private": true,
"dependencies": {
"@astrojs/cloudflare": "workspace:*",
"astro": "^4.10.1"
},
"devDependencies": {
"wrangler": "^3.15.0"
}
}
12 changes: 12 additions & 0 deletions packages/cloudflare/test/fixtures/astro-env/src/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/// <reference path="../.astro/env.d.ts" />
/// <reference types="astro/client" />

type Runtime = import('@astrojs/cloudflare').Runtime;

declare namespace App {
interface Locals extends Runtime {
otherLocals: {
test: string;
};
}
}
27 changes: 27 additions & 0 deletions packages/cloudflare/test/fixtures/astro-env/src/pages/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
import { PUBLIC_API_URL } from "astro:env/client"
import { PUBLIC_PORT, getSecret } from "astro:env/server"

const runtime = Astro.locals.runtime;
---
<html>
<head>
<title>Astro Env</title>
</head>
<body>
<h1>Astro Env</h1>
<pre id="runtime">{JSON.stringify(runtime.env, null, 2)}</pre>
<div>
<span>PUBLIC_API_URL</span>
<span id="client">{PUBLIC_API_URL}</span>
</div>
<div>
<span>PUBLIC_PORT</span>
<span id="server">{PUBLIC_PORT}</span>
</div>
<div>
<span>getSecret</span>
<span id="secret">{getSecret("API_SECRET")}</span>
</div>
</body>
</html>
3 changes: 3 additions & 0 deletions packages/cloudflare/test/fixtures/astro-env/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "astro/tsconfigs/strict"
}
5 changes: 5 additions & 0 deletions packages/cloudflare/test/fixtures/astro-env/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name = "astro-env"

[vars]
PUBLIC_API_URL = "https://google.de"
PUBLIC_PORT = 4322
1 change: 0 additions & 1 deletion packages/netlify/src/types.d.ts

This file was deleted.

12 changes: 0 additions & 12 deletions packages/test-utils/test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import fastGlob from 'fast-glob';
import stripAnsi from 'strip-ansi';
import { check } from './node_modules/astro/dist/cli/check/index.js';
import build from './node_modules/astro/dist/core/build/index.js';
import { RESOLVED_SPLIT_MODULE_ID } from './node_modules/astro/dist/core/build/plugins/plugin-ssr.js';
import { getVirtualModulePageNameFromPath } from './node_modules/astro/dist/core/build/plugins/util.js';
import { makeSplitEntryPointFileName } from './node_modules/astro/dist/core/build/static-build.js';
import { mergeConfig, resolveConfig } from './node_modules/astro/dist/core/config/index.js';
import { dev, preview } from './node_modules/astro/dist/core/index.js';
import { nodeLogDestination } from './node_modules/astro/dist/core/logger/node.js';
Expand Down Expand Up @@ -213,15 +210,6 @@ export async function loadFixture(inlineConfig) {
app.manifest = manifest;
return app;
},
loadEntryPoint: async (pagePath, routes, streaming) => {
const virtualModule = getVirtualModulePageNameFromPath(RESOLVED_SPLIT_MODULE_ID, pagePath);
const filePath = makeSplitEntryPointFileName(virtualModule, routes);
const url = new URL(`./server/${filePath}?id=${fixtureId}`, config.outDir);
const { createApp, manifest } = await import(url);
const app = createApp(streaming);
app.manifest = manifest;
return app;
},
editFile: async (filePath, newContentsOrCallback) => {
const fileUrl = new URL(filePath.replace(/^\//, ''), config.root);
const contents = await fs.promises.readFile(fileUrl, 'utf-8');
Expand Down
Loading
Loading