@cyberskill/shared 3.2.0 → 3.3.0

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 (237) hide show
  1. package/dist/config/commitlint/index.js +8 -9
  2. package/dist/config/commitlint/index.js.map +1 -1
  3. package/dist/config/config.type.js +8 -5
  4. package/dist/config/config.type.js.map +1 -1
  5. package/dist/config/config.util.js +33 -42
  6. package/dist/config/config.util.js.map +1 -1
  7. package/dist/config/env/env.constant.js +6 -5
  8. package/dist/config/env/env.constant.js.map +1 -1
  9. package/dist/config/env/env.util.js +26 -27
  10. package/dist/config/env/env.util.js.map +1 -1
  11. package/dist/config/env/index.js +2 -7
  12. package/dist/config/eslint/index.js +23 -19
  13. package/dist/config/eslint/index.js.map +1 -1
  14. package/dist/config/graphql-codegen/graphql-codegen.util.js +30 -38
  15. package/dist/config/graphql-codegen/graphql-codegen.util.js.map +1 -1
  16. package/dist/config/graphql-codegen/index.js +2 -5
  17. package/dist/config/index.js +3 -7
  18. package/dist/config/lint-staged/index.js +8 -7
  19. package/dist/config/lint-staged/index.js.map +1 -1
  20. package/dist/config/storybook/index.js +2 -6
  21. package/dist/config/storybook/storybook.main.js +19 -18
  22. package/dist/config/storybook/storybook.main.js.map +1 -1
  23. package/dist/config/storybook/storybook.preview.js +31 -37
  24. package/dist/config/storybook/storybook.preview.js.map +1 -1
  25. package/dist/config/vitest/index.js +3 -7
  26. package/dist/config/vitest/vitest.e2e.js +14 -17
  27. package/dist/config/vitest/vitest.e2e.js.map +1 -1
  28. package/dist/config/vitest/vitest.unit.js +31 -32
  29. package/dist/config/vitest/vitest.unit.js.map +1 -1
  30. package/dist/constant/common.js +6 -5
  31. package/dist/constant/common.js.map +1 -1
  32. package/dist/constant/index.js +3 -7
  33. package/dist/constant/response-status.d.ts +186 -186
  34. package/dist/constant/response-status.js +254 -253
  35. package/dist/constant/response-status.js.map +1 -1
  36. package/dist/node/apollo-server/apollo-server.util.js +27 -29
  37. package/dist/node/apollo-server/apollo-server.util.js.map +1 -1
  38. package/dist/node/apollo-server/index.js +2 -7
  39. package/dist/node/cli/index.js +112 -113
  40. package/dist/node/cli/index.js.map +1 -1
  41. package/dist/node/command/command.type.js +8 -5
  42. package/dist/node/command/command.type.js.map +1 -1
  43. package/dist/node/command/command.util.js +136 -149
  44. package/dist/node/command/command.util.js.map +1 -1
  45. package/dist/node/command/index.js +3 -12
  46. package/dist/node/express/express.type.d.ts +11 -0
  47. package/dist/node/express/express.type.js +2 -0
  48. package/dist/node/express/express.util.js +74 -65
  49. package/dist/node/express/express.util.js.map +1 -1
  50. package/dist/node/express/index.js +3 -14
  51. package/dist/node/fs/fs.util.js +27 -51
  52. package/dist/node/fs/fs.util.js.map +1 -1
  53. package/dist/node/fs/index.js +2 -19
  54. package/dist/node/log/index.js +2 -8
  55. package/dist/node/log/log.type.js +8 -5
  56. package/dist/node/log/log.type.js.map +1 -1
  57. package/dist/node/log/log.util.js +51 -68
  58. package/dist/node/log/log.util.js.map +1 -1
  59. package/dist/node/mongo/index.js +8 -26
  60. package/dist/node/mongo/mongo.constant.js +6 -6
  61. package/dist/node/mongo/mongo.constant.js.map +1 -1
  62. package/dist/node/mongo/mongo.controller.mongoose.d.ts +6 -1
  63. package/dist/node/mongo/mongo.controller.mongoose.js +333 -467
  64. package/dist/node/mongo/mongo.controller.mongoose.js.map +1 -1
  65. package/dist/node/mongo/mongo.controller.native.js +153 -212
  66. package/dist/node/mongo/mongo.controller.native.js.map +1 -1
  67. package/dist/node/mongo/mongo.dynamic-populate.js +164 -192
  68. package/dist/node/mongo/mongo.dynamic-populate.js.map +1 -1
  69. package/dist/node/mongo/mongo.populate.js +229 -262
  70. package/dist/node/mongo/mongo.populate.js.map +1 -1
  71. package/dist/node/mongo/mongo.type.js +8 -17
  72. package/dist/node/mongo/mongo.type.js.map +1 -1
  73. package/dist/node/mongo/mongo.util.js +134 -293
  74. package/dist/node/mongo/mongo.util.js.map +1 -1
  75. package/dist/node/package/index.js +3 -11
  76. package/dist/node/package/package.type.js +8 -5
  77. package/dist/node/package/package.type.js.map +1 -1
  78. package/dist/node/package/package.util.js +216 -225
  79. package/dist/node/package/package.util.js.map +1 -1
  80. package/dist/node/path/index.js +3 -58
  81. package/dist/node/path/path.constant.js +211 -298
  82. package/dist/node/path/path.constant.js.map +1 -1
  83. package/dist/node/path/path.util.js +13 -16
  84. package/dist/node/path/path.util.js.map +1 -1
  85. package/dist/node/storage/index.js +3 -10
  86. package/dist/node/storage/storage.constant.js +6 -8
  87. package/dist/node/storage/storage.constant.js.map +1 -1
  88. package/dist/node/storage/storage.util.js +127 -178
  89. package/dist/node/storage/storage.util.js.map +1 -1
  90. package/dist/node/upload/index.js +4 -16
  91. package/dist/node/upload/upload.constant.js +58 -32
  92. package/dist/node/upload/upload.constant.js.map +1 -1
  93. package/dist/node/upload/upload.type.js +8 -5
  94. package/dist/node/upload/upload.type.js.map +1 -1
  95. package/dist/node/upload/upload.util.js +125 -137
  96. package/dist/node/upload/upload.util.js.map +1 -1
  97. package/dist/node/ws/index.js +2 -6
  98. package/dist/node/ws/ws.type.d.ts +7 -8
  99. package/dist/node/ws/ws.util.js +46 -44
  100. package/dist/node/ws/ws.util.js.map +1 -1
  101. package/dist/node_modules/.pnpm/vitest@4.1.0_@types_node@25.5.0_jsdom@29.0.0_@noble_hashes@1.8.0__vite@8.0.0_@types_nod_53aa4254f295b3c40bb8f17b6ab226b5/node_modules/vitest/dist/config.js +8 -0
  102. package/dist/node_modules/.pnpm/vitest@4.1.0_@types_node@25.5.0_jsdom@29.0.0_@noble_hashes@1.8.0__vite@8.0.0_@types_nod_53aa4254f295b3c40bb8f17b6ab226b5/node_modules/vitest/dist/config.js.map +1 -0
  103. package/dist/react/apollo-client/apollo-client.component.js +16 -18
  104. package/dist/react/apollo-client/apollo-client.component.js.map +1 -1
  105. package/dist/react/apollo-client/apollo-client.constant.js +6 -5
  106. package/dist/react/apollo-client/apollo-client.constant.js.map +1 -1
  107. package/dist/react/apollo-client/apollo-client.context.js +10 -13
  108. package/dist/react/apollo-client/apollo-client.context.js.map +1 -1
  109. package/dist/react/apollo-client/apollo-client.module.scss.js +8 -7
  110. package/dist/react/apollo-client/apollo-client.module.scss.js.map +1 -1
  111. package/dist/react/apollo-client/apollo-client.util.js +57 -75
  112. package/dist/react/apollo-client/apollo-client.util.js.map +1 -1
  113. package/dist/react/apollo-client/index.js +7 -30
  114. package/dist/react/apollo-client/links/index.js +2 -5
  115. package/dist/react/apollo-client/links/upload.js +63 -107
  116. package/dist/react/apollo-client/links/upload.js.map +1 -1
  117. package/dist/react/apollo-client-nextjs/apollo-client-nextjs.component.js +14 -16
  118. package/dist/react/apollo-client-nextjs/apollo-client-nextjs.component.js.map +1 -1
  119. package/dist/react/apollo-client-nextjs/apollo-client-nextjs.rsc.js +8 -7
  120. package/dist/react/apollo-client-nextjs/apollo-client-nextjs.rsc.js.map +1 -1
  121. package/dist/react/apollo-client-nextjs/apollo-client-nextjs.util.js +14 -14
  122. package/dist/react/apollo-client-nextjs/apollo-client-nextjs.util.js.map +1 -1
  123. package/dist/react/apollo-client-nextjs/index.js +3 -7
  124. package/dist/react/apollo-error/apollo-error.component.js +57 -69
  125. package/dist/react/apollo-error/apollo-error.component.js.map +1 -1
  126. package/dist/react/apollo-error/apollo-error.context.js +7 -6
  127. package/dist/react/apollo-error/apollo-error.context.js.map +1 -1
  128. package/dist/react/apollo-error/apollo-error.hook.js +10 -10
  129. package/dist/react/apollo-error/apollo-error.hook.js.map +1 -1
  130. package/dist/react/apollo-error/apollo-error.module.scss.js +15 -11
  131. package/dist/react/apollo-error/apollo-error.module.scss.js.map +1 -1
  132. package/dist/react/apollo-error/apollo-error.provider.js +31 -25
  133. package/dist/react/apollo-error/apollo-error.provider.js.map +1 -1
  134. package/dist/react/apollo-error/apollo-error.util.js +14 -16
  135. package/dist/react/apollo-error/apollo-error.util.js.map +1 -1
  136. package/dist/react/apollo-error/index.js +5 -15
  137. package/dist/react/i18next/i18next.hook.js +7 -6
  138. package/dist/react/i18next/i18next.hook.js.map +1 -1
  139. package/dist/react/i18next/i18next.util.js +9 -8
  140. package/dist/react/i18next/i18next.util.js.map +1 -1
  141. package/dist/react/i18next/index.js +3 -7
  142. package/dist/react/loading/index.js +3 -9
  143. package/dist/react/loading/loading.component.js +47 -48
  144. package/dist/react/loading/loading.component.js.map +1 -1
  145. package/dist/react/loading/loading.context.js +7 -6
  146. package/dist/react/loading/loading.context.js.map +1 -1
  147. package/dist/react/loading/loading.hook.js +11 -11
  148. package/dist/react/loading/loading.hook.js.map +1 -1
  149. package/dist/react/loading/loading.module.scss.js +18 -15
  150. package/dist/react/loading/loading.module.scss.js.map +1 -1
  151. package/dist/react/loading/loading.provider.js +26 -18
  152. package/dist/react/loading/loading.provider.js.map +1 -1
  153. package/dist/react/log/index.js +2 -6
  154. package/dist/react/log/log.util.d.ts +8 -0
  155. package/dist/react/log/log.util.js +33 -29
  156. package/dist/react/log/log.util.js.map +1 -1
  157. package/dist/react/next-intl/index.js +6 -14
  158. package/dist/react/next-intl/next-intl.constant.js +16 -15
  159. package/dist/react/next-intl/next-intl.constant.js.map +1 -1
  160. package/dist/react/next-intl/next-intl.context.js +7 -6
  161. package/dist/react/next-intl/next-intl.context.js.map +1 -1
  162. package/dist/react/next-intl/next-intl.hoc.js +20 -23
  163. package/dist/react/next-intl/next-intl.hoc.js.map +1 -1
  164. package/dist/react/next-intl/next-intl.hook.js +13 -14
  165. package/dist/react/next-intl/next-intl.hook.js.map +1 -1
  166. package/dist/react/next-intl/next-intl.provider.js +28 -23
  167. package/dist/react/next-intl/next-intl.provider.js.map +1 -1
  168. package/dist/react/storage/index.js +3 -7
  169. package/dist/react/storage/storage.hook.js +61 -58
  170. package/dist/react/storage/storage.hook.js.map +1 -1
  171. package/dist/react/storage/storage.util.js +36 -68
  172. package/dist/react/storage/storage.util.js.map +1 -1
  173. package/dist/react/toast/index.js +2 -6
  174. package/dist/react/userback/index.js +2 -5
  175. package/dist/react/userback/userback.component.js +27 -27
  176. package/dist/react/userback/userback.component.js.map +1 -1
  177. package/dist/style.css +2 -1
  178. package/dist/typescript/common.type.js +8 -5
  179. package/dist/typescript/common.type.js.map +1 -1
  180. package/dist/typescript/index.js +2 -5
  181. package/dist/util/common/common.util.js +119 -48
  182. package/dist/util/common/common.util.js.map +1 -1
  183. package/dist/util/common/index.js +2 -9
  184. package/dist/util/index.js +6 -27
  185. package/dist/util/object/index.d.ts +3 -0
  186. package/dist/util/object/index.js +2 -10
  187. package/dist/util/object/object.util.js +94 -128
  188. package/dist/util/object/object.util.js.map +1 -1
  189. package/dist/util/serializer/index.js +2 -5
  190. package/dist/util/serializer/serializer.util.js +73 -78
  191. package/dist/util/serializer/serializer.util.js.map +1 -1
  192. package/dist/util/string/index.d.ts +3 -0
  193. package/dist/util/string/index.js +2 -10
  194. package/dist/util/string/string.util.js +59 -71
  195. package/dist/util/string/string.util.js.map +1 -1
  196. package/dist/util/validate/index.d.ts +3 -0
  197. package/dist/util/validate/index.js +2 -5
  198. package/dist/util/validate/validate.util.js +13 -39
  199. package/dist/util/validate/validate.util.js.map +1 -1
  200. package/package.json +29 -27
  201. package/dist/config/env/index.js.map +0 -1
  202. package/dist/config/graphql-codegen/index.js.map +0 -1
  203. package/dist/config/index.js.map +0 -1
  204. package/dist/config/storybook/index.js.map +0 -1
  205. package/dist/config/vitest/index.js.map +0 -1
  206. package/dist/constant/index.js.map +0 -1
  207. package/dist/node/apollo-server/index.js.map +0 -1
  208. package/dist/node/command/index.js.map +0 -1
  209. package/dist/node/express/index.js.map +0 -1
  210. package/dist/node/fs/index.js.map +0 -1
  211. package/dist/node/log/index.js.map +0 -1
  212. package/dist/node/mongo/index.js.map +0 -1
  213. package/dist/node/package/index.js.map +0 -1
  214. package/dist/node/path/index.js.map +0 -1
  215. package/dist/node/storage/index.js.map +0 -1
  216. package/dist/node/upload/index.js.map +0 -1
  217. package/dist/node/ws/index.js.map +0 -1
  218. package/dist/node_modules/.pnpm/vitest@4.0.18_@types_node@25.3.5_jiti@2.6.1_jsdom@28.1.0_@noble_hashes@1.8.0__sass@1.97.3_tsx@4.21.0_yaml@2.8.2/node_modules/vitest/dist/config.js +0 -7
  219. package/dist/node_modules/.pnpm/vitest@4.0.18_@types_node@25.3.5_jiti@2.6.1_jsdom@28.1.0_@noble_hashes@1.8.0__sass@1.97.3_tsx@4.21.0_yaml@2.8.2/node_modules/vitest/dist/config.js.map +0 -1
  220. package/dist/react/apollo-client/index.js.map +0 -1
  221. package/dist/react/apollo-client/links/index.js.map +0 -1
  222. package/dist/react/apollo-client-nextjs/index.js.map +0 -1
  223. package/dist/react/apollo-error/index.js.map +0 -1
  224. package/dist/react/i18next/index.js.map +0 -1
  225. package/dist/react/loading/index.js.map +0 -1
  226. package/dist/react/log/index.js.map +0 -1
  227. package/dist/react/next-intl/index.js.map +0 -1
  228. package/dist/react/storage/index.js.map +0 -1
  229. package/dist/react/toast/index.js.map +0 -1
  230. package/dist/react/userback/index.js.map +0 -1
  231. package/dist/typescript/index.js.map +0 -1
  232. package/dist/util/common/index.js.map +0 -1
  233. package/dist/util/index.js.map +0 -1
  234. package/dist/util/object/index.js.map +0 -1
  235. package/dist/util/serializer/index.js.map +0 -1
  236. package/dist/util/string/index.js.map +0 -1
  237. package/dist/util/validate/index.js.map +0 -1
@@ -1,144 +1,132 @@
1
- import { Buffer as w } from "node:buffer";
2
- import { Transform as C } from "node:stream";
3
- import { ReadableStream as D } from "node:stream/web";
4
- import { DEFAULT_UPLOAD_CONFIG as y, BYTES_PER_MB as R } from "./upload.constant.js";
5
- import { E_UploadType as E } from "./upload.type.js";
6
- import { dirname as O } from "../path/path.util.js";
7
- import { pathExistsSync as x, mkdirSync as z, createWriteStream as v } from "../fs/fs.util.js";
8
- import { RESPONSE_STATUS as c } from "../../constant/response-status.js";
9
- async function A(i) {
10
- return new Promise((o, t) => {
11
- let e = 0;
12
- i.on("data", (n) => {
13
- e += n.length;
14
- }), i.on("end", () => o(e)), i.on("error", t);
15
- });
1
+ import { RESPONSE_STATUS as e } from "../../constant/response-status.js";
2
+ import { E_UploadType as t } from "./upload.type.js";
3
+ import { BYTES_PER_MB as n, DEFAULT_UPLOAD_CONFIG as r } from "./upload.constant.js";
4
+ import { createWriteStream as i, mkdirSync as a, pathExistsSync as o } from "../fs/fs.util.js";
5
+ import { dirname as s } from "../path/path.util.js";
6
+ import { Buffer as c } from "node:buffer";
7
+ import { Transform as l } from "node:stream";
8
+ import { ReadableStream as u } from "node:stream/web";
9
+ //#region src/node/upload/upload.util.ts
10
+ async function d(e) {
11
+ return new Promise((t, n) => {
12
+ let r = 0;
13
+ e.on("data", (e) => {
14
+ r += e.length;
15
+ }), e.on("end", () => t(r)), e.on("error", n);
16
+ });
16
17
  }
17
- async function S(i, o, t) {
18
- const e = await (await o).file, n = e.createReadStream(), s = await A(n), r = t ?? g(), a = T(
19
- { filename: e.filename, fileSize: s },
20
- r,
21
- i
22
- );
23
- return a.isValid ? {
24
- success: !0,
25
- result: e,
26
- message: "File validated successfully"
27
- } : {
28
- success: !1,
29
- message: a.error || "File validation failed",
30
- code: c.BAD_REQUEST.CODE
31
- };
18
+ async function f(t, n, r) {
19
+ let i = await (await n).file, a = await d(i.createReadStream()), o = r ?? g(), s = h({
20
+ filename: i.filename,
21
+ fileSize: a
22
+ }, o, t);
23
+ return s.isValid ? {
24
+ success: !0,
25
+ result: i,
26
+ message: "File validated successfully"
27
+ } : {
28
+ success: !1,
29
+ message: s.error || "File validation failed",
30
+ code: e.BAD_REQUEST.CODE
31
+ };
32
32
  }
33
- async function h(i, o, t) {
34
- const n = (t ?? g())[i], s = await S(i, o, t);
35
- if (!s.success)
36
- return s;
37
- const { createReadStream: r } = s.result;
38
- let a = n.sizeLimit;
39
- const f = new C({
40
- transform(l, d, p) {
41
- a -= l.length, a < 0 ? p(new Error(`File size exceeds limit of ${n.sizeLimit / R}MB`)) : p(null, l);
42
- }
43
- }), u = r().pipe(f);
44
- return {
45
- success: !0,
46
- result: new D({
47
- start(l) {
48
- u.on("data", (d) => {
49
- l.enqueue(typeof d == "string" ? w.from(d) : d);
50
- }), u.on("end", () => l.close()), u.on("error", (d) => l.error(d));
51
- }
52
- })
53
- };
33
+ async function p(e, t, r) {
34
+ let i = (r ?? g())[e], a = await f(e, t, r);
35
+ if (!a.success) return a;
36
+ let { createReadStream: o } = a.result, s = i.sizeLimit, d = new l({ transform(e, t, r) {
37
+ s -= e.length, s < 0 ? r(/* @__PURE__ */ Error(`File size exceeds limit of ${i.sizeLimit / n}MB`)) : r(null, e);
38
+ } }), p = o().pipe(d);
39
+ return {
40
+ success: !0,
41
+ result: new u({ start(e) {
42
+ p.on("data", (t) => {
43
+ e.enqueue(typeof t == "string" ? c.from(t) : t);
44
+ }), p.on("end", () => e.close()), p.on("error", (t) => e.error(t));
45
+ } })
46
+ };
54
47
  }
55
- function F(i, o) {
56
- const t = i.lastIndexOf(".");
57
- if (t === -1)
58
- return !1;
59
- const e = i.substring(t + 1).toLowerCase();
60
- return o.includes(e);
48
+ function m(e, t) {
49
+ let n = e.lastIndexOf(".");
50
+ if (n === -1) return !1;
51
+ let r = e.substring(n + 1).toLowerCase();
52
+ return t.includes(r);
61
53
  }
62
- function T(i, o, t) {
63
- const { filename: e, fileSize: n } = i, s = o[t], { allowedExtensions: r, sizeLimit: a } = s;
64
- if (!F(e, r))
65
- return {
66
- isValid: !1,
67
- error: `File extension not allowed for ${t.toLowerCase()} files. Allowed extensions: ${r.join(", ")}`
68
- };
69
- if (n !== void 0 && n > a) {
70
- const f = Math.round(a / 1048576);
71
- return {
72
- isValid: !1,
73
- error: `File size exceeds limit for ${t.toLowerCase()} files. Maximum size: ${f}MB`
74
- };
75
- }
76
- return { isValid: !0 };
54
+ function h(e, t, n) {
55
+ let { filename: r, fileSize: i } = e, { allowedExtensions: a, sizeLimit: o } = t[n];
56
+ if (!m(r, a)) return {
57
+ isValid: !1,
58
+ error: `File extension not allowed for ${n.toLowerCase()} files. Allowed extensions: ${a.join(", ")}`
59
+ };
60
+ if (i !== void 0 && i > o) {
61
+ let e = Math.round(o / (1024 * 1024));
62
+ return {
63
+ isValid: !1,
64
+ error: `File size exceeds limit for ${n.toLowerCase()} files. Maximum size: ${e}MB`
65
+ };
66
+ }
67
+ return { isValid: !0 };
77
68
  }
78
- function g(i) {
79
- return { ...y, ...i };
69
+ function g(e) {
70
+ return {
71
+ ...r,
72
+ ...e
73
+ };
80
74
  }
81
- async function N(i) {
82
- const { path: o, file: t, config: e, type: n } = i;
83
- if (!o || typeof o != "string")
84
- return {
85
- success: !1,
86
- message: "Invalid path provided",
87
- code: c.BAD_REQUEST.CODE
88
- };
89
- if (!t || typeof t != "object")
90
- return {
91
- success: !1,
92
- message: "Invalid file provided",
93
- code: c.BAD_REQUEST.CODE
94
- };
95
- if (e) {
96
- const s = [E.IMAGE, E.VIDEO, E.DOCUMENT, E.OTHER];
97
- for (const r of s) {
98
- if (!e[r] || !Array.isArray(e[r].allowedExtensions) || e[r].allowedExtensions.length === 0)
99
- return {
100
- success: !1,
101
- message: `Invalid config for ${r.toLowerCase()} files`,
102
- code: c.BAD_REQUEST.CODE
103
- };
104
- if (typeof e[r].sizeLimit != "number" || e[r].sizeLimit <= 0)
105
- return {
106
- success: !1,
107
- message: `Invalid size limit for ${r.toLowerCase()} files`,
108
- code: c.BAD_REQUEST.CODE
109
- };
110
- }
111
- }
112
- try {
113
- const s = await S(n, await t, e);
114
- if (!s.success)
115
- return s;
116
- const { createReadStream: r } = s.result, a = O(o);
117
- x(a) || z(a, { recursive: !0 });
118
- const f = r(), m = v(o);
119
- return f.pipe(m), await new Promise((u, l) => {
120
- m.on("finish", () => u()), m.on("error", l), f.on("error", l);
121
- }), {
122
- success: !0,
123
- result: o,
124
- message: "File uploaded successfully",
125
- code: c.OK.CODE
126
- };
127
- } catch (s) {
128
- return {
129
- success: !1,
130
- message: s instanceof Error ? s.message : "File upload failed",
131
- code: c.INTERNAL_SERVER_ERROR.CODE
132
- };
133
- }
75
+ async function _(n) {
76
+ let { path: r, file: c, config: l, type: u } = n;
77
+ if (!r || typeof r != "string") return {
78
+ success: !1,
79
+ message: "Invalid path provided",
80
+ code: e.BAD_REQUEST.CODE
81
+ };
82
+ if (!c || typeof c != "object") return {
83
+ success: !1,
84
+ message: "Invalid file provided",
85
+ code: e.BAD_REQUEST.CODE
86
+ };
87
+ if (l) {
88
+ let n = [
89
+ t.IMAGE,
90
+ t.VIDEO,
91
+ t.DOCUMENT,
92
+ t.OTHER
93
+ ];
94
+ for (let t of n) {
95
+ if (!l[t] || !Array.isArray(l[t].allowedExtensions) || l[t].allowedExtensions.length === 0) return {
96
+ success: !1,
97
+ message: `Invalid config for ${t.toLowerCase()} files`,
98
+ code: e.BAD_REQUEST.CODE
99
+ };
100
+ if (typeof l[t].sizeLimit != "number" || l[t].sizeLimit <= 0) return {
101
+ success: !1,
102
+ message: `Invalid size limit for ${t.toLowerCase()} files`,
103
+ code: e.BAD_REQUEST.CODE
104
+ };
105
+ }
106
+ }
107
+ try {
108
+ let t = await f(u, await c, l);
109
+ if (!t.success) return t;
110
+ let { createReadStream: n } = t.result, d = s(r);
111
+ o(d) || a(d, { recursive: !0 });
112
+ let p = n(), m = i(r);
113
+ return p.pipe(m), await new Promise((e, t) => {
114
+ m.on("finish", () => e()), m.on("error", t), p.on("error", t);
115
+ }), {
116
+ success: !0,
117
+ result: r,
118
+ message: "File uploaded successfully",
119
+ code: e.OK.CODE
120
+ };
121
+ } catch (t) {
122
+ return {
123
+ success: !1,
124
+ message: t instanceof Error ? t.message : "File upload failed",
125
+ code: e.INTERNAL_SERVER_ERROR.CODE
126
+ };
127
+ }
134
128
  }
135
- export {
136
- g as createUploadConfig,
137
- S as getAndValidateFile,
138
- A as getFileSizeFromStream,
139
- h as getFileWebStream,
140
- N as upload,
141
- F as validateFileExtension,
142
- T as validateUpload
143
- };
144
- //# sourceMappingURL=upload.util.js.map
129
+ //#endregion
130
+ export { g as createUploadConfig, f as getAndValidateFile, d as getFileSizeFromStream, p as getFileWebStream, _ as upload, m as validateFileExtension, h as validateUpload };
131
+
132
+ //# sourceMappingURL=upload.util.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"upload.util.js","sources":["../../../src/node/upload/upload.util.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\nimport { Transform } from 'node:stream';\nimport { ReadableStream } from 'node:stream/web';\n\nimport type { I_Return } from '#typescript/index.js';\n\nimport { RESPONSE_STATUS } from '#constant/index.js';\n\nimport type { I_UploadConfig, I_UploadFile, I_UploadFileData, I_UploadOptions, I_UploadTypeConfig, I_UploadValidationConfig } from './upload.type.js';\n\nimport { createWriteStream, mkdirSync, pathExistsSync } from '../fs/index.js';\nimport { dirname } from '../path/index.js';\nimport { BYTES_PER_MB, DEFAULT_UPLOAD_CONFIG } from './upload.constant.js';\nimport { E_UploadType } from './upload.type.js';\n\n/**\n * Calculates the size of a file from a readable stream.\n * This function reads through the entire stream to determine the total byte size\n * by accumulating the length of each data chunk.\n *\n * @param stream - The readable stream to calculate the size for.\n * @returns A promise that resolves to the total size of the stream in bytes.\n */\nexport async function getFileSizeFromStream(stream: NodeJS.ReadableStream): Promise<number> {\n return new Promise((resolve, reject) => {\n let size = 0;\n stream.on('data', (chunk) => {\n size += chunk.length;\n });\n stream.on('end', () => resolve(size));\n stream.on('error', reject);\n });\n}\n\n/**\n * Extracts and validates file data from an upload file.\n * This function processes upload files by:\n * - Extracting file metadata and creating a readable stream\n * - Calculating the file size from the stream\n * - Validating file size and extension against upload configuration\n * - Returning a standardized response with success status and error codes\n * - Providing validated file data for further processing\n *\n * @param type - The type of upload being processed (IMAGE, VIDEO, DOCUMENT, OTHER).\n * @param file - The upload file object containing file metadata and stream creation method.\n * @param config - Optional upload configuration. If not provided, uses default configuration.\n * @returns A promise that resolves to a standardized response containing validated file data or error information.\n */\nexport async function getAndValidateFile(type: E_UploadType, file: I_UploadFile, config?: I_UploadConfig): Promise<I_Return<I_UploadFileData>> {\n const fileData = await (await file).file;\n const stream = fileData.createReadStream();\n const fileSize = await getFileSizeFromStream(stream);\n const uploadConfig = config ?? createUploadConfig();\n\n const validationResult = validateUpload(\n { filename: fileData.filename, fileSize },\n uploadConfig,\n type,\n );\n\n if (!validationResult.isValid) {\n return {\n success: false,\n message: validationResult.error || 'File validation failed',\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n\n return {\n success: true,\n result: fileData,\n message: 'File validated successfully',\n };\n}\n\n/**\n * Creates a validated web-readable stream from an upload file with size validation.\n * This function processes file uploads for web environments by:\n * - Validating file data using getAndValidateFile function\n * - Creating a size validation transform stream to monitor upload progress\n * - Returning a web-compatible ReadableStream with real-time validation\n * - Providing standardized error responses for validation failures\n * - Wrapping the stream in a standardized response format\n *\n * @param type - The type of upload being processed (IMAGE, VIDEO, DOCUMENT, OTHER).\n * @param file - The upload file object containing file metadata and stream creation method.\n * @param config - Optional upload configuration. If not provided, uses default configuration.\n * @returns A promise that resolves to a standardized response containing either a web ReadableStream or error information.\n */\nexport async function getFileWebStream(type: E_UploadType, file: I_UploadFile, config?: I_UploadConfig): Promise<I_Return<ReadableStream<Uint8Array>>> {\n const uploadConfig = config ?? createUploadConfig();\n const typeConfig = uploadConfig[type];\n\n const fileData = await getAndValidateFile(type, file, config);\n\n if (!fileData.success) {\n return fileData;\n }\n\n const { createReadStream } = fileData.result;\n\n let remainingBytes = typeConfig.sizeLimit;\n\n const sizeValidationStream = new Transform({\n transform(chunk: Buffer, _enc: BufferEncoding, cb) {\n remainingBytes -= chunk.length;\n\n if (remainingBytes < 0) {\n cb(new Error(`File size exceeds limit of ${typeConfig.sizeLimit / BYTES_PER_MB}MB`));\n }\n else {\n cb(null, chunk);\n }\n },\n });\n const originalStream = createReadStream();\n const validatedStream = originalStream.pipe(sizeValidationStream);\n\n return {\n success: true,\n result: new ReadableStream<Uint8Array>({\n start(controller) {\n validatedStream.on('data', (chunk: Buffer | string) => {\n controller.enqueue(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);\n });\n validatedStream.on('end', () => controller.close());\n validatedStream.on('error', (err: unknown) => controller.error(err));\n },\n }),\n };\n}\n\n/**\n * Validates if a file has an allowed extension.\n * This function extracts the file extension from the filename and checks if it's\n * included in the list of allowed extensions (case-insensitive comparison).\n *\n * @param filename - The filename to check for valid extension.\n * @param allowedExtensions - An array of allowed file extensions (without dots).\n * @returns True if the file extension is allowed, false otherwise.\n */\nexport function validateFileExtension(filename: string, allowedExtensions: string[]): boolean {\n const lastDotIndex = filename.lastIndexOf('.');\n\n if (lastDotIndex === -1) {\n return false;\n }\n\n const extension = filename.substring(lastDotIndex + 1).toLowerCase();\n\n return allowedExtensions.includes(extension);\n}\n\n/**\n * Validates an upload against the specified configuration.\n * This function performs comprehensive validation including:\n * - File extension validation against allowed extensions\n * - File size validation against size limits\n * - Returns detailed error messages for validation failures\n *\n * @param config - The validation configuration including filename and optional file size.\n * @param uploadConfig - The upload configuration containing allowed extensions and size limits.\n * @param uploadType - The type of upload being validated.\n * @returns An object indicating validation success and optional error message.\n */\nexport function validateUpload(\n config: I_UploadValidationConfig,\n uploadConfig: I_UploadConfig,\n uploadType: E_UploadType,\n): { isValid: boolean; error?: string } {\n const { filename, fileSize } = config;\n const typeConfig: I_UploadTypeConfig = uploadConfig[uploadType];\n\n const { allowedExtensions, sizeLimit } = typeConfig;\n\n if (!validateFileExtension(filename, allowedExtensions)) {\n return {\n isValid: false,\n error: `File extension not allowed for ${uploadType.toLowerCase()} files. Allowed extensions: ${allowedExtensions.join(', ')}`,\n };\n }\n\n if (fileSize !== undefined && fileSize > sizeLimit) {\n const maxSizeMB = Math.round(sizeLimit / (1024 * 1024));\n\n return {\n isValid: false,\n error: `File size exceeds limit for ${uploadType.toLowerCase()} files. Maximum size: ${maxSizeMB}MB`,\n };\n }\n\n return { isValid: true };\n}\n\n/**\n * Creates a default upload configuration with predefined settings for different file types.\n * This function provides sensible defaults for image, video, document, and other file types,\n * including allowed extensions and size limits. The configuration can be customized with overrides.\n *\n * @param overrides - Optional configuration overrides to merge with the default configuration.\n * @returns A complete upload configuration object with defaults and any provided overrides.\n */\nexport function createUploadConfig(overrides?: Partial<I_UploadConfig>): I_UploadConfig {\n return { ...DEFAULT_UPLOAD_CONFIG, ...overrides };\n}\n\n/**\n * Uploads a file with comprehensive validation and error handling.\n * This function processes file uploads with the following features:\n * - Input validation for path and file parameters\n * - Configuration validation for all upload types\n * - File validation using getAndValidateFile function\n * - Automatic directory creation\n * - Stream-based file writing\n * - Comprehensive error handling with standardized response codes\n *\n * @param options - Upload configuration including file, path, type, and optional validation config.\n * @returns A promise that resolves to a standardized response with success status, message, file path, and response codes.\n */\nexport async function upload(options: I_UploadOptions): Promise<I_Return<string>> {\n const { path, file, config, type } = options;\n\n if (!path || typeof path !== 'string') {\n return {\n success: false,\n message: 'Invalid path provided',\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n\n if (!file || typeof file !== 'object') {\n return {\n success: false,\n message: 'Invalid file provided',\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n\n if (config) {\n const requiredTypes = [E_UploadType.IMAGE, E_UploadType.VIDEO, E_UploadType.DOCUMENT, E_UploadType.OTHER];\n\n for (const requiredType of requiredTypes) {\n if (!config[requiredType] || !Array.isArray(config[requiredType].allowedExtensions) || config[requiredType].allowedExtensions.length === 0) {\n return {\n success: false,\n message: `Invalid config for ${requiredType.toLowerCase()} files`,\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n if (typeof config[requiredType].sizeLimit !== 'number' || config[requiredType].sizeLimit <= 0) {\n return {\n success: false,\n message: `Invalid size limit for ${requiredType.toLowerCase()} files`,\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n }\n }\n\n try {\n const fileData = await getAndValidateFile(type, await file, config);\n\n if (!fileData.success) {\n return fileData;\n }\n\n const { createReadStream } = fileData.result;\n\n const dir = dirname(path);\n\n if (!pathExistsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const writeStream = createReadStream();\n const out = createWriteStream(path);\n writeStream.pipe(out);\n\n await new Promise<void>((resolve, reject) => {\n out.on('finish', () => resolve());\n out.on('error', reject);\n writeStream.on('error', reject);\n });\n\n return {\n success: true,\n result: path,\n message: 'File uploaded successfully',\n code: RESPONSE_STATUS.OK.CODE,\n };\n }\n catch (error) {\n return {\n success: false,\n message: error instanceof Error ? error.message : 'File upload failed',\n code: RESPONSE_STATUS.INTERNAL_SERVER_ERROR.CODE,\n };\n }\n}\n"],"names":["getFileSizeFromStream","stream","resolve","reject","size","chunk","getAndValidateFile","type","file","config","fileData","fileSize","uploadConfig","createUploadConfig","validationResult","validateUpload","RESPONSE_STATUS","getFileWebStream","typeConfig","createReadStream","remainingBytes","sizeValidationStream","Transform","_enc","cb","BYTES_PER_MB","validatedStream","ReadableStream","controller","Buffer","err","validateFileExtension","filename","allowedExtensions","lastDotIndex","extension","uploadType","sizeLimit","maxSizeMB","overrides","DEFAULT_UPLOAD_CONFIG","upload","options","path","requiredTypes","E_UploadType","requiredType","dir","dirname","pathExistsSync","mkdirSync","writeStream","out","createWriteStream","error"],"mappings":"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"}
1
+ {"version":3,"file":"upload.util.js","names":[],"sources":["../../../src/node/upload/upload.util.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\nimport { Transform } from 'node:stream';\nimport { ReadableStream } from 'node:stream/web';\n\nimport type { I_Return } from '#typescript/index.js';\n\nimport { RESPONSE_STATUS } from '#constant/index.js';\n\nimport type { I_UploadConfig, I_UploadFile, I_UploadFileData, I_UploadOptions, I_UploadTypeConfig, I_UploadValidationConfig } from './upload.type.js';\n\nimport { createWriteStream, mkdirSync, pathExistsSync } from '../fs/index.js';\nimport { dirname } from '../path/index.js';\nimport { BYTES_PER_MB, DEFAULT_UPLOAD_CONFIG } from './upload.constant.js';\nimport { E_UploadType } from './upload.type.js';\n\n/**\n * Calculates the size of a file from a readable stream.\n * This function reads through the entire stream to determine the total byte size\n * by accumulating the length of each data chunk.\n *\n * @param stream - The readable stream to calculate the size for.\n * @returns A promise that resolves to the total size of the stream in bytes.\n */\nexport async function getFileSizeFromStream(stream: NodeJS.ReadableStream): Promise<number> {\n return new Promise((resolve, reject) => {\n let size = 0;\n stream.on('data', (chunk) => {\n size += chunk.length;\n });\n stream.on('end', () => resolve(size));\n stream.on('error', reject);\n });\n}\n\n/**\n * Extracts and validates file data from an upload file.\n * This function processes upload files by:\n * - Extracting file metadata and creating a readable stream\n * - Calculating the file size from the stream\n * - Validating file size and extension against upload configuration\n * - Returning a standardized response with success status and error codes\n * - Providing validated file data for further processing\n *\n * @param type - The type of upload being processed (IMAGE, VIDEO, DOCUMENT, OTHER).\n * @param file - The upload file object containing file metadata and stream creation method.\n * @param config - Optional upload configuration. If not provided, uses default configuration.\n * @returns A promise that resolves to a standardized response containing validated file data or error information.\n */\nexport async function getAndValidateFile(type: E_UploadType, file: I_UploadFile, config?: I_UploadConfig): Promise<I_Return<I_UploadFileData>> {\n const fileData = await (await file).file;\n const stream = fileData.createReadStream();\n // Stream is consumed here for validation; callers use createReadStream() again for the actual write.\n // This is intentional — createReadStream() is a factory that yields a new stream per call.\n const fileSize = await getFileSizeFromStream(stream);\n const uploadConfig = config ?? createUploadConfig();\n\n const validationResult = validateUpload(\n { filename: fileData.filename, fileSize },\n uploadConfig,\n type,\n );\n\n if (!validationResult.isValid) {\n return {\n success: false,\n message: validationResult.error || 'File validation failed',\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n\n return {\n success: true,\n result: fileData,\n message: 'File validated successfully',\n };\n}\n\n/**\n * Creates a validated web-readable stream from an upload file with size validation.\n * This function processes file uploads for web environments by:\n * - Validating file data using getAndValidateFile function\n * - Creating a size validation transform stream to monitor upload progress\n * - Returning a web-compatible ReadableStream with real-time validation\n * - Providing standardized error responses for validation failures\n * - Wrapping the stream in a standardized response format\n *\n * @param type - The type of upload being processed (IMAGE, VIDEO, DOCUMENT, OTHER).\n * @param file - The upload file object containing file metadata and stream creation method.\n * @param config - Optional upload configuration. If not provided, uses default configuration.\n * @returns A promise that resolves to a standardized response containing either a web ReadableStream or error information.\n */\nexport async function getFileWebStream(type: E_UploadType, file: I_UploadFile, config?: I_UploadConfig): Promise<I_Return<ReadableStream<Uint8Array>>> {\n const uploadConfig = config ?? createUploadConfig();\n const typeConfig = uploadConfig[type];\n\n const fileData = await getAndValidateFile(type, file, config);\n\n if (!fileData.success) {\n return fileData;\n }\n\n const { createReadStream } = fileData.result;\n\n let remainingBytes = typeConfig.sizeLimit;\n\n const sizeValidationStream = new Transform({\n transform(chunk: Buffer, _enc: BufferEncoding, cb) {\n remainingBytes -= chunk.length;\n\n if (remainingBytes < 0) {\n cb(new Error(`File size exceeds limit of ${typeConfig.sizeLimit / BYTES_PER_MB}MB`));\n }\n else {\n cb(null, chunk);\n }\n },\n });\n const originalStream = createReadStream();\n const validatedStream = originalStream.pipe(sizeValidationStream);\n\n return {\n success: true,\n result: new ReadableStream<Uint8Array>({\n start(controller) {\n validatedStream.on('data', (chunk: Buffer | string) => {\n controller.enqueue(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);\n });\n validatedStream.on('end', () => controller.close());\n validatedStream.on('error', (err: unknown) => controller.error(err));\n },\n }),\n };\n}\n\n/**\n * Validates if a file has an allowed extension.\n * This function extracts the file extension from the filename and checks if it's\n * included in the list of allowed extensions (case-insensitive comparison).\n *\n * @param filename - The filename to check for valid extension.\n * @param allowedExtensions - An array of allowed file extensions (without dots).\n * @returns True if the file extension is allowed, false otherwise.\n */\nexport function validateFileExtension(filename: string, allowedExtensions: string[]): boolean {\n const lastDotIndex = filename.lastIndexOf('.');\n\n if (lastDotIndex === -1) {\n return false;\n }\n\n const extension = filename.substring(lastDotIndex + 1).toLowerCase();\n\n return allowedExtensions.includes(extension);\n}\n\n/**\n * Validates an upload against the specified configuration.\n * This function performs comprehensive validation including:\n * - File extension validation against allowed extensions\n * - File size validation against size limits\n * - Returns detailed error messages for validation failures\n *\n * @param config - The validation configuration including filename and optional file size.\n * @param uploadConfig - The upload configuration containing allowed extensions and size limits.\n * @param uploadType - The type of upload being validated.\n * @returns An object indicating validation success and optional error message.\n */\nexport function validateUpload(\n config: I_UploadValidationConfig,\n uploadConfig: I_UploadConfig,\n uploadType: E_UploadType,\n): { isValid: boolean; error?: string } {\n const { filename, fileSize } = config;\n const typeConfig: I_UploadTypeConfig = uploadConfig[uploadType];\n\n const { allowedExtensions, sizeLimit } = typeConfig;\n\n if (!validateFileExtension(filename, allowedExtensions)) {\n return {\n isValid: false,\n error: `File extension not allowed for ${uploadType.toLowerCase()} files. Allowed extensions: ${allowedExtensions.join(', ')}`,\n };\n }\n\n if (fileSize !== undefined && fileSize > sizeLimit) {\n const maxSizeMB = Math.round(sizeLimit / (1024 * 1024));\n\n return {\n isValid: false,\n error: `File size exceeds limit for ${uploadType.toLowerCase()} files. Maximum size: ${maxSizeMB}MB`,\n };\n }\n\n return { isValid: true };\n}\n\n/**\n * Creates a default upload configuration with predefined settings for different file types.\n * This function provides sensible defaults for image, video, document, and other file types,\n * including allowed extensions and size limits. The configuration can be customized with overrides.\n *\n * @param overrides - Optional configuration overrides to merge with the default configuration.\n * @returns A complete upload configuration object with defaults and any provided overrides.\n */\nexport function createUploadConfig(overrides?: Partial<I_UploadConfig>): I_UploadConfig {\n return { ...DEFAULT_UPLOAD_CONFIG, ...overrides };\n}\n\n/**\n * Uploads a file with comprehensive validation and error handling.\n * This function processes file uploads with the following features:\n * - Input validation for path and file parameters\n * - Configuration validation for all upload types\n * - File validation using getAndValidateFile function\n * - Automatic directory creation\n * - Stream-based file writing\n * - Comprehensive error handling with standardized response codes\n *\n * @param options - Upload configuration including file, path, type, and optional validation config.\n * @returns A promise that resolves to a standardized response with success status, message, file path, and response codes.\n */\nexport async function upload(options: I_UploadOptions): Promise<I_Return<string>> {\n const { path, file, config, type } = options;\n\n if (!path || typeof path !== 'string') {\n return {\n success: false,\n message: 'Invalid path provided',\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n\n if (!file || typeof file !== 'object') {\n return {\n success: false,\n message: 'Invalid file provided',\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n\n if (config) {\n const requiredTypes = [E_UploadType.IMAGE, E_UploadType.VIDEO, E_UploadType.DOCUMENT, E_UploadType.OTHER];\n\n for (const requiredType of requiredTypes) {\n if (!config[requiredType] || !Array.isArray(config[requiredType].allowedExtensions) || config[requiredType].allowedExtensions.length === 0) {\n return {\n success: false,\n message: `Invalid config for ${requiredType.toLowerCase()} files`,\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n if (typeof config[requiredType].sizeLimit !== 'number' || config[requiredType].sizeLimit <= 0) {\n return {\n success: false,\n message: `Invalid size limit for ${requiredType.toLowerCase()} files`,\n code: RESPONSE_STATUS.BAD_REQUEST.CODE,\n };\n }\n }\n }\n\n try {\n const fileData = await getAndValidateFile(type, await file, config);\n\n if (!fileData.success) {\n return fileData;\n }\n\n const { createReadStream } = fileData.result;\n\n const dir = dirname(path);\n\n if (!pathExistsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const writeStream = createReadStream();\n const out = createWriteStream(path);\n writeStream.pipe(out);\n\n await new Promise<void>((resolve, reject) => {\n out.on('finish', () => resolve());\n out.on('error', reject);\n writeStream.on('error', reject);\n });\n\n return {\n success: true,\n result: path,\n message: 'File uploaded successfully',\n code: RESPONSE_STATUS.OK.CODE,\n };\n }\n catch (error) {\n return {\n success: false,\n message: error instanceof Error ? error.message : 'File upload failed',\n code: RESPONSE_STATUS.INTERNAL_SERVER_ERROR.CODE,\n };\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,2 @@
1
- import { createWSServer as t, initGraphQLWS as S } from "./ws.util.js";
2
- export {
3
- t as createWSServer,
4
- S as initGraphQLWS
5
- };
6
- //# sourceMappingURL=index.js.map
1
+ import { createWSServer as e, initGraphQLWS as t } from "./ws.util.js";
2
+ export { e as createWSServer, t as initGraphQLWS };
@@ -2,6 +2,11 @@ import { RequestHandler } from 'express';
2
2
  import { GraphQLSchema } from 'graphql';
3
3
  import { IncomingMessage, Server } from 'node:http';
4
4
  import { WebSocketServer } from 'ws';
5
+ /** Extends `IncomingMessage` with optional session and user properties set by authentication middleware. */
6
+ export interface I_AuthenticatedRequest extends IncomingMessage {
7
+ session?: Record<string, unknown>;
8
+ user?: Record<string, unknown>;
9
+ }
5
10
  export interface I_WSOptions {
6
11
  server: Server;
7
12
  path: string;
@@ -10,12 +15,6 @@ export interface I_WSOptions {
10
15
  export interface I_GraphqlWSOptions {
11
16
  schema: GraphQLSchema;
12
17
  server: WebSocketServer;
13
- context?: (req: IncomingMessage & {
14
- session?: any;
15
- user?: any;
16
- }) => Promise<Record<string, any>> | Record<string, any>;
17
- onConnect?: (req: IncomingMessage & {
18
- session?: any;
19
- user?: any;
20
- }) => Promise<void> | void;
18
+ context?: (req: I_AuthenticatedRequest) => Promise<Record<string, unknown>> | Record<string, unknown>;
19
+ onConnect?: (req: I_AuthenticatedRequest) => Promise<void> | void;
21
20
  }
@@ -1,46 +1,48 @@
1
- import { useServer as p } from "graphql-ws/use/ws";
2
- import { WebSocketServer as u } from "ws";
3
- function f(c) {
4
- const { server: o, path: a, sessionParser: n } = c;
5
- if (n) {
6
- const r = new u({ noServer: !0 });
7
- return o.on("upgrade", (e, t, s) => {
8
- try {
9
- if (new URL(e.url || "", "http://localhost").pathname !== a)
10
- return;
11
- n(e, {}, () => {
12
- r.handleUpgrade(e, t, s, (i) => {
13
- r.emit("connection", i, e);
14
- });
15
- });
16
- } catch {
17
- t.destroy();
18
- }
19
- }), r;
20
- }
21
- return new u({ server: o, path: a });
1
+ import { useServer as e } from "graphql-ws/use/ws";
2
+ import { WebSocketServer as t } from "ws";
3
+ //#region src/node/ws/ws.util.ts
4
+ function n(e) {
5
+ let { server: n, path: r, sessionParser: i } = e;
6
+ if (i) {
7
+ let e = new t({ noServer: !0 });
8
+ return n.on("upgrade", (t, n, a) => {
9
+ try {
10
+ if (new URL(t.url || "", "http://localhost").pathname !== r) return;
11
+ i(t, {}, () => {
12
+ e.handleUpgrade(t, n, a, (n) => {
13
+ e.emit("connection", n, t);
14
+ });
15
+ });
16
+ } catch {
17
+ n.destroy();
18
+ }
19
+ }), e;
20
+ }
21
+ return new t({
22
+ server: n,
23
+ path: r
24
+ });
22
25
  }
23
- function S(c) {
24
- const { schema: o, server: a, context: n, onConnect: r } = c;
25
- return p(
26
- {
27
- schema: o,
28
- context: async (e) => {
29
- const t = e.extra.request, s = n ? await n(t) : {};
30
- return { req: t, ...s };
31
- },
32
- onConnect: async (e) => {
33
- if (r) {
34
- const t = e.extra.request;
35
- await r(t);
36
- }
37
- }
38
- },
39
- a
40
- );
26
+ function r(t) {
27
+ let { schema: n, server: r, context: i, onConnect: a } = t;
28
+ return e({
29
+ schema: n,
30
+ context: async (e) => {
31
+ let t = e.extra.request;
32
+ return {
33
+ req: t,
34
+ ...i ? await i(t) : {}
35
+ };
36
+ },
37
+ onConnect: async (e) => {
38
+ if (a) {
39
+ let t = e.extra.request;
40
+ await a(t);
41
+ }
42
+ }
43
+ }, r);
41
44
  }
42
- export {
43
- f as createWSServer,
44
- S as initGraphQLWS
45
- };
46
- //# sourceMappingURL=ws.util.js.map
45
+ //#endregion
46
+ export { n as createWSServer, r as initGraphQLWS };
47
+
48
+ //# sourceMappingURL=ws.util.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ws.util.js","sources":["../../../src/node/ws/ws.util.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport type { Buffer } from 'node:buffer';\nimport type { IncomingMessage } from 'node:http';\nimport type { Duplex } from 'node:stream';\n\nimport { useServer as createGraphQLWSServer } from 'graphql-ws/use/ws';\nimport { WebSocketServer } from 'ws';\n\nimport type { I_GraphqlWSOptions, I_WSOptions } from './ws.type.js';\n\n/**\n * Creates a WebSocket server with the specified configuration.\n * This function creates a WebSocket server instance that can be attached to an HTTP server\n * and configured with a specific path for WebSocket connections.\n *\n * @param options - Configuration options including the HTTP server instance and WebSocket path.\n * @returns A configured WebSocket server instance ready to handle connections.\n */\nexport function createWSServer(options: I_WSOptions): WebSocketServer {\n const { server, path, sessionParser } = options;\n\n if (sessionParser) {\n const wss = new WebSocketServer({ noServer: true });\n\n server.on('upgrade', (req: IncomingMessage, socket: Duplex, head: Buffer) => {\n try {\n const url = new URL(req.url || '', 'http://localhost');\n if (url.pathname !== path)\n return;\n\n sessionParser(req as Request, {} as Response, () => {\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit('connection', ws, req);\n });\n });\n }\n catch {\n socket.destroy();\n }\n });\n\n return wss;\n }\n\n return new WebSocketServer({ server, path });\n}\n\n/**\n * Initializes GraphQL WebSocket server with schema and WebSocket server.\n * This function sets up GraphQL subscriptions over WebSocket by creating a GraphQL WebSocket server\n * that can handle GraphQL operations including queries, mutations, and subscriptions.\n *\n * @param options - Configuration options including the GraphQL schema and WebSocket server instance.\n * @returns A configured GraphQL WebSocket server ready to handle GraphQL operations over WebSocket.\n */\nexport function initGraphQLWS(options: I_GraphqlWSOptions) {\n const { schema, server, context: makeExtraContext, onConnect } = options;\n\n return createGraphQLWSServer(\n {\n schema,\n context: async (ctx) => {\n const req = ctx.extra.request as IncomingMessage & { session?: any; user?: any };\n\n const extra = makeExtraContext ? await makeExtraContext(req) : {};\n return { req, ...extra };\n },\n onConnect: async (ctx) => {\n if (onConnect) {\n const req = ctx.extra.request as IncomingMessage & { session?: any; user?: any };\n await onConnect(req);\n }\n },\n },\n server,\n );\n}\n"],"names":["createWSServer","options","server","path","sessionParser","wss","WebSocketServer","req","socket","head","ws","initGraphQLWS","schema","makeExtraContext","onConnect","createGraphQLWSServer","ctx","extra"],"mappings":";;AAkBO,SAASA,EAAeC,GAAuC;AAClE,QAAM,EAAE,QAAAC,GAAQ,MAAAC,GAAM,eAAAC,EAAA,IAAkBH;AAExC,MAAIG,GAAe;AACf,UAAMC,IAAM,IAAIC,EAAgB,EAAE,UAAU,IAAM;AAElD,WAAAJ,EAAO,GAAG,WAAW,CAACK,GAAsBC,GAAgBC,MAAiB;AACzE,UAAI;AAEA,YADY,IAAI,IAAIF,EAAI,OAAO,IAAI,kBAAkB,EAC7C,aAAaJ;AACjB;AAEJ,QAAAC,EAAcG,GAAgB,CAAA,GAAgB,MAAM;AAChD,UAAAF,EAAI,cAAcE,GAAKC,GAAQC,GAAM,CAACC,MAAO;AACzC,YAAAL,EAAI,KAAK,cAAcK,GAAIH,CAAG;AAAA,UAClC,CAAC;AAAA,QACL,CAAC;AAAA,MACL,QACM;AACF,QAAAC,EAAO,QAAA;AAAA,MACX;AAAA,IACJ,CAAC,GAEMH;AAAA,EACX;AAEA,SAAO,IAAIC,EAAgB,EAAE,QAAAJ,GAAQ,MAAAC,GAAM;AAC/C;AAUO,SAASQ,EAAcV,GAA6B;AACvD,QAAM,EAAE,QAAAW,GAAQ,QAAAV,GAAQ,SAASW,GAAkB,WAAAC,MAAcb;AAEjE,SAAOc;AAAAA,IACH;AAAA,MACI,QAAAH;AAAA,MACA,SAAS,OAAOI,MAAQ;AACpB,cAAMT,IAAMS,EAAI,MAAM,SAEhBC,IAAQJ,IAAmB,MAAMA,EAAiBN,CAAG,IAAI,CAAA;AAC/D,eAAO,EAAE,KAAAA,GAAK,GAAGU,EAAA;AAAA,MACrB;AAAA,MACA,WAAW,OAAOD,MAAQ;AACtB,YAAIF,GAAW;AACX,gBAAMP,IAAMS,EAAI,MAAM;AACtB,gBAAMF,EAAUP,CAAG;AAAA,QACvB;AAAA,MACJ;AAAA,IAAA;AAAA,IAEJL;AAAA,EAAA;AAER;"}
1
+ {"version":3,"file":"ws.util.js","names":[],"sources":["../../../src/node/ws/ws.util.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport type { Buffer } from 'node:buffer';\nimport type { IncomingMessage } from 'node:http';\nimport type { Duplex } from 'node:stream';\n\nimport { useServer as createGraphQLWSServer } from 'graphql-ws/use/ws';\nimport { WebSocketServer } from 'ws';\n\nimport type { I_AuthenticatedRequest, I_GraphqlWSOptions, I_WSOptions } from './ws.type.js';\n\n/**\n * Creates a WebSocket server with the specified configuration.\n * This function creates a WebSocket server instance that can be attached to an HTTP server\n * and configured with a specific path for WebSocket connections.\n *\n * @param options - Configuration options including the HTTP server instance and WebSocket path.\n * @returns A configured WebSocket server instance ready to handle connections.\n */\nexport function createWSServer(options: I_WSOptions): WebSocketServer {\n const { server, path, sessionParser } = options;\n\n if (sessionParser) {\n const wss = new WebSocketServer({ noServer: true });\n\n server.on('upgrade', (req: IncomingMessage, socket: Duplex, head: Buffer) => {\n try {\n const url = new URL(req.url || '', 'http://localhost');\n if (url.pathname !== path)\n return;\n\n sessionParser(req as Request, {} as Response, () => {\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit('connection', ws, req);\n });\n });\n }\n catch {\n socket.destroy();\n }\n });\n\n return wss;\n }\n\n return new WebSocketServer({ server, path });\n}\n\n/**\n * Initializes GraphQL WebSocket server with schema and WebSocket server.\n * This function sets up GraphQL subscriptions over WebSocket by creating a GraphQL WebSocket server\n * that can handle GraphQL operations including queries, mutations, and subscriptions.\n *\n * @param options - Configuration options including the GraphQL schema and WebSocket server instance.\n * @returns A configured GraphQL WebSocket server ready to handle GraphQL operations over WebSocket.\n */\nexport function initGraphQLWS(options: I_GraphqlWSOptions) {\n const { schema, server, context: makeExtraContext, onConnect } = options;\n\n return createGraphQLWSServer(\n {\n schema,\n context: async (ctx) => {\n const req = ctx.extra.request as I_AuthenticatedRequest;\n\n const extra = makeExtraContext ? await makeExtraContext(req) : {};\n return { req, ...extra };\n },\n onConnect: async (ctx) => {\n if (onConnect) {\n const req = ctx.extra.request as I_AuthenticatedRequest;\n await onConnect(req);\n }\n },\n },\n server,\n );\n}\n"],"mappings":";;;AAkBA,SAAgB,EAAe,GAAuC;CAClE,IAAM,EAAE,WAAQ,SAAM,qBAAkB;AAExC,KAAI,GAAe;EACf,IAAM,IAAM,IAAI,EAAgB,EAAE,UAAU,IAAM,CAAC;AAmBnD,SAjBA,EAAO,GAAG,YAAY,GAAsB,GAAgB,MAAiB;AACzE,OAAI;AAEA,QADY,IAAI,IAAI,EAAI,OAAO,IAAI,mBAAmB,CAC9C,aAAa,EACjB;AAEJ,MAAc,GAAgB,EAAE,QAAoB;AAChD,OAAI,cAAc,GAAK,GAAQ,IAAO,MAAO;AACzC,QAAI,KAAK,cAAc,GAAI,EAAI;OACjC;MACJ;WAEA;AACF,MAAO,SAAS;;IAEtB,EAEK;;AAGX,QAAO,IAAI,EAAgB;EAAE;EAAQ;EAAM,CAAC;;AAWhD,SAAgB,EAAc,GAA6B;CACvD,IAAM,EAAE,WAAQ,WAAQ,SAAS,GAAkB,iBAAc;AAEjE,QAAO,EACH;EACI;EACA,SAAS,OAAO,MAAQ;GACpB,IAAM,IAAM,EAAI,MAAM;AAGtB,UAAO;IAAE;IAAK,GADA,IAAmB,MAAM,EAAiB,EAAI,GAAG,EAAE;IACzC;;EAE5B,WAAW,OAAO,MAAQ;AACtB,OAAI,GAAW;IACX,IAAM,IAAM,EAAI,MAAM;AACtB,UAAM,EAAU,EAAI;;;EAG/B,EACD,EACH"}
@@ -0,0 +1,8 @@
1
+ //#region node_modules/.pnpm/vitest@4.1.0_@types+node@25.5.0_jsdom@29.0.0_@noble+hashes@1.8.0__vite@8.0.0_@types+nod_53aa4254f295b3c40bb8f17b6ab226b5/node_modules/vitest/dist/config.js
2
+ function e(e) {
3
+ return e;
4
+ }
5
+ //#endregion
6
+ export { e as defineConfig };
7
+
8
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../../../../../../node_modules/.pnpm/vitest@4.1.0_@types+node@25.5.0_jsdom@29.0.0_@noble+hashes@1.8.0__vite@8.0.0_@types+nod_53aa4254f295b3c40bb8f17b6ab226b5/node_modules/vitest/dist/config.js"],"sourcesContent":["export { c as configDefaults, a as coverageConfigDefaults, d as defaultExclude, b as defaultInclude } from './chunks/defaults.CdU2lD-q.js';\nexport { mergeConfig } from 'vite';\nexport { d as defaultBrowserPort } from './chunks/constants.CPYnjOGj.js';\nimport 'node:os';\nimport './chunks/env.D4Lgay0q.js';\nimport 'std-env';\n\nfunction defineConfig(config) {\n\treturn config;\n}\nfunction defineProject(config) {\n\treturn config;\n}\n\nexport { defineConfig, defineProject };\n"],"x_google_ignoreList":[0],"mappings":";AAOA,SAAS,EAAa,GAAQ;AAC7B,QAAO"}
@@ -1,19 +1,17 @@
1
- import { ApolloProvider as m } from "@apollo/client/react";
2
- import * as e from "react";
3
- import { useMemo as i } from "react";
4
- import { ApolloClientProvider as n } from "./apollo-client.context.js";
5
- import { getClient as p } from "./apollo-client.util.js";
6
- import { ApolloErrorProvider as a } from "../apollo-error/apollo-error.provider.js";
7
- import { ApolloErrorComponent as c } from "../apollo-error/apollo-error.component.js";
8
- import { Toaster as f } from "react-hot-toast";
9
- function g({ options: o, children: l, onError: r }) {
10
- const t = i(
11
- () => p(o ?? {}),
12
- [o]
13
- );
14
- return /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(a, { onError: r }, /* @__PURE__ */ e.createElement(n, { client: t }, /* @__PURE__ */ e.createElement(m, { client: t }, l)), !r && /* @__PURE__ */ e.createElement(c, null)), /* @__PURE__ */ e.createElement(f, { position: "top-right" }));
1
+ import { Toaster as e } from "../toast/index.js";
2
+ import { ApolloErrorComponent as t } from "../apollo-error/apollo-error.component.js";
3
+ import { ApolloErrorProvider as n } from "../apollo-error/apollo-error.provider.js";
4
+ import { getClient as r } from "./apollo-client.util.js";
5
+ import { ApolloClientProvider as i } from "./apollo-client.context.js";
6
+ import * as a from "react";
7
+ import { useMemo as o } from "react";
8
+ import { ApolloProvider as s } from "@apollo/client/react";
9
+ //#region src/react/apollo-client/apollo-client.component.tsx
10
+ function c({ options: c, children: l, onError: u }) {
11
+ let d = o(() => r(c ?? {}), [c?.uri, c?.wsUrl]);
12
+ return /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(n, { onError: u }, /* @__PURE__ */ a.createElement(i, { client: d }, /* @__PURE__ */ a.createElement(s, { client: d }, l)), !u && /* @__PURE__ */ a.createElement(t, null)), /* @__PURE__ */ a.createElement(e, { position: "top-right" }));
15
13
  }
16
- export {
17
- g as ApolloProvider
18
- };
19
- //# sourceMappingURL=apollo-client.component.js.map
14
+ //#endregion
15
+ export { c as ApolloProvider };
16
+
17
+ //# sourceMappingURL=apollo-client.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apollo-client.component.js","sources":["../../../src/react/apollo-client/apollo-client.component.tsx"],"sourcesContent":["import { ApolloProvider as ApolloProviderDefault } from '@apollo/client/react';\nimport * as React from 'react';\nimport { useMemo } from 'react';\n\nimport type { I_ApolloProviderProps } from './apollo-client.type.js';\n\nimport { ApolloErrorComponent, ApolloErrorProvider } from '../apollo-error/index.js';\nimport { Toaster } from '../toast/index.js';\nimport { ApolloClientProvider } from './apollo-client.context.js';\nimport { getClient } from './apollo-client.util.js';\n\n/**\n * Apollo Provider component that wraps the application with Apollo Client context.\n * This component provides the Apollo Client instance to all child components,\n * enabling GraphQL operations throughout the component tree. It includes\n * error handling and toast integration for a complete GraphQL experience.\n *\n * Features:\n * - Apollo Client context provision\n * - Error boundary integration\n * - Toast notification support\n * - Automatic error handling\n * - Development and production optimizations\n *\n * @param props - Component props containing options, children, and optional error override.\n * @param props.options - Apollo Client configuration options.\n * @param props.children - React children that will have access to Apollo Client context.\n * @param props.onError - Optional callback to override the default modal/toast error handling.\n * @returns A React component that provides Apollo Client context to its children.\n */\nexport function ApolloProvider({ options, children, onError }: I_ApolloProviderProps) {\n const client = useMemo(\n () => getClient(options ?? {}),\n [options],\n );\n\n return (\n <>\n <ApolloErrorProvider onError={onError}>\n <ApolloClientProvider client={client}>\n <ApolloProviderDefault client={client}>{children}</ApolloProviderDefault>\n </ApolloClientProvider>\n {!onError && <ApolloErrorComponent />}\n </ApolloErrorProvider>\n <Toaster position=\"top-right\" />\n </>\n );\n}\n"],"names":["ApolloProvider","options","children","onError","client","useMemo","getClient","React","ApolloErrorProvider","ApolloClientProvider","ApolloProviderDefault","ApolloErrorComponent","Toaster"],"mappings":";;;;;;;;AA8BO,SAASA,EAAe,EAAE,SAAAC,GAAS,UAAAC,GAAU,SAAAC,KAAkC;AAClF,QAAMC,IAASC;AAAA,IACX,MAAMC,EAAUL,KAAW,EAAE;AAAA,IAC7B,CAACA,CAAO;AAAA,EAAA;AAGZ,SACI,gBAAAM,EAAA,cAAAA,EAAA,UAAA,sCACKC,GAAA,EAAoB,SAAAL,EAAA,mCAChBM,GAAA,EAAqB,QAAAL,EAAA,GAClB,gBAAAG,EAAA,cAACG,GAAA,EAAsB,QAAAN,EAAA,GAAiBF,CAAS,CACrD,GACC,CAACC,KAAW,gBAAAI,EAAA,cAACI,GAAA,IAAqB,CACvC,GACA,gBAAAJ,EAAA,cAACK,GAAA,EAAQ,UAAS,YAAA,CAAY,CAClC;AAER;"}
1
+ {"version":3,"file":"apollo-client.component.js","names":[],"sources":["../../../src/react/apollo-client/apollo-client.component.tsx"],"sourcesContent":["import { ApolloProvider as ApolloProviderDefault } from '@apollo/client/react';\nimport * as React from 'react';\nimport { useMemo } from 'react';\n\nimport type { I_ApolloProviderProps } from './apollo-client.type.js';\n\nimport { ApolloErrorComponent, ApolloErrorProvider } from '../apollo-error/index.js';\nimport { Toaster } from '../toast/index.js';\nimport { ApolloClientProvider } from './apollo-client.context.js';\nimport { getClient } from './apollo-client.util.js';\n\n/**\n * Apollo Provider component that wraps the application with Apollo Client context.\n * This component provides the Apollo Client instance to all child components,\n * enabling GraphQL operations throughout the component tree. It includes\n * error handling and toast integration for a complete GraphQL experience.\n *\n * Features:\n * - Apollo Client context provision\n * - Error boundary integration\n * - Toast notification support\n * - Automatic error handling\n * - Development and production optimizations\n *\n * @param props - Component props containing options, children, and optional error override.\n * @param props.options - Apollo Client configuration options.\n * @param props.children - React children that will have access to Apollo Client context.\n * @param props.onError - Optional callback to override the default modal/toast error handling.\n * @returns A React component that provides Apollo Client context to its children.\n */\nexport function ApolloProvider({ options, children, onError }: I_ApolloProviderProps) {\n const client = useMemo(\n () => getClient(options ?? {}),\n // Depend on stable primitive values to avoid recreating ApolloClient when parent re-renders\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [options?.uri, options?.wsUrl],\n );\n\n return (\n <>\n <ApolloErrorProvider onError={onError}>\n <ApolloClientProvider client={client}>\n <ApolloProviderDefault client={client}>{children}</ApolloProviderDefault>\n </ApolloClientProvider>\n {!onError && <ApolloErrorComponent />}\n </ApolloErrorProvider>\n <Toaster position=\"top-right\" />\n </>\n );\n}\n"],"mappings":";;;;;;;;;AA8BA,SAAgB,EAAe,EAAE,YAAS,aAAU,cAAkC;CAClF,IAAM,IAAS,QACL,EAAU,KAAW,EAAE,CAAC,EAG9B,CAAC,GAAS,KAAK,GAAS,MAAM,CACjC;AAED,QACI,kBAAA,cAAA,EAAA,UAAA,MACI,kBAAA,cAAC,GAAD,EAA8B,YAKR,EAJlB,kBAAA,cAAC,GAAD,EAA8B,WAEP,EADnB,kBAAA,cAAC,GAAD,EAA+B,WAA0C,EAAjC,EAAiC,CACtD,EACtB,CAAC,KAAW,kBAAA,cAAC,GAAA,KAAuB,CACnB,EACtB,kBAAA,cAAC,GAAD,EAAS,UAAS,aAAc,CAAA,CACjC"}
@@ -1,5 +1,6 @@
1
- const o = "/graphql";
2
- export {
3
- o as GRAPHQL_URI_DEFAULT
4
- };
5
- //# sourceMappingURL=apollo-client.constant.js.map
1
+ //#region src/react/apollo-client/apollo-client.constant.ts
2
+ var e = "/graphql";
3
+ //#endregion
4
+ export { e as GRAPHQL_URI_DEFAULT };
5
+
6
+ //# sourceMappingURL=apollo-client.constant.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apollo-client.constant.js","sources":["../../../src/react/apollo-client/apollo-client.constant.ts"],"sourcesContent":["/**\n * Default GraphQL endpoint URI for Apollo Client configuration.\n * This constant provides the standard GraphQL endpoint path that is commonly used\n * in web applications for GraphQL API communication.\n */\nexport const GRAPHQL_URI_DEFAULT = '/graphql';\n"],"names":["GRAPHQL_URI_DEFAULT"],"mappings":"AAKO,MAAMA,IAAsB;"}
1
+ {"version":3,"file":"apollo-client.constant.js","names":[],"sources":["../../../src/react/apollo-client/apollo-client.constant.ts"],"sourcesContent":["/**\n * Default GraphQL endpoint URI for Apollo Client configuration.\n * This constant provides the standard GraphQL endpoint path that is commonly used\n * in web applications for GraphQL API communication.\n */\nexport const GRAPHQL_URI_DEFAULT = '/graphql';\n"],"mappings":";AAKA,IAAa,IAAsB"}