commit 3088bafce40464c5445e15ce0ed89f2245bf90cc
parent 549e0db7c7d60a2746ad72ce1bc9bff3ab0be8b4
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Thu, 7 Aug 2025 17:35:12 +0000
utils: restructure library modules. update build process to use tsc with targets for esm and cjs outputs
Diffstat:
44 files changed, 93 insertions(+), 2255 deletions(-)
diff --git a/utils/.gitignore b/utils/.gitignore
@@ -43,5 +43,8 @@ vite.config.ts.timestamp-*
.vscode
notes*.txt
notes*.md
-git-diff.txt
-justfile
+notes*.json
+git-diff*.txt
+prompt*.txt
+tree*.txt
+justfile
+\ No newline at end of file
diff --git a/utils/package.json b/utils/package.json
@@ -1,28 +1,32 @@
{
- "name": "@radroots/util",
- "version": "0.0.0",
+ "name": "@radroots/utils",
+ "version": "0.0.1",
"private": true,
- "license": "GPLv3",
"type": "module",
- "main": "dist/index.js",
- "module": "dist/index.js",
- "types": "dist/index.d.ts",
+ "main": "./dist/cjs/index.cjs",
+ "module": "./dist/esm/index.js",
+ "types": "./dist/types/index.d.ts",
"exports": {
".": {
- "import": "./dist/index.js",
- "require": "./dist/index.cjs"
+ "types": "./dist/types/index.d.ts",
+ "import": "./dist/esm/index.js",
+ "require": "./dist/cjs/index.js"
}
},
"scripts": {
- "build": "tsup",
- "dev": "tsup --watch",
+ "build:esm": "tsc -p tsconfig.esm.json",
+ "build:cjs": "tsc -p tsconfig.cjs.json",
+ "build": "npm run clean && npm run build:esm && npm run build:cjs",
+ "prebuild": "npm run clean",
+ "clean": "rimraf dist && rimraf tsconfig.tsbuildinfo",
+ "dev": "npm run watch",
"watch": "tsc -w"
},
"devDependencies": {
"@types/ngeohash": "0.6.8",
"@types/node": "^22.13.1",
"@types/uuid": "^10.0.0",
- "tsup": "^6.2.3",
+ "rimraf": "^6.0.1",
"typescript": "5.8.3"
},
"publishConfig": {
@@ -31,16 +35,10 @@
"dependencies": {
"@noble/curves": "^1.6.0",
"@noble/hashes": "^1.4.0",
- "@nostr-dev-kit/ndk": "^2.11.0",
- "@sveltekit-i18n/base": "^1.3.7",
- "@sveltekit-i18n/parser-icu": "^1.0.8",
"@radroots/radroots-common-bindings": "*",
"convert": "^5.5.1",
"geohashing": "^2.0.1",
- "nostr-geotags": "*",
- "nostr-tools": "^2.10.4",
- "sveltekit-i18n": "^2.4.2",
- "uuid": "^10.0.0",
- "zod": "^3.23.8"
+ "uuid": "^11.1.0",
+ "zod": "^4.0.5"
}
}
\ No newline at end of file
diff --git a/utils/src/*regex.ts b/utils/src/*regex.ts
@@ -1,141 +0,0 @@
-export const util_rxp = {
- product_key: /^[A-Za-z_]+$/,
- product_key_ch: /^[A-Za-z_]$/,
- product_title: /[A-Za-z0-9 ]+$/,
- product_title_ch: /[A-Za-z0-9 ]$/,
- float: /^[+-]?(\d+(\.\d*)?|\.\d+)$/,
- float_ch: /^[0-9\.\+\-]$/,
- float_pos: /^\d+(\.\d+)?$/,
- float_pos_ch: /^[0-9\.]$/,
- description: /^(?:\S+(?:\s+\S+)*)$/,
- description_ch: /[^a-zA-Z0-9.,!?;:'"(){}[]\s\u0600-\u06FF\u0900-\u097F\u0400-\u04FF\u0500-\u052F\u1F00-\u1FFF\u4E00-\u9FFF\uAC00-\uD7AF\u3040-\u309F\u30A0-\u30FF ]+/,
- nbsp: /[\u00A0]/g,
- nbsp_rp: /[\u00A0]+/g,
- rtlm: /[\u200F]/g,
- rtlm_rp: /[\u200F]+/g,
- commas: /[,]+/g,
- periods: /[.]+/g,
- word_only: /^[a-zA-Z]+$/,
- alpha: /[a-zA-Z ]$/,
- alpha_ch: /[a-zA-Z ]$/,
- num: /^[0-9]+$/,
- lat: /^[-+]?([1-8]?[0-9](\.\d{1,6})?|90(\.0{1,6})?)$/,
- lat_ch: /^[\d\.\+\-]$/,
- lng: /^[-+]?((1[0-7]?[0-9]|180)(\.\d{1,6})?|(\d{1,2})(\.\d{1,6})?)$/,
- lng_ch: /^[\d\.\+\-]$/,
- alphanum: /[a-zA-Z0-9., ]$/,
- alphanum_ch: /[a-zA-Z0-9.,\s\u0600-\u06FF\u0900-\u097F\u0400-\u04FF\u0500-\u052F\u1F00-\u1FFF\u4E00-\u9FFF\uAC00-\uD7AF\u3040-\u309F\u30A0-\u30FF ]+/,
- price: /^\d+(\.\d+)?$/,
- price_ch: /[0-9.]$/,
- price_cur: /^[A-Za-z]{3}$/,
- price_cur_ch: /[A-Za-z]$/,
- profile_name: /^[a-zA-Z0-9._]{3,30}$/,
- profile_name_ch: /[a-zA-Z0-9._]/,
- trade_product_key: /^(?:[a-zA-Z0-9]+(?:\s+[a-zA-Z0-9]+){0,2})$/,
- trade_product_category: /^(?:[a-zA-Z0-9]+(?:\s+[a-zA-Z0-9]+){0,2})$/,
- currency_symbol: /(?:[A-Za-z]{3,5}\$|\p{Sc})/u,
- currency_marker: /(?:[A-Za-z]{2,4}[^\d\s]+|[^\d\s]{1,3}[A-Za-z]{2,4})/,
- ws_proto: /^(wss:\/\/|ws:\/\/)/,
- quantity_unit: /^(kg|lb|g)$/,
- quantity_unit_ch: /[A-Za-z]$/,
- url_image_upload: /^file:\/\/.*\.(png|jpg|jpeg|gif|webp|bmp|svg)$/,
- ///^blob:https:\/\/domain\.tld\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/,
- url_image_upload_dev: /^file:\/\/.*\.(png|jpg|jpeg|gif|webp|bmp|svg)$/,
- // /^blob:http:\/\/localhost:\d+\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/,
- country_code_a2: /^[A-Za-z]{2}$/,
- addr_primary: /[a-zA-Z0-9., ]$/,
- addr_admin: /[a-zA-Z0-9., ]$/,
- num_int: /^[0-9]$/,
- area_unit: /^(ac|ha|ft2|m2)$/,
- area_unit_ch: /[A-Za-z2]$/,
-};
-
-export type FormFieldsKey =
- | `nostr_secret_key`
- | `product_title`
- | `product_key`
- | `product_process`
- | `product_description`
- | `price`
- | `price_currency`
- | `quantity_unit`
- | `quantity`
- | `quantity_label`
- | `farm_name`
- | `farm_size`
- | `area`
- | `area_unit`
- | `contact_name`
- | `profile_name`
-
-export type FormField = {
- validate: RegExp;
- charset: RegExp;
-};
-
-export const form_fields: Record<FormFieldsKey, FormField> = {
- profile_name: {
- charset: util_rxp.profile_name_ch,
- validate: util_rxp.profile_name,
- },
- product_description: {
- charset: util_rxp.alpha_ch,
- validate: util_rxp.alpha,
- },
- product_key: {
- charset: util_rxp.product_key_ch,
- validate: util_rxp.product_key,
- },
- product_title: {
- charset: util_rxp.product_title_ch,
- validate: util_rxp.product_title,
- },
- product_process: {
- charset: util_rxp.alphanum_ch,
- validate: util_rxp.alphanum,
- },
- price: {
- charset: util_rxp.price_ch,
- validate: util_rxp.price,
- },
- price_currency: {
- charset: util_rxp.price_cur_ch,
- validate: util_rxp.price_cur,
- },
- quantity: {
- charset: util_rxp.num,
- validate: util_rxp.num,
- },
- quantity_unit: {
- charset: util_rxp.quantity_unit_ch,
- validate: util_rxp.quantity_unit,
- },
- quantity_label: {
- charset: util_rxp.alphanum_ch,
- validate: util_rxp.alphanum,
- },
- area: {
- charset: util_rxp.float_ch,
- validate: util_rxp.float,
- },
- area_unit: {
- charset: util_rxp.area_unit_ch,
- validate: util_rxp.area_unit,
- },
- farm_name: {
- charset: util_rxp.alpha_ch,
- validate: util_rxp.alpha,
- },
- farm_size: {
- charset: util_rxp.num_int,
- validate: util_rxp.num_int,
- },
- contact_name: {
- charset: util_rxp.alpha_ch,
- validate: util_rxp.alpha,
- },
- nostr_secret_key: {
- charset: util_rxp.alpha_ch,
- validate: util_rxp.alpha,
- }
-};
diff --git a/utils/src/*validation.ts b/utils/src/*validation.ts
@@ -1,55 +0,0 @@
-import { GeocoderReverseResult, type GeolocationAddress, type GeolocationPoint, parse_int, util_rxp } from "$root";
-import { z } from "zod";
-
-export const zf_area_unit = z.union([
- z.literal(`ac`),
- z.literal(`ft2`),
- z.literal(`ha`),
- z.literal(`m2`),
-]);
-
-export const zf_mass_unit = z.union([
- z.literal(`kg`),
- z.literal(`lb`),
- 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));
-
-export const zf_quantity_amount = z.preprocess((input) => {
- return parse_int(String(input), 1);
-}, z.number().int().positive());
-
-export const zf_price = z.number().positive().multipleOf(0.01);
-
-export const zf_numi_pos = z.number().int().positive();
-
-export const zf_numf_pos = z.number().positive();
-
-export const zf_email = z.string().email();
-
-export const zf_username = z.string().regex(util_rxp.profile_name);
-\ No newline at end of file
diff --git a/utils/src/_env.ts b/utils/src/_env.ts
@@ -1,3 +0,0 @@
-export const _env = {
- PROD: process.env.NODE_ENV === `production`
-};
diff --git a/utils/src/app/config.ts b/utils/src/app/config.ts
@@ -1,30 +0,0 @@
-import type { AppLayoutKey } from "$root";
-
-type ConfigWindow = {
- layout: Record<AppLayoutKey, {
- h: number;
- }>;
- debounce: {
- search: number;
- }
-};
-
-export const cfg_app: ConfigWindow = {
- layout: {
- ios0: {
- h: 600
- },
- ios1: {
- h: 750
- },
- webm0: {
- h: 600
- },
- webm1: {
- h: 750
- }
- },
- debounce: {
- search: 200
- },
-};
-\ No newline at end of file
diff --git a/utils/src/app/glyph.ts b/utils/src/app/glyph.ts
@@ -1,131 +0,0 @@
-import type { GeometryCardinalDirection } from "$root";
-
-export type GlyphKey = |
- string |
- `chat-text` |
- `eye` |
- `export` |
- `video-camera` |
- `device-mobile-camera` |
- `crop` |
- `map-trifold` |
- `trash-simple` |
- `backspace` |
- `user-circle-check` |
- `images-square` |
- `bell` |
- `columns` |
- `bold` |
- `article` |
- `grid-four` |
- `link-simple` |
- `seal-check` |
- `selection-foreground` |
- `image-square` |
- `image-broken` |
- `funnel` |
- `users-three` |
- `note-blank` |
- `user-circle-plus` |
- `user-circle` |
- `receipt` |
- `invoice` |
- `note` |
- `arrow-left` |
- `arrows-down-up` |
- `basket` |
- `arrow-right` |
- `upload-simple` |
- `printer` |
- `download-simple` |
- `list` |
- `asterisk` |
- `asterisk-simple` |
- `subtitles-slash` |
- `cardholder` |
- `globe-x` |
- `exclamation-mark` |
- `network-x` |
- `x-circle` |
- `address-book-tabs` |
- `paper-plane-tilt` |
- `note-pencil` |
- `share-fat` |
- `folder` |
- `trash` |
- `plus-circle` |
- `currency-${GlyphKeyCurrency}` |
- `arrow-down` |
- `caret-circle-down` |
- `caret-circle-up` |
- `shopping-bag-open` |
- `coffee-bean` |
- `compass` |
- `map-pin-simple` |
- `handbag-simple` |
- `devices` |
- `lock-key` |
- `gear` |
- `gear-fine` |
- `bell-simple` |
- `envelope` |
- `house-line` |
- `arrows-left-right` |
- `list-plus` |
- `squares-four` |
- `list-plus` |
- `app-window` |
- `circle-notch` |
- `subtract-square` |
- `device-tablet-speaker` |
- `weather-cloud` |
- `warning` |
- `circle-notch` |
- `minus` |
- `key` |
- `arrow-u-up-left` |
- `arrow-counter-clockwise` |
- `circle` |
- `check-circle` |
- `circle-dashed` |
- `dots-three` |
- `cards-three` |
- `lightning` |
- `cards` |
- `note-pencil` |
- `tray` |
- `calendar-dots` |
- `notepad` |
- `network` |
- `calendar-blank` |
- `chats-circle` |
- `plant` |
- `farm` |
- `magnifying-glass` |
- `chat-circle-dots` |
- `dots-three-outline` |
- `copy` |
- `circles-four` |
- `waveform` |
- `film-strip` |
- `arrow-up` |
- `arrow-circle-up` |
- `plus` |
- `funnel-simple` |
- `user` |
- `camera` |
- `check` |
- `file` |
- `share-network` |
- `question` |
- `minus-circle` |
- `globe-simple` |
- `globe` |
- `warning-circle` |
- `x` |
- `info` |
- `caret-${GeometryCardinalDirection}` |
- `caret-up-down`;
-
-export type GlyphKeyCurrency = `dollar` | `eur`;
-export type GlyphWeight = `bold` | `fill` | `light`;
diff --git a/utils/src/app/lib.ts b/utils/src/app/lib.ts
@@ -1,51 +0,0 @@
-import type { CallbackPromise, CallbackPromiseGeneric } from "$root";
-
-export type IViewBasis<T extends object> = {
- kv_init_prevent?: boolean;
- on_mount?: CallbackPromise;
- on_destroy?: CallbackPromise;
-} & T;
-
-
-export type LabelFieldKind = `link` | `on` | `shade`;
-export type EntryStyle = `guide` | `line`;
-export type ImageAspectRatio = `auto` | `1/1` | `4/3` | `16/9` | `3/4`;
-
-export type SvelteTransitionEasingFunction = (t: number) => number;
-
-export type LoadingBlades = 8 | 12;
-export type LoadingDimension = GeometryDimension | `glyph-send-button`; //@todo remove
-
-export type LayerGlyphBasisKind = `_a` | `_d` | `_pl`;
-
-export interface SvelteTransitionConfig {
- delay?: number;
- duration?: number;
- easing?: SvelteTransitionEasingFunction;
- css?: (t: number, u: number) => string;
- tick?: (t: number, u: number) => void;
-}
-
-export type ElementCallbackValue = CallbackPromiseGeneric<{ value: string; pass: boolean; }>;
-export type ElementCallbackValueKeydown<T extends HTMLElement> = CallbackPromiseGeneric<{ key: string; key_s: boolean; el: T }>;
-export type ElementCallbackValueBlur<T extends HTMLElement> = CallbackPromiseGeneric<{ el: T }>;
-export type ElementCallbackValueFocus<T extends HTMLElement> = CallbackPromiseGeneric<{ el: T }>;
-export type ElementCallbackMount<T extends HTMLElement> = CallbackPromiseGeneric<{ el: T }>;
-
-export type GeometryScreenPositionHorizontal = `left` | `center` | `right`;
-export type GeometryScreenPositionVertical = `top` | `center` | `bottom`;
-export type GeometryScreenPosition = `${GeometryScreenPositionVertical}-${GeometryScreenPositionHorizontal}`;
-export type GeometryCardinalDirection = `up` | `down` | `left` | `right`;
-export type GeometryDimension =
- `xs` |
- `sm` |
- `md` |
- `lg` |
- `xl`;
-export type GeometryGlyphDimension =
- | `${GeometryDimension}`
- | `${GeometryDimension}-`
- | `${GeometryDimension}--`
- | `${GeometryDimension}+`;
-
-export type NavigationParamTuple<T extends string> = [T, string];
diff --git a/utils/src/app/search.ts b/utils/src/app/search.ts
@@ -1,72 +0,0 @@
-export type SearchServiceResult = Record<string, any> & { id: string, result_k: string; result_v: string; };
-export type SearchServiceFlattenedData = Record<string, any> & { list: string; };
-
-export type ISearchService = {
- search(input: string): SearchServiceResult[]
-};
-
-export class SearchService implements ISearchService {
- private _flattened_data: SearchServiceFlattenedData[] = [];
- private _index_map: Map<string, Record<string, any>[]> = new Map();
-
- constructor(data: Record<string, any[]>) {
- this.flatten_data(data);
- this.index_data();
- }
-
- private get flattened_data() {
- return this._flattened_data;
- }
-
- private flatten_data(data: Record<string, any[]>) {
- Object.keys(data).forEach((list_group) => {
- const list = data[list_group];
- list.forEach((item) => {
- const flattened_item: SearchServiceFlattenedData = { ...item, group: list_group };
- this._flattened_data.push(flattened_item);
- });
- });
- }
-
- private index_data(): void {
- this.flattened_data.forEach((item) => {
- Object.keys(item).forEach((key) => {
- const key_lower = key.toLowerCase();
- const value = item[key];
- if (value != null) {
- if (!this._index_map.has(key_lower)) this._index_map.set(key_lower, []);
- this._index_map.get(key_lower)?.push(item);
- }
- });
- });
- }
-
- public search(query: string): SearchServiceResult[] {
- if (!query) return [];
- const search_query = query.toLowerCase().trim();
- let results: SearchServiceResult[] = [];
- const results_seen = new Set<string>();
- this._index_map.forEach((items) => {
- items.forEach((item) => {
- for (const [key, value] of Object.entries(item)) {
- if (key === `id` || key === `created_at` || key === `updated_at` || key === `public_key` || key === `group`) continue;
- if (value && value.toString().replace(/[()_-]/gi, ` `).toLowerCase().includes(search_query)) {
- const { group, ...rest } = item;
- if (!(`id` in item)) continue;
- const result_key = item.id;
- if (results_seen.has(result_key)) continue;
- results_seen.add(result_key);
- const reshaped_result: SearchServiceResult = {
- id: item.id,
- result_k: key,
- result_v: value,
- [group]: { ...rest },
- };
- results.push(reshaped_result);
- }
- };
- });
- });
- return results;
- }
-}
diff --git a/utils/src/app/styles.ts b/utils/src/app/styles.ts
@@ -1,28 +0,0 @@
-export type ThemeLayer = 0 | 1 | 2;
-
-export type AppConfigType = `farmer` | `personal`
-
-export type AppLayoutKeyIOS = `ios0` | `ios1`;
-export type AppLayoutKeyWeb = `webm0` | `webm1`;
-export type AppLayoutKey = AppLayoutKeyIOS | AppLayoutKeyWeb;
-
-export type AppLayoutIOS<T extends string> = `${T}_${AppLayoutKeyIOS}`;
-export type AppLayoutWeb<T extends string> = `${T}_${AppLayoutKeyWeb}`;
-
-export type AppLayoutKeyHeight =
- | `lo_view_main`
- | `lo_bottom_button`
- | `nav_tabs`
- | `nav_page_header`
- | `nav_page_toolbar`;
-
-export type AppLayoutKeyWidth =
- | `lo`
- | `lo_line_entry`
- | `lo_textdesc`;
-
-export type AppHeightsResponsiveIOS = AppLayoutIOS<AppLayoutKeyHeight>;
-export type AppHeightsResponsiveWeb = AppLayoutWeb<AppLayoutKeyHeight>;
-
-export type AppWidthsResponsiveIOS = AppLayoutIOS<AppLayoutKeyWidth>;
-export type AppWidthsResponsiveWeb = AppLayoutWeb<AppLayoutKeyWidth>;
diff --git a/utils/src/app/util.ts b/utils/src/app/util.ts
@@ -1,163 +0,0 @@
-import { sleep, type AppLayoutKey, type AppLayoutKeyIOS, type AppLayoutKeyWeb, type LabelFieldKind, type NavigationParamTuple, type ThemeLayer } from "$root";
-
-export const fmt_cl = (classes?: string): string => {
- return classes ? classes : ``;
-};
-
-export const get_layout = (val?: string): AppLayoutKey | undefined => {
- const lo_ios = get_ios_layout(val);
- if (lo_ios) return lo_ios;
- const lo_web = get_web_layout(val);
- if (lo_web) return lo_web;
- return undefined;
-};
-
-export const get_layout_default = (val?: string): AppLayoutKey => {
- const res = get_layout(val);
- return res || `webm0`;
-};
-
-export const get_ios_layout = (val?: string): AppLayoutKeyIOS | undefined => {
- switch (val) {
- case `ios0`:
- case `ios1`:
- return val;
- default:
- return undefined;
- };
-};
-
-export const get_ios_layout_default = (val?: string): AppLayoutKeyIOS => {
- const res = get_ios_layout(val);
- return res || `ios0`;
-};
-
-export const get_web_layout = (val?: string): AppLayoutKeyWeb | undefined => {
- switch (val) {
- case `webm0`:
- case `webm1`:
- return val;
- default:
- return undefined;
- };
-};
-
-export const get_web_layout_default = (val?: string): AppLayoutKeyWeb => {
- const res = get_web_layout(val);
- return res || `webm0`;
-};
-
-export const parse_layer = (layer?: number, layer_default?: ThemeLayer): ThemeLayer => {
- switch (layer) {
- case 0:
- case 1:
- case 2:
- return layer;
- default:
- return layer_default ? layer_default : 0;
- };
-};
-
-export const value_constrain = (regex_charset: RegExp, value: string): string => {
- return value
- .split(``)
- .filter((char) => regex_charset.test(char))
- .join(``);
-};
-
-export const value_constrain_textarea = (regex_charset: RegExp, value: string): string => {
- return value
- .replace(/\u00A0/g, ` `)
- .split(/[\n]/)
- .map(line => line
- .split(``)
- .filter((char) => regex_charset.test(char))
- .join(``)
- )
- .join("\n");
-};
-
-export const encode_query_params = <T extends string>(params_list: NavigationParamTuple<T>[] = []): string => {
- let query = "";
- for (const [k, v] of params_list) {
- if (k && v) {
- if (query) query += `&`;
- query += `${k.trim()}=${encodeURIComponent(v.trim())}`;
- }
- }
- return query ? `?${query}` : ``;
-};
-
-export const encode_route = <TRoute extends string, TParam extends string>(route: TRoute, params_list?: NavigationParamTuple<TParam>[]): string => {
- const query = encode_query_params(params_list);
- if (!query) return route;
- return `${route === `/` ? `/` : route.replace(/\/+$/, ``)}${query}`;
-};
-
-export const fmt_trellis = (hide_border_t: boolean, hide_border_b: boolean): string => {
- return `${hide_border_t ? `group-first:border-t-0` : `group-first:border-t-line`} ${hide_border_b ? `group-last:border-b-0` : `group-last:border-b-line`}`;
-};
-
-export const get_label_classes_kind = (layer: ThemeLayer, label_kind: LabelFieldKind | undefined, hide_active: boolean): string => {
- return `text-layer-${layer}-glyph${label_kind ? `-${label_kind}` : ``} ${hide_active ? `` : `group-active:text-layer-${layer}-glyph${label_kind ? `-${label_kind}_a` : `_a`}`}`
-};
-
-export const fmt_textarea_value = (value: string): string => {
- return value.replace(/ /g, `\u00A0`);
-};
-
-export const list_assign = (list_curr: string[], list_new: string[]): string[] => {
- return Array.from(
- new Set([...list_curr, ...list_new]),
- ).filter((i) => !!i);
-};
-
-export const el_id = (id: string): HTMLElement | undefined => {
- const el = document.getElementById(id);
- return el ? el : undefined;
-};
-
-export const el_toggle = (id: string, toggle_class: string): void => {
- const el = document.getElementById(id);
- if (el) el.classList.toggle(toggle_class);
-};
-
-export const els_id_pref = (id_pref: string): Element[] | undefined => {
- const els = document.querySelectorAll(`[id^="${id_pref}"]`);
- if (els && els.length) return Array.from(els);
- return undefined;
-};
-
-export const els_id_pref_index = (id_pref: string, num_index: number, orientation: `greater` | `lesser` | `not` = `greater`, inclusive: boolean = true): Element[] | undefined => {
- const els = document.querySelectorAll(`[id^="${`${id_pref}-`.replaceAll(`--`, `-`)}"]`);
- if (els && els.length) return Array.from(els).filter(el => {
- const match = el.id.match(/(?<=^|\-)[0-9]\d*(?=\-)/)
- if (match) {
- const num = parseInt(match[0], 10);
- switch (orientation) {
- case `greater`: {
- if (inclusive) return num >= num_index;
- else return num > num_index;
- }
- case `lesser`: {
- if (inclusive) return num <= num_index;
- else return num < num_index;
- }
- case `not`: {
- return num !== num_index;
- }
- }
- }
- return false;
- });
- return undefined;
-};
-
-export const el_focus = async (id: string, callback: () => Promise<void>, layer: ThemeLayer = 1): Promise<void> => {
- const el = el_id(id);
- el?.classList.add(`entry-layer-${layer}-highlight`);
- el?.focus();
- await sleep(1200);
- await callback();
- el?.classList.remove(`entry-layer-${layer}-highlight`);
-};
diff --git a/utils/src/browser.ts b/utils/src/browser.ts
@@ -1,92 +0,0 @@
-export type BrowserPlatformInfo = {
- os: string;
- browser: string;
- version: string;
-};
-
-const remove_excess_mozilla_and_version = /^mozilla\/\d\.\d\W/;
-const browser_pattern = /(\w+)\/(\d+\.\d+(?:\.\d+)?(?:\.\d+)?)/g;
-const engine_and_version_pattern = /^(ver|cri|gec)/;
-const brand_list = ['chrome', 'opera', 'safari', 'edge', 'firefox'];
-
-const mobiles: Record<string, RegExp> = {
- iphone: /iphone/,
- ipad: /ipad|macintosh/,
- android: /android/
-};
-
-const desktops: Record<string, RegExp> = {
- windows: /win/,
- mac: /macintosh/,
- linux: /linux/
-};
-
-const parse_user_agent_string = (ua_string: string): BrowserPlatformInfo => {
- const ua = ua_string.toLowerCase().replace(remove_excess_mozilla_and_version, '');
-
- const mobile_os = Object.keys(mobiles).find(
- (key) => mobiles[key].test(ua) && navigator.maxTouchPoints >= 1
- );
- const desktop_os = Object.keys(desktops).find((key) => desktops[key].test(ua));
- const os = mobile_os || desktop_os || '';
-
- const browser_matches = ua.match(browser_pattern);
- const version_regex = /version\/(\d+(\.\d+)*)/;
- const safari_version_match = ua.match(version_regex);
- const safari_version = Array.isArray(safari_version_match) ? safari_version_match[1] : null;
-
- const browser_offset =
- browser_matches && browser_matches.length > 2 && !engine_and_version_pattern.test(browser_matches[1])
- ? 1
- : 0;
- const browser_result =
- browser_matches && browser_matches[browser_matches.length - 1 - browser_offset].split('/');
- const browser = browser_result ? browser_result[0] : '';
- const version = safari_version || (browser_result ? browser_result[1] : '');
-
- return { os, browser, version };
-};
-
-export const browser_platform = (): BrowserPlatformInfo | undefined => {
- if (typeof navigator !== 'undefined') {
- if ('userAgentData' in navigator && navigator.userAgentData) {
- const ua_data = navigator.userAgentData as {
- platform: string;
- brands: { brand: string; version: string }[];
- };
- const os = ua_data.platform.toLowerCase();
- let browser = '';
- let version = '';
-
- if (Array.isArray(ua_data.brands)) {
- for (const { brand, version: brand_version } of ua_data.brands) {
- const lower_brand = brand.toLowerCase();
- if (brand_list.some((b) => lower_brand.includes(b))) {
- browser = lower_brand;
- version = brand_version;
- break;
- }
- }
- }
-
- if (!browser && navigator.userAgent) {
- return parse_user_agent_string(navigator.userAgent);
- }
- return { os, browser, version };
- }
-
- if (navigator.userAgent) {
- return parse_user_agent_string(navigator.userAgent);
- }
-
- const nav_platform = navigator.platform;
- if (!nav_platform) return undefined;
- return {
- os: nav_platform,
- browser: '',
- version: ''
- };
- }
-
- return undefined;
-};
diff --git a/utils/src/client/datastore.ts b/utils/src/client/datastore.ts
@@ -1,23 +0,0 @@
-import type { ResolveError, ResultObj, ResultPass, ResultsList } from "$root";
-
-export type IClientDatastoreSetResolve = ResolveError<ResultPass>;
-export type IClientDatastoreGetResolve = ResolveError<ResultObj<string>>;
-export type IClientDatastoreSetPResolve = ResolveError<ResultPass>;
-export type IClientDatastoreGetPResolve = ResolveError<ResultObj<string>>;
-export type IClientDatastoreKeysResolve = ResolveError<ResultsList<string>>;
-export type IClientDatastoreEntriesResolve = ResolveError<ResultsList<[string, unknown]>>;
-export type IClientDatastoreRemoveResolve = ResolveError<ResultPass>;
-
-export type IClientDatastore<
- TKeyMap extends Record<string, string>,
- TParamKeyMap extends Record<string, (...args: any[]) => string>
-> = {
- init(): Promise<void>;
- set(key: keyof TKeyMap, value: string): Promise<IClientDatastoreSetResolve>;
- get(key: keyof TKeyMap): Promise<IClientDatastoreGetResolve>;
- setp<K extends keyof TParamKeyMap>(key: K, key_param: Parameters<TParamKeyMap[K]>[0], value: string): Promise<IClientDatastoreSetPResolve>;
- getp<K extends keyof TParamKeyMap>(key: K, key_param: Parameters<TParamKeyMap[K]>[0]): Promise<IClientDatastoreGetPResolve>;
- keys(): Promise<IClientDatastoreKeysResolve>;
- entries(): Promise<IClientDatastoreEntriesResolve>
- remove(key: string): Promise<IClientDatastoreRemoveResolve>;
-};
-\ No newline at end of file
diff --git a/utils/src/client/geo.ts b/utils/src/client/geo.ts
@@ -1,11 +0,0 @@
-import type { ErrorMessage, IClientGeolocationPosition } from "$root";
-
-export type IGeolocationErrorMessage =
- | `error.client.geolocation.permission_denied`
- | `error.client.geolocation.location_unavailable`
- | `error.client.geolocation.timeout`
- | `*`;
-
-export type IClientGeolocation = {
- current(): Promise<IClientGeolocationPosition | ErrorMessage<IGeolocationErrorMessage>>;
-};
-\ No newline at end of file
diff --git a/utils/src/client/gui.ts b/utils/src/client/gui.ts
@@ -1,22 +0,0 @@
-export type IClientGuiDialogKind = "info" | "warning" | "error";
-
-export type IClientGuiDialogAlertOpts = string;
-
-export type IClientGuiDialogConfirmOpts = string | { title?: string, kind?: IClientGuiDialogKind; message: string; cancel?: string; ok?: string; };
-
-export type IClientGuiDialogResolve = { results: string[]; };
-
-export type IClientGuiNotifyPermission = "default" | "denied" | "granted";
-export type IClientGuiNotifySendOptions = {
- id?: number;
- channel_id?: string;
- title: string;
- body?: string;
-};
-
-export type IClientGui = {
- alert(opts: IClientGuiDialogAlertOpts): Promise<boolean>;
- confirm(opts: IClientGuiDialogConfirmOpts): Promise<boolean>;
- notify_init(): Promise<IClientGuiNotifyPermission | undefined>;
- notify_send(opts: string | IClientGuiNotifySendOptions): Promise<void>;
-};
-\ No newline at end of file
diff --git a/utils/src/config.ts b/utils/src/config.ts
@@ -1,19 +0,0 @@
-export const cfg_map = {
- styles: {
- base: {
- light: `https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json`,
- dark: `https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json`
- }
- },
- popup: {
- dot: {
- offset: [0, -10] as [number, number]
- }
- },
- coords: {
- default: {
- lat: 0,
- lng: 0,
- }
- }
-};
-\ No newline at end of file
diff --git a/utils/src/currency.ts b/utils/src/currency.ts
@@ -1,46 +0,0 @@
-import { util_rxp } from "$root";
-
-export type FiatCurrency = `usd` | `eur`;
-export const fiat_currencies: FiatCurrency[] = [`usd`, `eur`] as const;
-
-// @todo
-export const price_to_formatted = (n: number, _currency: string) => Math.round(n * 100) / 100;
-
-export const parse_currency = (val?: string): FiatCurrency => {
- const cur = val?.trim().toLowerCase()
- switch (cur) {
- case `usd`:
- case `eur`:
- return cur;
- default:
- return `usd`;
- };
-};
-
-export const fmt_price = (locale: string, value: string, currency: string): string => {
- const fmt = new Intl.NumberFormat(locale, {
- style: 'currency',
- currency: currency.toUpperCase(),
- minimumFractionDigits: 2,
- maximumFractionDigits: 2
- });
- return fmt.format(parseFloat(value));
-};
-
-export const parse_currency_marker = (locale: string, currency: string): string => {
- const cur = parse_currency(currency);
- const fmt = new Intl.NumberFormat(locale, {
- style: 'currency',
- currency: cur.toUpperCase(),
- minimumFractionDigits: 2,
- });
- const fmt_basis = fmt.format(1);
- let fmt_res: string | undefined = undefined;
- fmt_res = fmt_basis.match(util_rxp.currency_marker)?.[0];
- if (fmt_res) return fmt_res;
- fmt_res = fmt_basis.match(util_rxp.currency_symbol)?.[0];
- if (fmt_res) return fmt_res;
- fmt_res = fmt_basis.match(new RegExp(cur, `i`))?.[0];
- if (fmt_res) return fmt_res;
- return cur.toUpperCase();
-};
-\ No newline at end of file
diff --git a/utils/src/error.ts b/utils/src/error.ts
@@ -1,24 +0,0 @@
-export type IErrorCatchCallback = {
- name: string;
- message: string;
- stack: string;
- url: string;
- func: string;
-};
-
-export type ErrorMessage<T extends string> = { err: T };
-
-export const err_msg = <T extends string>(err: T): ErrorMessage<T> => {
- return { err };
-};
-
-export const throw_err = (param: string | ErrorMessage<string>): never => {
- if (typeof param === `string`) throw new Error(param);
- else throw new Error(param.err);
-};
-
-export const handle_error = (e: unknown, append?: string): ErrorMessage<string> => {
- const msg = (e as Error).message ? (e as Error).message : String(e);
- const err = `${msg}${append ? ` ${append}` : ``}`;
- return { err };
-};
-\ No newline at end of file
diff --git a/utils/src/errors/lib.ts b/utils/src/errors/lib.ts
@@ -0,0 +1,16 @@
+import { ErrorMessage } from "../types/lib.js";
+
+export const err_msg = <T extends string>(err: T): ErrorMessage<T> => {
+ return { err };
+};
+
+export const throw_err = (param: string | ErrorMessage<string>): never => {
+ if (typeof param === `string`) throw new Error(param);
+ else throw new Error(param.err);
+};
+
+export const handle_error = (e: unknown, append?: string): ErrorMessage<string> => {
+ const msg = (e as Error).message ? (e as Error).message : String(e);
+ const err = `${msg}${append ? ` ${append}` : ``}`;
+ return { err };
+};
+\ No newline at end of file
diff --git a/utils/src/geo.ts b/utils/src/geo.ts
@@ -1,278 +0,0 @@
-import { LocationBasis, type GeolocationPointTuple, type GeometryPoint } from "$root";
-import { decodeBase32, encodeBase32 } from "geohashing";
-
-export type GeolocationAddress = {
- primary: string;
- admin: string;
- country: string;
-};
-
-export type GeolocationPoint = {
- lat: number;
- lng: number;
-};
-
-export type LocationPoint = GeolocationCoordinatesPoint & {
- error: GeolocationCoordinatesPoint;
-}
-
-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 = {
- lat: number;
- lng: number;
- accuracy?: number;
- altitude?: number;
- altitude_accuracy?: number;
-};
-
-export type GeolocationCoordinatesPoint = {
- lat: number;
- lng: number;
-}
-
-export type GeolocationLatitudeFmtOption = 'dms' | 'd' | 'dm';
-
-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: GeolocationCoordinatesPoint): string => {
- const { lat, lng } = point;
- const res = geohash_encode({ lat, lng });
- return res;
-};
-
-export const parse_geop_point = (point: GeolocationCoordinatesPoint): 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);
-
- const R = 6371;
-
- 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 / R;
-
- 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);
-
- const R = 6371;
-
- 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 / R;
-
- 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 location_gcs_to_location_basis = ({
- id,
- lat,
- lng,
- gc_name: primary,
- gc_admin1_name: admin,
- gc_country_id: country,
-}: {
- id: string;
- lat: number;
- lng: number;
- gc_name?: string;
- gc_admin1_name?: string;
- gc_country_id?: string;
-}): LocationBasis => ({
- id,
- point: {
- lat,
- lng,
- },
- address: primary && admin && country ? {
- primary,
- admin,
- country,
- } : undefined
-});
-
diff --git a/utils/src/http.ts b/utils/src/http.ts
@@ -1,110 +0,0 @@
-import { is_error_response, is_message_response, type ErrorMessage, type FieldRecord, type NotifyMessage } from "$root";
-
-export type IClientHttp = {
- fetch(opts: IHttpOpts): Promise<IHttpResponse | ErrorMessage<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): BodyInit => {
- 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;
- return {
- url,
- options
- }
-};
-
-export const lib_http_parse_response = async (res: Response): Promise<Promise<IHttpResponse>> => {
- let data: any = null;
- try {
- const res_json = await res.json();
- if (typeof res_json === `string`) data = JSON.parse(res_json);
- else data = res_json;
- } catch { }
- if (!data) data = await res.text();
- 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/i18n.ts b/utils/src/i18n.ts
@@ -1,51 +0,0 @@
-import { type Loader } from '@sveltekit-i18n/base';
-import type { Config as ConfigIcu, Parser as ParserIcu } from "@sveltekit-i18n/parser-icu";
-import parser_icu from "@sveltekit-i18n/parser-icu";
-import i18n, { type Config } from 'sveltekit-i18n';
-
-type LanguageConfig = {
- default?: string;
- value?: string;
-};
-
-const lib_config: Config<LanguageConfig> = {
- initLocale: `en`,
- fallbackLocale: `en`,
- translations: {},
- loaders: [],
-};
-
-const lib_i18n = new i18n(lib_config);
-export type I18nTranslateFunction = typeof lib_i18n.t;
-export type I18nTranslateLocale = typeof lib_i18n.locale;
-
-export const i18n_conf = <T extends string>(opts: {
- default_locale: T;
- translations: Record<T, any>;
- loaders: Loader.LoaderModule[]
-}) => {
- const { default_locale: initLocale, translations, loaders } = opts;
- const config: Config<LanguageConfig> = {
- initLocale,
- fallbackLocale: initLocale,
- translations,
- loaders,
- };
- return new i18n(config);
-};
-
-export const i18n_conf_icu = <T extends string>(opts: {
- default_locale: T;
- translations: Record<T, any>;
- loaders: Loader.LoaderModule[]
-}): i18n<ParserIcu.Params<LanguageConfig>> => {
- const { default_locale: initLocale, translations, loaders } = opts;
- const config: ConfigIcu<LanguageConfig> = {
- initLocale,
- fallbackLocale: initLocale,
- translations,
- parser: parser_icu(),
- loaders,
- };
- return new i18n(config);
-};
-\ No newline at end of file
diff --git a/utils/src/image.ts b/utils/src/image.ts
@@ -1,21 +0,0 @@
-import { type FilePath } from "$root";
-
-export type MediaImageUploadResult = {
- base_url: string;
- file_hash: string;
- file_ext: string;
-};
-
-export const fmt_media_image_upload_result_url = (res: MediaImageUploadResult): string => `${res.base_url}/${res.file_hash}.${res.file_ext}`;
-
-export const parse_file_path = (file_path: string): FilePath | undefined => {
- const file_path_spl = file_path.split(`/`);
- const file_path_file = file_path_spl[file_path_spl.length - 1] || ``;
- const [file_name, mime_type] = file_path_file.split(`.`);
- if (!file_name || !mime_type) return undefined;
- return {
- file_path,
- file_name,
- mime_type
- };
-};
-\ No newline at end of file
diff --git a/utils/src/index.ts b/utils/src/index.ts
@@ -1,33 +1,2 @@
-export * from "./*regex"
-export * from "./*validation"
-export * from "./app/config"
-export * from "./app/glyph"
-export * from "./app/lib"
-export * from "./app/search"
-export * from "./app/styles"
-export * from "./app/util"
-export * from "./browser"
-export * from "./client/datastore"
-export * from "./client/geo"
-export * from "./client/gui"
-export * from "./config"
-export * from "./currency"
-export * from "./error"
-export * from "./geo"
-export * from "./http"
-export * from "./i18n"
-export * from "./image"
-export * from "./lib"
-export * from "./list"
-export * from "./listings/order"
-export * from "./model"
-export * from "./models/farm"
-export * from "./models/location"
-export * from "./number"
-export * from "./object"
-export * from "./response"
-export * from "./time"
-export * from "./trade"
-export * from "./types"
-export * from "./unit"
-export * from "./uuid"
+export * from "./errors/lib.js"
+export * from "./types/lib.js"
diff --git a/utils/src/lib.ts b/utils/src/lib.ts
@@ -1,67 +0,0 @@
-import { type CallbackPromise } from "./types";
-
-export const symbols = {
- bullet: '•',
- dash: `—`,
- up: `↑`,
- down: `↓`,
- percent: `%`
-}
-
-export const root_symbol = "»--`--,---";
-
-export const sleep = async (ms: number): Promise<void> => {
- await new Promise((resolve) => setTimeout(resolve, ms));
-};
-
-export const obj_keys_maxnum = (obj: any): number => Math.max(
- ...Object.keys(obj).map(Number),
-);
-
-export const debounce_callback = (func: Function, delay: number) => {
- let timer: ReturnType<typeof setTimeout>;
- return function (this: any, ...args: any) {
- clearTimeout(timer);
- timer = setTimeout(() => func.apply(this, args), delay);
- };
-};
-
-export const str_trunc = (val: string, max_length: number = 28): string => {
- if (val.length <= max_length) return val;
- return `${val.slice(0, max_length - 3)}...`;
-};
-
-export const str_capitalize_words = (val?: string): string => {
- if (!val) return ``;
- return val.split(` `).map(i => i ? `${i[0].toUpperCase()}${i.slice(1)}` : ``).filter(i => !!i).join(` `);
-};
-
-export const exe_iter = async (callback: CallbackPromise, num: number = 1, delay: number = 400): Promise<void> => {
- try {
- const iter_fn = (count: number) => {
- if (count > 0) {
- callback();
- if (count > 1) {
- setTimeout(() => {
- iter_fn(count - 1);
- }, delay);
- }
- }
- };
- iter_fn(num);
- } catch (e) {
- console.log(`(error) exe_iter `, e);
- }
-};
-
-
-export const fmt_tags_key = (...args: (string | number | undefined)[]) =>
- args.filter(Boolean).join("-").toLowerCase();
-
-export const compare_str_eq = (a: string, b: string): boolean => {
- return a.toLowerCase() === b.toLowerCase();
-};
-
-export const compare_str_ne = (a: string, b: string): boolean => {
- return a.toLowerCase() !== b.toLowerCase();
-};
-\ No newline at end of file
diff --git a/utils/src/list.ts b/utils/src/list.ts
@@ -1 +0,0 @@
-export const list_defined = (i: any): boolean => typeof i !== `undefined`;
-\ No newline at end of file
diff --git a/utils/src/listings/order.ts b/utils/src/listings/order.ts
@@ -1,145 +0,0 @@
-import { compare_str_ne, fmt_tags_key, mass_to_g, parse_mass_unit, price_to_formatted, symbols } from "$root";
-import type { ListingOrder, ListingOrderDiscount } from "@radroots/radroots-common-bindings";
-
-export type IListingOrderCreate = {
- tags_prices: string[][];
- tags_quantities: string[][];
- tags_discounts: string[][];
- quantity: {
- amount: number;
- unit: string;
- count: number;
- };
-};
-
-export const listing_order_create = (opts: IListingOrderCreate): ListingOrder => {
- const {
- tags_prices, tags_quantities, tags_discounts,
- quantity: { amount: qty_amt, unit: qty_unit, count: qty_count }
- } = opts;
-
- const qty_key = fmt_tags_key(qty_amt, qty_unit);
- const qty_tag = tags_quantities.find(t => fmt_tags_key(t[1], t[2]) === qty_key);
- if (!qty_tag) throw new Error(`invalid quantity tag`);
-
- const [, qty_tag_amt, qty_tag_unit, qty_tag_label] = qty_tag;
- const qty_unit_parsed = parse_mass_unit(qty_tag_unit);
- if (!qty_unit_parsed) throw new Error(`invalid quantity unit`);
-
- const price_qty_key = fmt_tags_key(qty_tag_amt, qty_tag_unit, qty_tag_label);
- const price_tag = tags_prices.find(t => t[5]?.toLowerCase() === price_qty_key);
- if (!price_tag) throw new Error(`invalid price tag`);
-
- const [, price_tag_amt, price_tag_currency, price_tag_qty_amt, price_tag_qty_unit] = price_tag;
- const price_unit_parsed = parse_mass_unit(price_tag_qty_unit);
- if (!price_unit_parsed) throw new Error(`invalid price unit`);
-
- const qty_amt_num = parseFloat(qty_tag_amt);
- const price_amt = parseFloat(price_tag_amt);
- const price_qty_amt = parseFloat(price_tag_qty_amt);
-
- const mass_g = mass_to_g(qty_amt_num * qty_count, qty_tag_unit);
- const price_group_g = mass_to_g(price_qty_amt, price_tag_qty_unit);
- const group_count = mass_g / price_group_g;
- const subtotal = price_to_formatted(group_count * price_amt, price_tag_currency);
-
- const discounts: ListingOrderDiscount[] = [];
-
- for (const discount of tags_discounts) {
- const discount_type = discount[0];
-
- if (discount_type === `price-discount-subtotal`) {
- const [, threshold_str, currency, value_str, mode] = discount;
- if (compare_str_ne(currency, price_tag_currency)) continue;
- const threshold = parseFloat(threshold_str);
- if (subtotal < threshold) continue;
-
- if (mode === symbols.percent) {
- const percent = parseFloat(value_str);
- discounts.push({
- discount_type: `subtotal`,
- threshold,
- discount_percent: percent,
- discount_amount: price_to_formatted(subtotal * percent / 100, currency),
- currency
- });
- } else {
- const amount = parseFloat(value_str);
- discounts.push({
- discount_type: `subtotal`,
- threshold,
- discount_amount: price_to_formatted(amount, currency),
- currency
- });
- }
- }
-
- if (discount_type === `price-discount-mass`) {
- const [, discount_unit, threshold_str, threshold_unit, per_unit_str, currency] = discount;
- if (compare_str_ne(currency, price_tag_currency)) continue;
- const threshold = parseFloat(threshold_str);
- const mass_in_threshold = mass_g / mass_to_g(1, threshold_unit);
- if (mass_in_threshold < threshold) continue;
-
- const per_unit = parseFloat(per_unit_str);
- const unit_count = mass_g / mass_to_g(1, discount_unit);
- discounts.push({
- discount_type: `mass`,
- threshold,
- threshold_unit,
- discount_per_unit: per_unit,
- discount_unit,
- discount_amount: price_to_formatted(unit_count * per_unit, currency),
- currency
- });
- }
-
- if (discount_type === `price-discount-quantity`) {
- const [, key, min_str, per_unit_str, currency] = discount;
- if (compare_str_ne(currency, price_tag_currency)) continue;
- if (key !== price_qty_key) continue;
- const min = parseInt(min_str);
- if (qty_count < min) continue;
- const per_unit = parseFloat(per_unit_str);
- discounts.push({
- discount_type: `quantity`,
- threshold: min,
- discount_per_unit: per_unit,
- discount_amount: price_to_formatted(per_unit * qty_count, currency),
- currency
- });
- }
- }
-
- const total_discount = price_to_formatted(discounts.reduce((acc, d) => acc + d.discount_amount, 0), price_tag_currency);
- const subtotal_amt = price_to_formatted(subtotal, price_tag_currency);
- const total_amt = price_to_formatted(subtotal - total_discount, price_tag_currency);
-
- return {
- quantity: {
- amount: qty_amt_num,
- unit: qty_unit_parsed,
- label: qty_tag_label,
- count: qty_count,
- },
- price: {
- amount: price_amt,
- currency: price_tag_currency,
- quantity_amount: price_qty_amt,
- quantity_unit: price_unit_parsed
- },
- discounts,
- subtotal: {
- price_amount: subtotal_amt,
- price_currency: price_tag_currency,
- quantity_amount: qty_amt_num * qty_count,
- quantity_unit: qty_tag_unit
- },
- total: {
- price_amount: total_amt,
- price_currency: price_tag_currency,
- quantity_amount: qty_amt_num * qty_count,
- quantity_unit: qty_tag_unit
- }
- };
-};
diff --git a/utils/src/model.ts b/utils/src/model.ts
@@ -1,129 +0,0 @@
-export type IModelsQueryValue = string | number | boolean | null;
-export type IModelsQueryBindValue = string | number | boolean | null;;
-export type IModelsQueryBindValueTuple = [string, IModelsQueryValue];
-export type IModelsQueryBindValueOpt = (IModelsQueryBindValue | null);
-export type IModelsQueryFilterOption = `equals` | `starts-with` | `ends-with` | `contains` | `ne`;
-export type IModelsQueryFilterOptionList = `between` | `in`;
-export type IModelsQueryFilterCondition = `and` | `or` | `not`
-
-export type IModelsSortCreatedAt = 'newest' | 'oldest';
-export type IModelsQueryParam = { query: string; bind_values: IModelsQueryBindValue[] };
-export type IModelsFormErrorTuple = [boolean, string];
-export type IModelsFormValidationTuple = [RegExp, string];
-export type IModelsSchemaErrors = { err_s: string[]; };
-export type IModelsForm = {
- label?: string;
- placeholder?: string;
- validateKeypress?: boolean;
- preventFocusRest?: boolean;
- validation: RegExp;
- charset: RegExp;
- hidden?: boolean;
- optional?: boolean;
- default?: string | number;
-};
-
-export type IModelQueryFilterMapValuesTuplesOption = [IModelsQueryValue, IModelsQueryFilterOption];
-export type IModelQueryFilterMapValuesTuplesOptionList = [IModelsQueryValue[], IModelsQueryFilterOptionList];
-export type IModelQueryFilterMapValuesTuples = ModelQueryFilterMapTuple<IModelQueryFilterMapValuesTuplesOption> | ModelQueryFilterMapTuple<IModelQueryFilterMapValuesTuplesOptionList>;
-export type IModelQueryFilterMapValues = IModelsQueryValue | IModelQueryFilterMapValuesTuples;
-
-export type ModelQueryFilterMapTupleBasis =
- | [IModelsQueryValue, IModelsQueryFilterOption]
- | [IModelsQueryValue, IModelsQueryFilterOption, IModelsQueryFilterCondition]
- | [IModelsQueryValue[], IModelsQueryFilterOptionList]
- | [IModelsQueryValue[], IModelsQueryFilterOptionList, IModelsQueryFilterCondition];
-
-export type ModelQueryFilterMapTuple<T extends ModelQueryFilterMapTupleBasis> =
- T extends [IModelsQueryValue, IModelsQueryFilterOption]
- ? [IModelsQueryValue, IModelsQueryFilterOption, IModelsQueryFilterCondition]
- : T extends [IModelsQueryValue[], IModelsQueryFilterOptionList]
- ? [IModelsQueryValue[], IModelsQueryFilterOptionList, IModelsQueryFilterCondition]
- : T;
-
-export type IModelQueryFilterMap<ModelFilter extends object> = {
- [K in keyof ModelFilter]: ModelFilter[K] | [ModelFilter[K], IModelsQueryFilterOption] | [ModelFilter[K], IModelsQueryFilterOption, IModelsQueryFilterCondition] | [ModelFilter[K][], IModelsQueryFilterOptionList] | [ModelFilter[K][], IModelsQueryFilterOptionList, IModelsQueryFilterCondition];
-};
-export type IModelQueryFilterMapParsed = { query_values: string[]; bind_values: IModelsQueryValue[]; };
-
-export const parse_model_query_value = (val: IModelsQueryValue): IModelsQueryBindValue => {
- if (typeof val === `boolean`) return val ? '1' : '0';
- else if (typeof val === `number`) return val;
- else if (typeof val === `string` && val) return val;
- return null;
-};
-
-export const is_model_query_filter_option = (value: string): value is IModelsQueryFilterOption => {
- return ['equals', 'starts-with', 'ends-with', 'contains', 'ne'].includes(value);
-}
-
-export const is_model_query_filter_option_list = (value: string): value is IModelsQueryFilterOptionList => {
- return ['between', 'in'].includes(value);
-}
-
-export const is_model_query_values = (value: unknown): value is IModelsQueryValue => {
- return typeof value === `string` || typeof value === `number` || typeof value === `boolean`;
-}
-
-export const list_model_query_values_assert = (arr: (IModelsQueryValue | undefined)[]): (IModelsQueryValue)[] => {
- return arr.filter((item): item is string | number | boolean => item !== undefined);
-}
-
-export const parse_model_filter_map = <T extends object>(opts: IModelQueryFilterMap<T>): IModelQueryFilterMapParsed => {
- const bind_values: IModelsQueryValue[] = [];
- const query_values: string[] = [];
-
- for (const [index, entry] of Object.entries(opts).entries()) {
- const [field, filters] = entry as [string, IModelQueryFilterMapValues];
-
- if (is_model_query_values(filters)) {
- query_values.push(`${field} = ?`);
- bind_values.push(filters);
- } else if (Array.isArray(filters)) {
- const [filters_val, filters_opt] = filters;
- const filter_condition = index === 0 ? `` : typeof filters[2] === `undefined` ? `AND ` : ` ${filters[2]}`;
- if (is_model_query_values(filters_val) && is_model_query_filter_option(filters_opt)) {
- switch (filters_opt) {
- case `starts-with`: {
- query_values.push(`${filter_condition}${field} LIKE ?`);
- bind_values.push(`${filters[0]}%`);
- } break;
- case `ends-with`: {
- query_values.push(`${filter_condition}${field} LIKE ?`);
- bind_values.push(`%${filters[0]}`);
- } break;
- case `contains`: {
- query_values.push(`${filter_condition}${field} LIKE ?`);
- bind_values.push(`%${filters[0]}%`);
- } break;
- case `ne`: {
- query_values.push(`${filter_condition}${field} != ?`);
- bind_values.push(`${filters[0]}`);
- } break;
- case `equals`: {
- query_values.push(`${filter_condition}${field} = ?`);
- bind_values.push(filters[0]);
- } break;
- default:
- throw new Error("util.model.parse_model_filter_map.invalid_condition");
- };
- } else if (is_model_query_filter_option_list(filters_opt)) {
- switch (filters_opt) {
- case `between`: {
- query_values.push(`${filter_condition}${field} BETWEEN ? AND ?`);
- bind_values.push(...filters[0].slice(0, 2));
- } break;
- case `in`: {
- query_values.push(`${filter_condition}${field} IN (${`? `.repeat(filters[0].length).trim().split(" ").join(", ")})`);
- bind_values.push(...list_model_query_values_assert(filters[0]));
- } break;
- default:
- throw new Error("util.model.parse_model_filter_map.invalid_condition");
- };
- }
- }
- }
- if (!query_values.length) throw new Error("Error: invalid filter.");
- if (!bind_values.length) throw new Error("Error: invalid filter.");
- return { query_values, bind_values };
-};
diff --git a/utils/src/models/farm.ts b/utils/src/models/farm.ts
@@ -1,20 +0,0 @@
-import type { LocationBasis } from "$root";
-
-export type FarmExtended = {
- farm: FarmBasis;
- location?: LocationBasis;
- lots?: FarmLotBasis[];
-};
-
-export type FarmBasis = {
- id: string;
- name: string;
- area?: string;
- area_unit?: string;
-};
-
-export type FarmLotBasis = {
- id: string;
- location?: LocationBasis;
-};
-
diff --git a/utils/src/models/location.ts b/utils/src/models/location.ts
@@ -1,7 +0,0 @@
-import { GeolocationAddress, GeolocationPoint } from "$root";
-
-export type LocationBasis = {
- id: string;
- point: GeolocationPoint;
- address?: GeolocationAddress;
-};
-\ No newline at end of file
diff --git a/utils/src/number.ts b/utils/src/number.ts
@@ -1,13 +0,0 @@
-export const parse_int = (val: string, fallback: number = 0): number => {
- const num = parseInt(val);
- return isNaN(num) ? fallback : num;
-};
-
-export const parse_float = (val: string, fallback: number = 0): number => {
- const num = parseFloat(val);
- return isNaN(num) ? fallback : num;
-};
-
-export const num_str = (num: number): string => num.toString();
-
-export const num_interval_range = (min: number, max: number): number => Math.floor(Math.random() * (max - min + 1)) + min;
diff --git a/utils/src/object.ts b/utils/src/object.ts
@@ -1,17 +0,0 @@
-export const obj_en = <KeyType extends string, ValType>(object: Record<string, ValType>, parse_function: (key: string) => KeyType = (i) => i as KeyType): [KeyType, ValType][] => {
- return Object.entries(object).map<[KeyType, ValType]>(([k, v]) => [parse_function(k), v])
-};
-
-export const obj_truthy_fields = (obj: Record<string, string>): boolean => {
- return Object.values(obj).every(Boolean);
-};
-
-export const obj_result = (obj: any): string | undefined => {
- if (`result` in obj && typeof obj.result === `string`) return obj.result;
- return undefined;
-};
-
-export const obj_results_str = (obj: any): string[] | undefined => {
- if (Array.isArray(obj.results)) return obj.results.map(String);
- return undefined;
-};
-\ No newline at end of file
diff --git a/utils/src/response.ts b/utils/src/response.ts
@@ -1,32 +0,0 @@
-import type { NotifyMessage } from "$root";
-
-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")
- );
-};
-\ No newline at end of file
diff --git a/utils/src/time.ts b/utils/src/time.ts
@@ -1,5 +0,0 @@
-export const time_now_ms = (): number => Math.floor(new Date().getTime() / 1000);
-
-export const time_created_on = (): string => new Date().toISOString();
-
-export const year_curr = (): string => new Date().getFullYear().toString();
-\ No newline at end of file
diff --git a/utils/src/trade.ts b/utils/src/trade.ts
@@ -1,233 +0,0 @@
-import { parse_int, parse_mass_unit, type MassUnit } from "$root";
-
-export type TradeKey = `coffee` | `cacao` | `maca`;
-
-export type TradeQuantityMass = {
- mass: number;
- mass_unit: MassUnit;
-}
-export type TradeQuantity = TradeQuantityMass & {
- label: string;
-};
-
-export const fmt_trade_quantity_tup = (obj: TradeQuantity): string => `${obj.mass}-${obj.mass_unit}-${obj.label}`;
-
-export const parse_trade_quantity_tup = (sel_key: string): TradeQuantity | undefined => {
- const [qty_mass, qty_mass_u, qty_label] = sel_key.split(`-`);
- const mass_unit = parse_mass_unit(qty_mass_u);
- if (!qty_mass || !qty_mass_u || !qty_label || !mass_unit) return undefined;
- return {
- mass: parse_int(qty_mass, 1),
- mass_unit,
- label: qty_label
- }
-};
-
-export const trade_keys: TradeKey[] = [`coffee`, `cacao`, `maca`] as const;
-
-const trade_quantity_default: TradeQuantity[] = [
- {
- label: `bag`,
- mass: 10,
- mass_unit: `kg`
- },
- {
- label: `bag`,
- mass: 5,
- mass_unit: `kg`
- },
- {
- label: `bag`,
- mass: 25,
- mass_unit: `kg`
- },
-];
-
-const TRADE_PROCESS_DEFAULT = `natural`;
-
-//@todo
-const trade_process_default: string[] = [
- TRADE_PROCESS_DEFAULT,
- `dried`,
- `roasted`
-];
-
-export type TradeParam = {
- default: {
- quantity: TradeQuantity[];
- process: string[];
- },
- key: Record<TradeKey, {
- quantity: TradeQuantity[];
- process: string[];
- flavor: string[];
- }>;
-};
-
-export const trade: TradeParam = {
- default: {
- quantity: trade_quantity_default,
- process: trade_process_default,
- },
- key: {
- coffee: {
- quantity: [
- {
- label: `bag`,
- mass: 60,
- mass_unit: `kg`
- },
- {
- label: `bag`,
- mass: 69,
- mass_unit: `kg`
- },
- {
- label: `bag`,
- mass: 30,
- mass_unit: `kg`
- },
- ],
- process: [
- `washed`,
- `natural`,
- `honey`,
- `semi_washed`,
- `wet_hulled`,
- `dry`,
- `pulped_natural`,
- `carbonic_maceration`
- ],
- flavor: [
- `natural`,
- `bergamot`,
- `jasmine honeysuckle`,
- `orange`,
- `blueberry`,
- `apricot`,
- `black tea`,
- `raspberry`,
- `nougat`,
- `milk chocolate`,
- `peach`,
- `vanilla`,
- `berry`,
- `nut`,
- `brown sugar`,
- `grape`,
- `raisin`,
- `red apple`,
- `sweet bread pastry`,
- `pineapple`,
- `star fruit`,
- `mango`,
- `grapefruit`,
- `nectarine`,
- `red grape`,
- `maple syrup`,
- `dark chocolate`,
- `orange blossom`,
- `marshmallow`,
- `mandarin`,
- `dried dates`,
- `prune`,
- `green apple`,
- `licorice/anise`,
- `cranberry`,
- `caramel`,
- `chocolate`,
- `lemon`,
- `golden raisin`,
- `black cherry`,
- `plum`,
- `black currant`,
- `roses`,
- `cola`,
- `banana`,
- `red currant`,
- `white grape`,
- `green tea`,
- `lychee`,
- `tamarind`,
- `dried fig`,
- `green grape`,
- `sugar cane`,
- `cherry`,
- `magnolia`,
- `tropical fruit`,
- `ctrius`,
- `stronefruit`
- ],
- },
- cacao: {
- quantity: [
- ...trade_quantity_default
- ],
- process: [
- `raw`,
- `fermented`,
- `dried`,
- `roasted`,
- `cocoa_powder`,
- `cocoa_butter`,
- `chocolate`
- ],
- flavor: []
- },
- maca: {
- quantity: [
- {
- label: `bag`,
- mass: 1,
- mass_unit: `kg`
- },
- {
- label: `bag`,
- mass: 100,
- mass_unit: `g`
- },
- ...trade_quantity_default
- ],
- process: [
- `raw`,
- `powdered`,
- `roasted`,
- `gelatinized`,
- `capsules`
- ],
- flavor: []
- }
- }
-};
-
-export function parse_trade_key(val?: string): TradeKey | undefined {
- switch (val) {
- case "coffee":
- case "cacao":
- case "maca":
- return val;
- default:
- return undefined;
- };
-};
-
-export const trade_key_default_process = (val?: string): string => {
- const key = parse_trade_key(val);
- if (!key) return TRADE_PROCESS_DEFAULT;
- return trade.key[key].process[0];
-};
-
-export function parse_trade_mass_tuple(val?: string): [number, MassUnit, string] | undefined {
- if (!val) return;
- const vals = val.split('-');
- if (vals.length !== 3) return;
- const mass = vals[0];
- const mass_unit = vals[1];
- const label = vals[2];
- const amt = parseInt(mass || `0`, 10);
- if (isNaN(amt) || amt <= 0) return;
- const units = parse_mass_unit(mass_unit);
- if (!units) return;
- if (typeof label !== `string` || !label) return;
- return [amt, units, label]
-}
-\ No newline at end of file
diff --git a/utils/src/types.ts b/utils/src/types.ts
@@ -1,41 +0,0 @@
-import { ErrorMessage } from "$root";
-
-export type FieldRecord = Record<string, string>;
-export type NotifyMessage = {
- message: string;
- ok?: string;
- cancel?: string;
-};
-
-export type GeometryPoint = {
- type: string;
- coordinates: number[];
-};
-
-export type GeometryPolygon = {
- type: string;
- coordinates: number[][][];
-};
-
-export type GeolocationPointTuple = [number, number];
-
-export type ResultId = { id: string; };
-export type ResultPass = { pass: true; };
-export type ResultsList<T> = { results: T[]; };
-export type ResultObj<T> = { result: T; };
-export type ResultPublicKey = { public_key: string; };
-export type ResultSecretKey = { secret_key: string; };
-
-export type ResolveError<T> = T | ErrorMessage<string>;
-export type ResolveErrorMsg<TRes, TMsg extends string> = TRes | ErrorMessage<TMsg>;
-
-export type FileBytesFormat = `kb` | `mb` | `gb`;
-export type FileMimeType = string;
-export type FilePath = { file_path: string; file_name: string; mime_type: FileMimeType; }
-
-export type CallbackPromise = () => Promise<void>;
-export type CallbackPromiseFigureResult<Ti, Tr> = (value: Ti) => Promise<Tr | undefined>;
-export type CallbackPromiseFull<Ti, Tr> = (value: Ti) => Promise<Tr>;
-export type CallbackPromiseGeneric<T> = (value: T) => Promise<void>;
-export type CallbackPromiseReturn<T> = () => Promise<T>;
-export type CallbackPromiseResult<Tr> = () => Promise<Tr | undefined>;
-\ No newline at end of file
diff --git a/utils/src/types/lib.ts b/utils/src/types/lib.ts
@@ -0,0 +1,18 @@
+export type CallbackPromise = () => Promise<void>;
+export type CallbackPromiseFigureResult<Ti, Tr> = (value: Ti) => Promise<Tr | undefined>;
+export type CallbackPromiseFull<Ti, Tr> = (value: Ti) => Promise<Tr>;
+export type CallbackPromiseGeneric<T> = (value: T) => Promise<void>;
+export type CallbackPromiseReturn<T> = () => Promise<T>;
+export type CallbackPromiseResult<Tr> = () => Promise<Tr | undefined>;
+
+export type ErrorMessage<T extends string> = { err: T };
+
+export type ResultId = { id: string; };
+export type ResultPass = { pass: true; };
+export type ResultsList<T> = { results: T[]; };
+export type ResultObj<T> = { result: T; };
+export type ResultPublicKey = { public_key: string; };
+export type ResultSecretKey = { secret_key: string; };
+
+export type ResolveError<T> = T | ErrorMessage<string>;
+export type ResolveErrorMsg<TRes, TMsg extends string> = TRes | ErrorMessage<TMsg>;
diff --git a/utils/src/unit.ts b/utils/src/unit.ts
@@ -1,56 +0,0 @@
-import type { zf_area_unit, zf_mass_unit } from "$root";
-import { z } from "zod";
-
-export type AreaUnit = z.infer<typeof zf_area_unit>;
-export const area_units: AreaUnit[] = [`ac`, `ha`, `ft2`, `m2`] as const;
-
-export type MassUnit = z.infer<typeof zf_mass_unit>;
-export const mass_units: MassUnit[] = [`kg`, `lb`, `g`] as const;
-
-export function parse_mass_unit_default(val?: string): MassUnit {
- const unit = parse_mass_unit(val);
- return unit ?? `kg`
-}
-
-export function parse_mass_unit(val?: string): MassUnit | undefined {
- switch (val) {
- case `kg`:
- case `lb`:
- case `g`:
- return val;
- default:
- return undefined;
- };
-};
-
-export function mass_to_g(val: number, unit: string): number {
- const mass_unit = parse_mass_unit(unit);
- switch (mass_unit) {
- case `kg`:
- return val * 1000;
- case `lb`:
- return val * 453.592;
- case `g`:
- return val;
- default:
- throw new Error(`unsupported unit ${unit}`);
- }
-}
-
-
-export function parse_area_unit_default(val?: string): AreaUnit {
- const unit = parse_area_unit(val);
- return unit ?? `ac`
-}
-
-export function parse_area_unit(val?: string): AreaUnit | undefined {
- switch (val) {
- case `ac`:
- case `ha`:
- case `ft2`:
- case `m2`:
- return val;
- default:
- return undefined;
- };
-};
diff --git a/utils/src/uuid.ts b/utils/src/uuid.ts
@@ -1,5 +0,0 @@
-import { v4 } from "uuid";
-
-export function uuidv4() {
- return v4();
-};
-\ No newline at end of file
diff --git a/utils/tsconfig.base.json b/utils/tsconfig.base.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "target": "ES2019",
+ "strict": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "skipLibCheck": true,
+ "sourceMap": false,
+ "rootDir": "src"
+ }
+}
diff --git a/utils/tsconfig.cjs.json b/utils/tsconfig.cjs.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "./dist/cjs",
+ "module": "CommonJS",
+ "declaration": false,
+ "moduleResolution": "Node"
+ },
+ "include": ["src"]
+}
diff --git a/utils/tsconfig.esm.json b/utils/tsconfig.esm.json
@@ -0,0 +1,12 @@
+{
+ "extends": "./tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "./dist/esm",
+ "module": "NodeNext",
+ "declaration": true,
+ "declarationDir": "./dist/types",
+ "moduleResolution": "NodeNext",
+ "emitDeclarationOnly": false
+ },
+ "include": ["src"]
+}
diff --git a/utils/tsconfig.json b/utils/tsconfig.json
@@ -1,28 +0,0 @@
-{
- "compilerOptions": {
- "strict": true,
- "target": "es2021",
- "lib": [
- "es2021",
- "dom"
- ],
- "module": "ESNext",
- "moduleResolution": "node",
- "declaration": true,
- "declarationMap": true,
- "outDir": "./dist",
- "esModuleInterop": true,
- "skipLibCheck": true,
- "baseUrl": ".",
- "paths": {
- "$root": ["src/index.js"]
- }
- },
- "include": [
- "src"
- ],
- "exclude": [
- "node_modules",
- "dist"
- ],
-}
-\ No newline at end of file
diff --git a/utils/tsup.config.ts b/utils/tsup.config.ts
@@ -1,11 +0,0 @@
-import { defineConfig } from "tsup";
-
-export default defineConfig({
- entry: ['src/index.ts'],
- format: ['esm', 'cjs'],
- dts: true,
- outDir: 'dist',
- splitting: false,
- clean: true,
- sourcemap: true,
-});