@ecosy/core 0.3.4 → 0.5.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 (85) hide show
  1. package/CHANGELOG.md +163 -0
  2. package/README.md +7 -0
  3. package/agents/skills/ecosy-core-serialize/SKILL.md +93 -0
  4. package/agents/skills/ecosy-core-subscriber/SKILL.md +66 -0
  5. package/dist/cache/disk.d.ts +32 -0
  6. package/dist/cache/disk.js +1 -0
  7. package/dist/cache/disk.mjs +1 -0
  8. package/dist/cache/index.d.ts +17 -0
  9. package/dist/cache/index.js +1 -0
  10. package/dist/cache/index.mjs +1 -0
  11. package/dist/cache/memory.d.ts +19 -0
  12. package/dist/cache/memory.js +1 -0
  13. package/dist/cache/memory.mjs +1 -0
  14. package/dist/cache/redis.d.ts +63 -0
  15. package/dist/cache/redis.js +1 -0
  16. package/dist/cache/redis.mjs +1 -0
  17. package/dist/cache/types.d.ts +35 -0
  18. package/dist/cache/types.js +1 -0
  19. package/dist/cache/types.mjs +1 -0
  20. package/dist/ecosy-core.umd.js +2 -0
  21. package/dist/ecosy-core.umd.js.map +1 -0
  22. package/dist/index.d.ts +0 -9
  23. package/dist/index.js +1 -1
  24. package/dist/index.mjs +1 -1
  25. package/dist/serialize/index.d.ts +62 -0
  26. package/dist/serialize/index.js +1 -0
  27. package/dist/serialize/index.mjs +1 -0
  28. package/dist/serialize/interpolate.d.ts +10 -0
  29. package/dist/serialize/interpolate.js +1 -0
  30. package/dist/serialize/interpolate.mjs +1 -0
  31. package/dist/serialize/json.d.ts +3 -0
  32. package/dist/serialize/json.js +1 -0
  33. package/dist/serialize/json.mjs +1 -0
  34. package/dist/serialize/primitive.d.ts +3 -0
  35. package/dist/serialize/primitive.js +1 -0
  36. package/dist/serialize/primitive.mjs +1 -0
  37. package/dist/serialize/query-string.d.ts +3 -0
  38. package/dist/serialize/query-string.js +1 -0
  39. package/dist/serialize/query-string.mjs +1 -0
  40. package/dist/serialize/types.d.ts +42 -0
  41. package/dist/serialize/types.js +1 -0
  42. package/dist/serialize/types.mjs +1 -0
  43. package/dist/serialize/url.d.ts +3 -0
  44. package/dist/serialize/url.js +1 -0
  45. package/dist/serialize/url.mjs +1 -0
  46. package/dist/syhemo/collectors.d.ts +25 -0
  47. package/dist/syhemo/collectors.js +1 -0
  48. package/dist/syhemo/collectors.mjs +1 -0
  49. package/dist/syhemo/exposition.d.ts +15 -0
  50. package/dist/syhemo/exposition.js +1 -0
  51. package/dist/syhemo/exposition.mjs +1 -0
  52. package/dist/syhemo/index.d.ts +50 -0
  53. package/dist/syhemo/index.js +1 -0
  54. package/dist/syhemo/index.mjs +1 -0
  55. package/dist/{logger.d.ts → syhemo/logger.d.ts} +23 -11
  56. package/dist/syhemo/logger.js +1 -0
  57. package/dist/{logger.mjs → syhemo/logger.mjs} +1 -1
  58. package/dist/syhemo/types.d.ts +114 -0
  59. package/dist/syhemo/types.js +1 -0
  60. package/dist/syhemo/types.mjs +1 -0
  61. package/dist/utilities/index.d.ts +2 -0
  62. package/dist/utilities/index.js +1 -1
  63. package/dist/utilities/index.mjs +1 -1
  64. package/dist/{searchify.d.ts → utilities/searchify.d.ts} +1 -1
  65. package/dist/utilities/searchify.js +1 -0
  66. package/dist/utilities/searchify.mjs +1 -0
  67. package/package.json +52 -39
  68. package/dist/env.d.ts +0 -26
  69. package/dist/env.js +0 -1
  70. package/dist/env.mjs +0 -1
  71. package/dist/http.d.ts +0 -294
  72. package/dist/http.js +0 -1
  73. package/dist/http.mjs +0 -1
  74. package/dist/logger.js +0 -1
  75. package/dist/searchify.js +0 -1
  76. package/dist/searchify.mjs +0 -1
  77. package/dist/serialize.d.ts +0 -80
  78. package/dist/serialize.js +0 -1
  79. package/dist/serialize.mjs +0 -1
  80. package/dist/syhemo.d.ts +0 -102
  81. package/dist/syhemo.js +0 -1
  82. package/dist/syhemo.mjs +0 -1
  83. /package/dist/{slugify.d.ts → utilities/slugify.d.ts} +0 -0
  84. /package/dist/{slugify.js → utilities/slugify.js} +0 -0
  85. /package/dist/{slugify.mjs → utilities/slugify.mjs} +0 -0
package/dist/http.d.ts DELETED
@@ -1,294 +0,0 @@
1
- import { type FileListLike } from "./utilities/filelist";
2
- import type { Promisable } from "./types/built-in";
3
- /** Default base URL for HTTP requests, sourced from `API_URL` env variable. */
4
- export declare const DEFAULT_BASE_URL: string | undefined;
5
- /** Authentication token storage key, sourced from `API_AUTH_TOKEN_KEY` env variable. */
6
- export declare const API_AUTH_TOKEN_KEY: string | undefined;
7
- /** Authentication header name, sourced from `API_AUTH_HEADER_KEY` env variable. */
8
- export declare const API_AUTH_HEADER_KEY: string | undefined;
9
- /** Authentication header type prefix (e.g. "Bearer"), sourced from `API_AUTH_HEADER_TYPE` env variable. */
10
- export declare const API_AUTH_HEADER_TYPE: string | undefined;
11
- /** Supported HTTP methods. */
12
- export declare enum HttpMethod {
13
- GET = "GET",
14
- POST = "POST",
15
- PUT = "PUT",
16
- DELETE = "DELETE",
17
- PATCH = "PATCH",
18
- HEAD = "HEAD",
19
- OPTIONS = "OPTIONS"
20
- }
21
- /** Upload method types for {@link Http.createFactory}. */
22
- export declare enum HttpUpload {
23
- UPLOAD = "UPLOAD",
24
- RELATED = "RELATED"
25
- }
26
- /** Accepted query parameter formats for HTTP requests. */
27
- export type HttpQuery = string | Record<string, string | number | boolean | undefined> | Array<[string, string | number | boolean | undefined]> | URLSearchParams;
28
- /** Configuration object for an HTTP request. */
29
- export interface HttpRequest<Body = unknown, Params = Record<string, unknown>, Query = HttpQuery, Headers = Record<string, string>> {
30
- method: HttpMethod;
31
- url: string;
32
- headers?: Headers;
33
- body?: Body;
34
- query?: Query;
35
- params?: Params;
36
- signal?: AbortSignal;
37
- /**
38
- * Pass-through bag for `fetch`'s `RequestInit` options that the
39
- * library does not manage itself (`credentials`, `cache`, `mode`,
40
- * `redirect`, `referrer`, `referrerPolicy`, `integrity`, `keepalive`,
41
- * `priority`, `duplex`) plus framework extensions (`next` on Next.js,
42
- * `cf` on Cloudflare Workers, `dispatcher` on undici).
43
- *
44
- * Lib-level fields (`method`, `headers`, `body`, `signal`) cannot be
45
- * overridden here — they are applied after this bag is spread.
46
- * Unknown keys are silently dropped, so a compromised caller cannot
47
- * smuggle arbitrary fields into `fetch`.
48
- */
49
- configs?: Record<string, unknown>;
50
- }
51
- /** Constructor options for {@link Http}. */
52
- export interface HttpOptions {
53
- /** Base URL prepended to every relative request path. */
54
- baseURL?: string;
55
- /**
56
- * Additional origins (besides `baseURL`'s origin) that absolute URLs
57
- * and redirect responses are permitted to reach. Any other origin is
58
- * rejected before the request is sent and, for redirects, before the
59
- * response body is returned.
60
- */
61
- allowedOrigins?: ReadonlyArray<string>;
62
- /**
63
- * Default `configs` merged into every request sent through this
64
- * instance. Same shape and allowlist as {@link HttpRequest.configs}:
65
- * `credentials`, `cache`, `mode`, `redirect`, `referrer`,
66
- * `referrerPolicy`, `integrity`, `keepalive`, `priority`, `duplex`,
67
- * plus framework extensions (`next`, `cf`, `dispatcher`). Per-call
68
- * `configs` override these.
69
- */
70
- configs?: Record<string, unknown>;
71
- }
72
- /** Storage adapter interface for reading/writing auth tokens (e.g. `localStorage`). */
73
- export interface HttpStorage {
74
- getItem(key: string): Promisable<string | null>;
75
- setItem(key: string, value: string): Promisable<void>;
76
- removeItem(key: string, options?: any): Promisable<void>;
77
- }
78
- /** Interceptor that can modify a request before it is sent. */
79
- export type HttpInterceptorRequest = (options: HttpRequest) => Promise<HttpRequest> | HttpRequest;
80
- /** Interceptor that can modify a `Response` after it is received. */
81
- export type HttpInterceptorResponse = (response: Response) => Promise<Response> | Response;
82
- /** Interceptor that transforms the parsed response data. */
83
- export type HttpInterceptorTransform = (data: any) => Promise<any> | any;
84
- /** Interceptor that handles errors from requests. */
85
- export type HttpInterceptorError = (error: unknown) => Promise<any> | any;
86
- /** Tuple type for registering interceptors by phase. */
87
- export type HttpInterceptorParameters = ["request", HttpInterceptorRequest] | ["response", HttpInterceptorResponse] | ["transform", HttpInterceptorTransform] | ["error", HttpInterceptorError];
88
- /** Normalized response returned by all `Http` methods. */
89
- export interface HttpResponse<T = unknown, E = unknown> {
90
- success: boolean;
91
- data: T;
92
- status: number;
93
- statusText: string;
94
- headers: Record<string, string>;
95
- error: E | null;
96
- }
97
- /** Upload progress snapshot. */
98
- export interface HttpProgress {
99
- loaded: number;
100
- total: number;
101
- percentage: number;
102
- }
103
- /** Options for file upload, including progress tracking. */
104
- export interface HttpUploadOptions extends Pick<HttpRequest, "headers" | "params" | "signal" | "query"> {
105
- onProgress?: (progress: HttpProgress) => void;
106
- name: string;
107
- body?: Record<string, unknown>;
108
- }
109
- /** Options for a multipart/related upload (e.g. Google Drive). */
110
- export interface HttpRelatedOptions extends Pick<HttpRequest, "headers" | "params" | "signal" | "query"> {
111
- /** JSON metadata object (will be serialized as the first part). */
112
- metadata: Record<string, unknown>;
113
- /** MIME type of the metadata part. Default: "application/json" */
114
- metadataMimeType?: string;
115
- /** MIME type of the file content. */
116
- contentType: string;
117
- }
118
- /** Options for creating an HTTP factory via {@link Http.createFactory}. */
119
- export interface HttpFactoryOptions {
120
- baseURL?: string;
121
- http?: Http;
122
- storage?: HttpStorage | (() => Promise<HttpStorage> | HttpStorage);
123
- endpoint?: Record<string, unknown> | (() => Record<string, unknown>);
124
- }
125
- /** A factory-generated endpoint descriptor with a key and an async `fn`. */
126
- export interface HttpFactory<T = unknown, Args extends any[] = [], E = unknown> {
127
- key: string;
128
- fn: (...args: Args) => Promise<HttpResponse<T, E>>;
129
- }
130
- /** Central registry for grouping endpoint URLs by service name. */
131
- export declare class Endpoint {
132
- private static registered;
133
- static register(service: string, endpoints: Record<string, string>): typeof Endpoint;
134
- static all(): {
135
- [x: string]: Record<string, string>;
136
- };
137
- }
138
- /**
139
- * HTTP client with interceptors, auth token management, file uploads,
140
- * and a factory pattern for endpoint generation.
141
- *
142
- * @example
143
- * ```ts
144
- * const http = new Http("https://api.example.com");
145
- *
146
- * const { data } = await http.get<User[]>("/users");
147
- * await http.post<User>("/users", { name: "Alice" });
148
- * await http.upload<Media>("/upload", file, { name: "avatar" });
149
- * ```
150
- */
151
- export declare class Http {
152
- static readonly method: typeof HttpMethod;
153
- static readonly Endpoint: typeof Endpoint;
154
- static authTokenKey: string;
155
- static authHeaderKey: string;
156
- static authHeaderType: string;
157
- static authDetectToken: string[];
158
- /**
159
- * One-shot headers merged into the very next request across all
160
- * instances, then cleared. Intended for request-scoped values like
161
- * CSRF tokens or correlation IDs that callers don't want to thread
162
- * through every call site.
163
- *
164
- * Note: this is a process-wide mutable static. In concurrent async
165
- * contexts (e.g. multiple tenants sharing one process) it is the
166
- * caller's responsibility to ensure the set → dispatch → reset
167
- * sequence is not interleaved.
168
- */
169
- static extraHeaders: Record<string, string> | null;
170
- static storage: HttpStorage | null;
171
- private defaultHeaders;
172
- readonly method: typeof HttpMethod;
173
- private storage;
174
- private static interceptors;
175
- private interceptors;
176
- private readonly baseURL;
177
- private readonly allowedOrigins;
178
- private readonly defaultConfigs;
179
- /**
180
- * @param init - Either a base URL string (backwards-compatible form)
181
- * or an {@link HttpOptions} object. Using the object form lets
182
- * callers opt in to additional origins that absolute URLs and
183
- * redirect responses are permitted to reach. Any other origin is
184
- * rejected before the request is sent and, for redirects, before
185
- * the response body is returned.
186
- *
187
- * @example
188
- * ```ts
189
- * new Http("https://api.example.com");
190
- * new Http({
191
- * baseURL: "https://api.example.com",
192
- * allowedOrigins: ["https://cdn.example.com"],
193
- * });
194
- * ```
195
- */
196
- constructor(init?: string | HttpOptions);
197
- /** Whether `origin` is this instance's baseURL origin or an explicitly allowed one. */
198
- private isAllowedOrigin;
199
- /**
200
- * If a request was sent with credentials (Authorization / Cookie) and
201
- * ended up at a different origin via redirect, refuse to return the
202
- * response. Defends against token exfil via server-controlled 3xx.
203
- */
204
- private assertSameOriginResponse;
205
- /** Register a global interceptor (applies to all `Http` instances). */
206
- static on(...params: HttpInterceptorParameters): void;
207
- /** Remove a global interceptor. */
208
- static off(...params: HttpInterceptorParameters): void;
209
- /** Set the storage adapter for this instance (used to read auth tokens). */
210
- setStorage(storage: HttpStorage): void;
211
- /** Type guard that checks whether a value is a valid {@link HttpQuery}. */
212
- isValidQuery(query: unknown): query is HttpQuery;
213
- getQuery<Params extends Record<string, unknown>>(options: HttpRequest<unknown, Params>): string;
214
- /** Merge additional default headers into this instance. */
215
- addHeaders(headers: Record<string, string>): void;
216
- /** Register an instance-level interceptor. */
217
- on(...params: HttpInterceptorParameters): this;
218
- /** Remove an instance-level interceptor. */
219
- off(...params: HttpInterceptorParameters): this;
220
- /** Read the auth token from storage and format it with the configured header type. */
221
- getToken(): Promise<{
222
- key: string;
223
- value: string;
224
- }>;
225
- /** Build the final headers object, injecting auth token and Content-Type. */
226
- getHeaders(headers?: Record<string, string>, isFormData?: boolean): Promise<{
227
- [x: string]: string;
228
- }>;
229
- /**
230
- * Build the full URL from base URL, path, query string, and path params.
231
- *
232
- * Security rules applied here (see SECURITY audit):
233
- * - Absolute URLs must use `http`/`https` and their origin must match
234
- * `baseURL`'s origin or an entry in `allowedOrigins`.
235
- * - Protocol-relative URLs (`//host/…`) are rejected — they silently
236
- * flip the target host.
237
- * - Path params (`{id}`) are URL-encoded by `interpolateURL`
238
- * so a value of `"../admin"` cannot traverse the path.
239
- * - Proto-pollution keys in `params` are stripped.
240
- */
241
- getURL(options: HttpRequest): string;
242
- /** Serialize the request body (JSON, FormData, or binary). Returns `undefined` for bodyless methods. */
243
- getBody(options: HttpRequest): string | FormData | Uint8Array | ArrayBuffer | undefined;
244
- /** Execute a full HTTP request with all interceptors applied. */
245
- request<T = unknown, E = unknown>(options: HttpRequest): Promise<HttpResponse<T, E>>;
246
- /** Perform a GET request. */
247
- get<T = unknown, Query = Record<string, unknown>, E = unknown>(url: string, query?: Query, options?: Pick<HttpRequest, "headers" | "params" | "signal">): Promise<HttpResponse<T, E>>;
248
- /** Perform a POST request. */
249
- post<T = unknown, Body = unknown, E = unknown>(url: string, body?: Body, options?: Pick<HttpRequest, "headers" | "params" | "signal" | "query">): Promise<HttpResponse<T, E>>;
250
- /** Perform a PUT request. */
251
- put<T = unknown, Body = unknown, E = unknown>(url: string, body?: Body, options?: Pick<HttpRequest, "headers" | "params" | "signal" | "query">): Promise<HttpResponse<T, E>>;
252
- /** Perform a PATCH request. */
253
- patch<T = unknown, Body = unknown, E = unknown>(url: string, body?: Body, options?: Pick<HttpRequest, "headers" | "params" | "signal" | "query">): Promise<HttpResponse<T, E>>;
254
- /** Perform a DELETE request. */
255
- delete<T = unknown, E = unknown>(url: string, options?: Pick<HttpRequest, "headers" | "params" | "signal" | "query">): Promise<HttpResponse<T, E>>;
256
- /** Perform a HEAD request. */
257
- head<T = unknown, E = unknown>(url: string, options?: Pick<HttpRequest, "headers" | "params" | "signal" | "query">): Promise<HttpResponse<T, E>>;
258
- /** Perform an OPTIONS request. */
259
- options<T = unknown, E = unknown>(url: string, options?: Pick<HttpRequest, "headers" | "params" | "signal" | "query">): Promise<HttpResponse<T, E>>;
260
- /**
261
- * Upload one or more files via POST.
262
- * Falls back to `XMLHttpRequest` when `onProgress` is provided for progress tracking.
263
- */
264
- upload<T = unknown, E = unknown>(url: string, file: File | File[] | FileListLike, options?: HttpUploadOptions): Promise<HttpResponse<T, E>>;
265
- /**
266
- * Upload with multipart/related format.
267
- * Builds a proper multipart/related body with JSON metadata + binary file content.
268
- *
269
- * @example
270
- * ```ts
271
- * const result = await http.related<DriveFile>("/files?uploadType=multipart", fileBuffer, {
272
- * metadata: { name: "photo.jpg", parents: ["folderId"] },
273
- * contentType: "image/jpeg",
274
- * });
275
- * ```
276
- */
277
- related<T = unknown, E = unknown>(url: string, fileData: ArrayBuffer | Uint8Array, options: HttpRelatedOptions): Promise<HttpResponse<T, E>>;
278
- /**
279
- * Creates a factory function that generates typed endpoint descriptors.
280
- * Each descriptor has a `key` and an async `fn` that performs the HTTP call.
281
- *
282
- * @example
283
- * ```ts
284
- * const api = Http.createFactory({
285
- * baseURL: "https://api.example.com",
286
- * endpoint: { users: { list: "/users", create: "/users" } },
287
- * });
288
- *
289
- * const getUsers = api<User[]>("users.list");
290
- * const { data } = await getUsers.fn();
291
- * ```
292
- */
293
- static createFactory(options?: HttpFactoryOptions): <T, Args extends any[] = [], E = unknown>(key: string, method?: HttpMethod | HttpUpload) => HttpFactory<T, Args, E>;
294
- }
package/dist/http.js DELETED
@@ -1 +0,0 @@
1
- "use strict";var t=require("./utilities/get.js"),e=require("./env.js"),r=require("./utilities/flatten.js"),s=require("./serialize.js"),o=require("./utilities/sanitize-mime.js"),n=require("./utilities/formdata.js"),i=require("./utilities/filelist.js");function a(t){try{return new URL(t).origin}catch(t){return null}}const c=new Set(["__proto__","constructor","prototype"]),d=new Set(["credentials","cache","mode","redirect","referrer","referrerPolicy","integrity","keepalive","priority","duplex","window","next","cf","dispatcher"]);function l(t){const e=Object.create(null);for(const r of Object.keys(t))d.has(r)&&(e[r]=t[r]);return e}function p(t){const e=Object.create(null);for(const r of Object.keys(t))c.has(r)||(e[r]=t[r]);return e}const u=e.getEnv("API_URL","/"),h=e.getEnv("API_AUTH_TOKEN_KEY"),g=e.getEnv("API_AUTH_HEADER_KEY"),f=e.getEnv("API_AUTH_HEADER_TYPE");var y,T;exports.HttpMethod=void 0,(y=exports.HttpMethod||(exports.HttpMethod={})).GET="GET",y.POST="POST",y.PUT="PUT",y.DELETE="DELETE",y.PATCH="PATCH",y.HEAD="HEAD",y.OPTIONS="OPTIONS",exports.HttpUpload=void 0,(T=exports.HttpUpload||(exports.HttpUpload={})).UPLOAD="UPLOAD",T.RELATED="RELATED";class E{static register(t,e){return this.registered[t]=Object.assign({},e),this}static all(){return Object.assign({},this.registered)}}E.registered={};class H{constructor(t){var e,r,s;this.defaultHeaders={"Content-Type":"application/json"},this.method=H.method,this.storage=H.storage,this.interceptors={request:[],response:[],transform:[],error:[]};const o="string"==typeof t||void 0===t?{baseURL:null!=t?t:u}:t;this.baseURL=null!==(r=null!==(e=o.baseURL)&&void 0!==e?e:u)&&void 0!==r?r:"/";const n=new Set;for(const t of null!==(s=o.allowedOrigins)&&void 0!==s?s:[]){const e=a(t);if(!e)throw new Error(`Http: invalid allowedOrigins entry: ${t}`);n.add(e)}const i=a(this.baseURL);i&&n.add(i),this.allowedOrigins=n,this.defaultConfigs=o.configs?l(o.configs):{}}isAllowedOrigin(t){return 0===this.allowedOrigins.size||this.allowedOrigins.has(t)}assertSameOriginResponse(t,e,r){const s=Object.keys(r).some(t=>"authorization"===t.toLowerCase()&&!!r[t]),o=Object.keys(r).some(t=>"cookie"===t.toLowerCase()&&!!r[t]);if(!s&&!o)return;const n=a(t);if(!n)return;const i=e.url?a(e.url):null;if(i&&i!==n&&!this.isAllowedOrigin(i))throw new Error(`Http: credentialed request was redirected from ${n} to untrusted origin ${i}`)}static on(...t){const[e,r]=t,s=H.interceptors[e];s.includes(r)||s.push(r),H.interceptors[e]=s}static off(...t){const[e,r]=t,s=H.interceptors[e];H.interceptors[e]=s.filter(t=>t!==r)}setStorage(t){this.storage=t}isValidQuery(t){return"string"==typeof t||t instanceof URLSearchParams||(Array.isArray(t)?t.every(t=>Array.isArray(t)&&2===t.length&&"string"==typeof t[0]&&s.Serialize.Primitive.isPrimitive(t[1])):"object"==typeof t&&null!==t&&Object.values(t).every(t=>s.Serialize.Primitive.isPrimitive(t)))}getQuery(t){const{method:e,body:r,query:o}=t,n=e===exports.HttpMethod.GET&&this.isValidQuery(r)?r:o;if(!n||"object"!=typeof n)return"string"==typeof n?n:"";if(n instanceof URLSearchParams)return n.toString();const i=p(n);return s.Serialize.queryString.stringify(i,{skipNull:!0,skipEmptyString:!0})}addHeaders(t){this.defaultHeaders=Object.assign(Object.assign({},this.defaultHeaders),t)}on(...t){const[e,r]=t,s=this.interceptors[e];return s.includes(r)||s.push(r),this.interceptors[e]=s,this}off(...t){const[e,r]=t,s=this.interceptors[e];return this.interceptors[e]=s.filter(t=>t!==r),this}async getToken(){const t=h||H.authTokenKey,e=g||H.authHeaderKey,r=f||H.authHeaderType;if(!t||!e)return{key:e,value:""};let s="";this.storage&&(s=await this.storage.getItem(t)||"");const o={key:e,value:""};return s&&/^[\x21-\x7E]+$/.test(s)&&(o.value=r?`${r} ${s}`:s),o}async getHeaders(t={},e){const r=await this.getToken();r.key in t&&t[r.key]||(t[r.key]=r.value),e&&"Content-Type"in t?delete t["Content-Type"]:t["Content-Type"]=t["Content-Type"]||this.defaultHeaders["Content-Type"]||"application/json";const s=Object.assign(Object.assign(Object.assign({},this.defaultHeaders),t),H.extraHeaders||{});return H.extraHeaders=null,s}getURL(e){const{url:r="",params:o={}}=e,n=this.getQuery(e);let i;if(r){if(r.startsWith("//"))throw new Error(`Http: protocol-relative URLs are not allowed: ${r}`);if(/^[a-z][a-z0-9+.-]*:/i.test(r)){let t;try{t=new URL(r)}catch(t){throw new Error(`Http: invalid absolute URL: ${r}`)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new Error(`Http: unsupported URL scheme: ${t.protocol}`);if(!this.isAllowedOrigin(t.origin))throw new Error(`Http: URL origin '${t.origin}' is not in allowedOrigins`);i=t.toString()}else{const t=(this.baseURL||"/").replace(/\/+$/,""),e=r.replace(/^\/+/,"");i=t?`${t}/${e}`:`/${e}`}}else i=this.baseURL||"/";if(n){const t=i.includes("?")?"&":"?";i+=`${t}${n}`}if(!i.includes("{")||!i.includes("}"))return i;const a=Array.isArray(o)?o:p(o);return i.replace(/\{([a-zA-Z0-9_.-]+)\}/g,(e,r)=>{const o=t.get(a,r);return null==o||"object"==typeof o?"":s.Serialize.URL.encode(String(o))})}getBody(t){const{method:e,body:r}=t;if(e!==exports.HttpMethod.GET&&e!==exports.HttpMethod.HEAD&&e!==exports.HttpMethod.OPTIONS&&e!==exports.HttpMethod.DELETE)return e!==exports.HttpMethod.POST&&e!==exports.HttpMethod.PUT&&e!==exports.HttpMethod.PATCH||!n.isFormData(r)?r instanceof Uint8Array||r instanceof ArrayBuffer?r:void 0!==r?JSON.stringify(r):void 0:r}async request(t){const{method:e=exports.HttpMethod.GET}=t;try{let r=Object.assign({},t);const s=[...H.interceptors.request,...this.interceptors.request];for(const t of s)r=await t(r);const o=this.getURL(r),i=await this.getHeaders(r.headers||{});n.isFormData(r.body)&&"Content-Type"in i&&delete i["Content-Type"];const a=Object.assign(Object.assign({},this.defaultConfigs),r.configs?l(r.configs):{}),c=await fetch(o,Object.assign(Object.assign({},a),{method:r.method||e,headers:i,body:this.getBody(r),signal:r.signal}));this.assertSameOriginResponse(o,c,i);const d=c.headers.get("Content-Type")||"";let p=null;p=d.includes("application/json")?await c.json():await c.text();const u=[...H.interceptors.transform,...this.interceptors.transform];let h=p;for(const t of u)h=await t(h);const g=[...H.interceptors.response,...this.interceptors.response];let f=c;for(const t of g)f=await t(f);const y={};f.headers.forEach((t,e)=>{y[e]=t});const T=f.ok;let E=null;if(!T){E=p.error||p;const t=[...H.interceptors.error,...this.interceptors.error];for(const e of t)E=await e(E)}return{data:h,success:T,error:T?null:E,status:f.status,statusText:f.statusText,headers:y}}catch(t){let e=t instanceof Error?t:new Error(String(t));const r=[...H.interceptors.error,...this.interceptors.error];for(const t of r)e=await t(e);return{data:null,status:0,statusText:"Error",headers:{},error:e,success:!1}}}get(t,e,r){return this.request(Object.assign(Object.assign({},r),{method:exports.HttpMethod.GET,url:t,query:e}))}post(t,e,r){return this.request(Object.assign(Object.assign({},r),{method:exports.HttpMethod.POST,url:t,body:e}))}put(t,e,r){return this.request(Object.assign(Object.assign({},r),{method:exports.HttpMethod.PUT,url:t,body:e}))}patch(t,e,r){return this.request(Object.assign(Object.assign({},r),{method:exports.HttpMethod.PATCH,url:t,body:e}))}delete(t,e){return this.request(Object.assign(Object.assign({},e),{method:exports.HttpMethod.DELETE,url:t}))}head(t,e){return this.request(Object.assign(Object.assign({},e),{method:exports.HttpMethod.HEAD,url:t}))}options(t,e){return this.request(Object.assign(Object.assign({},e),{method:exports.HttpMethod.OPTIONS,url:t}))}upload(t,e,s){const o=(null==s?void 0:s.body)?n.objectToFormData(s.body):new FormData;let a=(null==s?void 0:s.name)||"file";if(Array.isArray(e)?(a.endsWith("[]")&&(a=a.slice(0,-2)),e.forEach((t,e)=>{o.append(`${a}[${e}]`,t,t.name)})):i.isFileList(e)?(a.endsWith("[]")&&(a=a.slice(0,-2)),Array.from(e).forEach((t,e)=>{o.append(`${a}[${e}]`,t,t.name)})):o.append(a,e,e.name),null==s?void 0:s.body){const t=r.flatten(s.body);Object.entries(t).forEach(([t,e])=>{null!=e&&o.append(t,String(e))})}return(null==s?void 0:s.onProgress)&&"undefined"!=typeof XMLHttpRequest?new Promise(async e=>{try{let r=Object.assign(Object.assign({},s),{method:exports.HttpMethod.POST,url:t,body:o});const n=[...H.interceptors.request,...this.interceptors.request];for(const t of n)r=await t(r);const i=this.getURL(r),a=await this.getHeaders(r.headers||{},!0),c=new XMLHttpRequest;c.upload.addEventListener("progress",t=>{var e;if(t.lengthComputable){const r=Math.round(t.loaded/t.total*100);null===(e=s.onProgress)||void 0===e||e.call(s,{loaded:t.loaded,total:t.total,percentage:r})}}),c.addEventListener("load",async()=>{try{const t=c.getResponseHeader("Content-Type")||"";let r=null;r=t.includes("application/json")?JSON.parse(c.responseText):c.responseText;const s=[...H.interceptors.transform,...this.interceptors.transform];let o=r;for(const t of s)o=await t(o);const n=[...H.interceptors.response,...this.interceptors.response];let i=new Response(c.responseText,{status:c.status,statusText:c.statusText,headers:a});for(const t of n)i=await t(i);const d={};i.headers.forEach((t,e)=>{d[e]=t});const l=i.ok;e({data:o,success:l,error:l?null:o,status:i.status,statusText:i.statusText,headers:d})}catch(t){const r=[...H.interceptors.error,...this.interceptors.error];for(const e of r)e(t);e({data:null,status:0,statusText:"Error",headers:{},error:t,success:!1})}}),c.addEventListener("error",t=>{const r=[...H.interceptors.error,...this.interceptors.error];for(const e of r)e(t);e({data:null,status:0,statusText:"Error",headers:{},error:t,success:!1})}),c.addEventListener("abort",()=>{e({data:null,status:0,statusText:"Aborted",headers:{},error:null,success:!1})}),c.open(r.method||exports.HttpMethod.POST,i,!0),Object.entries(a).forEach(([t,e])=>{"content-type"!==(null==t?void 0:t.toLowerCase())&&e&&c.setRequestHeader(t,e)}),c.send(r.body)}catch(t){const r=[...H.interceptors.error,...this.interceptors.error];for(const e of r)e(t);e({data:null,status:0,statusText:"Error",headers:{},error:t,success:!1})}}):this.request({method:exports.HttpMethod.POST,url:t,body:o,headers:null==s?void 0:s.headers,params:null==s?void 0:s.params,signal:null==s?void 0:s.signal,query:null==s?void 0:s.query})}related(t,e,r){const s=o.sanitizeMime(r.contentType),n=o.sanitizeMime(r.metadataMimeType||"application/json"),i=`----related-boundary-${Date.now()}-${Math.random().toString(36).slice(2)}`,a=JSON.stringify(r.metadata),c=new TextEncoder,d=c.encode(`--${i}\r\nContent-Type: ${n}; charset=UTF-8\r\n\r\n`+a+"\r\n"),l=c.encode(`--${i}\r\nContent-Type: ${s}\r\nContent-Transfer-Encoding: binary\r\n\r\n`),p=c.encode(`\r\n--${i}--`),u=e instanceof Uint8Array?e:new Uint8Array(e),h=new Uint8Array(d.length+l.length+u.length+p.length);return[d,l,u,p].reduce((t,e)=>(h.set(e,t),t+e.length),0),this.request({method:exports.HttpMethod.POST,url:t,body:h,headers:Object.assign(Object.assign({},r.headers||{}),{"Content-Type":`multipart/related; boundary=${i}`}),params:r.params,signal:r.signal,query:r.query})}static createFactory(t={}){const e=t.http||new H(t.baseURL);return function(s,o){const n=r.flatten("function"==typeof t.endpoint?t.endpoint():t.endpoint||{})[s];return{key:s,fn:async(...r)=>{const s="function"==typeof t.storage?await t.storage():t.storage;switch(s&&e.setStorage(s),o){case exports.HttpMethod.POST:return await e.post(n,...r);case exports.HttpMethod.PUT:return await e.put(n,...r);case exports.HttpMethod.PATCH:return await e.patch(n,...r);case exports.HttpMethod.DELETE:return await e.delete(n,...r);case exports.HttpMethod.HEAD:return await e.head(n,...r);case exports.HttpMethod.OPTIONS:return await e.options(n,...r);case exports.HttpUpload.UPLOAD:return await e.upload(n,...r);case exports.HttpUpload.RELATED:return await e.related(n,...r);default:return await e.get(n,...r)}}}}}}H.method=exports.HttpMethod,H.Endpoint=E,H.authTokenKey="access_token",H.authHeaderKey="Authorization",H.authHeaderType="Bearer",H.authDetectToken=["localStorage","sessionStorage","cookie"],H.extraHeaders=null,H.storage=null,H.interceptors={request:[],response:[],transform:[],error:[]},exports.API_AUTH_HEADER_KEY=g,exports.API_AUTH_HEADER_TYPE=f,exports.API_AUTH_TOKEN_KEY=h,exports.DEFAULT_BASE_URL=u,exports.Endpoint=E,exports.Http=H;
package/dist/http.mjs DELETED
@@ -1 +0,0 @@
1
- import{get as t}from"./utilities/get.mjs";import{getEnv as e}from"./env.mjs";import{flatten as r}from"./utilities/flatten.mjs";import{Serialize as s}from"./serialize.mjs";import{sanitizeMime as n}from"./utilities/sanitize-mime.mjs";import{isFormData as o,objectToFormData as i}from"./utilities/formdata.mjs";import{isFileList as a}from"./utilities/filelist.mjs";function c(t){try{return new URL(t).origin}catch(t){return null}}const l=new Set(["__proto__","constructor","prototype"]),u=new Set(["credentials","cache","mode","redirect","referrer","referrerPolicy","integrity","keepalive","priority","duplex","window","next","cf","dispatcher"]);function d(t){const e=Object.create(null);for(const r of Object.keys(t))u.has(r)&&(e[r]=t[r]);return e}function p(t){const e=Object.create(null);for(const r of Object.keys(t))l.has(r)||(e[r]=t[r]);return e}const h=e("API_URL","/"),f=e("API_AUTH_TOKEN_KEY"),g=e("API_AUTH_HEADER_KEY"),y=e("API_AUTH_HEADER_TYPE");var m,T;!function(t){t.GET="GET",t.POST="POST",t.PUT="PUT",t.DELETE="DELETE",t.PATCH="PATCH",t.HEAD="HEAD",t.OPTIONS="OPTIONS"}(m||(m={})),function(t){t.UPLOAD="UPLOAD",t.RELATED="RELATED"}(T||(T={}));class O{static register(t,e){return this.registered[t]=Object.assign({},e),this}static all(){return Object.assign({},this.registered)}}O.registered={};class b{constructor(t){var e,r,s;this.defaultHeaders={"Content-Type":"application/json"},this.method=b.method,this.storage=b.storage,this.interceptors={request:[],response:[],transform:[],error:[]};const n="string"==typeof t||void 0===t?{baseURL:null!=t?t:h}:t;this.baseURL=null!==(r=null!==(e=n.baseURL)&&void 0!==e?e:h)&&void 0!==r?r:"/";const o=new Set;for(const t of null!==(s=n.allowedOrigins)&&void 0!==s?s:[]){const e=c(t);if(!e)throw new Error(`Http: invalid allowedOrigins entry: ${t}`);o.add(e)}const i=c(this.baseURL);i&&o.add(i),this.allowedOrigins=o,this.defaultConfigs=n.configs?d(n.configs):{}}isAllowedOrigin(t){return 0===this.allowedOrigins.size||this.allowedOrigins.has(t)}assertSameOriginResponse(t,e,r){const s=Object.keys(r).some(t=>"authorization"===t.toLowerCase()&&!!r[t]),n=Object.keys(r).some(t=>"cookie"===t.toLowerCase()&&!!r[t]);if(!s&&!n)return;const o=c(t);if(!o)return;const i=e.url?c(e.url):null;if(i&&i!==o&&!this.isAllowedOrigin(i))throw new Error(`Http: credentialed request was redirected from ${o} to untrusted origin ${i}`)}static on(...t){const[e,r]=t,s=b.interceptors[e];s.includes(r)||s.push(r),b.interceptors[e]=s}static off(...t){const[e,r]=t,s=b.interceptors[e];b.interceptors[e]=s.filter(t=>t!==r)}setStorage(t){this.storage=t}isValidQuery(t){return"string"==typeof t||t instanceof URLSearchParams||(Array.isArray(t)?t.every(t=>Array.isArray(t)&&2===t.length&&"string"==typeof t[0]&&s.Primitive.isPrimitive(t[1])):"object"==typeof t&&null!==t&&Object.values(t).every(t=>s.Primitive.isPrimitive(t)))}getQuery(t){const{method:e,body:r,query:n}=t,o=e===m.GET&&this.isValidQuery(r)?r:n;if(!o||"object"!=typeof o)return"string"==typeof o?o:"";if(o instanceof URLSearchParams)return o.toString();const i=p(o);return s.queryString.stringify(i,{skipNull:!0,skipEmptyString:!0})}addHeaders(t){this.defaultHeaders=Object.assign(Object.assign({},this.defaultHeaders),t)}on(...t){const[e,r]=t,s=this.interceptors[e];return s.includes(r)||s.push(r),this.interceptors[e]=s,this}off(...t){const[e,r]=t,s=this.interceptors[e];return this.interceptors[e]=s.filter(t=>t!==r),this}async getToken(){const t=f||b.authTokenKey,e=g||b.authHeaderKey,r=y||b.authHeaderType;if(!t||!e)return{key:e,value:""};let s="";this.storage&&(s=await this.storage.getItem(t)||"");const n={key:e,value:""};return s&&/^[\x21-\x7E]+$/.test(s)&&(n.value=r?`${r} ${s}`:s),n}async getHeaders(t={},e){const r=await this.getToken();r.key in t&&t[r.key]||(t[r.key]=r.value),e&&"Content-Type"in t?delete t["Content-Type"]:t["Content-Type"]=t["Content-Type"]||this.defaultHeaders["Content-Type"]||"application/json";const s=Object.assign(Object.assign(Object.assign({},this.defaultHeaders),t),b.extraHeaders||{});return b.extraHeaders=null,s}getURL(e){const{url:r="",params:n={}}=e,o=this.getQuery(e);let i;if(r){if(r.startsWith("//"))throw new Error(`Http: protocol-relative URLs are not allowed: ${r}`);if(/^[a-z][a-z0-9+.-]*:/i.test(r)){let t;try{t=new URL(r)}catch(t){throw new Error(`Http: invalid absolute URL: ${r}`)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new Error(`Http: unsupported URL scheme: ${t.protocol}`);if(!this.isAllowedOrigin(t.origin))throw new Error(`Http: URL origin '${t.origin}' is not in allowedOrigins`);i=t.toString()}else{const t=(this.baseURL||"/").replace(/\/+$/,""),e=r.replace(/^\/+/,"");i=t?`${t}/${e}`:`/${e}`}}else i=this.baseURL||"/";if(o){const t=i.includes("?")?"&":"?";i+=`${t}${o}`}if(!i.includes("{")||!i.includes("}"))return i;const a=Array.isArray(n)?n:p(n);return i.replace(/\{([a-zA-Z0-9_.-]+)\}/g,(e,r)=>{const n=t(a,r);return null==n||"object"==typeof n?"":s.URL.encode(String(n))})}getBody(t){const{method:e,body:r}=t;if(e!==m.GET&&e!==m.HEAD&&e!==m.OPTIONS&&e!==m.DELETE)return e!==m.POST&&e!==m.PUT&&e!==m.PATCH||!o(r)?r instanceof Uint8Array||r instanceof ArrayBuffer?r:void 0!==r?JSON.stringify(r):void 0:r}async request(t){const{method:e=m.GET}=t;try{let r=Object.assign({},t);const s=[...b.interceptors.request,...this.interceptors.request];for(const t of s)r=await t(r);const n=this.getURL(r),i=await this.getHeaders(r.headers||{});o(r.body)&&"Content-Type"in i&&delete i["Content-Type"];const a=Object.assign(Object.assign({},this.defaultConfigs),r.configs?d(r.configs):{}),c=await fetch(n,Object.assign(Object.assign({},a),{method:r.method||e,headers:i,body:this.getBody(r),signal:r.signal}));this.assertSameOriginResponse(n,c,i);const l=c.headers.get("Content-Type")||"";let u=null;u=l.includes("application/json")?await c.json():await c.text();const p=[...b.interceptors.transform,...this.interceptors.transform];let h=u;for(const t of p)h=await t(h);const f=[...b.interceptors.response,...this.interceptors.response];let g=c;for(const t of f)g=await t(g);const y={};g.headers.forEach((t,e)=>{y[e]=t});const m=g.ok;let T=null;if(!m){T=u.error||u;const t=[...b.interceptors.error,...this.interceptors.error];for(const e of t)T=await e(T)}return{data:h,success:m,error:m?null:T,status:g.status,statusText:g.statusText,headers:y}}catch(t){let e=t instanceof Error?t:new Error(String(t));const r=[...b.interceptors.error,...this.interceptors.error];for(const t of r)e=await t(e);return{data:null,status:0,statusText:"Error",headers:{},error:e,success:!1}}}get(t,e,r){return this.request(Object.assign(Object.assign({},r),{method:m.GET,url:t,query:e}))}post(t,e,r){return this.request(Object.assign(Object.assign({},r),{method:m.POST,url:t,body:e}))}put(t,e,r){return this.request(Object.assign(Object.assign({},r),{method:m.PUT,url:t,body:e}))}patch(t,e,r){return this.request(Object.assign(Object.assign({},r),{method:m.PATCH,url:t,body:e}))}delete(t,e){return this.request(Object.assign(Object.assign({},e),{method:m.DELETE,url:t}))}head(t,e){return this.request(Object.assign(Object.assign({},e),{method:m.HEAD,url:t}))}options(t,e){return this.request(Object.assign(Object.assign({},e),{method:m.OPTIONS,url:t}))}upload(t,e,s){const n=(null==s?void 0:s.body)?i(s.body):new FormData;let o=(null==s?void 0:s.name)||"file";if(Array.isArray(e)?(o.endsWith("[]")&&(o=o.slice(0,-2)),e.forEach((t,e)=>{n.append(`${o}[${e}]`,t,t.name)})):a(e)?(o.endsWith("[]")&&(o=o.slice(0,-2)),Array.from(e).forEach((t,e)=>{n.append(`${o}[${e}]`,t,t.name)})):n.append(o,e,e.name),null==s?void 0:s.body){const t=r(s.body);Object.entries(t).forEach(([t,e])=>{null!=e&&n.append(t,String(e))})}return(null==s?void 0:s.onProgress)&&"undefined"!=typeof XMLHttpRequest?new Promise(async e=>{try{let r=Object.assign(Object.assign({},s),{method:m.POST,url:t,body:n});const o=[...b.interceptors.request,...this.interceptors.request];for(const t of o)r=await t(r);const i=this.getURL(r),a=await this.getHeaders(r.headers||{},!0),c=new XMLHttpRequest;c.upload.addEventListener("progress",t=>{var e;if(t.lengthComputable){const r=Math.round(t.loaded/t.total*100);null===(e=s.onProgress)||void 0===e||e.call(s,{loaded:t.loaded,total:t.total,percentage:r})}}),c.addEventListener("load",async()=>{try{const t=c.getResponseHeader("Content-Type")||"";let r=null;r=t.includes("application/json")?JSON.parse(c.responseText):c.responseText;const s=[...b.interceptors.transform,...this.interceptors.transform];let n=r;for(const t of s)n=await t(n);const o=[...b.interceptors.response,...this.interceptors.response];let i=new Response(c.responseText,{status:c.status,statusText:c.statusText,headers:a});for(const t of o)i=await t(i);const l={};i.headers.forEach((t,e)=>{l[e]=t});const u=i.ok;e({data:n,success:u,error:u?null:n,status:i.status,statusText:i.statusText,headers:l})}catch(t){const r=[...b.interceptors.error,...this.interceptors.error];for(const e of r)e(t);e({data:null,status:0,statusText:"Error",headers:{},error:t,success:!1})}}),c.addEventListener("error",t=>{const r=[...b.interceptors.error,...this.interceptors.error];for(const e of r)e(t);e({data:null,status:0,statusText:"Error",headers:{},error:t,success:!1})}),c.addEventListener("abort",()=>{e({data:null,status:0,statusText:"Aborted",headers:{},error:null,success:!1})}),c.open(r.method||m.POST,i,!0),Object.entries(a).forEach(([t,e])=>{"content-type"!==(null==t?void 0:t.toLowerCase())&&e&&c.setRequestHeader(t,e)}),c.send(r.body)}catch(t){const r=[...b.interceptors.error,...this.interceptors.error];for(const e of r)e(t);e({data:null,status:0,statusText:"Error",headers:{},error:t,success:!1})}}):this.request({method:m.POST,url:t,body:n,headers:null==s?void 0:s.headers,params:null==s?void 0:s.params,signal:null==s?void 0:s.signal,query:null==s?void 0:s.query})}related(t,e,r){const s=n(r.contentType),o=n(r.metadataMimeType||"application/json"),i=`----related-boundary-${Date.now()}-${Math.random().toString(36).slice(2)}`,a=JSON.stringify(r.metadata),c=new TextEncoder,l=c.encode(`--${i}\r\nContent-Type: ${o}; charset=UTF-8\r\n\r\n`+a+"\r\n"),u=c.encode(`--${i}\r\nContent-Type: ${s}\r\nContent-Transfer-Encoding: binary\r\n\r\n`),d=c.encode(`\r\n--${i}--`),p=e instanceof Uint8Array?e:new Uint8Array(e),h=new Uint8Array(l.length+u.length+p.length+d.length);return[l,u,p,d].reduce((t,e)=>(h.set(e,t),t+e.length),0),this.request({method:m.POST,url:t,body:h,headers:Object.assign(Object.assign({},r.headers||{}),{"Content-Type":`multipart/related; boundary=${i}`}),params:r.params,signal:r.signal,query:r.query})}static createFactory(t={}){const e=t.http||new b(t.baseURL);return function(s,n){const o=r("function"==typeof t.endpoint?t.endpoint():t.endpoint||{})[s];return{key:s,fn:async(...r)=>{const s="function"==typeof t.storage?await t.storage():t.storage;switch(s&&e.setStorage(s),n){case m.POST:return await e.post(o,...r);case m.PUT:return await e.put(o,...r);case m.PATCH:return await e.patch(o,...r);case m.DELETE:return await e.delete(o,...r);case m.HEAD:return await e.head(o,...r);case m.OPTIONS:return await e.options(o,...r);case T.UPLOAD:return await e.upload(o,...r);case T.RELATED:return await e.related(o,...r);default:return await e.get(o,...r)}}}}}}b.method=m,b.Endpoint=O,b.authTokenKey="access_token",b.authHeaderKey="Authorization",b.authHeaderType="Bearer",b.authDetectToken=["localStorage","sessionStorage","cookie"],b.extraHeaders=null,b.storage=null,b.interceptors={request:[],response:[],transform:[],error:[]};export{g as API_AUTH_HEADER_KEY,y as API_AUTH_HEADER_TYPE,f as API_AUTH_TOKEN_KEY,h as DEFAULT_BASE_URL,O as Endpoint,b as Http,m as HttpMethod,T as HttpUpload};
package/dist/logger.js DELETED
@@ -1 +0,0 @@
1
- "use strict";const o=()=>"undefined"==typeof window,t="",r="",e="",n="",s={LOG:"color:#22c55e;font-weight:bold",WARN:"color:#eab308;font-weight:bold",ERROR:"color:#ef4444;font-weight:bold",DEBUG:"color:#a855f7;font-weight:bold",VERBOSE:"color:#06b6d4;font-weight:bold"},c="color:inherit;font-weight:normal",a={LOG:"color:#22c55e",WARN:"color:#eab308",ERROR:"color:#ef4444",DEBUG:"color:#a855f7",VERBOSE:"color:#06b6d4"};function i(){return(new Date).toLocaleString("en-US",{month:"2-digit",day:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!0})}const f={LOG:"",WARN:e,ERROR:"",DEBUG:"",VERBOSE:""},l=Symbol.for("@ecosy:logger"),m=globalThis;m[l]||(m[l]={buffer:[],errors:0,warns:0,total:0});const R=m[l];exports.Logger=class{constructor(o="@ecosy"){this.context=o}format(t,r,...e){const n="ERROR"===t?console.error:"WARN"===t?console.warn:console.log;R.buffer.push({timestamp:Date.now(),level:t,context:this.context,message:r}),R.buffer.length>200&&R.buffer.shift(),R.total++,"ERROR"===t&&R.errors++,"WARN"===t&&R.warns++,o()?this.formatServer(n,t,r,...e):this.formatBrowser(n,t,r,...e)}formatServer(s,c,a,...l){const m=f[c],R=`${n}${i()}${t}`;s(`${`${m}${r}${c.padEnd(7)}${t}`} ${`${e}${o()&&"undefined"!=typeof process?process.pid:0}${t}`} - ${R} ${`${e}[${this.context}]${t}`} ${`${m}${a}${t}`}`,...l)}formatBrowser(o,t,r,...e){o(`%c${t.padEnd(7)}%c - %c${i()}%c %c[${this.context}]%c %c${r}`,s[t],c,"color:#9ca3af;font-weight:normal",c,"color:#eab308;font-weight:normal",c,a[t],...e)}log(o,...t){this.format("LOG",o,...t)}warn(o,...t){this.format("WARN",o,...t)}error(o,...t){this.format("ERROR",o,...t)}debug(o,...t){this.format("DEBUG",o,...t)}verbose(o,...t){this.format("VERBOSE",o,...t)}static getLogs(){return[...R.buffer]}static drainCounts(){const o={errors:R.errors,warns:R.warns,total:R.total};return R.errors=0,R.warns=0,R.total=0,o}};
package/dist/searchify.js DELETED
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("./slugify.js");const t={separator:"",silent:!0,transformer:Object.assign({},e.DEFAULT_TRANSFORMER)};exports.default=function(i,s){const n=e.slugify(s,t),r=n.length,o={matches:[],positions:[]};if(!r)return o;const l=new Map,g=[...i.split("")].map((i,s)=>{let n=l.get(i);return void 0===n&&(n=e.slugify(i,t),l.set(i,n)),{originIndex:s,slugified:n,char:i}}).filter((e,t,i)=>0===t||(" "!==e.char||" "!==i[t-1].char));if(g.length<r)return o;for(let e=0;e<g.length;){const t=g[e];if(""===t.slugified){e++;continue}let s="",l=e,u=!0;for(;s.length<r&&l<g.length;){const e=g[l];if(""!==e.slugified&&(s+=e.slugified,!n.startsWith(s))){u=!1;break}l++}if(u&&s===n){const s=g[l-1],n=i.substring(t.originIndex,s.originIndex+1);o.matches.push(n),o.positions.push({start:t.originIndex,length:n.length}),e=l}else e++}return o};
@@ -1 +0,0 @@
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};
@@ -1,80 +0,0 @@
1
- import type { LiteralObject } from "./types/built-in";
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 {};
package/dist/serialize.js DELETED
@@ -1 +0,0 @@
1
- "use strict";var e=require("./utilities/freeze.js"),t=require("./utilities/get.js"),r=require("./utilities/object.js"),i=require("./utilities/is-function.js");class n{static interpolate(e,r={}){return e&&"string"==typeof e&&e.trim().length&&e.includes("{")&&e.includes("}")?e.replace(/\{([a-zA-Z0-9_.-]+)\}/g,(e,i)=>{const n=t.get(r,i);return null==n||"object"==typeof n?"":String(n)}):e}static get Primitive(){var t;return null!==(t=n._primitive)&&void 0!==t?t:n._primitive=e.freeze({isString:e=>"string"==typeof e,isNumber:e=>"number"==typeof e&&Number.isFinite(e),isBoolean:e=>"boolean"==typeof e,isPrimitive:e=>!r.isObjectable(e),isDate:e=>e instanceof Date&&!Number.isNaN(e.getTime()),isPlainObject:r.isLiteralObject,normalize(e){const t=n.Primitive;if(t.isPrimitive(e))return"bigint"==typeof e?e.toString():e;if(t.isDate(e))return e.toISOString();if(Array.isArray(e))return e.map(e=>t.normalize(e));if(r.isLiteralObject(e)){const i={};for(const n in e)if(r.hasOwnProperty(e,n)){const r=e[n];void 0!==r&&(i[n]=t.normalize(r))}return i}return e&&r.hasOwnProperty(e,"toJSON")&&i.isFunction(e.toJSON)?e.toJSON():{}}})}static get JSON(){var t;return null!==(t=n._JSON)&&void 0!==t?t:n._JSON=e.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 t;return null!==(t=n._URL)&&void 0!==t?t:n._URL=e.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 t;return null!==(t=n._queryString)&&void 0!==t?t:n._queryString=e.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;
@@ -1 +0,0 @@
1
- import{freeze as t}from"./utilities/freeze.mjs";import{get as e}from"./utilities/get.mjs";import{isLiteralObject as r,hasOwnProperty as i,isObjectable as n}from"./utilities/object.mjs";import{isFunction as o}from"./utilities/is-function.mjs";class s{static interpolate(t,r={}){return t&&"string"==typeof t&&t.trim().length&&t.includes("{")&&t.includes("}")?t.replace(/\{([a-zA-Z0-9_.-]+)\}/g,(t,i)=>{const n=e(r,i);return null==n||"object"==typeof n?"":String(n)}):t}static get Primitive(){var e;return null!==(e=s._primitive)&&void 0!==e?e:s._primitive=t({isString:t=>"string"==typeof t,isNumber:t=>"number"==typeof t&&Number.isFinite(t),isBoolean:t=>"boolean"==typeof t,isPrimitive:t=>!n(t),isDate:t=>t instanceof Date&&!Number.isNaN(t.getTime()),isPlainObject:r,normalize(t){const e=s.Primitive;if(e.isPrimitive(t))return"bigint"==typeof t?t.toString():t;if(e.isDate(t))return t.toISOString();if(Array.isArray(t))return t.map(t=>e.normalize(t));if(r(t)){const r={};for(const n in t)if(i(t,n)){const i=t[n];void 0!==i&&(r[n]=e.normalize(i))}return r}return t&&i(t,"toJSON")&&o(t.toJSON)?t.toJSON():{}}})}static get JSON(){var e;return null!==(e=s._JSON)&&void 0!==e?e:s._JSON=t({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 e;return null!==(e=s._URL)&&void 0!==e?e:s._URL=t({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 e;return null!==(e=s._queryString)&&void 0!==e?e:s._queryString=t({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:a=!1}=e,l=t=>t.length>0&&/^[a-zA-Z0-9_\-.[\]]+$/.test(t),f=t=>u?s.URL.encode(t,u):t,p=[],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&&p.push(`${f(t)}=${f(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)?p.push(`${f(t)}=${f(e.toISOString())}`):p.push(`${f(t)}=${f(String(e))}`):p.push(`${f(t)}=${e?"true":"false"}`):o||p.push(`${f(t)}=`):n||p.push(`${f(t)}=`)};let g=Object.keys(t);a&&(g="function"==typeof a?g.sort(a):g.sort());for(const e of g)c&&!l(e)||m(e,t[e]);return p.join("&")}})}}export{s as Serialize};
package/dist/syhemo.d.ts DELETED
@@ -1,102 +0,0 @@
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 DELETED
@@ -1 +0,0 @@
1
- "use strict";var node_perf_hooks=require("node:perf_hooks"),subscriber=require("./subscriber.js"),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;
package/dist/syhemo.mjs DELETED
@@ -1 +0,0 @@
1
- import{monitorEventLoopDelay}from"node:perf_hooks";import{Subscriber}from"./subscriber.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};
File without changes
File without changes
File without changes