Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
31 changed files
with
84,216 additions
and
455 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
72 changes: 72 additions & 0 deletions
72
packages/resources/assets/RemixSite/config/read-remix-config.cjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
"use strict"; | ||
|
||
// Given we can't do synchronous dynamic imports within ESM we have to create | ||
// this script so that our CDK construct can execute it synchronously and get | ||
// the Remix config. | ||
|
||
// Makes the script crash on unhandled rejections instead of silently | ||
// ignoring them. In the future, promise rejections that are not handled will | ||
// terminate the Node.js process with a non-zero exit code. | ||
process.on("unhandledRejection", (err) => { | ||
throw err; | ||
}); | ||
|
||
const fs = require("fs-extra"); | ||
const chalk = require("chalk"); | ||
|
||
// https://remix.run/docs/en/v1/api/conventions#remixconfigjs | ||
const configDefaults = { | ||
assetsBuildDirectory: "public/build", | ||
publicPath: "/build/", | ||
serverBuildPath: "build/index.js", | ||
serverBuildTarget: "node-cjs", | ||
server: undefined, | ||
}; | ||
|
||
function failWithError(msg) { | ||
console.error(chalk.red(msg)); | ||
process.exit(1); | ||
} | ||
|
||
function getRemixConfig(configPath) { | ||
if (!fs.existsSync(configPath)) { | ||
failWithError( | ||
`Could not find remix.config.js at expected path "${configPath}".` | ||
); | ||
} | ||
const userConfig = require(configPath); | ||
const config = { | ||
...configDefaults, | ||
...userConfig, | ||
}; | ||
|
||
if (config.serverBuildTarget !== "node-cjs") { | ||
failWithError('\nremix.config.js "serverBuildTarget" must be "node-cjs"'); | ||
} | ||
|
||
return config; | ||
} | ||
|
||
const parsedArgs = parseArgs(process.argv); | ||
|
||
// Parse default config | ||
if (!parsedArgs["--path"]) { | ||
throw new Error("--path parameter is required"); | ||
} | ||
|
||
console.log(JSON.stringify(getRemixConfig(parsedArgs["--path"]))); | ||
|
||
function parseArgs(arrArgs) { | ||
return arrArgs.slice(2).reduce((acc, key, ind, self) => { | ||
if (key.startsWith("--")) { | ||
if (self[ind + 1] && self[ind + 1].startsWith("-")) { | ||
acc[key] = null; | ||
} else if (self[ind + 1]) { | ||
acc[key] = self[ind + 1]; | ||
} else if (!self[ind + 1]) { | ||
acc[key] = null; | ||
} | ||
} | ||
return acc; | ||
}, {}); | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/resources/assets/RemixSite/server-lambda-stub/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
"use strict"; | ||
|
||
exports.handler = () => { | ||
// placeholder function | ||
}; |
110 changes: 110 additions & 0 deletions
110
packages/resources/assets/RemixSite/server/server-template.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// This is a custom CloudFront Lambda@Edge handler which we will utilise to wrap | ||
// the Remix server build with. | ||
// | ||
// It additionally exposes an environment variable token which is used by our | ||
// Lambda Replacer code to inject the appropriate environment variables. This | ||
// strategy is required as Lambda@Edge doesn't natively support environment | ||
// variables - they need to be inlined. | ||
|
||
import { | ||
Headers as NodeHeaders, | ||
Request as NodeRequest, | ||
} from "@remix-run/node"; | ||
import { installGlobals } from "@remix-run/node"; | ||
import { createRequestHandler as createRemixRequestHandler } from "@remix-run/server-runtime"; | ||
import { URL } from "url"; | ||
|
||
import * as remixServerBuild from "./index.js"; | ||
|
||
installGlobals(); | ||
|
||
function createNodeRequestHeaders(requestHeaders) { | ||
const headers = new NodeHeaders(); | ||
|
||
for (const [key, values] of Object.entries(requestHeaders)) { | ||
for (const { value } of values) { | ||
if (value) { | ||
headers.append(key, value); | ||
} | ||
} | ||
} | ||
|
||
return headers; | ||
} | ||
|
||
function createNodeRequest(event) { | ||
const request = event.Records[0].cf.request; | ||
|
||
const host = request.headers["host"] | ||
? request.headers["host"][0].value | ||
: undefined; | ||
const search = request.querystring.length ? `?${request.querystring}` : ""; | ||
const url = new URL(request.uri + search, `https://${host}`); | ||
|
||
return new NodeRequest(url.toString(), { | ||
method: request.method, | ||
headers: createNodeRequestHeaders(request.headers), | ||
body: request.body?.data | ||
? request.body.encoding === "base64" | ||
? Buffer.from(request.body.data, "base64").toString() | ||
: request.body.data | ||
: undefined, | ||
}); | ||
} | ||
|
||
function createCloudFrontResponseHeaders(responseHeaders) { | ||
const headers = {}; | ||
const rawHeaders = responseHeaders.raw(); | ||
|
||
for (const key in rawHeaders) { | ||
const value = rawHeaders[key]; | ||
for (const v of value) { | ||
headers[key] = [...(headers[key] || []), { key, value: v }]; | ||
} | ||
} | ||
|
||
return headers; | ||
} | ||
|
||
function createCloudFrontRequestHandler({ | ||
remixServerBuild, | ||
getLoadContext, | ||
mode = process.env.NODE_ENV, | ||
}) { | ||
const remixRequestHandler = createRemixRequestHandler(remixServerBuild, mode); | ||
|
||
return async (event, _context) => { | ||
const request = createNodeRequest(event); | ||
|
||
const loadContext = | ||
typeof getLoadContext === "function" ? getLoadContext(event) : undefined; | ||
|
||
const response = await remixRequestHandler(request, loadContext); | ||
|
||
return { | ||
status: String(response.status), | ||
headers: createCloudFrontResponseHeaders(response.headers), | ||
bodyEncoding: "text", | ||
body: await response.text(), | ||
}; | ||
}; | ||
} | ||
|
||
const cloudFrontRequestHandler = createCloudFrontRequestHandler({ | ||
remixServerBuild, | ||
}); | ||
|
||
export async function handler(...args) { | ||
try { | ||
// The right hand side of this assignment will get replaced during | ||
// deployment with an object of environment key-value pairs; | ||
const environment = "{{ _SST_REMIX_SITE_ENVIRONMENT_ }}"; | ||
|
||
process.env = { ...process.env, ...environment }; | ||
} catch (e) { | ||
console.log("Failed to set SST RemixSite environment."); | ||
console.log(e); | ||
} | ||
|
||
return await cloudFrontRequestHandler(...args); | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
"use strict"; | ||
|
||
// Given we can't do synchronous dynamic imports within ESM we have to create | ||
// this script so that our CDK construct can execute it synchronously and get | ||
// the Remix config. | ||
|
||
// Makes the script crash on unhandled rejections instead of silently | ||
// ignoring them. In the future, promise rejections that are not handled will | ||
// terminate the Node.js process with a non-zero exit code. | ||
process.on("unhandledRejection", (err) => { | ||
throw err; | ||
}); | ||
|
||
const fs = require("fs-extra"); | ||
const chalk = require("chalk"); | ||
const { hashElement } = require("folder-hash"); | ||
|
||
function failWithError(msg) { | ||
console.error(chalk.red(msg)); | ||
process.exit(1); | ||
} | ||
|
||
async function getFolderHash(dir, ignore) { | ||
if (!fs.existsSync(dir)) { | ||
failWithError(`Could not find directory at path "${dir}".`); | ||
} | ||
if (!fs.statSync(dir).isDirectory()) { | ||
failWithError(`Path "${dir}" is not a directory.`); | ||
} | ||
|
||
const { hash } = await hashElement(dir, { | ||
folders: { | ||
exclude: ignore ? [ignore] : undefined, | ||
matchBasename: true, | ||
matchPath: false, | ||
ignoreBasename: true, | ||
}, | ||
}); | ||
return hash; | ||
} | ||
|
||
const parsedArgs = parseArgs(process.argv); | ||
|
||
// Parse default config | ||
if (!parsedArgs["--path"]) { | ||
throw new Error("--path parameter is required"); | ||
} | ||
|
||
getFolderHash(parsedArgs["--path"], parsedArgs["--ignore"]).then((hash) => { | ||
console.log(hash); | ||
}); | ||
|
||
function parseArgs(arrArgs) { | ||
return arrArgs.slice(2).reduce((acc, key, ind, self) => { | ||
if (key.startsWith("--")) { | ||
if (self[ind + 1] && self[ind + 1].startsWith("-")) { | ||
acc[key] = null; | ||
} else if (self[ind + 1]) { | ||
acc[key] = self[ind + 1]; | ||
} else if (!self[ind + 1]) { | ||
acc[key] = null; | ||
} | ||
} | ||
return acc; | ||
}, {}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.