Skip to content

Commit e008daf

Browse files
authored
refactor: move it to a simple node app (#9)
* intial build movement * intial build movement * limit public assets * fix: syncing * refactor: simplify things and inline a dep * chore: dependency cleanup * chore: add fly deploy
1 parent 7e6c9e6 commit e008daf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+4823
-2646
lines changed

.dockerignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/node_modules

.eslintrc

-61
This file was deleted.

.github/workflows/cron.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ on:
88
branches:
99
- dev
1010
schedule:
11-
- cron: '0 0 * * *'
11+
- cron: "0 0 * * *"
1212

1313
jobs:
1414
build:
1515
runs-on: ubuntu-latest
1616
strategy:
1717
matrix:
1818
node-version: [16.x]
19-
19+
2020
permissions:
2121
contents: write
2222

@@ -26,7 +26,7 @@ jobs:
2626
with:
2727
version: 6.32.10
2828
- run: pnpm i
29-
- run: export GH_TOKEN=${{ secrets.GH_TOKEN }}; npm run sync; node scripts/fill-release-dates.js;
29+
- run: export GH_TOKEN=${{ secrets.GITHUB_TOKEN }}; npm run sync; node scripts/fill-release-dates.js;
3030
- name: Commit changes
3131
uses: stefanzweifel/git-auto-commit-action@v5
3232
with:

.github/workflows/fly-deploy.yml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Fly Deploy
2+
on:
3+
push:
4+
branches:
5+
- main
6+
jobs:
7+
deploy:
8+
name: Deploy app
9+
runs-on: ubuntu-latest
10+
concurrency: deploy-group
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: superfly/flyctl-actions/setup-flyctl@master
14+
- run: flyctl deploy --remote-only
15+
env:
16+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

.prettierignore

-2
This file was deleted.

.prettierrc.json

-11
This file was deleted.

Dockerfile

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
FROM node:20-alpine
2+
3+
WORKDIR /app
4+
5+
COPY . .
6+
7+
RUN apk update && apk upgrade
8+
RUN apk add --no-cache sqlite
9+
10+
RUN corepack enable
11+
RUN pnpm i --frozen-lockfile
12+
RUN pnpm build
13+
14+
EXPOSE 3000
15+
16+
CMD ["pnpm","start"]

biome.json

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3+
"files": {
4+
"include": [
5+
"**/*.mjs",
6+
"**/*.js",
7+
"**/*.css",
8+
"**/*.json",
9+
"**/*.jsx",
10+
"**/*.njk"
11+
],
12+
"ignore": ["node_modules", ".next", "tmp", "dist"]
13+
},
14+
"formatter": {
15+
"enabled": true,
16+
"useEditorconfig": true,
17+
"formatWithErrors": false,
18+
"indentStyle": "space",
19+
"indentWidth": 2,
20+
"lineEnding": "lf",
21+
"lineWidth": 80,
22+
"attributePosition": "auto",
23+
"bracketSpacing": true
24+
},
25+
"organizeImports": { "enabled": true },
26+
"linter": {
27+
"enabled": false,
28+
"rules": {
29+
"recommended": false,
30+
"complexity": {
31+
"noExtraBooleanCast": "error",
32+
"noForEach": "error",
33+
"noMultipleSpacesInRegularExpressionLiterals": "error",
34+
"noUselessCatch": "error",
35+
"noWith": "error",
36+
"useArrowFunction": "off"
37+
},
38+
"correctness": {
39+
"noConstAssign": "error",
40+
"noConstantCondition": "error",
41+
"noEmptyCharacterClassInRegex": "error",
42+
"noEmptyPattern": "error",
43+
"noGlobalObjectCalls": "error",
44+
"noInvalidBuiltinInstantiation": "error",
45+
"noInvalidConstructorSuper": "error",
46+
"noNonoctalDecimalEscape": "error",
47+
"noPrecisionLoss": "error",
48+
"noSelfAssign": "error",
49+
"noSetterReturn": "error",
50+
"noSwitchDeclarations": "error",
51+
"noUndeclaredVariables": "error",
52+
"noUnreachable": "error",
53+
"noUnreachableSuper": "error",
54+
"noUnsafeFinally": "error",
55+
"noUnsafeOptionalChaining": "error",
56+
"noUnusedLabels": "error",
57+
"noUnusedPrivateClassMembers": "error",
58+
"noUnusedVariables": "error",
59+
"useIsNan": "error",
60+
"useValidForDirection": "error",
61+
"useYield": "error"
62+
},
63+
"style": { "useBlockStatements": "error", "useForOf": "warn" },
64+
"suspicious": {
65+
"noAssignInExpressions": "error",
66+
"noAsyncPromiseExecutor": "error",
67+
"noCatchAssign": "error",
68+
"noClassAssign": "error",
69+
"noCompareNegZero": "error",
70+
"noControlCharactersInRegex": "error",
71+
"noDebugger": "error",
72+
"noDuplicateCase": "error",
73+
"noDuplicateClassMembers": "error",
74+
"noDuplicateObjectKeys": "error",
75+
"noDuplicateParameters": "error",
76+
"noEmptyBlockStatements": "error",
77+
"noFallthroughSwitchClause": "error",
78+
"noFunctionAssign": "error",
79+
"noGlobalAssign": "error",
80+
"noImportAssign": "error",
81+
"noMisleadingCharacterClass": "error",
82+
"noPrototypeBuiltins": "error",
83+
"noRedeclare": "error",
84+
"noShadowRestrictedNames": "error",
85+
"noSparseArray": "error",
86+
"noUnsafeNegation": "error",
87+
"useGetterReturn": "error",
88+
"useValidTypeof": "error"
89+
}
90+
}
91+
},
92+
"javascript": {
93+
"jsxRuntime": "transparent",
94+
"formatter": {
95+
"jsxQuoteStyle": "double",
96+
"quoteProperties": "asNeeded",
97+
"trailingCommas": "es5",
98+
"semicolons": "asNeeded",
99+
"arrowParentheses": "asNeeded",
100+
"bracketSameLine": false,
101+
"quoteStyle": "single",
102+
"attributePosition": "auto",
103+
"bracketSpacing": true
104+
},
105+
"globals": ["exports"]
106+
}
107+
}

build.mjs

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import generatePkg from '@babel/generator'
2+
import { parse } from '@babel/parser'
3+
import traversePkg from '@babel/traverse'
4+
import esbuild from 'esbuild'
5+
import { nodeExternals } from 'esbuild-plugin-node-externals'
6+
import postcss from 'esbuild-postcss'
7+
import fs from 'fs/promises'
8+
import glob from 'tiny-glob'
9+
10+
const generate = generatePkg.default
11+
const traverse = traversePkg.default
12+
13+
const files = await glob('./pages/**/*.js', { filesOnly: true })
14+
15+
const buildOptions = {
16+
entryPoints: files,
17+
bundle: true,
18+
format: 'esm',
19+
jsx: 'automatic',
20+
jsxImportSource: 'preact',
21+
loader: { '.js': 'jsx' },
22+
}
23+
24+
await esbuild
25+
.build({
26+
...buildOptions,
27+
outdir: 'out',
28+
platform: 'node',
29+
target: 'node12',
30+
plugins: [nodeExternals(), postcss()],
31+
})
32+
.catch(() => process.exit(1))
33+
34+
await esbuild.build({
35+
...buildOptions,
36+
outdir: 'out/client',
37+
platform: 'browser',
38+
plugins: [
39+
postcss(),
40+
{
41+
name: 'remove-server-code',
42+
setup(builder) {
43+
builder.onLoad({ filter: /\.jsx?$/ }, async args => {
44+
const source = await fs.readFile(args.path, 'utf8')
45+
const ast = parse(source, { sourceType: 'module', plugins: ['jsx'] })
46+
47+
const importedDependencies = new Set()
48+
let defaultExportName
49+
50+
traverse(ast, {
51+
ImportDeclaration(path) {
52+
path.node.specifiers.forEach(specifier => {
53+
importedDependencies.add(specifier.local.name)
54+
})
55+
},
56+
ExportDefaultDeclaration(path) {
57+
defaultExportName = path.node.declaration?.name ?? false
58+
},
59+
FunctionDeclaration(path) {
60+
if (path.node.id.name === 'getServerSideProps') {
61+
const usedDependencies = new Set()
62+
path.traverse({
63+
Identifier(innerPath) {
64+
if (importedDependencies.has(innerPath.node.name)) {
65+
usedDependencies.add(innerPath.node.name)
66+
}
67+
},
68+
})
69+
path.remove()
70+
ast.program.body = ast.program.body.filter(node => {
71+
if (node.type === 'ImportDeclaration') {
72+
return !node.specifiers.some(specifier =>
73+
usedDependencies.has(specifier.local.name)
74+
)
75+
}
76+
return true
77+
})
78+
}
79+
},
80+
})
81+
82+
const { code } = generate(ast)
83+
84+
if (defaultExportName) {
85+
return {
86+
contents: `import { hydrate } from "preact"
87+
${code}
88+
const pageProps = JSON.parse(document.getElementById("pageProps").textContent)
89+
hydrate(<${defaultExportName} {...pageProps} />, document.getElementById("app"))
90+
`,
91+
loader: 'jsx',
92+
}
93+
} else {
94+
console.warn(
95+
`${args.path} doesn't name it's default export, please correct that`
96+
)
97+
}
98+
99+
return {
100+
contents: code,
101+
loader: 'jsx',
102+
}
103+
})
104+
},
105+
},
106+
],
107+
})

components/box.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import React from 'react';
2-
import { modsToStyle } from 'spacery';
1+
import { h } from 'preact'
2+
import { modsToStyle } from '../lib/mods-to-style'
33

44
const Box = function ({ elm = 'div', children, ...props }) {
5-
const { style, sanitizedProps } = modsToStyle(props, ''); // pass dimension as an empty string so it used the actual numbers
5+
const { style, sanitizedProps } = modsToStyle(props, '') // pass dimension as an empty string so it used the actual numbers
66

7-
return React.createElement(
7+
return h(
88
elm,
99
{
1010
style,
1111
...sanitizedProps,
1212
},
1313
children
14-
);
15-
};
14+
)
15+
}
1616

17-
export default Box;
17+
export default Box

components/button.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import Box from './box';
1+
import Box from './box'
22

33
export function Button({ children, primary, ...props }) {
44
return (
55
<>
6-
<Box elm='button' className={`${primary && 'primary'} button`} {...props}>
6+
<Box elm="button" className={`${primary && 'primary'} button`} {...props}>
77
{children}
88
</Box>
99
</>
10-
);
10+
)
1111
}

0 commit comments

Comments
 (0)