Skip to content

Commit 55e88c7

Browse files
committed
02/02: add problem text
1 parent 48eccd7 commit 55e88c7

File tree

229 files changed

+34590
-54
lines changed

Some content is hidden

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

229 files changed

+34590
-54
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
description:
3+
globs: *.tsx,*.jsx
4+
alwaysApply: false
5+
---
6+
### Avoid useEffect
7+
8+
[You Might Not Need `useEffect`](https://react.dev/learn/you-might-not-need-an-effect)
9+
10+
Instead of using `useEffect`, use ref callbacks, event handlers with
11+
`flushSync`, css, `useSyncExternalStore`, etc.
12+
13+
```tsx
14+
// This example was ripped from the docs:
15+
// ✅ Good
16+
function ProductPage({ product, addToCart }) {
17+
function buyProduct() {
18+
addToCart(product)
19+
showNotification(`Added ${product.name} to the shopping cart!`)
20+
}
21+
22+
function handleBuyClick() {
23+
buyProduct()
24+
}
25+
26+
function handleCheckoutClick() {
27+
buyProduct()
28+
navigateTo('/checkout')
29+
}
30+
// ...
31+
}
32+
33+
useEffect(() => {
34+
setCount(count + 1)
35+
}, [count])
36+
37+
// ❌ Avoid
38+
function ProductPage({ product, addToCart }) {
39+
useEffect(() => {
40+
if (product.isInCart) {
41+
showNotification(`Added ${product.name} to the shopping cart!`)
42+
}
43+
}, [product])
44+
45+
function handleBuyClick() {
46+
addToCart(product)
47+
}
48+
49+
function handleCheckoutClick() {
50+
addToCart(product)
51+
navigateTo('/checkout')
52+
}
53+
// ...
54+
}
55+
```
56+
57+
There are a lot more examples in the docs. `useEffect` is not banned or
58+
anything. There are just better ways to handle most cases.
59+
60+
Here's an example of a situation where `useEffect` is appropriate:
61+
62+
```tsx
63+
// ✅ Good
64+
useEffect(() => {
65+
const controller = new AbortController()
66+
67+
window.addEventListener(
68+
'keydown',
69+
(event: KeyboardEvent) => {
70+
if (event.key !== 'Escape') return
71+
72+
// do something based on escape key being pressed
73+
},
74+
{ signal: controller.signal },
75+
)
76+
77+
return () => {
78+
controller.abort()
79+
}
80+
}, [])
81+
```
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
LITEFS_DIR="/litefs/data"
2+
DATABASE_PATH="./prisma/data.db"
3+
DATABASE_URL="file:./data.db?connection_limit=1"
4+
CACHE_DATABASE_PATH="./other/cache.db"
5+
SESSION_SECRET="super-duper-s3cret"
6+
HONEYPOT_SECRET="super-duper-s3cret"
7+
RESEND_API_KEY="re_blAh_blaHBlaHblahBLAhBlAh"
8+
SENTRY_DSN="your-dsn"
9+
10+
# this is set to a random value in the Dockerfile
11+
INTERNAL_COMMAND_TOKEN="some-made-up-token"
12+
13+
# the mocks and some code rely on these two being prefixed with "MOCK_"
14+
# if they aren't then the real github api will be attempted
15+
GITHUB_CLIENT_ID="MOCK_GITHUB_CLIENT_ID"
16+
GITHUB_CLIENT_SECRET="MOCK_GITHUB_CLIENT_SECRET"
17+
GITHUB_TOKEN="MOCK_GITHUB_TOKEN"
18+
GITHUB_REDIRECT_URI="https://example.com/auth/github/callback"
19+
20+
# set this to false to prevent search engines from indexing the website
21+
# default to allow indexing for seo safety
22+
ALLOW_INDEXING="true"
23+
24+
# Tigris Object Storage (S3-compatible) Configuration
25+
AWS_ACCESS_KEY_ID="mock-access-key"
26+
AWS_SECRET_ACCESS_KEY="mock-secret-key"
27+
AWS_REGION="auto"
28+
AWS_ENDPOINT_URL_S3="https://fly.storage.tigris.dev"
29+
BUCKET_NAME="mock-bucket"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!-- Summary: Put your summary here -->
2+
3+
## Test Plan
4+
5+
<!-- What steps need to be taken to verify this works as expected? -->
6+
7+
## Checklist
8+
9+
- [ ] Tests updated
10+
- [ ] Docs updated
11+
12+
## Screenshots
13+
14+
<!-- If what you're changing is within the app, please show before/after.
15+
You can provide a video as well if that makes more sense -->
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
name: 🚀 Deploy
2+
on:
3+
push:
4+
branches:
5+
- main
6+
- dev
7+
pull_request: {}
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
permissions:
14+
actions: write
15+
contents: read
16+
17+
jobs:
18+
lint:
19+
name: ⬣ ESLint
20+
runs-on: ubuntu-22.04
21+
steps:
22+
- name: ⬇️ Checkout repo
23+
uses: actions/checkout@v4
24+
25+
- name: ⎔ Setup node
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: 22
29+
30+
- name: 📥 Download deps
31+
uses: bahmutov/npm-install@v1
32+
33+
- name: 🏄 Copy test env vars
34+
run: cp .env.example .env
35+
36+
- name: 🛠 Setup Database
37+
run: npx prisma migrate deploy && npx prisma generate --sql
38+
39+
- name: 🔬 Lint
40+
run: npm run lint
41+
42+
typecheck:
43+
name: ʦ TypeScript
44+
runs-on: ubuntu-22.04
45+
steps:
46+
- name: ⬇️ Checkout repo
47+
uses: actions/checkout@v4
48+
49+
- name: ⎔ Setup node
50+
uses: actions/setup-node@v4
51+
with:
52+
node-version: 22
53+
54+
- name: 📥 Download deps
55+
uses: bahmutov/npm-install@v1
56+
57+
- name: 🏗 Build
58+
run: npm run build
59+
60+
- name: 🏄 Copy test env vars
61+
run: cp .env.example .env
62+
63+
- name: 🛠 Setup Database
64+
run: npx prisma migrate deploy && npx prisma generate --sql
65+
66+
- name: 🔎 Type check
67+
run: npm run typecheck --if-present
68+
69+
vitest:
70+
name: ⚡ Vitest
71+
runs-on: ubuntu-22.04
72+
steps:
73+
- name: ⬇️ Checkout repo
74+
uses: actions/checkout@v4
75+
76+
- name: ⎔ Setup node
77+
uses: actions/setup-node@v4
78+
with:
79+
node-version: 22
80+
81+
- name: 📥 Download deps
82+
uses: bahmutov/npm-install@v1
83+
84+
- name: 🏄 Copy test env vars
85+
run: cp .env.example .env
86+
87+
- name: 🛠 Setup Database
88+
run: npx prisma migrate deploy && npx prisma generate --sql
89+
90+
- name: ⚡ Run vitest
91+
run: npm run test -- --coverage
92+
93+
playwright:
94+
name: 🎭 Playwright
95+
runs-on: ubuntu-22.04
96+
timeout-minutes: 60
97+
steps:
98+
- name: ⬇️ Checkout repo
99+
uses: actions/checkout@v4
100+
101+
- name: 🏄 Copy test env vars
102+
run: cp .env.example .env
103+
104+
- name: ⎔ Setup node
105+
uses: actions/setup-node@v4
106+
with:
107+
node-version: 22
108+
109+
- name: 📥 Download deps
110+
uses: bahmutov/npm-install@v1
111+
112+
- name: 📥 Install Playwright Browsers
113+
run: npm run test:e2e:install
114+
115+
- name: 🛠 Setup Database
116+
run: npx prisma migrate deploy && npx prisma generate --sql
117+
118+
- name: 🏦 Cache Database
119+
id: db-cache
120+
uses: actions/cache@v4
121+
with:
122+
path: prisma/data.db
123+
key:
124+
db-cache-schema_${{ hashFiles('./prisma/schema.prisma')
125+
}}-migrations_${{ hashFiles('./prisma/migrations/*/migration.sql')
126+
}}
127+
128+
- name: 🌱 Seed Database
129+
if: steps.db-cache.outputs.cache-hit != 'true'
130+
run: npx prisma migrate reset --force
131+
132+
- name: 🏗 Build
133+
run: npm run build
134+
135+
- name: 🎭 Playwright tests
136+
run: npx playwright test
137+
138+
- name: 📊 Upload report
139+
uses: actions/upload-artifact@v4
140+
if: always()
141+
with:
142+
name: playwright-report
143+
path: playwright-report/
144+
retention-days: 30
145+
146+
container:
147+
name: 📦 Prepare Container
148+
runs-on: ubuntu-24.04
149+
# only prepare container on pushes
150+
if: ${{ github.event_name == 'push' }}
151+
steps:
152+
- name: ⬇️ Checkout repo
153+
uses: actions/checkout@v4
154+
with:
155+
fetch-depth: 50
156+
157+
- name: 👀 Read app name
158+
uses: SebRollen/[email protected]
159+
id: app_name
160+
with:
161+
file: 'fly.toml'
162+
field: 'app'
163+
164+
- name: 🎈 Setup Fly
165+
uses: superfly/flyctl-actions/[email protected]
166+
167+
- name: 📦 Build Staging Container
168+
if: ${{ github.ref == 'refs/heads/dev' }}
169+
run: |
170+
flyctl deploy \
171+
--build-only \
172+
--push \
173+
--image-label ${{ github.sha }} \
174+
--build-arg COMMIT_SHA=${{ github.sha }} \
175+
--app ${{ steps.app_name.outputs.value }}-staging
176+
env:
177+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
178+
179+
- name: 📦 Build Production Container
180+
if: ${{ github.ref == 'refs/heads/main' }}
181+
run: |
182+
flyctl deploy \
183+
--build-only \
184+
--push \
185+
--image-label ${{ github.sha }} \
186+
--build-arg COMMIT_SHA=${{ github.sha }} \
187+
--build-secret SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} \
188+
--app ${{ steps.app_name.outputs.value }}
189+
env:
190+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
191+
192+
deploy:
193+
name: 🚀 Deploy
194+
runs-on: ubuntu-24.04
195+
needs: [lint, typecheck, vitest, playwright, container]
196+
# only deploy on pushes
197+
if: ${{ github.event_name == 'push' }}
198+
steps:
199+
- name: ⬇️ Checkout repo
200+
uses: actions/checkout@v4
201+
with:
202+
fetch-depth: '50'
203+
204+
- name: 👀 Read app name
205+
uses: SebRollen/[email protected]
206+
id: app_name
207+
with:
208+
file: 'fly.toml'
209+
field: 'app'
210+
211+
- name: 🎈 Setup Fly
212+
uses: superfly/flyctl-actions/[email protected]
213+
214+
- name: 🚀 Deploy Staging
215+
if: ${{ github.ref == 'refs/heads/dev' }}
216+
run: |
217+
flyctl deploy \
218+
--image "registry.fly.io/${{ steps.app_name.outputs.value }}-staging:${{ github.sha }}" \
219+
--app ${{ steps.app_name.outputs.value }}-staging
220+
env:
221+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
222+
223+
- name: 🚀 Deploy Production
224+
if: ${{ github.ref == 'refs/heads/main' }}
225+
run: |
226+
flyctl deploy \
227+
--image "registry.fly.io/${{ steps.app_name.outputs.value }}:${{ github.sha }}"
228+
env:
229+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
node_modules
2+
.DS_store
3+
4+
/build
5+
/server-build
6+
.env
7+
.cache
8+
9+
/prisma/data.db
10+
/prisma/data.db-journal
11+
/tests/prisma
12+
13+
/test-results/
14+
/playwright-report/
15+
/playwright/.cache/
16+
/tests/fixtures/email/
17+
/tests/fixtures/uploaded/
18+
/tests/fixtures/openimg/
19+
/coverage
20+
21+
/other/cache.db
22+
23+
# Easy way to create temporary files/folders that won't accidentally be added to git
24+
*.local.*
25+
26+
# generated files
27+
/app/components/ui/icons
28+
.react-router/
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
legacy-peer-deps=true
2+
registry=https://registry.npmjs.org/

0 commit comments

Comments
 (0)