aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/packages/ui/src/lib/tsrs-utils.ts
diff options
context:
space:
mode:
author苏向夜 <46275354+fu050409@users.noreply.github.com>2026-02-25 02:06:07 +0800
committerGitHub <noreply@github.com>2026-02-25 02:06:07 +0800
commit78ac61904d78d558d092eff08c9f261cbdb187e8 (patch)
tree96f68d1f1554ee3a0532793afaaa52b0c73dcbec /packages/ui/src/lib/tsrs-utils.ts
parent8ff3af6cb908fd824b512379dd21ed4f595ab6bb (diff)
parent329734b23957b84cde2af459fa61c7385fb5b5f1 (diff)
downloadDropOut-78ac61904d78d558d092eff08c9f261cbdb187e8.tar.gz
DropOut-78ac61904d78d558d092eff08c9f261cbdb187e8.zip
feat(ui): partial react rewrite (#77)
## Summary by Sourcery Export backend data structures to TypeScript for the new React-based UI and update CI to build additional targets. New Features: - Generate TypeScript definitions for core backend structs and enums used by the UI. - Now use our own Azure app(_DropOut_) to finish the authorize process. Enhancements: - Annotate existing Rust models with ts-rs metadata to control exported TypeScript shapes, including tagged enums and opaque JSON fields. Build: - Add ts-rs as a dependency for generating TypeScript bindings from Rust types. CI: - Extend the Semifold CI workflow to run on the dev branch and build additional Linux musl and Windows GNU targets using cross where needed.
Diffstat (limited to 'packages/ui/src/lib/tsrs-utils.ts')
-rw-r--r--packages/ui/src/lib/tsrs-utils.ts67
1 files changed, 67 insertions, 0 deletions
diff --git a/packages/ui/src/lib/tsrs-utils.ts b/packages/ui/src/lib/tsrs-utils.ts
new file mode 100644
index 0000000..f48f851
--- /dev/null
+++ b/packages/ui/src/lib/tsrs-utils.ts
@@ -0,0 +1,67 @@
+export type Maybe<T> = T | null | undefined;
+
+export function toNumber(
+ value: Maybe<number | bigint | string>,
+ fallback = 0,
+): number {
+ if (value === null || value === undefined) return fallback;
+
+ if (typeof value === "number") {
+ if (Number.isFinite(value)) return value;
+ return fallback;
+ }
+
+ if (typeof value === "bigint") {
+ // safe conversion for typical values (timestamps, sizes). Might overflow for huge bigint.
+ return Number(value);
+ }
+
+ if (typeof value === "string") {
+ const n = Number(value);
+ return Number.isFinite(n) ? n : fallback;
+ }
+
+ return fallback;
+}
+
+/**
+ * Like `toNumber` but ensures non-negative result (clamps at 0).
+ */
+export function toNonNegativeNumber(
+ value: Maybe<number | bigint | string>,
+ fallback = 0,
+): number {
+ const n = toNumber(value, fallback);
+ return n < 0 ? 0 : n;
+}
+
+export function toDate(
+ value: Maybe<number | bigint | string>,
+ opts?: { isSeconds?: boolean },
+): Date | null {
+ if (value === null || value === undefined) return null;
+
+ const isSeconds = opts?.isSeconds ?? true;
+
+ // accept bigint, number, numeric string
+ const n = toNumber(value, NaN);
+ if (Number.isNaN(n)) return null;
+
+ const ms = isSeconds ? Math.floor(n) * 1000 : Math.floor(n);
+ return new Date(ms);
+}
+
+/**
+ * Convert a binding boolean-ish value (0/1, "true"/"false", boolean) to boolean.
+ */
+export function toBoolean(value: unknown, fallback = false): boolean {
+ if (value === null || value === undefined) return fallback;
+ if (typeof value === "boolean") return value;
+ if (typeof value === "number") return value !== 0;
+ if (typeof value === "string") {
+ const s = value.toLowerCase().trim();
+ if (s === "true" || s === "1") return true;
+ if (s === "false" || s === "0") return false;
+ }
+ return fallback;
+}