@vielzeug/fetchit 1.0.1 → 1.0.3
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.
- package/dist/fetchit.cjs +1 -1
- package/dist/fetchit.cjs.map +1 -1
- package/dist/fetchit.js +138 -80
- package/dist/fetchit.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +31 -2
- package/dist/index.js +6 -5
- package/dist/logit/dist/logit.cjs +1 -1
- package/dist/logit/dist/logit.cjs.map +1 -1
- package/dist/logit/dist/logit.js +64 -62
- package/dist/logit/dist/logit.js.map +1 -1
- package/package.json +1 -1
package/dist/fetchit.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("./logit/dist/logit.cjs");class E extends Error{url;method;status;originalError;constructor(e,r,n,o,a){super(e),this.name="HttpError",this.url=r,this.method=n,this.status=o,this.originalError=a}}const C=5e3,R=12e4,S={ABORTED:499,BAD_REQUEST:400,CONFLICT:409,FORBIDDEN:403,NOT_ALLOWED:405,NOT_FOUND:404,PRE_CONDITION:412,TIMEOUT:408,UNAUTHORIZED:401},u={ERROR:"ERROR",PENDING:"PENDING",SUCCESS:"SUCCESS"},i=new Map;function T(t,e){if(e.id)return e.id;const{method:r="GET",body:n,headers:o}=e;return JSON.stringify({body:n,headers:o,method:r,url:t})}function f(t,e,r,n,o){const a=Date.now()-o,s=t.toLowerCase(),c=r.method?.toUpperCase()??"GET",l=b(e),p=t==="SUCCESS"?"✓":"✕";y.Logit[s](`HTTP::${c}(…/${l}) ${p} ${a}ms`,{req:r,res:n,url:e})}function b(t){return t.replace(/^https?:\/\/[^/]+\//,"")}async function h(t,e,{id:r,retries:n=2}){const o=Date.now(),a=e.method?.toUpperCase()??"GET";try{const s=await fetch(t,e),c=await O(s);return f("SUCCESS",t,e,c,o),d(r,u.SUCCESS),{data:c,ok:s.ok,status:s.status}}catch(s){if(f("ERROR",t,e,s,o),d(r,u.ERROR),n>0&&s instanceof TypeError)return h(t,e,{id:r,retries:n-1});throw new E(s instanceof Error?s.message:"Request failed",t,a,void 0,s)}finally{r&&e.method!=="GET"&&i.delete(r)}}async function O(t){if(t.status===204||t.headers.get("content-length")==="0")return;const e=t.headers.get("content-type")??"";return e.includes("application/json")?t.json():e.includes("text")?t.text():t.blob()}function d(t,e){const r=t?i.get(t):void 0;r&&(r.status=e)}async function m(t,e,r){const n=T(t,e);let o=i.get(n);if(o&&U(e,o)&&(o.controller.abort("Request aborted"),i.delete(n),o=void 0),o&&D(o))return o.request;const a=new AbortController,s=I(t,r),c=g(e,r,a),l=h(s,c,{id:n});return i.set(n,{controller:a,expiresIn:Date.now()+(r?.expiresIn??R),request:l,status:u.PENDING}),l}function U(t,e){return t.invalidate?!0:e?t.cancelable&&e.status===u.PENDING||e.status===u.ERROR:!1}function D(t){return Date.now()<=t.expiresIn}function I(t,e){if(!e?.url)return t;const r=e.url.replace(/\/+$/,""),n=t.replace(/^\/+/,"");return`${r}/${n}`}function N(t){return t instanceof FormData||t instanceof Blob||t instanceof ArrayBuffer||t instanceof URLSearchParams||typeof t=="string"}function g(t,e,r){const n=e?.timeout??C,o=AbortSignal.any([r.signal,AbortSignal.timeout(n)]);let a;const s={};return t.body!==void 0&&(N(t.body)?a=t.body:(a=JSON.stringify(t.body),s["Content-Type"]="application/json")),{...t,body:a,headers:j(e?.headers,t.headers,s),signal:o}}function w(t){const e={};if(t instanceof Headers)t.forEach((r,n)=>{e[n]=r});else if(Array.isArray(t))for(const[r,n]of t)e[r]=n;else for(const[r,n]of Object.entries(t))e[r]=n;return e}function j(t,e,r){const n={};if(t)for(const[o,a]of Object.entries(t))a!==void 0&&(n[o]=a);return e&&Object.assign(n,w(e)),r&&Object.assign(n,r),n}function A(t,e){if(!e||Object.keys(e).length===0)return t;const r=new URL(t);for(const[n,o]of Object.entries(e))o!==void 0&&r.searchParams.append(n,String(o));return r.toString()}function P(t={url:""}){const e=r=>(n,o={})=>m(n,{...o,method:r},t);return{cleanupCache(){const r=Date.now(),n=Array.from(i.entries()).filter(([,o])=>r>o.expiresIn).map(([o])=>o);for(const o of n)i.delete(o);return n.length},clearCache(){i.clear()},delete:e("DELETE"),get:e("GET"),getCacheSize(){return i.size},invalidateCache(r){return i.delete(r)},patch:e("PATCH"),post:e("POST"),put:e("PUT"),setHeaders(r){t.headers=Object.fromEntries(Object.entries({...t.headers,...r}).filter(([,n])=>n!==void 0))}}}exports.HttpError=E;exports.RequestErrorType=S;exports.RequestStatus=u;exports.buildUrl=A;exports.createHttpClient=P;
|
|
2
2
|
//# sourceMappingURL=fetchit.cjs.map
|
package/dist/fetchit.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchit.cjs","sources":["../src/fetchit.ts"],"sourcesContent":["import { Logit } from '@vielzeug/logit';\n\ntype RequestParams = Record<string, string | number | undefined>;\n\nexport type RequestResponse<T> = {\n data: T;\n ok: boolean;\n status: number;\n};\n\ntype RequestConfig = Omit<RequestInit, 'body'> & {\n id?: string;\n cancelable?: boolean;\n invalidate?: boolean;\n body?: unknown;\n};\n\ntype ContextProps = {\n expiresIn?: number;\n headers?: Record<string, string | undefined>;\n params?: RequestParams;\n timeout?: number;\n url: string;\n};\n\nconst REQUEST_TIMEOUT = 5000;\nconst CACHE_EXPIRES_IN = 120000;\n\nexport const RequestErrorType = {\n ABORTED: 499,\n BAD_REQUEST: 400,\n CONFLICT: 409,\n FORBIDDEN: 403,\n NOT_ALLOWED: 405,\n NOT_FOUND: 404,\n PRE_CONDITION: 412,\n TIMEOUT: 408,\n UNAUTHORIZED: 401,\n} as const;\n\nexport const RequestStatus = {\n ERROR: 'ERROR',\n PENDING: 'PENDING',\n SUCCESS: 'SUCCESS',\n} as const;\n\ntype RequestData<T> = {\n controller: AbortController;\n expiresIn: number;\n request: Promise<RequestResponse<T>>;\n status: (typeof RequestStatus)[keyof typeof RequestStatus];\n};\n\nconst HttpCache = new Map<string, RequestData<unknown>>();\n\n/**\n * Generates a unique cache key for a request.\n * Uses custom id if provided, otherwise creates a key from url and config.\n */\nfunction getCacheKey(url: string, config: RequestConfig): string {\n if (config.id) return config.id;\n\n // Create a stable cache key from url and relevant config properties\n const { method = 'GET', body, headers } = config;\n return JSON.stringify({ body, headers, method, url });\n}\n\n/**\n * Logs HTTP request results with elapsed time and details.\n */\nfunction log(type: 'SUCCESS' | 'ERROR', url: string, req: RequestInit, res: unknown, startTime: number): void {\n const elapsed = Date.now() - startTime;\n const logType = type.toLowerCase() as 'success' | 'error';\n const method = req.method?.toUpperCase() ?? 'GET';\n const shortUrl = formatUrlForLog(url);\n const icon = type === 'SUCCESS' ? '✓' : '✕';\n\n Logit[logType](`HTTP::${method}(…/${shortUrl}) ${icon} ${elapsed}ms`, {\n req,\n res,\n url,\n });\n}\n\n/**\n * Formats URL for logging by removing protocol and domain.\n */\nfunction formatUrlForLog(url: string): string {\n return url\n .replace(/^https?:\\/\\//, '')\n .split('/')\n .slice(1)\n .join('/');\n}\n\n/**\n * Core fetch function with retry logic and proper error handling.\n */\nasync function fetcher<T>(\n url: string,\n config: RequestInit,\n { id, retries = 2 }: { id?: string; retries?: number },\n): Promise<RequestResponse<T>> {\n const startTime = Date.now();\n\n try {\n const response = await fetch(url, config);\n const data = await parseResponse<T>(response);\n\n log('SUCCESS', url, config, data, startTime);\n updateCacheStatus(id, RequestStatus.SUCCESS);\n\n return { data, ok: response.ok, status: response.status };\n } catch (error) {\n log('ERROR', url, config, error, startTime);\n updateCacheStatus(id, RequestStatus.ERROR);\n\n // Retry on network errors\n if (retries > 0 && error instanceof TypeError) {\n return fetcher(url, config, { id, retries: retries - 1 });\n }\n\n throw error;\n } finally {\n // Clean up non-GET requests from cache\n if (id && config.method !== 'GET') {\n HttpCache.delete(id);\n }\n }\n}\n\n/**\n * Parses response based on content type.\n */\nasync function parseResponse<T>(response: Response): Promise<T> {\n const contentType = response.headers.get('content-type') ?? '';\n\n if (contentType.includes('application/json')) {\n return response.json();\n }\n\n if (contentType.includes('text')) {\n return response.text() as Promise<T>;\n }\n\n return response.blob() as Promise<T>;\n}\n\n/**\n * Updates cache entry status if it exists.\n */\nfunction updateCacheStatus(id: string | undefined, status: (typeof RequestStatus)[keyof typeof RequestStatus]): void {\n if (id) {\n const cached = HttpCache.get(id);\n if (cached) {\n cached.status = status;\n }\n }\n}\n\n/**\n * Makes an HTTP request with caching and cancellation support.\n */\nasync function makeRequest<T>(url: string, config: RequestConfig, context?: ContextProps): Promise<RequestResponse<T>> {\n const key = getCacheKey(url, config);\n let cached = HttpCache.get(key) as RequestData<T> | undefined;\n\n // Handle cache invalidation\n if (shouldInvalidateCache(config, cached)) {\n invalidateCacheEntry(key, cached);\n cached = undefined;\n }\n\n // Return cached response if valid\n if (cached && isCacheValid(cached)) {\n return cached.request;\n }\n\n // Create and execute new request\n const controller = new AbortController();\n const fullUrl = buildFullUrl(url, context);\n const requestConfig = buildRequestConfig(config, context, controller);\n const request = fetcher<T>(fullUrl, requestConfig, { id: key });\n\n // Store in cache\n HttpCache.set(key, {\n controller,\n expiresIn: Date.now() + (context?.expiresIn ?? CACHE_EXPIRES_IN),\n request,\n status: RequestStatus.PENDING,\n });\n\n return request;\n}\n\n/**\n * Checks if a cache should be invalidated.\n */\nfunction shouldInvalidateCache<T>(config: RequestConfig, cached: RequestData<T> | undefined): boolean {\n if (config.invalidate) return true;\n if (!cached) return false;\n\n if (config.cancelable && cached.status === RequestStatus.PENDING) return true;\n\n return cached.status === RequestStatus.ERROR;\n}\n\n/**\n * Invalidates a cache entry by aborting and deleting it.\n */\nfunction invalidateCacheEntry<T>(key: string, cached: RequestData<T> | undefined): void {\n if (cached) {\n cached.controller.abort('Request aborted');\n HttpCache.delete(key);\n }\n}\n\n/**\n * Checks if a cache entry is still valid.\n */\nfunction isCacheValid<T>(cached: RequestData<T>): boolean {\n return Date.now() <= cached.expiresIn;\n}\n\n/**\n * Builds the full URL with a context path.\n */\nfunction buildFullUrl(url: string, context?: ContextProps): string {\n return context?.url ? `${context.url}/${url}` : url;\n}\n\n/**\n * Builds the request configuration with merged headers and signal.\n */\nfunction buildRequestConfig(\n config: RequestConfig,\n context: ContextProps | undefined,\n controller: AbortController,\n): RequestInit {\n const timeout = context?.timeout ?? REQUEST_TIMEOUT;\n const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(timeout)]);\n\n return {\n ...config,\n body: config.body ? JSON.stringify(config.body) : undefined,\n headers: mergeHeaders(context?.headers, config.headers),\n signal,\n };\n}\n\n/**\n * Merges context and config headers.\n */\nfunction mergeHeaders(\n contextHeaders?: Record<string, string | undefined>,\n configHeaders?: HeadersInit,\n): Record<string, string> {\n return {\n ...(contextHeaders ?? {}),\n ...(configHeaders ?? {}),\n } as Record<string, string>;\n}\n\n/**\n * Builds a URL with query parameters.\n */\nexport function buildUrl(baseUrl: string, params?: RequestParams): string {\n if (!params || Object.keys(params).length === 0) {\n return baseUrl;\n }\n\n const url = new URL(baseUrl);\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n url.searchParams.append(key, String(value));\n }\n }\n\n return url.toString();\n}\n\n/**\n * Creates a fetch service with pre-configured context.\n */\nexport function createFetchService(context: ContextProps = { url: '' }) {\n const createMethodHandler = (method: string) => {\n return <T>(url: string, config: RequestConfig = {}): Promise<RequestResponse<T>> => {\n return makeRequest<T>(url, { ...config, method }, context);\n };\n };\n\n return {\n delete: createMethodHandler('DELETE'),\n get: createMethodHandler('GET'),\n patch: createMethodHandler('PATCH'),\n post: createMethodHandler('POST'),\n put: createMethodHandler('PUT'),\n\n /**\n * Updates the service headers, removing any with undefined values.\n */\n setHeaders(payload: Record<string, string | undefined>): void {\n context.headers = { ...context.headers, ...payload };\n\n // Remove undefined headers\n for (const key in context.headers) {\n if (context.headers[key] === undefined) {\n delete context.headers[key];\n }\n }\n },\n };\n}\n"],"names":["REQUEST_TIMEOUT","CACHE_EXPIRES_IN","RequestErrorType","RequestStatus","HttpCache","getCacheKey","url","config","method","body","headers","log","type","req","res","startTime","elapsed","logType","shortUrl","formatUrlForLog","icon","Logit","fetcher","id","retries","response","data","parseResponse","updateCacheStatus","error","contentType","status","cached","makeRequest","context","key","shouldInvalidateCache","invalidateCacheEntry","isCacheValid","controller","fullUrl","buildFullUrl","requestConfig","buildRequestConfig","request","timeout","signal","mergeHeaders","contextHeaders","configHeaders","buildUrl","baseUrl","params","value","createFetchService","createMethodHandler","payload"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fetchit.cjs","sources":["../src/fetchit.ts"],"sourcesContent":["import { Logit } from '@vielzeug/logit';\n\ntype RequestParams = Record<string, string | number | undefined>;\n\nexport type RequestResponse<T> = {\n data: T;\n ok: boolean;\n status: number;\n};\n\ntype RequestConfig = Omit<RequestInit, 'body'> & {\n id?: string;\n cancelable?: boolean;\n invalidate?: boolean;\n body?: unknown;\n};\n\ntype ContextProps = {\n expiresIn?: number;\n headers?: Record<string, string | undefined>;\n params?: RequestParams;\n timeout?: number;\n url: string;\n};\n\n/**\n * Custom error class for HTTP request failures with additional context.\n */\nexport class HttpError extends Error {\n readonly url: string;\n readonly method: string;\n readonly status?: number;\n readonly originalError?: unknown;\n\n constructor(message: string, url: string, method: string, status?: number, originalError?: unknown) {\n super(message);\n this.name = 'HttpError';\n this.url = url;\n this.method = method;\n this.status = status;\n this.originalError = originalError;\n }\n}\n\nconst REQUEST_TIMEOUT = 5000;\nconst CACHE_EXPIRES_IN = 120000;\n\nexport const RequestErrorType = {\n ABORTED: 499,\n BAD_REQUEST: 400,\n CONFLICT: 409,\n FORBIDDEN: 403,\n NOT_ALLOWED: 405,\n NOT_FOUND: 404,\n PRE_CONDITION: 412,\n TIMEOUT: 408,\n UNAUTHORIZED: 401,\n} as const;\n\nexport const RequestStatus = {\n ERROR: 'ERROR',\n PENDING: 'PENDING',\n SUCCESS: 'SUCCESS',\n} as const;\n\ntype RequestStatusType = (typeof RequestStatus)[keyof typeof RequestStatus];\n\ntype RequestData<T> = {\n controller: AbortController;\n expiresIn: number;\n request: Promise<RequestResponse<T>>;\n status: RequestStatusType;\n};\n\nconst HttpCache = new Map<string, RequestData<unknown>>();\n\n/**\n * Generates a unique cache key for a request.\n * Uses custom id if provided, otherwise creates a key from url and config.\n */\nfunction getCacheKey(url: string, config: RequestConfig): string {\n if (config.id) return config.id;\n\n // Create a stable cache key from url and relevant config properties\n const { method = 'GET', body, headers } = config;\n return JSON.stringify({ body, headers, method, url });\n}\n\n/**\n * Logs HTTP request results with elapsed time and details.\n */\nfunction log(type: 'SUCCESS' | 'ERROR', url: string, req: RequestInit, res: unknown, startTime: number): void {\n const elapsed = Date.now() - startTime;\n const logType = type.toLowerCase() as 'success' | 'error';\n const method = req.method?.toUpperCase() ?? 'GET';\n const shortUrl = formatUrlForLog(url);\n const icon = type === 'SUCCESS' ? '✓' : '✕';\n\n Logit[logType](`HTTP::${method}(…/${shortUrl}) ${icon} ${elapsed}ms`, {\n req,\n res,\n url,\n });\n}\n\n/**\n * Formats URL for logging by removing protocol and domain.\n */\nfunction formatUrlForLog(url: string): string {\n return url.replace(/^https?:\\/\\/[^/]+\\//, '');\n}\n\n/**\n * Core fetch function with retry logic and proper error handling.\n */\nasync function fetcher<T>(\n url: string,\n config: RequestInit,\n { id, retries = 2 }: { id?: string; retries?: number },\n): Promise<RequestResponse<T>> {\n const startTime = Date.now();\n const method = config.method?.toUpperCase() ?? 'GET';\n\n try {\n const response = await fetch(url, config);\n const data = await parseResponse<T>(response);\n\n log('SUCCESS', url, config, data, startTime);\n updateCacheStatus(id, RequestStatus.SUCCESS);\n\n return { data, ok: response.ok, status: response.status };\n } catch (error) {\n log('ERROR', url, config, error, startTime);\n updateCacheStatus(id, RequestStatus.ERROR);\n\n // Retry on network errors\n if (retries > 0 && error instanceof TypeError) {\n return fetcher(url, config, { id, retries: retries - 1 });\n }\n\n // Wrap error with additional context\n throw new HttpError(error instanceof Error ? error.message : 'Request failed', url, method, undefined, error);\n } finally {\n // Clean up non-GET requests from cache\n if (id && config.method !== 'GET') {\n HttpCache.delete(id);\n }\n }\n}\n\n/**\n * Parses response based on content type.\n * Handles empty responses (204 No Content, etc.) and various content types.\n */\nasync function parseResponse<T>(response: Response): Promise<T> {\n // Handle empty responses (204 No Content, etc.)\n if (response.status === 204 || response.headers.get('content-length') === '0') {\n return undefined as T;\n }\n\n const contentType = response.headers.get('content-type') ?? '';\n\n if (contentType.includes('application/json')) {\n return response.json();\n }\n\n if (contentType.includes('text')) {\n return response.text() as Promise<T>;\n }\n\n // Default to blob for binary data, form data, etc.\n return response.blob() as Promise<T>;\n}\n\n/**\n * Updates cache entry status if it exists.\n */\nfunction updateCacheStatus(id: string | undefined, status: RequestStatusType): void {\n const cached = id ? HttpCache.get(id) : undefined;\n if (cached) cached.status = status;\n}\n\n/**\n * Makes an HTTP request with caching and cancellation support.\n */\nasync function makeRequest<T>(url: string, config: RequestConfig, context?: ContextProps): Promise<RequestResponse<T>> {\n const key = getCacheKey(url, config);\n let cached = HttpCache.get(key) as RequestData<T> | undefined;\n\n // Invalidate cache if needed\n if (cached && shouldInvalidateCache(config, cached)) {\n cached.controller.abort('Request aborted');\n HttpCache.delete(key);\n cached = undefined;\n }\n\n // Return cached response if valid\n if (cached && isCacheValid(cached)) {\n return cached.request;\n }\n\n // Create and execute new request\n const controller = new AbortController();\n const fullUrl = buildFullUrl(url, context);\n const requestConfig = buildRequestConfig(config, context, controller);\n const request = fetcher<T>(fullUrl, requestConfig, { id: key });\n\n HttpCache.set(key, {\n controller,\n expiresIn: Date.now() + (context?.expiresIn ?? CACHE_EXPIRES_IN),\n request,\n status: RequestStatus.PENDING,\n });\n\n return request;\n}\n\n/**\n * Checks if a cache should be invalidated.\n */\nfunction shouldInvalidateCache<T>(config: RequestConfig, cached: RequestData<T> | undefined): boolean {\n if (config.invalidate) return true;\n if (!cached) return false;\n\n return (config.cancelable && cached.status === RequestStatus.PENDING) || cached.status === RequestStatus.ERROR;\n}\n\n/**\n * Checks if a cache entry is still valid.\n */\nfunction isCacheValid<T>(cached: RequestData<T>): boolean {\n return Date.now() <= cached.expiresIn;\n}\n\n/**\n * Builds the full URL with a context path.\n * Handles trailing/leading slashes to avoid double slashes.\n */\nfunction buildFullUrl(url: string, context?: ContextProps): string {\n if (!context?.url) return url;\n\n const baseUrl = context.url.replace(/\\/+$/, ''); // Remove trailing slashes\n const path = url.replace(/^\\/+/, ''); // Remove leading slashes\n return `${baseUrl}/${path}`;\n}\n\n/**\n * Checks if a value is a native BodyInit type that shouldn't be serialized.\n */\nfunction isBodyInit(value: unknown): value is BodyInit {\n return (\n value instanceof FormData ||\n value instanceof Blob ||\n value instanceof ArrayBuffer ||\n value instanceof URLSearchParams ||\n typeof value === 'string'\n );\n}\n\n/**\n * Builds the request configuration with merged headers and signal.\n * Automatically handles JSON serialization and sets appropriate Content-Type.\n */\nfunction buildRequestConfig(\n config: RequestConfig,\n context: ContextProps | undefined,\n controller: AbortController,\n): RequestInit {\n const timeout = context?.timeout ?? REQUEST_TIMEOUT;\n const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(timeout)]);\n\n let body: BodyInit | undefined;\n const additionalHeaders: Record<string, string> = {};\n\n if (config.body !== undefined) {\n if (isBodyInit(config.body)) {\n body = config.body;\n } else {\n // For plain objects, serialize as JSON\n body = JSON.stringify(config.body);\n additionalHeaders['Content-Type'] = 'application/json';\n }\n }\n\n return {\n ...config,\n body,\n headers: mergeHeaders(context?.headers, config.headers, additionalHeaders),\n signal,\n };\n}\n\n/**\n * Converts HeadersInit to a plain object.\n */\nfunction headersToObject(headers: HeadersInit): Record<string, string> {\n const result: Record<string, string> = {};\n\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n result[key] = value;\n });\n } else if (Array.isArray(headers)) {\n for (const [key, value] of headers) {\n result[key] = value;\n }\n } else {\n for (const [key, value] of Object.entries(headers)) {\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Merges context, config, and additional headers.\n * Properly handles HeadersInit types (Headers object, array, or plain object).\n */\nfunction mergeHeaders(\n contextHeaders?: Record<string, string | undefined>,\n configHeaders?: HeadersInit,\n additionalHeaders?: Record<string, string>,\n): Record<string, string> {\n const result: Record<string, string> = {};\n\n // Add context headers (filter out undefined)\n if (contextHeaders) {\n for (const [key, value] of Object.entries(contextHeaders)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n }\n\n // Add config headers\n if (configHeaders) {\n Object.assign(result, headersToObject(configHeaders));\n }\n\n // Add additional headers (like auto-generated Content-Type)\n if (additionalHeaders) {\n Object.assign(result, additionalHeaders);\n }\n\n return result;\n}\n\n/**\n * Builds a URL with query parameters.\n */\nexport function buildUrl(baseUrl: string, params?: RequestParams): string {\n if (!params || Object.keys(params).length === 0) {\n return baseUrl;\n }\n\n const url = new URL(baseUrl);\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n url.searchParams.append(key, String(value));\n }\n }\n\n return url.toString();\n}\n\n/**\n * Creates a fetch service with pre-configured context.\n */\nexport function createHttpClient(context: ContextProps = { url: '' }) {\n const createMethodHandler = (method: string) => {\n return <T>(url: string, config: RequestConfig = {}): Promise<RequestResponse<T>> => {\n return makeRequest<T>(url, { ...config, method }, context);\n };\n };\n\n return {\n /**\n * Cleans up expired cache entries.\n * Returns the number of entries removed.\n */\n cleanupCache(): number {\n const now = Date.now();\n const expiredKeys = Array.from(HttpCache.entries())\n .filter(([, value]) => now > value.expiresIn)\n .map(([key]) => key);\n\n for (const key of expiredKeys) {\n HttpCache.delete(key);\n }\n\n return expiredKeys.length;\n },\n\n /**\n * Clears all cached requests.\n */\n clearCache(): void {\n HttpCache.clear();\n },\n delete: createMethodHandler('DELETE'),\n get: createMethodHandler('GET'),\n\n /**\n * Returns the number of cached requests.\n */\n getCacheSize(): number {\n return HttpCache.size;\n },\n\n /**\n * Invalidates a specific cache entry by id or URL.\n */\n invalidateCache(idOrUrl: string): boolean {\n return HttpCache.delete(idOrUrl);\n },\n patch: createMethodHandler('PATCH'),\n post: createMethodHandler('POST'),\n put: createMethodHandler('PUT'),\n\n /**\n * Updates the service headers.\n * Headers with undefined values will be removed.\n */\n setHeaders(payload: Record<string, string | undefined>): void {\n context.headers = Object.fromEntries(\n Object.entries({ ...context.headers, ...payload }).filter(([, value]) => value !== undefined),\n );\n },\n };\n}\n"],"names":["HttpError","message","url","method","status","originalError","REQUEST_TIMEOUT","CACHE_EXPIRES_IN","RequestErrorType","RequestStatus","HttpCache","getCacheKey","config","body","headers","log","type","req","res","startTime","elapsed","logType","shortUrl","formatUrlForLog","icon","Logit","fetcher","id","retries","response","data","parseResponse","updateCacheStatus","error","contentType","cached","makeRequest","context","key","shouldInvalidateCache","isCacheValid","controller","fullUrl","buildFullUrl","requestConfig","buildRequestConfig","request","baseUrl","path","isBodyInit","value","timeout","signal","additionalHeaders","mergeHeaders","headersToObject","result","contextHeaders","configHeaders","buildUrl","params","createHttpClient","createMethodHandler","now","expiredKeys","idOrUrl","payload"],"mappings":"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"}
|
package/dist/fetchit.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import { Logit as
|
|
2
|
-
|
|
1
|
+
import { Logit as p } from "./logit/dist/logit.js";
|
|
2
|
+
class y extends Error {
|
|
3
|
+
url;
|
|
4
|
+
method;
|
|
5
|
+
status;
|
|
6
|
+
originalError;
|
|
7
|
+
constructor(e, r, n, o, a) {
|
|
8
|
+
super(e), this.name = "HttpError", this.url = r, this.method = n, this.status = o, this.originalError = a;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const C = 5e3, R = 12e4, j = {
|
|
3
12
|
ABORTED: 499,
|
|
4
13
|
BAD_REQUEST: 400,
|
|
5
14
|
CONFLICT: 409,
|
|
@@ -14,115 +23,164 @@ const S = 5e3, C = 12e4, P = {
|
|
|
14
23
|
PENDING: "PENDING",
|
|
15
24
|
SUCCESS: "SUCCESS"
|
|
16
25
|
}, i = /* @__PURE__ */ new Map();
|
|
17
|
-
function T(
|
|
18
|
-
if (
|
|
19
|
-
const { method: r = "GET", body: n, headers:
|
|
20
|
-
return JSON.stringify({ body: n, headers:
|
|
21
|
-
}
|
|
22
|
-
function
|
|
23
|
-
const
|
|
24
|
-
|
|
26
|
+
function T(t, e) {
|
|
27
|
+
if (e.id) return e.id;
|
|
28
|
+
const { method: r = "GET", body: n, headers: o } = e;
|
|
29
|
+
return JSON.stringify({ body: n, headers: o, method: r, url: t });
|
|
30
|
+
}
|
|
31
|
+
function f(t, e, r, n, o) {
|
|
32
|
+
const a = Date.now() - o, s = t.toLowerCase(), c = r.method?.toUpperCase() ?? "GET", l = O(e), h = t === "SUCCESS" ? "✓" : "✕";
|
|
33
|
+
p[s](`HTTP::${c}(…/${l}) ${h} ${a}ms`, {
|
|
25
34
|
req: r,
|
|
26
35
|
res: n,
|
|
27
|
-
url:
|
|
36
|
+
url: e
|
|
28
37
|
});
|
|
29
38
|
}
|
|
30
|
-
function
|
|
31
|
-
return
|
|
39
|
+
function O(t) {
|
|
40
|
+
return t.replace(/^https?:\/\/[^/]+\//, "");
|
|
32
41
|
}
|
|
33
|
-
async function
|
|
34
|
-
const
|
|
42
|
+
async function E(t, e, { id: r, retries: n = 2 }) {
|
|
43
|
+
const o = Date.now(), a = e.method?.toUpperCase() ?? "GET";
|
|
35
44
|
try {
|
|
36
|
-
const
|
|
37
|
-
return
|
|
38
|
-
} catch (
|
|
39
|
-
if (
|
|
40
|
-
return
|
|
41
|
-
throw
|
|
45
|
+
const s = await fetch(t, e), c = await S(s);
|
|
46
|
+
return f("SUCCESS", t, e, c, o), d(r, u.SUCCESS), { data: c, ok: s.ok, status: s.status };
|
|
47
|
+
} catch (s) {
|
|
48
|
+
if (f("ERROR", t, e, s, o), d(r, u.ERROR), n > 0 && s instanceof TypeError)
|
|
49
|
+
return E(t, e, { id: r, retries: n - 1 });
|
|
50
|
+
throw new y(s instanceof Error ? s.message : "Request failed", t, a, void 0, s);
|
|
42
51
|
} finally {
|
|
43
|
-
r &&
|
|
52
|
+
r && e.method !== "GET" && i.delete(r);
|
|
44
53
|
}
|
|
45
54
|
}
|
|
46
|
-
async function
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
async function S(t) {
|
|
56
|
+
if (t.status === 204 || t.headers.get("content-length") === "0")
|
|
57
|
+
return;
|
|
58
|
+
const e = t.headers.get("content-type") ?? "";
|
|
59
|
+
return e.includes("application/json") ? t.json() : e.includes("text") ? t.text() : t.blob();
|
|
49
60
|
}
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
r && (r.status = t);
|
|
54
|
-
}
|
|
61
|
+
function d(t, e) {
|
|
62
|
+
const r = t ? i.get(t) : void 0;
|
|
63
|
+
r && (r.status = e);
|
|
55
64
|
}
|
|
56
|
-
async function
|
|
57
|
-
const n = T(
|
|
58
|
-
let
|
|
59
|
-
if (
|
|
60
|
-
return
|
|
61
|
-
const
|
|
65
|
+
async function b(t, e, r) {
|
|
66
|
+
const n = T(t, e);
|
|
67
|
+
let o = i.get(n);
|
|
68
|
+
if (o && m(e, o) && (o.controller.abort("Request aborted"), i.delete(n), o = void 0), o && U(o))
|
|
69
|
+
return o.request;
|
|
70
|
+
const a = new AbortController(), s = D(t, r), c = N(e, r, a), l = E(s, c, { id: n });
|
|
62
71
|
return i.set(n, {
|
|
63
|
-
controller:
|
|
64
|
-
expiresIn: Date.now() + (r?.expiresIn ??
|
|
65
|
-
request:
|
|
72
|
+
controller: a,
|
|
73
|
+
expiresIn: Date.now() + (r?.expiresIn ?? R),
|
|
74
|
+
request: l,
|
|
66
75
|
status: u.PENDING
|
|
67
|
-
}),
|
|
76
|
+
}), l;
|
|
68
77
|
}
|
|
69
|
-
function
|
|
70
|
-
return
|
|
78
|
+
function m(t, e) {
|
|
79
|
+
return t.invalidate ? !0 : e ? t.cancelable && e.status === u.PENDING || e.status === u.ERROR : !1;
|
|
71
80
|
}
|
|
72
|
-
function U(
|
|
73
|
-
|
|
81
|
+
function U(t) {
|
|
82
|
+
return Date.now() <= t.expiresIn;
|
|
74
83
|
}
|
|
75
|
-
function D(e) {
|
|
76
|
-
|
|
84
|
+
function D(t, e) {
|
|
85
|
+
if (!e?.url) return t;
|
|
86
|
+
const r = e.url.replace(/\/+$/, ""), n = t.replace(/^\/+/, "");
|
|
87
|
+
return `${r}/${n}`;
|
|
77
88
|
}
|
|
78
|
-
function I(
|
|
79
|
-
return t
|
|
89
|
+
function I(t) {
|
|
90
|
+
return t instanceof FormData || t instanceof Blob || t instanceof ArrayBuffer || t instanceof URLSearchParams || typeof t == "string";
|
|
80
91
|
}
|
|
81
|
-
function
|
|
82
|
-
const n =
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
function N(t, e, r) {
|
|
93
|
+
const n = e?.timeout ?? C, o = AbortSignal.any([r.signal, AbortSignal.timeout(n)]);
|
|
94
|
+
let a;
|
|
95
|
+
const s = {};
|
|
96
|
+
return t.body !== void 0 && (I(t.body) ? a = t.body : (a = JSON.stringify(t.body), s["Content-Type"] = "application/json")), {
|
|
97
|
+
...t,
|
|
98
|
+
body: a,
|
|
99
|
+
headers: w(e?.headers, t.headers, s),
|
|
100
|
+
signal: o
|
|
88
101
|
};
|
|
89
102
|
}
|
|
90
|
-
function
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
103
|
+
function g(t) {
|
|
104
|
+
const e = {};
|
|
105
|
+
if (t instanceof Headers)
|
|
106
|
+
t.forEach((r, n) => {
|
|
107
|
+
e[n] = r;
|
|
108
|
+
});
|
|
109
|
+
else if (Array.isArray(t))
|
|
110
|
+
for (const [r, n] of t)
|
|
111
|
+
e[r] = n;
|
|
112
|
+
else
|
|
113
|
+
for (const [r, n] of Object.entries(t))
|
|
114
|
+
e[r] = n;
|
|
115
|
+
return e;
|
|
116
|
+
}
|
|
117
|
+
function w(t, e, r) {
|
|
118
|
+
const n = {};
|
|
119
|
+
if (t)
|
|
120
|
+
for (const [o, a] of Object.entries(t))
|
|
121
|
+
a !== void 0 && (n[o] = a);
|
|
122
|
+
return e && Object.assign(n, g(e)), r && Object.assign(n, r), n;
|
|
95
123
|
}
|
|
96
|
-
function
|
|
97
|
-
if (!
|
|
98
|
-
return
|
|
99
|
-
const r = new URL(
|
|
100
|
-
for (const [n,
|
|
101
|
-
|
|
124
|
+
function P(t, e) {
|
|
125
|
+
if (!e || Object.keys(e).length === 0)
|
|
126
|
+
return t;
|
|
127
|
+
const r = new URL(t);
|
|
128
|
+
for (const [n, o] of Object.entries(e))
|
|
129
|
+
o !== void 0 && r.searchParams.append(n, String(o));
|
|
102
130
|
return r.toString();
|
|
103
131
|
}
|
|
104
|
-
function v(
|
|
105
|
-
const
|
|
132
|
+
function v(t = { url: "" }) {
|
|
133
|
+
const e = (r) => (n, o = {}) => b(n, { ...o, method: r }, t);
|
|
106
134
|
return {
|
|
107
|
-
delete: t("DELETE"),
|
|
108
|
-
get: t("GET"),
|
|
109
|
-
patch: t("PATCH"),
|
|
110
|
-
post: t("POST"),
|
|
111
|
-
put: t("PUT"),
|
|
112
135
|
/**
|
|
113
|
-
*
|
|
136
|
+
* Cleans up expired cache entries.
|
|
137
|
+
* Returns the number of entries removed.
|
|
138
|
+
*/
|
|
139
|
+
cleanupCache() {
|
|
140
|
+
const r = Date.now(), n = Array.from(i.entries()).filter(([, o]) => r > o.expiresIn).map(([o]) => o);
|
|
141
|
+
for (const o of n)
|
|
142
|
+
i.delete(o);
|
|
143
|
+
return n.length;
|
|
144
|
+
},
|
|
145
|
+
/**
|
|
146
|
+
* Clears all cached requests.
|
|
147
|
+
*/
|
|
148
|
+
clearCache() {
|
|
149
|
+
i.clear();
|
|
150
|
+
},
|
|
151
|
+
delete: e("DELETE"),
|
|
152
|
+
get: e("GET"),
|
|
153
|
+
/**
|
|
154
|
+
* Returns the number of cached requests.
|
|
155
|
+
*/
|
|
156
|
+
getCacheSize() {
|
|
157
|
+
return i.size;
|
|
158
|
+
},
|
|
159
|
+
/**
|
|
160
|
+
* Invalidates a specific cache entry by id or URL.
|
|
161
|
+
*/
|
|
162
|
+
invalidateCache(r) {
|
|
163
|
+
return i.delete(r);
|
|
164
|
+
},
|
|
165
|
+
patch: e("PATCH"),
|
|
166
|
+
post: e("POST"),
|
|
167
|
+
put: e("PUT"),
|
|
168
|
+
/**
|
|
169
|
+
* Updates the service headers.
|
|
170
|
+
* Headers with undefined values will be removed.
|
|
114
171
|
*/
|
|
115
172
|
setHeaders(r) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
173
|
+
t.headers = Object.fromEntries(
|
|
174
|
+
Object.entries({ ...t.headers, ...r }).filter(([, n]) => n !== void 0)
|
|
175
|
+
);
|
|
119
176
|
}
|
|
120
177
|
};
|
|
121
178
|
}
|
|
122
179
|
export {
|
|
123
|
-
|
|
180
|
+
y as HttpError,
|
|
181
|
+
j as RequestErrorType,
|
|
124
182
|
u as RequestStatus,
|
|
125
|
-
|
|
126
|
-
v as
|
|
183
|
+
P as buildUrl,
|
|
184
|
+
v as createHttpClient
|
|
127
185
|
};
|
|
128
186
|
//# sourceMappingURL=fetchit.js.map
|
package/dist/fetchit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchit.js","sources":["../src/fetchit.ts"],"sourcesContent":["import { Logit } from '@vielzeug/logit';\n\ntype RequestParams = Record<string, string | number | undefined>;\n\nexport type RequestResponse<T> = {\n data: T;\n ok: boolean;\n status: number;\n};\n\ntype RequestConfig = Omit<RequestInit, 'body'> & {\n id?: string;\n cancelable?: boolean;\n invalidate?: boolean;\n body?: unknown;\n};\n\ntype ContextProps = {\n expiresIn?: number;\n headers?: Record<string, string | undefined>;\n params?: RequestParams;\n timeout?: number;\n url: string;\n};\n\nconst REQUEST_TIMEOUT = 5000;\nconst CACHE_EXPIRES_IN = 120000;\n\nexport const RequestErrorType = {\n ABORTED: 499,\n BAD_REQUEST: 400,\n CONFLICT: 409,\n FORBIDDEN: 403,\n NOT_ALLOWED: 405,\n NOT_FOUND: 404,\n PRE_CONDITION: 412,\n TIMEOUT: 408,\n UNAUTHORIZED: 401,\n} as const;\n\nexport const RequestStatus = {\n ERROR: 'ERROR',\n PENDING: 'PENDING',\n SUCCESS: 'SUCCESS',\n} as const;\n\ntype RequestData<T> = {\n controller: AbortController;\n expiresIn: number;\n request: Promise<RequestResponse<T>>;\n status: (typeof RequestStatus)[keyof typeof RequestStatus];\n};\n\nconst HttpCache = new Map<string, RequestData<unknown>>();\n\n/**\n * Generates a unique cache key for a request.\n * Uses custom id if provided, otherwise creates a key from url and config.\n */\nfunction getCacheKey(url: string, config: RequestConfig): string {\n if (config.id) return config.id;\n\n // Create a stable cache key from url and relevant config properties\n const { method = 'GET', body, headers } = config;\n return JSON.stringify({ body, headers, method, url });\n}\n\n/**\n * Logs HTTP request results with elapsed time and details.\n */\nfunction log(type: 'SUCCESS' | 'ERROR', url: string, req: RequestInit, res: unknown, startTime: number): void {\n const elapsed = Date.now() - startTime;\n const logType = type.toLowerCase() as 'success' | 'error';\n const method = req.method?.toUpperCase() ?? 'GET';\n const shortUrl = formatUrlForLog(url);\n const icon = type === 'SUCCESS' ? '✓' : '✕';\n\n Logit[logType](`HTTP::${method}(…/${shortUrl}) ${icon} ${elapsed}ms`, {\n req,\n res,\n url,\n });\n}\n\n/**\n * Formats URL for logging by removing protocol and domain.\n */\nfunction formatUrlForLog(url: string): string {\n return url\n .replace(/^https?:\\/\\//, '')\n .split('/')\n .slice(1)\n .join('/');\n}\n\n/**\n * Core fetch function with retry logic and proper error handling.\n */\nasync function fetcher<T>(\n url: string,\n config: RequestInit,\n { id, retries = 2 }: { id?: string; retries?: number },\n): Promise<RequestResponse<T>> {\n const startTime = Date.now();\n\n try {\n const response = await fetch(url, config);\n const data = await parseResponse<T>(response);\n\n log('SUCCESS', url, config, data, startTime);\n updateCacheStatus(id, RequestStatus.SUCCESS);\n\n return { data, ok: response.ok, status: response.status };\n } catch (error) {\n log('ERROR', url, config, error, startTime);\n updateCacheStatus(id, RequestStatus.ERROR);\n\n // Retry on network errors\n if (retries > 0 && error instanceof TypeError) {\n return fetcher(url, config, { id, retries: retries - 1 });\n }\n\n throw error;\n } finally {\n // Clean up non-GET requests from cache\n if (id && config.method !== 'GET') {\n HttpCache.delete(id);\n }\n }\n}\n\n/**\n * Parses response based on content type.\n */\nasync function parseResponse<T>(response: Response): Promise<T> {\n const contentType = response.headers.get('content-type') ?? '';\n\n if (contentType.includes('application/json')) {\n return response.json();\n }\n\n if (contentType.includes('text')) {\n return response.text() as Promise<T>;\n }\n\n return response.blob() as Promise<T>;\n}\n\n/**\n * Updates cache entry status if it exists.\n */\nfunction updateCacheStatus(id: string | undefined, status: (typeof RequestStatus)[keyof typeof RequestStatus]): void {\n if (id) {\n const cached = HttpCache.get(id);\n if (cached) {\n cached.status = status;\n }\n }\n}\n\n/**\n * Makes an HTTP request with caching and cancellation support.\n */\nasync function makeRequest<T>(url: string, config: RequestConfig, context?: ContextProps): Promise<RequestResponse<T>> {\n const key = getCacheKey(url, config);\n let cached = HttpCache.get(key) as RequestData<T> | undefined;\n\n // Handle cache invalidation\n if (shouldInvalidateCache(config, cached)) {\n invalidateCacheEntry(key, cached);\n cached = undefined;\n }\n\n // Return cached response if valid\n if (cached && isCacheValid(cached)) {\n return cached.request;\n }\n\n // Create and execute new request\n const controller = new AbortController();\n const fullUrl = buildFullUrl(url, context);\n const requestConfig = buildRequestConfig(config, context, controller);\n const request = fetcher<T>(fullUrl, requestConfig, { id: key });\n\n // Store in cache\n HttpCache.set(key, {\n controller,\n expiresIn: Date.now() + (context?.expiresIn ?? CACHE_EXPIRES_IN),\n request,\n status: RequestStatus.PENDING,\n });\n\n return request;\n}\n\n/**\n * Checks if a cache should be invalidated.\n */\nfunction shouldInvalidateCache<T>(config: RequestConfig, cached: RequestData<T> | undefined): boolean {\n if (config.invalidate) return true;\n if (!cached) return false;\n\n if (config.cancelable && cached.status === RequestStatus.PENDING) return true;\n\n return cached.status === RequestStatus.ERROR;\n}\n\n/**\n * Invalidates a cache entry by aborting and deleting it.\n */\nfunction invalidateCacheEntry<T>(key: string, cached: RequestData<T> | undefined): void {\n if (cached) {\n cached.controller.abort('Request aborted');\n HttpCache.delete(key);\n }\n}\n\n/**\n * Checks if a cache entry is still valid.\n */\nfunction isCacheValid<T>(cached: RequestData<T>): boolean {\n return Date.now() <= cached.expiresIn;\n}\n\n/**\n * Builds the full URL with a context path.\n */\nfunction buildFullUrl(url: string, context?: ContextProps): string {\n return context?.url ? `${context.url}/${url}` : url;\n}\n\n/**\n * Builds the request configuration with merged headers and signal.\n */\nfunction buildRequestConfig(\n config: RequestConfig,\n context: ContextProps | undefined,\n controller: AbortController,\n): RequestInit {\n const timeout = context?.timeout ?? REQUEST_TIMEOUT;\n const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(timeout)]);\n\n return {\n ...config,\n body: config.body ? JSON.stringify(config.body) : undefined,\n headers: mergeHeaders(context?.headers, config.headers),\n signal,\n };\n}\n\n/**\n * Merges context and config headers.\n */\nfunction mergeHeaders(\n contextHeaders?: Record<string, string | undefined>,\n configHeaders?: HeadersInit,\n): Record<string, string> {\n return {\n ...(contextHeaders ?? {}),\n ...(configHeaders ?? {}),\n } as Record<string, string>;\n}\n\n/**\n * Builds a URL with query parameters.\n */\nexport function buildUrl(baseUrl: string, params?: RequestParams): string {\n if (!params || Object.keys(params).length === 0) {\n return baseUrl;\n }\n\n const url = new URL(baseUrl);\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n url.searchParams.append(key, String(value));\n }\n }\n\n return url.toString();\n}\n\n/**\n * Creates a fetch service with pre-configured context.\n */\nexport function createFetchService(context: ContextProps = { url: '' }) {\n const createMethodHandler = (method: string) => {\n return <T>(url: string, config: RequestConfig = {}): Promise<RequestResponse<T>> => {\n return makeRequest<T>(url, { ...config, method }, context);\n };\n };\n\n return {\n delete: createMethodHandler('DELETE'),\n get: createMethodHandler('GET'),\n patch: createMethodHandler('PATCH'),\n post: createMethodHandler('POST'),\n put: createMethodHandler('PUT'),\n\n /**\n * Updates the service headers, removing any with undefined values.\n */\n setHeaders(payload: Record<string, string | undefined>): void {\n context.headers = { ...context.headers, ...payload };\n\n // Remove undefined headers\n for (const key in context.headers) {\n if (context.headers[key] === undefined) {\n delete context.headers[key];\n }\n }\n },\n };\n}\n"],"names":["REQUEST_TIMEOUT","CACHE_EXPIRES_IN","RequestErrorType","RequestStatus","HttpCache","getCacheKey","url","config","method","body","headers","log","type","req","res","startTime","elapsed","logType","shortUrl","formatUrlForLog","icon","Logit","fetcher","id","retries","response","data","parseResponse","updateCacheStatus","error","contentType","status","cached","makeRequest","context","key","shouldInvalidateCache","invalidateCacheEntry","isCacheValid","controller","fullUrl","buildFullUrl","requestConfig","buildRequestConfig","request","timeout","signal","mergeHeaders","contextHeaders","configHeaders","buildUrl","baseUrl","params","value","createFetchService","createMethodHandler","payload"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fetchit.js","sources":["../src/fetchit.ts"],"sourcesContent":["import { Logit } from '@vielzeug/logit';\n\ntype RequestParams = Record<string, string | number | undefined>;\n\nexport type RequestResponse<T> = {\n data: T;\n ok: boolean;\n status: number;\n};\n\ntype RequestConfig = Omit<RequestInit, 'body'> & {\n id?: string;\n cancelable?: boolean;\n invalidate?: boolean;\n body?: unknown;\n};\n\ntype ContextProps = {\n expiresIn?: number;\n headers?: Record<string, string | undefined>;\n params?: RequestParams;\n timeout?: number;\n url: string;\n};\n\n/**\n * Custom error class for HTTP request failures with additional context.\n */\nexport class HttpError extends Error {\n readonly url: string;\n readonly method: string;\n readonly status?: number;\n readonly originalError?: unknown;\n\n constructor(message: string, url: string, method: string, status?: number, originalError?: unknown) {\n super(message);\n this.name = 'HttpError';\n this.url = url;\n this.method = method;\n this.status = status;\n this.originalError = originalError;\n }\n}\n\nconst REQUEST_TIMEOUT = 5000;\nconst CACHE_EXPIRES_IN = 120000;\n\nexport const RequestErrorType = {\n ABORTED: 499,\n BAD_REQUEST: 400,\n CONFLICT: 409,\n FORBIDDEN: 403,\n NOT_ALLOWED: 405,\n NOT_FOUND: 404,\n PRE_CONDITION: 412,\n TIMEOUT: 408,\n UNAUTHORIZED: 401,\n} as const;\n\nexport const RequestStatus = {\n ERROR: 'ERROR',\n PENDING: 'PENDING',\n SUCCESS: 'SUCCESS',\n} as const;\n\ntype RequestStatusType = (typeof RequestStatus)[keyof typeof RequestStatus];\n\ntype RequestData<T> = {\n controller: AbortController;\n expiresIn: number;\n request: Promise<RequestResponse<T>>;\n status: RequestStatusType;\n};\n\nconst HttpCache = new Map<string, RequestData<unknown>>();\n\n/**\n * Generates a unique cache key for a request.\n * Uses custom id if provided, otherwise creates a key from url and config.\n */\nfunction getCacheKey(url: string, config: RequestConfig): string {\n if (config.id) return config.id;\n\n // Create a stable cache key from url and relevant config properties\n const { method = 'GET', body, headers } = config;\n return JSON.stringify({ body, headers, method, url });\n}\n\n/**\n * Logs HTTP request results with elapsed time and details.\n */\nfunction log(type: 'SUCCESS' | 'ERROR', url: string, req: RequestInit, res: unknown, startTime: number): void {\n const elapsed = Date.now() - startTime;\n const logType = type.toLowerCase() as 'success' | 'error';\n const method = req.method?.toUpperCase() ?? 'GET';\n const shortUrl = formatUrlForLog(url);\n const icon = type === 'SUCCESS' ? '✓' : '✕';\n\n Logit[logType](`HTTP::${method}(…/${shortUrl}) ${icon} ${elapsed}ms`, {\n req,\n res,\n url,\n });\n}\n\n/**\n * Formats URL for logging by removing protocol and domain.\n */\nfunction formatUrlForLog(url: string): string {\n return url.replace(/^https?:\\/\\/[^/]+\\//, '');\n}\n\n/**\n * Core fetch function with retry logic and proper error handling.\n */\nasync function fetcher<T>(\n url: string,\n config: RequestInit,\n { id, retries = 2 }: { id?: string; retries?: number },\n): Promise<RequestResponse<T>> {\n const startTime = Date.now();\n const method = config.method?.toUpperCase() ?? 'GET';\n\n try {\n const response = await fetch(url, config);\n const data = await parseResponse<T>(response);\n\n log('SUCCESS', url, config, data, startTime);\n updateCacheStatus(id, RequestStatus.SUCCESS);\n\n return { data, ok: response.ok, status: response.status };\n } catch (error) {\n log('ERROR', url, config, error, startTime);\n updateCacheStatus(id, RequestStatus.ERROR);\n\n // Retry on network errors\n if (retries > 0 && error instanceof TypeError) {\n return fetcher(url, config, { id, retries: retries - 1 });\n }\n\n // Wrap error with additional context\n throw new HttpError(error instanceof Error ? error.message : 'Request failed', url, method, undefined, error);\n } finally {\n // Clean up non-GET requests from cache\n if (id && config.method !== 'GET') {\n HttpCache.delete(id);\n }\n }\n}\n\n/**\n * Parses response based on content type.\n * Handles empty responses (204 No Content, etc.) and various content types.\n */\nasync function parseResponse<T>(response: Response): Promise<T> {\n // Handle empty responses (204 No Content, etc.)\n if (response.status === 204 || response.headers.get('content-length') === '0') {\n return undefined as T;\n }\n\n const contentType = response.headers.get('content-type') ?? '';\n\n if (contentType.includes('application/json')) {\n return response.json();\n }\n\n if (contentType.includes('text')) {\n return response.text() as Promise<T>;\n }\n\n // Default to blob for binary data, form data, etc.\n return response.blob() as Promise<T>;\n}\n\n/**\n * Updates cache entry status if it exists.\n */\nfunction updateCacheStatus(id: string | undefined, status: RequestStatusType): void {\n const cached = id ? HttpCache.get(id) : undefined;\n if (cached) cached.status = status;\n}\n\n/**\n * Makes an HTTP request with caching and cancellation support.\n */\nasync function makeRequest<T>(url: string, config: RequestConfig, context?: ContextProps): Promise<RequestResponse<T>> {\n const key = getCacheKey(url, config);\n let cached = HttpCache.get(key) as RequestData<T> | undefined;\n\n // Invalidate cache if needed\n if (cached && shouldInvalidateCache(config, cached)) {\n cached.controller.abort('Request aborted');\n HttpCache.delete(key);\n cached = undefined;\n }\n\n // Return cached response if valid\n if (cached && isCacheValid(cached)) {\n return cached.request;\n }\n\n // Create and execute new request\n const controller = new AbortController();\n const fullUrl = buildFullUrl(url, context);\n const requestConfig = buildRequestConfig(config, context, controller);\n const request = fetcher<T>(fullUrl, requestConfig, { id: key });\n\n HttpCache.set(key, {\n controller,\n expiresIn: Date.now() + (context?.expiresIn ?? CACHE_EXPIRES_IN),\n request,\n status: RequestStatus.PENDING,\n });\n\n return request;\n}\n\n/**\n * Checks if a cache should be invalidated.\n */\nfunction shouldInvalidateCache<T>(config: RequestConfig, cached: RequestData<T> | undefined): boolean {\n if (config.invalidate) return true;\n if (!cached) return false;\n\n return (config.cancelable && cached.status === RequestStatus.PENDING) || cached.status === RequestStatus.ERROR;\n}\n\n/**\n * Checks if a cache entry is still valid.\n */\nfunction isCacheValid<T>(cached: RequestData<T>): boolean {\n return Date.now() <= cached.expiresIn;\n}\n\n/**\n * Builds the full URL with a context path.\n * Handles trailing/leading slashes to avoid double slashes.\n */\nfunction buildFullUrl(url: string, context?: ContextProps): string {\n if (!context?.url) return url;\n\n const baseUrl = context.url.replace(/\\/+$/, ''); // Remove trailing slashes\n const path = url.replace(/^\\/+/, ''); // Remove leading slashes\n return `${baseUrl}/${path}`;\n}\n\n/**\n * Checks if a value is a native BodyInit type that shouldn't be serialized.\n */\nfunction isBodyInit(value: unknown): value is BodyInit {\n return (\n value instanceof FormData ||\n value instanceof Blob ||\n value instanceof ArrayBuffer ||\n value instanceof URLSearchParams ||\n typeof value === 'string'\n );\n}\n\n/**\n * Builds the request configuration with merged headers and signal.\n * Automatically handles JSON serialization and sets appropriate Content-Type.\n */\nfunction buildRequestConfig(\n config: RequestConfig,\n context: ContextProps | undefined,\n controller: AbortController,\n): RequestInit {\n const timeout = context?.timeout ?? REQUEST_TIMEOUT;\n const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(timeout)]);\n\n let body: BodyInit | undefined;\n const additionalHeaders: Record<string, string> = {};\n\n if (config.body !== undefined) {\n if (isBodyInit(config.body)) {\n body = config.body;\n } else {\n // For plain objects, serialize as JSON\n body = JSON.stringify(config.body);\n additionalHeaders['Content-Type'] = 'application/json';\n }\n }\n\n return {\n ...config,\n body,\n headers: mergeHeaders(context?.headers, config.headers, additionalHeaders),\n signal,\n };\n}\n\n/**\n * Converts HeadersInit to a plain object.\n */\nfunction headersToObject(headers: HeadersInit): Record<string, string> {\n const result: Record<string, string> = {};\n\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n result[key] = value;\n });\n } else if (Array.isArray(headers)) {\n for (const [key, value] of headers) {\n result[key] = value;\n }\n } else {\n for (const [key, value] of Object.entries(headers)) {\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Merges context, config, and additional headers.\n * Properly handles HeadersInit types (Headers object, array, or plain object).\n */\nfunction mergeHeaders(\n contextHeaders?: Record<string, string | undefined>,\n configHeaders?: HeadersInit,\n additionalHeaders?: Record<string, string>,\n): Record<string, string> {\n const result: Record<string, string> = {};\n\n // Add context headers (filter out undefined)\n if (contextHeaders) {\n for (const [key, value] of Object.entries(contextHeaders)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n }\n\n // Add config headers\n if (configHeaders) {\n Object.assign(result, headersToObject(configHeaders));\n }\n\n // Add additional headers (like auto-generated Content-Type)\n if (additionalHeaders) {\n Object.assign(result, additionalHeaders);\n }\n\n return result;\n}\n\n/**\n * Builds a URL with query parameters.\n */\nexport function buildUrl(baseUrl: string, params?: RequestParams): string {\n if (!params || Object.keys(params).length === 0) {\n return baseUrl;\n }\n\n const url = new URL(baseUrl);\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n url.searchParams.append(key, String(value));\n }\n }\n\n return url.toString();\n}\n\n/**\n * Creates a fetch service with pre-configured context.\n */\nexport function createHttpClient(context: ContextProps = { url: '' }) {\n const createMethodHandler = (method: string) => {\n return <T>(url: string, config: RequestConfig = {}): Promise<RequestResponse<T>> => {\n return makeRequest<T>(url, { ...config, method }, context);\n };\n };\n\n return {\n /**\n * Cleans up expired cache entries.\n * Returns the number of entries removed.\n */\n cleanupCache(): number {\n const now = Date.now();\n const expiredKeys = Array.from(HttpCache.entries())\n .filter(([, value]) => now > value.expiresIn)\n .map(([key]) => key);\n\n for (const key of expiredKeys) {\n HttpCache.delete(key);\n }\n\n return expiredKeys.length;\n },\n\n /**\n * Clears all cached requests.\n */\n clearCache(): void {\n HttpCache.clear();\n },\n delete: createMethodHandler('DELETE'),\n get: createMethodHandler('GET'),\n\n /**\n * Returns the number of cached requests.\n */\n getCacheSize(): number {\n return HttpCache.size;\n },\n\n /**\n * Invalidates a specific cache entry by id or URL.\n */\n invalidateCache(idOrUrl: string): boolean {\n return HttpCache.delete(idOrUrl);\n },\n patch: createMethodHandler('PATCH'),\n post: createMethodHandler('POST'),\n put: createMethodHandler('PUT'),\n\n /**\n * Updates the service headers.\n * Headers with undefined values will be removed.\n */\n setHeaders(payload: Record<string, string | undefined>): void {\n context.headers = Object.fromEntries(\n Object.entries({ ...context.headers, ...payload }).filter(([, value]) => value !== undefined),\n );\n },\n };\n}\n"],"names":["HttpError","message","url","method","status","originalError","REQUEST_TIMEOUT","CACHE_EXPIRES_IN","RequestErrorType","RequestStatus","HttpCache","getCacheKey","config","body","headers","log","type","req","res","startTime","elapsed","logType","shortUrl","formatUrlForLog","icon","Logit","fetcher","id","retries","response","data","parseResponse","updateCacheStatus","error","contentType","cached","makeRequest","context","key","shouldInvalidateCache","isCacheValid","controller","fullUrl","buildFullUrl","requestConfig","buildRequestConfig","request","baseUrl","path","isBodyInit","value","timeout","signal","additionalHeaders","mergeHeaders","headersToObject","result","contextHeaders","configHeaders","buildUrl","params","createHttpClient","createMethodHandler","now","expiredKeys","idOrUrl","payload"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./fetchit.cjs");exports.HttpError=t.HttpError;exports.RequestErrorType=t.RequestErrorType;exports.RequestStatus=t.RequestStatus;exports.buildUrl=t.buildUrl;exports.createHttpClient=t.createHttpClient;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.ts
CHANGED
|
@@ -14,18 +14,47 @@ declare type ContextProps = {
|
|
|
14
14
|
/**
|
|
15
15
|
* Creates a fetch service with pre-configured context.
|
|
16
16
|
*/
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function createHttpClient(context?: ContextProps): {
|
|
18
|
+
/**
|
|
19
|
+
* Cleans up expired cache entries.
|
|
20
|
+
* Returns the number of entries removed.
|
|
21
|
+
*/
|
|
22
|
+
cleanupCache(): number;
|
|
23
|
+
/**
|
|
24
|
+
* Clears all cached requests.
|
|
25
|
+
*/
|
|
26
|
+
clearCache(): void;
|
|
18
27
|
delete: <T>(url: string, config?: RequestConfig) => Promise<RequestResponse<T>>;
|
|
19
28
|
get: <T>(url: string, config?: RequestConfig) => Promise<RequestResponse<T>>;
|
|
29
|
+
/**
|
|
30
|
+
* Returns the number of cached requests.
|
|
31
|
+
*/
|
|
32
|
+
getCacheSize(): number;
|
|
33
|
+
/**
|
|
34
|
+
* Invalidates a specific cache entry by id or URL.
|
|
35
|
+
*/
|
|
36
|
+
invalidateCache(idOrUrl: string): boolean;
|
|
20
37
|
patch: <T>(url: string, config?: RequestConfig) => Promise<RequestResponse<T>>;
|
|
21
38
|
post: <T>(url: string, config?: RequestConfig) => Promise<RequestResponse<T>>;
|
|
22
39
|
put: <T>(url: string, config?: RequestConfig) => Promise<RequestResponse<T>>;
|
|
23
40
|
/**
|
|
24
|
-
* Updates the service headers
|
|
41
|
+
* Updates the service headers.
|
|
42
|
+
* Headers with undefined values will be removed.
|
|
25
43
|
*/
|
|
26
44
|
setHeaders(payload: Record<string, string | undefined>): void;
|
|
27
45
|
};
|
|
28
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Custom error class for HTTP request failures with additional context.
|
|
49
|
+
*/
|
|
50
|
+
export declare class HttpError extends Error {
|
|
51
|
+
readonly url: string;
|
|
52
|
+
readonly method: string;
|
|
53
|
+
readonly status?: number;
|
|
54
|
+
readonly originalError?: unknown;
|
|
55
|
+
constructor(message: string, url: string, method: string, status?: number, originalError?: unknown);
|
|
56
|
+
}
|
|
57
|
+
|
|
29
58
|
declare type RequestConfig = Omit<RequestInit, 'body'> & {
|
|
30
59
|
id?: string;
|
|
31
60
|
cancelable?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { RequestErrorType as
|
|
1
|
+
import { HttpError as e, RequestErrorType as o, RequestStatus as p, buildUrl as u, createHttpClient as l } from "./fetchit.js";
|
|
2
2
|
export {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
e as HttpError,
|
|
4
|
+
o as RequestErrorType,
|
|
5
|
+
p as RequestStatus,
|
|
6
|
+
u as buildUrl,
|
|
7
|
+
l as createHttpClient
|
|
7
8
|
};
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w={}
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w={},v={debug:"log",success:"log"},y=()=>typeof window<"u"&&w?.NODE_ENV?!1:typeof process<"u"&&process.env?.NODE_ENV?process.env.NODE_ENV==="production":!1,x=y(),L=typeof window<"u"&&window.matchMedia?.("(prefers-color-scheme: dark)").matches,b={debug:{bg:"#616161",border:"#424242",color:"#fff",icon:"☕",symbol:"🅳"},error:{bg:"#d32f2f",border:"#c62828",color:"#fff",icon:"✘",symbol:"🅴"},group:{bg:"#546e7a",border:"#455a64",color:"#fff",icon:"⚭",symbol:"🅶"},info:{bg:"#1976d2",border:"#1565c0",color:"#fff",icon:"ℹ",symbol:"🅸"},ns:L?{bg:"#fafafa",border:"#c7c7c7",color:"#000"}:{bg:"#424242",border:"#212121",color:"#fff"},success:{bg:"#689f38",border:"#558b2f",color:"#fff",icon:"✔",symbol:"🆂"},time:{bg:"#0097a7",border:"#00838f",color:"#fff",icon:"⏲",symbol:"🆃"},trace:{bg:"#d81b60",border:"#c2185b",color:"#fff",icon:"⛢",symbol:"🆃"},warn:{bg:"#ffb300",border:"#ffa000",color:"#fff",icon:"⚠",symbol:"🆆"}},l={debug:0,trace:1,time:2,table:3,info:4,success:5,warn:6,error:7,off:8},r={environment:!0,logLevel:"debug",namespace:"",remote:{handler:void 0,logLevel:"off"},timestamp:!0,variant:"symbol"},i=e=>l[r.logLevel]<=l[e],u=()=>new Date().toISOString().slice(11,23),g=()=>x?"🄿":"🄳",E=(e,o)=>{r.remote.handler&&l[r.remote.logLevel]<=l[e]&&r.remote.handler(e,...o)},m=e=>v[e]||e,d="border: 1px solid",p="border-radius: 4px",$="border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter",f=(e,o="")=>{const{bg:t,color:c,border:n}=b[e],s=`color: ${t}; ${d} ${n}; ${p}`;switch(r.variant){case"symbol":return`${s}; padding: 1px 1px 0${o}`;case"icon":return`${s}; padding: 0 3px${o}`;default:return`background: ${t}; color: ${c}; ${d} ${n}; ${p}; font-weight: bold; padding: 0 3px${o}`}},h=e=>{const o=b[e],{variant:t}=r;return t==="text"||!o[t]?e.toUpperCase():o[t]};function O(e){const{namespace:o,timestamp:t,environment:c}=r;let n=`%c${h(e)}%c`;const s=[f(e),""];return o&&(n+=` %c${o}%c`,s.push(f("ns",`; ${$}`),"")),c&&(n+=` %c${g()}%c`,s.push("color: darkgray","")),t&&(n+=` %c${u()}%c`,s.push("color: gray","")),{format:n,parts:s}}const a=(e,...o)=>{if(typeof window>"u"){const s=console[m(e)];s(`${h(e)} | ${g()} |`,...o);return}if(!i(e))return;const{format:t,parts:c}=O(e),n=console[m(e)];n(t,...c,...o),E(e,o)},D=e=>{const o=Math.floor(Date.now()-e);return o?`${o}ms`:""},N={assert:(e,o,t)=>console.assert(e,o,t),debug:(...e)=>a("debug",...e),error:(...e)=>a("error",...e),getLevel:()=>r.logLevel,getPrefix:()=>r.namespace,getTimestamp:()=>r.timestamp,groupCollapsed:(e,o="GROUP",t=Date.now())=>{if(!i("success"))return;const c=D(t),n=g(),s=r.timestamp?u():"";console.groupCollapsed(`%c${o}%c${r.namespace}%c${n}%c${s}%c${c}%c${e}`,f("group","; margin-right: 6px; padding: 1px 3px 0"),f("ns",`; ${$}; margin-right: 6px`),"color: darkgray; margin-right: 6px","color: gray; font-weight: lighter; margin-right: 6px","color: gray; font-weight: lighter; margin-right: 6px","color: inherit; font-weight: lighter")},groupEnd:()=>{i("success")&&console.groupEnd()},info:(...e)=>a("info",...e),initialise:e=>{Object.assign(r,e)},setLogLevel:e=>{r.logLevel=e},setPrefix:e=>{r.namespace=e},setRemote:e=>{r.remote=e},setRemoteLogLevel:e=>{r.remote.logLevel=e},setVariant:e=>{r.variant=e},showEnvironment:e=>{r.environment=e},showTimestamp:e=>{r.timestamp=e},success:(...e)=>a("success",...e),table:(...e)=>{i("table")&&console.table(...e)},time:e=>{i("time")&&console.time(e)},timeEnd:e=>{i("time")&&console.timeEnd(e)},trace:(...e)=>a("trace",...e),warn:(...e)=>a("warn",...e)};exports.Logit=N;
|
|
2
2
|
//# sourceMappingURL=logit.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logit.cjs","sources":["../../../../logit/dist/logit.js"],"sourcesContent":["const
|
|
1
|
+
{"version":3,"file":"logit.cjs","sources":["../../../../logit/dist/logit.js"],"sourcesContent":["const $ = {};\nconst v = {\n debug: \"log\",\n success: \"log\"\n}, w = () => typeof window < \"u\" && $?.NODE_ENV ? !1 : typeof process < \"u\" && process.env?.NODE_ENV ? process.env.NODE_ENV === \"production\" : !1, _ = w(), L = typeof window < \"u\" && window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches, b = {\n debug: { bg: \"#616161\", border: \"#424242\", color: \"#fff\", icon: \"☕\", symbol: \"🅳\" },\n error: { bg: \"#d32f2f\", border: \"#c62828\", color: \"#fff\", icon: \"✘\", symbol: \"🅴\" },\n group: { bg: \"#546e7a\", border: \"#455a64\", color: \"#fff\", icon: \"⚭\", symbol: \"🅶\" },\n info: { bg: \"#1976d2\", border: \"#1565c0\", color: \"#fff\", icon: \"ℹ\", symbol: \"🅸\" },\n ns: L ? { bg: \"#fafafa\", border: \"#c7c7c7\", color: \"#000\" } : { bg: \"#424242\", border: \"#212121\", color: \"#fff\" },\n success: { bg: \"#689f38\", border: \"#558b2f\", color: \"#fff\", icon: \"✔\", symbol: \"🆂\" },\n time: { bg: \"#0097a7\", border: \"#00838f\", color: \"#fff\", icon: \"⏲\", symbol: \"🆃\" },\n trace: { bg: \"#d81b60\", border: \"#c2185b\", color: \"#fff\", icon: \"⛢\", symbol: \"🆃\" },\n warn: { bg: \"#ffb300\", border: \"#ffa000\", color: \"#fff\", icon: \"⚠\", symbol: \"🆆\" }\n}, l = {\n debug: 0,\n trace: 1,\n time: 2,\n table: 3,\n info: 4,\n success: 5,\n warn: 6,\n error: 7,\n off: 8\n}, r = {\n environment: !0,\n logLevel: \"debug\",\n namespace: \"\",\n remote: { handler: void 0, logLevel: \"off\" },\n timestamp: !0,\n variant: \"symbol\"\n}, a = (e) => l[r.logLevel] <= l[e], u = () => (/* @__PURE__ */ new Date()).toISOString().slice(11, 23), d = () => _ ? \"🄿\" : \"🄳\", x = (e, o) => {\n r.remote.handler && l[r.remote.logLevel] <= l[e] && r.remote.handler(e, ...o);\n}, g = (e) => v[e] || e, m = \"border: 1px solid\", p = \"border-radius: 4px\", h = \"border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter\", f = (e, o = \"\") => {\n const { bg: t, color: c, border: n } = b[e], s = `color: ${t}; ${m} ${n}; ${p}`;\n switch (r.variant) {\n case \"symbol\":\n return `${s}; padding: 1px 1px 0${o}`;\n case \"icon\":\n return `${s}; padding: 0 3px${o}`;\n default:\n return `background: ${t}; color: ${c}; ${m} ${n}; ${p}; font-weight: bold; padding: 0 3px${o}`;\n }\n}, E = (e) => {\n const o = b[e], { variant: t } = r;\n return t === \"text\" || !o[t] ? e.toUpperCase() : o[t];\n};\nfunction D(e) {\n const { namespace: o, timestamp: t, environment: c } = r;\n let n = `%c${E(e)}%c`;\n const s = [f(e), \"\"];\n return o && (n += ` %c${o}%c`, s.push(f(\"ns\", `; ${h}`), \"\")), c && (n += ` %c${d()}%c`, s.push(\"color: darkgray\", \"\")), t && (n += ` %c${u()}%c`, s.push(\"color: gray\", \"\")), { format: n, parts: s };\n}\nconst i = (e, ...o) => {\n if (typeof window > \"u\") {\n const s = console[g(e)];\n s(`${E(e)} | ${d()} |`, ...o);\n return;\n }\n if (!a(e)) return;\n const { format: t, parts: c } = D(e), n = console[g(e)];\n n(t, ...c, ...o), x(e, o);\n}, O = (e) => {\n const o = Math.floor(Date.now() - e);\n return o ? `${o}ms` : \"\";\n}, y = {\n /**\n * Asserts a condition and logs an error if it's false.\n */\n assert: (e, o, t) => console.assert(e, o, t),\n debug: (...e) => i(\"debug\", ...e),\n error: (...e) => i(\"error\", ...e),\n /**\n * Gets the current log level.\n */\n getLevel: () => r.logLevel,\n /**\n * Gets the current namespace prefix.\n */\n getPrefix: () => r.namespace,\n /**\n * Gets whether timestamps are shown.\n */\n getTimestamp: () => r.timestamp,\n /**\n * Creates a collapsed group in the console.\n */\n groupCollapsed: (e, o = \"GROUP\", t = Date.now()) => {\n if (!a(\"success\")) return;\n const c = O(t), n = d(), s = r.timestamp ? u() : \"\";\n console.groupCollapsed(\n `%c${o}%c${r.namespace}%c${n}%c${s}%c${c}%c${e}`,\n f(\"group\", \"; margin-right: 6px; padding: 1px 3px 0\"),\n f(\"ns\", `; ${h}; margin-right: 6px`),\n \"color: darkgray; margin-right: 6px\",\n \"color: gray; font-weight: lighter; margin-right: 6px\",\n \"color: gray; font-weight: lighter; margin-right: 6px\",\n \"color: inherit; font-weight: lighter\"\n );\n },\n /**\n * Ends the current console group.\n */\n groupEnd: () => {\n a(\"success\") && console.groupEnd();\n },\n info: (...e) => i(\"info\", ...e),\n /**\n * Initializes Logit with custom options.\n */\n initialise: (e) => {\n Object.assign(r, e);\n },\n /**\n * Sets the minimum log level to display.\n */\n setLogLevel: (e) => {\n r.logLevel = e;\n },\n /**\n * Sets the namespace prefix for all logs.\n */\n setPrefix: (e) => {\n r.namespace = e;\n },\n /**\n * Configures remote logging options.\n */\n setRemote: (e) => {\n r.remote = e;\n },\n /**\n * Sets the log level for remote logging.\n */\n setRemoteLogLevel: (e) => {\n r.remote.logLevel = e;\n },\n /**\n * Sets the display variant (text, icon, or symbol).\n */\n setVariant: (e) => {\n r.variant = e;\n },\n /**\n * Shows or hides the environment indicator.\n */\n showEnvironment: (e) => {\n r.environment = e;\n },\n /**\n * Shows or hides timestamps in logs.\n */\n showTimestamp: (e) => {\n r.timestamp = e;\n },\n success: (...e) => i(\"success\", ...e),\n /**\n * Displays data in a table format.\n */\n table: (...e) => {\n a(\"table\") && console.table(...e);\n },\n /**\n * Starts a timer with the given label.\n */\n time: (e) => {\n a(\"time\") && console.time(e);\n },\n /**\n * Ends a timer with the given label.\n */\n timeEnd: (e) => {\n a(\"time\") && console.timeEnd(e);\n },\n trace: (...e) => i(\"trace\", ...e),\n warn: (...e) => i(\"warn\", ...e)\n};\nexport {\n y as Logit\n};\n//# sourceMappingURL=logit.js.map\n"],"names":["$","w","_","a","d","x","g","m","h","E","D","i","O","y"],"mappings":"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"}
|
package/dist/logit/dist/logit.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
const
|
|
1
|
+
const w = {}, v = {
|
|
2
2
|
debug: "log",
|
|
3
3
|
success: "log"
|
|
4
|
-
},
|
|
4
|
+
}, x = () => typeof window < "u" && w?.NODE_ENV ? !1 : typeof process < "u" && process.env?.NODE_ENV ? process.env.NODE_ENV === "production" : !1, y = x(), L = typeof window < "u" && window.matchMedia?.("(prefers-color-scheme: dark)").matches, b = {
|
|
5
5
|
debug: { bg: "#616161", border: "#424242", color: "#fff", icon: "☕", symbol: "🅳" },
|
|
6
6
|
error: { bg: "#d32f2f", border: "#c62828", color: "#fff", icon: "✘", symbol: "🅴" },
|
|
7
7
|
group: { bg: "#546e7a", border: "#455a64", color: "#fff", icon: "⚭", symbol: "🅶" },
|
|
8
8
|
info: { bg: "#1976d2", border: "#1565c0", color: "#fff", icon: "ℹ", symbol: "🅸" },
|
|
9
|
-
ns:
|
|
9
|
+
ns: L ? { bg: "#fafafa", border: "#c7c7c7", color: "#000" } : { bg: "#424242", border: "#212121", color: "#fff" },
|
|
10
10
|
success: { bg: "#689f38", border: "#558b2f", color: "#fff", icon: "✔", symbol: "🆂" },
|
|
11
11
|
time: { bg: "#0097a7", border: "#00838f", color: "#fff", icon: "⏲", symbol: "🆃" },
|
|
12
12
|
trace: { bg: "#d81b60", border: "#c2185b", color: "#fff", icon: "⛢", symbol: "🆃" },
|
|
13
13
|
warn: { bg: "#ffb300", border: "#ffa000", color: "#fff", icon: "⚠", symbol: "🆆" }
|
|
14
|
-
},
|
|
14
|
+
}, l = {
|
|
15
15
|
debug: 0,
|
|
16
16
|
trace: 1,
|
|
17
17
|
time: 2,
|
|
@@ -21,158 +21,160 @@ const h = {}, w = {
|
|
|
21
21
|
warn: 6,
|
|
22
22
|
error: 7,
|
|
23
23
|
off: 8
|
|
24
|
-
},
|
|
24
|
+
}, r = {
|
|
25
25
|
environment: !0,
|
|
26
26
|
logLevel: "debug",
|
|
27
27
|
namespace: "",
|
|
28
28
|
remote: { handler: void 0, logLevel: "off" },
|
|
29
29
|
timestamp: !0,
|
|
30
30
|
variant: "symbol"
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
const { bg: t, color:
|
|
35
|
-
switch (
|
|
31
|
+
}, i = (e) => l[r.logLevel] <= l[e], u = () => (/* @__PURE__ */ new Date()).toISOString().slice(11, 23), g = () => y ? "🄿" : "🄳", E = (e, o) => {
|
|
32
|
+
r.remote.handler && l[r.remote.logLevel] <= l[e] && r.remote.handler(e, ...o);
|
|
33
|
+
}, m = (e) => v[e] || e, d = "border: 1px solid", p = "border-radius: 4px", $ = "border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter", f = (e, o = "") => {
|
|
34
|
+
const { bg: t, color: c, border: n } = b[e], s = `color: ${t}; ${d} ${n}; ${p}`;
|
|
35
|
+
switch (r.variant) {
|
|
36
36
|
case "symbol":
|
|
37
|
-
return `${
|
|
37
|
+
return `${s}; padding: 1px 1px 0${o}`;
|
|
38
38
|
case "icon":
|
|
39
|
-
return `${
|
|
39
|
+
return `${s}; padding: 0 3px${o}`;
|
|
40
40
|
default:
|
|
41
|
-
return `background: ${t}; color: ${
|
|
41
|
+
return `background: ${t}; color: ${c}; ${d} ${n}; ${p}; font-weight: bold; padding: 0 3px${o}`;
|
|
42
42
|
}
|
|
43
|
+
}, h = (e) => {
|
|
44
|
+
const o = b[e], { variant: t } = r;
|
|
45
|
+
return t === "text" || !o[t] ? e.toUpperCase() : o[t];
|
|
43
46
|
};
|
|
44
|
-
function
|
|
45
|
-
const
|
|
46
|
-
let
|
|
47
|
-
const
|
|
48
|
-
return
|
|
47
|
+
function D(e) {
|
|
48
|
+
const { namespace: o, timestamp: t, environment: c } = r;
|
|
49
|
+
let n = `%c${h(e)}%c`;
|
|
50
|
+
const s = [f(e), ""];
|
|
51
|
+
return o && (n += ` %c${o}%c`, s.push(f("ns", `; ${$}`), "")), c && (n += ` %c${g()}%c`, s.push("color: darkgray", "")), t && (n += ` %c${u()}%c`, s.push("color: gray", "")), { format: n, parts: s };
|
|
49
52
|
}
|
|
50
|
-
const
|
|
53
|
+
const a = (e, ...o) => {
|
|
51
54
|
if (typeof window > "u") {
|
|
52
|
-
const
|
|
53
|
-
|
|
55
|
+
const s = console[m(e)];
|
|
56
|
+
s(`${h(e)} | ${g()} |`, ...o);
|
|
54
57
|
return;
|
|
55
58
|
}
|
|
56
|
-
if (!
|
|
57
|
-
const { format: t, parts:
|
|
58
|
-
n(t, ...
|
|
59
|
-
},
|
|
60
|
-
const
|
|
61
|
-
return
|
|
62
|
-
},
|
|
59
|
+
if (!i(e)) return;
|
|
60
|
+
const { format: t, parts: c } = D(e), n = console[m(e)];
|
|
61
|
+
n(t, ...c, ...o), E(e, o);
|
|
62
|
+
}, O = (e) => {
|
|
63
|
+
const o = Math.floor(Date.now() - e);
|
|
64
|
+
return o ? `${o}ms` : "";
|
|
65
|
+
}, N = {
|
|
63
66
|
/**
|
|
64
67
|
* Asserts a condition and logs an error if it's false.
|
|
65
68
|
*/
|
|
66
|
-
assert: (e,
|
|
67
|
-
debug: (...e) =>
|
|
68
|
-
error: (...e) =>
|
|
69
|
+
assert: (e, o, t) => console.assert(e, o, t),
|
|
70
|
+
debug: (...e) => a("debug", ...e),
|
|
71
|
+
error: (...e) => a("error", ...e),
|
|
69
72
|
/**
|
|
70
73
|
* Gets the current log level.
|
|
71
74
|
*/
|
|
72
|
-
getLevel: () =>
|
|
75
|
+
getLevel: () => r.logLevel,
|
|
73
76
|
/**
|
|
74
77
|
* Gets the current namespace prefix.
|
|
75
78
|
*/
|
|
76
|
-
getPrefix: () =>
|
|
79
|
+
getPrefix: () => r.namespace,
|
|
77
80
|
/**
|
|
78
81
|
* Gets whether timestamps are shown.
|
|
79
82
|
*/
|
|
80
|
-
getTimestamp: () =>
|
|
83
|
+
getTimestamp: () => r.timestamp,
|
|
81
84
|
/**
|
|
82
85
|
* Creates a collapsed group in the console.
|
|
83
86
|
*/
|
|
84
|
-
groupCollapsed: (e,
|
|
85
|
-
if (!
|
|
86
|
-
const
|
|
87
|
+
groupCollapsed: (e, o = "GROUP", t = Date.now()) => {
|
|
88
|
+
if (!i("success")) return;
|
|
89
|
+
const c = O(t), n = g(), s = r.timestamp ? u() : "";
|
|
87
90
|
console.groupCollapsed(
|
|
88
|
-
`%c${
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
"color: darkgray; margin-right: 6px
|
|
92
|
-
"color: gray;font-weight: lighter;margin-right: 6px
|
|
93
|
-
"color: gray; font-weight: lighter;margin-right: 6px
|
|
94
|
-
"color: inherit;font-weight: lighter
|
|
91
|
+
`%c${o}%c${r.namespace}%c${n}%c${s}%c${c}%c${e}`,
|
|
92
|
+
f("group", "; margin-right: 6px; padding: 1px 3px 0"),
|
|
93
|
+
f("ns", `; ${$}; margin-right: 6px`),
|
|
94
|
+
"color: darkgray; margin-right: 6px",
|
|
95
|
+
"color: gray; font-weight: lighter; margin-right: 6px",
|
|
96
|
+
"color: gray; font-weight: lighter; margin-right: 6px",
|
|
97
|
+
"color: inherit; font-weight: lighter"
|
|
95
98
|
);
|
|
96
99
|
},
|
|
97
100
|
/**
|
|
98
101
|
* Ends the current console group.
|
|
99
102
|
*/
|
|
100
103
|
groupEnd: () => {
|
|
101
|
-
|
|
104
|
+
i("success") && console.groupEnd();
|
|
102
105
|
},
|
|
103
|
-
info: (...e) =>
|
|
106
|
+
info: (...e) => a("info", ...e),
|
|
104
107
|
/**
|
|
105
108
|
* Initializes Logit with custom options.
|
|
106
109
|
*/
|
|
107
110
|
initialise: (e) => {
|
|
108
|
-
Object.assign(
|
|
111
|
+
Object.assign(r, e);
|
|
109
112
|
},
|
|
110
113
|
/**
|
|
111
114
|
* Sets the minimum log level to display.
|
|
112
115
|
*/
|
|
113
116
|
setLogLevel: (e) => {
|
|
114
|
-
|
|
117
|
+
r.logLevel = e;
|
|
115
118
|
},
|
|
116
119
|
/**
|
|
117
120
|
* Sets the namespace prefix for all logs.
|
|
118
121
|
*/
|
|
119
122
|
setPrefix: (e) => {
|
|
120
|
-
|
|
123
|
+
r.namespace = e;
|
|
121
124
|
},
|
|
122
125
|
/**
|
|
123
126
|
* Configures remote logging options.
|
|
124
127
|
*/
|
|
125
128
|
setRemote: (e) => {
|
|
126
|
-
|
|
129
|
+
r.remote = e;
|
|
127
130
|
},
|
|
128
131
|
/**
|
|
129
132
|
* Sets the log level for remote logging.
|
|
130
133
|
*/
|
|
131
134
|
setRemoteLogLevel: (e) => {
|
|
132
|
-
|
|
135
|
+
r.remote.logLevel = e;
|
|
133
136
|
},
|
|
134
137
|
/**
|
|
135
138
|
* Sets the display variant (text, icon, or symbol).
|
|
136
139
|
*/
|
|
137
140
|
setVariant: (e) => {
|
|
138
|
-
|
|
141
|
+
r.variant = e;
|
|
139
142
|
},
|
|
140
143
|
/**
|
|
141
144
|
* Shows or hides the environment indicator.
|
|
142
145
|
*/
|
|
143
146
|
showEnvironment: (e) => {
|
|
144
|
-
|
|
147
|
+
r.environment = e;
|
|
145
148
|
},
|
|
146
149
|
/**
|
|
147
150
|
* Shows or hides timestamps in logs.
|
|
148
151
|
*/
|
|
149
152
|
showTimestamp: (e) => {
|
|
150
|
-
|
|
153
|
+
r.timestamp = e;
|
|
151
154
|
},
|
|
152
|
-
success: (...e) =>
|
|
155
|
+
success: (...e) => a("success", ...e),
|
|
153
156
|
/**
|
|
154
157
|
* Displays data in a table format.
|
|
155
158
|
*/
|
|
156
159
|
table: (...e) => {
|
|
157
|
-
|
|
160
|
+
i("table") && console.table(...e);
|
|
158
161
|
},
|
|
159
162
|
/**
|
|
160
163
|
* Starts a timer with the given label.
|
|
161
164
|
*/
|
|
162
165
|
time: (e) => {
|
|
163
|
-
|
|
166
|
+
i("time") && console.time(e);
|
|
164
167
|
},
|
|
165
168
|
/**
|
|
166
169
|
* Ends a timer with the given label.
|
|
167
170
|
*/
|
|
168
171
|
timeEnd: (e) => {
|
|
169
|
-
|
|
172
|
+
i("time") && console.timeEnd(e);
|
|
170
173
|
},
|
|
171
|
-
trace: (...e) =>
|
|
172
|
-
warn: (...e) =>
|
|
174
|
+
trace: (...e) => a("trace", ...e),
|
|
175
|
+
warn: (...e) => a("warn", ...e)
|
|
173
176
|
};
|
|
174
|
-
typeof window < "u" && (window.Logit = E);
|
|
175
177
|
export {
|
|
176
|
-
|
|
178
|
+
N as Logit
|
|
177
179
|
};
|
|
178
180
|
//# sourceMappingURL=logit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logit.js","sources":["../../../../logit/dist/logit.js"],"sourcesContent":["const h = {};\nconst w = {\n debug: \"log\",\n success: \"log\"\n}, v = () => h?.NODE_ENV === \"production\", $ = typeof window < \"u\" && window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches, m = {\n debug: { bg: \"#616161\", border: \"#424242\", color: \"#fff\", icon: \"☕\", symbol: \"🅳\" },\n error: { bg: \"#d32f2f\", border: \"#c62828\", color: \"#fff\", icon: \"✘\", symbol: \"🅴\" },\n group: { bg: \"#546e7a\", border: \"#455a64\", color: \"#fff\", icon: \"⚭\", symbol: \"🅶\" },\n info: { bg: \"#1976d2\", border: \"#1565c0\", color: \"#fff\", icon: \"ℹ\", symbol: \"🅸\" },\n ns: $ ? { bg: \"#fafafa\", border: \"#c7c7c7\", color: \"#000\" } : { bg: \"#424242\", border: \"#212121\", color: \"#fff\" },\n success: { bg: \"#689f38\", border: \"#558b2f\", color: \"#fff\", icon: \"✔\", symbol: \"🆂\" },\n time: { bg: \"#0097a7\", border: \"#00838f\", color: \"#fff\", icon: \"⏲\", symbol: \"🆃\" },\n trace: { bg: \"#d81b60\", border: \"#c2185b\", color: \"#fff\", icon: \"⛢\", symbol: \"🆃\" },\n warn: { bg: \"#ffb300\", border: \"#ffa000\", color: \"#fff\", icon: \"⚠\", symbol: \"🆆\" }\n}, f = {\n debug: 0,\n trace: 1,\n time: 2,\n table: 3,\n info: 4,\n success: 5,\n warn: 6,\n error: 7,\n off: 8\n}, e = {\n environment: !0,\n logLevel: \"debug\",\n namespace: \"\",\n remote: { handler: void 0, logLevel: \"off\" },\n timestamp: !0,\n variant: \"symbol\"\n}, d = (o) => f[e.logLevel] <= f[o], u = () => (/* @__PURE__ */ new Date()).toISOString().slice(11, 23), b = () => v() ? \"🄿\" : \"🄳\", x = (o, r) => {\n e.remote.handler && f[e.remote.logLevel] <= f[o] && e.remote.handler(o, ...r);\n}, p = (o) => w[o] || o, g = (o, r = \"\") => {\n const { bg: t, color: s, border: n } = m[o], c = `color: ${t}; border: 1px solid ${n}; border-radius: 4px;`;\n switch (e.variant) {\n case \"symbol\":\n return `${c} padding: 1px 1px 0;${r};`;\n case \"icon\":\n return `${c} padding: 0 3px;${r};`;\n default:\n return `background: ${t}; color: ${s}; border: 1px solid ${n}; border-radius: 4px; font-weight: bold; padding: 0 3px;${r}`;\n }\n};\nfunction L(o) {\n const r = m[o], { namespace: t, variant: s, timestamp: n, environment: c } = e;\n let i = `%c${r[s] ?? o.toUpperCase()}%c`;\n const a = [g(o), \"\"];\n return t && (i += ` %c${t}%c`, a.push(g(\"ns\", \" border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter;\"), \"\")), c && (i += ` %c${b()}%c`, a.push(\"color: darkgray;\", \"\")), n && (i += ` %c${u()}%c`, a.push(\"color: gray;\", \"\")), { format: i, parts: a };\n}\nconst l = (o, ...r) => {\n if (typeof window > \"u\") {\n const c = m[o], { variant: i } = e, a = console[p(o)];\n a(`${c[i] ?? o.toUpperCase()} | ${b()} |`, ...r);\n return;\n }\n if (!d(o)) return;\n const { format: t, parts: s } = L(o), n = console[p(o)];\n n(t, ...s, ...r), x(o, r);\n}, E = (o) => {\n const r = Math.floor(Date.now() - o);\n return r ? `${r}ms` : \"\";\n}, _ = {\n /**\n * Asserts a condition and logs an error if it's false.\n */\n assert: (o, r, t) => console.assert(o, r, t),\n debug: (...o) => l(\"debug\", ...o),\n error: (...o) => l(\"error\", ...o),\n /**\n * Gets the current log level.\n */\n getLevel: () => e.logLevel,\n /**\n * Gets the current namespace prefix.\n */\n getPrefix: () => e.namespace,\n /**\n * Gets whether timestamps are shown.\n */\n getTimestamp: () => e.timestamp,\n /**\n * Creates a collapsed group in the console.\n */\n groupCollapsed: (o, r = \"GROUP\", t = Date.now()) => {\n if (!d(\"success\")) return;\n const s = E(t), n = b();\n console.groupCollapsed(\n `%c${r}%c${e.namespace}%c${n}%c${e.timestamp ? u() : \"\"}%c${s}%c${o}`,\n g(\"group\", \"margin-right: 6px; padding: 1px 3px 0\"),\n g(\"ns\", \" border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter;margin-right: 6px;\"),\n \"color: darkgray; margin-right: 6px;\",\n \"color: gray;font-weight: lighter;margin-right: 6px;\",\n \"color: gray; font-weight: lighter;margin-right: 6px;\",\n \"color: inherit;font-weight: lighter;\"\n );\n },\n /**\n * Ends the current console group.\n */\n groupEnd: () => {\n d(\"success\") && console.groupEnd();\n },\n info: (...o) => l(\"info\", ...o),\n /**\n * Initializes Logit with custom options.\n */\n initialise: (o) => {\n Object.assign(e, o);\n },\n /**\n * Sets the minimum log level to display.\n */\n setLogLevel: (o) => {\n e.logLevel = o;\n },\n /**\n * Sets the namespace prefix for all logs.\n */\n setPrefix: (o) => {\n e.namespace = o;\n },\n /**\n * Configures remote logging options.\n */\n setRemote: (o) => {\n e.remote = o;\n },\n /**\n * Sets the log level for remote logging.\n */\n setRemoteLogLevel: (o) => {\n e.remote.logLevel = o;\n },\n /**\n * Sets the display variant (text, icon, or symbol).\n */\n setVariant: (o) => {\n e.variant = o;\n },\n /**\n * Shows or hides the environment indicator.\n */\n showEnvironment: (o) => {\n e.environment = o;\n },\n /**\n * Shows or hides timestamps in logs.\n */\n showTimestamp: (o) => {\n e.timestamp = o;\n },\n success: (...o) => l(\"success\", ...o),\n /**\n * Displays data in a table format.\n */\n table: (...o) => {\n d(\"table\") && console.table(...o);\n },\n /**\n * Starts a timer with the given label.\n */\n time: (o) => {\n d(\"time\") && console.time(o);\n },\n /**\n * Ends a timer with the given label.\n */\n timeEnd: (o) => {\n d(\"time\") && console.timeEnd(o);\n },\n trace: (...o) => l(\"trace\", ...o),\n warn: (...o) => l(\"warn\", ...o)\n};\ntypeof window < \"u\" && (window.Logit = _);\nexport {\n _ as Logit\n};\n//# sourceMappingURL=logit.js.map\n"],"names":["v","$","e","d","o","b","x","p","g","L","i","a","E","_"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"logit.js","sources":["../../../../logit/dist/logit.js"],"sourcesContent":["const $ = {};\nconst v = {\n debug: \"log\",\n success: \"log\"\n}, w = () => typeof window < \"u\" && $?.NODE_ENV ? !1 : typeof process < \"u\" && process.env?.NODE_ENV ? process.env.NODE_ENV === \"production\" : !1, _ = w(), L = typeof window < \"u\" && window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches, b = {\n debug: { bg: \"#616161\", border: \"#424242\", color: \"#fff\", icon: \"☕\", symbol: \"🅳\" },\n error: { bg: \"#d32f2f\", border: \"#c62828\", color: \"#fff\", icon: \"✘\", symbol: \"🅴\" },\n group: { bg: \"#546e7a\", border: \"#455a64\", color: \"#fff\", icon: \"⚭\", symbol: \"🅶\" },\n info: { bg: \"#1976d2\", border: \"#1565c0\", color: \"#fff\", icon: \"ℹ\", symbol: \"🅸\" },\n ns: L ? { bg: \"#fafafa\", border: \"#c7c7c7\", color: \"#000\" } : { bg: \"#424242\", border: \"#212121\", color: \"#fff\" },\n success: { bg: \"#689f38\", border: \"#558b2f\", color: \"#fff\", icon: \"✔\", symbol: \"🆂\" },\n time: { bg: \"#0097a7\", border: \"#00838f\", color: \"#fff\", icon: \"⏲\", symbol: \"🆃\" },\n trace: { bg: \"#d81b60\", border: \"#c2185b\", color: \"#fff\", icon: \"⛢\", symbol: \"🆃\" },\n warn: { bg: \"#ffb300\", border: \"#ffa000\", color: \"#fff\", icon: \"⚠\", symbol: \"🆆\" }\n}, l = {\n debug: 0,\n trace: 1,\n time: 2,\n table: 3,\n info: 4,\n success: 5,\n warn: 6,\n error: 7,\n off: 8\n}, r = {\n environment: !0,\n logLevel: \"debug\",\n namespace: \"\",\n remote: { handler: void 0, logLevel: \"off\" },\n timestamp: !0,\n variant: \"symbol\"\n}, a = (e) => l[r.logLevel] <= l[e], u = () => (/* @__PURE__ */ new Date()).toISOString().slice(11, 23), d = () => _ ? \"🄿\" : \"🄳\", x = (e, o) => {\n r.remote.handler && l[r.remote.logLevel] <= l[e] && r.remote.handler(e, ...o);\n}, g = (e) => v[e] || e, m = \"border: 1px solid\", p = \"border-radius: 4px\", h = \"border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter\", f = (e, o = \"\") => {\n const { bg: t, color: c, border: n } = b[e], s = `color: ${t}; ${m} ${n}; ${p}`;\n switch (r.variant) {\n case \"symbol\":\n return `${s}; padding: 1px 1px 0${o}`;\n case \"icon\":\n return `${s}; padding: 0 3px${o}`;\n default:\n return `background: ${t}; color: ${c}; ${m} ${n}; ${p}; font-weight: bold; padding: 0 3px${o}`;\n }\n}, E = (e) => {\n const o = b[e], { variant: t } = r;\n return t === \"text\" || !o[t] ? e.toUpperCase() : o[t];\n};\nfunction D(e) {\n const { namespace: o, timestamp: t, environment: c } = r;\n let n = `%c${E(e)}%c`;\n const s = [f(e), \"\"];\n return o && (n += ` %c${o}%c`, s.push(f(\"ns\", `; ${h}`), \"\")), c && (n += ` %c${d()}%c`, s.push(\"color: darkgray\", \"\")), t && (n += ` %c${u()}%c`, s.push(\"color: gray\", \"\")), { format: n, parts: s };\n}\nconst i = (e, ...o) => {\n if (typeof window > \"u\") {\n const s = console[g(e)];\n s(`${E(e)} | ${d()} |`, ...o);\n return;\n }\n if (!a(e)) return;\n const { format: t, parts: c } = D(e), n = console[g(e)];\n n(t, ...c, ...o), x(e, o);\n}, O = (e) => {\n const o = Math.floor(Date.now() - e);\n return o ? `${o}ms` : \"\";\n}, y = {\n /**\n * Asserts a condition and logs an error if it's false.\n */\n assert: (e, o, t) => console.assert(e, o, t),\n debug: (...e) => i(\"debug\", ...e),\n error: (...e) => i(\"error\", ...e),\n /**\n * Gets the current log level.\n */\n getLevel: () => r.logLevel,\n /**\n * Gets the current namespace prefix.\n */\n getPrefix: () => r.namespace,\n /**\n * Gets whether timestamps are shown.\n */\n getTimestamp: () => r.timestamp,\n /**\n * Creates a collapsed group in the console.\n */\n groupCollapsed: (e, o = \"GROUP\", t = Date.now()) => {\n if (!a(\"success\")) return;\n const c = O(t), n = d(), s = r.timestamp ? u() : \"\";\n console.groupCollapsed(\n `%c${o}%c${r.namespace}%c${n}%c${s}%c${c}%c${e}`,\n f(\"group\", \"; margin-right: 6px; padding: 1px 3px 0\"),\n f(\"ns\", `; ${h}; margin-right: 6px`),\n \"color: darkgray; margin-right: 6px\",\n \"color: gray; font-weight: lighter; margin-right: 6px\",\n \"color: gray; font-weight: lighter; margin-right: 6px\",\n \"color: inherit; font-weight: lighter\"\n );\n },\n /**\n * Ends the current console group.\n */\n groupEnd: () => {\n a(\"success\") && console.groupEnd();\n },\n info: (...e) => i(\"info\", ...e),\n /**\n * Initializes Logit with custom options.\n */\n initialise: (e) => {\n Object.assign(r, e);\n },\n /**\n * Sets the minimum log level to display.\n */\n setLogLevel: (e) => {\n r.logLevel = e;\n },\n /**\n * Sets the namespace prefix for all logs.\n */\n setPrefix: (e) => {\n r.namespace = e;\n },\n /**\n * Configures remote logging options.\n */\n setRemote: (e) => {\n r.remote = e;\n },\n /**\n * Sets the log level for remote logging.\n */\n setRemoteLogLevel: (e) => {\n r.remote.logLevel = e;\n },\n /**\n * Sets the display variant (text, icon, or symbol).\n */\n setVariant: (e) => {\n r.variant = e;\n },\n /**\n * Shows or hides the environment indicator.\n */\n showEnvironment: (e) => {\n r.environment = e;\n },\n /**\n * Shows or hides timestamps in logs.\n */\n showTimestamp: (e) => {\n r.timestamp = e;\n },\n success: (...e) => i(\"success\", ...e),\n /**\n * Displays data in a table format.\n */\n table: (...e) => {\n a(\"table\") && console.table(...e);\n },\n /**\n * Starts a timer with the given label.\n */\n time: (e) => {\n a(\"time\") && console.time(e);\n },\n /**\n * Ends a timer with the given label.\n */\n timeEnd: (e) => {\n a(\"time\") && console.timeEnd(e);\n },\n trace: (...e) => i(\"trace\", ...e),\n warn: (...e) => i(\"warn\", ...e)\n};\nexport {\n y as Logit\n};\n//# sourceMappingURL=logit.js.map\n"],"names":["$","w","_","a","d","x","g","m","h","E","i","y"],"mappings":"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"}
|