@brickflow/http 0.0.14 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +272 -288
  2. package/dist/create-get.d.ts +12 -0
  3. package/dist/create-get.d.ts.map +1 -0
  4. package/dist/http.d.ts +46 -0
  5. package/dist/http.d.ts.map +1 -0
  6. package/dist/index.d.ts +4 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.mjs +171 -0
  9. package/dist/index.mjs.map +1 -0
  10. package/dist/nuxt-DAmJOX58.js +233 -0
  11. package/dist/nuxt-DAmJOX58.js.map +1 -0
  12. package/dist/nuxt.d.ts +55 -0
  13. package/dist/nuxt.d.ts.map +1 -0
  14. package/dist/nuxt.mjs +2 -0
  15. package/dist/utils.d.ts +5 -0
  16. package/dist/utils.d.ts.map +1 -0
  17. package/package.json +30 -18
  18. package/src/app.d.ts +11 -0
  19. package/src/create-get.ts +43 -0
  20. package/src/http.ts +286 -0
  21. package/src/index.ts +3 -0
  22. package/src/nuxt.ts +355 -0
  23. package/src/utils.ts +50 -0
  24. package/dist/module.d.mts +0 -73
  25. package/dist/module.json +0 -12
  26. package/dist/module.mjs +0 -59
  27. package/dist/runtime/composables/useHttp.d.ts +0 -27
  28. package/dist/runtime/composables/useHttp.js +0 -197
  29. package/dist/runtime/http/client.d.ts +0 -3
  30. package/dist/runtime/http/client.js +0 -217
  31. package/dist/runtime/plugin.d.ts +0 -7
  32. package/dist/runtime/plugin.js +0 -56
  33. package/dist/runtime/types.d.ts +0 -21
  34. package/dist/runtime/utils/helpers.d.ts +0 -5
  35. package/dist/runtime/utils/helpers.js +0 -14
  36. package/dist/runtime/utils/index.d.ts +0 -6
  37. package/dist/runtime/utils/index.js +0 -5
  38. package/dist/runtime/utils/indexeddb.d.ts +0 -14
  39. package/dist/runtime/utils/indexeddb.js +0 -222
  40. package/dist/runtime/utils/middleware.d.ts +0 -8
  41. package/dist/runtime/utils/middleware.js +0 -20
  42. package/dist/runtime/utils/shared.d.ts +0 -83
  43. package/dist/runtime/utils/shared.js +0 -50
  44. package/dist/runtime/utils/typed.d.ts +0 -46
  45. package/dist/runtime/utils/typed.js +0 -9
  46. package/dist/types.d.mts +0 -11
package/README.md CHANGED
@@ -1,406 +1,390 @@
1
- # `@brickflow/http`
1
+ # @brickflow/http
2
2
 
3
- Nuxt HTTP module and typed client with:
3
+ Минимальный HTTP-пакет для brickflow:
4
4
 
5
- - `NuxtApp.$http`
6
- - `useHttp()` auto-import
7
- - request/response middleware
8
- - retry and timeout support
9
- - optional client cache via IndexedDB
10
- - typed URL literals for `get`, `post`, and `useHttp`
5
+ - `createHttp` для низкоуровневых `GET`/`POST`
6
+ - `createUseHttp` для Nuxt state-обёртки с cache, SSR и ручным `fetch`
7
+ - `defineGet` для типизированных endpoint-фабрик
8
+ - `createUseCase` для DI-паттерна в доменных модулях
11
9
 
12
- ## Install
10
+ Актуальные примеры в репозитории лежат в `apps/playground`.
13
11
 
14
- ```bash
15
- pnpm add @brickflow/http
16
- ```
12
+ ## Exports
17
13
 
18
- ## Nuxt Setup
14
+ Рекомендуемый импорт:
19
15
 
20
16
  ```ts
21
- export default defineNuxtConfig({
22
- modules: ['@brickflow/http'],
23
- })
17
+ import { createHttp, createUseHttp, createUseCase, defineGet } from '@brickflow/http'
24
18
  ```
25
19
 
26
- With options:
20
+ Из пакета также экспортируются:
21
+
22
+ - `createURL`
23
+ - `hashData`
24
+ - типы `HttpClient`, `HttpConfig`, `HttpEndpoint`, `HttpKey`, `HttpParam`, `HttpResponse`, `HttpResponseData`
25
+ - Nuxt-типы `UseHttpFn`, `UseHttpOptions`, `UseHttpResult`
26
+
27
+ Сабпуть `@brickflow/http/nuxt` остаётся доступным, но в текущей кодовой базе `playground` использует импорты из корня.
28
+
29
+ ## Типизация API
30
+
31
+ Пакет не знает схему вашего API заранее. Её нужно объявить в проекте через `declare module '@brickflow/http'`.
32
+
33
+ Актуальный пример из `apps/playground/types/http.d.ts`:
27
34
 
28
35
  ```ts
29
- export default defineNuxtConfig({
30
- modules: ['@brickflow/http'],
31
- brickflowHttp: {
32
- baseURL: 'https://api.example.com',
33
- cache: true,
34
- cacheDbName: 'smart-cache-v2',
35
- cacheStoreName: 'data',
36
- cacheTtlMs: 1000 * 60 * 60 * 24 * 7,
37
- clientEnvHeader: true,
38
- defaultHeaders: {
39
- 'X-App-Version': '1.0.0',
40
- },
41
- disableCacheInDev: true,
42
- requestTimeoutMs: 80000,
43
- retry: {
44
- delay: 300,
45
- retries: 3,
46
- },
47
- },
48
- })
49
- ```
36
+ import type { HttpKey, HttpResponseData } from '@brickflow/http'
37
+
38
+ type Convention = {
39
+ '/api/http-error-demo': null
40
+ '/products':
41
+ | {
42
+ limit: number
43
+ products: {
44
+ category: string
45
+ id: number
46
+ price: number
47
+ rating: number
48
+ thumbnail: string
49
+ title: string
50
+ }[]
51
+ skip: number
52
+ total: number
53
+ }
54
+ | {
55
+ message: 'error'
56
+ }
57
+ }
58
+
59
+ declare module '@brickflow/http' {
60
+ interface HttpConfig<TKey extends HttpKey = HttpKey> {
61
+ ignore?: (data: HttpResponseData<TKey>) => boolean
62
+ }
50
63
 
51
- ## Defaults
64
+ interface HttpEndpoint extends Convention {}
65
+ }
52
66
 
53
- `brickflowHttp` defaults:
67
+ export {}
68
+ ```
54
69
 
55
- | Option | Default |
56
- | ------------------- | ------------------ |
57
- | `baseURL` | `''` |
58
- | `cache` | `true` |
59
- | `cacheDbName` | `'smart-cache-v2'` |
60
- | `cacheStoreName` | `'data'` |
61
- | `cacheTtlMs` | `604800000` |
62
- | `clientEnvHeader` | `true` |
63
- | `defaultHeaders` | `{}` |
64
- | `disableCacheInDev` | `true` |
65
- | `requestTimeoutMs` | `80000` |
66
- | `retry.delay` | `300` |
67
- | `retry.retries` | `3` |
70
+ Что это даёт:
68
71
 
69
- Runtime behavior:
72
+ - `HttpKey` становится union из endpoint-ключей
73
+ - `httpClient.get('/products')` получает корректный тип ответа
74
+ - `createGet<Params>()('/products')` наследует тот же контракт
75
+ - `HttpConfig` можно расширять своими полями, как в playground через `ignore`
70
76
 
71
- - `X-Requested-With: XMLHttpRequest` is added automatically
72
- - in dev, `Client-Env: development` is added when `clientEnvHeader` is enabled
73
- - `5xx` and `451` responses with `{ status: 'error' }` trigger Nuxt `showError()`
77
+ Если нужен типизированный `error` в `UseHttpResult`, дополнительно расширьте `HttpErrorMap`. По умолчанию `error` имеет тип `never`, а разделение между `data` и `error` зависит только от runtime `isError`.
74
78
 
75
- ## Basic Usage
79
+ ## createHttp
76
80
 
77
- Use `$http` in components, composables, or plugins:
81
+ Актуальный пример из `apps/playground/plugins/01.di.ts`:
78
82
 
79
83
  ```ts
80
- const { $http } = useNuxtApp()
84
+ import { createHttp } from '@brickflow/http'
81
85
 
82
- const response = await $http.get<{ id: string; name: string }>('/user', {
83
- params: {
84
- id: '42',
86
+ import { handlePlaygroundResponse } from '~/core/http-error'
87
+
88
+ const httpClient = createHttp({
89
+ baseURL: 'https://dummyjson.com',
90
+ headers: {
91
+ 'X-Playground-Http': 'playground-runtime',
85
92
  },
93
+ onResponse: handlePlaygroundResponse,
86
94
  })
87
-
88
- if ('status' in response.data && response.data.status === 'error') {
89
- console.error(response.data.message)
90
- } else {
91
- console.log(response.data.name)
92
- }
93
95
  ```
94
96
 
95
- POST:
97
+ Поддерживаемые опции:
96
98
 
97
- ```ts
98
- const { $http } = useNuxtApp()
99
+ - `baseURL: string`
100
+ - `arrayMode?: 'json' | 'repeat'`
101
+ - `fetch?: typeof fetch`
102
+ - `headers?: Record<string, string | undefined> | (() => Record<string, string | undefined>)`
103
+ - `onResponse?: (response) => void | Promise<void>`
104
+ - `timeout?: number`
105
+
106
+ ### GET
99
107
 
100
- const response = await $http.post<{ ok: true }>(
101
- '/posts',
102
- {
103
- title: 'Hello',
108
+ ```ts
109
+ const response = await httpClient.get('/products', {
110
+ params: {
111
+ limit: 10,
104
112
  },
105
- {
106
- params: {
107
- draft: true,
108
- },
113
+ retry: {
114
+ delay: 300,
115
+ retries: 3,
109
116
  },
110
- )
117
+ })
111
118
  ```
112
119
 
113
- ## `useHttp()`
120
+ Особенности:
114
121
 
115
- `useHttp()` is auto-imported and returns:
122
+ - query строится из `params`
123
+ - `GET` поддерживает retry для `429` и `5xx`
124
+ - delay экспоненциальный: `delay * 2 ** attempt`
125
+ - `signal` можно передать как один `AbortSignal` или массив `AbortSignal[]`
116
126
 
117
- - `data`
118
- - `error`
119
- - `pending`
120
- - `pendingCache`
121
- - `hasFirstData`
122
- - `hasFreshData`
123
- - `fetch()`
124
-
125
- Basic example:
127
+ ### POST
126
128
 
127
129
  ```ts
128
- const users = await useHttp<Array<{ id: string; name: string }>>({
129
- server: true,
130
- url: '/users',
131
- })
130
+ const { data } = await httpClient.post('/api/http-error-demo')
132
131
  ```
133
132
 
134
- With params:
133
+ Для `POST`:
135
134
 
136
- ```ts
137
- const users = await useHttp<Array<{ id: string; name: string }>, { page: number }>({
138
- initParams: {
139
- page: 1,
140
- },
141
- url: '/users',
142
- })
135
+ - `Record<string, unknown>` сериализуется в JSON
136
+ - `FormData` отправляется как есть
137
+ - retry нет
138
+ - если response не JSON, пакет вернёт пустой объект в `data`
143
139
 
144
- await users.fetch({
145
- page: 2,
146
- })
147
- ```
140
+ ### Расширение `HttpConfig`
141
+
142
+ Так как `HttpConfig` расширяемый, можно прокидывать свои поля в запрос и читать их в `onResponse`.
148
143
 
149
- With side effects:
144
+ Пример из playground:
150
145
 
151
146
  ```ts
152
- const profile = await useHttp<{ id: string; name: string }>({
153
- effect(payload, { cached }) {
154
- if (!cached) {
155
- console.log('fresh profile payload', payload)
156
- }
157
- },
158
- url: '/profile',
147
+ httpClient.get('/products', {
148
+ ignore: (data) => data?.limit === 20,
159
149
  })
160
150
  ```
161
151
 
162
- ## Typed Routes
163
-
164
- If you want `'/users'` and other URL literals to infer `params`, `data`, `error`, and `body` automatically, extend the global `BrickflowHttpRouteMap`.
165
-
166
- Create a declaration file, for example `types/brickflow-http.d.ts`:
167
-
168
152
  ```ts
169
- import type { HttpErrorPayload } from '@brickflow/http'
170
-
171
- declare global {
172
- interface BrickflowHttpRouteMap {
173
- '/api/user': {
174
- data: { id: string; name: string }
175
- error: HttpErrorPayload & { code?: 'NOT_FOUND' }
176
- params: { id: string }
177
- }
178
- '/api/posts': {
179
- data: Array<{ id: string; title: string }>
180
- params: { page?: number }
181
- }
182
- '/api/posts/create': {
183
- body: { title: string }
184
- data: { id: string }
185
- }
186
- }
153
+ export function handlePlaygroundResponse(
154
+ response: Parameters<NonNullable<CreateHttpOptions['onResponse']>>[0],
155
+ ): void {
156
+ console.log(response.config.ignore?.(response.data))
187
157
  }
188
-
189
- export {}
190
158
  ```
191
159
 
192
- After that, `$http` and `useHttp()` infer types from the URL literal automatically.
160
+ ## createUseHttp
193
161
 
194
- Typed `get`:
162
+ В `apps/playground/core/http.ts` app-level инстанс создаётся один раз:
195
163
 
196
164
  ```ts
197
- const { $http } = useNuxtApp()
165
+ import { createUseHttp, defineGet } from '@brickflow/http'
198
166
 
199
- const response = await $http.get('/api/user', {
200
- params: {
201
- id: '42',
202
- },
167
+ import { dbDeleteKeysWithPart, dbGet, dbSafeSet } from './indexdb'
168
+
169
+ const CACHE_DB_NAME = 'smart-cache-v2'
170
+ const CACHE_STORE_NAME = 'playground-http'
171
+
172
+ const useHttp = createUseHttp({
173
+ getCache: () => ({
174
+ deleteKeysWithPart: async (part: string) => await dbDeleteKeysWithPart(part, CACHE_DB_NAME, CACHE_STORE_NAME),
175
+ get: async <T>(key: string) => await dbGet<T>(key, CACHE_DB_NAME, CACHE_STORE_NAME),
176
+ set: async <T>(key: string, value: T, ttl: number) =>
177
+ await dbSafeSet<T>(key, value, CACHE_DB_NAME, CACHE_STORE_NAME, ttl),
178
+ }),
179
+ getHttpClient: () => useNuxtApp().$http,
180
+ isDev: () => false,
203
181
  })
182
+
183
+ export const createGet = defineGet(useHttp)
204
184
  ```
205
185
 
206
- Typed `post`:
186
+ Зависимости:
207
187
 
208
- ```ts
209
- const { $http } = useNuxtApp()
188
+ - `getHttpClient` обязательно
189
+ - `getCache` опционально
190
+ - `isDev` опционально
191
+ - `isError` опционально
192
+ - `ttl` опционально
193
+ - `channelName` опционально
210
194
 
211
- await $http.post('/api/posts/create', {
212
- title: 'New post',
213
- })
214
- ```
195
+ `createUseHttp` возвращает функцию `useHttp(options)`, которая создаёт реактивное состояние запроса:
215
196
 
216
- Typed `useHttp` without generics:
197
+ - `data`
198
+ - `error`
199
+ - `pending`
200
+ - `pendingCache`
201
+ - `hasFirstData`
202
+ - `hasFreshData`
203
+ - `fetch(params?, { signal? })`
217
204
 
218
- ```ts
219
- const posts = await useHttp({
220
- initParams: {
221
- page: 1,
222
- },
223
- url: '/api/posts',
224
- })
205
+ ### Опции useHttp
225
206
 
226
- await posts.fetch({
227
- page: 2,
228
- })
229
- ```
207
+ - `url`
208
+ - `initParams`
209
+ - `mapParams`
210
+ - `effect`
211
+ - `isError`
212
+ - `lazy`
213
+ - `server`
230
214
 
231
- ## Strict Client
215
+ `effect(data, config)` вызывается и для cache, и для fresh-response:
232
216
 
233
- `$http` keeps a fallback overload for plain `string`, so unknown URLs are still allowed.
217
+ - `config.cached === true` для cache
218
+ - `config.cached === false` для сети
219
+ - `config.params` содержит уже применённые params
234
220
 
235
- If you want to forbid unknown URLs completely:
221
+ ## defineGet
222
+
223
+ `defineGet` связывает app-level `useHttp` с endpoint-фабриками:
236
224
 
237
225
  ```ts
238
- import { createStrictHttpClient } from '@brickflow/http'
226
+ const useHttp = createUseHttp({ ... })
239
227
 
240
- const { $http } = useNuxtApp()
241
- const strictHttp = createStrictHttpClient($http)
228
+ export const createGet = defineGet(useHttp)
229
+ ```
242
230
 
243
- await strictHttp.get('/api/user', {
244
- params: { id: '42' },
245
- })
231
+ Дальше в домене можно описывать запросы коротко и типизированно:
246
232
 
247
- // TypeScript error
248
- await strictHttp.get('/api/unknown')
233
+ ```ts
234
+ products: createGet<{
235
+ limit: number
236
+ }>()('/products')
249
237
  ```
250
238
 
251
- If you want typed overloads on a standalone client while keeping the plain `string` fallback:
239
+ `defineGet` поддерживает два слоя настроек:
252
240
 
253
- ```ts
254
- import { createHttpClient, createTypedHttpClient } from '@brickflow/http'
241
+ 1. Базовые настройки endpoint-а при объявлении:
255
242
 
256
- const http = createTypedHttpClient(
257
- createHttpClient({
258
- baseURL: 'https://api.example.com',
243
+ ```ts
244
+ const products = createGet<{ limit: number }>()('/products', {
245
+ mapParams: (params) => ({
246
+ limit: params?.limit ?? 10,
259
247
  }),
260
- )
248
+ })
261
249
  ```
262
250
 
263
- ## Dynamic Base URL
264
-
265
- Standalone client supports a dynamic resolver:
251
+ 2. Runtime-опции при вызове:
266
252
 
267
253
  ```ts
268
- const tenantStore = useTenantStore()
269
-
270
- const http = createHttpClient({
271
- baseURL: () => tenantStore.apiBaseUrl,
254
+ const productsHttp = await products({
255
+ initParams: { limit: 20 },
256
+ lazy: true,
257
+ server: false,
272
258
  })
273
259
  ```
274
260
 
275
- In Nuxt, the better option is request middleware, because it works for both `$http` and `useHttp()`:
261
+ Если `effect`, `mapParams` или `isError` указаны и при объявлении, и при вызове, пакет объединяет их так:
262
+
263
+ - `effect` вызывает оба обработчика
264
+ - `isError` из runtime имеет приоритет
265
+ - `mapParams` из runtime имеет приоритет
266
+
267
+ ## createUseCase
268
+
269
+ В playground доменный модуль собирается через `createUseCase`:
276
270
 
277
271
  ```ts
278
- import { addHttpRequestMiddleware } from '@brickflow/http'
272
+ import { createUseCase } from '@brickflow/http'
279
273
 
280
- export default defineNuxtPlugin(() => {
281
- const apiBaseUrl = useState('api-base-url', () => 'https://dummyjson.com')
274
+ import { createGet } from '~/core/http'
282
275
 
283
- addHttpRequestMiddleware((request) => {
284
- if (request.url.startsWith('/products') || request.url.startsWith('/test')) {
285
- request.baseURL = apiBaseUrl.value
286
- }
287
- })
276
+ export default createUseCase()(({ httpClient }) => {
277
+ return {
278
+ async apiError() {
279
+ const { data } = await httpClient.post('/api/http-error-demo')
280
+ return data
281
+ },
282
+
283
+ products: createGet<{
284
+ limit: number
285
+ }>()('/products'),
286
+ }
288
287
  })
289
288
  ```
290
289
 
291
- Then the same request code can stay relative:
292
-
293
- ```ts
294
- const products = await useHttp({
295
- url: '/products',
296
- })
290
+ Это даёт простой контракт для DI: use-case получает `httpClient`, а внутри может смешивать:
297
291
 
298
- const { $http } = useNuxtApp()
299
- await $http.get('/test')
300
- ```
292
+ - прямые mutation/one-shot запросы через `httpClient`
293
+ - stateful GET-запросы через `createGet`
301
294
 
302
- The playground app contains a live example that switches the same typed requests between:
295
+ ## Использование в компоненте
303
296
 
304
- - direct `https://dummyjson.com`
305
- - local proxy `/api/dummyjson`
297
+ Актуальный пример из `apps/playground/pages/index.vue`:
306
298
 
307
- See:
299
+ ```vue
300
+ <script lang="ts" setup>
301
+ const app = useNuxtApp()
302
+ const httpProducts = await app.$di.product.products({
303
+ lazy: true,
304
+ })
305
+ </script>
306
+
307
+ <template>
308
+ <button
309
+ type="button"
310
+ @click="httpProducts.fetch()"
311
+ >
312
+ {{ httpProducts.hasFirstData }} Action
313
+ </button>
314
+
315
+ {{ httpProducts.data }}
316
+ </template>
317
+ ```
308
318
 
309
- - [apps/playground/app/pages/index.vue](/Users/andrii/Lab/personal/brickme/apps/playground/app/pages/index.vue:1)
310
- - [apps/playground/app/plugins/http-middleware.ts](/Users/andrii/Lab/personal/brickme/apps/playground/app/plugins/http-middleware.ts:1)
319
+ Типичный сценарий:
311
320
 
312
- ## Global Middleware
321
+ 1. Создать request-state через `await endpoint({ ...options })`
322
+ 2. Если `lazy: true`, вызвать `fetch()` вручную
323
+ 3. Читать `data`, `error`, `pending`, `pendingCache`
313
324
 
314
- Register middleware once and it will run for every request or response:
325
+ Пример с параметрами:
315
326
 
316
327
  ```ts
317
- import { addHttpRequestMiddleware, addHttpResponseMiddleware } from '@brickflow/http'
318
-
319
- export default defineNuxtPlugin(() => {
320
- addHttpRequestMiddleware((request) => {
321
- request.headers.set('X-App-Version', '1.0.0')
322
- })
328
+ const productsHttp = await app.$di.product.products({
329
+ initParams: {
330
+ limit: 10,
331
+ },
332
+ lazy: true,
333
+ })
323
334
 
324
- addHttpResponseMiddleware((response, request) => {
325
- if (response.status >= 500) {
326
- console.error('HTTP error', request.url, response.status)
327
- }
328
- })
335
+ await productsHttp.fetch({
336
+ limit: 30,
329
337
  })
330
338
  ```
331
339
 
332
- Request middleware can mutate:
340
+ ## Cache и синхронизация между вкладками
333
341
 
334
- - `baseURL`
335
- - `url`
336
- - `method`
337
- - `headers`
338
- - `body`
339
- - `params`
340
- - `signal`
341
- - `credentials`
342
+ Если передан `getCache`, `createUseHttp`:
342
343
 
343
- Response middleware receives:
344
+ - сначала пробует отдать cache
345
+ - вызывает `effect(..., { cached: true })` для cache-ответа
346
+ - затем делает сетевой запрос
347
+ - сохраняет успешный ответ в cache
348
+ - при изменении хеша удаляет связанные cache-ключи через `deleteKeysWithPart`
344
349
 
345
- - `response`
346
- - `request`
350
+ Дополнительно пакет использует `BroadcastChannel` и синхронизирует свежие успешные GET-ответы между вкладками.
347
351
 
348
- You can remove middleware later:
352
+ По умолчанию:
349
353
 
350
- ```ts
351
- import { addHttpRequestMiddleware, removeHttpRequestMiddleware } from '@brickflow/http'
354
+ - `ttl = 7 дней`
355
+ - `channelName = 'http-tab-sync'`
352
356
 
353
- const middleware = (request: Parameters<typeof addHttpRequestMiddleware>[0]) => {
354
- request.headers.set('X-Debug', '1')
355
- }
357
+ ## SSR
356
358
 
357
- addHttpRequestMiddleware(middleware)
358
- removeHttpRequestMiddleware(middleware)
359
- ```
359
+ Если вызвать endpoint с `server: true`, на сервере пакет использует `useLazyAsyncData`, сохраняет результат в `useState` и переиспользует его на клиенте после гидрации.
360
360
 
361
- ## Standalone Client
361
+ Это полезно для страниц, где нужен первый ответ уже в SSR, но тот же контракт `data / pending / fetch` должен остаться и на клиенте.
362
362
 
363
- You can use the client outside Nuxt injection:
363
+ ## Вспомогательные функции
364
364
 
365
365
  ```ts
366
- import { createHttpClient } from '@brickflow/http'
366
+ import { createURL, hashData } from '@brickflow/http'
367
+ ```
367
368
 
368
- const http = createHttpClient({
369
- baseURL: 'https://api.example.com',
370
- requestTimeoutMs: 10000,
371
- retry: {
372
- delay: 250,
373
- retries: 2,
374
- },
375
- })
369
+ - `createURL(url, params)` строит query string
370
+ - `hashData(data)` считает SHA-1 через `crypto.subtle`, а без него использует fallback-хеш
376
371
 
377
- const response = await http.get<{ ok: true }>('/health')
378
- ```
372
+ ## Когда что использовать
379
373
 
380
- With custom headers:
374
+ `createHttp`:
381
375
 
382
- ```ts
383
- const http = createHttpClient({
384
- baseURL: async () => `https://${tenant.value}.api.example.com`,
385
- createHeaders: async () => {
386
- return {
387
- Authorization: `Bearer ${token}`,
388
- }
389
- },
390
- })
391
- ```
376
+ - POST/мутации
377
+ - one-shot запросы
378
+ - когда не нужен reactive state
392
379
 
393
- ## Exports
380
+ `createUseHttp` + `defineGet`:
381
+
382
+ - SSR-friendly GET
383
+ - cache и `pendingCache`
384
+ - повторное использование endpoint-описаний
385
+ - ручной `fetch()`
386
+
387
+ `createUseCase`:
394
388
 
395
- Main exports:
396
-
397
- - default Nuxt module
398
- - `createHttpClient`
399
- - `createTypedHttpClient`
400
- - `createStrictHttpClient`
401
- - `defineHttpRoutes`
402
- - `addHttpRequestMiddleware`
403
- - `addHttpResponseMiddleware`
404
- - `removeHttpRequestMiddleware`
405
- - `removeHttpResponseMiddleware`
406
- - public TypeScript types for client, config, middleware, payloads, and typed route maps
389
+ - доменные модули с DI
390
+ - единый контракт для доступа к `httpClient`