web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

commit 459f17a0cada4ad4fc8b8ebc8634da5b1455e678
parent 444e8ebea5ebb734bc43cb41e8faa3c9adf1ffc3
Author: triesap <triesap@radroots.dev>
Date:   Sun, 21 Dec 2025 01:35:41 +0000

client: standardized typed error resolves, broadened image upload mime support, and expanded database client imports for backups and relations

Diffstat:
Mclient/src/fs/types.ts | 5++++-
Mclient/src/fs/web.ts | 4++--
Mclient/src/notifications/web.ts | 2+-
Mclient/src/radroots/types.ts | 13++++++-------
Mclient/src/radroots/web.ts | 64+++++++++++++++++++++++++++++++---------------------------------
Mclient/src/tangle/web.ts | 32++++++++++++++++----------------
6 files changed, 60 insertions(+), 60 deletions(-)

diff --git a/client/src/fs/types.ts b/client/src/fs/types.ts @@ -11,9 +11,12 @@ export type IClientFsFileInfo = { createdAt?: number }; + +export type IClientFsReadBinResolve = ResolveError<Uint8Array> + export type IClientFs = { exists(path: string): Promise<ResolveError<boolean>>; open(path: string): Promise<ResolveError<IClientFsOpenResult>>; info(path: string): Promise<ResolveError<IClientFsFileInfo>>; - read_bin(path: string): Promise<ResolveError<Uint8Array>>; + read_bin(path: string): Promise<IClientFsReadBinResolve>; }; diff --git a/client/src/fs/web.ts b/client/src/fs/web.ts @@ -18,8 +18,8 @@ export class WebFs implements IClientFs { public async info(path: string) { try { const res = await fetch(path, { method: 'HEAD' }); - const sizeHeader = res.headers.get('Content-Length'); - const size = sizeHeader ? Number(sizeHeader) : 0; + const size_header = res.headers.get('Content-Length'); + const size = size_header ? Number(size_header) : 0; return { size, isFile: true, isDirectory: false }; } catch (e) { return handle_err(e); diff --git a/client/src/notifications/web.ts b/client/src/notifications/web.ts @@ -58,7 +58,7 @@ export class WebNotifications implements IClientNotifications { const input = document.createElement('input'); input.type = 'file'; input.multiple = true; - input.accept = 'image/png'; + input.accept = 'image/png,image/jpg'; input.onchange = () => { const files = input.files; if (!files) return resolve(undefined); diff --git a/client/src/radroots/types.ts b/client/src/radroots/types.ts @@ -1,5 +1,4 @@ -import type { IError } from "@radroots/types-bindings"; -import { type FilePath, type ResultObj, type ResultPass } from '@radroots/utils'; +import { MediaResource, ResolveErrorMsg, type ResultObj, type ResultPass } from '@radroots/utils'; export type IClientRadrootsAccountsRequestMessage = | string @@ -7,13 +6,13 @@ export type IClientRadrootsAccountsRequestMessage = | `*-registered`; export type IClientRadrootsAccountsRequest = { profile_name: string; secret_key: string; }; -export type IClientRadrootsAccountsRequestResolve = ResultObj<string> | IError<IClientRadrootsAccountsRequestMessage>; +export type IClientRadrootsAccountsRequestResolve = ResolveErrorMsg<ResultObj<string>, IClientRadrootsAccountsRequestMessage>; export type IClientRadrootsAccountsCreate = { tok: string; secret_key: string; }; -export type IClientRadrootsAccountsCreateResolve = ResultObj<string> | IError<IClientRadrootsAccountsRequestMessage>; +export type IClientRadrootsAccountsCreateResolve = ResolveErrorMsg<ResultObj<string>, IClientRadrootsAccountsRequestMessage>; export type IClientRadrootsAccountsActivate = { id: string; secret_key: string; }; -export type IClientRadrootsAccountsActivateResolve = ResultPass | IError<IClientRadrootsAccountsRequestMessage>; -export type IClientRadrootsMediaImageUpload = { file_path: FilePath; file_data: Uint8Array; secret_key: string; }; -export type IClientRadrootsMediaImageUploadResolve = any; +export type IClientRadrootsAccountsActivateResolve = ResolveErrorMsg<ResultPass, IClientRadrootsAccountsRequestMessage>; +export type IClientRadrootsMediaImageUpload = { mime_type?: string; file_data: Uint8Array; secret_key: string; }; +export type IClientRadrootsMediaImageUploadResolve = ResolveErrorMsg<MediaResource, IClientRadrootsAccountsRequestMessage>; export type IClientRadroots = { accounts_request: (opts: IClientRadrootsAccountsRequest) => Promise<IClientRadrootsAccountsRequestResolve>; diff --git a/client/src/radroots/web.ts b/client/src/radroots/web.ts @@ -1,4 +1,4 @@ -import { err_msg, type IHttpResponse, is_err_response, is_error_response } from '@radroots/utils'; +import { err_msg, type IHttpResponse, is_err_response, is_error_response, schema_media_resource } from '@radroots/utils'; import { lib_nostr_event_sign_attest } from '@radroots/utils-nostr'; import { WebHttp } from '../http/web.js'; import type { IClientRadroots, IClientRadrootsAccountsActivate, IClientRadrootsAccountsActivateResolve, IClientRadrootsAccountsCreate, IClientRadrootsAccountsCreateResolve, IClientRadrootsAccountsRequest, IClientRadrootsAccountsRequestResolve, IClientRadrootsMediaImageUpload, IClientRadrootsMediaImageUploadResolve } from "./types.js"; @@ -16,15 +16,15 @@ export class WebClientRadroots implements IClientRadroots { } private is_res_pass(res: IHttpResponse): boolean { - return res.data && res.data.pass === true + return res.data && res.data.pass === true; } private parse_res_field(field: unknown): string | undefined { - if (typeof field === `string` && field) return field + if (typeof field === `string` && field) return field; } private create_x_nostr_event(secret_key: string): string { - return JSON.stringify(lib_nostr_event_sign_attest(secret_key)) + return JSON.stringify(lib_nostr_event_sign_attest(secret_key)); } public accounts_request = async (opts: IClientRadrootsAccountsRequest): Promise<IClientRadrootsAccountsRequestResolve> => { @@ -36,14 +36,14 @@ export class WebClientRadroots implements IClientRadroots { "X-Nostr-Event": this.create_x_nostr_event(secret_key), }, data: { profile_name } - }) - if (is_err_response(res)) return res - if (is_error_response(res)) return err_msg(res.error) + }); + if (is_err_response(res)) return res; + if (is_error_response(res)) return err_msg(res.error); else if (this.is_res_pass(res)) { - const tok = this.parse_res_field(res.data.tok) - if (tok) return { result: tok } + const tok = this.parse_res_field(res.data.tok); + if (tok) return { result: tok }; } - return err_msg(`error.radroots.account_registered`) + return err_msg(`error.radroots.account_registered`); } public accounts_create = async (opts: IClientRadrootsAccountsCreate): Promise<IClientRadrootsAccountsCreateResolve> => { @@ -55,14 +55,14 @@ export class WebClientRadroots implements IClientRadroots { "X-Nostr-Event": this.create_x_nostr_event(secret_key), }, authorization: tok - }) - if (is_err_response(res)) return res - if (is_error_response(res)) return err_msg(res.error) + }); + if (is_err_response(res)) return res; + if (is_error_response(res)) return err_msg(res.error); else if (this.is_res_pass(res)) { - const id = this.parse_res_field(res.data.id) - if (id) return { result: id } + const id = this.parse_res_field(res.data.id); + if (id) return { result: id }; } - return err_msg(`error.client.request_failure`) + return err_msg(`error.client.request_failure`); } public accounts_activate = async (opts: IClientRadrootsAccountsActivate): Promise<IClientRadrootsAccountsActivateResolve> => { @@ -74,33 +74,31 @@ export class WebClientRadroots implements IClientRadroots { "X-Nostr-Event": this.create_x_nostr_event(secret_key), }, data: { id } - }) - if (is_err_response(res)) return res - if (is_error_response(res)) return err_msg(res.error) - else if (this.is_res_pass(res)) return { pass: true } - return err_msg(`error.client.request_failure`) + }); + if (is_err_response(res)) return res; + if (is_error_response(res)) return err_msg(res.error); + else if (this.is_res_pass(res)) return { pass: true }; + return err_msg(`error.client.request_failure`); } public media_image_upload = async (opts: IClientRadrootsMediaImageUpload): Promise<IClientRadrootsMediaImageUploadResolve> => { - const { file_path, file_data, secret_key } = opts + const { mime_type, file_data, secret_key } = opts const res = await this._http_client.fetch({ url: `${this._base_url}/v1/media/image/upload`, method: `put`, headers: { - "Content-Type": file_path.mime_type, + "Content-Type": mime_type || "image/png", "X-Nostr-Event": this.create_x_nostr_event(secret_key), }, data_bin: file_data - }) - if (is_err_response(res)) return res - if (is_error_response(res)) return err_msg(res.error) - else if ( - this.is_res_pass(res) && - typeof res.data.res_base === 'string' && - typeof res.data.res_path === 'string' - ) { - return { res_base: res.data.res_base, res_path: res.data.res_path } + }); + if (is_err_response(res)) return res; + if (is_error_response(res)) return err_msg(res.error); + else if (this.is_res_pass(res)) { + const res_data = schema_media_resource.safeParse(res.data); + console.log(`res_data `, res_data) + if (res_data.success && res_data.data) return res_data.data; } - return err_msg(`error.client.request_failure`) + return err_msg(`error.client.request_failure`); } } diff --git a/client/src/tangle/web.ts b/client/src/tangle/web.ts @@ -7,6 +7,8 @@ import type { IFarmFindManyResolve, IFarmFindOne, IFarmFindOneResolve, + IFarmLocationRelation, + IFarmLocationResolve, IFarmUpdate, IFarmUpdateResolve, ILocationGcsCreate, @@ -47,6 +49,8 @@ import type { INostrProfileFindManyResolve, INostrProfileFindOne, INostrProfileFindOneResolve, + INostrProfileRelayRelation, + INostrProfileRelayResolve, INostrProfileUpdate, INostrProfileUpdateResolve, INostrRelayCreate, @@ -67,24 +71,24 @@ import type { ITradeProductFindManyResolve, ITradeProductFindOne, ITradeProductFindOneResolve, - ITradeProductUpdate, - ITradeProductUpdateResolve, - IFarmLocationRelation, - IFarmLocationResolve, - INostrProfileRelayRelation, - INostrProfileRelayResolve, ITradeProductLocationRelation, ITradeProductLocationResolve, ITradeProductMediaRelation, - ITradeProductMediaResolve + ITradeProductMediaResolve, + ITradeProductUpdate, + ITradeProductUpdateResolve } from "@radroots/tangle-schema-bindings"; import init_wasm, { query_sql, + tangle_db_export_backup, tangle_db_farm_create, tangle_db_farm_delete, tangle_db_farm_find_many, tangle_db_farm_find_one, + tangle_db_farm_location_set, + tangle_db_farm_location_unset, tangle_db_farm_update, + tangle_db_import_backup, tangle_db_location_gcs_create, tangle_db_location_gcs_delete, tangle_db_location_gcs_find_many, @@ -104,29 +108,25 @@ import init_wasm, { tangle_db_nostr_profile_delete, tangle_db_nostr_profile_find_many, tangle_db_nostr_profile_find_one, + tangle_db_nostr_profile_relay_set, + tangle_db_nostr_profile_relay_unset, tangle_db_nostr_profile_update, tangle_db_nostr_relay_create, tangle_db_nostr_relay_delete, tangle_db_nostr_relay_find_many, tangle_db_nostr_relay_find_one, tangle_db_nostr_relay_update, + tangle_db_reset_database, + tangle_db_run_migrations, tangle_db_trade_product_create, tangle_db_trade_product_delete, tangle_db_trade_product_find_many, tangle_db_trade_product_find_one, - tangle_db_trade_product_update, - tangle_db_farm_location_set, - tangle_db_farm_location_unset, - tangle_db_nostr_profile_relay_set, - tangle_db_nostr_profile_relay_unset, tangle_db_trade_product_location_set, tangle_db_trade_product_location_unset, tangle_db_trade_product_media_set, tangle_db_trade_product_media_unset, - tangle_db_reset_database, - tangle_db_run_migrations, - tangle_db_export_backup, - tangle_db_import_backup + tangle_db_trade_product_update } from "@radroots/tangle-sql-wasm"; import type { IError } from "@radroots/types-bindings"; import { type IdbClientConfig } from "@radroots/utils";