Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorporate new Epic-Stack template updates like Remix v2.3.1 #117

Merged
merged 3 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/heat-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ permissions:
jobs:
lint:
name: ⬣ ESLint
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
Expand All @@ -50,7 +50,7 @@ jobs:

typecheck:
name: ʦ TypeScript
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
Expand All @@ -73,7 +73,7 @@ jobs:

vitest:
name: ⚡ Vitest pyodide.test.ts
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
Expand All @@ -100,7 +100,7 @@ jobs:
# playwright tests work great but slight jank/inconsistency passing, and not used yet, so disabling for now
# playwright:
# name: 🎭 Playwright
# runs-on: ubuntu-latest
# runs-on: ubuntu-22.04
# timeout-minutes: 60
# steps:
# - name: ⬇️ Checkout repo
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ node_modules

# Easy way to create temporary files/folders that won't accidentally be added to git
*.local.*

#local temporary folders
heat-app
venv
heat-tmp
11 changes: 11 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"recommendations": [
"bradlc.vscode-tailwindcss",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"prisma.prisma",
"qwtel.sqlite-viewer",
"yoavbls.pretty-ts-errors",
"github.vscode-github-actions"
]
}
1 change: 1 addition & 0 deletions heat-stack/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ DATABASE_PATH="./prisma/data.db"
DATABASE_URL="file:./data.db?connection_limit=1"
CACHE_DATABASE_PATH="./other/cache.db"
SESSION_SECRET="super-duper-s3cret"
HONEYPOT_SECRET="super-duper-s3cret"
INTERNAL_COMMAND_TOKEN="some-made-up-token"
RESEND_API_KEY="re_blAh_blaHBlaHblahBLAhBlAh"
SENTRY_DSN="your-dsn"
Expand Down
4 changes: 4 additions & 0 deletions heat-stack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ npm install
npm run dev
```


### Set up in a new GitHub CodingSpace:

```
Expand All @@ -30,6 +31,9 @@ npm run dev

If you have the node version manager (`nvm`), then `nvm use 18` avoids engine error with node v19+ or newer which is default. nvm is preinstalled in coding spaces.


In Coding Spaces VSCode always go to hamburger menu -> File-> untick AutoSave. For a pic, see https://stackoverflow.com/a/76659316/14144258

### Under special circumstances:

Assume you don't need to, but if the version of pyodide changes run:
Expand Down
21 changes: 0 additions & 21 deletions heat-stack/app/components/confetti.tsx

This file was deleted.

4 changes: 3 additions & 1 deletion heat-stack/app/components/error-boundary.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {
type ErrorResponse,
isRouteErrorResponse,
useParams,
useRouteError,
} from '@remix-run/react'
import { type ErrorResponse } from '@remix-run/router'
import { captureRemixErrorBoundaryError } from '@sentry/remix'
import { getErrorMessage } from '#app/utils/misc.tsx'

type StatusHandler = (info: {
Expand All @@ -25,6 +26,7 @@ export function GeneralErrorBoundary({
unexpectedErrorHandler?: (error: unknown) => JSX.Element | null
}) {
const error = useRouteError()
captureRemixErrorBoundaryError(error)
const params = useParams()

if (typeof document !== 'undefined') {
Expand Down
4 changes: 2 additions & 2 deletions heat-stack/app/components/forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function ErrorList({
return (
<ul id={id} className="flex flex-col gap-1">
{errorsToRender.map(e => (
<li key={e} className="text-[10px] text-foreground-danger">
<li key={e} className="text-foreground-destructive text-[10px]">
{e}
</li>
))}
Expand Down Expand Up @@ -64,7 +64,7 @@ export function TextareaField({
className,
}: {
labelProps: React.LabelHTMLAttributes<HTMLLabelElement>
textareaProps: React.InputHTMLAttributes<HTMLTextAreaElement>
textareaProps: React.TextareaHTMLAttributes<HTMLTextAreaElement>
errors?: ListOfErrors
className?: string
}) {
Expand Down
63 changes: 63 additions & 0 deletions heat-stack/app/components/progress-bar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useNavigation } from '@remix-run/react'
import { useEffect, useRef, useState } from 'react'
import { useSpinDelay } from 'spin-delay'
import { cn } from '#app/utils/misc.tsx'
import { Icon } from './ui/icon.tsx'

function EpicProgress() {
const transition = useNavigation()
const busy = transition.state !== 'idle'
const delayedPending = useSpinDelay(busy, {
delay: 600,
minDuration: 400,
})
const ref = useRef<HTMLDivElement>(null)
const [animationComplete, setAnimationComplete] = useState(true)

useEffect(() => {
if (!ref.current) return
if (delayedPending) setAnimationComplete(false)

const animationPromises = ref.current
.getAnimations()
.map(({ finished }) => finished)

Promise.allSettled(animationPromises).then(() => {
if (!delayedPending) setAnimationComplete(true)
})
}, [delayedPending])

return (
<div
role="progressbar"
aria-hidden={delayedPending ? undefined : true}
aria-valuetext={delayedPending ? 'Loading' : undefined}
className="fixed inset-x-0 left-0 top-0 z-50 h-[0.20rem] animate-pulse"
>
<div
ref={ref}
className={cn(
'h-full w-0 bg-foreground duration-500 ease-in-out',
transition.state === 'idle' &&
(animationComplete
? 'transition-none'
: 'w-full opacity-0 transition-all'),
delayedPending && transition.state === 'submitting' && 'w-5/12',
delayedPending && transition.state === 'loading' && 'w-8/12',
)}
/>
{delayedPending && (
<div className="absolute flex items-center justify-center">
<Icon
name="update"
size="md"
className="m-1 animate-spin text-foreground"
aria-hidden
/>
</div>
)}
</div>
)
}

export { EpicProgress }
6 changes: 4 additions & 2 deletions heat-stack/app/components/search-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Form, useSearchParams, useSubmit } from '@remix-run/react'
import { useId } from 'react'
import { useDebounce, useIsPending } from '#app/utils/misc.tsx'
import { Icon } from './ui/icon.tsx'
import { Input } from './ui/input.tsx'
Expand All @@ -14,6 +15,7 @@ export function SearchBar({
autoFocus?: boolean
autoSubmit?: boolean
}) {
const id = useId()
const [searchParams] = useSearchParams()
const submit = useSubmit()
const isSubmitting = useIsPending({
Expand All @@ -33,13 +35,13 @@ export function SearchBar({
onChange={e => autoSubmit && handleFormChange(e.currentTarget)}
>
<div className="flex-1">
<Label htmlFor="search" className="sr-only">
<Label htmlFor={id} className="sr-only">
Search
</Label>
<Input
type="search"
name="search"
id="search"
id={id}
defaultValue={searchParams.get('search') ?? ''}
placeholder="Search"
className="w-full"
Expand Down
1 change: 1 addition & 0 deletions heat-stack/app/components/spinner.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* deprecated by epic stack 2.3, delete me */
export function Spinner({ showSpinner }: { showSpinner: boolean }) {
return (
<div
Expand Down
6 changes: 3 additions & 3 deletions heat-stack/app/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import * as React from 'react'
import { cn } from '#app/utils/misc.tsx'

const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors outline-none focus-visible:ring-4 focus-within:ring-4 ring-ring ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
default: 'bg-primary text-primary-foreground hover:bg-primary/80',
destructive:
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
'bg-destructive text-destructive-foreground hover:bg-destructive/80',
outline:
'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
secondary:
Expand Down
14 changes: 14 additions & 0 deletions heat-stack/app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { PassThrough } from 'stream'
import {
createReadableStreamFromReadable,
type DataFunctionArgs,
type HandleDocumentRequestFunction,
} from '@remix-run/node'
import { RemixServer } from '@remix-run/react'
import * as Sentry from '@sentry/remix'
import isbot from 'isbot'
import { getInstanceInfo } from 'litefs-js'
import { renderToPipeableStream } from 'react-dom/server'
Expand Down Expand Up @@ -72,6 +74,7 @@ export default async function handleRequest(...args: DocRequestArgs) {

console.error(error)
},
nonce,
},
)

Expand All @@ -88,3 +91,14 @@ export async function handleDataRequest(response: Response) {

return response
}

export function handleError(
error: unknown,
{ request }: DataFunctionArgs,
): void {
if (error instanceof Error) {
Sentry.captureRemixServerException(error, 'remix.server', request)
} else {
Sentry.captureException(error)
}
}
30 changes: 21 additions & 9 deletions heat-stack/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import { cssBundleHref } from '@remix-run/css-bundle'
import fontStyleSheetUrl from './styles/font.css'

Check warning on line 2 in heat-stack/app/root.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`./styles/font.css` import should occur after import of `./components/WeatherExample.tsx`
import tailwindStyleSheetUrl from './styles/tailwind.css'

Check warning on line 3 in heat-stack/app/root.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`./styles/tailwind.css` import should occur after import of `./components/WeatherExample.tsx`
import { Links, Scripts } from '@remix-run/react'

Check warning on line 4 in heat-stack/app/root.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`@remix-run/react` import should occur after import of `@remix-run/node`
import { href as iconsHref } from './components/ui/icon.tsx'

Check warning on line 5 in heat-stack/app/root.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`./components/ui/icon.tsx` import should occur after import of `./components/CaseSummary.tsx`
import { DataFunctionArgs, json, type LinksFunction } from '@remix-run/node'
import { DataFunctionArgs, HeadersFunction, json, type LinksFunction } from '@remix-run/node'

Check warning on line 6 in heat-stack/app/root.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

Imports "DataFunctionArgs" and "HeadersFunction" are only used as types

import { CaseSummary } from './components/CaseSummary.tsx'
import './App.css'
import { useNonce } from './utils/nonce-provider.ts'
import { makeTimings, time } from './utils/timing.server.ts'
import { combineServerTimings, makeTimings, time } from './utils/timing.server.ts'
import { combineHeaders, getDomainUrl } from './utils/misc.tsx'
// import { csrf } from './utils/csrf.server.ts'
import { getEnv } from './utils/env.server.ts'
// Hints may not be required. Double check.
import { getHints } from './utils/client-hints.tsx'
import { WeatherExample } from './components/WeatherExample.tsx'
import { Weather } from './WeatherExample.js'
import { getUserId } from './utils/auth.server.ts'
import { prisma } from './utils/db.server.ts'
import { csrf } from './utils/csrf.server.ts'
import { honeypot } from './utils/honeypot.server.ts'

export const links: LinksFunction = () => {
return [
Expand Down Expand Up @@ -76,8 +78,8 @@
{ timings, type: 'find user', desc: 'find user in root' },
)
: null
// const honeyProps = honeypot.getInputProps()
// const [csrfToken, csrfCookieHeader] = await csrf.commitToken()
const honeyProps = honeypot.getInputProps()
const [csrfToken, csrfCookieHeader] = await csrf.commitToken()
// Weather station data
const w_href: string =
'https://archive-api.open-meteo.com/v1/archive?latitude=52.52&longitude=13.41&daily=temperature_2m_max&timezone=America%2FNew_York&start_date=2022-01-01&end_date=2023-08-30&temperature_unit=fahrenheit'
Expand All @@ -89,24 +91,35 @@
weather: weather,
user: user,
requestInfo: {
/* hints may not be absolutely required, double check */
hints: getHints(request),
origin: getDomainUrl(request),
path: new URL(request.url).pathname,
userPrefs: {},
},
ENV: getEnv(),
// honeyProps,
// csrfToken,
honeyProps,
csrfToken,
},
{
headers: combineHeaders(
{ 'Server-Timing': timings.toString() },
// csrfCookieHeader ? { 'set-cookie': csrfCookieHeader } : null,
csrfCookieHeader ? { 'set-cookie': csrfCookieHeader } : null,
),
},
)
}

/**
* Step 4 of making Server Timings
* https://github.com/epicweb-dev/epic-stack/blob/main/docs/server-timing.md
*/
export const headers: HeadersFunction = ({ loaderHeaders, parentHeaders }) => {
return {
'Server-Timing': combineServerTimings(parentHeaders, loaderHeaders),
}
}

export default function HeatStack({ env = {} }) {
const nonce = useNonce()
return (
Expand All @@ -124,7 +137,6 @@
__html: `window.ENV = ${JSON.stringify(env)}`,
}}
/>
<div>left{nonce}right</div>
<Scripts nonce={nonce} />
</body>
</html>
Expand Down
Loading
Loading