Skip to content

Commit

Permalink
improves code (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderniebuhr committed Mar 27, 2024
1 parent 872f17b commit c1f07ff
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 77 deletions.
2 changes: 2 additions & 0 deletions packages/cloudflare/src/entrypoints/image-endpoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// NOTE: this file is empty on purpose
// it allows use to offer `imageService: 'compile'`
46 changes: 29 additions & 17 deletions packages/cloudflare/src/entrypoints/server.advanced.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,71 @@
import type {
Request as CFRequest,
CacheStorage,
CacheStorage as CLOUDFLARE_CACHESTORAGE,
Request as CLOUDFLARE_REQUEST,
ExecutionContext,
} from '@cloudflare/workers-types';
import type { SSRManifest } from 'astro';
import { App } from 'astro/app';
import { getProcessEnvProxy, isNode } from '../util.js';

if (!isNode) {
process.env = getProcessEnvProxy();
}

type Env = {
ASSETS: { fetch: (req: Request) => Promise<Response> };
ASSETS: { fetch: (req: Request | string) => Promise<Response> };
ASTRO_STUDIO_APP_TOKEN?: string;
};

export interface AdvancedRuntime<T extends object = object> {
runtime: {
waitUntil: (promise: Promise<any>) => void;
env: Env & T;
cf: CFRequest['cf'];
caches: CacheStorage;
cf: CLOUDFLARE_REQUEST['cf'];
caches: CLOUDFLARE_CACHESTORAGE;
};
}

export function createExports(manifest: SSRManifest) {
const app = new App(manifest);

const fetch = async (request: Request & CFRequest, env: Env, context: ExecutionContext) => {
// TODO: remove this any cast in the future
// REF: the type cast to any is needed because the Cloudflare Env Type is not assignable to type 'ProcessEnv'
process.env = env as any;

const fetch = async (
request: Request & CLOUDFLARE_REQUEST,
env: Env,
context: ExecutionContext
) => {
const { pathname } = new URL(request.url);

// static assets fallback, in case default _routes.json is not used
if (manifest.assets.has(pathname)) {
return env.ASSETS.fetch(request);
return env.ASSETS.fetch(request.url.replace(/\.html$/, ''));
}

const routeData = app.match(request);
if (!routeData) {
// https://developers.cloudflare.com/pages/functions/api-reference/#envassetsfetch
const asset = await env.ASSETS.fetch(
request.url.replace(/index.html$/, '').replace(/\.html$/, '')
);
if (asset.status !== 404) {
return asset;
}
}

Reflect.set(
request,
Symbol.for('astro.clientAddress'),
request.headers.get('cf-connecting-ip')
);

process.env.ASTRO_STUDIO_APP_TOKEN ??= (() => {
if (typeof env.ASTRO_STUDIO_APP_TOKEN === 'string') {
return env.ASTRO_STUDIO_APP_TOKEN;
}
})();

const locals: AdvancedRuntime = {
runtime: {
waitUntil: (promise: Promise<any>) => {
context.waitUntil(promise);
},
env: env,
cf: request.cf,
caches: caches as unknown as CacheStorage,
caches: caches as unknown as CLOUDFLARE_CACHESTORAGE,
},
};

Expand Down
21 changes: 0 additions & 21 deletions packages/cloudflare/src/getAdapter.ts

This file was deleted.

54 changes: 33 additions & 21 deletions packages/cloudflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import { createRedirectsFromAstroRoutes } from '@astrojs/underscore-redirects';
import { AstroError } from 'astro/errors';
import glob from 'tiny-glob';
import { getPlatformProxy } from 'wrangler';
import { getAdapter } from './getAdapter.js';
import { deduplicatePatterns } from './utils/deduplicatePatterns.js';
import { prepareImageConfig } from './utils/image-config.js';
import { setImageConfig } from './utils/image-config.js';
import { prependForwardSlash } from './utils/prependForwardSlash.js';
import { wasmModuleLoader } from './utils/wasm-module-loader.js';

export type { AdvancedRuntime } from './entrypoints/server.advanced.js';

export type Options = {
/** Options for handling images. */
imageService?: 'passthrough' | 'cloudflare' | 'compile';
routes?: {
/**
Expand Down Expand Up @@ -44,28 +44,20 @@ export type Options = {
/** Configuration persistence settings. Default '.wrangler/state/v3' */
persist?: boolean | { path: string };
};
/** Enable WebAssembly support */
wasmModuleImports?: boolean;
};

interface BuildConfig {
server: URL;
client: URL;
assets: string;
serverEntry: string;
split?: boolean;
}

export default function createIntegration(args?: Options): AstroIntegration {
let _config: AstroConfig;
let _buildConfig: BuildConfig;

return {
name: '@astrojs/cloudflare',
hooks: {
'astro:config:setup': ({ command, config, updateConfig, logger }) => {
updateConfig({
build: {
client: new URL(`.${config.base}`, config.outDir),
client: new URL(`.${config.base}/`, config.outDir),
server: new URL('./_worker.js/', config.outDir),
serverEntry: 'index.js',
redirects: false,
Expand All @@ -78,19 +70,38 @@ export default function createIntegration(args?: Options): AstroIntegration {
}),
],
},
image: prepareImageConfig(args?.imageService ?? 'DEFAULT', config.image, command, logger),
image: setImageConfig(args?.imageService ?? 'DEFAULT', config.image, command, logger),
});
},
'astro:config:done': ({ setAdapter, config }) => {
setAdapter(getAdapter());
_config = config;
_buildConfig = config.build;

if (_config.output === 'static') {
if (config.output === 'static') {
throw new AstroError(
'[@astrojs/cloudflare] `output: "server"` or `output: "hybrid"` is required to use this adapter. Otherwise, this adapter is not necessary to deploy a static site to Cloudflare.'
);
}

setAdapter({
name: '@astrojs/cloudflare',
serverEntrypoint: '@astrojs/cloudflare/entrypoints/server.advanced.js',
exports: ['default'],
adapterFeatures: {
functionPerRoute: false,
edgeMiddleware: false,
},
supportedAstroFeatures: {
serverOutput: 'stable',
hybridOutput: 'stable',
staticOutput: 'unsupported',
i18nDomains: 'experimental',
assets: {
supportKind: 'stable',
isSharpCompatible: false,
isSquooshCompatible: false,
},
},
});
},
'astro:server:setup': async ({ server, logger }) => {
if (args?.platformProxy?.enabled === true) {
Expand Down Expand Up @@ -146,15 +157,16 @@ export default function createIntegration(args?: Options): AstroIntegration {
vite.ssr ||= {};
vite.ssr.target = 'webworker';
vite.ssr.noExternal = true;
vite.ssr.external = _config.vite?.ssr?.external ?? [];
vite.ssr.external = _config.vite.ssr?.external ?? [];

vite.build ||= {};
vite.build.rollupOptions ||= {};
vite.build.rollupOptions.output ||= {};
// @ts-expect-error
vite.build.rollupOptions.output.banner ||= 'globalThis.process ??= {};';
vite.build.rollupOptions.output.banner ||=
'globalThis.process ??= {}; globalThis.process.env ??= {};';

vite.build.rollupOptions.external = _config.vite?.build?.rollupOptions?.external ?? [];
vite.build.rollupOptions.external = _config.vite.build?.rollupOptions?.external ?? [];

// Cloudflare env is only available per request. This isn't feasible for code that access env vars
// in a global way, so we shim their access as `process.env.*`. This is not the recommended way for users to access environment variables. But we'll add this for compatibility for chosen variables. Mainly to support `@astrojs/db`
Expand All @@ -172,7 +184,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
for (const file of cloudflareSpecialFiles) {
try {
await fs.promises.rename(
new URL(file, _buildConfig.client),
new URL(file, _config.build.client),
new URL(file, _config.outDir)
);
} catch (e) {
Expand Down Expand Up @@ -219,7 +231,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
});

const staticPathList: Array<string> = (
await glob(`${fileURLToPath(_buildConfig.client)}/**/*`, {
await glob(`${fileURLToPath(_config.build.client)}/**/*`, {
cwd: fileURLToPath(_config.outDir),
filesOnly: true,
dot: true,
Expand Down
16 changes: 0 additions & 16 deletions packages/cloudflare/src/util.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/cloudflare/src/utils/image-config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { AstroConfig, AstroIntegrationLogger } from 'astro';
import { passthroughImageService, sharpImageService } from 'astro/config';

export function prepareImageConfig(
export function setImageConfig(
service: string,
config: AstroConfig['image'],
command: 'dev' | 'build' | 'preview',
Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/test/fixtures/wasm/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ export default defineConfig({
adapter: cloudflare({
wasmModuleImports: true
}),
output: 'server'
output: 'hybrid'
});

0 comments on commit c1f07ff

Please sign in to comment.