synapse-storage 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/dist/api.cjs +891 -0
  2. package/dist/api.cjs.map +1 -0
  3. package/dist/api.d.cts +365 -0
  4. package/dist/api.d.ts +365 -0
  5. package/dist/api.js +860 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/core.cjs +2389 -0
  8. package/dist/core.cjs.map +1 -0
  9. package/dist/core.d.cts +397 -0
  10. package/dist/{core/storage/modules/plugin/plugin.interface.d.ts → core.d.ts} +203 -7
  11. package/dist/core.js +2356 -0
  12. package/dist/core.js.map +1 -0
  13. package/dist/dispatcher.module-CdpmkplA.d.cts +363 -0
  14. package/dist/dispatcher.module-jd8U_ZEs.d.ts +363 -0
  15. package/dist/index.cjs +4148 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.cts +10 -0
  18. package/dist/index.d.ts +10 -10
  19. package/dist/index.js +4092 -13
  20. package/dist/index.js.map +1 -1
  21. package/dist/react.cjs +268 -0
  22. package/dist/react.cjs.map +1 -0
  23. package/dist/react.d.cts +74 -0
  24. package/dist/react.d.ts +74 -0
  25. package/dist/react.js +239 -0
  26. package/dist/react.js.map +1 -0
  27. package/dist/reactive.cjs +643 -0
  28. package/dist/reactive.cjs.map +1 -0
  29. package/dist/reactive.d.cts +35 -0
  30. package/dist/reactive.d.ts +35 -0
  31. package/dist/reactive.js +604 -0
  32. package/dist/reactive.js.map +1 -0
  33. package/dist/{core/selector/selector.interface.d.ts → selector.interface-CA5y-kD_.d.cts} +7 -35
  34. package/dist/selector.interface-CA5y-kD_.d.ts +63 -0
  35. package/dist/storage.interface-Dl8SLUd1.d.cts +128 -0
  36. package/dist/storage.interface-Dl8SLUd1.d.ts +128 -0
  37. package/dist/utils.cjs +601 -0
  38. package/dist/utils.cjs.map +1 -0
  39. package/dist/utils.d.cts +92 -0
  40. package/dist/utils.d.ts +92 -0
  41. package/dist/utils.js +574 -0
  42. package/dist/utils.js.map +1 -0
  43. package/package.json +54 -17
  44. package/dist/_utils/chunk.util.d.ts +0 -8
  45. package/dist/_utils/chunk.util.d.ts.map +0 -1
  46. package/dist/_utils/chunk.util.js +0 -21
  47. package/dist/_utils/chunk.util.js.map +0 -1
  48. package/dist/_utils/deepMerge.util.d.ts +0 -2
  49. package/dist/_utils/deepMerge.util.d.ts.map +0 -1
  50. package/dist/_utils/deepMerge.util.js +0 -16
  51. package/dist/_utils/deepMerge.util.js.map +0 -1
  52. package/dist/_utils/flatMap.util.d.ts +0 -10
  53. package/dist/_utils/flatMap.util.d.ts.map +0 -1
  54. package/dist/_utils/flatMap.util.js +0 -23
  55. package/dist/_utils/flatMap.util.js.map +0 -1
  56. package/dist/_utils/index.d.ts +0 -4
  57. package/dist/_utils/index.d.ts.map +0 -1
  58. package/dist/_utils/index.js +0 -4
  59. package/dist/_utils/index.js.map +0 -1
  60. package/dist/api/api.module.d.ts +0 -38
  61. package/dist/api/api.module.d.ts.map +0 -1
  62. package/dist/api/api.module.js +0 -82
  63. package/dist/api/api.module.js.map +0 -1
  64. package/dist/api/components/endpoint.d.ts +0 -26
  65. package/dist/api/components/endpoint.d.ts.map +0 -1
  66. package/dist/api/components/endpoint.js +0 -253
  67. package/dist/api/components/endpoint.js.map +0 -1
  68. package/dist/api/components/query-storage.d.ts +0 -84
  69. package/dist/api/components/query-storage.d.ts.map +0 -1
  70. package/dist/api/components/query-storage.js +0 -221
  71. package/dist/api/components/query-storage.js.map +0 -1
  72. package/dist/api/example.d.ts +0 -83
  73. package/dist/api/example.d.ts.map +0 -1
  74. package/dist/api/example.js +0 -85
  75. package/dist/api/example.js.map +0 -1
  76. package/dist/api/index.d.ts +0 -4
  77. package/dist/api/index.d.ts.map +0 -1
  78. package/dist/api/index.js +0 -6
  79. package/dist/api/index.js.map +0 -1
  80. package/dist/api/types/api.interface.d.ts +0 -108
  81. package/dist/api/types/api.interface.d.ts.map +0 -1
  82. package/dist/api/types/api.interface.js +0 -19
  83. package/dist/api/types/api.interface.js.map +0 -1
  84. package/dist/api/types/endpoint.interface.d.ts +0 -116
  85. package/dist/api/types/endpoint.interface.d.ts.map +0 -1
  86. package/dist/api/types/endpoint.interface.js +0 -2
  87. package/dist/api/types/endpoint.interface.js.map +0 -1
  88. package/dist/api/types/query.interface.d.ts +0 -87
  89. package/dist/api/types/query.interface.d.ts.map +0 -1
  90. package/dist/api/types/query.interface.js +0 -2
  91. package/dist/api/types/query.interface.js.map +0 -1
  92. package/dist/api/utils/api-helpers.d.ts +0 -22
  93. package/dist/api/utils/api-helpers.d.ts.map +0 -1
  94. package/dist/api/utils/api-helpers.js +0 -44
  95. package/dist/api/utils/api-helpers.js.map +0 -1
  96. package/dist/api/utils/create-header-context.d.ts +0 -10
  97. package/dist/api/utils/create-header-context.d.ts.map +0 -1
  98. package/dist/api/utils/create-header-context.js +0 -36
  99. package/dist/api/utils/create-header-context.js.map +0 -1
  100. package/dist/api/utils/endpoint-headers.d.ts +0 -23
  101. package/dist/api/utils/endpoint-headers.d.ts.map +0 -1
  102. package/dist/api/utils/endpoint-headers.js +0 -57
  103. package/dist/api/utils/endpoint-headers.js.map +0 -1
  104. package/dist/api/utils/fetch-base-query.d.ts +0 -9
  105. package/dist/api/utils/fetch-base-query.d.ts.map +0 -1
  106. package/dist/api/utils/fetch-base-query.js +0 -181
  107. package/dist/api/utils/fetch-base-query.js.map +0 -1
  108. package/dist/api/utils/file-utils.d.ts +0 -43
  109. package/dist/api/utils/file-utils.d.ts.map +0 -1
  110. package/dist/api/utils/file-utils.js +0 -108
  111. package/dist/api/utils/file-utils.js.map +0 -1
  112. package/dist/api/utils/get-cacheable-headers.d.ts +0 -8
  113. package/dist/api/utils/get-cacheable-headers.d.ts.map +0 -1
  114. package/dist/api/utils/get-cacheable-headers.js +0 -21
  115. package/dist/api/utils/get-cacheable-headers.js.map +0 -1
  116. package/dist/core/index.d.ts +0 -3
  117. package/dist/core/index.d.ts.map +0 -1
  118. package/dist/core/index.js +0 -3
  119. package/dist/core/index.js.map +0 -1
  120. package/dist/core/selector/index.d.ts +0 -3
  121. package/dist/core/selector/index.d.ts.map +0 -1
  122. package/dist/core/selector/index.js +0 -2
  123. package/dist/core/selector/index.js.map +0 -1
  124. package/dist/core/selector/selector.interface.d.ts.map +0 -1
  125. package/dist/core/selector/selector.interface.js +0 -2
  126. package/dist/core/selector/selector.interface.js.map +0 -1
  127. package/dist/core/selector/selector.module.d.ts +0 -29
  128. package/dist/core/selector/selector.module.d.ts.map +0 -1
  129. package/dist/core/selector/selector.module.js +0 -467
  130. package/dist/core/selector/selector.module.js.map +0 -1
  131. package/dist/core/storage/adapters/base-storage.service.d.ts +0 -65
  132. package/dist/core/storage/adapters/base-storage.service.d.ts.map +0 -1
  133. package/dist/core/storage/adapters/base-storage.service.js +0 -660
  134. package/dist/core/storage/adapters/base-storage.service.js.map +0 -1
  135. package/dist/core/storage/adapters/indexed-DB.service.d.ts +0 -63
  136. package/dist/core/storage/adapters/indexed-DB.service.d.ts.map +0 -1
  137. package/dist/core/storage/adapters/indexed-DB.service.js +0 -595
  138. package/dist/core/storage/adapters/indexed-DB.service.js.map +0 -1
  139. package/dist/core/storage/adapters/indexed-DB.service.old.d.ts +0 -38
  140. package/dist/core/storage/adapters/indexed-DB.service.old.d.ts.map +0 -1
  141. package/dist/core/storage/adapters/indexed-DB.service.old.js +0 -318
  142. package/dist/core/storage/adapters/indexed-DB.service.old.js.map +0 -1
  143. package/dist/core/storage/adapters/local-storage.service.d.ts +0 -21
  144. package/dist/core/storage/adapters/local-storage.service.d.ts.map +0 -1
  145. package/dist/core/storage/adapters/local-storage.service.js +0 -99
  146. package/dist/core/storage/adapters/local-storage.service.js.map +0 -1
  147. package/dist/core/storage/adapters/memory-storage.service.d.ts +0 -22
  148. package/dist/core/storage/adapters/memory-storage.service.d.ts.map +0 -1
  149. package/dist/core/storage/adapters/memory-storage.service.js +0 -99
  150. package/dist/core/storage/adapters/memory-storage.service.js.map +0 -1
  151. package/dist/core/storage/adapters/path.utils.d.ts +0 -5
  152. package/dist/core/storage/adapters/path.utils.d.ts.map +0 -1
  153. package/dist/core/storage/adapters/path.utils.js +0 -35
  154. package/dist/core/storage/adapters/path.utils.js.map +0 -1
  155. package/dist/core/storage/index.d.ts +0 -11
  156. package/dist/core/storage/index.d.ts.map +0 -1
  157. package/dist/core/storage/index.js +0 -12
  158. package/dist/core/storage/index.js.map +0 -1
  159. package/dist/core/storage/middlewares/broadcast.middleware.d.ts +0 -9
  160. package/dist/core/storage/middlewares/broadcast.middleware.d.ts.map +0 -1
  161. package/dist/core/storage/middlewares/broadcast.middleware.js +0 -115
  162. package/dist/core/storage/middlewares/broadcast.middleware.js.map +0 -1
  163. package/dist/core/storage/middlewares/index.d.ts +0 -4
  164. package/dist/core/storage/middlewares/index.d.ts.map +0 -1
  165. package/dist/core/storage/middlewares/index.js +0 -3
  166. package/dist/core/storage/middlewares/index.js.map +0 -1
  167. package/dist/core/storage/middlewares/storage-batching.middleware.d.ts +0 -7
  168. package/dist/core/storage/middlewares/storage-batching.middleware.d.ts.map +0 -1
  169. package/dist/core/storage/middlewares/storage-batching.middleware.js +0 -36
  170. package/dist/core/storage/middlewares/storage-batching.middleware.js.map +0 -1
  171. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts +0 -7
  172. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts.map +0 -1
  173. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js +0 -46
  174. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js.map +0 -1
  175. package/dist/core/storage/modules/plugin/plugin.interface.d.ts.map +0 -1
  176. package/dist/core/storage/modules/plugin/plugin.interface.js +0 -2
  177. package/dist/core/storage/modules/plugin/plugin.interface.js.map +0 -1
  178. package/dist/core/storage/modules/plugin/plugin.service.d.ts +0 -25
  179. package/dist/core/storage/modules/plugin/plugin.service.d.ts.map +0 -1
  180. package/dist/core/storage/modules/plugin/plugin.service.js +0 -186
  181. package/dist/core/storage/modules/plugin/plugin.service.js.map +0 -1
  182. package/dist/core/storage/storage.interface.d.ts +0 -70
  183. package/dist/core/storage/storage.interface.d.ts.map +0 -1
  184. package/dist/core/storage/storage.interface.js +0 -10
  185. package/dist/core/storage/storage.interface.js.map +0 -1
  186. package/dist/core/storage/utils/batch.utils.d.ts +0 -33
  187. package/dist/core/storage/utils/batch.utils.d.ts.map +0 -1
  188. package/dist/core/storage/utils/batch.utils.js +0 -88
  189. package/dist/core/storage/utils/batch.utils.js.map +0 -1
  190. package/dist/core/storage/utils/broadcast.util.d.ts +0 -48
  191. package/dist/core/storage/utils/broadcast.util.d.ts.map +0 -1
  192. package/dist/core/storage/utils/broadcast.util.js +0 -162
  193. package/dist/core/storage/utils/broadcast.util.js.map +0 -1
  194. package/dist/core/storage/utils/cache.util.d.ts +0 -33
  195. package/dist/core/storage/utils/cache.util.d.ts.map +0 -1
  196. package/dist/core/storage/utils/cache.util.js +0 -47
  197. package/dist/core/storage/utils/cache.util.js.map +0 -1
  198. package/dist/core/storage/utils/middleware-module.d.ts +0 -46
  199. package/dist/core/storage/utils/middleware-module.d.ts.map +0 -1
  200. package/dist/core/storage/utils/middleware-module.js +0 -109
  201. package/dist/core/storage/utils/middleware-module.js.map +0 -1
  202. package/dist/core/storage/utils/storage-key.d.ts +0 -11
  203. package/dist/core/storage/utils/storage-key.d.ts.map +0 -1
  204. package/dist/core/storage/utils/storage-key.js +0 -21
  205. package/dist/core/storage/utils/storage-key.js.map +0 -1
  206. package/dist/core/storage/utils/storage.utils.d.ts +0 -17
  207. package/dist/core/storage/utils/storage.utils.d.ts.map +0 -1
  208. package/dist/core/storage/utils/storage.utils.js +0 -57
  209. package/dist/core/storage/utils/storage.utils.js.map +0 -1
  210. package/dist/index.d.ts.map +0 -1
  211. package/dist/react/hooks/index.d.ts +0 -3
  212. package/dist/react/hooks/index.d.ts.map +0 -1
  213. package/dist/react/hooks/index.js +0 -3
  214. package/dist/react/hooks/index.js.map +0 -1
  215. package/dist/react/hooks/useSelector.d.ts +0 -22
  216. package/dist/react/hooks/useSelector.d.ts.map +0 -1
  217. package/dist/react/hooks/useSelector.js +0 -104
  218. package/dist/react/hooks/useSelector.js.map +0 -1
  219. package/dist/react/hooks/useStorageSubscribe.d.ts +0 -12
  220. package/dist/react/hooks/useStorageSubscribe.d.ts.map +0 -1
  221. package/dist/react/hooks/useStorageSubscribe.js +0 -49
  222. package/dist/react/hooks/useStorageSubscribe.js.map +0 -1
  223. package/dist/react/index.d.ts +0 -3
  224. package/dist/react/index.d.ts.map +0 -1
  225. package/dist/react/index.js +0 -3
  226. package/dist/react/index.js.map +0 -1
  227. package/dist/react/utils/createSynapseCtx.d.ts +0 -40
  228. package/dist/react/utils/createSynapseCtx.d.ts.map +0 -1
  229. package/dist/react/utils/createSynapseCtx.js +0 -125
  230. package/dist/react/utils/createSynapseCtx.js.map +0 -1
  231. package/dist/react/utils/index.d.ts +0 -2
  232. package/dist/react/utils/index.d.ts.map +0 -1
  233. package/dist/react/utils/index.js +0 -2
  234. package/dist/react/utils/index.js.map +0 -1
  235. package/dist/reactive/dispatcher/dispatcher.module.d.ts +0 -195
  236. package/dist/reactive/dispatcher/dispatcher.module.d.ts.map +0 -1
  237. package/dist/reactive/dispatcher/dispatcher.module.js +0 -288
  238. package/dist/reactive/dispatcher/dispatcher.module.js.map +0 -1
  239. package/dist/reactive/dispatcher/index.d.ts +0 -3
  240. package/dist/reactive/dispatcher/index.d.ts.map +0 -1
  241. package/dist/reactive/dispatcher/index.js +0 -3
  242. package/dist/reactive/dispatcher/index.js.map +0 -1
  243. package/dist/reactive/dispatcher/middlewares/index.d.ts +0 -2
  244. package/dist/reactive/dispatcher/middlewares/index.d.ts.map +0 -1
  245. package/dist/reactive/dispatcher/middlewares/index.js +0 -2
  246. package/dist/reactive/dispatcher/middlewares/index.js.map +0 -1
  247. package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts +0 -31
  248. package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts.map +0 -1
  249. package/dist/reactive/dispatcher/middlewares/logger.middleware.js +0 -126
  250. package/dist/reactive/dispatcher/middlewares/logger.middleware.js.map +0 -1
  251. package/dist/reactive/effects/effects.module.d.ts +0 -150
  252. package/dist/reactive/effects/effects.module.d.ts.map +0 -1
  253. package/dist/reactive/effects/effects.module.js +0 -277
  254. package/dist/reactive/effects/effects.module.js.map +0 -1
  255. package/dist/reactive/effects/index.d.ts +0 -2
  256. package/dist/reactive/effects/index.d.ts.map +0 -1
  257. package/dist/reactive/effects/index.js +0 -2
  258. package/dist/reactive/effects/index.js.map +0 -1
  259. package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts +0 -12
  260. package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts.map +0 -1
  261. package/dist/reactive/effects/utils/chunkRequestConsistent.js +0 -16
  262. package/dist/reactive/effects/utils/chunkRequestConsistent.js.map +0 -1
  263. package/dist/reactive/effects/utils/chunkRequestParallel.d.ts +0 -12
  264. package/dist/reactive/effects/utils/chunkRequestParallel.d.ts.map +0 -1
  265. package/dist/reactive/effects/utils/chunkRequestParallel.js +0 -13
  266. package/dist/reactive/effects/utils/chunkRequestParallel.js.map +0 -1
  267. package/dist/reactive/effects/utils/index.d.ts +0 -3
  268. package/dist/reactive/effects/utils/index.d.ts.map +0 -1
  269. package/dist/reactive/effects/utils/index.js +0 -3
  270. package/dist/reactive/effects/utils/index.js.map +0 -1
  271. package/dist/reactive/index.d.ts +0 -3
  272. package/dist/reactive/index.d.ts.map +0 -1
  273. package/dist/reactive/index.js +0 -3
  274. package/dist/reactive/index.js.map +0 -1
  275. package/dist/utils/createSynapse.d.ts +0 -92
  276. package/dist/utils/createSynapse.d.ts.map +0 -1
  277. package/dist/utils/createSynapse.js +0 -79
  278. package/dist/utils/createSynapse.js.map +0 -1
  279. package/dist/utils/index.d.ts +0 -2
  280. package/dist/utils/index.d.ts.map +0 -1
  281. package/dist/utils/index.js +0 -2
  282. package/dist/utils/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/index.ts","../src/api/utils/api-helpers.ts","../src/api/utils/create-header-context.ts","../src/api/utils/endpoint-headers.ts","../src/api/types/api.interface.ts","../src/api/utils/file-utils.ts","../src/api/utils/fetch-base-query.ts","../src/api/utils/get-cacheable-headers.ts","../src/api/components/endpoint.ts","../src/core/storage/utils/storage-key.ts","../src/core/storage/utils/cache.util.ts","../src/api/components/query-storage.ts","../src/api/api.module.ts"],"sourcesContent":["export * from './api.module'\nexport { ResponseFormat } from './types/api.interface'\nexport * from './utils/api-helpers'\n// export * from './_utils/file-_utils'\n// export * from './_utils/get-cacheable-headers'\n","/**\n * Логгер для API\n */\nexport const apiLogger = {\n debug: (message: string, ...args: any[]) => {\n if (process.env.NODE_ENV !== 'production') {\n console.debug(`[API] ${message}`, ...args)\n }\n },\n\n log: (message: string, ...args: any[]) => {\n if (process.env.NODE_ENV !== 'production') {\n console.log(`[API] ${message}`, ...args)\n }\n },\n\n info: (message: string, ...args: any[]) => {\n console.info(`[API] ${message}`, ...args)\n },\n\n warn: (message: string, ...args: any[]) => {\n console.warn(`[API] ${message}`, ...args)\n },\n\n error: (message: string, ...args: any[]) => {\n console.error(`[API] ${message}`, ...args)\n },\n}\n\n/**\n * Создает уникальный идентификатор\n * @returns Строка с уникальным идентификатором\n */\nexport function createUniqueId(name?: string): string {\n return `${name ? `${name}|` : ''}${Math.random().toString(36).substring(2, 9) + Date.now().toString(36)}`\n}\n\n/**\n * Преобразует объект Headers в обычный объект\n * @param headers Объект Headers\n * @returns Обычный объект с заголовками\n */\nexport function headersToObject(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {}\n headers.forEach((value, key) => {\n result[key.toLowerCase()] = value\n })\n return result\n}\n","import { ApiContext } from '../types/api.interface'\n\n/**\n * Создает контекст для подготовки заголовков\n *\n * @param context - базовый контекст\n * @param optionContext - дополнительный контекст из опций\n * @returns - полный контекст для подготовки заголовков\n */\nexport function createHeaderContext<RequestParams extends Record<string, any>>(\n context: Partial<ApiContext> = {} as ApiContext<RequestParams>,\n optionContext: Record<string, any> = {},\n): ApiContext<RequestParams> {\n return {\n ...context,\n ...optionContext,\n getFromStorage:\n context.getFromStorage ||\n ((key: string) => {\n try {\n const item = localStorage.getItem(key)\n return item ? JSON.parse(item) : undefined\n } catch (error) {\n console.warn(`[API] Ошибка чтения из localStorage: ${error}`)\n return undefined\n }\n }),\n getCookie:\n context.getCookie ||\n ((name: string) => {\n try {\n const matches = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/([\\.$?*|{}\\(\\)\\[\\]\\\\\\/\\+^])/g, '\\\\$1')}=([^;]*)`))\n return matches ? decodeURIComponent(matches[1]) : undefined\n } catch (error) {\n console.warn(`[API] Ошибка чтения cookie: ${error}`)\n return undefined\n }\n }),\n }\n}\n","import { ApiContext } from '../types/api.interface'\nimport { createHeaderContext } from './create-header-context'\n\n/**\n * Тип функции для подготовки заголовков запроса\n */\nexport type PrepareHeadersFunction = (headers: Headers, context: ApiContext<any>) => Promise<Headers>\n\n/**\n * Подготавливает заголовки для запроса на основе контекста и пользовательских функций\n *\n * @param prepareHeadersFn - функция подготовки заголовков\n * @param context - контекст запроса\n * @returns - подготовленные заголовки\n */\nexport async function prepareRequestHeaders<RequestParams extends Record<string, any>>(\n prepareHeadersFn?: PrepareHeadersFunction,\n context?: ApiContext<RequestParams>,\n): Promise<Headers> {\n // Создаем заголовки\n let headers = new Headers()\n\n // Создаем контекст, если он не передан\n const headerContext = context || createHeaderContext({} as ApiContext<RequestParams>, {})\n\n // Применяем функцию подготовки заголовков, если она определена\n if (prepareHeadersFn) {\n try {\n headers = await Promise.resolve(prepareHeadersFn(headers, headerContext))\n } catch (error) {\n console.warn('[API] Ошибка при подготовке заголовков', error)\n }\n }\n\n return headers\n}\n\n/**\n * Создает комбинированную функцию для подготовки заголовков, объединяющую\n * глобальные заголовки и заголовки эндпоинта\n *\n * @param globalPrepareHeaders - функция подготовки заголовков на глобальном уровне\n * @param endpointPrepareHeaders - функция подготовки заголовков на уровне эндпоинта\n * @returns - функция для подготовки заголовков\n */\nexport function createPrepareHeaders(globalPrepareHeaders?: PrepareHeadersFunction, endpointPrepareHeaders?: PrepareHeadersFunction): PrepareHeadersFunction {\n return async (headers: Headers, context: ApiContext<any>): Promise<Headers> => {\n let processedHeaders = new Headers(headers)\n\n // Применяем глобальную функцию подготовки заголовков, если она определена\n if (globalPrepareHeaders) {\n try {\n processedHeaders = await Promise.resolve(globalPrepareHeaders(processedHeaders, context))\n } catch (error) {\n console.warn('[API] Ошибка при подготовке глобальных заголовков', error)\n }\n }\n\n // Применяем функцию подготовки заголовков эндпоинта, если она определена\n if (endpointPrepareHeaders) {\n try {\n processedHeaders = await Promise.resolve(endpointPrepareHeaders(processedHeaders, context))\n } catch (error) {\n console.warn('[API] Ошибка при подготовке заголовков эндпоинта', error)\n }\n }\n\n return processedHeaders\n }\n}\n","import { IStorage, StorageType } from '../../core'\nimport { CreateEndpoint, EndpointConfig } from './endpoint.interface'\n\n/**\n * Форматы ответа от сервера\n */\nexport enum ResponseFormat {\n /** JSON-объект (по умолчанию) */\n Json = 'json',\n /** Blob-объект для файлов */\n Blob = 'blob',\n /** ArrayBuffer для бинарных данных */\n ArrayBuffer = 'arrayBuffer',\n /** Текстовый формат */\n Text = 'text',\n /** FormData для форм */\n FormData = 'formData',\n /** Без преобразования - возвращает сырой ответ */\n Raw = 'raw',\n}\n\n/**\n * Настройки кэша\n * Может быть объектом с параметрами или boolean (true для кэширования с настройками по умолчанию, false для отключения)\n */\nexport type CacheConfig =\n | boolean\n | {\n /** Время жизни кэша в миллисекундах */\n ttl?: number\n /** Настройки периодической очистки */\n cleanup?: {\n /** Включить периодическую очистку */\n enabled: boolean\n /** Интервал очистки в миллисекундах */\n interval?: number\n }\n /** Инвалидировать кэш при ошибке */\n invalidateOnError?: boolean\n }\n\n/**\n * Определение запроса\n * Содержит всю необходимую информацию для выполнения HTTP-запроса\n */\nexport interface RequestDefinition<RequestParams extends Record<string, any>> {\n /** Путь запроса (относительный или абсолютный URL) */\n path: string\n /** HTTP-метод */\n method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'\n /** Тело запроса (автоматически сериализуется) */\n body?: any\n /** Параметры запроса (автоматически добавляются в URL) */\n query?: RequestParams\n /** HTTP-заголовки */\n headers?: Record<string, string>\n /** Формат ответа (по умолчанию json) */\n responseFormat?: ResponseFormat\n /** Имя файла для автоматического скачивания */\n fileName?: string\n /** Тип контента для автоматического скачивания */\n fileType?: string\n}\n\n/**\n * Контекст API для использования в prepareHeaders и других функциях\n * Содержит вспомогательные методы и информацию о запросе\n */\nexport interface ApiContext<RequestParams extends Record<string, any> = any> {\n /** Параметры запроса */\n requestParams?: RequestParams\n /** Получить значение из localStorage */\n getFromStorage: <T>(key: string) => T | undefined\n /** Получить значение cookie */\n getCookie: (name: string) => string | undefined\n /** Поддержка для дополнительных свойств */\n [key: string]: any\n}\n\n/**\n * Аргументы для создания fetch-запроса\n */\nexport interface FetchBaseQueryArgs {\n /** Базовый URL для всех запросов */\n baseUrl: string\n /** Функция для подготовки заголовков, может быть асинхронной */\n prepareHeaders?: (headers: Headers, context: ApiContext) => Promise<Headers>\n /** Таймаут запроса в миллисекундах */\n timeout?: number\n /** Пользовательская fetch-функция */\n fetchFn?: typeof fetch\n credentials?: RequestCredentials\n}\n\nexport interface CreateApiClientOptions<T extends Record<string, EndpointConfig<any, any>> = Record<string, EndpointConfig<any, any>>> {\n storage: IStorage\n /** Настройки кэша\n * если явно указан false - значит ни один запрос НЕ будет кэшироваться, даже если в эндпоинтах указаны параметры\n * */\n cache?: CacheConfig\n /** Базовый запрос или его настройки */\n baseQuery: FetchBaseQueryArgs\n /** Функция для создания эндпоинтов */\n endpoints?: (create: CreateEndpoint) => Promise<T>\n /** Глобальные заголовки, влияющие на кэш */\n cacheableHeaderKeys?: string[]\n}\n\n/**\n * Извлечение типа параметров из конфигурации эндпоинта\n */\nexport type ExtractParamsType<T> = T extends EndpointConfig<infer P, any> ? P : never\n\n/**\n * Извлечение типа результата из конфигурации эндпоинта\n */\nexport type ExtractResultType<T> = T extends EndpointConfig<any, infer R> ? R : never\n","import { ResponseFormat } from '../types/api.interface'\n\n/**\n * Получает формат ответа на основе MIME-типа\n * @param contentType MIME-тип контента\n * @returns Формат ответа\n */\nexport function getResponseFormatForMimeType(contentType: string): ResponseFormat | undefined {\n const type = contentType.toLowerCase().split(';')[0].trim()\n\n if (type.includes('application/json')) {\n return ResponseFormat.Json\n }\n\n if (type.includes('text/')) {\n return ResponseFormat.Text\n }\n\n if (type.includes('multipart/form-data')) {\n return ResponseFormat.FormData\n }\n\n if (type.includes('application/octet-stream') || type.includes('application/pdf') || type.includes('image/') || type.includes('audio/') || type.includes('video/')) {\n return ResponseFormat.Blob\n }\n\n return undefined\n}\n\n/**\n * Проверяет, является ли ответ файлом на основе заголовков\n * @param headers Заголовки ответа\n * @returns true если ответ является файлом\n */\nexport function isFileResponse(headers: Headers): boolean {\n const contentType = headers.get('content-type') || ''\n const contentDisposition = headers.get('content-disposition') || ''\n\n // Проверяем по типу контента\n const isFileContentType =\n contentType.includes('application/octet-stream') ||\n contentType.includes('application/pdf') ||\n contentType.includes('image/') ||\n contentType.includes('audio/') ||\n contentType.includes('video/')\n\n // Проверяем по заголовку content-disposition\n const isAttachment = contentDisposition.includes('attachment') || contentDisposition.includes('filename=')\n\n return isFileContentType || isAttachment\n}\n\n/**\n * Извлекает имя файла из заголовков\n * @param headers Заголовки ответа\n * @returns Имя файла\n */\nexport function extractFilenameFromHeaders(headers: Headers): string | undefined {\n const contentDisposition = headers.get('content-disposition')\n\n if (!contentDisposition) return undefined\n\n // Пытаемся извлечь имя файла из content-disposition\n const filenameMatch = contentDisposition.match(/filename[^;=\\n]*=((['\"]).*?\\2|[^;\\n]*)/)\n if (filenameMatch && filenameMatch[1]) {\n // Очищаем от кавычек\n return filenameMatch[1].replace(/['\"]/g, '').trim()\n }\n\n return undefined\n}\n\n/**\n * Извлекает метаданные файла из заголовков\n * @param headers Заголовки ответа\n * @returns Метаданные файла\n */\nexport function getFileMetadataFromHeaders(headers: Headers): Record<string, any> | undefined {\n const contentType = headers.get('content-type') || ''\n const contentDisposition = headers.get('content-disposition') || ''\n const contentLength = headers.get('content-length')\n\n if (!isFileResponse(headers)) {\n return undefined\n }\n\n const filename = extractFilenameFromHeaders(headers)\n\n return {\n filename,\n contentType,\n contentDisposition,\n size: contentLength ? parseInt(contentLength, 10) : undefined,\n }\n}\n\n/**\n * Создает blob URL для файла\n * @param blob Объект Blob или File\n * @returns URL для доступа к файлу\n */\nexport function createBlobUrl(blob: Blob): string {\n return URL.createObjectURL(blob)\n}\n\n/**\n * Освобождает blob URL\n * @param url URL для освобождения\n */\nexport function revokeBlobUrl(url: string): void {\n URL.revokeObjectURL(url)\n}\n\n/**\n * Скачивает файл в браузере\n * @param blob Объект Blob или File\n * @param filename Имя файла\n */\nexport function downloadBlob(blob: Blob, filename: string): void {\n const url = createBlobUrl(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = filename\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n setTimeout(() => revokeBlobUrl(url), 100)\n}\n","import { ApiContext, FetchBaseQueryArgs, RequestDefinition, ResponseFormat } from '../types/api.interface'\nimport { FileDownloadResult, QueryOptions, QueryResult } from '../types/query.interface'\nimport { getFileMetadataFromHeaders, getResponseFormatForMimeType, isFileResponse } from './file-utils'\n\n/**\n * Извлекает данные из response в зависимости от формата\n * @param response Объект Response\n * @param format Формат ответа\n * @returns Объект с данными или ошибкой\n */\nasync function getResponseData<T, E extends Error>(response: Response, format?: ResponseFormat): Promise<{ data?: T; error?: E; fileMetadata?: FileDownloadResult }> {\n let responseFormat = format\n const contentType = response.headers.get('content-type') || ''\n\n // Если формат не указан, пытаемся определить его из MIME-типа\n if (!responseFormat && contentType) {\n // Проверка, является ли ответ файлом на основе заголовков\n if (isFileResponse(response.headers)) {\n responseFormat = ResponseFormat.Blob\n } else {\n responseFormat = getResponseFormatForMimeType(contentType)\n }\n }\n\n // Если формат всё ещё не определен, используем JSON по умолчанию\n if (!responseFormat) {\n responseFormat = ResponseFormat.Json\n }\n\n try {\n // Получение метаданных файла, если формат указывает на файл\n let fileMetadata: any\n if (responseFormat === ResponseFormat.Blob || responseFormat === ResponseFormat.ArrayBuffer) {\n fileMetadata = getFileMetadataFromHeaders(response.headers)\n }\n\n // Обработка данных в зависимости от формата\n switch (responseFormat) {\n case ResponseFormat.Json: {\n // Пробуем получить JSON-данные\n try {\n const data = await response.json()\n return response.ok ? { data: data as T, fileMetadata } : { error: data as E, fileMetadata }\n } catch (error) {\n // Если не удалось разобрать JSON, возвращаем текст\n const text = await response.text()\n return response.ok ? { data: text as unknown as T, fileMetadata } : { error: text as unknown as E, fileMetadata }\n }\n }\n\n case ResponseFormat.Text: {\n const text = await response.text()\n return response.ok ? { data: text as unknown as T, fileMetadata } : { error: text as unknown as E, fileMetadata }\n }\n\n case ResponseFormat.Blob: {\n const blob = await response.blob()\n return response.ok ? { data: blob as unknown as T, fileMetadata } : { error: blob as unknown as E, fileMetadata }\n }\n\n case ResponseFormat.ArrayBuffer: {\n const buffer = await response.arrayBuffer()\n return response.ok ? { data: buffer as unknown as T, fileMetadata } : { error: buffer as unknown as E, fileMetadata }\n }\n\n case ResponseFormat.FormData: {\n const formData = await response.formData()\n return response.ok ? { data: formData as unknown as T, fileMetadata } : { error: formData as unknown as E, fileMetadata }\n }\n\n case ResponseFormat.Raw: {\n return response.ok ? { data: response as unknown as T, fileMetadata } : { error: response as unknown as E, fileMetadata }\n }\n\n default:\n // Если формат неизвестен, возвращаем blob как наиболее универсальный\n // eslint-disable-next-line no-case-declarations\n const blob = await response.blob()\n return response.ok ? { data: blob as unknown as T, fileMetadata } : { error: blob as unknown as E, fileMetadata }\n }\n } catch (err) {\n console.error(`[API] Ошибка извлечения данных из ответа (формат: ${responseFormat})`, err)\n return response.ok ? { data: undefined } : { error: err as E }\n }\n}\n\n/**\n * Создает базовый fetch-клиент для запросов с поддержкой файлов\n * @param options Настройки базового клиента\n * @returns Функция для выполнения запросов\n */\nexport function fetchBaseQuery(options: Omit<FetchBaseQueryArgs, 'prepareHeaders'>) {\n const { baseUrl, timeout = 30000, fetchFn = fetch, credentials = 'same-origin' } = options\n\n return async <RequestResult, RequestParams extends Record<string, any>, E extends Error = Error>(\n args: RequestDefinition<RequestParams>,\n queryOptions: QueryOptions = {},\n headers: Headers,\n ): Promise<QueryResult<RequestResult, E>> => {\n const { path, method, body, query, responseFormat: reqResponseFormat } = args\n\n const { signal, timeout: requestTimeout = timeout, responseFormat: optResponseFormat } = queryOptions\n\n // Определяем формат ответа с приоритетом от options\n const responseFormat = optResponseFormat || reqResponseFormat\n\n // Строим URL с учетом api параметров\n const url = new URL(path.startsWith('http') ? path : `${baseUrl}${path}`)\n\n // Добавляем query-параметры в URL\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((item) => url.searchParams.append(key, String(item)))\n } else {\n url.searchParams.append(key, String(value))\n }\n }\n })\n }\n\n // Если body это объект, конвертируем в JSON и устанавливаем Content-Type\n let serializedBody: string | FormData | Blob | undefined\n if (body !== undefined) {\n if (body instanceof FormData || body instanceof Blob) {\n serializedBody = body\n } else if (typeof body === 'object' && body !== null) {\n try {\n serializedBody = JSON.stringify(body)\n if (!headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n } catch (error) {\n console.error('[API] Ошибка сериализации тела запроса', error)\n serializedBody = String(body)\n }\n } else {\n serializedBody = String(body)\n }\n }\n\n // Создаем таймаут если указан\n let timeoutId: number | undefined\n const timeoutPromise = new Promise<never>((_, reject) => {\n if (requestTimeout) {\n timeoutId = window.setTimeout(() => {\n reject(new Error(`Превышено время ожидания запроса (${requestTimeout}мс)`))\n }, requestTimeout)\n }\n })\n\n try {\n // Выполняем запрос\n const fetchPromise = fetchFn(url.toString(), {\n method,\n headers,\n body: serializedBody,\n signal,\n credentials,\n })\n\n // Используем Promise.race для обработки таймаута\n const response = await Promise.race([fetchPromise, timeoutPromise])\n\n // Обрабатываем ответ\n const { data, error, fileMetadata } = await getResponseData<RequestResult, E>(response, responseFormat as ResponseFormat)\n\n // Формируем результат запроса\n const result: QueryResult<RequestResult, E> = {\n data,\n error,\n ok: response.ok,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n fileDownloadResult: fileMetadata,\n }\n\n return result\n } catch (err) {\n // Обрабатываем ошибки сети или таймаута\n const error = err as Error\n console.error('[API] Ошибка выполнения запроса', error)\n\n // Формируем результат с ошибкой\n return {\n error: error as E,\n ok: false,\n status: 0,\n statusText: error.message,\n headers: new Headers(),\n }\n } finally {\n // Очищаем таймер в любом случае\n if (timeoutId) {\n window.clearTimeout(timeoutId)\n }\n }\n }\n}\n","/**\n * Создает объект с заголовками для кэширования на основе списка допустимых ключей\n * @param headers Заголовки запроса\n * @param cacheableHeaders Массив ключей заголовков, которые нужно включить в кэш\n * @returns Объект с отфильтрованными заголовками\n */\nexport function getCacheableHeaders(headers: Headers, cacheableHeaders: string[] = []): Record<string, string> {\n const result: Record<string, string> = {}\n\n if (!headers || cacheableHeaders.length === 0) {\n return result\n }\n\n // Проходим по всем ключам в cacheableHeaders\n cacheableHeaders.forEach((key) => {\n // Если заголовок существует, добавляем его в результат\n if (headers.has(key)) {\n result[key] = headers.get(key) || ''\n }\n })\n\n return result\n}\n","import { CreateApiClientOptions } from '../types/api.interface'\nimport { Endpoint as EndpointType, EndpointConfig, EndpointState, RequestResponseModify, RequestState } from '../types/endpoint.interface'\nimport { QueryOptions, QueryResult, Unsubscribe } from '../types/query.interface'\nimport { createUniqueId, headersToObject } from '../utils/api-helpers'\nimport { createHeaderContext } from '../utils/create-header-context'\nimport { createPrepareHeaders, prepareRequestHeaders } from '../utils/endpoint-headers'\nimport { fetchBaseQuery } from '../utils/fetch-base-query'\nimport { getCacheableHeaders } from '../utils/get-cacheable-headers'\nimport { QueryStorage } from './query-storage'\n\nexport class EndpointClass<RequestParams extends Record<string, any>, RequestResponse> implements EndpointType<RequestParams, RequestResponse> {\n private readonly endpointSubscribers = new Set<(state: EndpointState) => void>()\n\n /** Сколько раз был вызван метод request */\n fetchCounts: number = 0\n\n meta: EndpointType['meta'] = {\n cache: false,\n invalidatesTags: [],\n name: '',\n tags: [],\n }\n\n private readonly queryFunction: ReturnType<typeof fetchBaseQuery>\n\n /** Массив заголовков, которые нужно включить в ключ кэширования */\n private readonly cacheableHeaders: string[]\n\n private readonly prepareHeaders: ReturnType<typeof createPrepareHeaders>\n\n constructor(\n private readonly name: string,\n private readonly queryStorage: QueryStorage,\n private readonly configCurrentEndpoint: EndpointConfig<RequestParams, RequestResponse>,\n private readonly cacheableHeaderKeys: CreateApiClientOptions['cacheableHeaderKeys'],\n private readonly globalCacheConfig: CreateApiClientOptions['cache'],\n private readonly baseQueryConfig: CreateApiClientOptions['baseQuery'],\n ) {\n // 1. Создаем функцию подготовки заголовков\n this.prepareHeaders = createPrepareHeaders(baseQueryConfig.prepareHeaders, configCurrentEndpoint.prepareHeaders)\n // 2. Создаем функцию исполнения запроса\n this.queryFunction = fetchBaseQuery({\n baseUrl: baseQueryConfig.baseUrl,\n fetchFn: baseQueryConfig.fetchFn,\n timeout: baseQueryConfig.timeout,\n credentials: baseQueryConfig.credentials,\n })\n // 3. Создаем массив тех заголовков, которые нужно включить в ключ кэширования\n this.cacheableHeaders = [...(cacheableHeaderKeys || []), ...(configCurrentEndpoint.includeCacheableHeaderKeys || [])].filter(\n (key) => !configCurrentEndpoint.excludeCacheableHeaderKeys?.includes(key),\n )\n // 4. Сохраняем информацию в meta\n this.meta.name = name\n this.meta.tags = configCurrentEndpoint.tags ?? this.meta.tags\n this.meta.invalidatesTags = configCurrentEndpoint.invalidatesTags ?? this.meta.invalidatesTags\n this.meta.cache = this.queryStorage.createCacheConfig(this.configCurrentEndpoint) ?? this.meta.cache\n }\n\n public request(params: RequestParams, options?: QueryOptions): RequestResponseModify<RequestResponse> {\n // 1. Подготовка и инициализация\n this.fetchCounts++\n const requestId = createUniqueId(this.name)\n const controller = new AbortController()\n const requestSubscribers = new Set<(state: RequestState<RequestResponse, RequestParams>) => void>()\n const currentState: RequestState<RequestResponse, RequestParams> = {\n status: 'idle',\n requestParams: params,\n headers: {},\n error: undefined,\n data: undefined,\n fromCache: false,\n }\n const headerContext = createHeaderContext({ requestParams: params }, options?.context || {})\n\n // 2. Создаем функции для управления состоянием\n const notifyRequestSubscribers = (newState: Partial<RequestState<RequestResponse, RequestParams>>) => {\n Object.assign(currentState, newState)\n requestSubscribers.forEach((cb) => {\n cb({ ...currentState })\n })\n }\n\n // 3. Создаем промис для метода wait()\n const waitPromise = new Promise<QueryResult<RequestResponse, Error>>(async (resolve, reject) => {\n try {\n // Формируем заголовки\n const headers = await prepareRequestHeaders(this.prepareHeaders, headerContext)\n // Получаем заголовки для кэширования\n const headersForCache = getCacheableHeaders(headers, options?.cacheableHeaderKeys ? options.cacheableHeaderKeys : this.cacheableHeaders)\n // Проверяем включено ли кэширование\n const shouldCache = this.queryStorage.shouldCache(this.configCurrentEndpoint, options)\n // Формируем ключ кэша\n const [cacheKey, cacheParams] = this.queryStorage.createCacheKey(this.name, { ...params, ...headersForCache })\n\n // 4. Проверяем кэш до установки loading\n let cachedResult: QueryResult<RequestResponse> | undefined\n if (shouldCache) {\n cachedResult = await this.queryStorage.getCachedResult<QueryResult<RequestResponse> | undefined>(cacheKey)\n }\n\n if (cachedResult) {\n // Есть данные в кэше - сразу переходим к success\n notifyRequestSubscribers({\n fromCache: true,\n status: 'success',\n data: cachedResult.data,\n error: undefined,\n headers: cachedResult.headers,\n requestParams: params,\n })\n resolve({\n ...cachedResult,\n fromCache: true,\n })\n } else {\n // Нет данных в кэше - устанавливаем loading и делаем запрос\n notifyRequestSubscribers({\n fromCache: false,\n status: 'loading',\n })\n\n // 5. Выполняем запрос\n const requestDefinition = this.configCurrentEndpoint.request(params, options?.context)\n const mergedOptions: QueryOptions = { ...options, signal: controller.signal }\n\n const response = await this.queryFunction<RequestResponse, RequestParams>(requestDefinition, mergedOptions, headers)\n\n // 6. Обрабатываем результат запроса\n if (response.ok) {\n const { headers, ...restResponse } = response\n // Сохраняем в кэш, если нужно\n if (shouldCache) {\n const currentCacheConfig = this.queryStorage.createCacheConfig(this.configCurrentEndpoint)\n await this.queryStorage.setCachedResult(\n cacheKey,\n { ...restResponse, headers: headersToObject(headers) },\n currentCacheConfig,\n cacheParams ?? {},\n this.configCurrentEndpoint.tags ?? [],\n this.configCurrentEndpoint.invalidatesTags ?? [],\n )\n }\n\n // Оповещаем о success\n notifyRequestSubscribers({\n fromCache: false,\n status: 'success',\n data: response.data,\n error: undefined,\n headers: response.headers,\n requestParams: params,\n })\n\n // Уведомляем подписчиков эндпоинта\n this.endpointSubscribers.forEach((cb) => {\n const endpointState: EndpointState = {\n status: 'success',\n fetchCounts: this.fetchCounts,\n meta: this.meta,\n cacheableHeaders: this.cacheableHeaders,\n error: undefined,\n }\n cb(endpointState)\n })\n resolve({\n ...response,\n fromCache: false,\n })\n } else {\n // Оповещаем об ошибке\n notifyRequestSubscribers({\n fromCache: false,\n status: 'error',\n data: undefined,\n error: response.error,\n headers: response.headers,\n requestParams: params,\n })\n\n // Уведомляем подписчиков эндпоинта\n this.endpointSubscribers.forEach((cb) => {\n const endpointState: EndpointState = {\n status: 'error',\n fetchCounts: this.fetchCounts,\n meta: this.meta,\n cacheableHeaders: this.cacheableHeaders,\n error: response.error,\n }\n cb(endpointState)\n })\n\n reject(response.error)\n }\n }\n } catch (error) {\n // Обрабатываем неожиданные ошибки\n notifyRequestSubscribers({\n fromCache: false,\n status: 'error',\n data: undefined,\n error: error as Error,\n headers: undefined,\n requestParams: params,\n })\n reject(error)\n }\n })\n\n // 4. Возвращаем объект с методами управления запросом\n return {\n id: requestId,\n\n subscribe(listener, options = {}) {\n const { autoUnsubscribe = true } = options\n requestSubscribers.add(listener)\n listener(currentState)\n\n const unsubscribe = () => requestSubscribers.delete(listener)\n\n if (autoUnsubscribe) {\n waitPromise.finally(() => {\n unsubscribe()\n })\n }\n\n return unsubscribe\n },\n\n wait: () => waitPromise,\n\n waitWithCallbacks(handlers = {}) {\n const { idle, loading, success, error } = handlers\n\n this.subscribe(\n (state: RequestState<RequestResponse, RequestParams>) => {\n switch (state.status) {\n case 'idle':\n idle?.(state)\n break\n case 'loading':\n loading?.(state)\n break\n case 'success':\n success?.(state.data, state)\n break\n case 'error':\n error?.(state.error, state)\n break\n }\n },\n { autoUnsubscribe: true },\n )\n\n return waitPromise\n },\n\n abort: () => {\n if (controller && !controller.signal.aborted) {\n controller.abort()\n }\n },\n\n then: (onfulfilled, onrejected) => waitPromise.then(onfulfilled, onrejected),\n catch: (onrejected) => waitPromise.catch(onrejected),\n finally: (onfinally) => waitPromise.finally(onfinally),\n }\n }\n\n public subscribe(cb: (state: EndpointState) => void): Unsubscribe {\n this.endpointSubscribers.add(cb)\n\n // Создаем объект с текущей статистикой, соответствующий интерфейсу EndpointState\n const currentState: EndpointState = {\n status: 'idle',\n fetchCounts: this.fetchCounts,\n meta: this.meta,\n cacheableHeaders: this.cacheableHeaders,\n error: undefined,\n }\n\n // Вызываем callback с текущим состоянием\n cb(currentState)\n\n // Возвращаем функцию отписки\n return () => this.endpointSubscribers.delete(cb)\n }\n\n public reset() {\n this.fetchCounts = 0\n return Promise.resolve()\n }\n\n public destroy() {\n this.endpointSubscribers.clear()\n }\n}\n","export class StorageKey {\n constructor(\n private readonly value: string,\n private readonly isRawKey: boolean = false,\n ) {}\n\n toString(): string {\n return this.value\n }\n\n toJSON(): string {\n return this.value\n }\n\n valueOf(): string {\n return this.value\n }\n\n isUnparseable(): boolean {\n return this.isRawKey\n }\n}\n\n// Тип, который может быть либо строкой, либо StorageKey\nexport type StorageKeyType = string | StorageKey\n","import { StorageKey, StorageKeyType } from './storage-key'\n\nexport interface CacheMetadata {\n createdAt: number\n updatedAt: number\n expiresAt: number\n tags?: string[]\n createdAtDateTime: string\n updatedAtDateTime: string\n expiresAtDateTime: string\n}\n\nexport interface CacheOptions {\n ttl?: number\n cleanup?: {\n enabled: boolean\n interval?: number\n }\n invalidateOnError?: boolean\n}\n\nexport interface CacheEntry<Data, Params extends Record<string, any> = any> {\n data: Data\n metadata: CacheMetadata\n params: Params\n}\n\nexport class CacheUtils {\n static createMetadata(ttl: number = 0, tags: string[] = []): CacheMetadata {\n const now = Date.now()\n const expiresAt = ttl > 0 ? now + ttl : Infinity\n\n return {\n createdAt: now,\n updatedAt: now,\n expiresAt,\n tags,\n createdAtDateTime: this.formatDateTime(now),\n updatedAtDateTime: this.formatDateTime(now),\n expiresAtDateTime: expiresAt === Infinity ? 'never' : this.formatDateTime(expiresAt),\n }\n }\n\n private static formatDateTime(timestamp: number): string {\n return new Date(timestamp).toISOString()\n }\n\n static isExpired(metadata: CacheMetadata): boolean {\n return Date.now() > metadata.expiresAt\n }\n\n static updateMetadata(metadata: CacheMetadata): CacheMetadata {\n return {\n ...metadata,\n updatedAt: Date.now(),\n }\n }\n\n static createKey(...parts: (string | number)[]): StorageKey {\n return new StorageKey(parts.join('_'))\n }\n\n static createApiKey(endpoint: string, params?: Record<string, any>): [StorageKeyType, Record<string, any> | undefined] {\n if (!params) return [new StorageKey(endpoint, true), params]\n\n const sortedParams = Object.entries(params)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}=${v}`)\n .join('&')\n\n return [new StorageKey(`${endpoint}_${sortedParams}`, true), params]\n }\n\n // Функция для проверки, есть ли у записи определенные теги\n static hasAnyTag(metadata: CacheMetadata, tags: string[] = []): boolean {\n if (!metadata.tags || !tags.length) return false\n return tags.some((tag) => metadata.tags?.includes(tag))\n }\n}\n","import { IndexedDBStorage, IStorage, LocalStorage, MemoryStorage, StorageKeyType, StorageType } from '../../core/storage'\nimport { CacheEntry, CacheUtils } from '../../core/storage/utils/cache.util'\nimport { CacheConfig, CreateApiClientOptions } from '../types/api.interface'\nimport { EndpointConfig } from '../types/endpoint.interface'\nimport { QueryOptions } from '../types/query.interface'\n\n/**\n * Менеджер хранилища для API\n * Объединяет в себе функционал хранилища и управления кэшем\n */\nexport class QueryStorage {\n /** Экземпляр хранилища */\n private storage: IStorage | null = null\n\n private cleanupInterval: NodeJS.Timeout | number | null = null\n\n /** Настройки кэша по умолчанию */\n private defaultCacheOptions: Exclude<CacheConfig, boolean> = {\n ttl: 5 * 60 * 1000, // 5 минут по умолчанию\n cleanup: {\n enabled: true,\n interval: 10 * 60 * 1000, // 10 минут\n },\n invalidateOnError: true,\n }\n\n constructor(\n private readonly storageExternal: CreateApiClientOptions['storage'],\n private readonly globalCacheConfig: CreateApiClientOptions['cache'],\n ) {}\n\n public async initialize(): Promise<this> {\n // 1. Создаем хранилище\n await this.createStorage()\n // 2. Запускаем периодическую очистку, если это указано в настройках\n this.startCleanupInterval()\n\n return this\n }\n\n private async createStorage() {\n try {\n const s: IStorage = this.storageExternal\n\n await s.initialize()\n this.storage = s\n } catch (error) {\n console.error('Ошибка инициализации хранилища', error)\n throw error\n }\n }\n\n private startCleanupInterval(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval)\n this.cleanupInterval = null\n }\n\n // Получаем настройки очистки\n const cleanupConfig = typeof this.globalCacheConfig === 'object' ? this.globalCacheConfig.cleanup : this.defaultCacheOptions.cleanup\n\n // Запускаем интервал очистки, если он включен\n if (cleanupConfig?.enabled && cleanupConfig.interval) {\n this.cleanupInterval = setInterval(() => {\n this.cleanup().catch((err) => console.error('Ошибка при очистке кэша:', err))\n }, cleanupConfig.interval)\n }\n }\n\n /**\n * Получает экземпляр хранилища\n */\n public getStorage(): IStorage | null {\n return this.storage\n }\n\n /**\n * Создает ключ кэша для запроса с учетом заголовков\n * @param endpoint Имя эндпоинта\n * @param params Параметры запроса (все что посчитаем нужным)\n */\n public createCacheKey<CacheParams extends Record<string, any>>(endpoint: string, params: CacheParams) {\n return CacheUtils.createApiKey(endpoint, params)\n }\n\n /**\n * Получает результат запроса из кэша\n */\n public async getCachedResult<T>(cacheKey: StorageKeyType): Promise<T | undefined> {\n if (!this.storage) throw new Error('Хранилище не инициализировано')\n\n const cachedEntry = await this.storage.get<CacheEntry<T>>(cacheKey)\n if (!cachedEntry) return undefined\n\n // Проверяем срок годности кэша\n if (CacheUtils.isExpired(cachedEntry.metadata)) {\n await this.storage.delete(cacheKey)\n return undefined\n }\n\n // Обновляем метаданные кэша (счетчик доступа, время обновления)\n const updatedEntry: CacheEntry<T> = {\n ...cachedEntry,\n metadata: CacheUtils.updateMetadata(cachedEntry.metadata),\n }\n await this.storage.set(cacheKey, updatedEntry)\n\n return cachedEntry.data\n }\n\n /**\n * Сохраняет результат запроса в кэш\n * @param cacheKey Ключ кэша\n * @param data Данные для кэширования\n * @param cacheOptions Метаданные\n * @param cacheParams Параметры которые влияли на созадние ключа\n * @param tags Тэги эндпоинта\n * @param invalidatesTags Тэги которые нужно инвалидировать\n */\n public async setCachedResult<T, CacheParams extends Record<string, any>>(\n cacheKey: StorageKeyType,\n data: T,\n cacheOptions: Exclude<CacheConfig, boolean>,\n cacheParams: CacheParams,\n tags: string[],\n invalidatesTags: string[],\n ): Promise<void> {\n if (!this.storage) throw new Error('Хранилище не инициализировано')\n\n // Проверяем, нужно ли инвалидировать другие кэши по тегам\n if (invalidatesTags?.length) {\n await this.invalidateCacheByTags(invalidatesTags)\n }\n\n // Создаем метаданные кэша\n const cacheMetadata = CacheUtils.createMetadata(cacheOptions.ttl, tags)\n\n // Создаем запись кэша\n const cacheEntry: CacheEntry<T> = {\n data,\n metadata: cacheMetadata,\n params: cacheParams,\n }\n\n await this.storage.set(cacheKey, cacheEntry)\n }\n\n /**\n * Проверяет, должен ли запрос быть кэширован\n * @param endpointConfig Конфигурация эндпоинта\n * @param options Опции запроса\n * @returns true если запрос должен кэшироваться\n */\n public shouldCache(endpointConfig?: EndpointConfig, options?: QueryOptions) {\n // Если глобальный кэш отключен, возвращаем false\n if (this.globalCacheConfig === false) return false\n // Если эндпоинт явно отключает кэш, возвращаем false\n if (endpointConfig?.cache === false) return false\n // Если по какой то причине указали время кэша 0\n if (typeof endpointConfig?.cache === 'object' && endpointConfig?.cache.ttl === 0) return false\n // Если при вызове самого запроса явно указали НЕ кэшировать\n if (options?.disableCache === true) return false\n // Если настройки нигде не указаны - по умолчанию НЕ кэшируем\n if (this.globalCacheConfig === undefined && endpointConfig?.cache === undefined) return false\n\n return true\n }\n\n /**\n * Создает итоговую конфигурацию кэширования для конкретного эндпоинта\n * Объединяет глабальный конфиг с текущим\n * @param endpointConfig Конфигурация эндпоинта\n */\n public createCacheConfig(endpointConfig?: EndpointConfig) {\n // Создаем опции по умолчанию\n let resultConfig = this.defaultCacheOptions\n\n // Если в глобальном конфиге кэш передан как объект а не boolean - по умолчанию станет он\n if (typeof this.globalCacheConfig === 'object') {\n resultConfig = this.globalCacheConfig\n }\n // Если в настройках эндпоинта кэш как объект - дополняем этими параметрами итоговый объект кэша\n if (typeof endpointConfig?.cache === 'object') {\n const endpointCache = endpointConfig.cache\n resultConfig = {\n // @ts-ignore\n ...resultConfig,\n ...endpointCache,\n }\n }\n\n return resultConfig\n }\n\n /**\n * Инвалидирует кэш по тегам\n * @param tags Теги для инвалидации\n */\n public async invalidateCacheByTags(tags: string[]): Promise<void> {\n if (!this.storage) throw new Error('Хранилище не инициализировано')\n\n const keys = await this.storage.keys()\n for (const key of keys) {\n const cachedEntry = await this.storage.get<CacheEntry<any>>(key)\n if (cachedEntry && CacheUtils.hasAnyTag(cachedEntry.metadata, tags)) {\n await this.storage.delete(key)\n }\n }\n }\n\n /**\n * Инвалидирует кэш по ключу\n * @param cacheKey Ключ кэша\n */\n public async invalidateCache(cacheKey: StorageKeyType): Promise<void> {\n if (!this.storage) throw new Error('Хранилище не инициализировано')\n\n await this.storage.delete(cacheKey)\n }\n\n /**\n * Выполняет очистку всех просроченных записей кэша\n */\n public async cleanup(): Promise<void> {\n if (!this.storage) {\n throw new Error('Хранилище не инициализировано')\n }\n\n const keys = await this.storage.keys()\n for (const key of keys) {\n const value = await this.storage.get<CacheEntry<any>>(key)\n if (value && CacheUtils.isExpired(value.metadata)) {\n await this.storage.delete(key)\n }\n }\n }\n\n /**\n * Уничтожает хранилище и освобождает ресурсы\n */\n public async destroy(): Promise<void> {\n // Останавливаем интервал очистки\n if (this.cleanupInterval) {\n window.clearInterval(this.cleanupInterval)\n this.cleanupInterval = null\n }\n\n // Очищаем хранилище\n if (this.storage) {\n await this.storage.destroy()\n this.storage = null\n }\n }\n}\n","import { EndpointClass } from './components/endpoint'\nimport { QueryStorage } from './components/query-storage'\nimport { CreateApiClientOptions, ExtractParamsType, ExtractResultType } from './types/api.interface'\nimport { CreateEndpoint, Endpoint as EndpointType, EndpointConfig } from './types/endpoint.interface'\nimport { QueryOptions, QueryResult } from './types/query.interface'\nimport { apiLogger } from './utils/api-helpers'\n\n// Тип для извлечения типов из функции endpoints\ntype EndpointsResult<F> = F extends (create: any) => Promise<infer R> ? R : never\n\nexport class ApiClient<EndpointsFn extends (create: CreateEndpoint) => Promise<Record<string, EndpointConfig<any, any>>>> {\n /** Хранилище запросов */\n // @ts-ignore\n private queryStorage: QueryStorage\n\n private readonly cacheableHeaderKeys: CreateApiClientOptions['cacheableHeaderKeys']\n\n private readonly globalCacheConfig: CreateApiClientOptions['cache']\n\n private readonly baseQueryConfig: CreateApiClientOptions['baseQuery']\n\n private readonly storageExternal: CreateApiClientOptions['storage']\n\n private readonly createEndpoints: EndpointsFn\n\n /** Реестр эндпоинтов */\n private endpoints: {\n [K in keyof EndpointsResult<EndpointsFn>]?: EndpointType<ExtractParamsType<EndpointsResult<EndpointsFn>[K]>, ExtractResultType<EndpointsResult<EndpointsFn>[K]>>\n } = {}\n\n constructor(options: Omit<CreateApiClientOptions, 'endpoints'> & { endpoints: EndpointsFn }) {\n // Сохраняем переданные параметры\n this.cacheableHeaderKeys = options.cacheableHeaderKeys\n this.globalCacheConfig = options.cache\n this.baseQueryConfig = options.baseQuery\n this.storageExternal = options.storage\n this.createEndpoints = options.endpoints\n }\n\n public async init(): Promise<this> {\n // 1. Создаем кэшированное хранилище запросов\n this.queryStorage = await new QueryStorage(this.storageExternal, this.globalCacheConfig).initialize()\n\n // 2. Создаем эндпоинты\n await this.initializeEndpoints()\n\n return this\n }\n\n private async initializeEndpoints() {\n // Получаем конфигурацию будущих эндпоинтов\n const create: CreateEndpoint = <TParams extends Record<string, any>, TResult>(config: EndpointConfig<TParams, TResult>) => config\n // Создаем объект с конфигурациями для эндпоинтов\n const endpointsConfig = (await this.createEndpoints(create)) || {}\n\n // Создаем эндпоинты\n for (const [endpointKey, endpointConfig] of Object.entries(endpointsConfig)) {\n const key = endpointKey as keyof EndpointsResult<EndpointsFn>\n this.endpoints[key] = new EndpointClass(endpointKey, this.queryStorage, endpointConfig, this.cacheableHeaderKeys, this.globalCacheConfig, this.baseQueryConfig)\n }\n }\n\n /**\n * Получает все эндпоинты с улучшенной типизацией\n * @returns Типизированный объект эндпоинтов\n */\n public getEndpoints(): {\n [K in keyof EndpointsResult<EndpointsFn>]: EndpointType<ExtractParamsType<EndpointsResult<EndpointsFn>[K]>, ExtractResultType<EndpointsResult<EndpointsFn>[K]>>\n } {\n return this.endpoints as any\n }\n\n /**\n * Выполняет запрос к API с типизацией и обработкой ошибок\n * @param endpointName Имя эндпоинта (с подсказками TypeScript)\n * @param params Параметры запроса (с типизацией)\n * @param options Опции запроса\n * @returns Promise с типизированным результатом запроса\n */\n public async request<K extends keyof EndpointsResult<EndpointsFn> & string>(\n endpointName: K,\n params: ExtractParamsType<EndpointsResult<EndpointsFn>[K]>,\n options?: QueryOptions,\n ): Promise<QueryResult<ExtractResultType<EndpointsResult<EndpointsFn>[K]>, Error>> {\n const endpoints = this.getEndpoints()\n const endpoint = endpoints[endpointName]\n\n if (!endpoint) {\n throw new Error(`Эндпоинт ${String(endpointName)} не найден`)\n }\n\n try {\n const stateRequest = endpoint.request(params, options)\n return await stateRequest.wait()\n } catch (error) {\n apiLogger.error(`Ошибка запроса к ${String(endpointName)}`, { error, params })\n throw error\n }\n }\n\n public async destroy() {\n // 1. Сначала уничтожаем каждый эндпоинт\n await Promise.all(\n Object.values(this.endpoints).map(async (endpoint) => {\n endpoint.destroy()\n return Promise.resolve()\n }),\n )\n\n // 2. Очищаем коллекцию эндпоинтов\n this.endpoints = {}\n // 3. Уничтожаем хранилище\n await this.queryStorage.destroy()\n }\n}\n"],"mappings":"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","names":["ResponseFormat","blob","headers","options"]}
package/dist/api.d.cts ADDED
@@ -0,0 +1,365 @@
1
+ import { I as IStorage } from './storage.interface-Dl8SLUd1.cjs';
2
+
3
+ /**
4
+ * Тип для функции отписки от событий
5
+ */
6
+ type Unsubscribe = VoidFunction;
7
+ /**
8
+ * Опции для выполнения запроса
9
+ */
10
+ interface QueryOptions {
11
+ /** Отключить кэширование для этого запроса */
12
+ disableCache?: boolean;
13
+ /** Signal для отмены запроса */
14
+ signal?: AbortSignal;
15
+ /** Таймаут в миллисекундах (переопределяет глобальный) */
16
+ timeout?: number;
17
+ /** Дополнительные заголовки */
18
+ headers?: Headers;
19
+ /** Пользовательский контекст */
20
+ context?: Record<string, any>;
21
+ /** Ключи заголовков, влияющие на кэш (для конкретного запроса) */
22
+ cacheableHeaderKeys?: string[];
23
+ /** Формат ответа (переопределяет формат из RequestDefinition) */
24
+ responseFormat?: ResponseFormat;
25
+ /** Название файла при скачивании (переопределяет fileName из RequestDefinition) */
26
+ fileName?: string;
27
+ /** Тип файла при скачивании (переопределяет fileType из RequestDefinition) */
28
+ fileType?: string;
29
+ /** Автоматически скачать файл после получения */
30
+ downloadFile?: boolean;
31
+ /**
32
+ * Функция для повторного выполнения запроса
33
+ */
34
+ retry?: <T = any, R = any>(params: T, options?: QueryOptions) => Promise<R>;
35
+ }
36
+ /**
37
+ * Метаданные для файла
38
+ */
39
+ interface FileMetadata {
40
+ /** Имя файла */
41
+ fileName: string;
42
+ /** Тип файла (MIME-тип) */
43
+ fileType: string;
44
+ /** Размер файла в байтах */
45
+ size?: number;
46
+ /** Дата создания файла */
47
+ createdAt?: Date | string;
48
+ /** Дата изменения файла */
49
+ updatedAt?: Date | string;
50
+ }
51
+ /**
52
+ * Результат скачивания файла
53
+ */
54
+ interface FileDownloadResult<T = Blob | ArrayBuffer> {
55
+ /** Данные файла */
56
+ data: T;
57
+ /** Метаданные файла */
58
+ metadata: FileMetadata;
59
+ /** HTTP-статус */
60
+ status: number;
61
+ /** Текст статуса */
62
+ statusText: string;
63
+ /** Заголовки ответа */
64
+ headers: Headers;
65
+ /** Успешна ли загрузка */
66
+ ok: boolean;
67
+ }
68
+ /**
69
+ * Результат выполнения запроса
70
+ */
71
+ interface QueryResult<T = any, E = Error> {
72
+ /** Данные ответа (при успешном запросе) */
73
+ data?: T;
74
+ /** Ошибка (при неуспешном запросе) */
75
+ error?: E;
76
+ /** Флаг успешности запроса */
77
+ ok: boolean;
78
+ /** HTTP-статус */
79
+ status: number;
80
+ /** Текстовое описание статуса */
81
+ statusText: string;
82
+ /** Заголовки ответа */
83
+ headers: Headers;
84
+ /** Результат скачивания файла (если responseFormat - Blob или ArrayBuffer) */
85
+ fileDownloadResult?: FileDownloadResult;
86
+ fromCache?: boolean;
87
+ }
88
+
89
+ /**
90
+ * Конфигурация эндпоинта
91
+ */
92
+ interface EndpointConfig<RequestParams extends Record<string, any> = any, RequestResult = any> {
93
+ /** Функция для создания определения запроса из параметров */
94
+ request: (params: RequestParams, context?: Record<string, any>) => RequestDefinition<RequestParams>;
95
+ /** Настройки кэша для эндпоинта */
96
+ cache?: CacheConfig;
97
+ /** Теги эндпоинта для группировки в кэше */
98
+ tags?: string[];
99
+ /** Теги, которые инвалидируются при успешном запросе */
100
+ invalidatesTags?: string[];
101
+ /** Функция для подготовки заголовков (дополняет глобальную) */
102
+ prepareHeaders?: (headers: Headers, context: ApiContext<RequestParams>) => Promise<Headers>;
103
+ /** Добавить ключи заголовков, влияющие на кэш (Дополняет глобавльные ключи) */
104
+ includeCacheableHeaderKeys?: string[];
105
+ /** Исключить ключи заголовков, влияющие на кэш (Дополняет глобавльные ключи) */
106
+ excludeCacheableHeaderKeys?: string[];
107
+ }
108
+ /**
109
+ * Состояние эндпоинта
110
+ * Содержит информацию о текущем состоянии запроса и данные
111
+ */
112
+ interface EndpointState {
113
+ /** Статус запроса */
114
+ status: 'idle' | 'loading' | 'success' | 'error';
115
+ /** Ошибка (при неуспешном запросе) */
116
+ error?: Error;
117
+ /** Количество вызовов */
118
+ fetchCounts: number;
119
+ /** Метаданные эндпоинта */
120
+ meta: Endpoint['meta'];
121
+ /** Какие заголовки участвовали в формировании ключа кэша (итоговые) */
122
+ cacheableHeaders: string[];
123
+ }
124
+ /**
125
+ * Состояние самого запроса
126
+ */
127
+ interface RequestState<ResponseData = any, RequestParams extends Record<string, any> = any, E = Error> {
128
+ status: 'loading' | 'success' | 'error' | 'idle';
129
+ data?: ResponseData;
130
+ error?: E;
131
+ headers: Record<string, any> | Headers;
132
+ requestParams: RequestParams;
133
+ fromCache: boolean;
134
+ }
135
+ interface SubscribeOptions {
136
+ /** Автоматически отписаться после завершения запроса */
137
+ autoUnsubscribe?: boolean;
138
+ }
139
+ /**
140
+ * Дополнительные методы для request
141
+ */
142
+ interface RequestResponseModify<T, P extends Record<string, any> = any> {
143
+ id: string;
144
+ /**
145
+ * Подписка на изменения состояния запроса
146
+ */
147
+ subscribe: (listener: (state: RequestState<T, P>) => void, options?: SubscribeOptions) => VoidFunction;
148
+ /**
149
+ * Ожидание завершения запроса
150
+ * @returns Promise с результатом запроса
151
+ */
152
+ wait: () => Promise<QueryResult<T, Error>>;
153
+ waitWithCallbacks: (handlers: {
154
+ idle?: (request: RequestState<T, P>) => void;
155
+ loading?: (request: RequestState<T, P>) => void;
156
+ success?: (data: T | undefined, request: RequestState<T, P>) => void;
157
+ error?: (error: Error | undefined, request: RequestState<T, P>) => void;
158
+ }) => Promise<QueryResult<T, Error>>;
159
+ /**
160
+ * Отменить запрос
161
+ */
162
+ abort: VoidFunction;
163
+ then<TResult1 = QueryResult<T, Error>, TResult2 = never>(onfulfilled?: ((value: QueryResult<T, Error>) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: Error) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
164
+ catch<TResult = never>(onrejected?: ((reason: Error) => TResult | PromiseLike<TResult>) | undefined | null): Promise<QueryResult<T, Error> | TResult>;
165
+ finally(onfinally?: VoidFunction | undefined | null): Promise<QueryResult<T, Error>>;
166
+ }
167
+ /**
168
+ * Структура эндпоинта
169
+ *
170
+ * Эндпоинт - это всего лишь определение того6 как будет вызван метод
171
+ * Эндпоинт может быть вызван в разных частях приложения с разными параметрами
172
+ * По этому нет смысла хранить ответы так как они будут перезаписываться
173
+ * метод subscribe больше нужен для мониторинга
174
+ * meta - метаинформация по эндпоинту (то как он сконфигурирован)
175
+ */
176
+ interface Endpoint<RequestParams extends Record<string, any> = any, ResponseData = any> {
177
+ /** Счетчик вызова конкретного эндпоинта в проекте */
178
+ fetchCounts: number;
179
+ /** Выполнить запрос с параметрами */
180
+ request: (params: RequestParams, options?: QueryOptions) => RequestResponseModify<ResponseData>;
181
+ /** Подписаться на изменения состояния эндпоинта (в основном для сбора статистики) */
182
+ subscribe: (callback: (state: EndpointState) => void) => Unsubscribe;
183
+ /** Сбросить состояние */
184
+ reset: () => Promise<void>;
185
+ /** Метаданные эндпоинта */
186
+ meta: {
187
+ /** Имя эндпоинта */
188
+ name: string;
189
+ /** Теги эндпоинта */
190
+ tags: string[];
191
+ /** Теги, которые инвалидируются */
192
+ invalidatesTags: string[];
193
+ /** Настройки кэша */
194
+ cache: CacheConfig;
195
+ };
196
+ destroy: VoidFunction;
197
+ }
198
+ /**
199
+ * Функция для создания типизированных эндпоинтов
200
+ */
201
+ type CreateEndpoint = <RequestParams extends Record<string, any>, RequestResult>(config: EndpointConfig<RequestParams, RequestResult>) => EndpointConfig<RequestParams, RequestResult>;
202
+
203
+ /**
204
+ * Форматы ответа от сервера
205
+ */
206
+ declare enum ResponseFormat {
207
+ /** JSON-объект (по умолчанию) */
208
+ Json = "json",
209
+ /** Blob-объект для файлов */
210
+ Blob = "blob",
211
+ /** ArrayBuffer для бинарных данных */
212
+ ArrayBuffer = "arrayBuffer",
213
+ /** Текстовый формат */
214
+ Text = "text",
215
+ /** FormData для форм */
216
+ FormData = "formData",
217
+ /** Без преобразования - возвращает сырой ответ */
218
+ Raw = "raw"
219
+ }
220
+ /**
221
+ * Настройки кэша
222
+ * Может быть объектом с параметрами или boolean (true для кэширования с настройками по умолчанию, false для отключения)
223
+ */
224
+ type CacheConfig = boolean | {
225
+ /** Время жизни кэша в миллисекундах */
226
+ ttl?: number;
227
+ /** Настройки периодической очистки */
228
+ cleanup?: {
229
+ /** Включить периодическую очистку */
230
+ enabled: boolean;
231
+ /** Интервал очистки в миллисекундах */
232
+ interval?: number;
233
+ };
234
+ /** Инвалидировать кэш при ошибке */
235
+ invalidateOnError?: boolean;
236
+ };
237
+ /**
238
+ * Определение запроса
239
+ * Содержит всю необходимую информацию для выполнения HTTP-запроса
240
+ */
241
+ interface RequestDefinition<RequestParams extends Record<string, any>> {
242
+ /** Путь запроса (относительный или абсолютный URL) */
243
+ path: string;
244
+ /** HTTP-метод */
245
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
246
+ /** Тело запроса (автоматически сериализуется) */
247
+ body?: any;
248
+ /** Параметры запроса (автоматически добавляются в URL) */
249
+ query?: RequestParams;
250
+ /** HTTP-заголовки */
251
+ headers?: Record<string, string>;
252
+ /** Формат ответа (по умолчанию json) */
253
+ responseFormat?: ResponseFormat;
254
+ /** Имя файла для автоматического скачивания */
255
+ fileName?: string;
256
+ /** Тип контента для автоматического скачивания */
257
+ fileType?: string;
258
+ }
259
+ /**
260
+ * Контекст API для использования в prepareHeaders и других функциях
261
+ * Содержит вспомогательные методы и информацию о запросе
262
+ */
263
+ interface ApiContext<RequestParams extends Record<string, any> = any> {
264
+ /** Параметры запроса */
265
+ requestParams?: RequestParams;
266
+ /** Получить значение из localStorage */
267
+ getFromStorage: <T>(key: string) => T | undefined;
268
+ /** Получить значение cookie */
269
+ getCookie: (name: string) => string | undefined;
270
+ /** Поддержка для дополнительных свойств */
271
+ [key: string]: any;
272
+ }
273
+ /**
274
+ * Аргументы для создания fetch-запроса
275
+ */
276
+ interface FetchBaseQueryArgs {
277
+ /** Базовый URL для всех запросов */
278
+ baseUrl: string;
279
+ /** Функция для подготовки заголовков, может быть асинхронной */
280
+ prepareHeaders?: (headers: Headers, context: ApiContext) => Promise<Headers>;
281
+ /** Таймаут запроса в миллисекундах */
282
+ timeout?: number;
283
+ /** Пользовательская fetch-функция */
284
+ fetchFn?: typeof fetch;
285
+ credentials?: RequestCredentials;
286
+ }
287
+ interface CreateApiClientOptions<T extends Record<string, EndpointConfig<any, any>> = Record<string, EndpointConfig<any, any>>> {
288
+ storage: IStorage;
289
+ /** Настройки кэша
290
+ * если явно указан false - значит ни один запрос НЕ будет кэшироваться, даже если в эндпоинтах указаны параметры
291
+ * */
292
+ cache?: CacheConfig;
293
+ /** Базовый запрос или его настройки */
294
+ baseQuery: FetchBaseQueryArgs;
295
+ /** Функция для создания эндпоинтов */
296
+ endpoints?: (create: CreateEndpoint) => Promise<T>;
297
+ /** Глобальные заголовки, влияющие на кэш */
298
+ cacheableHeaderKeys?: string[];
299
+ }
300
+ /**
301
+ * Извлечение типа параметров из конфигурации эндпоинта
302
+ */
303
+ type ExtractParamsType<T> = T extends EndpointConfig<infer P, any> ? P : never;
304
+ /**
305
+ * Извлечение типа результата из конфигурации эндпоинта
306
+ */
307
+ type ExtractResultType<T> = T extends EndpointConfig<any, infer R> ? R : never;
308
+
309
+ type EndpointsResult<F> = F extends (create: any) => Promise<infer R> ? R : never;
310
+ declare class ApiClient<EndpointsFn extends (create: CreateEndpoint) => Promise<Record<string, EndpointConfig<any, any>>>> {
311
+ /** Хранилище запросов */
312
+ private queryStorage;
313
+ private readonly cacheableHeaderKeys;
314
+ private readonly globalCacheConfig;
315
+ private readonly baseQueryConfig;
316
+ private readonly storageExternal;
317
+ private readonly createEndpoints;
318
+ /** Реестр эндпоинтов */
319
+ private endpoints;
320
+ constructor(options: Omit<CreateApiClientOptions, 'endpoints'> & {
321
+ endpoints: EndpointsFn;
322
+ });
323
+ init(): Promise<this>;
324
+ private initializeEndpoints;
325
+ /**
326
+ * Получает все эндпоинты с улучшенной типизацией
327
+ * @returns Типизированный объект эндпоинтов
328
+ */
329
+ getEndpoints(): {
330
+ [K in keyof EndpointsResult<EndpointsFn>]: Endpoint<ExtractParamsType<EndpointsResult<EndpointsFn>[K]>, ExtractResultType<EndpointsResult<EndpointsFn>[K]>>;
331
+ };
332
+ /**
333
+ * Выполняет запрос к API с типизацией и обработкой ошибок
334
+ * @param endpointName Имя эндпоинта (с подсказками TypeScript)
335
+ * @param params Параметры запроса (с типизацией)
336
+ * @param options Опции запроса
337
+ * @returns Promise с типизированным результатом запроса
338
+ */
339
+ request<K extends keyof EndpointsResult<EndpointsFn> & string>(endpointName: K, params: ExtractParamsType<EndpointsResult<EndpointsFn>[K]>, options?: QueryOptions): Promise<QueryResult<ExtractResultType<EndpointsResult<EndpointsFn>[K]>, Error>>;
340
+ destroy(): Promise<void>;
341
+ }
342
+
343
+ /**
344
+ * Логгер для API
345
+ */
346
+ declare const apiLogger: {
347
+ debug: (message: string, ...args: any[]) => void;
348
+ log: (message: string, ...args: any[]) => void;
349
+ info: (message: string, ...args: any[]) => void;
350
+ warn: (message: string, ...args: any[]) => void;
351
+ error: (message: string, ...args: any[]) => void;
352
+ };
353
+ /**
354
+ * Создает уникальный идентификатор
355
+ * @returns Строка с уникальным идентификатором
356
+ */
357
+ declare function createUniqueId(name?: string): string;
358
+ /**
359
+ * Преобразует объект Headers в обычный объект
360
+ * @param headers Объект Headers
361
+ * @returns Обычный объект с заголовками
362
+ */
363
+ declare function headersToObject(headers: Headers): Record<string, string>;
364
+
365
+ export { ApiClient, ResponseFormat, apiLogger, createUniqueId, headersToObject };