web_lib

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

commit 2e5c99ceafbe8ba4bb291318b1dab7fe21ad2c81
parent dc2a0c27fe20fd351398183fb2b12c6a946e9f0b
Author: triesap <triesap@radroots.dev>
Date:   Mon, 22 Dec 2025 15:19:47 +0000

utils: remove internal geo and http utilities

Diffstat:
Mutils/package.json | 3---
Dutils/src/geo/index.ts | 281-------------------------------------------------------------------------------
Dutils/src/http/index.ts | 143-------------------------------------------------------------------------------
Mutils/src/index.ts | 2--
Mutils/src/types/index.ts | 8--------
Mutils/src/validation/schema.ts | 23-----------------------
6 files changed, 0 insertions(+), 460 deletions(-)

diff --git a/utils/package.json b/utils/package.json @@ -25,7 +25,6 @@ }, "devDependencies": { "@radroots/tsconfig": "*", - "@types/ngeohash": "0.6.8", "@types/node": "^22.13.1", "@types/uuid": "^10.0.0", "rimraf": "^6.0.1", @@ -35,12 +34,10 @@ "access": "public" }, "dependencies": { - "@radroots/tangle-schema-bindings": "*", "@radroots/types-bindings": "*", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.4.0", "convert": "^5.5.1", - "geohashing": "^2.0.1", "uuid": "^11.1.0", "zod": "^4.0.5" } diff --git a/utils/src/geo/index.ts b/utils/src/geo/index.ts @@ -1,280 +0,0 @@ -import { LocationGcs } from "@radroots/tangle-schema-bindings"; -import { decodeBase32, encodeBase32 } from "geohashing"; - -const EARTH_RADIUS = 6371; - -export type GeometryPoint = { - type: string; - coordinates: number[]; -}; - -export type GeometryPolygon = { - type: string; - coordinates: number[][][]; -}; - -export type GeolocationPointTuple = [number, number]; - -export type GeolocationAddress = { - primary: string; - admin: string; - country: string; -}; - -export type GeolocationPoint = { - lat: number; - lng: number; -}; - -export type LocationPoint = GeolocationPoint & { - error: GeolocationPoint; -} - -export type GeocoderReverseResult = { - id: number; - name: string; - admin1_id: string | number; - admin1_name: string; - country_id: string; - country_name: string; - latitude: number; - longitude: number; -}; - -export type IClientGeolocationPosition = GeolocationPoint & { - accuracy?: number; - altitude?: number; - altitude_accuracy?: number; -}; - -export type GeolocationLatitudeFmtOption = 'dms' | 'd' | 'dm'; - -export type LocationBasis = { - id: string; - point: GeolocationPoint; - address?: GeolocationAddress; -}; - -export const geohash_encode = (opts: { - lat: string | number; - lng: string | number; -}): string => { - const lat = typeof opts.lat === `string` ? parseFloat(opts.lat) : opts.lat; - const lng = typeof opts.lng === `string` ? parseFloat(opts.lng) : opts.lng; - const geohash = encodeBase32(lat, lng); - return geohash; -}; - -export const geohash_decode = (geohash: string): LocationPoint => { - const { lat, lng, error: { lat: lat_err, lng: lng_err } } = decodeBase32(geohash); - return { - lat, - lng, - error: { - lat: lat_err, - lng: lng_err - } - }; -}; - -export const location_geohash = (point: GeolocationPoint): string => { - const { lat, lng } = point; - const res = geohash_encode({ lat, lng }); - return res; -}; - -export const parse_geop_point = (point: GeolocationPoint): GeolocationPoint => { - const { lat, lng } = point; - return { lat, lng }; -}; - -export const parse_geol_coords = (number: number): number => { - return Math.round(number * 1e7) / 1e7; -}; - -export const parse_geolocation_address = (addr?: GeolocationAddress): GeolocationAddress | undefined => { - if (!addr) return undefined; - const { primary, admin, country } = addr; - return { primary, admin, country }; -}; - -export const parse_geolocation_point = (point?: GeometryPoint): GeolocationPoint | undefined => { - if (!point) return undefined; - return { - lat: point.coordinates[1], - lng: point.coordinates[0], - }; -}; - -export const geo_point_to_geometry = (point?: GeolocationPoint): GeometryPoint | undefined => { - if (!point) return undefined; - return { - type: 'Point', - coordinates: [point.lng, point.lat] - }; -}; - -export const location_basis_to_geo_point = (basis?: LocationBasis): GeolocationPoint | undefined => { - if (!basis) return undefined; - return { - lat: basis.point.lat, - lng: basis.point.lng - }; -}; - -export const parse_geocode_address = (geoc?: GeocoderReverseResult): GeolocationAddress | undefined => { - if (!geoc) return undefined; - const { name: primary, admin1_name: admin, country_id: country } = geoc; - return { primary, admin, country }; -}; - -export const fmt_geocode_address = (geoc: GeocoderReverseResult): string => { - const addr = parse_geocode_address(geoc); - return addr ? `${addr.primary}, ${addr.admin}, ${addr.country}` : ``; -}; - -export const fmt_geolocation_address = (addr: GeolocationAddress): string => { - return `${addr.primary}, ${addr.admin}, ${addr.country}`; -}; - -export const fmt_geometry_point_coords = (point: GeometryPoint, locale: string): string => { - const lat = geol_lat_fmt(point.coordinates[0], `dms`, locale, 3); - const lng = geol_lng_fmt(point.coordinates[1], `dms`, locale, 3); - return `${lat}, ${lng}`; -}; - -export const parse_geom_point_tup = (point: GeometryPoint): GeolocationPointTuple => { - return [ - point.coordinates[0], - point.coordinates[1], - ]; -}; - -export const parse_geol_point_tup = (point: GeolocationPoint): GeolocationPointTuple => { - return [ - point.lng, - point.lat - ]; -}; - -export const parse_tup_geop_point = (map_center: GeolocationPointTuple): GeolocationPoint => { - return { - lat: map_center[1], - lng: map_center[0] - } -}; - -export const geol_lat_fmt = (lat: number, fmt_opt: GeolocationLatitudeFmtOption, locale: string, precision: number = 5): string => { - const options: Intl.NumberFormatOptions = { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }; - const fmt_deg = new Intl.NumberFormat(locale, { maximumFractionDigits: 0 }); - const fmt_min = new Intl.NumberFormat(locale, options); - const fmt_sec = new Intl.NumberFormat(locale, options); - if (fmt_opt === 'dms') { - const deg = Math.floor(Math.abs(lat)); - const min = Math.floor((Math.abs(lat) - deg) * 60); - const sec = ((Math.abs(lat) - deg - min / 60) * 3600); - return `${fmt_deg.format(deg)}° ${fmt_min.format(min)}' ${fmt_sec.format(sec)}" ${lat >= 0 ? 'N' : 'S'}`; - } else if (fmt_opt === 'dm') { - const deg = Math.floor(Math.abs(lat)); - const min = (Math.abs(lat) - deg) * 60; - return `${fmt_deg.format(deg)}° ${fmt_min.format(min)}' ${lat >= 0 ? 'N' : 'S'}`; - } else { - return `${lat.toLocaleString(locale, { maximumFractionDigits: precision })}° ${lat >= 0 ? 'N' : 'S'}`; - } -}; - -export const geol_lng_fmt = (lng: number, fmt_opt: GeolocationLatitudeFmtOption, locale: string, precision: number = 5): string => { - const options: Intl.NumberFormatOptions = { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }; - const fmt_deg = new Intl.NumberFormat(locale, { maximumFractionDigits: 0 }); - const fmt_min = new Intl.NumberFormat(locale, options); - const fmt_sec = new Intl.NumberFormat(locale, options); - if (fmt_opt === 'dms') { - const degrees = Math.floor(Math.abs(lng)); - const minutes = Math.floor((Math.abs(lng) - degrees) * 60); - const seconds = ((Math.abs(lng) - degrees - minutes / 60) * 3600); - return `${fmt_deg.format(degrees)}° ${fmt_min.format(minutes)}' ${fmt_sec.format(seconds)}" ${lng >= 0 ? 'E' : 'W'}`; - } else if (fmt_opt === 'dm') { - const degrees = Math.floor(Math.abs(lng)); - const minutes = (Math.abs(lng) - degrees) * 60; - return `${fmt_deg.format(degrees)}° ${fmt_min.format(minutes)}' ${lng >= 0 ? 'E' : 'W'}`; - } else { - return `${lng.toLocaleString(locale, { maximumFractionDigits: precision })}° ${lng >= 0 ? 'E' : 'W'}`; - } -}; - -export const compute_bounding_box = (lat: number, lng: number, distance_km: number): { nw: GeolocationPoint; ne: GeolocationPoint; se: GeolocationPoint; sw: GeolocationPoint; } => { - const deg_to_rad = (deg: number) => deg * (Math.PI / 180); - const rad_to_deg = (rad: number) => rad * (180 / Math.PI); - - function destination_point(lat: number, lng: number, bearing: number, distance_km: number): GeolocationPoint { - const lat1 = deg_to_rad(lat); - const lon1 = deg_to_rad(lng); - const angular_distance = distance_km / EARTH_RADIUS; - - const lat2 = Math.asin(Math.sin(lat1) * Math.cos(angular_distance) + Math.cos(lat1) * Math.sin(angular_distance) * Math.cos(deg_to_rad(bearing))); - const lon2 = lon1 + Math.atan2(Math.sin(deg_to_rad(bearing)) * Math.sin(angular_distance) * Math.cos(lat1), Math.cos(angular_distance) - Math.sin(lat1) * Math.sin(lat2)); - - return { lat: rad_to_deg(lat2), lng: rad_to_deg(lon2) }; - } - - const bearings = [0, 90, 180, 270]; - - const coords = bearings.map(bearing => destination_point(lat, lng, bearing, distance_km / Math.sqrt(2))); - - return { - nw: coords[0], - ne: coords[1], - se: coords[2], - sw: coords[3] - }; -}; - -export const geo_bounds_calc = (lat: number, lng: number, distance_km: number): { north: GeolocationPoint; south: GeolocationPoint; east: GeolocationPoint; west: GeolocationPoint; } => { - const deg_to_rad = (deg: number) => deg * (Math.PI / 180); - const rad_to_deg = (rad: number) => rad * (180 / Math.PI); - - function destination_point(lat: number, lng: number, bearing: number, distance_km: number): GeolocationPoint { - const lat1 = deg_to_rad(lat); - const lon1 = deg_to_rad(lng); - const angular_distance = distance_km / EARTH_RADIUS; - - const lat2 = Math.asin(Math.sin(lat1) * Math.cos(angular_distance) + Math.cos(lat1) * Math.sin(angular_distance) * Math.cos(deg_to_rad(bearing))); - const lon2 = lon1 + Math.atan2(Math.sin(deg_to_rad(bearing)) * Math.sin(angular_distance) * Math.cos(lat1), Math.cos(angular_distance) - Math.sin(lat1) * Math.sin(lat2)); - - return { lat: rad_to_deg(lat2), lng: rad_to_deg(lon2) }; - } - - return { - north: destination_point(lat, lng, 0, distance_km), - south: destination_point(lat, lng, 180, distance_km), - east: destination_point(lat, lng, 90, distance_km), - west: destination_point(lat, lng, 270, distance_km) - }; -}; - - -export const gcs_to_location_basis = ({ - id, - lat, - lng, - gc_name: primary, - gc_admin1_name: admin, - gc_country_id: country, -}: LocationGcs): LocationBasis => ({ - id, - point: { - lat, - lng, - }, - address: primary && admin && country ? { - primary, - admin, - country, - } : undefined -}); -\ No newline at end of file diff --git a/utils/src/http/index.ts b/utils/src/http/index.ts @@ -1,143 +0,0 @@ -import type { IError } from "@radroots/types-bindings"; -import { FieldRecord, NotifyMessage } from "../types/index.js"; - -export const is_err_response = (response: any): response is { err: string } => { - return "err" in response && typeof response.err === "string"; -} - -export const is_pass_response = (response: any): response is { pass: true } => { - return "pass" in response && response.pass === true; -} - -export const is_result_response = (response: any): response is { result: string } => { - return "result" in response && typeof response.result === "string"; -} - -export const is_results_response = (response: any): response is { results: string[] } => { - return "results" in response && Array.isArray(response.results); -} - -export const is_error_response = (response: any): response is { error: string } => { - return "error" in response && response.error; -} - -export const is_message_response = (response: any): response is NotifyMessage => { - return ( - typeof response === "object" && - response !== null && - "message" in response && - typeof response.message === "string" && - (response.ok === undefined || typeof response.ok === "string") && - (response.cancel === undefined || typeof response.cancel === "string") - ); -}; -export type IClientHttp = { - fetch(opts: IHttpOpts): Promise<IHttpResponse | IError<string>>; -}; - -export type IHttpImageResponse = { - status: number; - blob?: Blob; - headers: FieldRecord; - url: string; -}; - -export type IHttpResponse = { - status: number; - data?: any; - error?: string; - message?: NotifyMessage; - headers: FieldRecord; - url: string; -}; - -export type IHttpOptsData = any; -export type IHttpOptsParams = Record<string, string | string[]>; - -export type IHttpOpts = { - url: string; - method?: `get` | `post` | `put`; - params?: IHttpOptsParams; - data?: IHttpOptsData; - data_bin?: Uint8Array; - authorization?: string; - headers?: FieldRecord; - connect_timeout?: number; -}; - -export const lib_http_to_bodyinit = (data: any): RequestInit["body"] => { - if (typeof data === 'string') return data; - else if (data instanceof FormData) return data; - else if (data instanceof Blob) return data; - else if (data instanceof ArrayBuffer) return data; - else if (data instanceof URLSearchParams) return data; - return JSON.stringify(data); -} - -export const lib_http_parse_headers = (headers: Headers): FieldRecord => { - const acc: FieldRecord = {}; - headers.forEach((value, key) => acc[key] = value); - return acc; -}; - -export const http_fetch_opts = (opts: IHttpOpts): { url: string; options: RequestInit; } => { - const { url } = opts; - const method = opts.method ? opts.method.toUpperCase() : `GET`; - const headers = new Headers(); - if (method === `POST`) headers.append(`Content-Type`, `application/json`); - if (opts.authorization) headers.append(`Authorization`, `Bearer ${encodeURIComponent(opts.authorization)}`); - if (opts.headers) Object.entries(opts.headers).forEach(([k, v]) => headers.append(k, v)) - const options: RequestInit = { - method, - headers, - } - if (opts.data) options.body = lib_http_to_bodyinit(opts.data); - if (opts.data_bin) options.body = opts.data_bin as any; - return { - url, - options - } -}; - -export const lib_http_parse_response = async (res: Response): Promise<IHttpResponse> => { - let data: unknown = null; - try { - const res_json = await res.clone().json(); - data = typeof res_json === `string` ? JSON.parse(res_json) : res_json; - } catch { } - if (!data) { - try { - data = await res.text(); - } catch { } - } - return { - status: res.status, - url: res.url, - data: res.ok && data ? data : null, - error: !res.ok && is_error_response(data) ? data.error : undefined, - message: res.ok && is_message_response(data) ? data : undefined, - headers: lib_http_parse_headers(res.headers) - }; -}; - -export const http_fetch = async (opts: IHttpOpts): Promise<IHttpResponse> => { - const { url, options } = http_fetch_opts(opts); - const response = await fetch(url, options); - let data: any = null; - try { - const res_json = await response.json(); - data = typeof res_json === `string` ? JSON.parse(res_json) : res_json; - } catch { } - if (!data) { - try { - const res_text = await response.text(); - data = res_text; - } catch { } - } - return { - status: response.status, - url: response.url, - data, - headers: lib_http_parse_headers(response.headers) - }; -}; diff --git a/utils/src/index.ts b/utils/src/index.ts @@ -2,8 +2,6 @@ export * from "./async/index.js"; export * from "./binary/index.js"; export * from "./currency/index.js"; export * from "./errors/index.js"; -export * from "./geo/index.js"; -export * from "./http/index.js"; export * from "./id/index.js"; export * from "./index.js"; export * from "./media/index.js"; diff --git a/utils/src/types/index.ts b/utils/src/types/index.ts @@ -1,15 +1,7 @@ import type { IError } from "@radroots/types-bindings"; -export type FieldRecord = Record<string, string>; - export type ResolveStatus = "info" | "warning" | "error" | "success"; -export type NotifyMessage = { - message: string; - ok?: string; - cancel?: string; -}; - export type FileBytesFormat = `kb` | `mb` | `gb`; export type FileMimeType = string; export type FilePath = { file_path: string; file_name: string; mime_type: FileMimeType; } diff --git a/utils/src/validation/schema.ts b/utils/src/validation/schema.ts @@ -1,5 +1,4 @@ import { z } from "zod"; -import { GeocoderReverseResult, GeolocationAddress, GeolocationPoint } from "../geo/index.js"; import { parse_int } from "../numbers/index.js"; import { util_rxp } from "./regex.js"; @@ -16,28 +15,6 @@ export const zf_mass_unit = z.union([ z.literal(`g`), ]); -export const schema_geolocation_address: z.ZodSchema<GeolocationAddress> = z.object({ - primary: z.string().regex(util_rxp.addr_primary), - admin: z.string().regex(util_rxp.addr_admin), - country: z.string().regex(util_rxp.country_code_a2) -}); - -export const schema_geocode_result: z.ZodSchema<GeocoderReverseResult> = z.object({ - id: z.number(), - name: z.string(), - admin1_id: z.union([z.string(), z.number()]), - admin1_name: z.string(), - country_id: z.string(), - country_name: z.string(), - latitude: z.number(), - longitude: z.number(), -}); - -export const schema_geolocation_point: z.ZodSchema<GeolocationPoint> = z.object({ - lat: z.number().min(-90).max(90), - lng: z.number().min(-180).max(180), -}); - export const zf_price_amount = z.preprocess((input) => { return parse_int(String(input), 1.00); }, z.number().positive().multipleOf(0.01));