@brickflow/http 0.0.20 → 0.0.22

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/README.md CHANGED
@@ -236,6 +236,61 @@ products: createGet<{
236
236
  }>()('/products')
237
237
  ```
238
238
 
239
+ Path-параметры можно передавать тем же объектом `params`:
240
+
241
+ ```ts
242
+ productOne: createGet<{
243
+ productId: number
244
+ }>()('/products/:productId')
245
+ ```
246
+
247
+ При вызове `productId` будет подставлен в URL, а не уйдёт в query string:
248
+
249
+ ```ts
250
+ const productHttp = await app.$di.product.productOne({
251
+ lazy: true,
252
+ })
253
+
254
+ await productHttp.fetch({
255
+ productId: 3,
256
+ })
257
+ ```
258
+
259
+ Если generic не передан, `:segment` автоматически типизируется как `string`:
260
+
261
+ ```ts
262
+ productOne: createGet()('/products/:productId')
263
+ ```
264
+
265
+ Если generic передан, path params мерджатся с ним:
266
+
267
+ ```ts
268
+ productOne: createGet<{
269
+ test: number
270
+ }>()('/products/:productId')
271
+ ```
272
+
273
+ В этом случае тип params будет таким:
274
+
275
+ ```ts
276
+ {
277
+ productId: string
278
+ test: number
279
+ }
280
+ ```
281
+
282
+ Path params нужно передавать явно:
283
+
284
+ ```ts
285
+ const productHttp = await app.$di.product.productOne({
286
+ lazy: true,
287
+ })
288
+
289
+ await productHttp.fetch({
290
+ productId: '3',
291
+ })
292
+ ```
293
+
239
294
  Если нужно явно переопределить тип ответа для конкретного endpoint-а, можно добавить ещё один generic-слой:
240
295
 
241
296
  ```ts
@@ -1,8 +1,7 @@
1
1
  import type { HttpClient, HttpKey, HttpParam, HttpResponseData } from './http';
2
2
  import type { HttpError, UseHttpFn, UseHttpOptions, UseHttpResult } from './nuxt';
3
3
  export interface CreateGetFactory<P extends HttpParam> {
4
- <T extends HttpKey>(url: T, payload?: CreateGetPayload<T, P>): (options?: CreateGetOptions<T, P>) => Promise<CreateGetResult<T, P>>;
5
- <D>(url: HttpKey, payload?: CreateGetPayload<HttpKey, P, D>): (options?: CreateGetOptions<HttpKey, P, D>) => Promise<CreateGetResult<HttpKey, P, D>>;
4
+ <D = never, T extends HttpKey = HttpKey>(url: T, payload?: CreateGetPayload<T, CreateGetParams<T, P>, D>): (options?: CreateGetOptions<T, CreateGetParams<T, P>, D>) => Promise<CreateGetResult<T, CreateGetParams<T, P>, D>>;
6
5
  }
7
6
  export type CreateGetOptions<T extends HttpKey, P extends HttpParam, D = never> = Omit<UseHttpOptions<T, P>, 'effect' | 'isError' | 'url'> & {
8
7
  effect?: CreateGetEffect<T, P, D>;
@@ -23,12 +22,18 @@ type CreateGetEffectConfig<P extends HttpParam> = {
23
22
  cached: boolean;
24
23
  params: P;
25
24
  };
25
+ type CreateGetEmptyParams = Record<never, never>;
26
26
  type CreateGetIsError<T extends HttpKey, D = never> = (payload: CreateGetData<T, D>) => boolean;
27
+ type CreateGetParamKeys<T extends string> = T extends `${string}:${infer Rest}` ? Rest extends `${infer Key}/${infer Tail}` ? CreateGetParamKeys<`/${Tail}`> | Key : Rest : never;
28
+ type CreateGetParams<T extends HttpKey, P extends HttpParam> = Omit<CreateGetPathParams<T>, keyof P> & P;
29
+ type CreateGetPathParams<T extends HttpKey> = [CreateGetParamKeys<T>] extends [never] ? CreateGetEmptyParams : {
30
+ [K in CreateGetParamKeys<T>]: string;
31
+ };
27
32
  export declare function createUseCase<D>(): <T>(callback: (payload: D & {
28
33
  httpClient: HttpClient;
29
34
  }) => T) => ((payload: D & {
30
35
  httpClient: HttpClient;
31
36
  }) => T);
32
- export declare function defineGet(useHttp: UseHttpFn): <P extends HttpParam>() => CreateGetFactory<P>;
37
+ export declare function defineGet(useHttp: UseHttpFn): <P extends HttpParam = CreateGetEmptyParams>() => CreateGetFactory<P>;
33
38
  export {};
34
39
  //# sourceMappingURL=create-get.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-get.d.ts","sourceRoot":"","sources":["../src/create-get.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-get.d.ts","sourceRoot":"","sources":["../src/create-get.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as createUseHttp } from "./nuxt-BsZgB52H.js";
1
+ import { n as resolveUrlParams, t as createUseHttp } from "./nuxt-CcmCJhA5.js";
2
2
  //#region src/create-get.ts
3
3
  function createUseCase() {
4
4
  return (callback) => callback;
@@ -31,7 +31,8 @@ function createHttp(options) {
31
31
  return {
32
32
  get(url, config) {
33
33
  const requestConfig = config ?? {};
34
- const requestUrl = `${joinUrl(options.baseURL, url)}${toQueryString(requestConfig.params, arrayMode)}`;
34
+ const resolved = resolveUrlParams(url, requestConfig.params);
35
+ const requestUrl = `${joinUrl(options.baseURL, resolved.url)}${toQueryString(resolved.params, arrayMode)}`;
35
36
  const { delay = 300, retries = 3 } = requestConfig.retry ?? {};
36
37
  const attemptRequest = async (attempt) => {
37
38
  try {
@@ -43,7 +44,10 @@ function createHttp(options) {
43
44
  });
44
45
  const parsedResult = await result.json();
45
46
  const response = {
46
- config: createResponseConfig(joinUrl(options.baseURL, url), requestConfig),
47
+ config: createResponseConfig(joinUrl(options.baseURL, resolved.url), {
48
+ ...requestConfig,
49
+ params: resolved.params
50
+ }),
47
51
  data: parsedResult,
48
52
  status: result.status
49
53
  };
@@ -64,7 +68,8 @@ function createHttp(options) {
64
68
  async post(url, data, config) {
65
69
  const requestConfig = config ?? {};
66
70
  const isForm = isFormData(data);
67
- const response = await clientFetch(`${joinUrl(options.baseURL, url)}${toQueryString(requestConfig.params, arrayMode)}`, {
71
+ const resolved = resolveUrlParams(url, requestConfig.params);
72
+ const response = await clientFetch(`${joinUrl(options.baseURL, resolved.url)}${toQueryString(resolved.params, arrayMode)}`, {
68
73
  body: isForm || data === void 0 ? data : JSON.stringify(data),
69
74
  credentials: "include",
70
75
  headers: resolveHeaders(options.headers, data !== void 0 && !isForm ? { "Content-Type": "application/json" } : void 0),
@@ -78,7 +83,10 @@ function createHttp(options) {
78
83
  parsedResult = {};
79
84
  }
80
85
  const parsedResponse = {
81
- config: createResponseConfig(joinUrl(options.baseURL, url), requestConfig),
86
+ config: createResponseConfig(joinUrl(options.baseURL, resolved.url), {
87
+ ...requestConfig,
88
+ params: resolved.params
89
+ }),
82
90
  data: parsedResult,
83
91
  status: response.status
84
92
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/create-get.ts","../src/http.ts"],"sourcesContent":["import type { HttpClient, HttpKey, HttpParam, HttpResponseData } from './http'\nimport type { HttpError, UseHttpFn, UseHttpOptions, UseHttpResult } from './nuxt'\n\nexport interface CreateGetFactory<P extends HttpParam> {\n <T extends HttpKey>(\n url: T,\n payload?: CreateGetPayload<T, P>,\n ): (options?: CreateGetOptions<T, P>) => Promise<CreateGetResult<T, P>>\n <D>(\n url: HttpKey,\n payload?: CreateGetPayload<HttpKey, P, D>,\n ): (options?: CreateGetOptions<HttpKey, P, D>) => Promise<CreateGetResult<HttpKey, P, D>>\n}\nexport type CreateGetOptions<T extends HttpKey, P extends HttpParam, D = never> = Omit<\n UseHttpOptions<T, P>,\n 'effect' | 'isError' | 'url'\n> & {\n effect?: CreateGetEffect<T, P, D>\n isError?: CreateGetIsError<T, D>\n}\nexport type CreateGetPayload<T extends HttpKey, P extends HttpParam, D = never> = {\n effect?: CreateGetEffect<T, P, D>\n isError?: CreateGetIsError<T, D>\n mapParams?: UseHttpOptions<T, P>['mapParams']\n}\nexport type CreateGetResult<T extends HttpKey, P extends HttpParam, D = never> = Omit<\n UseHttpResult<T, P>,\n 'data' | 'error'\n> & {\n data: Exclude<CreateGetData<T, D>, HttpError> | null\n error: Extract<CreateGetData<T, D>, HttpError> | null\n}\n\ntype CreateGetData<T extends HttpKey, D> = [D] extends [never] ? HttpResponseData<T> : D\n\ntype CreateGetEffect<T extends HttpKey, P extends HttpParam, D = never> = (\n data: CreateGetData<T, D>,\n config: CreateGetEffectConfig<P>,\n) => void\n\ntype CreateGetEffectConfig<P extends HttpParam> = {\n cached: boolean\n params: P\n}\n\ntype CreateGetIsError<T extends HttpKey, D = never> = (payload: CreateGetData<T, D>) => boolean\n\nexport function createUseCase<D>() {\n return <T>(\n callback: (payload: D & { httpClient: HttpClient }) => T,\n ): ((payload: D & { httpClient: HttpClient }) => T) => callback\n}\n\nexport function defineGet(useHttp: UseHttpFn) {\n return function withParams<P extends HttpParam>(): CreateGetFactory<P> {\n function withUrl<T extends HttpKey, D = never>(\n url: T,\n payload?: CreateGetPayload<T, P, D>,\n ): (options?: CreateGetOptions<T, P, D>) => Promise<CreateGetResult<T, P, D>> {\n return async function request(options: CreateGetOptions<T, P, D> = {}): Promise<CreateGetResult<T, P, D>> {\n const result = await useHttp({\n ...options,\n effect: (data, config) => {\n payload?.effect?.(data as CreateGetData<T, D>, config)\n options?.effect?.(data as CreateGetData<T, D>, config)\n },\n isError: options.isError ?? payload?.isError,\n mapParams: options.mapParams ?? payload?.mapParams,\n url,\n } as UseHttpOptions<T, P>)\n\n return result as CreateGetResult<T, P, D>\n }\n }\n\n return withUrl as CreateGetFactory<P>\n }\n}\n","export interface CreateHttpOptions {\n arrayMode?: HttpArrayMode\n baseURL: string\n fetch?: typeof fetch\n headers?: (() => HttpHeaders) | HttpHeaders\n onResponse?: (response: HttpAnyResponse) => Promise<void> | void\n timeout?: number\n}\n\nexport type GetConfig<TKey extends HttpKey = HttpKey> = HttpConfigFull<TKey> & {\n retry?: {\n delay?: number\n retries?: number\n }\n}\n\nexport type HttpAnyResponse = HttpResponse<HttpResponseData<HttpKey>, HttpKey, HttpConfigFull<HttpKey>>\n\nexport type HttpArrayMode = 'json' | 'repeat'\nexport type HttpClient = {\n get: <T extends HttpKey, TConfig extends GetConfig<T> = GetConfig<T>>(\n url: T,\n config?: TConfig,\n ) => Promise<HttpResponse<HttpResponseData<T>, T, TConfig>>\n post: <\n T extends HttpKey,\n TData extends Record<string, unknown> = Record<string, unknown>,\n TConfig extends PostConfig<T> = PostConfig<T>,\n >(\n url: T,\n data?: HttpPostData<TData>,\n config?: TConfig,\n ) => Promise<HttpResponse<HttpResponseData<T>, T, TConfig>>\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport interface HttpConfig<TKey extends HttpKey = HttpKey> {}\n\nexport interface HttpEndpoint {}\nexport type HttpErrorGuard<TData = unknown, TError extends TData = TData> = (payload: TData) => payload is TError\nexport type HttpKey = Extract<keyof HttpSchema, string>\n\nexport type HttpParam = Record<string, boolean | number | string | string[] | undefined>\nexport type HttpPostData<TData extends Record<string, unknown> = Record<string, unknown>> = FormData | TData\n\nexport interface HttpResponse<\n T = unknown,\n TKey extends HttpKey = HttpKey,\n TConfig extends HttpConfigFull<TKey> = HttpConfigFull<TKey>,\n> {\n config: HttpResponseConfig<TKey, TConfig>\n data: T\n status: number\n}\nexport type HttpResponseConfig<\n TKey extends HttpKey = HttpKey,\n TConfig extends HttpConfig<TKey> = HttpConfig<TKey>,\n> = Omit<TConfig, 'signal'> & { url: string }\n\nexport type HttpResponseData<TKey extends HttpKey = HttpKey> = HttpSchema[TKey]\n\nexport type PostConfig<TKey extends HttpKey = HttpKey> = HttpConfigFull<TKey>\n\ntype HttpConfigFull<TKey extends HttpKey = HttpKey> = HttpConfig<TKey> & {\n params?: HttpParam\n signal?: AbortSignal | AbortSignal[]\n}\n\ntype HttpHeaders = Record<string, string | undefined>\n\ntype HttpSchema = keyof HttpEndpoint extends never ? Record<string, unknown> : HttpEndpoint\n\nexport function createHttp(options: CreateHttpOptions): HttpClient {\n const arrayMode = options.arrayMode ?? 'json'\n const clientFetch = options.fetch ?? fetch\n const timeout = options.timeout ?? 80000\n\n return {\n get<T extends HttpKey, TConfig extends GetConfig<T> = GetConfig<T>>(url: T, config?: TConfig) {\n const requestConfig = (config ?? {}) as TConfig\n const requestUrl = `${joinUrl(options.baseURL, url)}${toQueryString(requestConfig.params, arrayMode)}`\n const { delay = 300, retries = 3 } = requestConfig.retry ?? {}\n\n const attemptRequest = async (attempt: number): Promise<HttpResponse<HttpResponseData<T>, T, TConfig>> => {\n try {\n const result = await clientFetch(requestUrl, {\n credentials: 'include',\n headers: resolveHeaders(options.headers),\n method: 'GET',\n signal: createSignal(requestConfig.signal, timeout),\n })\n\n const parsedResult = await result.json()\n const response: HttpResponse<HttpResponseData<T>, T, TConfig> = {\n config: createResponseConfig<T, TConfig>(joinUrl(options.baseURL, url), requestConfig),\n data: parsedResult,\n status: result.status,\n }\n\n if (!result.ok && isRetryableStatus(result.status) && attempt < retries) {\n await wait(getRetryDelay(attempt, delay))\n return attemptRequest(attempt + 1)\n }\n\n await options.onResponse?.(response as HttpAnyResponse)\n return response\n } catch (err) {\n if (isAbortError(err) || attempt >= retries) {\n throw err\n }\n\n await wait(getRetryDelay(attempt, delay))\n return attemptRequest(attempt + 1)\n }\n }\n\n return attemptRequest(0)\n },\n async post<\n T extends HttpKey,\n TData extends Record<string, unknown> = Record<string, unknown>,\n TConfig extends PostConfig<T> = PostConfig<T>,\n >(url: T, data?: HttpPostData<TData>, config?: TConfig) {\n const requestConfig = (config ?? {}) as TConfig\n const isForm = isFormData(data)\n const requestUrl = `${joinUrl(options.baseURL, url)}${toQueryString(requestConfig.params, arrayMode)}`\n const response = await clientFetch(requestUrl, {\n body: isForm || data === undefined ? data : JSON.stringify(data),\n credentials: 'include',\n headers: resolveHeaders(\n options.headers,\n data !== undefined && !isForm ? { 'Content-Type': 'application/json' } : undefined,\n ),\n method: 'POST',\n signal: createSignal(requestConfig.signal, timeout),\n })\n\n let parsedResult: Awaited<ReturnType<typeof response.json>> = {}\n try {\n parsedResult = await response.json()\n } catch {\n parsedResult = {}\n }\n\n const parsedResponse: HttpResponse<HttpResponseData<T>, T, TConfig> = {\n config: createResponseConfig<T, TConfig>(joinUrl(options.baseURL, url), requestConfig),\n data: parsedResult,\n status: response.status,\n }\n\n await options.onResponse?.(parsedResponse as HttpAnyResponse)\n return parsedResponse\n },\n }\n}\n\nfunction createAnySignal(signals: AbortSignal[]): AbortSignal {\n if (typeof AbortSignal?.any === 'function') {\n return AbortSignal.any(signals)\n }\n\n const controller = new AbortController()\n\n signals.filter(Boolean).forEach((signal) => {\n signal.addEventListener('abort', () => controller.abort(), { once: true })\n })\n\n return controller.signal\n}\n\nfunction createResponseConfig<TKey extends HttpKey, TConfig extends HttpConfigFull<TKey>>(\n url: string,\n config: TConfig,\n): HttpResponseConfig<TKey, TConfig> {\n const responseConfig = { ...config } as Record<string, unknown>\n delete responseConfig.signal\n\n return {\n ...responseConfig,\n url,\n } as HttpResponseConfig<TKey, TConfig>\n}\n\nfunction createSignal(signal: AbortSignal | AbortSignal[] | undefined, timeout: number): AbortSignal {\n const timeoutSignal = createTimeoutSignal(timeout)\n\n if (Array.isArray(signal)) {\n return createAnySignal([...signal, timeoutSignal])\n }\n\n if (signal) {\n return createAnySignal([signal, timeoutSignal])\n }\n\n return timeoutSignal\n}\n\nfunction createTimeoutSignal(ms: number): AbortSignal {\n if (typeof AbortSignal?.timeout === 'function') {\n return AbortSignal.timeout(ms)\n }\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), ms)\n\n controller.signal.addEventListener('abort', () => clearTimeout(timeoutId), {\n once: true,\n })\n\n return controller.signal\n}\n\nfunction getRetryDelay(attempt: number, delay: number): number {\n return delay * 2 ** attempt\n}\n\nfunction isAbortError(err: unknown): boolean {\n return err instanceof DOMException && err.name === 'AbortError'\n}\n\nfunction isFormData(value: unknown): value is FormData {\n return typeof FormData !== 'undefined' && value instanceof FormData\n}\n\nfunction isRetryableStatus(status: number): boolean {\n return status >= 500 || status === 429\n}\n\nfunction joinUrl(baseURL: string, url: string): string {\n const normalizedBase = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL\n const normalizedUrl = url.startsWith('/') ? url.slice(1) : url\n\n return `${normalizedBase}/${normalizedUrl}`\n}\n\nfunction resolveHeaders(\n value: CreateHttpOptions['headers'],\n extraHeaders?: Record<string, string>,\n): Record<string, string> {\n const headers = typeof value === 'function' ? value() : value\n\n return Object.entries({\n ...headers,\n ...extraHeaders,\n }).reduce<Record<string, string>>((acc, [key, headerValue]) => {\n if (typeof headerValue === 'string') {\n acc[key] = headerValue\n }\n\n return acc\n }, {})\n}\n\nfunction serializeQueryValue(\n urlParams: URLSearchParams,\n key: string,\n value: HttpParam[string],\n arrayMode: HttpArrayMode,\n): void {\n if (value === undefined) {\n return\n }\n\n if (Array.isArray(value)) {\n if (arrayMode === 'json') {\n urlParams.append(key, JSON.stringify(value))\n return\n }\n\n value.forEach((item) => {\n urlParams.append(`${key}[]`, item)\n })\n return\n }\n\n urlParams.append(key, String(value))\n}\n\nfunction toQueryString(params?: HttpParam, arrayMode: HttpArrayMode = 'json'): string {\n const urlParams = new URLSearchParams()\n\n Object.entries(params ?? {}).forEach(([key, value]) => {\n serializeQueryValue(urlParams, key, value, arrayMode)\n })\n\n return urlParams.size > 0 ? `?${urlParams}` : ''\n}\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/create-get.ts","../src/http.ts"],"sourcesContent":["import type { HttpClient, HttpKey, HttpParam, HttpResponseData } from './http'\nimport type { HttpError, UseHttpFn, UseHttpOptions, UseHttpResult } from './nuxt'\n\nexport interface CreateGetFactory<P extends HttpParam> {\n <D = never, T extends HttpKey = HttpKey>(\n url: T,\n payload?: CreateGetPayload<T, CreateGetParams<T, P>, D>,\n ): (\n options?: CreateGetOptions<T, CreateGetParams<T, P>, D>,\n ) => Promise<CreateGetResult<T, CreateGetParams<T, P>, D>>\n}\nexport type CreateGetOptions<T extends HttpKey, P extends HttpParam, D = never> = Omit<\n UseHttpOptions<T, P>,\n 'effect' | 'isError' | 'url'\n> & {\n effect?: CreateGetEffect<T, P, D>\n isError?: CreateGetIsError<T, D>\n}\nexport type CreateGetPayload<T extends HttpKey, P extends HttpParam, D = never> = {\n effect?: CreateGetEffect<T, P, D>\n isError?: CreateGetIsError<T, D>\n mapParams?: UseHttpOptions<T, P>['mapParams']\n}\nexport type CreateGetResult<T extends HttpKey, P extends HttpParam, D = never> = Omit<\n UseHttpResult<T, P>,\n 'data' | 'error'\n> & {\n data: Exclude<CreateGetData<T, D>, HttpError> | null\n error: Extract<CreateGetData<T, D>, HttpError> | null\n}\n\ntype CreateGetData<T extends HttpKey, D> = [D] extends [never] ? HttpResponseData<T> : D\ntype CreateGetEffect<T extends HttpKey, P extends HttpParam, D = never> = (\n data: CreateGetData<T, D>,\n config: CreateGetEffectConfig<P>,\n) => void\ntype CreateGetEffectConfig<P extends HttpParam> = {\n cached: boolean\n params: P\n}\ntype CreateGetEmptyParams = Record<never, never>\n\ntype CreateGetIsError<T extends HttpKey, D = never> = (payload: CreateGetData<T, D>) => boolean\n\ntype CreateGetParamKeys<T extends string> = T extends `${string}:${infer Rest}`\n ? Rest extends `${infer Key}/${infer Tail}`\n ? CreateGetParamKeys<`/${Tail}`> | Key\n : Rest\n : never\ntype CreateGetParams<T extends HttpKey, P extends HttpParam> = Omit<CreateGetPathParams<T>, keyof P> & P\ntype CreateGetPathParams<T extends HttpKey> = [CreateGetParamKeys<T>] extends [never]\n ? CreateGetEmptyParams\n : {\n [K in CreateGetParamKeys<T>]: string\n }\n\nexport function createUseCase<D>() {\n return <T>(\n callback: (payload: D & { httpClient: HttpClient }) => T,\n ): ((payload: D & { httpClient: HttpClient }) => T) => callback\n}\n\nexport function defineGet(useHttp: UseHttpFn) {\n return function withParams<P extends HttpParam = CreateGetEmptyParams>(): CreateGetFactory<P> {\n function withUrl<T extends HttpKey, D = never>(\n url: T,\n payload?: CreateGetPayload<T, CreateGetParams<T, P>, D>,\n ): (\n options?: CreateGetOptions<T, CreateGetParams<T, P>, D>,\n ) => Promise<CreateGetResult<T, CreateGetParams<T, P>, D>> {\n return async function request(\n options: CreateGetOptions<T, CreateGetParams<T, P>, D> = {},\n ): Promise<CreateGetResult<T, CreateGetParams<T, P>, D>> {\n const result = await useHttp({\n ...options,\n effect: (data, config) => {\n payload?.effect?.(data as CreateGetData<T, D>, config)\n options?.effect?.(data as CreateGetData<T, D>, config)\n },\n isError: options.isError ?? payload?.isError,\n mapParams: options.mapParams ?? payload?.mapParams,\n url,\n } as UseHttpOptions<T, CreateGetParams<T, P>>)\n\n return result as CreateGetResult<T, CreateGetParams<T, P>, D>\n }\n }\n\n return withUrl as CreateGetFactory<P>\n }\n}\n","import { resolveUrlParams } from './utils'\n\nexport interface CreateHttpOptions {\n arrayMode?: HttpArrayMode\n baseURL: string\n fetch?: typeof fetch\n headers?: (() => HttpHeaders) | HttpHeaders\n onResponse?: (response: HttpAnyResponse) => Promise<void> | void\n timeout?: number\n}\n\nexport type GetConfig<TKey extends HttpKey = HttpKey> = HttpConfigFull<TKey> & {\n retry?: {\n delay?: number\n retries?: number\n }\n}\n\nexport type HttpAnyResponse = HttpResponse<HttpResponseData<HttpKey>, HttpKey, HttpConfigFull<HttpKey>>\n\nexport type HttpArrayMode = 'json' | 'repeat'\nexport type HttpClient = {\n get: <T extends HttpKey, TConfig extends GetConfig<T> = GetConfig<T>>(\n url: T,\n config?: TConfig,\n ) => Promise<HttpResponse<HttpResponseData<T>, T, TConfig>>\n post: <\n T extends HttpKey,\n TData extends Record<string, unknown> = Record<string, unknown>,\n TConfig extends PostConfig<T> = PostConfig<T>,\n >(\n url: T,\n data?: HttpPostData<TData>,\n config?: TConfig,\n ) => Promise<HttpResponse<HttpResponseData<T>, T, TConfig>>\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport interface HttpConfig<TKey extends HttpKey = HttpKey> {}\n\nexport interface HttpEndpoint {}\nexport type HttpErrorGuard<TData = unknown, TError extends TData = TData> = (payload: TData) => payload is TError\nexport type HttpKey = Extract<keyof HttpSchema, string>\n\nexport type HttpParam = Record<string, boolean | number | string | string[] | undefined>\nexport type HttpPostData<TData extends Record<string, unknown> = Record<string, unknown>> = FormData | TData\n\nexport interface HttpResponse<\n T = unknown,\n TKey extends HttpKey = HttpKey,\n TConfig extends HttpConfigFull<TKey> = HttpConfigFull<TKey>,\n> {\n config: HttpResponseConfig<TKey, TConfig>\n data: T\n status: number\n}\nexport type HttpResponseConfig<\n TKey extends HttpKey = HttpKey,\n TConfig extends HttpConfig<TKey> = HttpConfig<TKey>,\n> = Omit<TConfig, 'signal'> & { url: string }\n\nexport type HttpResponseData<TKey extends HttpKey = HttpKey> = HttpSchema[TKey]\n\nexport type PostConfig<TKey extends HttpKey = HttpKey> = HttpConfigFull<TKey>\n\ntype HttpConfigFull<TKey extends HttpKey = HttpKey> = HttpConfig<TKey> & {\n params?: HttpParam\n signal?: AbortSignal | AbortSignal[]\n}\n\ntype HttpHeaders = Record<string, string | undefined>\n\ntype HttpSchema = keyof HttpEndpoint extends never ? Record<string, unknown> : HttpEndpoint\n\nexport function createHttp(options: CreateHttpOptions): HttpClient {\n const arrayMode = options.arrayMode ?? 'json'\n const clientFetch = options.fetch ?? fetch\n const timeout = options.timeout ?? 80000\n\n return {\n get<T extends HttpKey, TConfig extends GetConfig<T> = GetConfig<T>>(url: T, config?: TConfig) {\n const requestConfig = (config ?? {}) as TConfig\n const resolved = resolveUrlParams(url, requestConfig.params)\n const requestUrl = `${joinUrl(options.baseURL, resolved.url)}${toQueryString(resolved.params, arrayMode)}`\n const { delay = 300, retries = 3 } = requestConfig.retry ?? {}\n\n const attemptRequest = async (attempt: number): Promise<HttpResponse<HttpResponseData<T>, T, TConfig>> => {\n try {\n const result = await clientFetch(requestUrl, {\n credentials: 'include',\n headers: resolveHeaders(options.headers),\n method: 'GET',\n signal: createSignal(requestConfig.signal, timeout),\n })\n\n const parsedResult = await result.json()\n const response: HttpResponse<HttpResponseData<T>, T, TConfig> = {\n config: createResponseConfig<T, TConfig>(joinUrl(options.baseURL, resolved.url), {\n ...requestConfig,\n params: resolved.params,\n }),\n data: parsedResult,\n status: result.status,\n }\n\n if (!result.ok && isRetryableStatus(result.status) && attempt < retries) {\n await wait(getRetryDelay(attempt, delay))\n return attemptRequest(attempt + 1)\n }\n\n await options.onResponse?.(response as HttpAnyResponse)\n return response\n } catch (err) {\n if (isAbortError(err) || attempt >= retries) {\n throw err\n }\n\n await wait(getRetryDelay(attempt, delay))\n return attemptRequest(attempt + 1)\n }\n }\n\n return attemptRequest(0)\n },\n async post<\n T extends HttpKey,\n TData extends Record<string, unknown> = Record<string, unknown>,\n TConfig extends PostConfig<T> = PostConfig<T>,\n >(url: T, data?: HttpPostData<TData>, config?: TConfig) {\n const requestConfig = (config ?? {}) as TConfig\n const isForm = isFormData(data)\n const resolved = resolveUrlParams(url, requestConfig.params)\n const requestUrl = `${joinUrl(options.baseURL, resolved.url)}${toQueryString(resolved.params, arrayMode)}`\n const response = await clientFetch(requestUrl, {\n body: isForm || data === undefined ? data : JSON.stringify(data),\n credentials: 'include',\n headers: resolveHeaders(\n options.headers,\n data !== undefined && !isForm ? { 'Content-Type': 'application/json' } : undefined,\n ),\n method: 'POST',\n signal: createSignal(requestConfig.signal, timeout),\n })\n\n let parsedResult: Awaited<ReturnType<typeof response.json>> = {}\n try {\n parsedResult = await response.json()\n } catch {\n parsedResult = {}\n }\n\n const parsedResponse: HttpResponse<HttpResponseData<T>, T, TConfig> = {\n config: createResponseConfig<T, TConfig>(joinUrl(options.baseURL, resolved.url), {\n ...requestConfig,\n params: resolved.params,\n }),\n data: parsedResult,\n status: response.status,\n }\n\n await options.onResponse?.(parsedResponse as HttpAnyResponse)\n return parsedResponse\n },\n }\n}\n\nfunction createAnySignal(signals: AbortSignal[]): AbortSignal {\n if (typeof AbortSignal?.any === 'function') {\n return AbortSignal.any(signals)\n }\n\n const controller = new AbortController()\n\n signals.filter(Boolean).forEach((signal) => {\n signal.addEventListener('abort', () => controller.abort(), { once: true })\n })\n\n return controller.signal\n}\n\nfunction createResponseConfig<TKey extends HttpKey, TConfig extends HttpConfigFull<TKey>>(\n url: string,\n config: TConfig,\n): HttpResponseConfig<TKey, TConfig> {\n const responseConfig = { ...config } as Record<string, unknown>\n delete responseConfig.signal\n\n return {\n ...responseConfig,\n url,\n } as HttpResponseConfig<TKey, TConfig>\n}\n\nfunction createSignal(signal: AbortSignal | AbortSignal[] | undefined, timeout: number): AbortSignal {\n const timeoutSignal = createTimeoutSignal(timeout)\n\n if (Array.isArray(signal)) {\n return createAnySignal([...signal, timeoutSignal])\n }\n\n if (signal) {\n return createAnySignal([signal, timeoutSignal])\n }\n\n return timeoutSignal\n}\n\nfunction createTimeoutSignal(ms: number): AbortSignal {\n if (typeof AbortSignal?.timeout === 'function') {\n return AbortSignal.timeout(ms)\n }\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), ms)\n\n controller.signal.addEventListener('abort', () => clearTimeout(timeoutId), {\n once: true,\n })\n\n return controller.signal\n}\n\nfunction getRetryDelay(attempt: number, delay: number): number {\n return delay * 2 ** attempt\n}\n\nfunction isAbortError(err: unknown): boolean {\n return err instanceof DOMException && err.name === 'AbortError'\n}\n\nfunction isFormData(value: unknown): value is FormData {\n return typeof FormData !== 'undefined' && value instanceof FormData\n}\n\nfunction isRetryableStatus(status: number): boolean {\n return status >= 500 || status === 429\n}\n\nfunction joinUrl(baseURL: string, url: string): string {\n const normalizedBase = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL\n const normalizedUrl = url.startsWith('/') ? url.slice(1) : url\n\n return `${normalizedBase}/${normalizedUrl}`\n}\n\nfunction resolveHeaders(\n value: CreateHttpOptions['headers'],\n extraHeaders?: Record<string, string>,\n): Record<string, string> {\n const headers = typeof value === 'function' ? value() : value\n\n return Object.entries({\n ...headers,\n ...extraHeaders,\n }).reduce<Record<string, string>>((acc, [key, headerValue]) => {\n if (typeof headerValue === 'string') {\n acc[key] = headerValue\n }\n\n return acc\n }, {})\n}\n\nfunction serializeQueryValue(\n urlParams: URLSearchParams,\n key: string,\n value: HttpParam[string],\n arrayMode: HttpArrayMode,\n): void {\n if (value === undefined) {\n return\n }\n\n if (Array.isArray(value)) {\n if (arrayMode === 'json') {\n urlParams.append(key, JSON.stringify(value))\n return\n }\n\n value.forEach((item) => {\n urlParams.append(`${key}[]`, item)\n })\n return\n }\n\n urlParams.append(key, String(value))\n}\n\nfunction toQueryString(params?: HttpParam, arrayMode: HttpArrayMode = 'json'): string {\n const urlParams = new URLSearchParams()\n\n Object.entries(params ?? {}).forEach(([key, value]) => {\n serializeQueryValue(urlParams, key, value, arrayMode)\n })\n\n return urlParams.size > 0 ? `?${urlParams}` : ''\n}\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n"],"mappings":"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"}
@@ -2,8 +2,9 @@ import { useLazyAsyncData, useState } from "nuxt/app";
2
2
  import { onScopeDispose, shallowReactive, shallowRef } from "vue";
3
3
  //#region src/utils.ts
4
4
  function createURL(url, params) {
5
+ const resolved = resolveUrlParams(url, params);
5
6
  const urlParams = new URLSearchParams();
6
- Object.entries(params ?? {}).forEach(([key, value]) => {
7
+ Object.entries(resolved.params ?? {}).forEach(([key, value]) => {
7
8
  if (value === void 0) return;
8
9
  if (Array.isArray(value)) {
9
10
  value.forEach((item) => {
@@ -14,7 +15,7 @@ function createURL(url, params) {
14
15
  urlParams.append(key, String(value));
15
16
  });
16
17
  const query = urlParams.size > 0 ? `?${urlParams}` : "";
17
- return urlParams.size > 0 ? `${url}${query}` : url;
18
+ return urlParams.size > 0 ? `${resolved.url}${query}` : resolved.url;
18
19
  }
19
20
  function fastDevHash(data) {
20
21
  const str = JSON.stringify(data);
@@ -35,6 +36,28 @@ async function hashData(data) {
35
36
  }
36
37
  return fastDevHash(data);
37
38
  }
39
+ function resolveUrlParams(url, params) {
40
+ if (!params) return {
41
+ params,
42
+ url
43
+ };
44
+ const usedKeys = {};
45
+ const resolvedUrl = url.replaceAll(/:(\w+)/g, (segment, key) => {
46
+ const value = params[key];
47
+ if (value === void 0) return segment;
48
+ usedKeys[key] = true;
49
+ return encodeURIComponent(String(value));
50
+ });
51
+ const queryParams = Object.entries(params).reduce((acc, [key, value]) => {
52
+ if (usedKeys[key]) return acc;
53
+ acc[key] = value;
54
+ return acc;
55
+ }, {});
56
+ return {
57
+ params: Object.keys(queryParams).length > 0 ? queryParams : void 0,
58
+ url: resolvedUrl
59
+ };
60
+ }
38
61
  //#endregion
39
62
  //#region src/nuxt.ts
40
63
  const DAY = 1e3 * 60 * 60 * 24;
@@ -228,6 +251,6 @@ function normalizeBroadcastValue(payload) {
228
251
  }
229
252
  }
230
253
  //#endregion
231
- export { createUseHttp as t };
254
+ export { resolveUrlParams as n, createUseHttp as t };
232
255
 
233
- //# sourceMappingURL=nuxt-BsZgB52H.js.map
256
+ //# sourceMappingURL=nuxt-CcmCJhA5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nuxt-CcmCJhA5.js","names":[],"sources":["../src/utils.ts","../src/nuxt.ts"],"sourcesContent":["import type { HttpParam } from './http'\n\nexport function createURL(url: string, params?: HttpParam): string {\n const resolved = resolveUrlParams(url, params)\n const urlParams = new URLSearchParams()\n\n Object.entries(resolved.params ?? {}).forEach(([key, value]) => {\n if (value === undefined) {\n return\n }\n\n if (Array.isArray(value)) {\n value.forEach((item) => {\n urlParams.append(`${key}[]`, item)\n })\n return\n }\n\n urlParams.append(key, String(value))\n })\n\n const query = urlParams.size > 0 ? `?${urlParams}` : ''\n return urlParams.size > 0 ? `${resolved.url}${query}` : resolved.url\n}\n\nexport function fastDevHash(data: unknown): string {\n const str = JSON.stringify(data)\n let hash = 0\n\n for (let i = 0; i < str.length; i++) {\n const chr = str.charCodeAt(i)\n hash = (hash << 5) - hash + chr\n hash |= 0\n }\n\n return Math.abs(hash).toString(16)\n}\n\nexport async function hashData(data: unknown): Promise<string> {\n const subtle = globalThis.crypto?.subtle\n\n if (subtle) {\n const encoded = new TextEncoder().encode(JSON.stringify(data))\n const buffer = await subtle.digest('SHA-1', encoded)\n const array = Array.from(new Uint8Array(buffer))\n\n return array.map((value) => value.toString(16).padStart(2, '0')).join('')\n }\n\n return fastDevHash(data)\n}\n\nexport function resolveUrlParams(\n url: string,\n params?: HttpParam,\n): {\n params: HttpParam | undefined\n url: string\n} {\n if (!params) {\n return {\n params,\n url,\n }\n }\n\n const usedKeys: Record<string, true> = {}\n const resolvedUrl = url.replaceAll(/:(\\w+)/g, (segment, key: string) => {\n const value = params[key]\n\n if (value === undefined) {\n return segment\n }\n\n usedKeys[key] = true\n return encodeURIComponent(String(value))\n })\n const queryParams = Object.entries(params).reduce<HttpParam>((acc, [key, value]) => {\n if (usedKeys[key]) {\n return acc\n }\n\n acc[key] = value\n return acc\n }, {})\n\n return {\n params: Object.keys(queryParams).length > 0 ? queryParams : undefined,\n url: resolvedUrl,\n }\n}\n","import { useLazyAsyncData, useState } from 'nuxt/app'\nimport { onScopeDispose, shallowReactive, shallowRef } from 'vue'\n\nimport type { GetConfig, HttpClient, HttpErrorGuard, HttpKey, HttpParam, HttpResponseData } from './http'\n\nimport { createURL, hashData } from './utils'\n\nconst DAY = 1000 * 60 * 60 * 24\nconst DEFAULT_CHANNEL_NAME = 'http-tab-sync'\nconst DEFAULT_TTL = DAY * 7\nexport interface CreateUseHttpDependencies {\n channelName?: string\n getCache: () => null | UseHttpCache\n getHttpClient: () => HttpClient\n isDev?: () => boolean\n isError?: HttpErrorGuard<unknown>\n ttl?: number\n}\n\nexport type HttpError = HttpErrorMap[keyof HttpErrorMap]\nexport interface HttpErrorMap {}\nexport type HttpSuccessData<TKey extends HttpKey = HttpKey> = Exclude<HttpResponseData<TKey>, HttpError>\n\nexport interface UseHttpCache {\n deleteKeysWithPart: (part: string) => Promise<void>\n get: <T>(key: string) => Promise<null | UseHttpCacheEntry<T>>\n set: <T>(key: string, value: T, ttl: number) => Promise<void>\n}\n\nexport interface UseHttpCacheEntry<T> {\n hash: string\n value: T\n}\n\nexport interface UseHttpFn {\n <T extends HttpKey, P extends HttpParam>(options: UseHttpOptions<T, P>): Promise<UseHttpResult<T, P>>\n}\n\nexport interface UseHttpOptions<T extends HttpKey, P extends HttpParam> {\n effect?: UseHttpEffect<T, P>\n initParams?: P\n isError?: (payload: HttpResponseData<T>) => boolean\n lazy?: true\n mapParams?: (params?: P) => P\n server?: boolean\n url: T\n}\n\nexport interface UseHttpResult<T extends HttpKey, P extends HttpParam> {\n data: HttpSuccessData<T> | null\n error: null | UseHttpError<T>\n fetch: UseHttpFetch<P>\n hasFirstData: boolean\n hasFreshData: boolean\n pending: boolean\n pendingCache: boolean\n}\n\ntype BroadcastMessage = {\n data: unknown\n fullUrl: string\n params: HttpParam\n type: 'STATE_UPDATE'\n}\n\ntype UseHttpEffect<T extends HttpKey, P extends HttpParam> = (\n data: HttpResponseData<T>,\n config: UseHttpEffectConfig<P>,\n) => void\ntype UseHttpEffectConfig<P extends HttpParam> = {\n cached: boolean\n params: P\n}\ntype UseHttpError<T extends HttpKey> = Extract<HttpResponseData<T>, HttpError>\n\ntype UseHttpFetch<P extends HttpParam> = (params?: P, opt?: { signal: AbortSignal }) => Promise<void>\n\nexport function createUseHttp(dependencies: CreateUseHttpDependencies): UseHttpFn {\n let channel: BroadcastChannel | null\n\n const useHttp: UseHttpFn = async <T extends HttpKey, P extends HttpParam>(\n options: UseHttpOptions<T, P>,\n ): Promise<UseHttpResult<T, P>> => {\n const mapParams = (params?: P): P => {\n if (options.mapParams) {\n return options.mapParams(params)\n }\n\n return params ?? ({} as P)\n }\n const effect = options.effect\n const isError = createIsErrorGuard(options.isError, dependencies.isError)\n\n const buildUrl = createURL\n const initFullUrl = buildUrl(options.url, mapParams(options.initParams))\n const httpClient = dependencies.getHttpClient()\n const cache = import.meta.client ? (dependencies.getCache?.() ?? null) : null\n let hasDataFromServer = false\n\n const result = shallowReactive({\n data: null as null | unknown,\n error: null as null | unknown,\n fetch: async (_params?: P, _opt?: { signal: AbortSignal }): Promise<void> => await undefined,\n hasFirstData: false,\n hasFreshData: false,\n pending: true,\n pendingCache: true,\n })\n const setError = (value: null | unknown): void => {\n result.error = value\n }\n const setData = (value: null | unknown): void => {\n result.data = value\n }\n const syncResult = (payload: HttpResponseData<T> | null | undefined): void => {\n if (payload === null || payload === undefined) {\n setData(null)\n setError(null)\n return\n }\n\n if (isError(payload)) {\n setData(null)\n setError(payload)\n return\n }\n\n setData(payload)\n setError(null)\n }\n\n const controller = new AbortController()\n const serverData = useState<null | unknown>(`http-${initFullUrl}`, () => null)\n\n if (options.server && import.meta.server) {\n const paramsReactive = shallowRef(mapParams(options.initParams))\n const ssr = await useLazyAsyncData(initFullUrl, async () => {\n return await httpClient.get<T>(options.url, {\n params: paramsReactive.value,\n } as GetConfig<T>)\n })\n\n result.fetch = async (params?: P) => {\n paramsReactive.value = mapParams(params)\n await ssr.refresh()\n }\n\n serverData.value = ssr.data.value?.data ?? null\n const serverPayload = serverData.value as HttpResponseData<T>\n syncResult(serverPayload)\n\n result.pending = false\n result.pendingCache = false\n result.hasFirstData = true\n result.hasFreshData = true\n\n if (serverData.value) {\n effect?.(serverData.value as HttpResponseData<T>, {\n cached: false,\n params: mapParams(options.initParams),\n })\n }\n\n if (result.data) {\n hasDataFromServer = true\n }\n }\n\n if (import.meta.client) {\n channel = getChannel(dependencies.channelName ?? DEFAULT_CHANNEL_NAME, channel)\n const fullUrlHistory: Record<string, true> = {}\n\n function onMessage(event: MessageEvent<Partial<BroadcastMessage>>): void {\n if (event.data.fullUrl && fullUrlHistory[event.data.fullUrl]) {\n const eventPayload = event.data.data as HttpResponseData<T> | undefined\n\n if (eventPayload) {\n effect?.(eventPayload, {\n cached: false,\n params: event.data.params as P,\n })\n }\n\n syncResult(eventPayload)\n\n result.hasFirstData = true\n result.hasFreshData = true\n }\n }\n\n channel?.addEventListener('message', onMessage)\n\n if (serverData.value) {\n const clientServerPayload = serverData.value as HttpResponseData<T>\n syncResult(clientServerPayload)\n result.pending = false\n result.pendingCache = false\n result.hasFirstData = true\n result.hasFreshData = true\n }\n\n const raceCondition: Record<string, number> = {}\n const ttl = dependencies.ttl ?? DEFAULT_TTL\n\n const runFetch = async (params?: P, fetchOpt?: { signal?: AbortSignal }): Promise<void> => {\n const mappedParams = mapParams(params)\n const fullUrl = buildUrl(options.url, mappedParams)\n const fetchId = Date.now() + getRandom(0, 300)\n\n if (raceCondition[fullUrl]) {\n console.info('Race Condition affect', fullUrl)\n return\n }\n\n raceCondition[fullUrl] = fetchId\n\n try {\n result.pending = true\n result.pendingCache = true\n\n const cachedFetch = cache && !dependencies.isDev?.() ? await cache.get<unknown>(fullUrl) : null\n\n if (cachedFetch) {\n const cachedPayload = cachedFetch.value as HttpResponseData<T>\n\n effect?.(cachedPayload, {\n cached: true,\n params: mappedParams,\n })\n\n syncResult(cachedPayload)\n result.hasFirstData = true\n\n result.pendingCache = false\n }\n\n if (controller.signal.aborted || fetchOpt?.signal?.aborted) {\n throw new DOMException('Aborted', 'AbortError')\n }\n\n const signalHttp = fetchOpt?.signal ? [controller.signal, fetchOpt.signal] : controller.signal\n const response = await httpClient.get<T>(options.url, {\n params: mappedParams,\n signal: signalHttp,\n } as GetConfig<T>)\n const responsePayload = response.data as HttpResponseData<T>\n\n effect?.(responsePayload, {\n cached: false,\n params: mappedParams,\n })\n\n if (isError(responsePayload)) {\n syncResult(responsePayload)\n } else {\n syncResult(responsePayload)\n const successData = responsePayload\n\n fullUrlHistory[fullUrl] = true\n channel?.postMessage({\n data: normalizeBroadcastValue(successData),\n fullUrl,\n params: normalizeBroadcastValue(mappedParams),\n type: 'STATE_UPDATE',\n } satisfies BroadcastMessage)\n\n if (cache) {\n if (cachedFetch) {\n const newHash = await hashData(responsePayload)\n if (newHash !== cachedFetch.hash) {\n await cache.deleteKeysWithPart(options.url)\n }\n }\n\n if (response.status === 200) {\n await cache.set(fullUrl, successData, ttl)\n }\n }\n }\n\n result.hasFirstData = true\n result.hasFreshData = true\n } catch (error) {\n console.error(error)\n } finally {\n if (raceCondition[fullUrl] === fetchId) {\n delete raceCondition[fullUrl]\n }\n\n result.pending = false\n result.pendingCache = false\n }\n }\n\n result.fetch = runFetch\n\n if (!hasDataFromServer && options.lazy !== true) {\n runFetch(options.initParams)\n }\n\n onScopeDispose(() => {\n channel?.removeEventListener('message', onMessage)\n controller.abort(`Http Abort -> onScopeDispose ${options.url}`)\n\n if (serverData.value) {\n serverData.value = null\n }\n })\n }\n\n return result as UseHttpResult<T, P>\n }\n\n return useHttp\n}\n\nfunction createIsErrorGuard<TData>(\n localGuard?: (payload: TData) => boolean,\n globalGuard?: HttpErrorGuard<unknown>,\n): (payload: TData) => boolean {\n if (localGuard) {\n return localGuard\n }\n\n if (globalGuard) {\n return globalGuard as (payload: TData) => boolean\n }\n\n return (): boolean => false\n}\n\nfunction getChannel(name: string, currentChannel?: BroadcastChannel | null): BroadcastChannel | null {\n if (currentChannel) {\n return currentChannel\n }\n\n if (import.meta.server || typeof BroadcastChannel !== 'function') {\n return null\n }\n\n return new BroadcastChannel(name)\n}\n\nfunction getRandom(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\nfunction normalizeBroadcastValue<T>(payload: T): T {\n try {\n return structuredClone(payload)\n } catch {\n return JSON.parse(JSON.stringify(payload)) as T\n }\n}\n"],"mappings":"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"}
package/dist/nuxt.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as createUseHttp } from "./nuxt-BsZgB52H.js";
1
+ import { t as createUseHttp } from "./nuxt-CcmCJhA5.js";
2
2
  export { createUseHttp };
package/dist/utils.d.ts CHANGED
@@ -2,4 +2,8 @@ import type { HttpParam } from './http';
2
2
  export declare function createURL(url: string, params?: HttpParam): string;
3
3
  export declare function fastDevHash(data: unknown): string;
4
4
  export declare function hashData(data: unknown): Promise<string>;
5
+ export declare function resolveUrlParams(url: string, params?: HttpParam): {
6
+ params: HttpParam | undefined;
7
+ url: string;
8
+ };
5
9
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAEvC,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAoBjE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAWjD;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAY7D"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAEvC,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAqBjE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAWjD;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAY7D;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,SAAS,GACjB;IACD,MAAM,EAAE,SAAS,GAAG,SAAS,CAAA;IAC7B,GAAG,EAAE,MAAM,CAAA;CACZ,CAgCA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brickflow/http",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "description": "Minimal HTTP transport and Nuxt state helpers for brickflow.",
5
5
  "sideEffects": false,
6
6
  "files": [
@@ -36,13 +36,13 @@
36
36
  "access": "public"
37
37
  },
38
38
  "dependencies": {
39
- "@nuxt/kit": "4.4.7"
39
+ "@nuxt/kit": "4.4.8"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@brickflow/lint": "workspace:*",
43
43
  "@brickflow/prettier": "workspace:*",
44
- "rolldown": "1.1.0",
45
- "vue-tsc": "3.3.4"
44
+ "rolldown": "1.1.3",
45
+ "vue-tsc": "3.3.5"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "nuxt": ">=3",
package/src/create-get.ts CHANGED
@@ -2,14 +2,12 @@ import type { HttpClient, HttpKey, HttpParam, HttpResponseData } from './http'
2
2
  import type { HttpError, UseHttpFn, UseHttpOptions, UseHttpResult } from './nuxt'
3
3
 
4
4
  export interface CreateGetFactory<P extends HttpParam> {
5
- <T extends HttpKey>(
5
+ <D = never, T extends HttpKey = HttpKey>(
6
6
  url: T,
7
- payload?: CreateGetPayload<T, P>,
8
- ): (options?: CreateGetOptions<T, P>) => Promise<CreateGetResult<T, P>>
9
- <D>(
10
- url: HttpKey,
11
- payload?: CreateGetPayload<HttpKey, P, D>,
12
- ): (options?: CreateGetOptions<HttpKey, P, D>) => Promise<CreateGetResult<HttpKey, P, D>>
7
+ payload?: CreateGetPayload<T, CreateGetParams<T, P>, D>,
8
+ ): (
9
+ options?: CreateGetOptions<T, CreateGetParams<T, P>, D>,
10
+ ) => Promise<CreateGetResult<T, CreateGetParams<T, P>, D>>
13
11
  }
14
12
  export type CreateGetOptions<T extends HttpKey, P extends HttpParam, D = never> = Omit<
15
13
  UseHttpOptions<T, P>,
@@ -32,19 +30,30 @@ export type CreateGetResult<T extends HttpKey, P extends HttpParam, D = never> =
32
30
  }
33
31
 
34
32
  type CreateGetData<T extends HttpKey, D> = [D] extends [never] ? HttpResponseData<T> : D
35
-
36
33
  type CreateGetEffect<T extends HttpKey, P extends HttpParam, D = never> = (
37
34
  data: CreateGetData<T, D>,
38
35
  config: CreateGetEffectConfig<P>,
39
36
  ) => void
40
-
41
37
  type CreateGetEffectConfig<P extends HttpParam> = {
42
38
  cached: boolean
43
39
  params: P
44
40
  }
41
+ type CreateGetEmptyParams = Record<never, never>
45
42
 
46
43
  type CreateGetIsError<T extends HttpKey, D = never> = (payload: CreateGetData<T, D>) => boolean
47
44
 
45
+ type CreateGetParamKeys<T extends string> = T extends `${string}:${infer Rest}`
46
+ ? Rest extends `${infer Key}/${infer Tail}`
47
+ ? CreateGetParamKeys<`/${Tail}`> | Key
48
+ : Rest
49
+ : never
50
+ type CreateGetParams<T extends HttpKey, P extends HttpParam> = Omit<CreateGetPathParams<T>, keyof P> & P
51
+ type CreateGetPathParams<T extends HttpKey> = [CreateGetParamKeys<T>] extends [never]
52
+ ? CreateGetEmptyParams
53
+ : {
54
+ [K in CreateGetParamKeys<T>]: string
55
+ }
56
+
48
57
  export function createUseCase<D>() {
49
58
  return <T>(
50
59
  callback: (payload: D & { httpClient: HttpClient }) => T,
@@ -52,12 +61,16 @@ export function createUseCase<D>() {
52
61
  }
53
62
 
54
63
  export function defineGet(useHttp: UseHttpFn) {
55
- return function withParams<P extends HttpParam>(): CreateGetFactory<P> {
64
+ return function withParams<P extends HttpParam = CreateGetEmptyParams>(): CreateGetFactory<P> {
56
65
  function withUrl<T extends HttpKey, D = never>(
57
66
  url: T,
58
- payload?: CreateGetPayload<T, P, D>,
59
- ): (options?: CreateGetOptions<T, P, D>) => Promise<CreateGetResult<T, P, D>> {
60
- return async function request(options: CreateGetOptions<T, P, D> = {}): Promise<CreateGetResult<T, P, D>> {
67
+ payload?: CreateGetPayload<T, CreateGetParams<T, P>, D>,
68
+ ): (
69
+ options?: CreateGetOptions<T, CreateGetParams<T, P>, D>,
70
+ ) => Promise<CreateGetResult<T, CreateGetParams<T, P>, D>> {
71
+ return async function request(
72
+ options: CreateGetOptions<T, CreateGetParams<T, P>, D> = {},
73
+ ): Promise<CreateGetResult<T, CreateGetParams<T, P>, D>> {
61
74
  const result = await useHttp({
62
75
  ...options,
63
76
  effect: (data, config) => {
@@ -67,9 +80,9 @@ export function defineGet(useHttp: UseHttpFn) {
67
80
  isError: options.isError ?? payload?.isError,
68
81
  mapParams: options.mapParams ?? payload?.mapParams,
69
82
  url,
70
- } as UseHttpOptions<T, P>)
83
+ } as UseHttpOptions<T, CreateGetParams<T, P>>)
71
84
 
72
- return result as CreateGetResult<T, P, D>
85
+ return result as CreateGetResult<T, CreateGetParams<T, P>, D>
73
86
  }
74
87
  }
75
88
 
package/src/http.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { resolveUrlParams } from './utils'
2
+
1
3
  export interface CreateHttpOptions {
2
4
  arrayMode?: HttpArrayMode
3
5
  baseURL: string
@@ -78,7 +80,8 @@ export function createHttp(options: CreateHttpOptions): HttpClient {
78
80
  return {
79
81
  get<T extends HttpKey, TConfig extends GetConfig<T> = GetConfig<T>>(url: T, config?: TConfig) {
80
82
  const requestConfig = (config ?? {}) as TConfig
81
- const requestUrl = `${joinUrl(options.baseURL, url)}${toQueryString(requestConfig.params, arrayMode)}`
83
+ const resolved = resolveUrlParams(url, requestConfig.params)
84
+ const requestUrl = `${joinUrl(options.baseURL, resolved.url)}${toQueryString(resolved.params, arrayMode)}`
82
85
  const { delay = 300, retries = 3 } = requestConfig.retry ?? {}
83
86
 
84
87
  const attemptRequest = async (attempt: number): Promise<HttpResponse<HttpResponseData<T>, T, TConfig>> => {
@@ -92,7 +95,10 @@ export function createHttp(options: CreateHttpOptions): HttpClient {
92
95
 
93
96
  const parsedResult = await result.json()
94
97
  const response: HttpResponse<HttpResponseData<T>, T, TConfig> = {
95
- config: createResponseConfig<T, TConfig>(joinUrl(options.baseURL, url), requestConfig),
98
+ config: createResponseConfig<T, TConfig>(joinUrl(options.baseURL, resolved.url), {
99
+ ...requestConfig,
100
+ params: resolved.params,
101
+ }),
96
102
  data: parsedResult,
97
103
  status: result.status,
98
104
  }
@@ -123,7 +129,8 @@ export function createHttp(options: CreateHttpOptions): HttpClient {
123
129
  >(url: T, data?: HttpPostData<TData>, config?: TConfig) {
124
130
  const requestConfig = (config ?? {}) as TConfig
125
131
  const isForm = isFormData(data)
126
- const requestUrl = `${joinUrl(options.baseURL, url)}${toQueryString(requestConfig.params, arrayMode)}`
132
+ const resolved = resolveUrlParams(url, requestConfig.params)
133
+ const requestUrl = `${joinUrl(options.baseURL, resolved.url)}${toQueryString(resolved.params, arrayMode)}`
127
134
  const response = await clientFetch(requestUrl, {
128
135
  body: isForm || data === undefined ? data : JSON.stringify(data),
129
136
  credentials: 'include',
@@ -143,7 +150,10 @@ export function createHttp(options: CreateHttpOptions): HttpClient {
143
150
  }
144
151
 
145
152
  const parsedResponse: HttpResponse<HttpResponseData<T>, T, TConfig> = {
146
- config: createResponseConfig<T, TConfig>(joinUrl(options.baseURL, url), requestConfig),
153
+ config: createResponseConfig<T, TConfig>(joinUrl(options.baseURL, resolved.url), {
154
+ ...requestConfig,
155
+ params: resolved.params,
156
+ }),
147
157
  data: parsedResult,
148
158
  status: response.status,
149
159
  }
package/src/utils.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import type { HttpParam } from './http'
2
2
 
3
3
  export function createURL(url: string, params?: HttpParam): string {
4
+ const resolved = resolveUrlParams(url, params)
4
5
  const urlParams = new URLSearchParams()
5
6
 
6
- Object.entries(params ?? {}).forEach(([key, value]) => {
7
+ Object.entries(resolved.params ?? {}).forEach(([key, value]) => {
7
8
  if (value === undefined) {
8
9
  return
9
10
  }
@@ -19,7 +20,7 @@ export function createURL(url: string, params?: HttpParam): string {
19
20
  })
20
21
 
21
22
  const query = urlParams.size > 0 ? `?${urlParams}` : ''
22
- return urlParams.size > 0 ? `${url}${query}` : url
23
+ return urlParams.size > 0 ? `${resolved.url}${query}` : resolved.url
23
24
  }
24
25
 
25
26
  export function fastDevHash(data: unknown): string {
@@ -48,3 +49,43 @@ export async function hashData(data: unknown): Promise<string> {
48
49
 
49
50
  return fastDevHash(data)
50
51
  }
52
+
53
+ export function resolveUrlParams(
54
+ url: string,
55
+ params?: HttpParam,
56
+ ): {
57
+ params: HttpParam | undefined
58
+ url: string
59
+ } {
60
+ if (!params) {
61
+ return {
62
+ params,
63
+ url,
64
+ }
65
+ }
66
+
67
+ const usedKeys: Record<string, true> = {}
68
+ const resolvedUrl = url.replaceAll(/:(\w+)/g, (segment, key: string) => {
69
+ const value = params[key]
70
+
71
+ if (value === undefined) {
72
+ return segment
73
+ }
74
+
75
+ usedKeys[key] = true
76
+ return encodeURIComponent(String(value))
77
+ })
78
+ const queryParams = Object.entries(params).reduce<HttpParam>((acc, [key, value]) => {
79
+ if (usedKeys[key]) {
80
+ return acc
81
+ }
82
+
83
+ acc[key] = value
84
+ return acc
85
+ }, {})
86
+
87
+ return {
88
+ params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
89
+ url: resolvedUrl,
90
+ }
91
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"nuxt-BsZgB52H.js","names":[],"sources":["../src/utils.ts","../src/nuxt.ts"],"sourcesContent":["import type { HttpParam } from './http'\n\nexport function createURL(url: string, params?: HttpParam): string {\n const urlParams = new URLSearchParams()\n\n Object.entries(params ?? {}).forEach(([key, value]) => {\n if (value === undefined) {\n return\n }\n\n if (Array.isArray(value)) {\n value.forEach((item) => {\n urlParams.append(`${key}[]`, item)\n })\n return\n }\n\n urlParams.append(key, String(value))\n })\n\n const query = urlParams.size > 0 ? `?${urlParams}` : ''\n return urlParams.size > 0 ? `${url}${query}` : url\n}\n\nexport function fastDevHash(data: unknown): string {\n const str = JSON.stringify(data)\n let hash = 0\n\n for (let i = 0; i < str.length; i++) {\n const chr = str.charCodeAt(i)\n hash = (hash << 5) - hash + chr\n hash |= 0\n }\n\n return Math.abs(hash).toString(16)\n}\n\nexport async function hashData(data: unknown): Promise<string> {\n const subtle = globalThis.crypto?.subtle\n\n if (subtle) {\n const encoded = new TextEncoder().encode(JSON.stringify(data))\n const buffer = await subtle.digest('SHA-1', encoded)\n const array = Array.from(new Uint8Array(buffer))\n\n return array.map((value) => value.toString(16).padStart(2, '0')).join('')\n }\n\n return fastDevHash(data)\n}\n","import { useLazyAsyncData, useState } from 'nuxt/app'\nimport { onScopeDispose, shallowReactive, shallowRef } from 'vue'\n\nimport type { GetConfig, HttpClient, HttpErrorGuard, HttpKey, HttpParam, HttpResponseData } from './http'\n\nimport { createURL, hashData } from './utils'\n\nconst DAY = 1000 * 60 * 60 * 24\nconst DEFAULT_CHANNEL_NAME = 'http-tab-sync'\nconst DEFAULT_TTL = DAY * 7\nexport interface CreateUseHttpDependencies {\n channelName?: string\n getCache: () => null | UseHttpCache\n getHttpClient: () => HttpClient\n isDev?: () => boolean\n isError?: HttpErrorGuard<unknown>\n ttl?: number\n}\n\nexport type HttpError = HttpErrorMap[keyof HttpErrorMap]\nexport interface HttpErrorMap {}\nexport type HttpSuccessData<TKey extends HttpKey = HttpKey> = Exclude<HttpResponseData<TKey>, HttpError>\n\nexport interface UseHttpCache {\n deleteKeysWithPart: (part: string) => Promise<void>\n get: <T>(key: string) => Promise<null | UseHttpCacheEntry<T>>\n set: <T>(key: string, value: T, ttl: number) => Promise<void>\n}\n\nexport interface UseHttpCacheEntry<T> {\n hash: string\n value: T\n}\n\nexport interface UseHttpFn {\n <T extends HttpKey, P extends HttpParam>(options: UseHttpOptions<T, P>): Promise<UseHttpResult<T, P>>\n}\n\nexport interface UseHttpOptions<T extends HttpKey, P extends HttpParam> {\n effect?: UseHttpEffect<T, P>\n initParams?: P\n isError?: (payload: HttpResponseData<T>) => boolean\n lazy?: true\n mapParams?: (params?: P) => P\n server?: boolean\n url: T\n}\n\nexport interface UseHttpResult<T extends HttpKey, P extends HttpParam> {\n data: HttpSuccessData<T> | null\n error: null | UseHttpError<T>\n fetch: UseHttpFetch<P>\n hasFirstData: boolean\n hasFreshData: boolean\n pending: boolean\n pendingCache: boolean\n}\n\ntype BroadcastMessage = {\n data: unknown\n fullUrl: string\n params: HttpParam\n type: 'STATE_UPDATE'\n}\n\ntype UseHttpEffect<T extends HttpKey, P extends HttpParam> = (\n data: HttpResponseData<T>,\n config: UseHttpEffectConfig<P>,\n) => void\ntype UseHttpEffectConfig<P extends HttpParam> = {\n cached: boolean\n params: P\n}\ntype UseHttpError<T extends HttpKey> = Extract<HttpResponseData<T>, HttpError>\n\ntype UseHttpFetch<P extends HttpParam> = (params?: P, opt?: { signal: AbortSignal }) => Promise<void>\n\nexport function createUseHttp(dependencies: CreateUseHttpDependencies): UseHttpFn {\n let channel: BroadcastChannel | null\n\n const useHttp: UseHttpFn = async <T extends HttpKey, P extends HttpParam>(\n options: UseHttpOptions<T, P>,\n ): Promise<UseHttpResult<T, P>> => {\n const mapParams = (params?: P): P => {\n if (options.mapParams) {\n return options.mapParams(params)\n }\n\n return params ?? ({} as P)\n }\n const effect = options.effect\n const isError = createIsErrorGuard(options.isError, dependencies.isError)\n\n const buildUrl = createURL\n const initFullUrl = buildUrl(options.url, mapParams(options.initParams))\n const httpClient = dependencies.getHttpClient()\n const cache = import.meta.client ? (dependencies.getCache?.() ?? null) : null\n let hasDataFromServer = false\n\n const result = shallowReactive({\n data: null as null | unknown,\n error: null as null | unknown,\n fetch: async (_params?: P, _opt?: { signal: AbortSignal }): Promise<void> => await undefined,\n hasFirstData: false,\n hasFreshData: false,\n pending: true,\n pendingCache: true,\n })\n const setError = (value: null | unknown): void => {\n result.error = value\n }\n const setData = (value: null | unknown): void => {\n result.data = value\n }\n const syncResult = (payload: HttpResponseData<T> | null | undefined): void => {\n if (payload === null || payload === undefined) {\n setData(null)\n setError(null)\n return\n }\n\n if (isError(payload)) {\n setData(null)\n setError(payload)\n return\n }\n\n setData(payload)\n setError(null)\n }\n\n const controller = new AbortController()\n const serverData = useState<null | unknown>(`http-${initFullUrl}`, () => null)\n\n if (options.server && import.meta.server) {\n const paramsReactive = shallowRef(mapParams(options.initParams))\n const ssr = await useLazyAsyncData(initFullUrl, async () => {\n return await httpClient.get<T>(options.url, {\n params: paramsReactive.value,\n } as GetConfig<T>)\n })\n\n result.fetch = async (params?: P) => {\n paramsReactive.value = mapParams(params)\n await ssr.refresh()\n }\n\n serverData.value = ssr.data.value?.data ?? null\n const serverPayload = serverData.value as HttpResponseData<T>\n syncResult(serverPayload)\n\n result.pending = false\n result.pendingCache = false\n result.hasFirstData = true\n result.hasFreshData = true\n\n if (serverData.value) {\n effect?.(serverData.value as HttpResponseData<T>, {\n cached: false,\n params: mapParams(options.initParams),\n })\n }\n\n if (result.data) {\n hasDataFromServer = true\n }\n }\n\n if (import.meta.client) {\n channel = getChannel(dependencies.channelName ?? DEFAULT_CHANNEL_NAME, channel)\n const fullUrlHistory: Record<string, true> = {}\n\n function onMessage(event: MessageEvent<Partial<BroadcastMessage>>): void {\n if (event.data.fullUrl && fullUrlHistory[event.data.fullUrl]) {\n const eventPayload = event.data.data as HttpResponseData<T> | undefined\n\n if (eventPayload) {\n effect?.(eventPayload, {\n cached: false,\n params: event.data.params as P,\n })\n }\n\n syncResult(eventPayload)\n\n result.hasFirstData = true\n result.hasFreshData = true\n }\n }\n\n channel?.addEventListener('message', onMessage)\n\n if (serverData.value) {\n const clientServerPayload = serverData.value as HttpResponseData<T>\n syncResult(clientServerPayload)\n result.pending = false\n result.pendingCache = false\n result.hasFirstData = true\n result.hasFreshData = true\n }\n\n const raceCondition: Record<string, number> = {}\n const ttl = dependencies.ttl ?? DEFAULT_TTL\n\n const runFetch = async (params?: P, fetchOpt?: { signal?: AbortSignal }): Promise<void> => {\n const mappedParams = mapParams(params)\n const fullUrl = buildUrl(options.url, mappedParams)\n const fetchId = Date.now() + getRandom(0, 300)\n\n if (raceCondition[fullUrl]) {\n console.info('Race Condition affect', fullUrl)\n return\n }\n\n raceCondition[fullUrl] = fetchId\n\n try {\n result.pending = true\n result.pendingCache = true\n\n const cachedFetch = cache && !dependencies.isDev?.() ? await cache.get<unknown>(fullUrl) : null\n\n if (cachedFetch) {\n const cachedPayload = cachedFetch.value as HttpResponseData<T>\n\n effect?.(cachedPayload, {\n cached: true,\n params: mappedParams,\n })\n\n syncResult(cachedPayload)\n result.hasFirstData = true\n\n result.pendingCache = false\n }\n\n if (controller.signal.aborted || fetchOpt?.signal?.aborted) {\n throw new DOMException('Aborted', 'AbortError')\n }\n\n const signalHttp = fetchOpt?.signal ? [controller.signal, fetchOpt.signal] : controller.signal\n const response = await httpClient.get<T>(options.url, {\n params: mappedParams,\n signal: signalHttp,\n } as GetConfig<T>)\n const responsePayload = response.data as HttpResponseData<T>\n\n effect?.(responsePayload, {\n cached: false,\n params: mappedParams,\n })\n\n if (isError(responsePayload)) {\n syncResult(responsePayload)\n } else {\n syncResult(responsePayload)\n const successData = responsePayload\n\n fullUrlHistory[fullUrl] = true\n channel?.postMessage({\n data: normalizeBroadcastValue(successData),\n fullUrl,\n params: normalizeBroadcastValue(mappedParams),\n type: 'STATE_UPDATE',\n } satisfies BroadcastMessage)\n\n if (cache) {\n if (cachedFetch) {\n const newHash = await hashData(responsePayload)\n if (newHash !== cachedFetch.hash) {\n await cache.deleteKeysWithPart(options.url)\n }\n }\n\n if (response.status === 200) {\n await cache.set(fullUrl, successData, ttl)\n }\n }\n }\n\n result.hasFirstData = true\n result.hasFreshData = true\n } catch (error) {\n console.error(error)\n } finally {\n if (raceCondition[fullUrl] === fetchId) {\n delete raceCondition[fullUrl]\n }\n\n result.pending = false\n result.pendingCache = false\n }\n }\n\n result.fetch = runFetch\n\n if (!hasDataFromServer && options.lazy !== true) {\n runFetch(options.initParams)\n }\n\n onScopeDispose(() => {\n channel?.removeEventListener('message', onMessage)\n controller.abort(`Http Abort -> onScopeDispose ${options.url}`)\n\n if (serverData.value) {\n serverData.value = null\n }\n })\n }\n\n return result as UseHttpResult<T, P>\n }\n\n return useHttp\n}\n\nfunction createIsErrorGuard<TData>(\n localGuard?: (payload: TData) => boolean,\n globalGuard?: HttpErrorGuard<unknown>,\n): (payload: TData) => boolean {\n if (localGuard) {\n return localGuard\n }\n\n if (globalGuard) {\n return globalGuard as (payload: TData) => boolean\n }\n\n return (): boolean => false\n}\n\nfunction getChannel(name: string, currentChannel?: BroadcastChannel | null): BroadcastChannel | null {\n if (currentChannel) {\n return currentChannel\n }\n\n if (import.meta.server || typeof BroadcastChannel !== 'function') {\n return null\n }\n\n return new BroadcastChannel(name)\n}\n\nfunction getRandom(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\nfunction normalizeBroadcastValue<T>(payload: T): T {\n try {\n return structuredClone(payload)\n } catch {\n return JSON.parse(JSON.stringify(payload)) as T\n }\n}\n"],"mappings":";;;AAEA,SAAgB,UAAU,KAAa,QAA4B;CACjE,MAAM,YAAY,IAAI,gBAAgB;CAEtC,OAAO,QAAQ,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,WAAW;EACrD,IAAI,UAAU,KAAA,GACZ;EAGF,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,MAAM,SAAS,SAAS;IACtB,UAAU,OAAO,GAAG,IAAI,KAAK,IAAI;GACnC,CAAC;GACD;EACF;EAEA,UAAU,OAAO,KAAK,OAAO,KAAK,CAAC;CACrC,CAAC;CAED,MAAM,QAAQ,UAAU,OAAO,IAAI,IAAI,cAAc;CACrD,OAAO,UAAU,OAAO,IAAI,GAAG,MAAM,UAAU;AACjD;AAEA,SAAgB,YAAY,MAAuB;CACjD,MAAM,MAAM,KAAK,UAAU,IAAI;CAC/B,IAAI,OAAO;CAEX,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;EACnC,MAAM,MAAM,IAAI,WAAW,CAAC;EAC5B,QAAQ,QAAQ,KAAK,OAAO;EAC5B,QAAQ;CACV;CAEA,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,EAAE;AACnC;AAEA,eAAsB,SAAS,MAAgC;CAC7D,MAAM,SAAS,WAAW,QAAQ;CAElC,IAAI,QAAQ;EACV,MAAM,UAAU,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,UAAU,IAAI,CAAC;EAC7D,MAAM,SAAS,MAAM,OAAO,OAAO,SAAS,OAAO;EAGnD,OAFc,MAAM,KAAK,IAAI,WAAW,MAAM,CAEnC,CAAC,CAAC,KAAK,UAAU,MAAM,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;CAC1E;CAEA,OAAO,YAAY,IAAI;AACzB;;;AC1CA,MAAM,MAAM,MAAO,KAAK,KAAK;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,cAAc,MAAM;AAoE1B,SAAgB,cAAc,cAAoD;CAChF,IAAI;CAEJ,MAAM,UAAqB,OACzB,YACiC;EACjC,MAAM,aAAa,WAAkB;GACnC,IAAI,QAAQ,WACV,OAAO,QAAQ,UAAU,MAAM;GAGjC,OAAO,UAAW,CAAC;EACrB;EACA,MAAM,SAAS,QAAQ;EACvB,MAAM,UAAU,mBAAmB,QAAQ,SAAS,aAAa,OAAO;EAExE,MAAM,WAAW;EACjB,MAAM,cAAc,SAAS,QAAQ,KAAK,UAAU,QAAQ,UAAU,CAAC;EACvE,MAAM,aAAa,aAAa,cAAc;EAC9C,MAAM,QAAQ,OAAO,KAAK,SAAU,aAAa,WAAW,KAAK,OAAQ;EACzE,IAAI,oBAAoB;EAExB,MAAM,SAAS,gBAAgB;GAC7B,MAAM;GACN,OAAO;GACP,OAAO,OAAO,SAAa,SAAkD,MAAM,KAAA;GACnF,cAAc;GACd,cAAc;GACd,SAAS;GACT,cAAc;EAChB,CAAC;EACD,MAAM,YAAY,UAAgC;GAChD,OAAO,QAAQ;EACjB;EACA,MAAM,WAAW,UAAgC;GAC/C,OAAO,OAAO;EAChB;EACA,MAAM,cAAc,YAA0D;GAC5E,IAAI,YAAY,QAAQ,YAAY,KAAA,GAAW;IAC7C,QAAQ,IAAI;IACZ,SAAS,IAAI;IACb;GACF;GAEA,IAAI,QAAQ,OAAO,GAAG;IACpB,QAAQ,IAAI;IACZ,SAAS,OAAO;IAChB;GACF;GAEA,QAAQ,OAAO;GACf,SAAS,IAAI;EACf;EAEA,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,aAAa,SAAyB,QAAQ,qBAAqB,IAAI;EAE7E,IAAI,QAAQ,UAAU,OAAO,KAAK,QAAQ;GACxC,MAAM,iBAAiB,WAAW,UAAU,QAAQ,UAAU,CAAC;GAC/D,MAAM,MAAM,MAAM,iBAAiB,aAAa,YAAY;IAC1D,OAAO,MAAM,WAAW,IAAO,QAAQ,KAAK,EAC1C,QAAQ,eAAe,MACzB,CAAiB;GACnB,CAAC;GAED,OAAO,QAAQ,OAAO,WAAe;IACnC,eAAe,QAAQ,UAAU,MAAM;IACvC,MAAM,IAAI,QAAQ;GACpB;GAEA,WAAW,QAAQ,IAAI,KAAK,OAAO,QAAQ;GAC3C,MAAM,gBAAgB,WAAW;GACjC,WAAW,aAAa;GAExB,OAAO,UAAU;GACjB,OAAO,eAAe;GACtB,OAAO,eAAe;GACtB,OAAO,eAAe;GAEtB,IAAI,WAAW,OACb,SAAS,WAAW,OAA8B;IAChD,QAAQ;IACR,QAAQ,UAAU,QAAQ,UAAU;GACtC,CAAC;GAGH,IAAI,OAAO,MACT,oBAAoB;EAExB;EAEA,IAAI,OAAO,KAAK,QAAQ;GACtB,UAAU,WAAW,aAAa,eAAe,sBAAsB,OAAO;GAC9E,MAAM,iBAAuC,CAAC;GAE9C,SAAS,UAAU,OAAsD;IACvE,IAAI,MAAM,KAAK,WAAW,eAAe,MAAM,KAAK,UAAU;KAC5D,MAAM,eAAe,MAAM,KAAK;KAEhC,IAAI,cACF,SAAS,cAAc;MACrB,QAAQ;MACR,QAAQ,MAAM,KAAK;KACrB,CAAC;KAGH,WAAW,YAAY;KAEvB,OAAO,eAAe;KACtB,OAAO,eAAe;IACxB;GACF;GAEA,SAAS,iBAAiB,WAAW,SAAS;GAE9C,IAAI,WAAW,OAAO;IACpB,MAAM,sBAAsB,WAAW;IACvC,WAAW,mBAAmB;IAC9B,OAAO,UAAU;IACjB,OAAO,eAAe;IACtB,OAAO,eAAe;IACtB,OAAO,eAAe;GACxB;GAEA,MAAM,gBAAwC,CAAC;GAC/C,MAAM,MAAM,aAAa,OAAO;GAEhC,MAAM,WAAW,OAAO,QAAY,aAAuD;IACzF,MAAM,eAAe,UAAU,MAAM;IACrC,MAAM,UAAU,SAAS,QAAQ,KAAK,YAAY;IAClD,MAAM,UAAU,KAAK,IAAI,IAAI,UAAU,GAAG,GAAG;IAE7C,IAAI,cAAc,UAAU;KAC1B,QAAQ,KAAK,yBAAyB,OAAO;KAC7C;IACF;IAEA,cAAc,WAAW;IAEzB,IAAI;KACF,OAAO,UAAU;KACjB,OAAO,eAAe;KAEtB,MAAM,cAAc,SAAS,CAAC,aAAa,QAAQ,IAAI,MAAM,MAAM,IAAa,OAAO,IAAI;KAE3F,IAAI,aAAa;MACf,MAAM,gBAAgB,YAAY;MAElC,SAAS,eAAe;OACtB,QAAQ;OACR,QAAQ;MACV,CAAC;MAED,WAAW,aAAa;MACxB,OAAO,eAAe;MAEtB,OAAO,eAAe;KACxB;KAEA,IAAI,WAAW,OAAO,WAAW,UAAU,QAAQ,SACjD,MAAM,IAAI,aAAa,WAAW,YAAY;KAGhD,MAAM,aAAa,UAAU,SAAS,CAAC,WAAW,QAAQ,SAAS,MAAM,IAAI,WAAW;KACxF,MAAM,WAAW,MAAM,WAAW,IAAO,QAAQ,KAAK;MACpD,QAAQ;MACR,QAAQ;KACV,CAAiB;KACjB,MAAM,kBAAkB,SAAS;KAEjC,SAAS,iBAAiB;MACxB,QAAQ;MACR,QAAQ;KACV,CAAC;KAED,IAAI,QAAQ,eAAe,GACzB,WAAW,eAAe;UACrB;MACL,WAAW,eAAe;MAC1B,MAAM,cAAc;MAEpB,eAAe,WAAW;MAC1B,SAAS,YAAY;OACnB,MAAM,wBAAwB,WAAW;OACzC;OACA,QAAQ,wBAAwB,YAAY;OAC5C,MAAM;MACR,CAA4B;MAE5B,IAAI,OAAO;OACT,IAAI;YAEE,MADkB,SAAS,eAAe,MAC9B,YAAY,MAC1B,MAAM,MAAM,mBAAmB,QAAQ,GAAG;OAAA;OAI9C,IAAI,SAAS,WAAW,KACtB,MAAM,MAAM,IAAI,SAAS,aAAa,GAAG;MAE7C;KACF;KAEA,OAAO,eAAe;KACtB,OAAO,eAAe;IACxB,SAAS,OAAO;KACd,QAAQ,MAAM,KAAK;IACrB,UAAU;KACR,IAAI,cAAc,aAAa,SAC7B,OAAO,cAAc;KAGvB,OAAO,UAAU;KACjB,OAAO,eAAe;IACxB;GACF;GAEA,OAAO,QAAQ;GAEf,IAAI,CAAC,qBAAqB,QAAQ,SAAS,MACzC,SAAS,QAAQ,UAAU;GAG7B,qBAAqB;IACnB,SAAS,oBAAoB,WAAW,SAAS;IACjD,WAAW,MAAM,gCAAgC,QAAQ,KAAK;IAE9D,IAAI,WAAW,OACb,WAAW,QAAQ;GAEvB,CAAC;EACH;EAEA,OAAO;CACT;CAEA,OAAO;AACT;AAEA,SAAS,mBACP,YACA,aAC6B;CAC7B,IAAI,YACF,OAAO;CAGT,IAAI,aACF,OAAO;CAGT,aAAsB;AACxB;AAEA,SAAS,WAAW,MAAc,gBAAmE;CACnG,IAAI,gBACF,OAAO;CAGT,IAAI,OAAO,KAAK,UAAU,OAAO,qBAAqB,YACpD,OAAO;CAGT,OAAO,IAAI,iBAAiB,IAAI;AAClC;AAEA,SAAS,UAAU,KAAa,KAAqB;CACnD,OAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;AACvD;AAEA,SAAS,wBAA2B,SAAe;CACjD,IAAI;EACF,OAAO,gBAAgB,OAAO;CAChC,QAAQ;EACN,OAAO,KAAK,MAAM,KAAK,UAAU,OAAO,CAAC;CAC3C;AACF"}