@ecosy/core 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +40 -198
  2. package/dist/http.d.ts +176 -0
  3. package/dist/http.js +1 -0
  4. package/dist/http.mjs +1 -0
  5. package/dist/index.d.ts +13 -0
  6. package/dist/index.js +1 -1
  7. package/dist/index.mjs +1 -1
  8. package/dist/logger.d.ts +66 -0
  9. package/dist/logger.js +1 -0
  10. package/dist/logger.mjs +1 -0
  11. package/dist/searchify.d.ts +35 -0
  12. package/dist/searchify.js +1 -0
  13. package/dist/searchify.mjs +1 -0
  14. package/dist/serialize.d.ts +80 -0
  15. package/dist/serialize.js +1 -0
  16. package/dist/serialize.mjs +1 -0
  17. package/dist/slugify.d.ts +34 -0
  18. package/dist/slugify.js +1 -0
  19. package/dist/slugify.mjs +1 -0
  20. package/dist/syhemo.d.ts +102 -0
  21. package/dist/syhemo.js +1 -0
  22. package/dist/syhemo.mjs +1 -0
  23. package/dist/types/built-in.d.ts +22 -1
  24. package/dist/utilities/defer.d.ts +53 -0
  25. package/dist/utilities/defer.js +1 -0
  26. package/dist/utilities/defer.mjs +1 -0
  27. package/dist/utilities/filelist.d.ts +25 -0
  28. package/dist/utilities/filelist.js +1 -0
  29. package/dist/utilities/filelist.mjs +1 -0
  30. package/dist/utilities/flatten.d.ts +57 -0
  31. package/dist/utilities/flatten.js +1 -0
  32. package/dist/utilities/flatten.mjs +1 -0
  33. package/dist/utilities/get.d.ts +21 -0
  34. package/dist/utilities/get.js +1 -0
  35. package/dist/utilities/get.mjs +1 -0
  36. package/dist/utilities/index.d.ts +6 -0
  37. package/dist/utilities/index.js +1 -1
  38. package/dist/utilities/index.mjs +1 -1
  39. package/dist/utilities/object-to-formdata.d.ts +26 -0
  40. package/dist/utilities/object-to-formdata.js +1 -0
  41. package/dist/utilities/object-to-formdata.mjs +1 -0
  42. package/dist/utilities/object.js +1 -1
  43. package/dist/utilities/object.mjs +1 -1
  44. package/dist/utilities/pascal-to-kebab.d.ts +15 -0
  45. package/dist/utilities/pascal-to-kebab.js +1 -0
  46. package/dist/utilities/pascal-to-kebab.mjs +1 -0
  47. package/package.json +39 -3
@@ -0,0 +1 @@
1
+ import{DEFAULT_TRANSFORMER as t,slugify as e}from"./slugify.mjs";const i={separator:"",silent:!0,transformer:Object.assign({},t)};function n(t,n){const s=e(n,i),r=s.length,o={matches:[],positions:[]};if(!r)return o;const l=new Map,g=[...t.split("")].map((t,n)=>{let s=l.get(t);return void 0===s&&(s=e(t,i),l.set(t,s)),{originIndex:n,slugified:s,char:t}}).filter((t,e,i)=>0===e||(" "!==t.char||" "!==i[e-1].char));if(g.length<r)return o;for(let e=0;e<g.length;){const i=g[e];if(""===i.slugified){e++;continue}let n="",l=e,f=!0;for(;n.length<r&&l<g.length;){const t=g[l];if(""!==t.slugified&&(n+=t.slugified,!s.startsWith(n))){f=!1;break}l++}if(f&&n===s){const n=g[l-1],s=t.substring(i.originIndex,n.originIndex+1);o.matches.push(s),o.positions.push({start:i.originIndex,length:s.length}),e=l}else e++}return o}export{n as default};
@@ -0,0 +1,80 @@
1
+ import type { LiteralObject } from "./types";
2
+ type Primitive = string | number | boolean | null | undefined | symbol | bigint;
3
+ /** Options for {@link Serialize.queryString.stringify}. */
4
+ export interface SerializeQueryOptions {
5
+ /** Array serialization format. Defaults to `"none"`. */
6
+ arrayFormat?: "bracket" | "index" | "comma" | "separator" | "none";
7
+ /** Separator character when `arrayFormat` is `"separator"`. Defaults to `","`. */
8
+ arrayFormatSeparator?: string;
9
+ /** Skip keys whose value is `null` or `undefined`. */
10
+ skipNull?: boolean;
11
+ /** Skip keys whose value is an empty string. */
12
+ skipEmptyString?: boolean;
13
+ /** Whether to URL-encode keys and values, or a custom encoder function. Defaults to `true`. */
14
+ encode?: boolean | ((value: string) => string);
15
+ /** Reject keys with non-standard characters when `true`. Defaults to `true`. */
16
+ strict?: boolean;
17
+ /** Sort keys alphabetically, or provide a custom comparator. */
18
+ sort?: boolean | ((a: string, b: string) => number);
19
+ }
20
+ /**
21
+ * Centralized serialization engine and type-guard toolkit.
22
+ * Addresses common pitfalls of `JSON.stringify`/`JSON.parse` — BigInt safety,
23
+ * Date preservation, undefined stripping, and safe URL encoding/decoding.
24
+ *
25
+ * All methods are organized into frozen static getters:
26
+ * - `Serialize.Primitive` — type guards and deep normalization
27
+ * - `Serialize.JSON` — safe stringify/parse that never throws
28
+ * - `Serialize.URL` — encode/decode/build with malformed-char recovery
29
+ * - `Serialize.queryString` — parse and stringify query strings
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * Serialize.JSON.stringify({ date: new Date(), big: 123n });
34
+ * Serialize.JSON.parse<User>(jsonText);
35
+ * Serialize.URL.encode("hello world");
36
+ * Serialize.queryString.stringify({ page: 1, tags: ["a", "b"] });
37
+ * ```
38
+ */
39
+ export declare class Serialize {
40
+ /**
41
+ * Interpolates `{key}` placeholders in a string using deep path resolution via {@link get}.
42
+ * Objects are silently replaced with empty strings to avoid `[object Object]`.
43
+ *
44
+ * @param pattern - Template string with `{key}` or `{path.to.key}` placeholders.
45
+ * @param params - Data object or array to resolve values from.
46
+ * @returns The interpolated string.
47
+ */
48
+ static interpolate(pattern: string, params?: Record<string, unknown> | Array<unknown>): string;
49
+ /** Type guards and deep normalization utilities. */
50
+ private static _primitive;
51
+ static get Primitive(): {
52
+ readonly isString: (value: unknown) => value is string;
53
+ readonly isNumber: (value: unknown) => value is number;
54
+ readonly isBoolean: (value: unknown) => value is boolean;
55
+ readonly isPrimitive: (value: unknown) => value is Primitive;
56
+ readonly isDate: (value: unknown) => value is Date;
57
+ readonly isPlainObject: (value: unknown) => value is LiteralObject;
58
+ readonly normalize: <T, R = unknown>(data: T) => R;
59
+ };
60
+ /** Safe JSON stringify/parse that never throws. */
61
+ private static _JSON;
62
+ static get JSON(): {
63
+ readonly stringify: (value: unknown, space?: number) => string;
64
+ readonly parse: <T = unknown>(text: string, reviver?: ((this: any, key: string, value: any) => any) | undefined) => T | null;
65
+ };
66
+ /** URL encoding/decoding with malformed-character recovery. */
67
+ private static _URL;
68
+ static get URL(): {
69
+ readonly encode: (value: string, component?: boolean | ((value: string) => string)) => string;
70
+ readonly decode: (value: string, component?: boolean | ((value: string) => string)) => string;
71
+ readonly build: (uri: string, params?: Record<string, Primitive> | null) => string;
72
+ };
73
+ /** Query string parse/stringify with configurable array formats. */
74
+ private static _queryString;
75
+ static get queryString(): {
76
+ readonly parse: (query: string) => Record<string, string>;
77
+ readonly stringify: (params: Record<string, unknown>, options?: SerializeQueryOptions) => string;
78
+ };
79
+ }
80
+ export {};
@@ -0,0 +1 @@
1
+ "use strict";require("./utilities/clone.js");var e=require("./utilities/is-function.js"),t=require("./utilities/freeze.js"),r=require("./utilities/get.js"),i=require("./utilities/object.js");class n{static interpolate(e,t={}){return e&&"string"==typeof e&&e.trim().length&&e.includes("{")&&e.includes("}")?e.replace(/\{([a-zA-Z0-9_.-]+)\}/g,(e,i)=>{const n=r.get(t,i);return null==n||"object"==typeof n?"":String(n)}):e}static get Primitive(){var r;return null!==(r=n._primitive)&&void 0!==r?r:n._primitive=t.freeze({isString:e=>"string"==typeof e,isNumber:e=>"number"==typeof e&&Number.isFinite(e),isBoolean:e=>"boolean"==typeof e,isPrimitive:e=>!i.isObjectable(e),isDate:e=>e instanceof Date&&!Number.isNaN(e.getTime()),isPlainObject:i.isLiteralObject,normalize(t){const r=n.Primitive;if(r.isPrimitive(t))return"bigint"==typeof t?t.toString():t;if(r.isDate(t))return t.toISOString();if(Array.isArray(t))return t.map(e=>r.normalize(e));if(i.isLiteralObject(t)){const e={};for(const n in t)if(i.hasOwnProperty(t,n)){const i=t[n];void 0!==i&&(e[n]=r.normalize(i))}return e}return t&&i.hasOwnProperty(t,"toJSON")&&e.isFunction(t.toJSON)?t.toJSON():{}}})}static get JSON(){var e;return null!==(e=n._JSON)&&void 0!==e?e:n._JSON=t.freeze({stringify:(e,t)=>{var r;try{const i=n.Primitive.normalize(e);return null!==(r=JSON.stringify(i,null,t))&&void 0!==r?r:""}catch(e){return""}},parse:(e,t)=>{if(!e)return null;try{return JSON.parse(e,t)}catch(e){return null}}})}static get URL(){var e;return null!==(e=n._URL)&&void 0!==e?e:n._URL=t.freeze({encode(e,t=!0){if(!e)return"";if("function"==typeof t)return t(e);try{return t?encodeURIComponent(e):encodeURI(e)}catch(r){const i=e.replace(/[\uD800-\uDFFF]/g,"");return t?encodeURIComponent(i):encodeURI(i)}},decode:(e,t=!0)=>{if(!e)return"";if("function"==typeof t)return t(e);const r=t?decodeURIComponent:decodeURI;return(t?e.replace(/\+/g,"%20"):e).replace(/(%[0-9A-F]{2})+/gi,e=>{try{return r(e)}catch(t){return e}})},build:(e,t)=>e?t&&"object"==typeof t?e.replace(/:([a-zA-Z\d_]+)/g,(e,r)=>{const i=t[r];return null==i?e:n.URL.encode(String(i),!0)}):e:""})}static get queryString(){var e;return null!==(e=n._queryString)&&void 0!==e?e:n._queryString=t.freeze({parse(e){if(!e)return{};const t=e.startsWith("?")?e.slice(1):e,r={};return t.split("&").forEach(e=>{if(!e)return;const[t,i]=e.split("=");t&&(r[n.URL.decode(t)]=i?n.URL.decode(i):"")}),r},stringify(e,t={}){if(null===e||"object"!=typeof e)return"";const{arrayFormat:r="none",arrayFormatSeparator:i=",",skipNull:o=!1,skipEmptyString:s=!1,encode:u=!0,strict:c=!0,sort:a=!1}=t,l=e=>e.length>0&&/^[a-zA-Z0-9_\-.[\]]+$/.test(e),f=e=>u?n.URL.encode(e,u):e,p=[],y=(e,t)=>{if(Array.isArray(t)){if("comma"===r||"separator"===r){const r=t.filter(e=>null!=e&&""!==e);return void(r.length>0&&p.push(`${f(e)}=${f(r.map(String).join(i))}`))}t.forEach((t,i)=>{let n=e;"bracket"===r?n=`${e}[]`:"index"===r&&(n=`${e}[${i}]`),y(n,t)})}else if(n.Primitive.isPlainObject(t))for(const r in t)Object.prototype.hasOwnProperty.call(t,r)&&y(`${e}[${r}]`,t[r]);else null!=t?""!==t?"boolean"!=typeof t?n.Primitive.isDate(t)?p.push(`${f(e)}=${f(t.toISOString())}`):p.push(`${f(e)}=${f(String(t))}`):p.push(`${f(e)}=${t?"true":"false"}`):s||p.push(`${f(e)}=`):o||p.push(`${f(e)}=`)};let g=Object.keys(e);a&&(g="function"==typeof a?g.sort(a):g.sort());for(const t of g)c&&!l(t)||y(t,e[t]);return p.join("&")}})}}exports.Serialize=n;
@@ -0,0 +1 @@
1
+ import"./utilities/clone.mjs";import{isFunction as t}from"./utilities/is-function.mjs";import{freeze as e}from"./utilities/freeze.mjs";import{get as r}from"./utilities/get.mjs";import{isLiteralObject as i,hasOwnProperty as n,isObjectable as o}from"./utilities/object.mjs";class s{static interpolate(t,e={}){return t&&"string"==typeof t&&t.trim().length&&t.includes("{")&&t.includes("}")?t.replace(/\{([a-zA-Z0-9_.-]+)\}/g,(t,i)=>{const n=r(e,i);return null==n||"object"==typeof n?"":String(n)}):t}static get Primitive(){var r;return null!==(r=s._primitive)&&void 0!==r?r:s._primitive=e({isString:t=>"string"==typeof t,isNumber:t=>"number"==typeof t&&Number.isFinite(t),isBoolean:t=>"boolean"==typeof t,isPrimitive:t=>!o(t),isDate:t=>t instanceof Date&&!Number.isNaN(t.getTime()),isPlainObject:i,normalize(e){const r=s.Primitive;if(r.isPrimitive(e))return"bigint"==typeof e?e.toString():e;if(r.isDate(e))return e.toISOString();if(Array.isArray(e))return e.map(t=>r.normalize(t));if(i(e)){const t={};for(const i in e)if(n(e,i)){const n=e[i];void 0!==n&&(t[i]=r.normalize(n))}return t}return e&&n(e,"toJSON")&&t(e.toJSON)?e.toJSON():{}}})}static get JSON(){var t;return null!==(t=s._JSON)&&void 0!==t?t:s._JSON=e({stringify:(t,e)=>{var r;try{const i=s.Primitive.normalize(t);return null!==(r=JSON.stringify(i,null,e))&&void 0!==r?r:""}catch(t){return""}},parse:(t,e)=>{if(!t)return null;try{return JSON.parse(t,e)}catch(t){return null}}})}static get URL(){var t;return null!==(t=s._URL)&&void 0!==t?t:s._URL=e({encode(t,e=!0){if(!t)return"";if("function"==typeof e)return e(t);try{return e?encodeURIComponent(t):encodeURI(t)}catch(r){const i=t.replace(/[\uD800-\uDFFF]/g,"");return e?encodeURIComponent(i):encodeURI(i)}},decode:(t,e=!0)=>{if(!t)return"";if("function"==typeof e)return e(t);const r=e?decodeURIComponent:decodeURI;return(e?t.replace(/\+/g,"%20"):t).replace(/(%[0-9A-F]{2})+/gi,t=>{try{return r(t)}catch(e){return t}})},build:(t,e)=>t?e&&"object"==typeof e?t.replace(/:([a-zA-Z\d_]+)/g,(t,r)=>{const i=e[r];return null==i?t:s.URL.encode(String(i),!0)}):t:""})}static get queryString(){var t;return null!==(t=s._queryString)&&void 0!==t?t:s._queryString=e({parse(t){if(!t)return{};const e=t.startsWith("?")?t.slice(1):t,r={};return e.split("&").forEach(t=>{if(!t)return;const[e,i]=t.split("=");e&&(r[s.URL.decode(e)]=i?s.URL.decode(i):"")}),r},stringify(t,e={}){if(null===t||"object"!=typeof t)return"";const{arrayFormat:r="none",arrayFormatSeparator:i=",",skipNull:n=!1,skipEmptyString:o=!1,encode:u=!0,strict:c=!0,sort:l=!1}=e,a=t=>t.length>0&&/^[a-zA-Z0-9_\-.[\]]+$/.test(t),p=t=>u?s.URL.encode(t,u):t,f=[],m=(t,e)=>{if(Array.isArray(e)){if("comma"===r||"separator"===r){const r=e.filter(t=>null!=t&&""!==t);return void(r.length>0&&f.push(`${p(t)}=${p(r.map(String).join(i))}`))}e.forEach((e,i)=>{let n=t;"bracket"===r?n=`${t}[]`:"index"===r&&(n=`${t}[${i}]`),m(n,e)})}else if(s.Primitive.isPlainObject(e))for(const r in e)Object.prototype.hasOwnProperty.call(e,r)&&m(`${t}[${r}]`,e[r]);else null!=e?""!==e?"boolean"!=typeof e?s.Primitive.isDate(e)?f.push(`${p(t)}=${p(e.toISOString())}`):f.push(`${p(t)}=${p(String(e))}`):f.push(`${p(t)}=${e?"true":"false"}`):o||f.push(`${p(t)}=`):n||f.push(`${p(t)}=`)};let g=Object.keys(t);l&&(g="function"==typeof l?g.sort(l):g.sort());for(const e of g)c&&!a(e)||m(e,t[e]);return f.join("&")}})}}export{s as Serialize};
@@ -0,0 +1,34 @@
1
+ /** Options for {@link slugify}. */
2
+ export interface SlugifyOptions {
3
+ /** Word separator character. Defaults to `"-"`. */
4
+ separator?: string;
5
+ /** Custom character-to-replacement map (merged with {@link DEFAULT_TRANSFORMER}). */
6
+ transformer?: Record<string, string>;
7
+ /** When `true`, silently removes characters whose replacement is longer than 1 char. */
8
+ silent?: boolean;
9
+ }
10
+ /**
11
+ * Default character transformer map for common non-ASCII characters.
12
+ * Can be extended or overridden via {@link SlugifyOptions.transformer}.
13
+ */
14
+ export declare const DEFAULT_TRANSFORMER: Record<string, string>;
15
+ /**
16
+ * Converts a string into a URL-friendly slug.
17
+ * Handles Unicode normalization, custom character transformations,
18
+ * and separator deduplication.
19
+ *
20
+ * @param str - The input string to slugify.
21
+ * @param options - Configuration options.
22
+ * @returns A lowercase, URL-safe slug string.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * slugify("Hello World"); // "hello-world"
27
+ * slugify("Xin Chào Đất Nước"); // "xin-chao-dat-nuoc" (Vietnamese)
28
+ * slugify("Straße nach München"); // "strasse-nach-munchen" (German)
29
+ * slugify("Ærlig talt, det er sjovt"); // "aerlig-talt-det-er-sjovt" (Danish)
30
+ * slugify("C'est la crème brûlée"); // "cest-la-creme-brulee" (French)
31
+ * slugify("Foo Bar", { separator: "_" }); // "foo_bar"
32
+ * ```
33
+ */
34
+ export declare function slugify(str: string, options?: SlugifyOptions): string;
@@ -0,0 +1 @@
1
+ "use strict";const e={"đ":"d","æ":"ae","ø":"o","å":"a","œ":"oe","ß":"ss","þ":"th","ð":"d"};exports.DEFAULT_TRANSFORMER=e,exports.slugify=function(t,r={}){const{separator:n="-",silent:s=!1}=r;if(!t)return"";t=t.toLowerCase();const c=Object.assign(Object.assign({},e),r.transformer),o=Object.keys(c);if(o.length>0){o.sort((e,t)=>t.length-e.length);const e=o.map(e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")),r=new RegExp(e.join("|"),"g");t=t.replace(r,e=>{const t=c[e];return s&&t.length>1?"":t})}if(t=t.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^\w]|_|-/g,n),!n)return t.trim();const a=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return t.replace(new RegExp(`${a}+`,"g"),n).replace(new RegExp(`^${a}|${a}$`,"g"),"").trim()};
@@ -0,0 +1 @@
1
+ const e={"đ":"d","æ":"ae","ø":"o","å":"a","œ":"oe","ß":"ss","þ":"th","ð":"d"};function t(t,r={}){const{separator:n="-",silent:s=!1}=r;if(!t)return"";t=t.toLowerCase();const a=Object.assign(Object.assign({},e),r.transformer),c=Object.keys(a);if(c.length>0){c.sort((e,t)=>t.length-e.length);const e=c.map(e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")),r=new RegExp(e.join("|"),"g");t=t.replace(r,e=>{const t=a[e];return s&&t.length>1?"":t})}if(t=t.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^\w]|_|-/g,n),!n)return t.trim();const o=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return t.replace(new RegExp(`${o}+`,"g"),n).replace(new RegExp(`^${o}|${o}$`,"g"),"").trim()}export{e as DEFAULT_TRANSFORMER,t as slugify};
@@ -0,0 +1,102 @@
1
+ import { Subscriber } from "./subscriber";
2
+ import type { LogEntry } from "./logger";
3
+ export interface MemorySnapshot {
4
+ rss: number;
5
+ heapUsed: number;
6
+ heapTotal: number;
7
+ external: number;
8
+ arrayBuffers: number;
9
+ }
10
+ export interface CpuSnapshot {
11
+ model: string;
12
+ count: number;
13
+ usage: number;
14
+ }
15
+ export interface HeapSnapshot {
16
+ totalHeapSize: number;
17
+ usedHeapSize: number;
18
+ heapSizeLimit: number;
19
+ mallocedMemory: number;
20
+ nativeContexts: number;
21
+ detachedContexts: number;
22
+ }
23
+ export interface ModuleInfo {
24
+ path: string;
25
+ count: number;
26
+ }
27
+ export interface HandleSnapshot {
28
+ timers: number;
29
+ sockets: number;
30
+ requests: number;
31
+ total: number;
32
+ }
33
+ export interface EventLoopSnapshot {
34
+ lagMs: number;
35
+ min: number;
36
+ max: number;
37
+ mean: number;
38
+ p99: number;
39
+ }
40
+ export interface LogRateSnapshot {
41
+ errors: number;
42
+ warns: number;
43
+ total: number;
44
+ }
45
+ export interface HttpSnapshot {
46
+ totalRequests: number;
47
+ recentRequests: number;
48
+ avgLatency: number;
49
+ }
50
+ export interface DbPoolSnapshot {
51
+ connected: boolean;
52
+ }
53
+ export interface MetricSnapshot {
54
+ timestamp: number;
55
+ memory: MemorySnapshot;
56
+ cpu: CpuSnapshot;
57
+ heap: HeapSnapshot;
58
+ handles: HandleSnapshot;
59
+ modules: {
60
+ count: number;
61
+ top: ModuleInfo[];
62
+ };
63
+ eventLoop: EventLoopSnapshot;
64
+ logRate: LogRateSnapshot;
65
+ http: HttpSnapshot;
66
+ dbPool: DbPoolSnapshot;
67
+ system: {
68
+ platform: string;
69
+ arch: string;
70
+ nodeVersion: string;
71
+ totalMemory: number;
72
+ freeMemory: number;
73
+ uptime: number;
74
+ loadAvg: number[];
75
+ };
76
+ }
77
+ export interface SyhemoState {
78
+ current: MetricSnapshot | null;
79
+ snapshots: MetricSnapshot[];
80
+ logs: LogEntry[];
81
+ started: boolean;
82
+ }
83
+ declare const syhemoEvents: {
84
+ readonly metrics: {
85
+ readonly snapshot: string;
86
+ };
87
+ };
88
+ type SyhemoEvents = typeof syhemoEvents;
89
+ export declare function recordHttpRequest(latencyMs: number): void;
90
+ export interface SyhemoOptions {
91
+ interval?: number;
92
+ db?: () => boolean;
93
+ }
94
+ export declare class Syhemo extends Subscriber<SyhemoState, SyhemoEvents> {
95
+ private timer;
96
+ private readonly logger;
97
+ constructor();
98
+ start(options?: SyhemoOptions): void;
99
+ stop(): void;
100
+ private collect;
101
+ }
102
+ export {};
package/dist/syhemo.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var node_perf_hooks=require("node:perf_hooks"),subscriber=require("./subscriber.js");require("./utilities/clone.js");var utilities_freeze=require("./utilities/freeze.js"),logger=require("./logger.js"),v8=require("v8"),os=require("os");function _interopNamespace(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach(function(o){if("default"!==o){var s=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,s.get?s:{enumerable:!0,get:function(){return e[o]}})}}),t.default=e,Object.freeze(t)}var v8__namespace=_interopNamespace(v8),os__namespace=_interopNamespace(os);const syhemoEvents=utilities_freeze.freeze({metrics:{snapshot:"$syhemo:metrics:snapshot"}}),MB=1048576;function collectMemory(){const e=process.memoryUsage();return{rss:Math.round(e.rss/MB*100)/100,heapUsed:Math.round(e.heapUsed/MB*100)/100,heapTotal:Math.round(e.heapTotal/MB*100)/100,external:Math.round(e.external/MB*100)/100,arrayBuffers:Math.round(e.arrayBuffers/MB*100)/100}}let prevCpuUsage=null;function collectCpu(){var e,t;const o=os__namespace.cpus();let s=0;if(prevCpuUsage&&prevCpuUsage.length===o.length){let e=0,t=0;for(let s=0;s<o.length;s++){const r=prevCpuUsage[s].times,n=o[s].times,a=r.user+r.nice+r.sys+r.idle+r.irq;e+=n.user+n.nice+n.sys+n.idle+n.irq-a,t+=n.idle-r.idle}s=e>0?Math.round(1e4*(1-t/e))/100:0}return prevCpuUsage=o,{model:null!==(t=null===(e=o[0])||void 0===e?void 0:e.model)&&void 0!==t?t:"unknown",count:o.length,usage:s}}function collectHeap(){const e=v8__namespace.getHeapStatistics();return{totalHeapSize:Math.round(e.total_heap_size/MB*100)/100,usedHeapSize:Math.round(e.used_heap_size/MB*100)/100,heapSizeLimit:Math.round(e.heap_size_limit/MB*100)/100,mallocedMemory:Math.round(e.malloced_memory/MB*100)/100,nativeContexts:e.number_of_native_contexts,detachedContexts:e.number_of_detached_contexts}}function collectHandles(){var e,t,o,s,r,n;const a=null!==(t=null===(e=process._getActiveHandles)||void 0===e?void 0:e.call(process))&&void 0!==t?t:[],c=null!==(s=null===(o=process._getActiveRequests)||void 0===o?void 0:o.call(process))&&void 0!==s?s:[];let l=0,u=0;for(const e of a){const t=null!==(n=null===(r=null==e?void 0:e.constructor)||void 0===r?void 0:r.name)&&void 0!==n?n:"";"Timeout"===t||"Timer"===t||"Immediate"===t?l++:"Socket"!==t&&"TCP"!==t&&"TLSSocket"!==t||u++}return{timers:l,sockets:u,requests:c.length,total:a.length+c.length}}function collectModules(){var _a;try{const cache=eval("typeof require !== 'undefined' && require.cache")||{},keys=Object.keys(cache),count=keys.length,groups=new Map;for(const e of keys){const t=e.match(/node_modules\/([^/]+)/),o=t?`node_modules/${t[1]}`:e.replace(process.cwd(),".");groups.set(o,(null!==(_a=groups.get(o))&&void 0!==_a?_a:0)+1)}const top=Array.from(groups.entries()).sort((e,t)=>t[1]-e[1]).slice(0,20).map(([e,t])=>({path:e,count:t}));return{count:count,top:top}}catch(e){return{count:0,top:[]}}}const histogram=node_perf_hooks.monitorEventLoopDelay({resolution:10});function collectEventLoop(){const e={lagMs:Math.round(histogram.mean/1e6*100)/100,min:Math.round(histogram.min/1e6*100)/100,max:Math.round(histogram.max/1e6*100)/100,mean:Math.round(histogram.mean/1e6*100)/100,p99:Math.round(histogram.percentile(99)/1e6*100)/100};return histogram.reset(),e}histogram.enable();let httpTotalRequests=0,httpRecentRequests=0,httpLatencySum=0,httpLatencySamples=0;function recordHttpRequest(e){httpTotalRequests++,httpRecentRequests++,httpLatencySum+=e,httpLatencySamples++}function collectHttp(){const e=httpLatencySamples>0?Math.round(httpLatencySum/httpLatencySamples*100)/100:0,t={totalRequests:httpTotalRequests,recentRequests:httpRecentRequests,avgLatency:e};return httpRecentRequests=0,httpLatencySum=0,httpLatencySamples=0,t}let dbChecker=null;function collectDbPool(){return{connected:!!dbChecker&&dbChecker()}}function collectSnapshot(){return{timestamp:Date.now(),memory:collectMemory(),cpu:collectCpu(),heap:collectHeap(),handles:collectHandles(),modules:collectModules(),eventLoop:collectEventLoop(),logRate:logger.Logger.drainCounts(),http:collectHttp(),dbPool:collectDbPool(),system:{platform:os__namespace.platform(),arch:os__namespace.arch(),nodeVersion:process.version,totalMemory:Math.round(os__namespace.totalmem()/MB),freeMemory:Math.round(os__namespace.freemem()/MB),uptime:Math.round(process.uptime()),loadAvg:os__namespace.loadavg().map(e=>Math.round(100*e)/100)}}}const MAX_SNAPSHOTS=60;class Syhemo extends subscriber.Subscriber{constructor(){super({current:null,snapshots:[],logs:[],started:!1},syhemoEvents),this.timer=null,this.logger=new logger.Logger("Syhemo")}start(e={}){if(this.getState().started)return;const{interval:t=5e3,db:o}=e;o&&(dbChecker=o),this.setState({started:!0}),this.collect(),this.timer=setInterval(()=>this.collect(),t),this.logger.log(`Started (interval: ${t}ms)`)}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.setState({started:!1}),this.logger.log("Stopped")}collect(){try{const e=collectSnapshot(),t=this.getState().snapshots,o=t.length>=MAX_SNAPSHOTS?[...t.slice(1),e]:[...t,e],s=logger.Logger.getLogs();this.setState({current:e,snapshots:o,logs:s}),this.dispatch(syhemoEvents.metrics.snapshot,e),this.logger.log(`Snapshot completed (count: ${o.length})`)}catch(e){this.logger.error(`Collection failed: ${e}`)}}}exports.Syhemo=Syhemo,exports.recordHttpRequest=recordHttpRequest;
@@ -0,0 +1 @@
1
+ import{monitorEventLoopDelay}from"node:perf_hooks";import{Subscriber}from"./subscriber.mjs";import"./utilities/clone.mjs";import{freeze}from"./utilities/freeze.mjs";import{Logger}from"./logger.mjs";import*as v8 from"v8";import*as os from"os";const syhemoEvents=freeze({metrics:{snapshot:"$syhemo:metrics:snapshot"}}),MB=1048576;function collectMemory(){const e=process.memoryUsage();return{rss:Math.round(e.rss/MB*100)/100,heapUsed:Math.round(e.heapUsed/MB*100)/100,heapTotal:Math.round(e.heapTotal/MB*100)/100,external:Math.round(e.external/MB*100)/100,arrayBuffers:Math.round(e.arrayBuffers/MB*100)/100}}let prevCpuUsage=null;function collectCpu(){var e,t;const o=os.cpus();let s=0;if(prevCpuUsage&&prevCpuUsage.length===o.length){let e=0,t=0;for(let s=0;s<o.length;s++){const r=prevCpuUsage[s].times,n=o[s].times,l=r.user+r.nice+r.sys+r.idle+r.irq;e+=n.user+n.nice+n.sys+n.idle+n.irq-l,t+=n.idle-r.idle}s=e>0?Math.round(1e4*(1-t/e))/100:0}return prevCpuUsage=o,{model:null!==(t=null===(e=o[0])||void 0===e?void 0:e.model)&&void 0!==t?t:"unknown",count:o.length,usage:s}}function collectHeap(){const e=v8.getHeapStatistics();return{totalHeapSize:Math.round(e.total_heap_size/MB*100)/100,usedHeapSize:Math.round(e.used_heap_size/MB*100)/100,heapSizeLimit:Math.round(e.heap_size_limit/MB*100)/100,mallocedMemory:Math.round(e.malloced_memory/MB*100)/100,nativeContexts:e.number_of_native_contexts,detachedContexts:e.number_of_detached_contexts}}function collectHandles(){var e,t,o,s,r,n;const l=null!==(t=null===(e=process._getActiveHandles)||void 0===e?void 0:e.call(process))&&void 0!==t?t:[],a=null!==(s=null===(o=process._getActiveRequests)||void 0===o?void 0:o.call(process))&&void 0!==s?s:[];let c=0,i=0;for(const e of l){const t=null!==(n=null===(r=null==e?void 0:e.constructor)||void 0===r?void 0:r.name)&&void 0!==n?n:"";"Timeout"===t||"Timer"===t||"Immediate"===t?c++:"Socket"!==t&&"TCP"!==t&&"TLSSocket"!==t||i++}return{timers:c,sockets:i,requests:a.length,total:l.length+a.length}}function collectModules(){var _a;try{const cache=eval("typeof require !== 'undefined' && require.cache")||{},keys=Object.keys(cache),count=keys.length,groups=new Map;for(const e of keys){const t=e.match(/node_modules\/([^/]+)/),o=t?`node_modules/${t[1]}`:e.replace(process.cwd(),".");groups.set(o,(null!==(_a=groups.get(o))&&void 0!==_a?_a:0)+1)}const top=Array.from(groups.entries()).sort((e,t)=>t[1]-e[1]).slice(0,20).map(([e,t])=>({path:e,count:t}));return{count:count,top:top}}catch(e){return{count:0,top:[]}}}const histogram=monitorEventLoopDelay({resolution:10});function collectEventLoop(){const e={lagMs:Math.round(histogram.mean/1e6*100)/100,min:Math.round(histogram.min/1e6*100)/100,max:Math.round(histogram.max/1e6*100)/100,mean:Math.round(histogram.mean/1e6*100)/100,p99:Math.round(histogram.percentile(99)/1e6*100)/100};return histogram.reset(),e}histogram.enable();let httpTotalRequests=0,httpRecentRequests=0,httpLatencySum=0,httpLatencySamples=0;function recordHttpRequest(e){httpTotalRequests++,httpRecentRequests++,httpLatencySum+=e,httpLatencySamples++}function collectHttp(){const e=httpLatencySamples>0?Math.round(httpLatencySum/httpLatencySamples*100)/100:0,t={totalRequests:httpTotalRequests,recentRequests:httpRecentRequests,avgLatency:e};return httpRecentRequests=0,httpLatencySum=0,httpLatencySamples=0,t}let dbChecker=null;function collectDbPool(){return{connected:!!dbChecker&&dbChecker()}}function collectSnapshot(){return{timestamp:Date.now(),memory:collectMemory(),cpu:collectCpu(),heap:collectHeap(),handles:collectHandles(),modules:collectModules(),eventLoop:collectEventLoop(),logRate:Logger.drainCounts(),http:collectHttp(),dbPool:collectDbPool(),system:{platform:os.platform(),arch:os.arch(),nodeVersion:process.version,totalMemory:Math.round(os.totalmem()/MB),freeMemory:Math.round(os.freemem()/MB),uptime:Math.round(process.uptime()),loadAvg:os.loadavg().map(e=>Math.round(100*e)/100)}}}const MAX_SNAPSHOTS=60;class Syhemo extends Subscriber{constructor(){super({current:null,snapshots:[],logs:[],started:!1},syhemoEvents),this.timer=null,this.logger=new Logger("Syhemo")}start(e={}){if(this.getState().started)return;const{interval:t=5e3,db:o}=e;o&&(dbChecker=o),this.setState({started:!0}),this.collect(),this.timer=setInterval(()=>this.collect(),t),this.logger.log(`Started (interval: ${t}ms)`)}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.setState({started:!1}),this.logger.log("Stopped")}collect(){try{const e=collectSnapshot(),t=this.getState().snapshots,o=t.length>=MAX_SNAPSHOTS?[...t.slice(1),e]:[...t,e],s=Logger.getLogs();this.setState({current:e,snapshots:o,logs:s}),this.dispatch(syhemoEvents.metrics.snapshot,e),this.logger.log(`Snapshot completed (count: ${o.length})`)}catch(e){this.logger.error(`Collection failed: ${e}`)}}}export{Syhemo,recordHttpRequest};
@@ -1,22 +1,43 @@
1
+ /** JavaScript primitive types (including `null` and `undefined`). */
1
2
  export type primitive = string | number | boolean | bigint | symbol | undefined | null;
3
+ /**
4
+ * Union of all built-in class types that should be treated as opaque values
5
+ * (not recursed into by deep utilities like `Freezable` or `PartialLiteral`).
6
+ */
2
7
  export type PrimitiveClass = Date | RegExp | File | FileList | URL | Blob | ArrayBuffer | SharedArrayBuffer | DataView | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array | FormData | Headers | Request | Response | URLSearchParams | AbortController | AbortSignal | ReadableStream | WritableStream | TransformStream | Event | CustomEvent | EventTarget | MutationObserver | IntersectionObserver | ResizeObserver | Worker | MessageChannel | MessagePort | BroadcastChannel | Generator | AsyncGenerator | Element | HTMLElement | Node | Document | Window | Error | TypeError | RangeError | SyntaxError | ReferenceError | EvalError | AggregateError | URIError;
8
+ /** Union of all primitive values and built-in class instances. */
3
9
  export type BuiltInPrimitive = primitive | PrimitiveClass;
10
+ /** A plain object with string/symbol/number keys and unknown values. */
4
11
  export type LiteralObject<Keys extends PropertyKey = PropertyKey> = Record<Keys, unknown> | {
5
12
  [K in Keys]: unknown;
6
13
  } | object;
14
+ /** A single-key object mapping `Key` to `Value`. */
7
15
  export type AtomicObject<Key extends PropertyKey = PropertyKey, Value = unknown> = {
8
16
  [K in Key]: Value;
9
17
  };
18
+ /** Generic function type with configurable return type and argument tuple. */
10
19
  export type LiteralFunction<R = unknown, A extends unknown[] = unknown[]> = (...args: A) => R;
20
+ /** Any object-like value: plain object, array, or function. */
11
21
  export type Objectable = LiteralObject | Array<unknown> | LiteralFunction;
22
+ /** A value that may be either synchronous or wrapped in a `Promise`. */
12
23
  export type Promisable<Value> = Value | Promise<Value>;
24
+ /** A function with additional static properties (callable object pattern). */
13
25
  export type ExtendedFunction<F = LiteralFunction, O = LiteralObject> = F & O;
14
- export type Freezable<T> = T extends primitive ? T : T extends (...args: unknown[]) => unknown ? T : T extends Array<infer U> ? ReadonlyArray<Freezable<U>> : T extends object ? {
26
+ /**
27
+ * Deep-freezes a type by making all properties `readonly` recursively.
28
+ * Preserves functions, built-in classes, and arrays without flattening them.
29
+ */
30
+ export type Freezable<T> = T extends primitive ? T : T extends (...args: any[]) => any ? T : T extends Date | RegExp | Error | Map<any, any> | Set<any> ? T : T extends ReadonlyArray<infer U> ? ReadonlyArray<Freezable<U>> : T extends object ? {
15
31
  readonly [K in keyof T]: Freezable<T[K]>;
16
32
  } : T;
33
+ /**
34
+ * Deep-partial type that correctly handles built-in generics
35
+ * (`Map`, `Set`, `Promise`, `WeakRef`, etc.) and extended functions.
36
+ */
17
37
  export type PartialLiteral<T> = T extends Map<infer K, infer V> ? Map<PartialLiteral<K>, PartialLiteral<V>> : T extends WeakMap<infer K, infer V> ? WeakMap<PartialLiteral<K>, PartialLiteral<V>> : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<PartialLiteral<K>, PartialLiteral<V>> : T extends Set<infer U> ? Set<PartialLiteral<U>> : T extends WeakSet<infer U> ? WeakSet<PartialLiteral<U>> : T extends ReadonlySet<infer U> ? ReadonlySet<PartialLiteral<U>> : T extends Promise<infer U> ? Promise<PartialLiteral<U>> : T extends WeakRef<infer U> ? WeakRef<PartialLiteral<U>> : T extends FinalizationRegistry<infer U> ? FinalizationRegistry<PartialLiteral<U>> : T extends BuiltInPrimitive ? T : T extends ExtendedFunction ? T extends ExtendedFunction<infer F> ? F & {
18
38
  [K in keyof T]?: PartialLiteral<T[K]>;
19
39
  } : T : T extends LiteralObject ? {
20
40
  [K in keyof T]?: PartialLiteral<T[K]>;
21
41
  } : T extends Array<infer U> ? Array<PartialLiteral<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<PartialLiteral<U>> : T;
42
+ /** Converts a value type to its string representation at the type level. */
22
43
  export type ToString<T> = T extends string | number | bigint | boolean ? `${T}` : T extends symbol ? string : T extends null ? "null" : T extends undefined ? "undefined" : never;
@@ -0,0 +1,53 @@
1
+ type Timeout = ReturnType<typeof setTimeout>;
2
+ /** Callback function for {@link defer}. */
3
+ export type DeferCallback = () => void;
4
+ /** Internal timer IDs used by {@link defer} for cancellation. */
5
+ export type DeferIds = {
6
+ /** `requestAnimationFrame` ID. */
7
+ r: number | null;
8
+ /** `setTimeout` ID. */
9
+ s: Timeout | null;
10
+ };
11
+ /**
12
+ * Schedules a callback using `requestAnimationFrame` + `setTimeout` for optimal
13
+ * browser execution timing. Falls back to plain `setTimeout` in non-browser environments.
14
+ *
15
+ * @param callback - Function to execute after the defer.
16
+ * @param delay - Additional delay in milliseconds after the animation frame. Defaults to `0`.
17
+ * @returns An object with `ids` (internal timer IDs) and a `cancel` function.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const { cancel } = defer(() => console.log("done"), 100);
22
+ * // Later:
23
+ * cancel(); // Cancels if not yet executed
24
+ * ```
25
+ */
26
+ export declare function defer(callback: DeferCallback, delay?: number): {
27
+ ids: DeferIds;
28
+ cancel: () => void;
29
+ };
30
+ /** A `Promise<void>` with an attached `cancel` method. */
31
+ export interface CancelablePromise extends Promise<void> {
32
+ /** Cancels the pending defer, preventing the promise from resolving. */
33
+ cancel: () => void;
34
+ }
35
+ /**
36
+ * Promise-based wrapper around {@link defer}.
37
+ * Resolves after the specified delay, and can be cancelled before resolution.
38
+ *
39
+ * @param delay - Delay in milliseconds. Defaults to `0`.
40
+ * @returns A {@link CancelablePromise} that resolves when the defer completes.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * const wait = deferAsync(500);
45
+ * await wait; // Resolves after ~500ms
46
+ *
47
+ * // Or cancel early:
48
+ * const wait2 = deferAsync(5000);
49
+ * wait2.cancel();
50
+ * ```
51
+ */
52
+ export declare function deferAsync(delay?: number): CancelablePromise;
53
+ export {};
@@ -0,0 +1 @@
1
+ "use strict";function n(n,e){const t={r:null,s:null},r=Math.max(0,e||0);function c(){t.r&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(t.r),t.s&&clearTimeout(t.s),t.r=null,t.s=null}return"function"==typeof requestAnimationFrame?t.r=requestAnimationFrame(()=>{t.s=setTimeout(()=>{n(),c()},r)}):t.s=setTimeout(()=>{n(),c()},r),{ids:t,cancel:c}}exports.defer=n,exports.deferAsync=function(e){let t;const r=new Promise(r=>{const{cancel:c}=n(()=>r(),e);t=c});return r.cancel=()=>{t()},r};
@@ -0,0 +1 @@
1
+ function n(n,e){const t={r:null,s:null},c=Math.max(0,e||0);function o(){t.r&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(t.r),t.s&&clearTimeout(t.s),t.r=null,t.s=null}return"function"==typeof requestAnimationFrame?t.r=requestAnimationFrame(()=>{t.s=setTimeout(()=>{n(),o()},c)}):t.s=setTimeout(()=>{n(),o()},c),{ids:t,cancel:o}}function e(e){let t;const c=new Promise(c=>{const{cancel:o}=n(()=>c(),e);t=o});return c.cancel=()=>{t()},c}export{n as defer,e as deferAsync};
@@ -0,0 +1,25 @@
1
+ /**
2
+ * A platform-agnostic interface representing a `FileList`-like object.
3
+ * Works in both browser (native `FileList`) and Node.js environments.
4
+ */
5
+ export interface FileListLike {
6
+ readonly length: number;
7
+ item(index: number): File;
8
+ [index: number]: File;
9
+ }
10
+ /**
11
+ * Checks whether a value is a `FileList` or a `FileList`-like object.
12
+ * Uses `instanceof FileList` in browser environments and falls back to
13
+ * `Object.prototype.toString` tag detection for isomorphic compatibility.
14
+ *
15
+ * @param data - The value to check.
16
+ * @returns `true` if the value is a `FileList` or has the `[object FileList]` tag.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const input = document.querySelector("input[type=file]");
21
+ * isFileList(input.files); // true
22
+ * isFileList([]); // false
23
+ * ```
24
+ */
25
+ export declare function isFileList(data: unknown): data is FileListLike;
@@ -0,0 +1 @@
1
+ "use strict";var i=require("./is-function.js"),t=require("./to-string.js");exports.isFileList=function(e){return"undefined"!=typeof FileList&&e instanceof FileList||"object"==typeof e&&null!==e&&"[object FileList]"===t.toString(e)&&"length"in e&&"item"in e&&i.isFunction(e.item)};
@@ -0,0 +1 @@
1
+ import{isFunction as t}from"./is-function.mjs";import{toString as i}from"./to-string.mjs";function e(e){return"undefined"!=typeof FileList&&e instanceof FileList||"object"==typeof e&&null!==e&&"[object FileList]"===i(e)&&"length"in e&&"item"in e&&t(e.item)}export{e as isFileList};
@@ -0,0 +1,57 @@
1
+ /** A generic string-keyed record type. */
2
+ export type ObjectOf<T = unknown> = Record<string, T>;
3
+ /**
4
+ * Recursively flattens a nested object or array into a single-level object
5
+ * with dot-separated keys.
6
+ *
7
+ * Array indices use dot notation (`users.0.name` instead of `users[0].name`).
8
+ *
9
+ * @param data - The value to flatten.
10
+ * @param prefix - Internal prefix for recursive key building.
11
+ * @param acc - Internal accumulator for the result.
12
+ * @returns A flat `Record<string, unknown>` with dot-separated keys.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * flatten({ users: [{ name: "Alice" }] });
17
+ * // { "users.0.name": "Alice" }
18
+ *
19
+ * flatten({ a: { b: { c: 1 } } });
20
+ * // { "a.b.c": 1 }
21
+ * ```
22
+ */
23
+ export declare function flatten(data: unknown, prefix?: string, acc?: Record<string, unknown>): Record<string, unknown>;
24
+ /**
25
+ * Extracts entries from a flattened object under a given path and reconstructs
26
+ * them as an array of objects (if the keys are numeric indices) or a list of
27
+ * `{ key, value }` pairs (if the keys are non-numeric).
28
+ *
29
+ * @param data - A flattened `Record<string, unknown>` (output of {@link flatten}).
30
+ * @param path - The dot-separated path prefix to extract.
31
+ * @returns An array of reconstructed objects, primitive values, or `{ key, value }` pairs.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const flat = flatten({ users: [{ name: "Alice" }, { name: "Bob" }] });
36
+ * flattenToArray(flat, "users");
37
+ * // [{ name: "Alice" }, { name: "Bob" }]
38
+ *
39
+ * const flat2 = flatten({ config: { host: "localhost", port: 3000 } });
40
+ * flattenToArray(flat2, "config");
41
+ * // [{ key: "host", value: "localhost" }, { key: "port", value: 3000 }]
42
+ * ```
43
+ */
44
+ export declare function flattenToArray(data: Record<string, unknown>, path: string): any[];
45
+ /**
46
+ * Escapes special regex characters in a key string so it can be safely
47
+ * used inside a `RegExp` constructor.
48
+ *
49
+ * @param key - The string to escape.
50
+ * @returns The escaped string with special characters prefixed by `\\`.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * escapeRegexKey("users[0].name"); // "users\\[0\\]\\.name"
55
+ * ```
56
+ */
57
+ export declare function escapeRegexKey(key: string): string;
@@ -0,0 +1 @@
1
+ "use strict";exports.escapeRegexKey=function(e){return e.replace(/([.[\]{}])/g,"\\$1")},exports.flatten=function e(t,r="",n={}){if("object"!=typeof t||null===t)return r&&(n[r]=t),n;if(Array.isArray(t))for(let s=0;s<t.length;s++){const c=r?`${r}.${s}`:`${s}`;e(t[s],c,n)}else for(const[s,c]of Object.entries(t)){e(c,r?`${r}.${s}`:s,n)}return n},exports.flattenToArray=function(e,t){const r=`${t}.`,n=Object.entries(e).filter(([e])=>e.startsWith(r));if(!n.length)return[];const s=n[0][0].replace(r,"").split(".")[0];if(!!isNaN(Number(s)))return n.map(([e,t])=>({key:e.replace(r,""),value:t}));const c=n.reduce((e,[t,n])=>{const s=t.replace(r,"").split("."),c=s[0],o=s.slice(1).join(".");return e[c]||(e[c]={}),o?e[c][o]=n:e[c]=n,e},{});return Object.values(c)};
@@ -0,0 +1 @@
1
+ function e(t,r="",n={}){if("object"!=typeof t||null===t)return r&&(n[r]=t),n;if(Array.isArray(t))for(let c=0;c<t.length;c++){const i=r?`${r}.${c}`:`${c}`;e(t[c],i,n)}else for(const[c,i]of Object.entries(t)){e(i,r?`${r}.${c}`:c,n)}return n}function t(e,t){const r=`${t}.`,n=Object.entries(e).filter(([e])=>e.startsWith(r));if(!n.length)return[];const c=n[0][0].replace(r,"").split(".")[0];if(!!isNaN(Number(c)))return n.map(([e,t])=>({key:e.replace(r,""),value:t}));const i=n.reduce((e,[t,n])=>{const c=t.replace(r,"").split("."),i=c[0],s=c.slice(1).join(".");return e[i]||(e[i]={}),s?e[i][s]=n:e[i]=n,e},{});return Object.values(i)}function r(e){return e.replace(/([.[\]{}])/g,"\\$1")}export{r as escapeRegexKey,e as flatten,t as flattenToArray};
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Safely retrieves a nested value from an object using a dot/bracket path.
3
+ * Returns `defaultValue` only when the resolved value is `undefined` —
4
+ * falsy values like `null`, `0`, `false`, and `""` are returned as-is.
5
+ *
6
+ * @param data - The source object to traverse.
7
+ * @param path - Dot-notation string (`"a.b.c"`), bracket-notation (`"a[0].b"`), or an array of keys.
8
+ * @param defaultValue - Value returned when the path resolves to `undefined`.
9
+ * @returns The resolved value, or `defaultValue` if not found.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const obj = { users: [{ name: "Alice" }] };
14
+ *
15
+ * get(obj, "users[0].name"); // "Alice"
16
+ * get(obj, "users.0.name"); // "Alice"
17
+ * get(obj, "users[1].name", "N/A"); // "N/A"
18
+ * get(obj, "count", 0); // 0
19
+ * ```
20
+ */
21
+ export declare function get<Type = unknown>(data: unknown, path: string | string[], defaultValue?: Type): Type;
@@ -0,0 +1 @@
1
+ "use strict";exports.get=function(r,t,e){if(null==r)return e;const n=Array.isArray(t)?t:t.replace(/\[(\d+)]/g,".$1").split(".").filter(Boolean);if(0===n.length)return r;let l=r;for(const r of n){if(null==l)return e;l=l[r]}return void 0===l?e:l};
@@ -0,0 +1 @@
1
+ function r(r,n,t){if(null==r)return t;const e=Array.isArray(n)?n:n.replace(/\[(\d+)]/g,".$1").split(".").filter(Boolean);if(0===e.length)return r;let l=r;for(const r of e){if(null==l)return t;l=l[r]}return void 0===l?t:l}export{r as get};
@@ -1,8 +1,14 @@
1
1
  export { clone } from "./clone";
2
+ export { defer, deferAsync, type DeferIds, type DeferCallback, type CancelablePromise } from "./defer";
3
+ export { isFileList, type FileListLike } from "./filelist";
4
+ export { flatten, flattenToArray, escapeRegexKey, type ObjectOf } from "./flatten";
2
5
  export { freeze } from "./freeze";
6
+ export { get } from "./get";
3
7
  export { isEqual } from "./is-equal";
4
8
  export { isFunction } from "./is-function";
5
9
  export { isLiteralObject, isComplexObject, isObject, isObjectable, hasOwnProperty } from "./object";
6
10
  export { merge } from "./merge";
11
+ export { objectToFormData } from "./object-to-formdata";
12
+ export { pascalToKebab } from "./pascal-to-kebab";
7
13
  export { toString } from "./to-string";
8
14
  export { ucfirst } from "./ucfirst";
@@ -1 +1 @@
1
- "use strict";var e=require("./clone.js"),r=require("./freeze.js"),s=require("./is-equal.js"),t=require("./is-function.js"),i=require("./object.js"),o=require("./merge.js"),c=require("./to-string.js"),u=require("./ucfirst.js");exports.clone=e.clone,exports.freeze=r.freeze,exports.isEqual=s.isEqual,exports.isFunction=t.isFunction,exports.hasOwnProperty=i.hasOwnProperty,exports.isComplexObject=i.isComplexObject,exports.isLiteralObject=i.isLiteralObject,exports.isObject=i.isObject,exports.isObjectable=i.isObjectable,exports.merge=o.merge,exports.toString=c.toString,exports.ucfirst=u.ucfirst;
1
+ "use strict";var e=require("./clone.js"),r=require("./defer.js"),t=require("./filelist.js"),s=require("./flatten.js"),o=require("./freeze.js"),i=require("./get.js"),a=require("./is-equal.js"),p=require("./is-function.js"),c=require("./object.js"),j=require("./merge.js"),x=require("./object-to-formdata.js"),l=require("./pascal-to-kebab.js"),u=require("./to-string.js"),n=require("./ucfirst.js");exports.clone=e.clone,exports.defer=r.defer,exports.deferAsync=r.deferAsync,exports.isFileList=t.isFileList,exports.escapeRegexKey=s.escapeRegexKey,exports.flatten=s.flatten,exports.flattenToArray=s.flattenToArray,exports.freeze=o.freeze,exports.get=i.get,exports.isEqual=a.isEqual,exports.isFunction=p.isFunction,exports.hasOwnProperty=c.hasOwnProperty,exports.isComplexObject=c.isComplexObject,exports.isLiteralObject=c.isLiteralObject,exports.isObject=c.isObject,exports.isObjectable=c.isObjectable,exports.merge=j.merge,exports.objectToFormData=x.objectToFormData,exports.pascalToKebab=l.pascalToKebab,exports.toString=u.toString,exports.ucfirst=n.ucfirst;
@@ -1 +1 @@
1
- export{clone}from"./clone.mjs";export{freeze}from"./freeze.mjs";export{isEqual}from"./is-equal.mjs";export{isFunction}from"./is-function.mjs";export{hasOwnProperty,isComplexObject,isLiteralObject,isObject,isObjectable}from"./object.mjs";export{merge}from"./merge.mjs";export{toString}from"./to-string.mjs";export{ucfirst}from"./ucfirst.mjs";
1
+ export{clone}from"./clone.mjs";export{defer,deferAsync}from"./defer.mjs";export{isFileList}from"./filelist.mjs";export{escapeRegexKey,flatten,flattenToArray}from"./flatten.mjs";export{freeze}from"./freeze.mjs";export{get}from"./get.mjs";export{isEqual}from"./is-equal.mjs";export{isFunction}from"./is-function.mjs";export{hasOwnProperty,isComplexObject,isLiteralObject,isObject,isObjectable}from"./object.mjs";export{merge}from"./merge.mjs";export{objectToFormData}from"./object-to-formdata.mjs";export{pascalToKebab}from"./pascal-to-kebab.mjs";export{toString}from"./to-string.mjs";export{ucfirst}from"./ucfirst.mjs";
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Recursively converts a value into a `FormData` instance.
3
+ * Handles Date, File, Blob, FileList, arrays, nested objects, and primitives.
4
+ *
5
+ * @param data - The value to convert.
6
+ * @param formData - The `FormData` instance to append to (created automatically if omitted).
7
+ * @param parentKey - Internal key prefix for recursive nesting.
8
+ * @returns The populated `FormData` instance.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const fd = objectToFormData({
13
+ * name: "Alice",
14
+ * avatar: someFile,
15
+ * tags: ["a", "b"],
16
+ * meta: { role: "admin" },
17
+ * });
18
+ * // FormData entries:
19
+ * // name → "Alice"
20
+ * // avatar → File
21
+ * // tags[0] → "a"
22
+ * // tags[1] → "b"
23
+ * // meta[role] → "admin"
24
+ * ```
25
+ */
26
+ export declare function objectToFormData(data: unknown, formData?: FormData, parentKey?: string): FormData;
@@ -0,0 +1 @@
1
+ "use strict";var t=require("./filelist.js");exports.objectToFormData=function e(r,n=new FormData,a=""){return null==r||(r instanceof Date?n.append(a,r.toISOString()):r instanceof File||r instanceof Blob?n.append(a,r):t.isFileList(r)?Array.from(r).forEach((t,e)=>{const r=a?`${a}[${e}]`:String(e);n.append(r,t,t.name)}):Array.isArray(r)?r.forEach((t,r)=>{const o=a?`${a}[${r}]`:String(r);e(t,n,o)}):"object"==typeof r?Object.entries(r).forEach(([t,r])=>{e(r,n,a?`${a}[${t}]`:t)}):n.append(a,String(r))),n};
@@ -0,0 +1 @@
1
+ import{isFileList as n}from"./filelist.mjs";function r(t,e=new FormData,o=""){return null==t||(t instanceof Date?e.append(o,t.toISOString()):t instanceof File||t instanceof Blob?e.append(o,t):n(t)?Array.from(t).forEach((n,r)=>{const t=o?`${o}[${r}]`:String(r);e.append(t,n,n.name)}):Array.isArray(t)?t.forEach((n,t)=>{const a=o?`${o}[${t}]`:String(t);r(n,e,a)}):"object"==typeof t?Object.entries(t).forEach(([n,t])=>{r(t,e,o?`${o}[${n}]`:n)}):e.append(o,String(t))),e}export{r as objectToFormData};
@@ -1 +1 @@
1
- "use strict";var t=require("./is-function.js");function r(t){return"object"==typeof t&&null!==t}exports.hasOwnProperty=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},exports.isComplexObject=function(t){return r(t)&&!Array.isArray(t)},exports.isLiteralObject=function(t){if(!r(t)||Array.isArray(t))return!1;const e=Object.getPrototypeOf(t);return null===e||e===Object.prototype},exports.isObject=r,exports.isObjectable=function(e){return r(e)||t.isFunction(e)};
1
+ "use strict";var t=require("./is-function.js");function r(t){return"object"==typeof t&&null!==t}function e(e){return r(e)||t.isFunction(e)}exports.hasOwnProperty=function(t,r){return!!t&&(e(t)?Object.prototype.hasOwnProperty.call(t,r)||r in t:Object.prototype.hasOwnProperty.call(t,r))},exports.isComplexObject=function(t){return r(t)&&!Array.isArray(t)},exports.isLiteralObject=function(t){if(!r(t)||Array.isArray(t))return!1;const e=Object.getPrototypeOf(t);return null===e||e===Object.prototype},exports.isObject=r,exports.isObjectable=e;
@@ -1 +1 @@
1
- import{isFunction as r}from"./is-function.mjs";function t(r){return"object"==typeof r&&null!==r}function n(r){if(!t(r)||Array.isArray(r))return!1;const n=Object.getPrototypeOf(r);return null===n||n===Object.prototype}function o(r){return t(r)&&!Array.isArray(r)}function e(n){return t(n)||r(n)}function u(r,t){return Object.prototype.hasOwnProperty.call(r,t)}export{u as hasOwnProperty,o as isComplexObject,n as isLiteralObject,t as isObject,e as isObjectable};
1
+ import{isFunction as t}from"./is-function.mjs";function r(t){return"object"==typeof t&&null!==t}function n(t){if(!r(t)||Array.isArray(t))return!1;const n=Object.getPrototypeOf(t);return null===n||n===Object.prototype}function o(t){return r(t)&&!Array.isArray(t)}function e(n){return r(n)||t(n)}function c(t,r){return!!t&&(e(t)?Object.prototype.hasOwnProperty.call(t,r)||r in t:Object.prototype.hasOwnProperty.call(t,r))}export{c as hasOwnProperty,o as isComplexObject,n as isLiteralObject,r as isObject,e as isObjectable};
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Converts a PascalCase or camelCase string to kebab-case.
3
+ * Handles consecutive uppercase characters (e.g. acronyms) gracefully.
4
+ *
5
+ * @param str - The string to convert.
6
+ * @returns The kebab-case version of the string.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * pascalToKebab("MyComponent"); // "my-component"
11
+ * pascalToKebab("HTMLParser"); // "html-parser"
12
+ * pascalToKebab("camelCase"); // "camel-case"
13
+ * ```
14
+ */
15
+ export declare function pascalToKebab(str: string): string;
@@ -0,0 +1 @@
1
+ "use strict";exports.pascalToKebab=function(e){return e?e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/([A-Z])([A-Z][a-z])/g,"$1-$2").toLowerCase():e};
@@ -0,0 +1 @@
1
+ function e(e){return e?e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/([A-Z])([A-Z][a-z])/g,"$1-$2").toLowerCase():e}export{e as pascalToKebab};