Skip to content

Commit 2b47ba8

Browse files
Handle catch-all scanner posts
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
1 parent cdb6249 commit 2b47ba8

3 files changed

Lines changed: 108 additions & 0 deletions

File tree

epicshop/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"type": "module",
33
"scripts": {
4+
"postinstall": "node ./patch-workshop-app.js",
5+
"test:patch": "node --test ./patch-workshop-app.test.js",
46
"test:setup": "playwright install chromium --with-deps",
57
"test": "playwright test"
68
},

epicshop/patch-workshop-app.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { readFile, writeFile } from 'node:fs/promises'
2+
import path from 'node:path'
3+
import { fileURLToPath } from 'node:url'
4+
5+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
6+
const workshopAppServerBuildPath = path.join(
7+
'node_modules',
8+
'@epic-web',
9+
'workshop-app',
10+
'build',
11+
'server',
12+
'index.js',
13+
)
14+
15+
const catchAllActionSource = `async function action$catchAll() {
16+
throw new Response("Not Found", { status: 404 });
17+
}
18+
`
19+
20+
const routeWithoutAction = `const route1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
21+
__proto__: null,
22+
ErrorBoundary: ErrorBoundary$7,
23+
default: $,
24+
loader: loader$L
25+
}, Symbol.toStringTag, { value: "Module" }));`
26+
27+
const routeWithAction = `const route1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
28+
__proto__: null,
29+
ErrorBoundary: ErrorBoundary$7,
30+
default: $,
31+
action: action$catchAll,
32+
loader: loader$L
33+
}, Symbol.toStringTag, { value: "Module" }));`
34+
35+
const manifestWithoutAction = `"routes/$": { "id": "routes/$", "parentId": "root", "path": "*", "index": void 0, "caseSensitive": void 0, "hasAction": false,`
36+
const manifestWithAction = `"routes/$": { "id": "routes/$", "parentId": "root", "path": "*", "index": void 0, "caseSensitive": void 0, "hasAction": true,`
37+
38+
export function patchServerBuild(contents) {
39+
if (contents.includes('action: action$catchAll')) {
40+
return contents
41+
}
42+
43+
if (!contents.includes(routeWithoutAction)) {
44+
throw new Error('Could not find the workshop app catch-all route module.')
45+
}
46+
47+
if (!contents.includes(manifestWithoutAction)) {
48+
throw new Error('Could not find the workshop app catch-all route manifest.')
49+
}
50+
51+
return contents
52+
.replace(routeWithoutAction, `${catchAllActionSource}${routeWithAction}`)
53+
.replace(manifestWithoutAction, manifestWithAction)
54+
}
55+
56+
export async function patchWorkshopApp({ cwd = __dirname } = {}) {
57+
const serverBuildPath = path.join(cwd, workshopAppServerBuildPath)
58+
const currentContents = await readFile(serverBuildPath, 'utf8')
59+
const patchedContents = patchServerBuild(currentContents)
60+
61+
if (patchedContents === currentContents) {
62+
return { serverBuildPath, patched: false }
63+
}
64+
65+
await writeFile(serverBuildPath, patchedContents)
66+
return { serverBuildPath, patched: true }
67+
}
68+
69+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
70+
const { serverBuildPath, patched } = await patchWorkshopApp()
71+
console.log(
72+
`${patched ? 'Patched' : 'Already patched'} @epic-web/workshop-app catch-all route: ${serverBuildPath}`,
73+
)
74+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import assert from 'node:assert/strict'
2+
import { test } from 'node:test'
3+
4+
import { patchServerBuild } from './patch-workshop-app.js'
5+
6+
const serverBuildFixture = `const route1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
7+
__proto__: null,
8+
ErrorBoundary: ErrorBoundary$7,
9+
default: $,
10+
loader: loader$L
11+
}, Symbol.toStringTag, { value: "Module" }));
12+
const serverManifest = { "routes": { "routes/$": { "id": "routes/$", "parentId": "root", "path": "*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true } } };`
13+
14+
test('patches the workshop app catch-all route with a 404 action', () => {
15+
const patched = patchServerBuild(serverBuildFixture)
16+
17+
assert.match(
18+
patched,
19+
/async function action\$catchAll\(\) {\n throw new Response\("Not Found", { status: 404 }\);\n}/,
20+
)
21+
assert.match(patched, /action: action\$catchAll,/)
22+
assert.match(
23+
patched,
24+
/"routes\/\$": { "id": "routes\/\$", "parentId": "root", "path": "\*", "index": void 0, "caseSensitive": void 0, "hasAction": true,/,
25+
)
26+
})
27+
28+
test('patching the server build is idempotent', () => {
29+
const patched = patchServerBuild(serverBuildFixture)
30+
31+
assert.equal(patchServerBuild(patched), patched)
32+
})

0 commit comments

Comments
 (0)