Skip to content
Draft
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
6 changes: 3 additions & 3 deletions .github/workflows/web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ jobs:
# - name: Lint
# run: deno task lint

# - name: Typecheck
# run: deno task check

# package.json based projects need to run deno install step
- name: Install Dependencies
run: deno install --allow-scripts

- name: Typecheck
run: deno task check

- name: Build
run: deno task build

Expand Down
94 changes: 89 additions & 5 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion packages/core/src/lib/file_processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,12 @@ class FileProcessor {
}

async * #readlines(stream: ReadableStream<Uint8Array>) {
const reader = stream.pipeThrough(new TextDecoderStream()).getReader()
// TextDecoderStream types its writable side as WritableStream<BufferSource>, which
// TypeScript's DOM lib does not treat as assignable to the WritableStream<Uint8Array>
// that pipeThrough infers. The pairing is valid at runtime (a Uint8Array is a
// BufferSource), so bridge the lib-level mismatch explicitly.
const decoder = new TextDecoderStream() as ReadableWritablePair<string, Uint8Array>
const reader = stream.pipeThrough(decoder).getReader()
let buffer = ''
let read_result = await reader.read()
while (!read_result.done) {
Expand Down
16 changes: 13 additions & 3 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,29 @@
"build": "vite build",
"build:local": "LOCAL_BUILD=true vite build",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.svelte.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.svelte.json --watch"
},
"dependencies": {
"@andykais/ts-rpc": "npm:@jsr/andykais__ts-rpc@^0.2.4",
"@opentelemetry/api": "1.9.0",
"@torm/sqlite": "npm:@jsr/torm__sqlite@^1.9.7"
"@std/datetime": "npm:@jsr/std__datetime@^0.225.3",
"@std/fmt": "npm:@jsr/std__fmt@0.225.6",
"@std/fs": "npm:@jsr/std__fs@0.229.3",
"@std/log": "npm:@jsr/std__log@^0.224.6",
"@std/media-types": "npm:@jsr/std__media-types@0.224.0",
"@std/path": "npm:@jsr/std__path@1.0.3",
"@std/yaml": "npm:@jsr/std__yaml@^1.0.5",
"@torm/sqlite": "npm:@jsr/torm__sqlite@^1.9.7",
"ts-pattern": "npm:ts-pattern@5.2.0",
"zod": "npm:zod@4.1.11"
},
"devDependencies": {
"@deno/vite-plugin": "1.0.6",
"@sveltejs/kit": "2.43.7",
"@sveltejs/vite-plugin-svelte": "6.2.1",
"@tailwindcss/vite": "4.1.14",
"@types/deno": "^2.5.0",
"svelte": "5.39.8",
"svelte-check": "4.3.2",
"tailwindcss": "4.1.14",
Expand Down
8 changes: 7 additions & 1 deletion packages/web/src/app.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
import type { Forager } from '@forager/core'
import type { Config } from '$lib/server/config.ts'

declare global {
namespace App {
// interface Error {}
// interface Locals {}
interface Locals {
forager: Forager
config: Config
}
// interface PageData {}
// interface PageState {}
// interface Platform {}
Expand Down
6 changes: 4 additions & 2 deletions packages/web/src/hooks.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ if (!building) {
forager.init()
} else {
if (env.FORAGER_INSTANCE) {
forager = env.FORAGER_INSTANCE
config = env.FORAGER_CONFIG
// In production the CLI injects a live Forager instance and parsed config
// through these env slots, so they are not the plain strings $env types them as.
forager = env.FORAGER_INSTANCE as unknown as Forager
config = env.FORAGER_CONFIG as unknown as Config
} else {
throw new Error(`FORAGER_INSTANCE must be passed to sveltekit hooks`)
}
Expand Down
18 changes: 11 additions & 7 deletions packages/web/src/lib/actions/focusable.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
export function focusable(node: HTMLElement) {
export function focusable(node: HTMLElement, focused: boolean) {
const apply = (should_focus: boolean) => {
if (should_focus) {
node.focus()
} else {
node.blur()
}
}
apply(focused)
return {
update(focused: boolean) {
if (focused) {
node.focus()
} else {
node.blur()
}
update(should_focus: boolean) {
apply(should_focus)
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/lib/actions/scrollable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function scrollable(node: HTMLElement) {
export function scrollable(node: HTMLElement, _focused: boolean) {
let is_visible = false
const observer = new IntersectionObserver((entries) => {
is_visible = entries[0].isIntersecting
Expand Down
32 changes: 29 additions & 3 deletions packages/web/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,37 @@ class ForagerTagApi extends rpc.ApiController<Context> {
parent_delete = this.context.forager.tag.parent_delete
}

class ForagerMediaApi extends rpc.ApiController<Context> {
create = this.context.forager.media.create
update = this.context.forager.media.update
upsert = this.context.forager.media.upsert
delete = this.context.forager.media.delete
search = this.context.forager.media.search
group = this.context.forager.media.group
get = this.context.forager.media.get
thumbnail = this.context.forager.media.thumbnail
reload = this.context.forager.media.reload
}

class ForagerSeriesApi extends rpc.ApiController<Context> {
create = this.context.forager.series.create
update = this.context.forager.series.update
upsert = this.context.forager.series.upsert
add = this.context.forager.series.add
get = this.context.forager.series.get
search = this.context.forager.series.search
}

class ForagerViewsApi extends rpc.ApiController<Context> {
start = this.context.forager.views.start
update = this.context.forager.views.update
}

class ForagerApi extends rpc.ApiController<Context> {
media = this.context.forager.media
series = this.context.forager.series
media = this.module(ForagerMediaApi)
series = this.module(ForagerSeriesApi)
tag = this.module(ForagerTagApi)
views = this.context.forager.views
views = this.module(ForagerViewsApi)

}

Expand Down
2 changes: 0 additions & 2 deletions packages/web/src/lib/base_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ abstract class BaseController {
if (this.#config) return this.#config
else throw new Error(`Controller::config not initialized`)
}

abstract handlers: {}
}

export { BaseController }
1 change: 1 addition & 0 deletions packages/web/src/lib/components/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
...props
}: {
title: string
height?: number
children: SvelteHTMLElements['div']['children']
} = $props()

Expand Down
6 changes: 3 additions & 3 deletions packages/web/src/lib/components/SelectInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
value: string
}
interface Props {
label: string
options: SelectOption
label?: string
options: SelectOption[]
value: string
onchange: () => void | undefined
onchange?: (e: Event) => void
}
let {
label,
Expand Down
Loading