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:
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";