Skip to content

Commit

Permalink
feat: added sourcemap support (remix-run#242)
Browse files Browse the repository at this point in the history
feat: added sourcemap support
feat!: remix-node has been renamed remix-server. remix-node has been repurposed to house the abstractions of the node runtime.
feat!: added abstraction for runtimes (remix-run#244)
feat!: moved fileStorage session to remix-node this removes the last node specific platform modules from remix-server-runtime
feat: added cloudflare worker handler (untested)
feat: moved to webcrypto instead of "crypto" to support more platforms
feat!: updated .npmrc to minimum required version for webcrypto API
feat: Use node-fetch types in node adapters
feat: abstracted req and res types through the platform
feat: Add base64 encoding primitives to node globals

Co-authored-by: Michael Jackson <[email protected]>
  • Loading branch information
jacob-ebey and mjackson authored Aug 18, 2021
1 parent 841b5f8 commit a8bcc1f
Show file tree
Hide file tree
Showing 71 changed files with 1,297 additions and 645 deletions.
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
14
15
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

- CLI no longer crashes on syntax errors and reports errors with location
- Dynamic imports no longer blows up build
- Renamed @remix-run/node to @remix-run/server-runtime and abstracted node specific functionality back to the repurposed @remix-run/node
- Moved fileStorage session to remix-node this removes the last node specific platform modules from remix-server-runtime as far as I'm aware
- Made cookie parse and serialize methods async to support web crypto API
- Moved to webcrypto instead of "crypto" to support more platforms
- Updated .npmrc to minimum required version for webcrypto API (v15)
- Abstracted req and res types through the platform
- Add base64 encoding primitives to node globals (atob and btoa)

This is a history of changes to [Remix](https://remix.run).

Expand Down
18 changes: 9 additions & 9 deletions docs/api/remix.md
Original file line number Diff line number Diff line change
Expand Up @@ -557,14 +557,14 @@ import { useRouteData, json, redirect } from "remix";

import { userPrefs as cookie } from "../cookies";

export function loader({ request }) {
let value = cookie.parse(request.headers.get("Cookie")) || {};
export async function loader({ request }) {
let value = await cookie.parse(request.headers.get("Cookie")) || {};
let showBanner = "showBanner" in value ? value.showBanner : true;
return { showBanner };
}

export async function action({ request }) {
let value = cookie.parse(request.headers.get("Cookie")) || {};
let value = await cookie.parse(request.headers.get("Cookie")) || {};
let bodyParams = new URLSearchParams(await request.text());

if (bodyParams.get("bannerVisibility") === "hidden") {
Expand All @@ -573,7 +573,7 @@ export async function action({ request }) {

return redirect("/", {
headers: {
"Set-Cookie": cookie.serialize(value)
"Set-Cookie": await cookie.serialize(value)
}
});
}
Expand Down Expand Up @@ -649,15 +649,15 @@ let cookie = createCookie("user-prefs", {
});
// in your route module...
export function loader({ request }) {
export async function loader({ request }) {
let oldCookie = request.headers.get("Cookie");
// oldCookie may have been signed with "olds3cret", but still parses ok
let value = cookie.parse(oldCookie);
let value = await cookie.parse(oldCookie);
new Response("...", {
headers: {
// Set-Cookie is signed with "n3wsecr3t"
"Set-Cookie": cookie.serialize(value)
"Set-Cookie": await cookie.serialize(value)
}
});
}
Expand Down Expand Up @@ -716,7 +716,7 @@ The name of the cookie, used in `Cookie` and `Set-Cookie` HTTP headers.
Extracts and returns the value of this cookie in a given `Cookie` header.
```js
let value = cookie.parse(request.headers.get("Cookie"));
let value = await cookie.parse(request.headers.get("Cookie"));
```
### `cookie.serialize()`
Expand All @@ -726,7 +726,7 @@ Serializes a value and combines it with this cookie's options to create a `Set-C
```js
new Response("...", {
headers: {
"Set-Cookie": cookie.serialize({ showBanner: true })
"Set-Cookie": await cookie.serialize({ showBanner: true })
}
});
```
Expand Down
6 changes: 6 additions & 0 deletions fixtures/gists-app/app/routes/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export function loader() {
return null;
}

export function headers() {
return {
"test": "value"
}
}

export default function Index() {
useEffect(() => {
console.log(clientMessage);
Expand Down
3 changes: 2 additions & 1 deletion fixtures/gists-app/scripts/install_remix.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ async function run() {
await fs.ensureDir(installDir);
await fs.copy(buildDir, installDir);

// Manually run postinstall for node + react
// Manually run postinstall for node + react + server
execSync("node node_modules/@remix-run/node/scripts/postinstall.js");
execSync("node node_modules/@remix-run/react/scripts/postinstall.js");
execSync("node node_modules/@remix-run/server-runtime/scripts/postinstall.js");
}

run().then(
Expand Down
17 changes: 14 additions & 3 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,31 @@ module.exports = {
{
displayName: "express",
testEnvironment: "node",
testMatch: ["<rootDir>/packages/remix-express/**/*-test.[jt]s?(x)"]
testMatch: ["<rootDir>/packages/remix-express/**/*-test.[jt]s?(x)"],
setupFiles: ["<rootDir>/jest/setupNodeGlobals.ts"]
},
{
displayName: "node",
testEnvironment: "node",
testMatch: ["<rootDir>/packages/remix-node/**/*-test.[jt]s?(x)"]
testMatch: ["<rootDir>/packages/remix-node/**/*-test.[jt]s?(x)"],
setupFiles: ["<rootDir>/jest/setupNodeGlobals.ts"]
},
{
displayName: "server",
testEnvironment: "node",
testMatch: [
"<rootDir>/packages/remix-server-runtime/**/*-test.[jt]s?(x)"
],
setupFiles: ["<rootDir>/jest/setupNodeGlobals.ts"]
},
{
displayName: "gists-app",
testEnvironment: "node",
testMatch: ["<rootDir>/fixtures/gists-app/**/*-test.[jt]s?(x)"],
globalSetup: "<rootDir>/fixtures/gists-app/jest/global-setup.js",
globalTeardown: "<rootDir>/fixtures/gists-app/jest/global-teardown.js",
setupFilesAfterEnv: ["<rootDir>/fixtures/gists-app/jest/setup.js"]
setupFilesAfterEnv: ["<rootDir>/fixtures/gists-app/jest/setup.js"],
setupFiles: ["<rootDir>/jest/setupNodeGlobals.ts"]
}
]
};
3 changes: 3 additions & 0 deletions jest/setupNodeGlobals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { installGlobals } from "../packages/remix-node/globals";

installGlobals();
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
"packages/create-remix",
"packages/remix",
"packages/remix-architect",
"packages/remix-cloudflare-workers",
"packages/remix-dev",
"packages/remix-init",
"packages/remix-express",
"packages/remix-node",
"packages/remix-react",
"packages/remix-serve",
"packages/remix-server-runtime",
"packages/remix-vercel"
],
"dependencies": {
Expand Down
3 changes: 2 additions & 1 deletion packages/remix-architect/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"version": "0.17.5",
"repository": "https://github.com/remix-run/packages",
"dependencies": {
"@remix-run/node": "0.17.5"
"@remix-run/node": "0.17.5",
"@remix-run/server-runtime": "0.17.5"
},
"peerDependencies": {
"@architect/architect": "^8.3.7",
Expand Down
26 changes: 16 additions & 10 deletions packages/remix-architect/server.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { URL } from "url";
import type {
Request as ArcRequest,
Response as ArcResponse
} from "@architect/functions";
import type { ServerBuild, AppLoadContext } from "@remix-run/node";
import {
Request,
createRequestHandler as createRemixRequestHandler
} from "@remix-run/node";
import type {
AppLoadContext,
ServerBuild,
ServerPlatform
} from "@remix-run/server-runtime";
import { createRequestHandler as createRemixRequestHandler } from "@remix-run/server-runtime";
import type { Response as NodeResponse } from "@remix-run/node";
import { Request as NodeRequest, formatServerError } from "@remix-run/node";

/**
* A function that returns the value to use as `context` in route `loader` and
Expand Down Expand Up @@ -35,14 +37,18 @@ export function createRequestHandler({
getLoadContext: GetLoadContextFunction;
mode?: string;
}) {
let handleRequest = createRemixRequestHandler(build, mode);
let platform: ServerPlatform = { formatServerError };
let handleRequest = createRemixRequestHandler(build, platform, mode);

return async (req: ArcRequest): Promise<ArcResponse> => {
let request = createRemixRequest(req);
let loadContext =
typeof getLoadContext === "function" ? getLoadContext(req) : undefined;

let response = await handleRequest(request, loadContext);
let response = ((await handleRequest(
(request as unknown) as Request,
loadContext
)) as unknown) as NodeResponse;

return {
statusCode: response.status,
Expand All @@ -52,12 +58,12 @@ export function createRequestHandler({
};
}

function createRemixRequest(req: ArcRequest): Request {
function createRemixRequest(req: ArcRequest): NodeRequest {
let host = req.headers["x-forwarded-host"] || req.headers.host;
let search = req.rawQueryString.length ? "?" + req.rawQueryString : "";
let url = new URL(req.rawPath + search, `https://${host}`);

return new Request(url.toString(), {
return new NodeRequest(url.toString(), {
method: req.requestContext.http.method,
headers: req.cookies
? { ...req.headers, Cookie: req.cookies.join(";") }
Expand Down
2 changes: 2 additions & 0 deletions packages/remix-cloudflare-workers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type { GetLoadContextFunction, RequestHandler } from "./worker";
export { createRequestHandler } from "./worker";
15 changes: 15 additions & 0 deletions packages/remix-cloudflare-workers/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "@remix-run/cloudflare-workers",
"description": "Cloudflare worker request handler for Remix",
"version": "0.17.5",
"repository": "https://github.com/remix-run/packages",
"dependencies": {
"@remix-run/server-runtime": "0.17.5"
},
"peerDependencies": {
"@cloudflare/workers-types": "^2.2.2"
},
"devDependencies": {
"@cloudflare/workers-types": "^2.2.2"
}
}
1 change: 1 addition & 0 deletions packages/remix-cloudflare-workers/responses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { json, redirect } from "@remix-run/server-runtime";
11 changes: 11 additions & 0 deletions packages/remix-cloudflare-workers/routeModules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type {
ActionFunction as CoreActionFunction,
HeadersFunction as CoreHeadersFunction,
LoaderFunction as CoreLoaderFunction
} from "@remix-run/server-runtime";

export type ActionFunction = CoreActionFunction<Request, Response>;

export type HeadersFunction = CoreHeadersFunction<Headers, HeadersInit>;

export type LoaderFunction = CoreLoaderFunction<Request, Response>;
17 changes: 17 additions & 0 deletions packages/remix-cloudflare-workers/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"lib": ["ES2019", "WebWorker"],
"target": "ES2019",
"types": ["@cloudflare/workers-types"],

"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"strict": true,

"declaration": true,
"emitDeclarationOnly": true,

"outDir": "../../build/node_modules/@remix-run/cloudflare-workers",
"rootDir": "."
}
}
43 changes: 43 additions & 0 deletions packages/remix-cloudflare-workers/worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type {
AppLoadContext,
ServerBuild,
ServerPlatform
} from "@remix-run/server-runtime";
import { createRequestHandler as createRemixRequestHandler } from "@remix-run/server-runtime";

/**
* A function that returns the value to use as `context` in route `loader` and
* `action` functions.
*
* You can think of this as an escape hatch that allows you to pass
* environment/platform-specific values through to your loader/action.
*/
export interface GetLoadContextFunction {
(event: FetchEvent): AppLoadContext;
}

export type RequestHandler = ReturnType<typeof createRequestHandler>;

/**
* Returns a request handler for Cloudflare runtime that serves the
* response using Remix.
*/
export function createRequestHandler({
build,
getLoadContext,
mode
}: {
build: ServerBuild;
getLoadContext?: GetLoadContextFunction;
mode?: string;
}) {
let platform: ServerPlatform = {};
let handleRequest = createRemixRequestHandler(build, platform, mode);

return (event: FetchEvent) => {
let loadContext =
typeof getLoadContext === "function" ? getLoadContext(event) : undefined;

return handleRequest(event.request, loadContext);
};
}
2 changes: 2 additions & 0 deletions packages/remix-dev/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ async function createBrowserBuild(
bundle: true,
logLevel: "silent",
splitting: true,
sourcemap: true,
metafile: true,
incremental: options.incremental,
minify: options.mode === BuildMode.Production,
Expand Down Expand Up @@ -304,6 +305,7 @@ async function createServerBuild(
bundle: true,
logLevel: "silent",
incremental: options.incremental,
sourcemap: true,
// The server build needs to know how to generate asset URLs for imports
// of CSS and other files.
assetNames: "_assets/[name]-[hash]",
Expand Down
6 changes: 2 additions & 4 deletions packages/remix-express/__tests__/server-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ import supertest from "supertest";

import { createRequestHandler } from "../server";

import { Response } from "@remix-run/node";

import { createRequestHandler as createRemixRequestHandler } from "@remix-run/node/server";
import { createRequestHandler as createRemixRequestHandler } from "@remix-run/server-runtime";

// We don't want to test that the remix server works here (that's what the
// puppetteer tests do), we just want to test the express adapter
jest.mock("@remix-run/node/server");
jest.mock("@remix-run/server-runtime/server");
let mockedCreateRequestHandler = createRemixRequestHandler as jest.MockedFunction<
typeof createRemixRequestHandler
>;
Expand Down
3 changes: 2 additions & 1 deletion packages/remix-express/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"version": "0.17.5",
"repository": "https://github.com/remix-run/packages",
"dependencies": {
"@remix-run/node": "0.17.5"
"@remix-run/node": "0.17.5",
"@remix-run/server-runtime": "0.17.5"
},
"peerDependencies": {
"express": "^4.17.1"
Expand Down
Loading

0 comments on commit a8bcc1f

Please sign in to comment.