diff --git a/.dev.vars.example b/.dev.vars.example new file mode 100644 index 0000000..0c6a33d --- /dev/null +++ b/.dev.vars.example @@ -0,0 +1 @@ +GITHUB_TOKEN= \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2565be0..13f4c12 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,8 @@ node_modules # Cloudflare .wrangler -wrangler.toml +.dev.vars +worker-configuration.d.ts # Playwright /test-results diff --git a/README.md b/README.md index afd4cef..d8cb9b1 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,11 @@ What's included? ## Development -Before start, copy `wrangler.toml.example` and name it `wrangler.toml`. This -file will be used to configure the development environment and define all the -environment variables that you need for your application. +Before start, copy [.dev.vars.example](./.dev.vars.example) and name it +`.dev.vars` with the required secrets. ```sh -cp wrangler.toml.example wrangler.toml +cp .dev.vars.example .dev.vars ``` To starts the vite dev server: @@ -48,17 +47,21 @@ server with: npm run build && npm run start ``` -### New environment variable +### New environment variable & secret -To add a new environment variable, you can update the **var** section on the -[wrangler.toml](./wrangler.toml) file with the new variable: +To add a new secret, please +[update the value on **.dev.vars**](https://developers.cloudflare.com/workers/configuration/secrets/#secrets-in-development) +similar to a `.env` file. + +For the rest of the environment variable, you can update the **var** section on +the [wrangler.toml](./wrangler.toml) file with the new variable: ```toml [vars] NEW_VARIABLE = "..." ``` -The variable will be available from the `env` object in the context. +The variables will be available from the `env` object in the context. ### Setup a KV Namespace @@ -77,10 +80,14 @@ Note that the `id` has no effect on the dev environment. You can use the same name for both `id` and `binding`. The namespace will be available form the `env` object in the context. -### Improving types +### Generate env types + +You can generate the types of the `env` object based on `wrangler.toml` and +`.dev.vars` with: -You can improve the types of the `env` object by updating -[env.d.ts](./env.d.ts). +```sh +npm run typegen +``` ## Deployment diff --git a/app/root.tsx b/app/root.tsx index 0832532..f814346 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,4 +1,4 @@ -import type { MetaFunction } from '@remix-run/cloudflare'; +import type { LoaderFunctionArgs, MetaFunction } from '@remix-run/cloudflare'; import * as React from 'react'; import { Link, @@ -13,7 +13,6 @@ import { useRouteError, } from '@remix-run/react'; import '~/styles.css'; -import { metadata } from './services/github.server'; import { RemixLogo } from './components'; // We will rollback to loading CSS through links when `.css?url` is supported @@ -29,10 +28,10 @@ export const meta: MetaFunction = () => { ]; }; -export function loader() { +export function loader({ context }: LoaderFunctionArgs) { return json({ - repo: metadata.repo, - owner: metadata.owner, + repo: context.env.GITHUB_REPO, + owner: context.env.GITHUB_OWNER, description: '📜 All-in-one remix starter template for Cloudflare Pages', }); } diff --git a/app/services/github.server.ts b/app/services/github.server.ts index bd23569..803a4b1 100644 --- a/app/services/github.server.ts +++ b/app/services/github.server.ts @@ -1,11 +1,6 @@ import type { Endpoints } from '@octokit/types'; import type { AppLoadContext } from '@remix-run/cloudflare'; -export const metadata = { - repo: 'remix-cloudflare-template', - owner: 'edmundhung', -}; - export function getHeaders(auth: string | undefined) { const headers = new Headers({ Accept: 'application/vnd.github+json', @@ -64,8 +59,8 @@ export async function getFileContentWithCache( const content = await getFileContent({ auth: context.env.GITHUB_TOKEN, - owner: metadata.owner, - repo: metadata.repo, + owner: context.env.GITHUB_OWNER, + repo: context.env.GITHUB_REPO, path, }); diff --git a/env.d.ts b/env.d.ts deleted file mode 100644 index 5ec33de..0000000 --- a/env.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import 'vite/client'; -import '@remix-run/cloudflare'; -import '@cloudflare/workers-types'; - -interface Env { - ENVIRONMENT?: 'development'; - GITHUB_TOKEN?: string; - cache: KVNamespace; -} - -declare module '@remix-run/cloudflare' { - export interface AppLoadContext { - env: Env; - } -} diff --git a/functions/[[path]].ts b/functions/[[path]].ts index c95cf92..f5a851f 100644 --- a/functions/[[path]].ts +++ b/functions/[[path]].ts @@ -4,13 +4,9 @@ import { createPagesFunctionHandler } from '@remix-run/cloudflare-pages'; // @ts-ignore - the server build file is generated by `remix vite:build` // eslint-disable-next-line import/no-unresolved import * as build from '../build/server'; +import { getLoadContext } from '../load-context'; export const onRequest = createPagesFunctionHandler({ build, - getLoadContext: context => ({ - env: context.env, - waitUntil(promise: Promise) { - context.waitUntil(promise); - }, - }), + getLoadContext, }); diff --git a/load-context.ts b/load-context.ts new file mode 100644 index 0000000..0b3a9aa --- /dev/null +++ b/load-context.ts @@ -0,0 +1,31 @@ +import type { PlatformProxy } from 'wrangler'; + +// You can generate the ENV type based on `wrangler.toml` and `.dev.vars` +// by running `npm run typegen` +type Cloudflare = Omit, 'dispose'>; +type LoadContext = { + cloudflare: Cloudflare; +}; + +declare module '@remix-run/cloudflare' { + interface AppLoadContext { + env: Cloudflare['env']; + cf: Cloudflare['cf']; + ctx: Cloudflare['ctx']; + cache: Cloudflare['caches']; + } +} + +export function getLoadContext({ + context, +}: { + request: Request; + context: LoadContext; +}) { + return { + env: context.cloudflare.env, + cf: context.cloudflare.cf, + ctx: context.cloudflare.ctx, + cache: context.cloudflare.caches, + }; +} diff --git a/package.json b/package.json index 11f8d06..2ca6fe1 100644 --- a/package.json +++ b/package.json @@ -11,43 +11,44 @@ "cleanup": "rimraf .cache ./build", "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "typecheck": "tsc", + "typegen": "wrangler types", "prepare": "husky" }, "dependencies": { "@markdoc/markdoc": "^0.4.0", - "@remix-run/cloudflare": "*", - "@remix-run/cloudflare-pages": "*", - "@remix-run/react": "*", + "@remix-run/cloudflare": "^2.8.1", + "@remix-run/cloudflare-pages": "^2.8.1", + "@remix-run/react": "^2.8.1", "isbot": "^3.6.5", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20240208.0", - "@octokit/types": "^12.4.0", - "@playwright/test": "^1.41.2", - "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", + "@cloudflare/workers-types": "^4.20240222.0", + "@octokit/types": "^12.6.0", + "@playwright/test": "^1.42.1", + "@remix-run/dev": "^2.8.1", + "@remix-run/eslint-config": "^2.8.1", "@tailwindcss/typography": "^0.5.10", - "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.19", - "autoprefixer": "^10.4.17", + "@types/react": "^18.2.64", + "@types/react-dom": "^18.2.21", + "autoprefixer": "^10.4.18", "concurrently": "^8.2.2", "cross-env": "^7.0.3", - "eslint": "^8.56.0", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "husky": "^9.0.10", + "husky": "^9.0.11", "lint-staged": "^15.2.2", - "msw": "^2.1.7", + "msw": "^2.2.3", "postcss": "^8.4.35", "prettier": "^3.2.5", - "prettier-plugin-tailwindcss": "^0.5.11", + "prettier-plugin-tailwindcss": "^0.5.12", "rimraf": "^5.0.5", "tailwindcss": "^3.4.1", - "typescript": "^5.3.3", - "vite": "^5.1.1", + "typescript": "^5.4.2", + "vite": "^5.1.5", "vite-tsconfig-paths": "^4.3.1", - "wrangler": "^3.28.1" + "wrangler": "^3.32.0" }, "engines": { "node": ">=18" diff --git a/tests/playwright.ts b/tests/playwright.ts index 21899b4..b61f819 100644 --- a/tests/playwright.ts +++ b/tests/playwright.ts @@ -2,13 +2,13 @@ import { test as baseTest, expect as baseExpect } from '@playwright/test'; import type { Env } from 'env'; import { type ViteDevServer, createServer } from 'vite'; import { type SetupServer, setupServer } from 'msw/node'; -import { type BindingsProxy, getBindingsProxy } from 'wrangler'; +import { type PlatformProxy, getPlatformProxy } from 'wrangler'; interface TestFixtures {} interface WorkerFixtures { port: number; - wrangler: BindingsProxy; + wrangler: PlatformProxy; server: ViteDevServer; msw: SetupServer; } @@ -71,13 +71,13 @@ export const test = baseTest.extend({ wrangler: [ // eslint-disable-next-line no-empty-pattern async ({}, use) => { - const wrangler = await getBindingsProxy(); + const wrangler = await getPlatformProxy(); // To access bindings in the tests. await use(wrangler); // Ensure all cachees are cleaned up - await clearKV(wrangler.bindings.cache); + await clearKV(wrangler.env.cache); await wrangler.dispose(); }, diff --git a/tsconfig.json b/tsconfig.json index 77291a9..a61e663 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,15 @@ { - "include": ["env.d.ts", "**/*.ts", "**/*.tsx"], + "include": [ + "**/*.ts", + "**/*.tsx", + "**/.server/**/*.ts", + "**/.server/**/*.tsx", + "**/.client/**/*.ts", + "**/.client/**/*.tsx" + ], "compilerOptions": { "lib": ["DOM", "DOM.Iterable", "ES2022"], + "types": ["@remix-run/cloudflare", "vite/client"], "isolatedModules": true, "esModuleInterop": true, "jsx": "react-jsx", diff --git a/vite.config.ts b/vite.config.ts index c79c48f..f1923ef 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,26 +1,15 @@ import { - unstable_vitePlugin as remix, - unstable_cloudflarePreset as cloudflare, + vitePlugin as remix, + cloudflareDevProxyVitePlugin as remixCloudflareDevProxy, } from '@remix-run/dev'; import { defineConfig } from 'vite'; import tsconfigPaths from 'vite-tsconfig-paths'; +import { getLoadContext } from './load-context'; export default defineConfig({ plugins: [ - remix({ - presets: [ - cloudflare({ - getRemixDevLoadContext(context) { - return context; - }, - }), - ], - }), + remixCloudflareDevProxy({ getLoadContext }), + remix(), tsconfigPaths(), ], - ssr: { - resolve: { - externalConditions: ['workerd', 'worker'], - }, - }, }); diff --git a/wrangler.toml.example b/wrangler.toml similarity index 65% rename from wrangler.toml.example rename to wrangler.toml index 765717c..24607dd 100644 --- a/wrangler.toml.example +++ b/wrangler.toml @@ -5,4 +5,5 @@ kv_namespaces = [ ] [vars] -GITHUB_TOKEN = "" +GITHUB_OWNER = "edmundhung" +GITHUB_REPO = "remix-cloudflare-template"