@usethrottle/invoices 0.1.1 → 0.1.2

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/index.cjs CHANGED
@@ -68,7 +68,7 @@ var InvoicesClient = class {
68
68
  const init = { method, headers: { "content-type": "application/json", ...this.apiKey ? { "x-api-key": this.apiKey } : {} }, signal: ctrl.signal };
69
69
  const res = this.fetcher ? await this.fetcher(path, init) : await this.fetchImpl(`${this.baseUrl}${path}`, init);
70
70
  const json = await res.json().catch(() => ({}));
71
- if (!res.ok) throw new ThrottleInvoicesError({ code: json.error?.code ?? "unknown_error", message: json.error?.message ?? `HTTP ${res.status}`, statusCode: res.status, details: json.error?.details });
71
+ if (!res.ok) throw new ThrottleInvoicesError({ code: json.error?.code ?? "unknown_error", message: json.error?.message ?? `HTTP ${res.status}`, statusCode: res.status, details: json.error?.details, responseHeaders: res.headers });
72
72
  return json;
73
73
  } finally {
74
74
  clearTimeout(timer);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx","../src/errors.ts","../src/client.ts","../src/provider.tsx","../src/hooks.ts"],"sourcesContent":["export { InvoicesClient, createInvoicesClient } from './client';\nexport { ThrottleInvoicesError, ThrottleError, isThrottleError } from './errors';\nexport { InvoiceProvider, useInvoiceClient, useInvoiceInvalidation } from './provider';\nexport { useInvoices, useInvoice, useDownloadInvoice } from './hooks';\nexport type * from './types';\n","import { ThrottleError } from '@usethrottle/errors';\nexport class ThrottleInvoicesError extends ThrottleError {\n constructor(args: { code: string; message: string; statusCode: number; details?: unknown }) {\n super(args); this.name = 'ThrottleInvoicesError';\n }\n}\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n","import { ThrottleInvoicesError } from './errors';\nimport type { Invoice, InvoicesClientContract, InvoicesClientOptions, ListInvoicesParams, PaginatedInvoices, ThrottleEnvelope } from './types';\n\nexport class InvoicesClient implements InvoicesClientContract {\n private readonly apiKey?: string; private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch; private readonly fetcher?: InvoicesClientOptions['fetcher']; private readonly timeoutMs: number;\n constructor(opts: InvoicesClientOptions = {}) {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('InvoicesClient: fetch is required');\n if (!opts.apiKey && !opts.fetcher) throw new Error('InvoicesClient: apiKey or fetcher is required');\n this.apiKey = opts.apiKey; this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl; this.fetcher = opts.fetcher; this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n private async requestEnvelope<T>(method: string, path: string): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController(); const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const init: RequestInit = { method, headers: { 'content-type': 'application/json', ...(this.apiKey ? { 'x-api-key': this.apiKey } : {}) }, signal: ctrl.signal };\n const res = this.fetcher ? await this.fetcher(path, init) : await this.fetchImpl(`${this.baseUrl}${path}`, init);\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) throw new ThrottleInvoicesError({ code: json.error?.code ?? 'unknown_error', message: json.error?.message ?? `HTTP ${res.status}`, statusCode: res.status, details: json.error?.details });\n return json;\n } finally { clearTimeout(timer); }\n }\n async list(params: ListInvoicesParams = {}): Promise<PaginatedInvoices> {\n const q = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) if (v !== undefined && v !== null && v !== '') q.set(k, String(v));\n const suffix = q.toString() ? `?${q}` : '';\n const env = await this.requestEnvelope<Invoice[]>('GET', `/api/v1/invoices${suffix}`);\n return { data: env.data ?? [], pagination: env.meta?.pagination ? { cursor: env.meta.pagination.cursor ?? null, hasMore: Boolean(env.meta.pagination.hasMore) } : undefined };\n }\n async get(id: string): Promise<Invoice> {\n const env = await this.requestEnvelope<Invoice>('GET', `/api/v1/invoices/${encodeURIComponent(id)}`);\n return env.data as Invoice;\n }\n async getDownloadUrl(id: string): Promise<string> {\n const env = await this.requestEnvelope<{ url: string }>('GET', `/api/v1/invoices/${encodeURIComponent(id)}/download?format=json`);\n return (env.data as { url: string }).url;\n }\n}\nexport function createInvoicesClient(opts: InvoicesClientOptions): InvoicesClient { return new InvoicesClient(opts); }\n","import { createContext, useCallback, useContext, useMemo, useReducer, type ReactNode } from 'react';\nimport { InvoicesClient } from './client';\nimport type {\n InvoiceFetcher,\n InvoicesProviderProps,\n InvoicesClientContract,\n} from './types';\n\ninterface InvoiceContextValue {\n client: InvoicesClientContract;\n cacheVersion: number;\n invalidate: () => void;\n}\n\nconst InvoiceContext = createContext<InvoiceContextValue | null>(null);\n\nexport function InvoiceProvider({\n children,\n client,\n fetcher,\n baseUrl,\n timeoutMs,\n}: InvoicesProviderProps) {\n const [cacheVersion, invalidate] = useReducer((value: number) => value + 1, 0);\n const resolvedClient = useMemo(() => {\n if (client) return client;\n return new InvoicesClient({\n fetcher: fetcher ?? createInvoiceFetcher('/api/throttle'),\n baseUrl,\n timeoutMs,\n });\n }, [baseUrl, client, fetcher, timeoutMs]);\n\n const value = useMemo(\n () => ({ client: resolvedClient, cacheVersion, invalidate }),\n [cacheVersion, resolvedClient],\n );\n\n return <InvoiceContext.Provider value={value}>{children}</InvoiceContext.Provider>;\n}\n\nexport function useInvoiceClient(): InvoicesClientContract {\n return useInvoiceContext().client;\n}\n\nexport function useInvoiceInvalidation(): () => void {\n return useInvoiceContext().invalidate;\n}\n\nexport function useInvoiceCacheVersion(): number {\n return useInvoiceContext().cacheVersion;\n}\n\nexport function createInvoiceFetcher(basePath: string): InvoiceFetcher {\n const cleanBase = basePath.replace(/\\/+$/, '');\n return (path, init) => {\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return fetch(`${cleanBase}${cleanPath}`, init);\n };\n}\n\nexport function useInvoiceContext(): InvoiceContextValue {\n const ctx = useContext(InvoiceContext);\n if (!ctx) {\n throw new Error(\n '@usethrottle/invoices hooks must be used inside <InvoiceProvider />',\n );\n }\n return ctx;\n}\n\nexport function InvoiceProviderWithClient({\n children,\n client,\n}: {\n children: ReactNode;\n client: InvoicesClientContract;\n}) {\n const [cacheVersion, invalidate] = useReducer((value: number) => value + 1, 0);\n const value = useMemo(() => ({ client, cacheVersion, invalidate }), [cacheVersion, client]);\n return <InvoiceContext.Provider value={value}>{children}</InvoiceContext.Provider>;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n useInvoiceCacheVersion,\n useInvoiceClient,\n} from './provider';\nimport type {\n Invoice,\n ListInvoicesParams,\n PaginatedInvoices,\n QueryOptions,\n QueryState,\n} from './types';\n\nexport function useInvoices(\n params: ListInvoicesParams = {},\n options: QueryOptions<PaginatedInvoices> = {},\n): QueryState<PaginatedInvoices> {\n const client = useInvoiceClient();\n const v = useInvoiceCacheVersion();\n const p = useStableValue(params);\n return useAsyncQuery(() => client.list(p), [client, p, v], options);\n}\n\nexport function useInvoice(\n id: string | null | undefined,\n options: QueryOptions<Invoice> = {},\n): QueryState<Invoice> {\n const client = useInvoiceClient();\n const v = useInvoiceCacheVersion();\n return useAsyncQuery(\n () => (id ? client.get(id) : Promise.resolve(null)),\n [client, id, v],\n { ...options, enabled: options.enabled ?? Boolean(id) },\n );\n}\n\nexport function useDownloadInvoice() {\n const client = useInvoiceClient();\n return async (id: string) => {\n const url = await client.getDownloadUrl(id);\n if (typeof window !== 'undefined') window.open(url, '_blank');\n return url;\n };\n}\n\nfunction useAsyncQuery<T>(\n load: () => Promise<T | null>,\n deps: readonly unknown[],\n options: QueryOptions<T>,\n): QueryState<T> {\n const enabled = options.enabled ?? true;\n const [data, setData] = useState<T | null>(options.initialData ?? null);\n const [error, setError] = useState<unknown>(null);\n const [isLoading, setIsLoading] = useState(enabled && options.initialData === undefined);\n const [isFetching, setIsFetching] = useState(false);\n const loadRef = useRef(load);\n loadRef.current = load;\n\n const refetch = useCallback(async () => {\n if (!enabled) return data;\n setIsFetching(true);\n setError(null);\n try {\n const next = await loadRef.current();\n setData(next);\n return next;\n } catch (err) {\n setError(err);\n throw err;\n } finally {\n setIsFetching(false);\n setIsLoading(false);\n }\n }, [data, enabled]);\n\n useEffect(() => {\n if (!enabled) {\n setIsLoading(false);\n return;\n }\n let cancelled = false;\n setIsFetching(true);\n setError(null);\n load()\n .then((next) => {\n if (!cancelled) setData(next);\n })\n .catch((err) => {\n if (!cancelled) setError(err);\n })\n .finally(() => {\n if (!cancelled) {\n setIsLoading(false);\n setIsFetching(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, ...deps]);\n\n return { data, error, isLoading, isFetching, refetch };\n}\n\nfunction useStableValue<T>(value: T): T {\n const key = JSON.stringify(value);\n return useMemo(() => value, [key]);\n}\n"],"mappings":"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","names":["import_errors","value","import_react"]}
1
+ {"version":3,"sources":["../src/index.tsx","../src/errors.ts","../src/client.ts","../src/provider.tsx","../src/hooks.ts"],"sourcesContent":["export { InvoicesClient, createInvoicesClient } from './client';\nexport { ThrottleInvoicesError, ThrottleError, isThrottleError } from './errors';\nexport { InvoiceProvider, useInvoiceClient, useInvoiceInvalidation } from './provider';\nexport { useInvoices, useInvoice, useDownloadInvoice } from './hooks';\nexport type * from './types';\n","import { ThrottleError, type ThrottleErrorArgs } from '@usethrottle/errors';\nexport class ThrottleInvoicesError extends ThrottleError {\n constructor(args: { code: string; message: string; statusCode: number; details?: unknown; responseHeaders?: ThrottleErrorArgs['responseHeaders'] }) {\n super(args); this.name = 'ThrottleInvoicesError';\n }\n}\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n","import { ThrottleInvoicesError } from './errors';\nimport type { Invoice, InvoicesClientContract, InvoicesClientOptions, ListInvoicesParams, PaginatedInvoices, ThrottleEnvelope } from './types';\n\nexport class InvoicesClient implements InvoicesClientContract {\n private readonly apiKey?: string; private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch; private readonly fetcher?: InvoicesClientOptions['fetcher']; private readonly timeoutMs: number;\n constructor(opts: InvoicesClientOptions = {}) {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('InvoicesClient: fetch is required');\n if (!opts.apiKey && !opts.fetcher) throw new Error('InvoicesClient: apiKey or fetcher is required');\n this.apiKey = opts.apiKey; this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl; this.fetcher = opts.fetcher; this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n private async requestEnvelope<T>(method: string, path: string): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController(); const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const init: RequestInit = { method, headers: { 'content-type': 'application/json', ...(this.apiKey ? { 'x-api-key': this.apiKey } : {}) }, signal: ctrl.signal };\n const res = this.fetcher ? await this.fetcher(path, init) : await this.fetchImpl(`${this.baseUrl}${path}`, init);\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) throw new ThrottleInvoicesError({ code: json.error?.code ?? 'unknown_error', message: json.error?.message ?? `HTTP ${res.status}`, statusCode: res.status, details: json.error?.details, responseHeaders: res.headers });\n return json;\n } finally { clearTimeout(timer); }\n }\n async list(params: ListInvoicesParams = {}): Promise<PaginatedInvoices> {\n const q = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) if (v !== undefined && v !== null && v !== '') q.set(k, String(v));\n const suffix = q.toString() ? `?${q}` : '';\n const env = await this.requestEnvelope<Invoice[]>('GET', `/api/v1/invoices${suffix}`);\n return { data: env.data ?? [], pagination: env.meta?.pagination ? { cursor: env.meta.pagination.cursor ?? null, hasMore: Boolean(env.meta.pagination.hasMore) } : undefined };\n }\n async get(id: string): Promise<Invoice> {\n const env = await this.requestEnvelope<Invoice>('GET', `/api/v1/invoices/${encodeURIComponent(id)}`);\n return env.data as Invoice;\n }\n async getDownloadUrl(id: string): Promise<string> {\n const env = await this.requestEnvelope<{ url: string }>('GET', `/api/v1/invoices/${encodeURIComponent(id)}/download?format=json`);\n return (env.data as { url: string }).url;\n }\n}\nexport function createInvoicesClient(opts: InvoicesClientOptions): InvoicesClient { return new InvoicesClient(opts); }\n","import { createContext, useCallback, useContext, useMemo, useReducer, type ReactNode } from 'react';\nimport { InvoicesClient } from './client';\nimport type {\n InvoiceFetcher,\n InvoicesProviderProps,\n InvoicesClientContract,\n} from './types';\n\ninterface InvoiceContextValue {\n client: InvoicesClientContract;\n cacheVersion: number;\n invalidate: () => void;\n}\n\nconst InvoiceContext = createContext<InvoiceContextValue | null>(null);\n\nexport function InvoiceProvider({\n children,\n client,\n fetcher,\n baseUrl,\n timeoutMs,\n}: InvoicesProviderProps) {\n const [cacheVersion, invalidate] = useReducer((value: number) => value + 1, 0);\n const resolvedClient = useMemo(() => {\n if (client) return client;\n return new InvoicesClient({\n fetcher: fetcher ?? createInvoiceFetcher('/api/throttle'),\n baseUrl,\n timeoutMs,\n });\n }, [baseUrl, client, fetcher, timeoutMs]);\n\n const value = useMemo(\n () => ({ client: resolvedClient, cacheVersion, invalidate }),\n [cacheVersion, resolvedClient],\n );\n\n return <InvoiceContext.Provider value={value}>{children}</InvoiceContext.Provider>;\n}\n\nexport function useInvoiceClient(): InvoicesClientContract {\n return useInvoiceContext().client;\n}\n\nexport function useInvoiceInvalidation(): () => void {\n return useInvoiceContext().invalidate;\n}\n\nexport function useInvoiceCacheVersion(): number {\n return useInvoiceContext().cacheVersion;\n}\n\nexport function createInvoiceFetcher(basePath: string): InvoiceFetcher {\n const cleanBase = basePath.replace(/\\/+$/, '');\n return (path, init) => {\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return fetch(`${cleanBase}${cleanPath}`, init);\n };\n}\n\nexport function useInvoiceContext(): InvoiceContextValue {\n const ctx = useContext(InvoiceContext);\n if (!ctx) {\n throw new Error(\n '@usethrottle/invoices hooks must be used inside <InvoiceProvider />',\n );\n }\n return ctx;\n}\n\nexport function InvoiceProviderWithClient({\n children,\n client,\n}: {\n children: ReactNode;\n client: InvoicesClientContract;\n}) {\n const [cacheVersion, invalidate] = useReducer((value: number) => value + 1, 0);\n const value = useMemo(() => ({ client, cacheVersion, invalidate }), [cacheVersion, client]);\n return <InvoiceContext.Provider value={value}>{children}</InvoiceContext.Provider>;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n useInvoiceCacheVersion,\n useInvoiceClient,\n} from './provider';\nimport type {\n Invoice,\n ListInvoicesParams,\n PaginatedInvoices,\n QueryOptions,\n QueryState,\n} from './types';\n\nexport function useInvoices(\n params: ListInvoicesParams = {},\n options: QueryOptions<PaginatedInvoices> = {},\n): QueryState<PaginatedInvoices> {\n const client = useInvoiceClient();\n const v = useInvoiceCacheVersion();\n const p = useStableValue(params);\n return useAsyncQuery(() => client.list(p), [client, p, v], options);\n}\n\nexport function useInvoice(\n id: string | null | undefined,\n options: QueryOptions<Invoice> = {},\n): QueryState<Invoice> {\n const client = useInvoiceClient();\n const v = useInvoiceCacheVersion();\n return useAsyncQuery(\n () => (id ? client.get(id) : Promise.resolve(null)),\n [client, id, v],\n { ...options, enabled: options.enabled ?? Boolean(id) },\n );\n}\n\nexport function useDownloadInvoice() {\n const client = useInvoiceClient();\n return async (id: string) => {\n const url = await client.getDownloadUrl(id);\n if (typeof window !== 'undefined') window.open(url, '_blank');\n return url;\n };\n}\n\nfunction useAsyncQuery<T>(\n load: () => Promise<T | null>,\n deps: readonly unknown[],\n options: QueryOptions<T>,\n): QueryState<T> {\n const enabled = options.enabled ?? true;\n const [data, setData] = useState<T | null>(options.initialData ?? null);\n const [error, setError] = useState<unknown>(null);\n const [isLoading, setIsLoading] = useState(enabled && options.initialData === undefined);\n const [isFetching, setIsFetching] = useState(false);\n const loadRef = useRef(load);\n loadRef.current = load;\n\n const refetch = useCallback(async () => {\n if (!enabled) return data;\n setIsFetching(true);\n setError(null);\n try {\n const next = await loadRef.current();\n setData(next);\n return next;\n } catch (err) {\n setError(err);\n throw err;\n } finally {\n setIsFetching(false);\n setIsLoading(false);\n }\n }, [data, enabled]);\n\n useEffect(() => {\n if (!enabled) {\n setIsLoading(false);\n return;\n }\n let cancelled = false;\n setIsFetching(true);\n setError(null);\n load()\n .then((next) => {\n if (!cancelled) setData(next);\n })\n .catch((err) => {\n if (!cancelled) setError(err);\n })\n .finally(() => {\n if (!cancelled) {\n setIsLoading(false);\n setIsFetching(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, ...deps]);\n\n return { data, error, isLoading, isFetching, refetch };\n}\n\nfunction useStableValue<T>(value: T): T {\n const key = JSON.stringify(value);\n return useMemo(() => value, [key]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAAsD;AAMtD,IAAAA,iBAA+C;AALxC,IAAM,wBAAN,cAAoC,4BAAc;AAAA,EACvD,YAAY,MAAwI;AAClJ,UAAM,IAAI;AAAG,SAAK,OAAO;AAAA,EAC3B;AACF;;;ACFO,IAAM,iBAAN,MAAuD;AAAA,EAC3C;AAAA,EAAkC;AAAA,EAClC;AAAA,EAAqD;AAAA,EAA6D;AAAA,EACnI,YAAY,OAA8B,CAAC,GAAG;AAC5C,UAAM,YAAY,KAAK,SAAS,WAAW;AAC3C,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,mCAAmC;AACnE,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,QAAS,OAAM,IAAI,MAAM,+CAA+C;AAClG,SAAK,SAAS,KAAK;AAAQ,SAAK,WAAW,KAAK,WAAW,+BAA+B,QAAQ,QAAQ,EAAE;AAC5G,SAAK,YAAY;AAAW,SAAK,UAAU,KAAK;AAAS,SAAK,YAAY,KAAK,aAAa;AAAA,EAC9F;AAAA,EACA,MAAc,gBAAmB,QAAgB,MAA4C;AAC3F,UAAM,OAAO,IAAI,gBAAgB;AAAG,UAAM,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,SAAS;AAC/F,QAAI;AACF,YAAM,OAAoB,EAAE,QAAQ,SAAS,EAAE,gBAAgB,oBAAoB,GAAI,KAAK,SAAS,EAAE,aAAa,KAAK,OAAO,IAAI,CAAC,EAAG,GAAG,QAAQ,KAAK,OAAO;AAC/J,YAAM,MAAM,KAAK,UAAU,MAAM,KAAK,QAAQ,MAAM,IAAI,IAAI,MAAM,KAAK,UAAU,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI,IAAI;AAC/G,YAAM,OAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC/C,UAAI,CAAC,IAAI,GAAI,OAAM,IAAI,sBAAsB,EAAE,MAAM,KAAK,OAAO,QAAQ,iBAAiB,SAAS,KAAK,OAAO,WAAW,QAAQ,IAAI,MAAM,IAAI,YAAY,IAAI,QAAQ,SAAS,KAAK,OAAO,SAAS,iBAAiB,IAAI,QAAQ,CAAC;AACpO,aAAO;AAAA,IACT,UAAE;AAAU,mBAAa,KAAK;AAAA,IAAG;AAAA,EACnC;AAAA,EACA,MAAM,KAAK,SAA6B,CAAC,GAA+B;AACtE,UAAM,IAAI,IAAI,gBAAgB;AAC9B,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,EAAG,KAAI,MAAM,UAAa,MAAM,QAAQ,MAAM,GAAI,GAAE,IAAI,GAAG,OAAO,CAAC,CAAC;AAC9G,UAAM,SAAS,EAAE,SAAS,IAAI,IAAI,CAAC,KAAK;AACxC,UAAM,MAAM,MAAM,KAAK,gBAA2B,OAAO,mBAAmB,MAAM,EAAE;AACpF,WAAO,EAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,YAAY,IAAI,MAAM,aAAa,EAAE,QAAQ,IAAI,KAAK,WAAW,UAAU,MAAM,SAAS,QAAQ,IAAI,KAAK,WAAW,OAAO,EAAE,IAAI,OAAU;AAAA,EAC9K;AAAA,EACA,MAAM,IAAI,IAA8B;AACtC,UAAM,MAAM,MAAM,KAAK,gBAAyB,OAAO,oBAAoB,mBAAmB,EAAE,CAAC,EAAE;AACnG,WAAO,IAAI;AAAA,EACb;AAAA,EACA,MAAM,eAAe,IAA6B;AAChD,UAAM,MAAM,MAAM,KAAK,gBAAiC,OAAO,oBAAoB,mBAAmB,EAAE,CAAC,uBAAuB;AAChI,WAAQ,IAAI,KAAyB;AAAA,EACvC;AACF;AACO,SAAS,qBAAqB,MAA6C;AAAE,SAAO,IAAI,eAAe,IAAI;AAAG;;;ACvCrH,mBAA4F;AAsCnF;AAxBT,IAAM,qBAAiB,4BAA0C,IAAI;AAE9D,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,CAAC,cAAc,UAAU,QAAI,yBAAW,CAACC,WAAkBA,SAAQ,GAAG,CAAC;AAC7E,QAAM,qBAAiB,sBAAQ,MAAM;AACnC,QAAI,OAAQ,QAAO;AACnB,WAAO,IAAI,eAAe;AAAA,MACxB,SAAS,WAAW,qBAAqB,eAAe;AAAA,MACxD;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,SAAS,QAAQ,SAAS,SAAS,CAAC;AAExC,QAAM,YAAQ;AAAA,IACZ,OAAO,EAAE,QAAQ,gBAAgB,cAAc,WAAW;AAAA,IAC1D,CAAC,cAAc,cAAc;AAAA,EAC/B;AAEA,SAAO,4CAAC,eAAe,UAAf,EAAwB,OAAe,UAAS;AAC1D;AAEO,SAAS,mBAA2C;AACzD,SAAO,kBAAkB,EAAE;AAC7B;AAEO,SAAS,yBAAqC;AACnD,SAAO,kBAAkB,EAAE;AAC7B;AAEO,SAAS,yBAAiC;AAC/C,SAAO,kBAAkB,EAAE;AAC7B;AAEO,SAAS,qBAAqB,UAAkC;AACrE,QAAM,YAAY,SAAS,QAAQ,QAAQ,EAAE;AAC7C,SAAO,CAAC,MAAM,SAAS;AACrB,UAAM,YAAY,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AACxD,WAAO,MAAM,GAAG,SAAS,GAAG,SAAS,IAAI,IAAI;AAAA,EAC/C;AACF;AAEO,SAAS,oBAAyC;AACvD,QAAM,UAAM,yBAAW,cAAc;AACrC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACrEA,IAAAC,gBAAkE;AAa3D,SAAS,YACd,SAA6B,CAAC,GAC9B,UAA2C,CAAC,GACb;AAC/B,QAAM,SAAS,iBAAiB;AAChC,QAAM,IAAI,uBAAuB;AACjC,QAAM,IAAI,eAAe,MAAM;AAC/B,SAAO,cAAc,MAAM,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,GAAG,OAAO;AACpE;AAEO,SAAS,WACd,IACA,UAAiC,CAAC,GACb;AACrB,QAAM,SAAS,iBAAiB;AAChC,QAAM,IAAI,uBAAuB;AACjC,SAAO;AAAA,IACL,MAAO,KAAK,OAAO,IAAI,EAAE,IAAI,QAAQ,QAAQ,IAAI;AAAA,IACjD,CAAC,QAAQ,IAAI,CAAC;AAAA,IACd,EAAE,GAAG,SAAS,SAAS,QAAQ,WAAW,QAAQ,EAAE,EAAE;AAAA,EACxD;AACF;AAEO,SAAS,qBAAqB;AACnC,QAAM,SAAS,iBAAiB;AAChC,SAAO,OAAO,OAAe;AAC3B,UAAM,MAAM,MAAM,OAAO,eAAe,EAAE;AAC1C,QAAI,OAAO,WAAW,YAAa,QAAO,KAAK,KAAK,QAAQ;AAC5D,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cACP,MACA,MACA,SACe;AACf,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAmB,QAAQ,eAAe,IAAI;AACtE,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAkB,IAAI;AAChD,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAS,WAAW,QAAQ,gBAAgB,MAAS;AACvF,QAAM,CAAC,YAAY,aAAa,QAAI,wBAAS,KAAK;AAClD,QAAM,cAAU,sBAAO,IAAI;AAC3B,UAAQ,UAAU;AAElB,QAAM,cAAU,2BAAY,YAAY;AACtC,QAAI,CAAC,QAAS,QAAO;AACrB,kBAAc,IAAI;AAClB,aAAS,IAAI;AACb,QAAI;AACF,YAAM,OAAO,MAAM,QAAQ,QAAQ;AACnC,cAAQ,IAAI;AACZ,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,eAAS,GAAG;AACZ,YAAM;AAAA,IACR,UAAE;AACA,oBAAc,KAAK;AACnB,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,OAAO,CAAC;AAElB,+BAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ,mBAAa,KAAK;AAClB;AAAA,IACF;AACA,QAAI,YAAY;AAChB,kBAAc,IAAI;AAClB,aAAS,IAAI;AACb,SAAK,EACF,KAAK,CAAC,SAAS;AACd,UAAI,CAAC,UAAW,SAAQ,IAAI;AAAA,IAC9B,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,UAAI,CAAC,UAAW,UAAS,GAAG;AAAA,IAC9B,CAAC,EACA,QAAQ,MAAM;AACb,UAAI,CAAC,WAAW;AACd,qBAAa,KAAK;AAClB,sBAAc,KAAK;AAAA,MACrB;AAAA,IACF,CAAC;AAEH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EAEF,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;AAErB,SAAO,EAAE,MAAM,OAAO,WAAW,YAAY,QAAQ;AACvD;AAEA,SAAS,eAAkB,OAAa;AACtC,QAAM,MAAM,KAAK,UAAU,KAAK;AAChC,aAAO,uBAAQ,MAAM,OAAO,CAAC,GAAG,CAAC;AACnC;","names":["import_errors","value","import_react"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { ThrottleError } from '@usethrottle/errors';
2
+ import { ThrottleError, ThrottleErrorArgs } from '@usethrottle/errors';
3
3
  export { ThrottleError, isThrottleError } from '@usethrottle/errors';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
 
@@ -104,6 +104,7 @@ declare class ThrottleInvoicesError extends ThrottleError {
104
104
  message: string;
105
105
  statusCode: number;
106
106
  details?: unknown;
107
+ responseHeaders?: ThrottleErrorArgs['responseHeaders'];
107
108
  });
108
109
  }
109
110
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { ThrottleError } from '@usethrottle/errors';
2
+ import { ThrottleError, ThrottleErrorArgs } from '@usethrottle/errors';
3
3
  export { ThrottleError, isThrottleError } from '@usethrottle/errors';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
 
@@ -104,6 +104,7 @@ declare class ThrottleInvoicesError extends ThrottleError {
104
104
  message: string;
105
105
  statusCode: number;
106
106
  details?: unknown;
107
+ responseHeaders?: ThrottleErrorArgs['responseHeaders'];
107
108
  });
108
109
  }
109
110
 
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ var InvoicesClient = class {
32
32
  const init = { method, headers: { "content-type": "application/json", ...this.apiKey ? { "x-api-key": this.apiKey } : {} }, signal: ctrl.signal };
33
33
  const res = this.fetcher ? await this.fetcher(path, init) : await this.fetchImpl(`${this.baseUrl}${path}`, init);
34
34
  const json = await res.json().catch(() => ({}));
35
- if (!res.ok) throw new ThrottleInvoicesError({ code: json.error?.code ?? "unknown_error", message: json.error?.message ?? `HTTP ${res.status}`, statusCode: res.status, details: json.error?.details });
35
+ if (!res.ok) throw new ThrottleInvoicesError({ code: json.error?.code ?? "unknown_error", message: json.error?.message ?? `HTTP ${res.status}`, statusCode: res.status, details: json.error?.details, responseHeaders: res.headers });
36
36
  return json;
37
37
  } finally {
38
38
  clearTimeout(timer);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/client.ts","../src/provider.tsx","../src/hooks.ts"],"sourcesContent":["import { ThrottleError } from '@usethrottle/errors';\nexport class ThrottleInvoicesError extends ThrottleError {\n constructor(args: { code: string; message: string; statusCode: number; details?: unknown }) {\n super(args); this.name = 'ThrottleInvoicesError';\n }\n}\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n","import { ThrottleInvoicesError } from './errors';\nimport type { Invoice, InvoicesClientContract, InvoicesClientOptions, ListInvoicesParams, PaginatedInvoices, ThrottleEnvelope } from './types';\n\nexport class InvoicesClient implements InvoicesClientContract {\n private readonly apiKey?: string; private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch; private readonly fetcher?: InvoicesClientOptions['fetcher']; private readonly timeoutMs: number;\n constructor(opts: InvoicesClientOptions = {}) {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('InvoicesClient: fetch is required');\n if (!opts.apiKey && !opts.fetcher) throw new Error('InvoicesClient: apiKey or fetcher is required');\n this.apiKey = opts.apiKey; this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl; this.fetcher = opts.fetcher; this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n private async requestEnvelope<T>(method: string, path: string): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController(); const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const init: RequestInit = { method, headers: { 'content-type': 'application/json', ...(this.apiKey ? { 'x-api-key': this.apiKey } : {}) }, signal: ctrl.signal };\n const res = this.fetcher ? await this.fetcher(path, init) : await this.fetchImpl(`${this.baseUrl}${path}`, init);\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) throw new ThrottleInvoicesError({ code: json.error?.code ?? 'unknown_error', message: json.error?.message ?? `HTTP ${res.status}`, statusCode: res.status, details: json.error?.details });\n return json;\n } finally { clearTimeout(timer); }\n }\n async list(params: ListInvoicesParams = {}): Promise<PaginatedInvoices> {\n const q = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) if (v !== undefined && v !== null && v !== '') q.set(k, String(v));\n const suffix = q.toString() ? `?${q}` : '';\n const env = await this.requestEnvelope<Invoice[]>('GET', `/api/v1/invoices${suffix}`);\n return { data: env.data ?? [], pagination: env.meta?.pagination ? { cursor: env.meta.pagination.cursor ?? null, hasMore: Boolean(env.meta.pagination.hasMore) } : undefined };\n }\n async get(id: string): Promise<Invoice> {\n const env = await this.requestEnvelope<Invoice>('GET', `/api/v1/invoices/${encodeURIComponent(id)}`);\n return env.data as Invoice;\n }\n async getDownloadUrl(id: string): Promise<string> {\n const env = await this.requestEnvelope<{ url: string }>('GET', `/api/v1/invoices/${encodeURIComponent(id)}/download?format=json`);\n return (env.data as { url: string }).url;\n }\n}\nexport function createInvoicesClient(opts: InvoicesClientOptions): InvoicesClient { return new InvoicesClient(opts); }\n","import { createContext, useCallback, useContext, useMemo, useReducer, type ReactNode } from 'react';\nimport { InvoicesClient } from './client';\nimport type {\n InvoiceFetcher,\n InvoicesProviderProps,\n InvoicesClientContract,\n} from './types';\n\ninterface InvoiceContextValue {\n client: InvoicesClientContract;\n cacheVersion: number;\n invalidate: () => void;\n}\n\nconst InvoiceContext = createContext<InvoiceContextValue | null>(null);\n\nexport function InvoiceProvider({\n children,\n client,\n fetcher,\n baseUrl,\n timeoutMs,\n}: InvoicesProviderProps) {\n const [cacheVersion, invalidate] = useReducer((value: number) => value + 1, 0);\n const resolvedClient = useMemo(() => {\n if (client) return client;\n return new InvoicesClient({\n fetcher: fetcher ?? createInvoiceFetcher('/api/throttle'),\n baseUrl,\n timeoutMs,\n });\n }, [baseUrl, client, fetcher, timeoutMs]);\n\n const value = useMemo(\n () => ({ client: resolvedClient, cacheVersion, invalidate }),\n [cacheVersion, resolvedClient],\n );\n\n return <InvoiceContext.Provider value={value}>{children}</InvoiceContext.Provider>;\n}\n\nexport function useInvoiceClient(): InvoicesClientContract {\n return useInvoiceContext().client;\n}\n\nexport function useInvoiceInvalidation(): () => void {\n return useInvoiceContext().invalidate;\n}\n\nexport function useInvoiceCacheVersion(): number {\n return useInvoiceContext().cacheVersion;\n}\n\nexport function createInvoiceFetcher(basePath: string): InvoiceFetcher {\n const cleanBase = basePath.replace(/\\/+$/, '');\n return (path, init) => {\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return fetch(`${cleanBase}${cleanPath}`, init);\n };\n}\n\nexport function useInvoiceContext(): InvoiceContextValue {\n const ctx = useContext(InvoiceContext);\n if (!ctx) {\n throw new Error(\n '@usethrottle/invoices hooks must be used inside <InvoiceProvider />',\n );\n }\n return ctx;\n}\n\nexport function InvoiceProviderWithClient({\n children,\n client,\n}: {\n children: ReactNode;\n client: InvoicesClientContract;\n}) {\n const [cacheVersion, invalidate] = useReducer((value: number) => value + 1, 0);\n const value = useMemo(() => ({ client, cacheVersion, invalidate }), [cacheVersion, client]);\n return <InvoiceContext.Provider value={value}>{children}</InvoiceContext.Provider>;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n useInvoiceCacheVersion,\n useInvoiceClient,\n} from './provider';\nimport type {\n Invoice,\n ListInvoicesParams,\n PaginatedInvoices,\n QueryOptions,\n QueryState,\n} from './types';\n\nexport function useInvoices(\n params: ListInvoicesParams = {},\n options: QueryOptions<PaginatedInvoices> = {},\n): QueryState<PaginatedInvoices> {\n const client = useInvoiceClient();\n const v = useInvoiceCacheVersion();\n const p = useStableValue(params);\n return useAsyncQuery(() => client.list(p), [client, p, v], options);\n}\n\nexport function useInvoice(\n id: string | null | undefined,\n options: QueryOptions<Invoice> = {},\n): QueryState<Invoice> {\n const client = useInvoiceClient();\n const v = useInvoiceCacheVersion();\n return useAsyncQuery(\n () => (id ? client.get(id) : Promise.resolve(null)),\n [client, id, v],\n { ...options, enabled: options.enabled ?? Boolean(id) },\n );\n}\n\nexport function useDownloadInvoice() {\n const client = useInvoiceClient();\n return async (id: string) => {\n const url = await client.getDownloadUrl(id);\n if (typeof window !== 'undefined') window.open(url, '_blank');\n return url;\n };\n}\n\nfunction useAsyncQuery<T>(\n load: () => Promise<T | null>,\n deps: readonly unknown[],\n options: QueryOptions<T>,\n): QueryState<T> {\n const enabled = options.enabled ?? true;\n const [data, setData] = useState<T | null>(options.initialData ?? null);\n const [error, setError] = useState<unknown>(null);\n const [isLoading, setIsLoading] = useState(enabled && options.initialData === undefined);\n const [isFetching, setIsFetching] = useState(false);\n const loadRef = useRef(load);\n loadRef.current = load;\n\n const refetch = useCallback(async () => {\n if (!enabled) return data;\n setIsFetching(true);\n setError(null);\n try {\n const next = await loadRef.current();\n setData(next);\n return next;\n } catch (err) {\n setError(err);\n throw err;\n } finally {\n setIsFetching(false);\n setIsLoading(false);\n }\n }, [data, enabled]);\n\n useEffect(() => {\n if (!enabled) {\n setIsLoading(false);\n return;\n }\n let cancelled = false;\n setIsFetching(true);\n setError(null);\n load()\n .then((next) => {\n if (!cancelled) setData(next);\n })\n .catch((err) => {\n if (!cancelled) setError(err);\n })\n .finally(() => {\n if (!cancelled) {\n setIsLoading(false);\n setIsFetching(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, ...deps]);\n\n return { data, error, isLoading, isFetching, refetch };\n}\n\nfunction useStableValue<T>(value: T): T {\n const key = JSON.stringify(value);\n return useMemo(() => value, [key]);\n}\n"],"mappings":"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","names":["ThrottleError","value","useCallback","useMemo","useCallback","useMemo"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/client.ts","../src/provider.tsx","../src/hooks.ts"],"sourcesContent":["import { ThrottleError, type ThrottleErrorArgs } from '@usethrottle/errors';\nexport class ThrottleInvoicesError extends ThrottleError {\n constructor(args: { code: string; message: string; statusCode: number; details?: unknown; responseHeaders?: ThrottleErrorArgs['responseHeaders'] }) {\n super(args); this.name = 'ThrottleInvoicesError';\n }\n}\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n","import { ThrottleInvoicesError } from './errors';\nimport type { Invoice, InvoicesClientContract, InvoicesClientOptions, ListInvoicesParams, PaginatedInvoices, ThrottleEnvelope } from './types';\n\nexport class InvoicesClient implements InvoicesClientContract {\n private readonly apiKey?: string; private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch; private readonly fetcher?: InvoicesClientOptions['fetcher']; private readonly timeoutMs: number;\n constructor(opts: InvoicesClientOptions = {}) {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('InvoicesClient: fetch is required');\n if (!opts.apiKey && !opts.fetcher) throw new Error('InvoicesClient: apiKey or fetcher is required');\n this.apiKey = opts.apiKey; this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl; this.fetcher = opts.fetcher; this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n private async requestEnvelope<T>(method: string, path: string): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController(); const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const init: RequestInit = { method, headers: { 'content-type': 'application/json', ...(this.apiKey ? { 'x-api-key': this.apiKey } : {}) }, signal: ctrl.signal };\n const res = this.fetcher ? await this.fetcher(path, init) : await this.fetchImpl(`${this.baseUrl}${path}`, init);\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) throw new ThrottleInvoicesError({ code: json.error?.code ?? 'unknown_error', message: json.error?.message ?? `HTTP ${res.status}`, statusCode: res.status, details: json.error?.details, responseHeaders: res.headers });\n return json;\n } finally { clearTimeout(timer); }\n }\n async list(params: ListInvoicesParams = {}): Promise<PaginatedInvoices> {\n const q = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) if (v !== undefined && v !== null && v !== '') q.set(k, String(v));\n const suffix = q.toString() ? `?${q}` : '';\n const env = await this.requestEnvelope<Invoice[]>('GET', `/api/v1/invoices${suffix}`);\n return { data: env.data ?? [], pagination: env.meta?.pagination ? { cursor: env.meta.pagination.cursor ?? null, hasMore: Boolean(env.meta.pagination.hasMore) } : undefined };\n }\n async get(id: string): Promise<Invoice> {\n const env = await this.requestEnvelope<Invoice>('GET', `/api/v1/invoices/${encodeURIComponent(id)}`);\n return env.data as Invoice;\n }\n async getDownloadUrl(id: string): Promise<string> {\n const env = await this.requestEnvelope<{ url: string }>('GET', `/api/v1/invoices/${encodeURIComponent(id)}/download?format=json`);\n return (env.data as { url: string }).url;\n }\n}\nexport function createInvoicesClient(opts: InvoicesClientOptions): InvoicesClient { return new InvoicesClient(opts); }\n","import { createContext, useCallback, useContext, useMemo, useReducer, type ReactNode } from 'react';\nimport { InvoicesClient } from './client';\nimport type {\n InvoiceFetcher,\n InvoicesProviderProps,\n InvoicesClientContract,\n} from './types';\n\ninterface InvoiceContextValue {\n client: InvoicesClientContract;\n cacheVersion: number;\n invalidate: () => void;\n}\n\nconst InvoiceContext = createContext<InvoiceContextValue | null>(null);\n\nexport function InvoiceProvider({\n children,\n client,\n fetcher,\n baseUrl,\n timeoutMs,\n}: InvoicesProviderProps) {\n const [cacheVersion, invalidate] = useReducer((value: number) => value + 1, 0);\n const resolvedClient = useMemo(() => {\n if (client) return client;\n return new InvoicesClient({\n fetcher: fetcher ?? createInvoiceFetcher('/api/throttle'),\n baseUrl,\n timeoutMs,\n });\n }, [baseUrl, client, fetcher, timeoutMs]);\n\n const value = useMemo(\n () => ({ client: resolvedClient, cacheVersion, invalidate }),\n [cacheVersion, resolvedClient],\n );\n\n return <InvoiceContext.Provider value={value}>{children}</InvoiceContext.Provider>;\n}\n\nexport function useInvoiceClient(): InvoicesClientContract {\n return useInvoiceContext().client;\n}\n\nexport function useInvoiceInvalidation(): () => void {\n return useInvoiceContext().invalidate;\n}\n\nexport function useInvoiceCacheVersion(): number {\n return useInvoiceContext().cacheVersion;\n}\n\nexport function createInvoiceFetcher(basePath: string): InvoiceFetcher {\n const cleanBase = basePath.replace(/\\/+$/, '');\n return (path, init) => {\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return fetch(`${cleanBase}${cleanPath}`, init);\n };\n}\n\nexport function useInvoiceContext(): InvoiceContextValue {\n const ctx = useContext(InvoiceContext);\n if (!ctx) {\n throw new Error(\n '@usethrottle/invoices hooks must be used inside <InvoiceProvider />',\n );\n }\n return ctx;\n}\n\nexport function InvoiceProviderWithClient({\n children,\n client,\n}: {\n children: ReactNode;\n client: InvoicesClientContract;\n}) {\n const [cacheVersion, invalidate] = useReducer((value: number) => value + 1, 0);\n const value = useMemo(() => ({ client, cacheVersion, invalidate }), [cacheVersion, client]);\n return <InvoiceContext.Provider value={value}>{children}</InvoiceContext.Provider>;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n useInvoiceCacheVersion,\n useInvoiceClient,\n} from './provider';\nimport type {\n Invoice,\n ListInvoicesParams,\n PaginatedInvoices,\n QueryOptions,\n QueryState,\n} from './types';\n\nexport function useInvoices(\n params: ListInvoicesParams = {},\n options: QueryOptions<PaginatedInvoices> = {},\n): QueryState<PaginatedInvoices> {\n const client = useInvoiceClient();\n const v = useInvoiceCacheVersion();\n const p = useStableValue(params);\n return useAsyncQuery(() => client.list(p), [client, p, v], options);\n}\n\nexport function useInvoice(\n id: string | null | undefined,\n options: QueryOptions<Invoice> = {},\n): QueryState<Invoice> {\n const client = useInvoiceClient();\n const v = useInvoiceCacheVersion();\n return useAsyncQuery(\n () => (id ? client.get(id) : Promise.resolve(null)),\n [client, id, v],\n { ...options, enabled: options.enabled ?? Boolean(id) },\n );\n}\n\nexport function useDownloadInvoice() {\n const client = useInvoiceClient();\n return async (id: string) => {\n const url = await client.getDownloadUrl(id);\n if (typeof window !== 'undefined') window.open(url, '_blank');\n return url;\n };\n}\n\nfunction useAsyncQuery<T>(\n load: () => Promise<T | null>,\n deps: readonly unknown[],\n options: QueryOptions<T>,\n): QueryState<T> {\n const enabled = options.enabled ?? true;\n const [data, setData] = useState<T | null>(options.initialData ?? null);\n const [error, setError] = useState<unknown>(null);\n const [isLoading, setIsLoading] = useState(enabled && options.initialData === undefined);\n const [isFetching, setIsFetching] = useState(false);\n const loadRef = useRef(load);\n loadRef.current = load;\n\n const refetch = useCallback(async () => {\n if (!enabled) return data;\n setIsFetching(true);\n setError(null);\n try {\n const next = await loadRef.current();\n setData(next);\n return next;\n } catch (err) {\n setError(err);\n throw err;\n } finally {\n setIsFetching(false);\n setIsLoading(false);\n }\n }, [data, enabled]);\n\n useEffect(() => {\n if (!enabled) {\n setIsLoading(false);\n return;\n }\n let cancelled = false;\n setIsFetching(true);\n setError(null);\n load()\n .then((next) => {\n if (!cancelled) setData(next);\n })\n .catch((err) => {\n if (!cancelled) setError(err);\n })\n .finally(() => {\n if (!cancelled) {\n setIsLoading(false);\n setIsFetching(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, ...deps]);\n\n return { data, error, isLoading, isFetching, refetch };\n}\n\nfunction useStableValue<T>(value: T): T {\n const key = JSON.stringify(value);\n return useMemo(() => value, [key]);\n}\n"],"mappings":";AAAA,SAAS,qBAA6C;AAMtD,SAAS,iBAAAA,gBAAe,uBAAuB;AALxC,IAAM,wBAAN,cAAoC,cAAc;AAAA,EACvD,YAAY,MAAwI;AAClJ,UAAM,IAAI;AAAG,SAAK,OAAO;AAAA,EAC3B;AACF;;;ACFO,IAAM,iBAAN,MAAuD;AAAA,EAC3C;AAAA,EAAkC;AAAA,EAClC;AAAA,EAAqD;AAAA,EAA6D;AAAA,EACnI,YAAY,OAA8B,CAAC,GAAG;AAC5C,UAAM,YAAY,KAAK,SAAS,WAAW;AAC3C,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,mCAAmC;AACnE,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,QAAS,OAAM,IAAI,MAAM,+CAA+C;AAClG,SAAK,SAAS,KAAK;AAAQ,SAAK,WAAW,KAAK,WAAW,+BAA+B,QAAQ,QAAQ,EAAE;AAC5G,SAAK,YAAY;AAAW,SAAK,UAAU,KAAK;AAAS,SAAK,YAAY,KAAK,aAAa;AAAA,EAC9F;AAAA,EACA,MAAc,gBAAmB,QAAgB,MAA4C;AAC3F,UAAM,OAAO,IAAI,gBAAgB;AAAG,UAAM,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,SAAS;AAC/F,QAAI;AACF,YAAM,OAAoB,EAAE,QAAQ,SAAS,EAAE,gBAAgB,oBAAoB,GAAI,KAAK,SAAS,EAAE,aAAa,KAAK,OAAO,IAAI,CAAC,EAAG,GAAG,QAAQ,KAAK,OAAO;AAC/J,YAAM,MAAM,KAAK,UAAU,MAAM,KAAK,QAAQ,MAAM,IAAI,IAAI,MAAM,KAAK,UAAU,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI,IAAI;AAC/G,YAAM,OAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC/C,UAAI,CAAC,IAAI,GAAI,OAAM,IAAI,sBAAsB,EAAE,MAAM,KAAK,OAAO,QAAQ,iBAAiB,SAAS,KAAK,OAAO,WAAW,QAAQ,IAAI,MAAM,IAAI,YAAY,IAAI,QAAQ,SAAS,KAAK,OAAO,SAAS,iBAAiB,IAAI,QAAQ,CAAC;AACpO,aAAO;AAAA,IACT,UAAE;AAAU,mBAAa,KAAK;AAAA,IAAG;AAAA,EACnC;AAAA,EACA,MAAM,KAAK,SAA6B,CAAC,GAA+B;AACtE,UAAM,IAAI,IAAI,gBAAgB;AAC9B,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,EAAG,KAAI,MAAM,UAAa,MAAM,QAAQ,MAAM,GAAI,GAAE,IAAI,GAAG,OAAO,CAAC,CAAC;AAC9G,UAAM,SAAS,EAAE,SAAS,IAAI,IAAI,CAAC,KAAK;AACxC,UAAM,MAAM,MAAM,KAAK,gBAA2B,OAAO,mBAAmB,MAAM,EAAE;AACpF,WAAO,EAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,YAAY,IAAI,MAAM,aAAa,EAAE,QAAQ,IAAI,KAAK,WAAW,UAAU,MAAM,SAAS,QAAQ,IAAI,KAAK,WAAW,OAAO,EAAE,IAAI,OAAU;AAAA,EAC9K;AAAA,EACA,MAAM,IAAI,IAA8B;AACtC,UAAM,MAAM,MAAM,KAAK,gBAAyB,OAAO,oBAAoB,mBAAmB,EAAE,CAAC,EAAE;AACnG,WAAO,IAAI;AAAA,EACb;AAAA,EACA,MAAM,eAAe,IAA6B;AAChD,UAAM,MAAM,MAAM,KAAK,gBAAiC,OAAO,oBAAoB,mBAAmB,EAAE,CAAC,uBAAuB;AAChI,WAAQ,IAAI,KAAyB;AAAA,EACvC;AACF;AACO,SAAS,qBAAqB,MAA6C;AAAE,SAAO,IAAI,eAAe,IAAI;AAAG;;;ACvCrH,SAAS,eAA4B,YAAY,SAAS,kBAAkC;AAsCnF;AAxBT,IAAM,iBAAiB,cAA0C,IAAI;AAE9D,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,CAAC,cAAc,UAAU,IAAI,WAAW,CAACC,WAAkBA,SAAQ,GAAG,CAAC;AAC7E,QAAM,iBAAiB,QAAQ,MAAM;AACnC,QAAI,OAAQ,QAAO;AACnB,WAAO,IAAI,eAAe;AAAA,MACxB,SAAS,WAAW,qBAAqB,eAAe;AAAA,MACxD;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,SAAS,QAAQ,SAAS,SAAS,CAAC;AAExC,QAAM,QAAQ;AAAA,IACZ,OAAO,EAAE,QAAQ,gBAAgB,cAAc,WAAW;AAAA,IAC1D,CAAC,cAAc,cAAc;AAAA,EAC/B;AAEA,SAAO,oBAAC,eAAe,UAAf,EAAwB,OAAe,UAAS;AAC1D;AAEO,SAAS,mBAA2C;AACzD,SAAO,kBAAkB,EAAE;AAC7B;AAEO,SAAS,yBAAqC;AACnD,SAAO,kBAAkB,EAAE;AAC7B;AAEO,SAAS,yBAAiC;AAC/C,SAAO,kBAAkB,EAAE;AAC7B;AAEO,SAAS,qBAAqB,UAAkC;AACrE,QAAM,YAAY,SAAS,QAAQ,QAAQ,EAAE;AAC7C,SAAO,CAAC,MAAM,SAAS;AACrB,UAAM,YAAY,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AACxD,WAAO,MAAM,GAAG,SAAS,GAAG,SAAS,IAAI,IAAI;AAAA,EAC/C;AACF;AAEO,SAAS,oBAAyC;AACvD,QAAM,MAAM,WAAW,cAAc;AACrC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACrEA,SAAS,eAAAC,cAAa,WAAW,WAAAC,UAAS,QAAQ,gBAAgB;AAa3D,SAAS,YACd,SAA6B,CAAC,GAC9B,UAA2C,CAAC,GACb;AAC/B,QAAM,SAAS,iBAAiB;AAChC,QAAM,IAAI,uBAAuB;AACjC,QAAM,IAAI,eAAe,MAAM;AAC/B,SAAO,cAAc,MAAM,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,GAAG,OAAO;AACpE;AAEO,SAAS,WACd,IACA,UAAiC,CAAC,GACb;AACrB,QAAM,SAAS,iBAAiB;AAChC,QAAM,IAAI,uBAAuB;AACjC,SAAO;AAAA,IACL,MAAO,KAAK,OAAO,IAAI,EAAE,IAAI,QAAQ,QAAQ,IAAI;AAAA,IACjD,CAAC,QAAQ,IAAI,CAAC;AAAA,IACd,EAAE,GAAG,SAAS,SAAS,QAAQ,WAAW,QAAQ,EAAE,EAAE;AAAA,EACxD;AACF;AAEO,SAAS,qBAAqB;AACnC,QAAM,SAAS,iBAAiB;AAChC,SAAO,OAAO,OAAe;AAC3B,UAAM,MAAM,MAAM,OAAO,eAAe,EAAE;AAC1C,QAAI,OAAO,WAAW,YAAa,QAAO,KAAK,KAAK,QAAQ;AAC5D,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cACP,MACA,MACA,SACe;AACf,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAmB,QAAQ,eAAe,IAAI;AACtE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAkB,IAAI;AAChD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,WAAW,QAAQ,gBAAgB,MAAS;AACvF,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,UAAU,OAAO,IAAI;AAC3B,UAAQ,UAAU;AAElB,QAAM,UAAUC,aAAY,YAAY;AACtC,QAAI,CAAC,QAAS,QAAO;AACrB,kBAAc,IAAI;AAClB,aAAS,IAAI;AACb,QAAI;AACF,YAAM,OAAO,MAAM,QAAQ,QAAQ;AACnC,cAAQ,IAAI;AACZ,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,eAAS,GAAG;AACZ,YAAM;AAAA,IACR,UAAE;AACA,oBAAc,KAAK;AACnB,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,OAAO,CAAC;AAElB,YAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ,mBAAa,KAAK;AAClB;AAAA,IACF;AACA,QAAI,YAAY;AAChB,kBAAc,IAAI;AAClB,aAAS,IAAI;AACb,SAAK,EACF,KAAK,CAAC,SAAS;AACd,UAAI,CAAC,UAAW,SAAQ,IAAI;AAAA,IAC9B,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,UAAI,CAAC,UAAW,UAAS,GAAG;AAAA,IAC9B,CAAC,EACA,QAAQ,MAAM;AACb,UAAI,CAAC,WAAW;AACd,qBAAa,KAAK;AAClB,sBAAc,KAAK;AAAA,MACrB;AAAA,IACF,CAAC;AAEH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EAEF,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;AAErB,SAAO,EAAE,MAAM,OAAO,WAAW,YAAY,QAAQ;AACvD;AAEA,SAAS,eAAkB,OAAa;AACtC,QAAM,MAAM,KAAK,UAAU,KAAK;AAChC,SAAOC,SAAQ,MAAM,OAAO,CAAC,GAAG,CAAC;AACnC;","names":["ThrottleError","value","useCallback","useMemo","useCallback","useMemo"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usethrottle/invoices",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "React hooks + server proxy for Throttle customer invoices.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "README.md"
24
24
  ],
25
25
  "dependencies": {
26
- "@usethrottle/errors": "^1.0.0"
26
+ "@usethrottle/errors": "^1.1.0"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "react": ">=18"