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

utilize more types in LFNext #1664

Merged
merged 61 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
e437c5d
corrected file extension
Dec 8, 2022
851687f
typed sf call
Dec 9, 2022
b250349
missed a possibility
Dec 9, 2022
be97967
typed the activities api
Dec 9, 2022
e6aed83
cleaned up some param syntax
Dec 9, 2022
b7b40ec
Merge branch 'develop' into chore/types
Dec 13, 2022
1a48cba
Merge branch 'develop' into chore/types
Dec 21, 2022
b06a2f9
changed extensions for TS
Dec 21, 2022
a65686c
upgraded more deps
Dec 21, 2022
eb03cef
resolved ts warning
Dec 21, 2022
0610f49
preferring type over interface
Dec 21, 2022
658dc7a
type the event
Dec 21, 2022
db04118
class attr not needed at this point
Dec 21, 2022
872c9db
class attr not needed
Dec 21, 2022
c0f60f1
cleaned up sf wrapper
Dec 21, 2022
8af30c1
tried different typing approach
Dec 21, 2022
14a5e22
typed dashboard page
Dec 21, 2022
1025ae0
renamed result
Dec 21, 2022
7d85c9a
typed some of the dashboard code
Dec 22, 2022
a029d7b
fixed some "undefined" classes showing up in final HTML
Dec 22, 2022
ac5cc79
gave up on correcting this ts error
Dec 22, 2022
5e96bb4
typed the Input comp
Dec 22, 2022
411f350
didn't want playground to autoscroll to the focused input
Dec 22, 2022
ab8a30e
typed sf calls
Dec 22, 2022
22b01b7
typed Progress comp
Dec 22, 2022
67f89a5
typed client-side fetch normalizer
Dec 23, 2022
1d35ae7
removed tsc warning
Dec 23, 2022
0c5a75f
addressed tsc warning
Dec 23, 2022
0d2151a
type the Sf response
Dec 23, 2022
26a3e2d
resolved some tsc warnings
Dec 23, 2022
45a6f87
addressed some type hints
Dec 23, 2022
4e208e2
typed user call
Dec 23, 2022
9f4a8fc
typed project details call a little more
Dec 23, 2022
7bfcb3b
addressed a couple more type warnings
Dec 23, 2022
1a8f9fe
consistent convention
Dec 24, 2022
9741324
typed some transforms
Dec 24, 2022
6b0b3d8
consistent convention
Dec 24, 2022
815c0c6
Merge branch 'develop' into chore/types
Dec 24, 2022
b821149
Merge branch 'develop' into chore/types
Jan 3, 2023
d6448da
Merge branch 'develop' into chore/types
Jan 4, 2023
02061b4
incorporated PR feedback
Jan 4, 2023
c5323cc
incorporated PR feedback
Jan 4, 2023
31d2e35
incorporated PR feedback
Jan 4, 2023
684a7f1
incorporated PR feedback
Jan 4, 2023
4ee2094
incorporated PR feedback
Jan 4, 2023
9f1fce8
Merge branch 'develop' into chore/types
Jan 5, 2023
fccc305
simplified audio/picture detection algorithm
Jan 5, 2023
cc966de
incorporated PR feedback
Jan 5, 2023
20f57f6
eliminated use of types.d.ts files
Jan 6, 2023
c2d0749
Merge branch 'develop' into chore/types
Jan 6, 2023
5123da7
Merge branch 'develop' into chore/types
Jan 6, 2023
00f3bf6
updated deps
Jan 6, 2023
d7ecf3b
incorporated PR feedback
Jan 9, 2023
d6dac14
incorporated PR feedback
Jan 9, 2023
31338f2
eliminated remaining `svelte check` warnings
Jan 9, 2023
3046119
accepted PR suggestion
Jan 9, 2023
3e02ce2
incorporated PR feedback
Jan 9, 2023
85cef15
accepted PR suggestion
Jan 9, 2023
c3b7322
incorporated PR feedback
Jan 9, 2023
e45a2d2
simplified error handling
Jan 9, 2023
776d44c
Merge branch 'develop' into chore/types
Jan 9, 2023
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
4 changes: 1 addition & 3 deletions next-app/README-Tech.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,11 @@ Of course choosing tailwindcss comes with a number of criticisms but we believe
1. The codebase can be kept free of class clutter by simply utlizing `@apply` in the `<style>` section of our `.svelte` files but when doing this a couple of things need to be taken into consideration:
> modifiers are not supported in `@apply` without additional `preprocess` and `postcss` configuration and increased specificity can sometimes cause problems when class overrides are needed on an element directly.
> modifiers are not supported in `@apply` without additional `preprocess` and `postcss` configuration and increased specificity can sometimes cause problems when class overrides are needed on an element directly. See [Warn: Unused CSS selector](https://github.com/saadeghi/daisyui/discussions/1490) for some elaboration. We do still use the `@apply` in a component but not scoped, simply for an organizational benefit, see `/next-app/src/lib/forms/Form.svelte`
2. We will inevitably have situations where parent components or views will want to pass styles down to children. This is very common and requires writing global classes anyway. Using something like tailwindcss or bootstrap takes all of that work off of our plate. Unused CSS will still get purged by the compiler so the app doesn't take on unnecessary bloat.
3. daisyUI is built upon tailwindcss anyway so we benefit from using it in both situations.
[ ] Confirm no additional configuration is required to purge unused CSS.
#### daisyUI
With such a small team, we were always going to need a well thought-out UI library to keep us from having to make a bunch of design decisions along the way. While there are a handful of Svelte-based libraries, none of them met the criteria necessary to help make our team as efficient as possible. There were many mature UI systems already in place built upon tailwindcss and daisyUI represents one of the best of the ones we looked at in it's goal of further simplifying the use of tailwindcss. Additionally, daisyUI has already integrated many best practices and opinions in its design decisions.
Expand Down
691 changes: 324 additions & 367 deletions next-app/package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions next-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
"clean": "rimraf .svelte-kit build node_modules && echo '🔔 reminder: you will need to reinstall deps, `npm i`'"
},
"devDependencies": {
"@sveltejs/adapter-node": "next",
"@sveltejs/kit": "next",
"@sveltejs/adapter-node": "^1",
"@sveltejs/kit": "^1",
"@tailwindcss/typography": "^0.5.2",
"autoprefixer": "^10",
"daisyui": "^2",
"rimraf": "^3",
"svelte": "^3",
"svelte-check": "^2",
"tailwindcss": "^3.0.23",
"tailwindcss": "^3",
"tslib": "^2",
"typescript": "^4",
"vite": "^4"
Expand Down
4 changes: 2 additions & 2 deletions next-app/src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
<body data-sveltekit-preload-data=hover>
<div style='display: contents'>%sveltekit.body%</div>
</body>
</html>
2 changes: 1 addition & 1 deletion next-app/src/lib/PageHeader.svelte
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<h1 class='text-2xl md:text-3xl { $$props.class }'>
<h1 class='text-2xl md:text-3xl'>
<slot />
</h1>
43 changes: 43 additions & 0 deletions next-app/src/lib/Stats.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script lang=ts>
import { goto } from '$app/navigation'
type Stat = {
title: string,
value?: number,
icon?: ConstructorOfATypedSvelteComponent,
url?: string | URL,
}
export let stats: Stat[]
$: _stats = stats.map(({ title, value, icon, url }) => ({
title,
value,
icon,
href: value ? url : ''
}))
const clicked = (href: string | URL = '') => href ? goto(href) : {}
</script>

<!-- https://daisyui.com/components/stat/ -->
<dl class='stats shadow max-w-full'> <!-- added max-w-full so a horiz scroll will appear on small screens rather than stretching the whole doc -->
{#each _stats as { title, value, icon, href }}
<div class='stat place-items-center' class:href on:click={ () => clicked(href) } on:keydown={ () => clicked(href) }>
<dt class=stat-title>{ title }</dt>
<dd class='stat-value text-primary'>{ Number(value).toLocaleString() }</dd>

{#if icon}
<div class='stat-figure text-primary pl-4'>
<svelte:component this={icon} />
</div>
{/if}
</div>
{/each}
</dl>

<style>
.href {
cursor: pointer;
}
</style>
22 changes: 4 additions & 18 deletions next-app/src/lib/error/index.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
import { browser } from '$app/environment'
import { writable, type Writable } from 'svelte/store'

interface LfError {
message: string,
code?: number,
}
export const error: Writable<LfError> = writable({ message: '' })

export function throw_error(message: string, code: number = 0) {
throw set({ message, code })
}
export const error: Writable<Error> = writable(Error())

export const dismiss = set
export const dismiss = () => error.set(Error())

if (browser) {
// https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror#window.addEventListenererror
window.addEventListener('error', (event: ErrorEvent) => set(event.error))
window.addEventListener('error', (event: ErrorEvent) => error.set(event.error))

// https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
window.onunhandledrejection = (event: PromiseRejectionEvent) => set(event.reason)
}

function set({ message, code = 0 }: LfError) {
error.set({ code, message })

return { code, message }
window.onunhandledrejection = (event: PromiseRejectionEvent) => error.set(event.reason)
}
51 changes: 20 additions & 31 deletions next-app/src/lib/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,37 @@
import { throw_error } from '$lib/error'
import { start, stop } from '$lib/progress'
import type { HttpMethod } from '@sveltejs/kit/types/private'

export async function CREATE(url, body) { return await custom_fetch('post' , url, body) }
export async function GET (url ) { return await custom_fetch('get' , url ) }
export async function UPDATE(url, body) { return await custom_fetch('put' , url, body) }
export async function DELETE(url ) { return await custom_fetch('delete', url ) }
type FetchArgs = {
myieye marked this conversation as resolved.
Show resolved Hide resolved
url: string,
body?: object,
}
interface AdaptedFetchArgs extends FetchArgs {
method: HttpMethod,
}

// https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData
// export const upload = async formData => await CREATE('post', formData)
export async function CREATE({url, body}: FetchArgs) { return await adapted_fetch({method: 'POST' , url, body}) }
export async function GET ({url }: FetchArgs) { return await adapted_fetch({method: 'GET' , url }) }
export async function UPDATE({url, body}: FetchArgs) { return await adapted_fetch({method: 'PUT' , url, body}) }
export async function DELETE({url }: FetchArgs) { return await adapted_fetch({method: 'DELETE', url }) }

// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Supplying_request_options
async function custom_fetch(method, url, body) {
const headers = {
'content-type': 'application/json',
}

// when dealing with FormData, i.e., when uploading files, allow the browser to set the request up
// so boundary information is built properly.
if (body instanceof FormData) {
delete headers['content-type']
} else {
body = JSON.stringify(body)
}

async function adapted_fetch({method, url, body}: AdaptedFetchArgs) {
start(url)
const response = await fetch(url, {

const response: Response = await fetch(url, {
hahn-kev marked this conversation as resolved.
Show resolved Hide resolved
method,
headers,
body,
headers: {
'content-type': 'application/json',
},
body: JSON.stringify(body),
})
.catch (throw_error) // these only occur for network errors, like these:
// * request made with a bad host, e.g., //httpbin
// * the host is refusing connections
// * client is offline, i.e., airplane mode or something
// * CORS preflight failures
.finally(() => stop(url))

// reminder: fetch does not throw exceptions for non-200 responses (https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch)
if (! response.ok) {
const results = await response.json().catch(() => {}) || {}

const message = results.message || response.statusText

throw_error(message, response.status)
throw Error(results.message || response.statusText)
}

return await response.json()
Expand Down
11 changes: 4 additions & 7 deletions next-app/src/lib/forms/Button.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
<script>
export let danger = false
export {clazz as class}

let clazz = ''
</script>

<!-- https://daisyui.com/components/button -->
<button on:click class:danger class='btn btn-primary { $$props.class }'>
<button on:click class:btn-error={danger} class='btn btn-primary { clazz }'>
<slot />
</button>

<style>
.danger { @apply
btn-error;
}
</style>
2 changes: 1 addition & 1 deletion next-app/src/lib/forms/Form.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<slot />
</form>

<style>
<style lang=postcss>
:global(form > input) { @apply
mb-6;
}
Expand Down
8 changes: 4 additions & 4 deletions next-app/src/lib/forms/Input.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script>
<script lang=ts>
import { onMount } from 'svelte'
export let label = ''
Expand All @@ -8,7 +8,7 @@
export let autofocus = false
let id = randomId()
let input = {}
let input: HTMLInputElement
onMount(autofocusIfRequested)
Expand All @@ -17,11 +17,11 @@
}
function autofocusIfRequested() {
autofocus && input.focus()
autofocus && input?.focus()
}
// works around "svelte(invalid-type)" warning, i.e., can't have a dynamic type AND bind:value...keep an eye on https://github.com/sveltejs/svelte/issues/3921
function typeWorkaround(node) {
function typeWorkaround(node: HTMLInputElement) {
node.type = type
}
</script>
Expand Down
13 changes: 7 additions & 6 deletions next-app/src/lib/progress/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { writable } from 'svelte/store'
import { writable, type Writable } from 'svelte/store'

export const loading = writable(false)
export const loading: Writable<boolean> = writable(false)

const pending = []
type Id = string | number
const pending: Id[] = []

export function start(id) {
export function start(id: Id) {
loading.set(true)

pending.push(id)
}

export function stop(id) {
const i = pending.findIndex(anId => anId === id)
export function stop(id: Id) {
const i = pending.findIndex(_id => _id === id)

if (i >= 0) {
pending.splice(i,1)
Expand Down
45 changes: 26 additions & 19 deletions next-app/src/lib/server/sf.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import { error } from '@sveltejs/kit'
import type { HttpMethod } from '@sveltejs/kit/types/private'

/**
*
* @typedef RPC
* @type {object}
* @property {string} name Name of the remote procedure to call
* @property {string[]} [args] Arguments to pass to the remote procedure
* @property {string} [cookie] https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
*
* @param { RPC } rpc
*/
export async function sf(rpc) {
const { name, args = [], cookie } = rpc
export type Rpc = {
myieye marked this conversation as resolved.
Show resolved Hide resolved
name: string,
args?: string[] | object[],
myieye marked this conversation as resolved.
Show resolved Hide resolved
cookie?: string,
}

type FetchArgs = {
url: string,
method: HttpMethod,
body: object,
cookie?: string,
}

type SfResponse = {
error?: {
message: string
},
result?: any,
}

export async function sf<T>({name, args = [], cookie = ''}: Rpc): Promise<T> {
const body = {
id: Date.now(),
method: name,
Expand All @@ -21,7 +30,7 @@ export async function sf(rpc) {
},
}

const results = await custom_fetch(`${process.env.API_HOST}/api/sf`, 'post', body, cookie)
const results = await adapted_fetch({url: `${process.env.API_HOST}/api/sf`, method: 'POST', body, cookie})

if (results.error) {
console.log('lib/server/sf.ts.sf results.error: ', {results})
Expand All @@ -36,27 +45,25 @@ export async function sf(rpc) {
return results.result
}

async function custom_fetch(url, method, body, cookie) {
const bodyAsJSON = JSON.stringify(body)

async function adapted_fetch({url, method, body, cookie = ''}: FetchArgs): Promise<SfResponse> {
// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Supplying_request_options
const response: Response = await fetch(url, {
method,
headers: {
'content-type': 'application/json',
cookie,
},
body: bodyAsJSON,
body: JSON.stringify(body),
}).catch(e => {
// these only occur for network errors, like these:
// request made with a bad host, e.g., //httpbin
// the host is refusing connections
console.log(`lib/server/sf.ts.custom_fetch caught error on ${url}=>${bodyAsJSON}: `, {e})
console.log(`lib/server/sf.ts.adapted_fetch caught error on ${url}: `, {body}, {e})
throw error(500, 'NETWORK ERROR with legacy app')
})

if (! response.ok) {
console.log(`lib/server/sf.ts.custom_fetch response !ok ${url}=>${bodyAsJSON}: `, await response.text())
console.log(`lib/server/sf.ts.adapted_fetch response !ok ${url}: `, {body}, await response.text())
throw error(response.status, response.statusText)
}

Expand Down
14 changes: 12 additions & 2 deletions next-app/src/lib/server/user.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { error } from '@sveltejs/kit'
import { sf } from '$lib/server/sf'

export async function fetch_current_user(cookie) {
const { userId, userProjectRole } = await sf({
type LegacySession = {
userId: string,
userProjectRole: string,
}

type User = {
id: string,
role: string,
}

export async function fetch_current_user(cookie: string): Promise<User> {
const { userId, userProjectRole }: LegacySession = await sf({
name: 'session_getSessionData',
cookie,
})
Expand Down
Loading