Skip to content
Open
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
354 changes: 41 additions & 313 deletions deno.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion packages/web/adapter/lib/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

"imports": {
"@opentelemetry/api": "npm:@opentelemetry/api@1.9.0",
"@andykais/ts-rpc": "jsr:@andykais/ts-rpc@^0.2.2",
"@std/http/file-server": "jsr:@std/http@0.224.5/file-server",
"svelte": "npm:svelte@~5.39.8"

Expand Down
1 change: 0 additions & 1 deletion packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
},
"dependencies": {
"@andykais/ts-rpc": "npm:@jsr/andykais__ts-rpc@^0.2.4",
"@torm/sqlite": "npm:@jsr/torm__sqlite@^1.9.7",
"@opentelemetry/api": "1.9.0"
},
Expand Down
37 changes: 1 addition & 36 deletions packages/web/src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,6 @@
import * as sveltekit from '@sveltejs/kit'
import { Forager } from '@forager/core'
import { env } from '$env/dynamic/private'
import { dev, building } from '$app/environment'
import { type Config, load_config, PackagesConfig } from '$lib/server/config.ts'
import { trace } from "@opentelemetry/api"


let forager: Forager
let config: Config

if (!building) {
if (dev) {
if (env.FORAGER_CONFIG) {
// TODO make this dev-only
config = await load_config(env.FORAGER_CONFIG)
if (config.web.editing) {
config.core.editing = config.web.editing
}
forager = new Forager(config.core)
} else {
config = PackagesConfig.parse({
core: {database: {folder: 'database'}, thumbnail_folder: 'thumbnails', logger: {level: 'INFO'}},
web: {asset_folder: 'static_assets', logger: {level: 'INFO'}}
})
forager = new Forager(config.core)
}

forager.init()
} else {
if (env.FORAGER_INSTANCE) {
forager = env.FORAGER_INSTANCE
config = env.FORAGER_CONFIG
} else {
throw new Error(`FORAGER_INSTANCE must be passed to sveltekit hooks`)
}
}
}
import {forager, config} from '$lib/api/backend.ts'

export const handle: sveltekit.Handle = async ({ event, resolve }) => {
const span = trace.getActiveSpan()
Expand Down
35 changes: 0 additions & 35 deletions packages/web/src/lib/api.ts

This file was deleted.

50 changes: 50 additions & 0 deletions packages/web/src/lib/api/backend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as svelte_server from '$app/server';
import { Forager } from '@forager/core'
import { env } from '$env/dynamic/private'
import { dev, building } from '$app/environment'
import { type Config, load_config, PackagesConfig } from '$lib/server/config.ts'


let forager: Forager
let config: Config

if (!building) {
if (dev) {
if (env.FORAGER_CONFIG) {
// TODO make this dev-only
config = await load_config(env.FORAGER_CONFIG)
if (config.web.editing) {
config.core.editing = config.web.editing
}
forager = new Forager(config.core)
} else {
config = PackagesConfig.parse({
core: {database: {folder: 'database'}, thumbnail_folder: 'thumbnails', logger: {level: 'INFO'}},
web: {asset_folder: 'static_assets', logger: {level: 'INFO'}}
})
forager = new Forager(config.core)
}

forager.init()
} else {
if (env.FORAGER_INSTANCE) {
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`)
}
}
}

export const query = <Params extends unknown[], Return>(fn: (...args: Params) => Return) => {
const fn_wrappped = (arg_list: Params): Return => {
return fn(...arg_list)
}
return svelte_server.query('unchecked', fn_wrappped)
}


export {
forager,
config
}
27 changes: 27 additions & 0 deletions packages/web/src/lib/api/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as media from '$lib/api/remote_functions/media.remote.ts'
import * as tag from '$lib/api/remote_functions/tag.remote.ts'
import * as views from '$lib/api/remote_functions/views.remote.ts'

const wrap_args = <Params extends unknown[], Return>(fn: (params: Params) => Return): (...args: Params) => Return => {
return (...args: Params): Return => {
return fn(args)
}
}

export const forager = {
media: {
search: wrap_args(media.search),
group: wrap_args(media.group),
update: wrap_args(media.update),
get: wrap_args(media.get),
create: wrap_args(media.create),
upsert: wrap_args(media.upsert),
},
tag: {
search: wrap_args(tag.search),
},
views: {
start: wrap_args(views.start),
update: wrap_args(views.update),
},
}
9 changes: 9 additions & 0 deletions packages/web/src/lib/api/remote_functions/media.remote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {forager, query} from '$lib/api/backend.ts'

export const search = query(forager.media.search)
export const group = query(forager.media.group)
export const update = query(forager.media.update)
export const get = query(forager.media.get)
export const create = query(forager.media.create)
export const upsert = query(forager.media.upsert)
// export delete = query(forager.media.delete) // NOTE we cannot name functions delete :(
3 changes: 3 additions & 0 deletions packages/web/src/lib/api/remote_functions/tag.remote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import {forager, query} from '$lib/api/backend.ts'

export const search = query(forager.tag.search)
4 changes: 4 additions & 0 deletions packages/web/src/lib/api/remote_functions/views.remote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {forager, query} from '$lib/api/backend.ts'

export const start = query(forager.views.start)
export const update = query(forager.views.update)
5 changes: 0 additions & 5 deletions packages/web/src/lib/base_controller.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import * as svelte from 'svelte'
import type {ApiSpec} from '$lib/api.ts'
import * as rpc from '@andykais/ts-rpc/client.ts'
import type { Config } from '$lib/server/config.ts'
import {create_focuser, SettingsRune} from '$lib/runes/index.ts'
import {Keybinds} from '$lib/keybinds.ts'


abstract class BaseController {
client: ReturnType<typeof rpc.create<ApiSpec>>
keybinds: Keybinds
#config: Config | undefined

Expand All @@ -18,7 +14,6 @@ abstract class BaseController {

constructor(config: Config) {
this.#config = config
this.client = rpc.create<ApiSpec>(`${window.location.protocol}${window.location.host}/rpc/:signature`)
this.keybinds = new Keybinds(config)
}

Expand Down
3 changes: 2 additions & 1 deletion packages/web/src/lib/components/TagAutoCompleteInput.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import * as parsers from '$lib/parsers.ts'
import {forager} from '$lib/api/client'
import type { Forager } from '@forager/core'
import type { BaseController } from "$lib/base_controller.ts";
import Tag from '$lib/components/Tag.svelte'
Expand Down Expand Up @@ -50,7 +51,7 @@
if (contextual_query) {
search_options.contextual_query = contextual_query
}
const tags = await controller.client.forager.tag.search(search_options)
const tags = await forager.tag.search(search_options)
input_state.suggestion_buttons = Array(tags.results.length).fill(null)
this.state = tags.results
}
Expand Down
15 changes: 10 additions & 5 deletions packages/web/src/lib/runes/media_list_rune.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Rune} from '$lib/runes/rune.ts'
import type { Forager, MediaResponse, outputs } from '@forager/core'
import { MediaViewRune } from '.'
import {forager} from '$lib/api/client'
import { MediaViewRune } from './media_view_rune.svelte.ts'


type Result =
Expand Down Expand Up @@ -79,20 +80,24 @@ export class MediaListRune extends Rune {
}

const params_type = params?.type ?? this.#saved_params_type
if (params_type === 'filesystem') {
throw new Error('unimplemented for filesystem queries')
}

this.#saved_params_type = params_type
let content: Result
if (params_type === 'media') {
content = await this.client.forager.media.search(fetch_params)
content = await forager.media.search(fetch_params as SearchInput['params'])
}
else if (params_type === 'group_by') {
fetch_params.limit = fetch_params.limit ?? 30
content = await this.client.forager.media.group(fetch_params)
content = await forager.media.group(fetch_params)
} else {
throw new Error('unimplemented')
}

const results = content.results.map(result => {
return MediaViewRune.create(this.client, result, fetch_params)
return MediaViewRune.create(result, fetch_params)
})

this.#cursor = content.cursor
Expand Down Expand Up @@ -120,7 +125,7 @@ export class MediaListRune extends Rune {
return
}

const content = await this.client.forager.tag.search({
const content = await forager.tag.search({
contextual_query: params.params?.query
})
console.log(content)
Expand Down
27 changes: 14 additions & 13 deletions packages/web/src/lib/runes/media_view_rune.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Rune} from '$lib/runes/rune.ts'
import {forager} from '$lib/api/client.ts'
import type { BaseController } from '$lib/base_controller.ts'
import type { MediaResponse, inputs, type model_types } from '@forager/core'

Expand All @@ -16,8 +17,8 @@ export class MediaViewRune extends Rune {
state = $state<State>()
current_view: model_types.View

protected constructor(client: BaseController['client'], media_response: MediaResponse) {
super(client)
protected constructor(media_response: MediaResponse) {
super()
this.state = {
media: media_response,
full_thumbnails: undefined
Expand Down Expand Up @@ -57,7 +58,7 @@ export class MediaViewRune extends Rune {
}

public async star(stars: number) {
const updated = await this.client.forager.media.update(
const updated = await forager.media.update(
this.media_reference.id,
{stars}
)
Expand All @@ -70,19 +71,19 @@ export class MediaViewRune extends Rune {

public async add_view() {
// TODO track view and update it as a video loops, or as an image has stayed open for a while
const view_response = await this.client.forager.views.start({media_reference_id: this.media_reference.id })
const view_response = await forager.views.start({media_reference_id: this.media_reference.id })
this.current_view = view_response.view
console.log('setting view count to ', view_response.media_reference.view_count)
this.state.media.media_reference.view_count = view_response.media_reference.view_count
}

static create(client: BaseController['client'], media_response: MediaResponse, search_params: SearchParams) {
static create(media_response: MediaResponse, search_params: SearchParams) {
if (media_response.media_type === 'media_file') {
return new MediaFileRune(client, media_response)
return new MediaFileRune(media_response)
} else if (media_response.media_type === 'media_series') {
return new MediaSeriesRune(client, media_response)
return new MediaSeriesRune(media_response)
} else if (media_response.media_type === 'grouped') {
return new MediaGroupRune(client, media_response, search_params)
return new MediaGroupRune(media_response, search_params)
} else {
throw new Error(`Unexpected media_response ${JSON.stringify(media_response)}`)
}
Expand All @@ -99,7 +100,7 @@ export class MediaFileRune extends MediaViewRune {
media_type = 'media_file' as const satisfies MediaResponse['media_type']

public override async update(media_info: inputs.MediaInfo, tags: inputs.MediaReferenceUpdateTags) {
const updated = await this.client.forager.media.update(
const updated = await forager.media.update(
this.media_reference.id,
media_info,
tags
Expand All @@ -109,7 +110,7 @@ export class MediaFileRune extends MediaViewRune {

public override async load_detailed_view() {
if (this.state!.full_thumbnails) return
const result = await this.client.forager.media.get({media_reference_id: this.media_reference.id })
const result = await forager.media.get({media_reference_id: this.media_reference.id })
this.state!.full_thumbnails = result.thumbnails
}

Expand Down Expand Up @@ -152,9 +153,9 @@ export class MediaGroupRune extends MediaViewRune {
media_list: []
})

protected constructor(client: BaseController['client'], media_response: MediaResponse, search_params: SearchParams) {
public constructor(media_response: MediaResponse, search_params: SearchParams) {
// debugger
super(client, media_response)
super(media_response)

const {group_by, cursor, ...merged_search_params} = search_params

Expand All @@ -173,7 +174,7 @@ export class MediaGroupRune extends MediaViewRune {
throw new Error(`unexpected search group`)
}

this.client.forager.media.search(merged_search_params)
forager.media.search(merged_search_params)
.then((result: {}) => {
this.grouped_state.media_list = result.results
})
Expand Down
4 changes: 1 addition & 3 deletions packages/web/src/lib/runes/rune.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import type { BaseController } from '$lib/base_controller.ts'

export class Rune {
public constructor(protected client: BaseController['client']) {}
public constructor() {}
}

5 changes: 2 additions & 3 deletions packages/web/src/lib/runes/settings_rune.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Config } from '$lib/server/config.ts'
import { Rune } from './rune';
import type { BaseController } from '$lib/base_controller.ts'

interface MutatableSettings {
'ui.media_list.thumbnail_size': Config['web']['ui_defaults']['media_list']['thumbnail_size']
Expand All @@ -11,8 +10,8 @@ interface MutatableSettings {
export class SettingsRune extends Rune {
#state = $state<Config>({} as Config);

constructor(client: BaseController['client'], config: Config) {
super(client)
constructor(config: Config) {
super()
this.#state = config
}

Expand Down
Loading
Loading