@ledgerhq/device-management-kit 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/package.json +1 -2
- package/lib/cjs/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.js +1 -1
- package/lib/cjs/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.js.map +3 -3
- package/lib/cjs/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.test.js +1 -1
- package/lib/cjs/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.test.js.map +2 -2
- package/lib/cjs/src/api/device-action/os/GetDeviceStatus/types.js +1 -1
- package/lib/cjs/src/api/device-action/os/GetDeviceStatus/types.js.map +1 -1
- package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.js +1 -1
- package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.js.map +2 -2
- package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.test.js +1 -1
- package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.test.js.map +2 -2
- package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/types.js +1 -1
- package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/types.js.map +1 -1
- package/lib/cjs/src/api/device-action/os/OpenAppWithDependencies/types.js.map +1 -1
- package/lib/cjs/src/api/logger-subscriber/service/WebLogsExporterLogger.js.map +2 -2
- package/lib/cjs/src/api/network/DmkNetworkClient.js +1 -1
- package/lib/cjs/src/api/network/DmkNetworkClient.js.map +3 -3
- package/lib/cjs/src/api/network/DmkNetworkClient.test.js +1 -1
- package/lib/cjs/src/api/network/DmkNetworkClient.test.js.map +3 -3
- package/lib/cjs/src/api/network/DmkNetworkClientError.js +1 -1
- package/lib/cjs/src/api/network/DmkNetworkClientError.js.map +2 -2
- package/lib/cjs/src/api/network/DmkNetworkClientHelpers.js +1 -1
- package/lib/cjs/src/api/network/DmkNetworkClientHelpers.js.map +3 -3
- package/lib/cjs/src/api/network/DmkNetworkClientHelpers.test.js +1 -1
- package/lib/cjs/src/api/network/DmkNetworkClientHelpers.test.js.map +3 -3
- package/lib/cjs/src/api/utils/Base64String.js +1 -1
- package/lib/cjs/src/api/utils/Base64String.js.map +3 -3
- package/lib/cjs/src/api/utils/Base64String.test.js +3 -1
- package/lib/cjs/src/api/utils/Base64String.test.js.map +3 -3
- package/lib/cjs/src/internal/secure-channel/data/DefaultSecureChannelDataSource.js +1 -1
- package/lib/cjs/src/internal/secure-channel/data/DefaultSecureChannelDataSource.js.map +3 -3
- package/lib/cjs/src/internal/secure-channel/data/DefaultSecureChannelDataSource.test.js +1 -1
- package/lib/cjs/src/internal/secure-channel/data/DefaultSecureChannelDataSource.test.js.map +2 -2
- package/lib/esm/package.json +1 -2
- package/lib/esm/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.js +1 -1
- package/lib/esm/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.js.map +3 -3
- package/lib/esm/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.test.js +1 -1
- package/lib/esm/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.test.js.map +2 -2
- package/lib/esm/src/api/device-action/os/GetDeviceStatus/types.js.map +1 -1
- package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.js +1 -1
- package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.js.map +2 -2
- package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.test.js +1 -1
- package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.test.js.map +2 -2
- package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/types.js.map +1 -1
- package/lib/esm/src/api/device-action/os/OpenAppWithDependencies/types.js.map +1 -1
- package/lib/esm/src/api/logger-subscriber/service/WebLogsExporterLogger.js.map +2 -2
- package/lib/esm/src/api/network/DmkNetworkClient.js +1 -1
- package/lib/esm/src/api/network/DmkNetworkClient.js.map +3 -3
- package/lib/esm/src/api/network/DmkNetworkClient.test.js +1 -1
- package/lib/esm/src/api/network/DmkNetworkClient.test.js.map +3 -3
- package/lib/esm/src/api/network/DmkNetworkClientError.js +1 -1
- package/lib/esm/src/api/network/DmkNetworkClientError.js.map +2 -2
- package/lib/esm/src/api/network/DmkNetworkClientHelpers.js +1 -1
- package/lib/esm/src/api/network/DmkNetworkClientHelpers.js.map +3 -3
- package/lib/esm/src/api/network/DmkNetworkClientHelpers.test.js +1 -1
- package/lib/esm/src/api/network/DmkNetworkClientHelpers.test.js.map +3 -3
- package/lib/esm/src/api/utils/Base64String.js +1 -1
- package/lib/esm/src/api/utils/Base64String.js.map +3 -3
- package/lib/esm/src/api/utils/Base64String.test.js +3 -1
- package/lib/esm/src/api/utils/Base64String.test.js.map +3 -3
- package/lib/esm/src/internal/secure-channel/data/DefaultSecureChannelDataSource.js +1 -1
- package/lib/esm/src/internal/secure-channel/data/DefaultSecureChannelDataSource.js.map +3 -3
- package/lib/esm/src/internal/secure-channel/data/DefaultSecureChannelDataSource.test.js +1 -1
- package/lib/esm/src/internal/secure-channel/data/DefaultSecureChannelDataSource.test.js.map +2 -2
- package/lib/types/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.d.ts.map +1 -1
- package/lib/types/src/api/device-action/os/GetDeviceStatus/types.d.ts +1 -0
- package/lib/types/src/api/device-action/os/GetDeviceStatus/types.d.ts.map +1 -1
- package/lib/types/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.d.ts.map +1 -1
- package/lib/types/src/api/device-action/os/OpenAppDeviceAction/types.d.ts +1 -1
- package/lib/types/src/api/device-action/os/OpenAppDeviceAction/types.d.ts.map +1 -1
- package/lib/types/src/api/device-action/os/OpenAppWithDependencies/types.d.ts +1 -1
- package/lib/types/src/api/device-action/os/OpenAppWithDependencies/types.d.ts.map +1 -1
- package/lib/types/src/api/logger-subscriber/service/WebLogsExporterLogger.d.ts.map +1 -1
- package/lib/types/src/api/network/DmkNetworkClient.d.ts +1 -6
- package/lib/types/src/api/network/DmkNetworkClient.d.ts.map +1 -1
- package/lib/types/src/api/network/DmkNetworkClientError.d.ts +2 -6
- package/lib/types/src/api/network/DmkNetworkClientError.d.ts.map +1 -1
- package/lib/types/src/api/network/DmkNetworkClientHelpers.d.ts +10 -7
- package/lib/types/src/api/network/DmkNetworkClientHelpers.d.ts.map +1 -1
- package/lib/types/src/api/utils/Base64String.d.ts.map +1 -1
- package/lib/types/src/internal/secure-channel/data/DefaultSecureChannelDataSource.d.ts.map +1 -1
- package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
- package/package.json +3 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/api/network/DmkNetworkClient.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { DmkNetworkClient } from \"./DmkNetworkClient\";\nimport { DmkNetworkClientError } from \"./DmkNetworkClientError\";\n\ndescribe(\"DmkNetworkClient\", () => {\n const jsonResponse = (body: unknown, init: ResponseInit = {}) =>\n new Response(JSON.stringify(body), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n ...init,\n });\n\n describe(\"URL composition\", () => {\n it(\"should send requests to an absolute URL as-is\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\");\n\n const [calledUrl] = fetchMock.mock.calls[0]!;\n expect(typeof calledUrl).toBe(\"string\");\n expect(calledUrl).toBe(\"https://api.example.com/items\");\n });\n\n it(\"should prepend baseUrl to relative paths with slash normalization\", async () => {\n const fetchMock = vi\n .fn()\n .mockImplementation(() => Promise.resolve(jsonResponse({ ok: true })));\n const client = new DmkNetworkClient({\n baseUrl: \"https://api.example.com/\",\n fetch: fetchMock,\n });\n\n await client.get(\"/items\");\n await client.get(\"items\");\n\n expect(fetchMock.mock.calls[0]![0]).toBe(\"https://api.example.com/items\");\n expect(fetchMock.mock.calls[1]![0]).toBe(\"https://api.example.com/items\");\n });\n\n it(\"should set URL search params from the config\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\", {\n params: {\n chain: 1,\n contract: \"0xabc\",\n active: true,\n skip: null,\n alsoSkip: undefined,\n },\n });\n\n const calledUrl = fetchMock.mock.calls[0]![0] as string;\n expect(typeof calledUrl).toBe(\"string\");\n const url = new URL(calledUrl);\n expect(url.searchParams.get(\"chain\")).toBe(\"1\");\n expect(url.searchParams.get(\"contract\")).toBe(\"0xabc\");\n expect(url.searchParams.get(\"active\")).toBe(\"true\");\n expect(url.searchParams.has(\"skip\")).toBe(false);\n expect(url.searchParams.has(\"alsoSkip\")).toBe(false);\n });\n\n it(\"should pass a plain string URL to fetch with no trailing slash after the query (facebook/react-native#54242)\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\n \"https://manager.api.live.ledger.com/api/get_device_version\",\n { params: { target_id: 858783748, provider: 1 } },\n );\n\n const [calledUrl] = fetchMock.mock.calls[0]!;\n expect(typeof calledUrl).toBe(\"string\");\n expect(calledUrl).toBe(\n \"https://manager.api.live.ledger.com/api/get_device_version?target_id=858783748&provider=1\",\n );\n expect((calledUrl as string).endsWith(\"/\")).toBe(false);\n });\n });\n\n describe(\"headers\", () => {\n it(\"should merge default and per-request headers\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({\n fetch: fetchMock,\n headers: { \"X-Default\": \"default\", \"X-Shared\": \"from-default\" },\n });\n\n await client.get(\"https://api.example.com/items\", {\n headers: { \"X-Shared\": \"overridden\", \"X-Per-Request\": \"per\" },\n });\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.headers).toMatchObject({\n \"X-Default\": \"default\",\n \"X-Shared\": \"overridden\",\n \"X-Per-Request\": \"per\",\n });\n });\n });\n\n describe(\"body handling\", () => {\n it(\"should JSON-stringify plain-object bodies and set Content-Type\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.post(\"https://api.example.com/items\", { foo: \"bar\" });\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.method).toBe(\"POST\");\n expect(init.body).toBe(JSON.stringify({ foo: \"bar\" }));\n expect(init.headers).toMatchObject({\n \"Content-Type\": \"application/json\",\n });\n });\n\n it(\"should not override an explicit Content-Type header\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.post(\n \"https://api.example.com/items\",\n { foo: \"bar\" },\n { headers: { \"content-type\": \"application/vnd.custom+json\" } },\n );\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.headers).toMatchObject({\n \"content-type\": \"application/vnd.custom+json\",\n });\n });\n\n it(\"should pass raw BodyInit values through unchanged\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n const formData = new FormData();\n formData.set(\"field\", \"value\");\n\n await client.post(\"https://api.example.com/items\", formData);\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.body).toBe(formData);\n expect(init.headers).not.toMatchObject({\n \"Content-Type\": \"application/json\",\n });\n });\n\n it(\"should not send a body on GET or HEAD\", async () => {\n const fetchMock = vi\n .fn()\n .mockImplementation(() => Promise.resolve(jsonResponse({ ok: true })));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\");\n await client.head(\"https://api.example.com/items\");\n\n expect(fetchMock.mock.calls[0]![1]).toMatchObject({ body: undefined });\n expect(fetchMock.mock.calls[1]![1]).toMatchObject({ body: undefined });\n });\n });\n\n describe(\"response parsing\", () => {\n it(\"should return the parsed JSON body by default\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(jsonResponse({ hello: \"world\" }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const result = await client.get(\"https://api.example.com/items\");\n\n expect(result).toEqual({ hello: \"world\" });\n });\n\n it(\"should return text when responseType is 'text'\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(\"plain-body\", { status: 200 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const result = await client.get(\"https://api.example.com/items\", {\n responseType: \"text\",\n });\n\n expect(result).toBe(\"plain-body\");\n });\n\n it(\"should resolve HEAD to void without reading the body\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(null, { status: 200 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const result = await client.head(\"https://api.example.com/items\");\n\n expect(result).toBeUndefined();\n });\n\n it(\"should resolve empty JSON body to undefined\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(null, { status: 204 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const result = await client.get(\"https://api.example.com/items\");\n\n expect(result).toBeUndefined();\n });\n\n it(\"should throw a DmkNetworkClientError on malformed JSON\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(\"not-json\", { status: 200 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await expect(\n client.get(\"https://api.example.com/items\"),\n ).rejects.toBeInstanceOf(DmkNetworkClientError);\n });\n });\n\n describe(\"error handling\", () => {\n it(\"should throw DmkNetworkClientError with status on non-2xx responses\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(\n new Response(\"boom\", {\n status: 500,\n statusText: \"Server Error\",\n }),\n );\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const error = await client\n .get(\"https://api.example.com/items\")\n .catch((e: unknown) => e);\n\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n const dmkError = error as DmkNetworkClientError;\n expect(dmkError.status).toBe(500);\n expect(dmkError.statusText).toBe(\"Server Error\");\n expect(dmkError.responseBody).toBe(\"boom\");\n expect(dmkError.isTimeout).toBe(false);\n expect(dmkError.isAbort).toBe(false);\n });\n\n it(\"should not throw when throwOnHttpError is disabled\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(\"boom\", { status: 500 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const response = await client.request({\n method: \"GET\",\n url: \"https://api.example.com/items\",\n responseType: \"text\",\n throwOnHttpError: false,\n });\n\n expect(response.status).toBe(500);\n expect(response.ok).toBe(false);\n expect(response.data).toBe(\"boom\");\n });\n\n it(\"should wrap generic fetch failures into DmkNetworkClientError\", async () => {\n const cause = new TypeError(\"network down\");\n const fetchMock = vi.fn().mockRejectedValue(cause);\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const error = await client\n .get(\"https://api.example.com/items\")\n .catch((e: unknown) => e);\n\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n expect((error as DmkNetworkClientError).cause).toBe(cause);\n });\n });\n\n describe(\"timeout\", () => {\n it(\"should pass an AbortSignal when timeoutMs is configured\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\", { timeoutMs: 1000 });\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.signal).toBeInstanceOf(AbortSignal);\n });\n\n it(\"should not pass a signal when no timeout and no external signal are set\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\");\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.signal).toBeUndefined();\n });\n\n it(\"should mark the error as a timeout when fetch rejects with TimeoutError\", async () => {\n const timeoutError = new Error(\"The operation was aborted\");\n timeoutError.name = \"TimeoutError\";\n const fetchMock = vi.fn().mockRejectedValue(timeoutError);\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const error = await client\n .get(\"https://api.example.com/items\", { timeoutMs: 10 })\n .catch((e: unknown) => e);\n\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n expect((error as DmkNetworkClientError).isTimeout).toBe(true);\n expect((error as DmkNetworkClientError).isAbort).toBe(false);\n });\n\n it(\"should mark the error as an abort when the caller signal is aborted\", async () => {\n const abortController = new AbortController();\n abortController.abort();\n const abortError = new Error(\"aborted\");\n abortError.name = \"AbortError\";\n const fetchMock = vi.fn().mockRejectedValue(abortError);\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const error = await client\n .get(\"https://api.example.com/items\", {\n signal: abortController.signal,\n })\n .catch((e: unknown) => e);\n\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n expect((error as DmkNetworkClientError).isAbort).toBe(true);\n expect((error as DmkNetworkClientError).isTimeout).toBe(false);\n });\n });\n\n describe(\"request envelope\", () => {\n it(\"should expose full response metadata via request()\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(\n new Response(JSON.stringify({ hello: \"world\" }), {\n status: 201,\n statusText: \"Created\",\n headers: { \"X-Custom\": \"1\", \"Content-Type\": \"application/json\" },\n }),\n );\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const response = await client.request({\n method: \"GET\",\n url: \"https://api.example.com/items\",\n });\n\n expect(response.status).toBe(201);\n expect(response.statusText).toBe(\"Created\");\n expect(response.ok).toBe(true);\n expect(response.data).toEqual({ hello: \"world\" });\n expect(response.headers.get(\"X-Custom\")).toBe(\"1\");\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "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
|
|
6
|
-
"names": ["DmkNetworkClient", "DmkNetworkClientError", "jsonResponse", "body", "init", "fetchMock", "calledUrl", "client", "url", "formData", "result", "error", "e", "dmkError", "response", "cause", "
|
|
4
|
+
"sourcesContent": ["import { DmkNetworkClient } from \"./DmkNetworkClient\";\nimport { DmkNetworkClientError } from \"./DmkNetworkClientError\";\n\ndescribe(\"DmkNetworkClient\", () => {\n const jsonResponse = (body: unknown, init: ResponseInit = {}) =>\n new Response(JSON.stringify(body), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n ...init,\n });\n\n describe(\"URL composition\", () => {\n it(\"should send requests to an absolute URL as-is\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\");\n\n const [calledUrl] = fetchMock.mock.calls[0]!;\n expect(typeof calledUrl).toBe(\"string\");\n expect(calledUrl).toBe(\"https://api.example.com/items\");\n });\n\n it(\"should prepend baseUrl to relative paths with slash normalization\", async () => {\n const fetchMock = vi\n .fn()\n .mockImplementation(() => Promise.resolve(jsonResponse({ ok: true })));\n const client = new DmkNetworkClient({\n baseUrl: \"https://api.example.com/\",\n fetch: fetchMock,\n });\n\n await client.get(\"/items\");\n await client.get(\"items\");\n\n expect(fetchMock.mock.calls[0]![0]).toBe(\"https://api.example.com/items\");\n expect(fetchMock.mock.calls[1]![0]).toBe(\"https://api.example.com/items\");\n });\n\n it(\"should set URL search params from the config\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\", {\n params: {\n chain: 1,\n contract: \"0xabc\",\n active: true,\n skip: null,\n alsoSkip: undefined,\n },\n });\n\n const calledUrl = fetchMock.mock.calls[0]![0] as string;\n expect(typeof calledUrl).toBe(\"string\");\n const url = new URL(calledUrl);\n expect(url.searchParams.get(\"chain\")).toBe(\"1\");\n expect(url.searchParams.get(\"contract\")).toBe(\"0xabc\");\n expect(url.searchParams.get(\"active\")).toBe(\"true\");\n expect(url.searchParams.has(\"skip\")).toBe(false);\n expect(url.searchParams.has(\"alsoSkip\")).toBe(false);\n });\n\n it(\"should pass a plain string URL to fetch with no trailing slash after the query (facebook/react-native#54242)\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\n \"https://manager.api.live.ledger.com/api/get_device_version\",\n { params: { target_id: 858783748, provider: 1 } },\n );\n\n const [calledUrl] = fetchMock.mock.calls[0]!;\n expect(typeof calledUrl).toBe(\"string\");\n expect(calledUrl).toBe(\n \"https://manager.api.live.ledger.com/api/get_device_version?target_id=858783748&provider=1\",\n );\n expect((calledUrl as string).endsWith(\"/\")).toBe(false);\n });\n });\n\n describe(\"headers\", () => {\n it(\"should merge default and per-request headers\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({\n fetch: fetchMock,\n headers: { \"X-Default\": \"default\", \"X-Shared\": \"from-default\" },\n });\n\n await client.get(\"https://api.example.com/items\", {\n headers: { \"X-Shared\": \"overridden\", \"X-Per-Request\": \"per\" },\n });\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.headers).toMatchObject({\n \"X-Default\": \"default\",\n \"X-Shared\": \"overridden\",\n \"X-Per-Request\": \"per\",\n });\n });\n });\n\n describe(\"body handling\", () => {\n it(\"should JSON-stringify plain-object bodies and set Content-Type\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.post(\"https://api.example.com/items\", { foo: \"bar\" });\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.method).toBe(\"POST\");\n expect(init.body).toBe(JSON.stringify({ foo: \"bar\" }));\n expect(init.headers).toMatchObject({\n \"Content-Type\": \"application/json\",\n });\n });\n\n it(\"should not override an explicit Content-Type header\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.post(\n \"https://api.example.com/items\",\n { foo: \"bar\" },\n { headers: { \"content-type\": \"application/vnd.custom+json\" } },\n );\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.headers).toMatchObject({\n \"content-type\": \"application/vnd.custom+json\",\n });\n });\n\n it(\"should pass raw BodyInit values through unchanged\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n const formData = new FormData();\n formData.set(\"field\", \"value\");\n\n await client.post(\"https://api.example.com/items\", formData);\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.body).toBe(formData);\n expect(init.headers).not.toMatchObject({\n \"Content-Type\": \"application/json\",\n });\n });\n\n it(\"should not send a body on GET or HEAD\", async () => {\n const fetchMock = vi\n .fn()\n .mockImplementation(() => Promise.resolve(jsonResponse({ ok: true })));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\");\n await client.head(\"https://api.example.com/items\");\n\n expect(fetchMock.mock.calls[0]![1]).toMatchObject({ body: undefined });\n expect(fetchMock.mock.calls[1]![1]).toMatchObject({ body: undefined });\n });\n });\n\n describe(\"response parsing\", () => {\n it(\"should return the parsed JSON body by default\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(jsonResponse({ hello: \"world\" }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const result = await client.get(\"https://api.example.com/items\");\n\n expect(result).toEqual({ hello: \"world\" });\n });\n\n it(\"should return text when responseType is 'text'\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(\"plain-body\", { status: 200 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const result = await client.get(\"https://api.example.com/items\", {\n responseType: \"text\",\n });\n\n expect(result).toBe(\"plain-body\");\n });\n\n it(\"should resolve HEAD to void without reading the body\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(null, { status: 200 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const result = await client.head(\"https://api.example.com/items\");\n\n expect(result).toBeUndefined();\n });\n\n it(\"should resolve empty JSON body to undefined\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(null, { status: 204 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const result = await client.get(\"https://api.example.com/items\");\n\n expect(result).toBeUndefined();\n });\n\n it(\"should throw a DmkNetworkClientError on malformed JSON\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(\"not-json\", { status: 200 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await expect(\n client.get(\"https://api.example.com/items\"),\n ).rejects.toBeInstanceOf(DmkNetworkClientError);\n });\n });\n\n describe(\"error handling\", () => {\n it(\"should throw DmkNetworkClientError with status on non-2xx responses\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(\n new Response(\"boom\", {\n status: 500,\n statusText: \"Server Error\",\n }),\n );\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const error = await client\n .get(\"https://api.example.com/items\")\n .catch((e: unknown) => e);\n\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n const dmkError = error as DmkNetworkClientError;\n expect(dmkError.status).toBe(500);\n expect(dmkError.statusText).toBe(\"Server Error\");\n expect(dmkError.responseBody).toBe(\"boom\");\n expect(dmkError.isTimeout).toBe(false);\n });\n\n it(\"should not throw when throwOnHttpError is disabled\", async () => {\n const fetchMock = vi\n .fn()\n .mockResolvedValue(new Response(\"boom\", { status: 500 }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const response = await client.request({\n method: \"GET\",\n url: \"https://api.example.com/items\",\n responseType: \"text\",\n throwOnHttpError: false,\n });\n\n expect(response.status).toBe(500);\n expect(response.ok).toBe(false);\n expect(response.data).toBe(\"boom\");\n });\n\n it(\"should wrap generic fetch failures into DmkNetworkClientError\", async () => {\n const cause = new TypeError(\"network down\");\n const fetchMock = vi.fn().mockRejectedValue(cause);\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const error = await client\n .get(\"https://api.example.com/items\")\n .catch((e: unknown) => e);\n\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n expect((error as DmkNetworkClientError).cause).toBe(cause);\n });\n });\n\n describe(\"timeout\", () => {\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it(\"should pass an AbortSignal when timeoutMs is configured\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\", { timeoutMs: 1000 });\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.signal).toBeInstanceOf(AbortSignal);\n });\n\n it(\"should not pass a signal when no timeout and no external signal are set\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\");\n\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n expect(init.signal).toBeUndefined();\n });\n\n it(\"GIVEN a successful request with timeout WHEN fetch resolves THEN it clears the timeout\", async () => {\n vi.useFakeTimers();\n const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client.get(\"https://api.example.com/items\", { timeoutMs: 1000 });\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n\n vi.advanceTimersByTime(1000);\n\n expect(init.signal).toBeInstanceOf(AbortSignal);\n expect(init.signal?.aborted).toBe(false);\n });\n\n it(\"GIVEN a failed request with timeout WHEN fetch rejects THEN it clears the timeout\", async () => {\n vi.useFakeTimers();\n const cause = new TypeError(\"network down\");\n const fetchMock = vi.fn().mockRejectedValue(cause);\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n await client\n .get(\"https://api.example.com/items\", { timeoutMs: 1000 })\n .catch(() => undefined);\n const init = fetchMock.mock.calls[0]![1] as RequestInit;\n\n vi.advanceTimersByTime(1000);\n\n expect(init.signal).toBeInstanceOf(AbortSignal);\n expect(init.signal?.aborted).toBe(false);\n });\n\n it(\"GIVEN a pending request with timeout WHEN the timeout signal aborts fetch THEN it throws a timeout error\", async () => {\n vi.useFakeTimers();\n const fetchMock = vi.fn(\n (_url: string | URL | Request, init?: RequestInit) =>\n new Promise<Response>((_resolve, reject) => {\n init?.signal?.addEventListener(\"abort\", () => {\n const abortError = new Error(\"The operation was aborted\");\n abortError.name = \"AbortError\";\n reject(abortError);\n });\n }),\n );\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const request = client\n .get(\"https://api.example.com/items\", { timeoutMs: 1000 })\n .catch((e: unknown) => e);\n\n await vi.advanceTimersByTimeAsync(1000);\n const error = await request;\n\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n expect((error as DmkNetworkClientError).isTimeout).toBe(true);\n });\n\n it(\"should mark the error as a timeout when fetch rejects with TimeoutError\", async () => {\n const timeoutError = new Error(\"The operation was aborted\");\n timeoutError.name = \"TimeoutError\";\n const fetchMock = vi.fn().mockRejectedValue(timeoutError);\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const error = await client\n .get(\"https://api.example.com/items\", { timeoutMs: 10 })\n .catch((e: unknown) => e);\n\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n expect((error as DmkNetworkClientError).isTimeout).toBe(true);\n });\n });\n\n describe(\"request envelope\", () => {\n it(\"should expose full response metadata via request()\", async () => {\n const fetchMock = vi.fn().mockResolvedValue(\n new Response(JSON.stringify({ hello: \"world\" }), {\n status: 201,\n statusText: \"Created\",\n headers: { \"X-Custom\": \"1\", \"Content-Type\": \"application/json\" },\n }),\n );\n const client = new DmkNetworkClient({ fetch: fetchMock });\n\n const response = await client.request({\n method: \"GET\",\n url: \"https://api.example.com/items\",\n });\n\n expect(response.status).toBe(201);\n expect(response.statusText).toBe(\"Created\");\n expect(response.ok).toBe(true);\n expect(response.data).toEqual({ hello: \"world\" });\n expect(response.headers.get(\"X-Custom\")).toBe(\"1\");\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["DmkNetworkClient", "DmkNetworkClientError", "jsonResponse", "body", "init", "fetchMock", "calledUrl", "client", "url", "formData", "result", "error", "e", "dmkError", "response", "cause", "_url", "_resolve", "reject", "abortError", "request", "timeoutError"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
class t extends Error{status;statusText;responseBody;isTimeout;
|
|
1
|
+
class t extends Error{status;statusText;responseBody;isTimeout;cause;constructor(e){super(e.message),this.name="DmkNetworkClientError",this.status=e.status,this.statusText=e.statusText,this.responseBody=e.responseBody,this.isTimeout=e.isTimeout??!1,this.cause=e.cause}}export{t as DmkNetworkClientError};
|
|
2
2
|
//# sourceMappingURL=DmkNetworkClientError.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/api/network/DmkNetworkClientError.ts"],
|
|
4
|
-
"sourcesContent": ["export type DmkNetworkClientErrorParams = {\n message: string;\n status?: number;\n statusText?: string;\n responseBody?: string;\n isTimeout?: boolean;\n
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["export type DmkNetworkClientErrorParams = {\n message: string;\n status?: number;\n statusText?: string;\n responseBody?: string;\n isTimeout?: boolean;\n cause?: unknown;\n};\n\n/**\n * Error thrown by {@link DmkNetworkClient} for HTTP, timeout or transport-level\n * failures.\n *\n * - When the remote returned a non-2xx response, {@link status} and\n * {@link statusText} are populated and {@link responseBody} contains the\n * raw text body (best effort).\n * - When the request timed out via the client's `timeoutMs`,\n * {@link isTimeout} is `true`.\n * - For other fetch/network failures, {@link cause} carries the original\n * error.\n */\nexport class DmkNetworkClientError extends Error {\n public readonly status?: number;\n public readonly statusText?: string;\n public readonly responseBody?: string;\n public readonly isTimeout: boolean;\n public override readonly cause?: unknown;\n\n constructor(params: DmkNetworkClientErrorParams) {\n super(params.message);\n this.name = \"DmkNetworkClientError\";\n this.status = params.status;\n this.statusText = params.statusText;\n this.responseBody = params.responseBody;\n this.isTimeout = params.isTimeout ?? false;\n this.cause = params.cause;\n }\n}\n"],
|
|
5
|
+
"mappings": "AAqBO,MAAMA,UAA8B,KAAM,CAC/B,OACA,WACA,aACA,UACS,MAEzB,YAAYC,EAAqC,CAC/C,MAAMA,EAAO,OAAO,EACpB,KAAK,KAAO,wBACZ,KAAK,OAASA,EAAO,OACrB,KAAK,WAAaA,EAAO,WACzB,KAAK,aAAeA,EAAO,aAC3B,KAAK,UAAYA,EAAO,WAAa,GACrC,KAAK,MAAQA,EAAO,KACtB,CACF",
|
|
6
6
|
"names": ["DmkNetworkClientError", "params"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{DmkNetworkClientError as
|
|
1
|
+
import{DmkNetworkClientError as i}from"./DmkNetworkClientError";const d="application/json";function c(e,t){if(!t)return e;const r=e.endsWith("/")?e.slice(0,-1):e,n=t.startsWith("/")?t:`/${t}`;return`${r}${n}`}function f(e){const t=[];for(const[r,n]of Object.entries(e))n!=null&&t.push(`${encodeURIComponent(r)}=${encodeURIComponent(String(n))}`);return t.join("&")}function g(e){const{url:t,params:r,baseUrl:n}=e,o=/^[a-z][a-z0-9+.-]*:\/\//i.test(t)?t:n?c(n,t):t,a=r?f(r):"";if(a.length===0)return o;const u=o.includes("?")?"&":"?";return`${o}${u}${a}`}function m(e,t){const r=t.toLowerCase();return Object.keys(e).some(n=>n.toLowerCase()===r)}function l(e){return!!(typeof e=="string"||e instanceof ArrayBuffer||ArrayBuffer.isView(e)||typeof Blob<"u"&&e instanceof Blob||typeof FormData<"u"&&e instanceof FormData||typeof URLSearchParams<"u"&&e instanceof URLSearchParams||typeof ReadableStream<"u"&&e instanceof ReadableStream)}function y(e){const{method:t,body:r,defaultHeaders:n,perRequestHeaders:s}=e,o={...n,...s};return r===void 0||t==="GET"||t==="HEAD"?{body:void 0,headers:o}:l(r)?{body:r,headers:o}:(m(o,"content-type")||(o["Content-Type"]=d),{body:JSON.stringify(r),headers:o})}function b(e){const{timeoutMs:t}=e;if(!t||t<=0)return{signal:void 0,cleanup:()=>{}};const r=new AbortController,n=setTimeout(()=>{r.abort()},t);return{signal:r.signal,cleanup:()=>clearTimeout(n)}}async function w(e,t){switch(t){case"void":return;case"text":return await e.text();case"blob":return await e.blob();case"arrayBuffer":return await e.arrayBuffer();case"json":default:{const r=await e.text();if(r.length===0)return;try{return JSON.parse(r)}catch(n){throw new i({message:"Failed to parse JSON response body",status:e.status,statusText:e.statusText,responseBody:r,cause:n})}}}}async function x(e){try{return await e.text()}catch{return}}function R(e){const{cause:t,timeoutMs:r}=e,n=!!(r&&r>0);if(t instanceof Error&&(t.name==="AbortError"||t.name==="TimeoutError")){const o=t.name==="TimeoutError"||n;return new i({message:o?"Request timed out":"Request aborted",isTimeout:o,cause:t})}return new i({message:t instanceof Error?t.message:"Network request failed",cause:t})}export{d as JSON_CONTENT_TYPE,y as buildBodyAndHeaders,b as buildSignal,g as buildUrl,m as hasHeader,l as isRawBody,c as joinPath,w as parseBody,x as safeReadText,R as wrapFetchError};
|
|
2
2
|
//# sourceMappingURL=DmkNetworkClientHelpers.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/api/network/DmkNetworkClientHelpers.ts"],
|
|
4
|
-
"sourcesContent": ["import { DmkNetworkClientError } from \"./DmkNetworkClientError\";\n\nexport type DmkQueryParamValue = string | number | boolean | null | undefined;\n\nexport type DmkQueryParams = Record<string, DmkQueryParamValue>;\n\nexport type DmkResponseType = \"json\" | \"text\" | \"blob\" | \"arrayBuffer\" | \"void\";\n\nexport const JSON_CONTENT_TYPE = \"application/json\";\n\n/**\n * Joins a base URL with a relative path, normalizing surrounding slashes so\n * that exactly one `/` appears between them.\n */\nexport function joinPath(base: string, path: string): string {\n if (!path) return base;\n const trimmedBase = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n const trimmedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${trimmedBase}${trimmedPath}`;\n}\n\n/**\n * Serializes a {@link DmkQueryParams} object into a percent-encoded\n * (RFC 3986) query string (without the leading `?`). `null`/`undefined`\n * entries are skipped.\n *\n * Note: this is not strictly `application/x-www-form-urlencoded` \u2014 spaces\n * are encoded as `%20` (via `encodeURIComponent`) rather than `+`. Any\n * RFC 3986-compliant server will decode both forms identically.\n *\n * Implemented manually rather than via `URLSearchParams` so it works on\n * runtimes where `URLSearchParams.set` is not implemented (e.g. some\n * React Native versions).\n */\nfunction serializeParams(params: DmkQueryParams): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(params)) {\n if (value === null || value === undefined) continue;\n parts.push(\n `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`,\n );\n }\n return parts.join(\"&\");\n}\n\n/**\n * Builds the final request URL as a plain string. `null`/`undefined` params\n * are skipped; params are appended (not merged) when `url` already has a\n * query string; fragments are not supported alongside `params`.\n *\n * Returns a string (not a `URL`) to avoid React Native's `URL.toString()`,\n * which appends a stray trailing `/` to URLs with a query string on affected\n * versions (facebook/react-native#54242).\n */\nexport function buildUrl(args: {\n url: string;\n params?: DmkQueryParams;\n baseUrl?: string;\n}): string {\n const { url, params, baseUrl } = args;\n const isAbsolute = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(url);\n const composed = isAbsolute ? url : baseUrl ? joinPath(baseUrl, url) : url;\n\n const query = params ? serializeParams(params) : \"\";\n if (query.length === 0) {\n return composed;\n }\n\n const separator = composed.includes(\"?\") ? \"&\" : \"?\";\n return `${composed}${separator}${query}`;\n}\n\n/**\n * Case-insensitive lookup for a header name in a plain record.\n */\nexport function hasHeader(\n headers: Record<string, string>,\n name: string,\n): boolean {\n const lower = name.toLowerCase();\n return Object.keys(headers).some((k) => k.toLowerCase() === lower);\n}\n\n/**\n * Returns `true` when the value is already a `BodyInit` accepted by `fetch`\n * and should be passed through without JSON serialization.\n *\n * Each Web-global `instanceof` check is guarded with a `typeof` test so the\n * function is safe on runtimes (e.g. some React Native versions) where\n * `Blob`, `FormData`, `URLSearchParams` or `ReadableStream` are not defined.\n */\nexport function isRawBody(body: unknown): body is BodyInit {\n if (typeof body === \"string\") return true;\n if (body instanceof ArrayBuffer) return true;\n if (ArrayBuffer.isView(body)) return true;\n if (typeof Blob !== \"undefined\" && body instanceof Blob) return true;\n if (typeof FormData !== \"undefined\" && body instanceof FormData) return true;\n if (typeof URLSearchParams !== \"undefined\" && body instanceof URLSearchParams)\n return true;\n if (typeof ReadableStream !== \"undefined\" && body instanceof ReadableStream)\n return true;\n return false;\n}\n\n/**\n * Computes the final request body and merged headers. Plain-object bodies are\n * JSON-serialized and the `Content-Type` header is set (unless the caller\n * already provided one). Raw `BodyInit` values pass through unchanged.\n */\nexport function buildBodyAndHeaders(args: {\n method: string;\n body: unknown;\n defaultHeaders: Record<string, string>;\n perRequestHeaders?: Record<string, string>;\n}): { body?: BodyInit; headers: Record<string, string> } {\n const { method, body, defaultHeaders, perRequestHeaders } = args;\n const headers: Record<string, string> = {\n ...defaultHeaders,\n ...perRequestHeaders,\n };\n\n if (body === undefined || method === \"GET\" || method === \"HEAD\") {\n return { body: undefined, headers };\n }\n\n if (isRawBody(body)) {\n return { body, headers };\n }\n\n if (!hasHeader(headers, \"content-type\")) {\n headers[\"Content-Type\"] = JSON_CONTENT_TYPE;\n }\n return { body: JSON.stringify(body), headers };\n}\n\
|
|
5
|
-
"mappings": "AAAA,OAAS,yBAAAA,MAA6B,0BAQ/B,MAAMC,EAAoB,mBAM1B,SAASC,EAASC,EAAcC,EAAsB,CAC3D,GAAI,CAACA,EAAM,OAAOD,EAClB,MAAME,EAAcF,EAAK,SAAS,GAAG,EAAIA,EAAK,MAAM,EAAG,EAAE,EAAIA,EACvDG,EAAcF,EAAK,WAAW,GAAG,EAAIA,EAAO,IAAIA,CAAI,GAC1D,MAAO,GAAGC,CAAW,GAAGC,CAAW,EACrC,CAeA,SAASC,EAAgBC,EAAgC,CACvD,MAAMC,EAAkB,CAAC,EACzB,SAAW,CAACC,EAAKC,CAAK,IAAK,OAAO,QAAQH,CAAM,EAC1CG,GAAU,MACdF,EAAM,KACJ,GAAG,mBAAmBC,CAAG,CAAC,IAAI,mBAAmB,OAAOC,CAAK,CAAC,CAAC,EACjE,EAEF,OAAOF,EAAM,KAAK,GAAG,CACvB,CAWO,SAASG,EAASC,EAId,CACT,KAAM,CAAE,IAAAC,EAAK,OAAAN,EAAQ,QAAAO,CAAQ,EAAIF,EAE3BG,EADa,2BAA2B,KAAKF,CAAG,EACxBA,EAAMC,EAAUb,EAASa,EAASD,CAAG,EAAIA,EAEjEG,EAAQT,EAASD,EAAgBC,CAAM,EAAI,GACjD,GAAIS,EAAM,SAAW,EACnB,OAAOD,EAGT,MAAME,EAAYF,EAAS,SAAS,GAAG,EAAI,IAAM,IACjD,MAAO,GAAGA,CAAQ,GAAGE,CAAS,GAAGD,CAAK,EACxC,CAKO,SAASE,EACdC,EACAC,EACS,CACT,MAAMC,EAAQD,EAAK,YAAY,EAC/B,OAAO,OAAO,KAAKD,CAAO,EAAE,KAAMG,GAAMA,EAAE,YAAY,IAAMD,CAAK,CACnE,CAUO,SAASE,EAAUC,EAAiC,
|
|
6
|
-
"names": ["DmkNetworkClientError", "JSON_CONTENT_TYPE", "joinPath", "base", "path", "trimmedBase", "trimmedPath", "serializeParams", "params", "parts", "key", "value", "buildUrl", "args", "url", "baseUrl", "composed", "query", "separator", "hasHeader", "headers", "name", "lower", "k", "isRawBody", "body", "buildBodyAndHeaders", "method", "defaultHeaders", "perRequestHeaders", "buildSignal", "timeoutMs", "
|
|
4
|
+
"sourcesContent": ["import { DmkNetworkClientError } from \"./DmkNetworkClientError\";\n\nexport type DmkQueryParamValue = string | number | boolean | null | undefined;\n\nexport type DmkQueryParams = Record<string, DmkQueryParamValue>;\n\nexport type DmkResponseType = \"json\" | \"text\" | \"blob\" | \"arrayBuffer\" | \"void\";\n\nexport const JSON_CONTENT_TYPE = \"application/json\";\n\n/**\n * Joins a base URL with a relative path, normalizing surrounding slashes so\n * that exactly one `/` appears between them.\n */\nexport function joinPath(base: string, path: string): string {\n if (!path) return base;\n const trimmedBase = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n const trimmedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${trimmedBase}${trimmedPath}`;\n}\n\n/**\n * Serializes a {@link DmkQueryParams} object into a percent-encoded\n * (RFC 3986) query string (without the leading `?`). `null`/`undefined`\n * entries are skipped.\n *\n * Note: this is not strictly `application/x-www-form-urlencoded` \u2014 spaces\n * are encoded as `%20` (via `encodeURIComponent`) rather than `+`. Any\n * RFC 3986-compliant server will decode both forms identically.\n *\n * Implemented manually rather than via `URLSearchParams` so it works on\n * runtimes where `URLSearchParams.set` is not implemented (e.g. some\n * React Native versions).\n */\nfunction serializeParams(params: DmkQueryParams): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(params)) {\n if (value === null || value === undefined) continue;\n parts.push(\n `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`,\n );\n }\n return parts.join(\"&\");\n}\n\n/**\n * Builds the final request URL as a plain string. `null`/`undefined` params\n * are skipped; params are appended (not merged) when `url` already has a\n * query string; fragments are not supported alongside `params`.\n *\n * Returns a string (not a `URL`) to avoid React Native's `URL.toString()`,\n * which appends a stray trailing `/` to URLs with a query string on affected\n * versions (facebook/react-native#54242).\n */\nexport function buildUrl(args: {\n url: string;\n params?: DmkQueryParams;\n baseUrl?: string;\n}): string {\n const { url, params, baseUrl } = args;\n const isAbsolute = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(url);\n const composed = isAbsolute ? url : baseUrl ? joinPath(baseUrl, url) : url;\n\n const query = params ? serializeParams(params) : \"\";\n if (query.length === 0) {\n return composed;\n }\n\n const separator = composed.includes(\"?\") ? \"&\" : \"?\";\n return `${composed}${separator}${query}`;\n}\n\n/**\n * Case-insensitive lookup for a header name in a plain record.\n */\nexport function hasHeader(\n headers: Record<string, string>,\n name: string,\n): boolean {\n const lower = name.toLowerCase();\n return Object.keys(headers).some((k) => k.toLowerCase() === lower);\n}\n\n/**\n * Returns `true` when the value is already a `BodyInit` accepted by `fetch`\n * and should be passed through without JSON serialization.\n *\n * Each Web-global `instanceof` check is guarded with a `typeof` test so the\n * function is safe on runtimes (e.g. some React Native versions) where\n * `Blob`, `FormData`, `URLSearchParams` or `ReadableStream` are not defined.\n */\nexport function isRawBody(body: unknown): body is BodyInit {\n if (typeof body === \"string\") return true;\n if (body instanceof ArrayBuffer) return true;\n if (ArrayBuffer.isView(body)) return true;\n /* eslint-disable no-restricted-globals -- Each Web global is guarded so the checks are safe when the global is missing in RN/Hermes. */\n if (typeof Blob !== \"undefined\" && body instanceof Blob) return true;\n if (typeof FormData !== \"undefined\" && body instanceof FormData) return true;\n if (typeof URLSearchParams !== \"undefined\" && body instanceof URLSearchParams)\n return true;\n if (typeof ReadableStream !== \"undefined\" && body instanceof ReadableStream)\n return true;\n /* eslint-enable no-restricted-globals */\n return false;\n}\n\n/**\n * Computes the final request body and merged headers. Plain-object bodies are\n * JSON-serialized and the `Content-Type` header is set (unless the caller\n * already provided one). Raw `BodyInit` values pass through unchanged.\n */\nexport function buildBodyAndHeaders(args: {\n method: string;\n body: unknown;\n defaultHeaders: Record<string, string>;\n perRequestHeaders?: Record<string, string>;\n}): { body?: BodyInit; headers: Record<string, string> } {\n const { method, body, defaultHeaders, perRequestHeaders } = args;\n const headers: Record<string, string> = {\n ...defaultHeaders,\n ...perRequestHeaders,\n };\n\n if (body === undefined || method === \"GET\" || method === \"HEAD\") {\n return { body: undefined, headers };\n }\n\n if (isRawBody(body)) {\n return { body, headers };\n }\n\n if (!hasHeader(headers, \"content-type\")) {\n headers[\"Content-Type\"] = JSON_CONTENT_TYPE;\n }\n return { body: JSON.stringify(body), headers };\n}\n\nexport type TimeoutSignal = {\n signal: AbortSignal | undefined;\n cleanup: () => void;\n};\n\n/**\n * Builds an abort signal for request timeouts using `AbortController`.\n *\n * `AbortSignal.timeout` is intentionally avoided because React Native/Hermes\n * does not reliably provide that static helper.\n */\nexport function buildSignal(args: {\n timeoutMs: number | undefined;\n}): TimeoutSignal {\n const { timeoutMs } = args;\n\n if (!timeoutMs || timeoutMs <= 0) {\n return {\n signal: undefined,\n cleanup: () => {},\n };\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, timeoutMs);\n\n return {\n signal: controller.signal,\n cleanup: () => clearTimeout(timeoutId),\n };\n}\n\n/**\n * Parses the response body according to the requested {@link DmkResponseType}.\n * Empty JSON bodies resolve to `undefined`; malformed JSON throws a\n * {@link DmkNetworkClientError}.\n */\nexport async function parseBody(\n response: Response,\n responseType: DmkResponseType,\n): Promise<unknown> {\n switch (responseType) {\n case \"void\":\n return undefined;\n case \"text\":\n return await response.text();\n case \"blob\":\n return await response.blob();\n case \"arrayBuffer\":\n return await response.arrayBuffer();\n case \"json\":\n default: {\n const text = await response.text();\n if (text.length === 0) {\n return undefined;\n }\n try {\n return JSON.parse(text);\n } catch (cause) {\n throw new DmkNetworkClientError({\n message: \"Failed to parse JSON response body\",\n status: response.status,\n statusText: response.statusText,\n responseBody: text,\n cause,\n });\n }\n }\n }\n}\n\n/**\n * Reads the response body as text, swallowing any error so callers can use it\n * for best-effort diagnostics (e.g. building an error payload).\n */\nexport async function safeReadText(\n response: Response,\n): Promise<string | undefined> {\n try {\n return await response.text();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Wraps a `fetch` rejection into a typed {@link DmkNetworkClientError},\n * discriminating between request timeouts and generic failures.\n */\nexport function wrapFetchError(args: {\n cause: unknown;\n timeoutMs: number | undefined;\n}): DmkNetworkClientError {\n const { cause, timeoutMs } = args;\n const hasTimeout = Boolean(timeoutMs && timeoutMs > 0);\n const isAbortError =\n cause instanceof Error &&\n (cause.name === \"AbortError\" || cause.name === \"TimeoutError\");\n\n if (isAbortError) {\n const timedOut = cause.name === \"TimeoutError\" || hasTimeout;\n return new DmkNetworkClientError({\n message: timedOut ? `Request timed out` : \"Request aborted\",\n isTimeout: timedOut,\n cause,\n });\n }\n\n return new DmkNetworkClientError({\n message: cause instanceof Error ? cause.message : \"Network request failed\",\n cause,\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["DmkNetworkClientError", "JSON_CONTENT_TYPE", "joinPath", "base", "path", "trimmedBase", "trimmedPath", "serializeParams", "params", "parts", "key", "value", "buildUrl", "args", "url", "baseUrl", "composed", "query", "separator", "hasHeader", "headers", "name", "lower", "k", "isRawBody", "body", "buildBodyAndHeaders", "method", "defaultHeaders", "perRequestHeaders", "buildSignal", "timeoutMs", "controller", "timeoutId", "parseBody", "response", "responseType", "text", "cause", "safeReadText", "wrapFetchError", "hasTimeout", "timedOut"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{DmkNetworkClientError as u}from"./DmkNetworkClientError";import{buildBodyAndHeaders as i,buildSignal as l,buildUrl as a,hasHeader as d,isRawBody as o,joinPath as p,JSON_CONTENT_TYPE as m,parseBody as r,safeReadText as h,wrapFetchError as c}from"./DmkNetworkClientHelpers";describe("DmkNetworkClientHelpers",()=>{describe("joinPath",()=>{it("should return the base when the path is empty",()=>{expect(p("https://api.example.com","")).toBe("https://api.example.com")}),it("should insert a single slash when neither side has one",()=>{expect(p("https://api.example.com","items")).toBe("https://api.example.com/items")}),it("should collapse a trailing base slash with a leading path slash",()=>{expect(p("https://api.example.com/","/items")).toBe("https://api.example.com/items")}),it("should keep a single slash when only one side has one",()=>{expect(p("https://api.example.com/","items")).toBe("https://api.example.com/items"),expect(p("https://api.example.com","/items")).toBe("https://api.example.com/items")})}),describe("buildUrl",()=>{it("should keep an absolute URL as-is",()=>{const e=a({url:"https://api.example.com/items"});expect(e).toBe("https://api.example.com/items")}),it("should prepend the base URL to a relative path",()=>{const e=a({url:"/items",baseUrl:"https://api.example.com/"});expect(e).toBe("https://api.example.com/items")}),it("should ignore the base URL when the input URL is absolute",()=>{const e=a({url:"https://other.example.com/items",baseUrl:"https://api.example.com"});expect(e).toBe("https://other.example.com/items")}),it("should append query params and skip null/undefined entries",()=>{const e=a({url:"https://api.example.com/items",params:{chain:1,contract:"0xabc",active:!0,skip:null,alsoSkip:void 0}});expect(typeof e).toBe("string");const t=new URL(e);expect(t.searchParams.get("chain")).toBe("1"),expect(t.searchParams.get("contract")).toBe("0xabc"),expect(t.searchParams.get("active")).toBe("true"),expect(t.searchParams.has("skip")).toBe(!1),expect(t.searchParams.has("alsoSkip")).toBe(!1)}),it("should preserve a pre-existing query string in the input URL",()=>{const e=a({url:"https://api.example.com/items?keep=1",params:{chain:2}}),t=new URL(e);expect(t.searchParams.get("keep")).toBe("1"),expect(t.searchParams.get("chain")).toBe("2")}),it("should percent-encode keys and values",()=>{const e=a({url:"https://api.example.com/items",params:{"a key":"a value&b"}});expect(e).toBe("https://api.example.com/items?a%20key=a%20value%26b")}),it("should not append a trailing slash after the last query value (facebook/react-native#54242)",()=>{const e=a({url:"https://manager.api.live.ledger.com/api/get_device_version",params:{target_id:858783748,provider:1}});expect(typeof e).toBe("string"),expect(e).toBe("https://manager.api.live.ledger.com/api/get_device_version?target_id=858783748&provider=1"),expect(e.endsWith("/")).toBe(!1)}),it("should return a plain string (not a URL instance) so RN URL serialization is bypassed",()=>{const e=a({url:"https://api.example.com/items",params:{chain:1}});expect(typeof e).toBe("string"),expect(e).not.toBeInstanceOf(URL)}),it("should still build the URL when URLSearchParams.set is unavailable (React Native regression)",()=>{const e=URLSearchParams.prototype.set;URLSearchParams.prototype.set=function(){throw new Error("URLSearchParams.set is not implemented")};try{const t=a({url:"https://api.example.com/items",params:{chain:1,contract:"0xabc"}});expect(t).toContain("chain=1"),expect(t).toContain("contract=0xabc")}finally{URLSearchParams.prototype.set=e}})}),describe("hasHeader",()=>{it("should find a header regardless of case",()=>{expect(d({"Content-Type":"json"},"content-type")).toBe(!0),expect(d({"content-type":"json"},"Content-Type")).toBe(!0)}),it("should return false when no matching header exists",()=>{expect(d({Accept:"json"},"content-type")).toBe(!1),expect(d({},"content-type")).toBe(!1)})}),describe("isRawBody",()=>{it("should accept native BodyInit values",()=>{expect(o("raw-string")).toBe(!0),expect(o(new ArrayBuffer(4))).toBe(!0),expect(o(new Uint8Array([1,2,3]))).toBe(!0),expect(o(new Blob(["a"]))).toBe(!0),expect(o(new FormData)).toBe(!0),expect(o(new URLSearchParams({a:"1"}))).toBe(!0),expect(o(new ReadableStream)).toBe(!0)}),it("should reject plain objects and primitives",()=>{expect(o({foo:"bar"})).toBe(!1),expect(o([1,2,3])).toBe(!1),expect(o(42)).toBe(!1),expect(o(null)).toBe(!1),expect(o(void 0)).toBe(!1)}),it("should not throw when optional Web globals are missing (React Native regression)",()=>{const e=globalThis,t=["Blob","FormData","URLSearchParams","ReadableStream"],s={};for(const n of t)s[n]=e[n],delete e[n];try{expect(()=>o({foo:"bar"})).not.toThrow(),expect(o({foo:"bar"})).toBe(!1),expect(o("raw")).toBe(!0),expect(o(new Uint8Array([1]))).toBe(!0)}finally{for(const n of t)e[n]=s[n]}})}),describe("buildBodyAndHeaders",()=>{it("should merge default and per-request headers with per-request winning",()=>{const{headers:e}=i({method:"GET",body:void 0,defaultHeaders:{"X-Default":"default","X-Shared":"from-default"},perRequestHeaders:{"X-Shared":"overridden","X-Per":"per"}});expect(e).toEqual({"X-Default":"default","X-Shared":"overridden","X-Per":"per"})}),it("should not emit a body on GET/HEAD even when a body is provided",()=>{const e=i({method:"GET",body:{foo:"bar"},defaultHeaders:{}});expect(e.body).toBeUndefined(),expect(e.headers["Content-Type"]).toBeUndefined()}),it("should JSON-stringify plain objects and set the Content-Type",()=>{const e=i({method:"POST",body:{foo:"bar"},defaultHeaders:{}});expect(e.body).toBe(JSON.stringify({foo:"bar"})),expect(e.headers["Content-Type"]).toBe(m)}),it("should not override an explicit Content-Type header",()=>{const e=i({method:"POST",body:{foo:"bar"},defaultHeaders:{},perRequestHeaders:{"content-type":"application/vnd.custom+json"}});expect(e.body).toBe(JSON.stringify({foo:"bar"})),expect(e.headers["content-type"]).toBe("application/vnd.custom+json"),expect(e.headers["Content-Type"]).toBeUndefined()}),it("should pass raw BodyInit values through unchanged without JSON headers",()=>{const e=new FormData;e.set("field","value");const t=i({method:"POST",body:e,defaultHeaders:{}});expect(t.body).toBe(e),expect(t.headers["Content-Type"]).toBeUndefined()}),it("should return an undefined body when the body itself is undefined",()=>{const e=i({method:"POST",body:void 0,defaultHeaders:{"X-Default":"d"}});expect(e.body).toBeUndefined(),expect(e.headers).toEqual({"X-Default":"d"})})}),describe("buildSignal",()=>{it("should return undefined when no timeout and no external signal",()=>{expect(l({timeoutMs:void 0,externalSignal:void 0})).toBeUndefined()}),it("should return undefined when timeout is zero and no external signal",()=>{expect(l({timeoutMs:0,externalSignal:void 0})).toBeUndefined()}),it("should return the external signal alone when no timeout is configured",()=>{const e=new AbortController,t=l({timeoutMs:void 0,externalSignal:e.signal});expect(t).toBe(e.signal)}),it("should return a timeout signal when only a timeout is configured",()=>{const e=l({timeoutMs:1e3,externalSignal:void 0});expect(e).toBeInstanceOf(AbortSignal)}),it("should use the provided timeout value for AbortSignal.timeout",()=>{const e=vi.spyOn(AbortSignal,"timeout");l({timeoutMs:50,externalSignal:void 0}),expect(e).toHaveBeenCalledWith(50),e.mockRestore()}),it("should compose both signals with AbortSignal.any when both are set",()=>{const e=vi.spyOn(AbortSignal,"any"),t=new AbortController,s=l({timeoutMs:100,externalSignal:t.signal});expect(s).toBeInstanceOf(AbortSignal),expect(e).toHaveBeenCalledTimes(1),e.mockRestore()})}),describe("parseBody",()=>{it("should return undefined for 'void' response type without consuming the body",async()=>{const e=new Response("ignored"),t=await r(e,"void");expect(t).toBeUndefined(),expect(e.bodyUsed).toBe(!1)}),it("should return text for 'text' response type",async()=>{const e=new Response("plain-body");await expect(r(e,"text")).resolves.toBe("plain-body")}),it("should return a Blob for 'blob' response type",async()=>{const e=new Response("blob-body"),t=await r(e,"blob");expect(t).toBeInstanceOf(Blob)}),it("should return an ArrayBuffer for 'arrayBuffer' response type",async()=>{const e=new Response(new Uint8Array([1,2,3])),t=await r(e,"arrayBuffer");expect(t).toBeInstanceOf(ArrayBuffer),expect(new Uint8Array(t)).toEqual(new Uint8Array([1,2,3]))}),it("should parse JSON for 'json' response type",async()=>{const e=new Response(JSON.stringify({hello:"world"}));await expect(r(e,"json")).resolves.toEqual({hello:"world"})}),it("should resolve to undefined for an empty JSON body",async()=>{const e=new Response("");await expect(r(e,"json")).resolves.toBeUndefined()}),it("should throw a DmkNetworkClientError for malformed JSON",async()=>{const e=new Response("not-json",{status:200,statusText:"OK"}),t=await r(e,"json").catch(n=>n);expect(t).toBeInstanceOf(u);const s=t;expect(s.status).toBe(200),expect(s.statusText).toBe("OK"),expect(s.responseBody).toBe("not-json"),expect(s.cause).toBeInstanceOf(SyntaxError)})}),describe("safeReadText",()=>{it("should return the text body",async()=>{await expect(h(new Response("hello"))).resolves.toBe("hello")}),it("should return undefined when reading the body throws",async()=>{const e={text:()=>Promise.reject(new Error("read failed"))};await expect(h(e)).resolves.toBeUndefined()})}),describe("wrapFetchError",()=>{it("should wrap a generic Error with its message",()=>{const e=new TypeError("network down"),t=c({cause:e,externalSignal:void 0,timeoutMs:void 0});expect(t).toBeInstanceOf(u),expect(t.message).toBe("network down"),expect(t.cause).toBe(e),expect(t.isTimeout).toBe(!1),expect(t.isAbort).toBe(!1)}),it("should fall back to a generic message for non-Error causes",()=>{const e=c({cause:"something",externalSignal:void 0,timeoutMs:void 0});expect(e.message).toBe("Network request failed"),expect(e.cause).toBe("something")}),it("should flag TimeoutError as a timeout",()=>{const e=new Error("timed out");e.name="TimeoutError";const t=c({cause:e,externalSignal:void 0,timeoutMs:10});expect(t.isTimeout).toBe(!0),expect(t.isAbort).toBe(!1),expect(t.message).toBe("Request timed out")}),it("should flag AbortError as a timeout when a timeout is configured and no external abort",()=>{const e=new Error("aborted");e.name="AbortError";const t=c({cause:e,externalSignal:void 0,timeoutMs:1e3});expect(t.isTimeout).toBe(!0),expect(t.isAbort).toBe(!1)}),it("should flag AbortError as an external abort when the caller signal is aborted",()=>{const e=new AbortController;e.abort();const t=new Error("aborted");t.name="AbortError";const s=c({cause:t,externalSignal:e.signal,timeoutMs:void 0});expect(s.isAbort).toBe(!0),expect(s.isTimeout).toBe(!1),expect(s.message).toBe("Request aborted")}),it("should treat AbortError with no timeout and no external abort as a plain abort",()=>{const e=new Error("aborted");e.name="AbortError";const t=c({cause:e,externalSignal:void 0,timeoutMs:void 0});expect(t.isTimeout).toBe(!1),expect(t.isAbort).toBe(!1),expect(t.message).toBe("Request aborted")})})});
|
|
1
|
+
import{DmkNetworkClientError as u}from"./DmkNetworkClientError";import{buildBodyAndHeaders as i,buildSignal as p,buildUrl as s,hasHeader as d,isRawBody as o,joinPath as c,JSON_CONTENT_TYPE as h,parseBody as r,safeReadText as m,wrapFetchError as l}from"./DmkNetworkClientHelpers";describe("DmkNetworkClientHelpers",()=>{describe("joinPath",()=>{it("should return the base when the path is empty",()=>{expect(c("https://api.example.com","")).toBe("https://api.example.com")}),it("should insert a single slash when neither side has one",()=>{expect(c("https://api.example.com","items")).toBe("https://api.example.com/items")}),it("should collapse a trailing base slash with a leading path slash",()=>{expect(c("https://api.example.com/","/items")).toBe("https://api.example.com/items")}),it("should keep a single slash when only one side has one",()=>{expect(c("https://api.example.com/","items")).toBe("https://api.example.com/items"),expect(c("https://api.example.com","/items")).toBe("https://api.example.com/items")})}),describe("buildUrl",()=>{it("should keep an absolute URL as-is",()=>{const e=s({url:"https://api.example.com/items"});expect(e).toBe("https://api.example.com/items")}),it("should prepend the base URL to a relative path",()=>{const e=s({url:"/items",baseUrl:"https://api.example.com/"});expect(e).toBe("https://api.example.com/items")}),it("should ignore the base URL when the input URL is absolute",()=>{const e=s({url:"https://other.example.com/items",baseUrl:"https://api.example.com"});expect(e).toBe("https://other.example.com/items")}),it("should append query params and skip null/undefined entries",()=>{const e=s({url:"https://api.example.com/items",params:{chain:1,contract:"0xabc",active:!0,skip:null,alsoSkip:void 0}});expect(typeof e).toBe("string");const t=new URL(e);expect(t.searchParams.get("chain")).toBe("1"),expect(t.searchParams.get("contract")).toBe("0xabc"),expect(t.searchParams.get("active")).toBe("true"),expect(t.searchParams.has("skip")).toBe(!1),expect(t.searchParams.has("alsoSkip")).toBe(!1)}),it("should preserve a pre-existing query string in the input URL",()=>{const e=s({url:"https://api.example.com/items?keep=1",params:{chain:2}}),t=new URL(e);expect(t.searchParams.get("keep")).toBe("1"),expect(t.searchParams.get("chain")).toBe("2")}),it("should percent-encode keys and values",()=>{const e=s({url:"https://api.example.com/items",params:{"a key":"a value&b"}});expect(e).toBe("https://api.example.com/items?a%20key=a%20value%26b")}),it("should not append a trailing slash after the last query value (facebook/react-native#54242)",()=>{const e=s({url:"https://manager.api.live.ledger.com/api/get_device_version",params:{target_id:858783748,provider:1}});expect(typeof e).toBe("string"),expect(e).toBe("https://manager.api.live.ledger.com/api/get_device_version?target_id=858783748&provider=1"),expect(e.endsWith("/")).toBe(!1)}),it("should return a plain string (not a URL instance) so RN URL serialization is bypassed",()=>{const e=s({url:"https://api.example.com/items",params:{chain:1}});expect(typeof e).toBe("string"),expect(e).not.toBeInstanceOf(URL)}),it("should still build the URL when URLSearchParams.set is unavailable (React Native regression)",()=>{const e=URLSearchParams.prototype.set;URLSearchParams.prototype.set=function(){throw new Error("URLSearchParams.set is not implemented")};try{const t=s({url:"https://api.example.com/items",params:{chain:1,contract:"0xabc"}});expect(t).toContain("chain=1"),expect(t).toContain("contract=0xabc")}finally{URLSearchParams.prototype.set=e}})}),describe("hasHeader",()=>{it("should find a header regardless of case",()=>{expect(d({"Content-Type":"json"},"content-type")).toBe(!0),expect(d({"content-type":"json"},"Content-Type")).toBe(!0)}),it("should return false when no matching header exists",()=>{expect(d({Accept:"json"},"content-type")).toBe(!1),expect(d({},"content-type")).toBe(!1)})}),describe("isRawBody",()=>{it("should accept native BodyInit values",()=>{expect(o("raw-string")).toBe(!0),expect(o(new ArrayBuffer(4))).toBe(!0),expect(o(new Uint8Array([1,2,3]))).toBe(!0),expect(o(new Blob(["a"]))).toBe(!0),expect(o(new FormData)).toBe(!0),expect(o(new URLSearchParams({a:"1"}))).toBe(!0),expect(o(new ReadableStream)).toBe(!0)}),it("should reject plain objects and primitives",()=>{expect(o({foo:"bar"})).toBe(!1),expect(o([1,2,3])).toBe(!1),expect(o(42)).toBe(!1),expect(o(null)).toBe(!1),expect(o(void 0)).toBe(!1)}),it("should not throw when optional Web globals are missing (React Native regression)",()=>{const e=globalThis,t=["Blob","FormData","URLSearchParams","ReadableStream"],n={};for(const a of t)n[a]=e[a],delete e[a];try{expect(()=>o({foo:"bar"})).not.toThrow(),expect(o({foo:"bar"})).toBe(!1),expect(o("raw")).toBe(!0),expect(o(new Uint8Array([1]))).toBe(!0)}finally{for(const a of t)e[a]=n[a]}})}),describe("buildBodyAndHeaders",()=>{it("should merge default and per-request headers with per-request winning",()=>{const{headers:e}=i({method:"GET",body:void 0,defaultHeaders:{"X-Default":"default","X-Shared":"from-default"},perRequestHeaders:{"X-Shared":"overridden","X-Per":"per"}});expect(e).toEqual({"X-Default":"default","X-Shared":"overridden","X-Per":"per"})}),it("should not emit a body on GET/HEAD even when a body is provided",()=>{const e=i({method:"GET",body:{foo:"bar"},defaultHeaders:{}});expect(e.body).toBeUndefined(),expect(e.headers["Content-Type"]).toBeUndefined()}),it("should JSON-stringify plain objects and set the Content-Type",()=>{const e=i({method:"POST",body:{foo:"bar"},defaultHeaders:{}});expect(e.body).toBe(JSON.stringify({foo:"bar"})),expect(e.headers["Content-Type"]).toBe(h)}),it("should not override an explicit Content-Type header",()=>{const e=i({method:"POST",body:{foo:"bar"},defaultHeaders:{},perRequestHeaders:{"content-type":"application/vnd.custom+json"}});expect(e.body).toBe(JSON.stringify({foo:"bar"})),expect(e.headers["content-type"]).toBe("application/vnd.custom+json"),expect(e.headers["Content-Type"]).toBeUndefined()}),it("should pass raw BodyInit values through unchanged without JSON headers",()=>{const e=new FormData;e.set("field","value");const t=i({method:"POST",body:e,defaultHeaders:{}});expect(t.body).toBe(e),expect(t.headers["Content-Type"]).toBeUndefined()}),it("should return an undefined body when the body itself is undefined",()=>{const e=i({method:"POST",body:void 0,defaultHeaders:{"X-Default":"d"}});expect(e.body).toBeUndefined(),expect(e.headers).toEqual({"X-Default":"d"})})}),describe("buildSignal",()=>{afterEach(()=>{vi.useRealTimers()}),it("GIVEN no timeout WHEN building a signal THEN it returns no signal",()=>{const e=p({timeoutMs:void 0});expect(e.signal).toBeUndefined(),expect(e.cleanup).toEqual(expect.any(Function))}),it("GIVEN a zero timeout WHEN building a signal THEN it returns no signal",()=>{const e=p({timeoutMs:0});expect(e.signal).toBeUndefined(),expect(e.cleanup).toEqual(expect.any(Function))}),it("GIVEN a negative timeout WHEN building a signal THEN it returns no signal",()=>{const e=p({timeoutMs:-1});expect(e.signal).toBeUndefined(),expect(e.cleanup).toEqual(expect.any(Function))}),it("GIVEN a positive timeout WHEN building a signal THEN it returns an AbortSignal",()=>{const{signal:e,cleanup:t}=p({timeoutMs:1e3});expect(e).toBeInstanceOf(AbortSignal),expect(e?.aborted).toBe(!1),t()}),it("GIVEN a positive timeout WHEN the delay elapses THEN it aborts the signal",()=>{vi.useFakeTimers();const{signal:e,cleanup:t}=p({timeoutMs:1e3});expect(e?.aborted).toBe(!1),vi.advanceTimersByTime(999),expect(e?.aborted).toBe(!1),vi.advanceTimersByTime(1),expect(e?.aborted).toBe(!0),t()}),it("GIVEN a timeout signal WHEN cleanup runs before the delay THEN it does not abort",()=>{vi.useFakeTimers();const{signal:e,cleanup:t}=p({timeoutMs:100});t(),vi.advanceTimersByTime(100),expect(e?.aborted).toBe(!1)})}),describe("parseBody",()=>{it("should return undefined for 'void' response type without consuming the body",async()=>{const e=new Response("ignored"),t=await r(e,"void");expect(t).toBeUndefined(),expect(e.bodyUsed).toBe(!1)}),it("should return text for 'text' response type",async()=>{const e=new Response("plain-body");await expect(r(e,"text")).resolves.toBe("plain-body")}),it("should return a Blob for 'blob' response type",async()=>{const e=new Response("blob-body"),t=await r(e,"blob");expect(t).toBeInstanceOf(Blob)}),it("should return an ArrayBuffer for 'arrayBuffer' response type",async()=>{const e=new Response(new Uint8Array([1,2,3])),t=await r(e,"arrayBuffer");expect(t).toBeInstanceOf(ArrayBuffer),expect(new Uint8Array(t)).toEqual(new Uint8Array([1,2,3]))}),it("should parse JSON for 'json' response type",async()=>{const e=new Response(JSON.stringify({hello:"world"}));await expect(r(e,"json")).resolves.toEqual({hello:"world"})}),it("should resolve to undefined for an empty JSON body",async()=>{const e=new Response("");await expect(r(e,"json")).resolves.toBeUndefined()}),it("should throw a DmkNetworkClientError for malformed JSON",async()=>{const e=new Response("not-json",{status:200,statusText:"OK"}),t=await r(e,"json").catch(a=>a);expect(t).toBeInstanceOf(u);const n=t;expect(n.status).toBe(200),expect(n.statusText).toBe("OK"),expect(n.responseBody).toBe("not-json"),expect(n.cause).toBeInstanceOf(SyntaxError)})}),describe("safeReadText",()=>{it("should return the text body",async()=>{await expect(m(new Response("hello"))).resolves.toBe("hello")}),it("should return undefined when reading the body throws",async()=>{const e={text:()=>Promise.reject(new Error("read failed"))};await expect(m(e)).resolves.toBeUndefined()})}),describe("wrapFetchError",()=>{it("should wrap a generic Error with its message",()=>{const e=new TypeError("network down"),t=l({cause:e,timeoutMs:void 0});expect(t).toBeInstanceOf(u),expect(t.message).toBe("network down"),expect(t.cause).toBe(e),expect(t.isTimeout).toBe(!1)}),it("should fall back to a generic message for non-Error causes",()=>{const e=l({cause:"something",timeoutMs:void 0});expect(e.message).toBe("Network request failed"),expect(e.cause).toBe("something")}),it("should flag TimeoutError as a timeout",()=>{const e=new Error("timed out");e.name="TimeoutError";const t=l({cause:e,timeoutMs:10});expect(t.isTimeout).toBe(!0),expect(t.message).toBe("Request timed out")}),it("should flag AbortError as a timeout when a timeout is configured and no external abort",()=>{const e=new Error("aborted");e.name="AbortError";const t=l({cause:e,timeoutMs:1e3});expect(t.isTimeout).toBe(!0)}),it("should treat AbortError with no timeout and no external abort as a plain abort",()=>{const e=new Error("aborted");e.name="AbortError";const t=l({cause:e,timeoutMs:void 0});expect(t.isTimeout).toBe(!1),expect(t.message).toBe("Request aborted")})})});
|
|
2
2
|
//# sourceMappingURL=DmkNetworkClientHelpers.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/api/network/DmkNetworkClientHelpers.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { DmkNetworkClientError } from \"./DmkNetworkClientError\";\nimport {\n buildBodyAndHeaders,\n buildSignal,\n buildUrl,\n hasHeader,\n isRawBody,\n joinPath,\n JSON_CONTENT_TYPE,\n parseBody,\n safeReadText,\n wrapFetchError,\n} from \"./DmkNetworkClientHelpers\";\n\ndescribe(\"DmkNetworkClientHelpers\", () => {\n describe(\"joinPath\", () => {\n it(\"should return the base when the path is empty\", () => {\n expect(joinPath(\"https://api.example.com\", \"\")).toBe(\n \"https://api.example.com\",\n );\n });\n\n it(\"should insert a single slash when neither side has one\", () => {\n expect(joinPath(\"https://api.example.com\", \"items\")).toBe(\n \"https://api.example.com/items\",\n );\n });\n\n it(\"should collapse a trailing base slash with a leading path slash\", () => {\n expect(joinPath(\"https://api.example.com/\", \"/items\")).toBe(\n \"https://api.example.com/items\",\n );\n });\n\n it(\"should keep a single slash when only one side has one\", () => {\n expect(joinPath(\"https://api.example.com/\", \"items\")).toBe(\n \"https://api.example.com/items\",\n );\n expect(joinPath(\"https://api.example.com\", \"/items\")).toBe(\n \"https://api.example.com/items\",\n );\n });\n });\n\n describe(\"buildUrl\", () => {\n it(\"should keep an absolute URL as-is\", () => {\n const url = buildUrl({ url: \"https://api.example.com/items\" });\n expect(url).toBe(\"https://api.example.com/items\");\n });\n\n it(\"should prepend the base URL to a relative path\", () => {\n const url = buildUrl({\n url: \"/items\",\n baseUrl: \"https://api.example.com/\",\n });\n expect(url).toBe(\"https://api.example.com/items\");\n });\n\n it(\"should ignore the base URL when the input URL is absolute\", () => {\n const url = buildUrl({\n url: \"https://other.example.com/items\",\n baseUrl: \"https://api.example.com\",\n });\n expect(url).toBe(\"https://other.example.com/items\");\n });\n\n it(\"should append query params and skip null/undefined entries\", () => {\n const url = buildUrl({\n url: \"https://api.example.com/items\",\n params: {\n chain: 1,\n contract: \"0xabc\",\n active: true,\n skip: null,\n alsoSkip: undefined,\n },\n });\n expect(typeof url).toBe(\"string\");\n const parsed = new URL(url);\n expect(parsed.searchParams.get(\"chain\")).toBe(\"1\");\n expect(parsed.searchParams.get(\"contract\")).toBe(\"0xabc\");\n expect(parsed.searchParams.get(\"active\")).toBe(\"true\");\n expect(parsed.searchParams.has(\"skip\")).toBe(false);\n expect(parsed.searchParams.has(\"alsoSkip\")).toBe(false);\n });\n\n it(\"should preserve a pre-existing query string in the input URL\", () => {\n const url = buildUrl({\n url: \"https://api.example.com/items?keep=1\",\n params: { chain: 2 },\n });\n const parsed = new URL(url);\n expect(parsed.searchParams.get(\"keep\")).toBe(\"1\");\n expect(parsed.searchParams.get(\"chain\")).toBe(\"2\");\n });\n\n it(\"should percent-encode keys and values\", () => {\n const url = buildUrl({\n url: \"https://api.example.com/items\",\n params: { \"a key\": \"a value&b\" },\n });\n expect(url).toBe(\"https://api.example.com/items?a%20key=a%20value%26b\");\n });\n\n it(\"should not append a trailing slash after the last query value (facebook/react-native#54242)\", () => {\n const url = buildUrl({\n url: \"https://manager.api.live.ledger.com/api/get_device_version\",\n params: { target_id: 858783748, provider: 1 },\n });\n expect(typeof url).toBe(\"string\");\n expect(url).toBe(\n \"https://manager.api.live.ledger.com/api/get_device_version?target_id=858783748&provider=1\",\n );\n expect(url.endsWith(\"/\")).toBe(false);\n });\n\n it(\"should return a plain string (not a URL instance) so RN URL serialization is bypassed\", () => {\n const url = buildUrl({\n url: \"https://api.example.com/items\",\n params: { chain: 1 },\n });\n expect(typeof url).toBe(\"string\");\n expect(url).not.toBeInstanceOf(URL);\n });\n\n it(\"should still build the URL when URLSearchParams.set is unavailable (React Native regression)\", () => {\n const original = URLSearchParams.prototype.set;\n URLSearchParams.prototype.set = function notImplemented(): never {\n throw new Error(\"URLSearchParams.set is not implemented\");\n };\n try {\n const url = buildUrl({\n url: \"https://api.example.com/items\",\n params: { chain: 1, contract: \"0xabc\" },\n });\n expect(url).toContain(\"chain=1\");\n expect(url).toContain(\"contract=0xabc\");\n } finally {\n URLSearchParams.prototype.set = original;\n }\n });\n });\n\n describe(\"hasHeader\", () => {\n it(\"should find a header regardless of case\", () => {\n expect(hasHeader({ \"Content-Type\": \"json\" }, \"content-type\")).toBe(true);\n expect(hasHeader({ \"content-type\": \"json\" }, \"Content-Type\")).toBe(true);\n });\n\n it(\"should return false when no matching header exists\", () => {\n expect(hasHeader({ Accept: \"json\" }, \"content-type\")).toBe(false);\n expect(hasHeader({}, \"content-type\")).toBe(false);\n });\n });\n\n describe(\"isRawBody\", () => {\n it(\"should accept native BodyInit values\", () => {\n expect(isRawBody(\"raw-string\")).toBe(true);\n expect(isRawBody(new ArrayBuffer(4))).toBe(true);\n expect(isRawBody(new Uint8Array([1, 2, 3]))).toBe(true);\n expect(isRawBody(new Blob([\"a\"]))).toBe(true);\n expect(isRawBody(new FormData())).toBe(true);\n expect(isRawBody(new URLSearchParams({ a: \"1\" }))).toBe(true);\n expect(isRawBody(new ReadableStream())).toBe(true);\n });\n\n it(\"should reject plain objects and primitives\", () => {\n expect(isRawBody({ foo: \"bar\" })).toBe(false);\n expect(isRawBody([1, 2, 3])).toBe(false);\n expect(isRawBody(42)).toBe(false);\n expect(isRawBody(null)).toBe(false);\n expect(isRawBody(undefined)).toBe(false);\n });\n\n it(\"should not throw when optional Web globals are missing (React Native regression)\", () => {\n const globals = globalThis as unknown as Record<string, unknown>;\n const names = [\"Blob\", \"FormData\", \"URLSearchParams\", \"ReadableStream\"];\n const saved: Record<string, unknown> = {};\n for (const name of names) {\n saved[name] = globals[name];\n delete globals[name];\n }\n try {\n expect(() => isRawBody({ foo: \"bar\" })).not.toThrow();\n expect(isRawBody({ foo: \"bar\" })).toBe(false);\n expect(isRawBody(\"raw\")).toBe(true);\n expect(isRawBody(new Uint8Array([1]))).toBe(true);\n } finally {\n for (const name of names) {\n globals[name] = saved[name];\n }\n }\n });\n });\n\n describe(\"buildBodyAndHeaders\", () => {\n it(\"should merge default and per-request headers with per-request winning\", () => {\n const { headers } = buildBodyAndHeaders({\n method: \"GET\",\n body: undefined,\n defaultHeaders: { \"X-Default\": \"default\", \"X-Shared\": \"from-default\" },\n perRequestHeaders: { \"X-Shared\": \"overridden\", \"X-Per\": \"per\" },\n });\n expect(headers).toEqual({\n \"X-Default\": \"default\",\n \"X-Shared\": \"overridden\",\n \"X-Per\": \"per\",\n });\n });\n\n it(\"should not emit a body on GET/HEAD even when a body is provided\", () => {\n const result = buildBodyAndHeaders({\n method: \"GET\",\n body: { foo: \"bar\" },\n defaultHeaders: {},\n });\n expect(result.body).toBeUndefined();\n expect(result.headers[\"Content-Type\"]).toBeUndefined();\n });\n\n it(\"should JSON-stringify plain objects and set the Content-Type\", () => {\n const result = buildBodyAndHeaders({\n method: \"POST\",\n body: { foo: \"bar\" },\n defaultHeaders: {},\n });\n expect(result.body).toBe(JSON.stringify({ foo: \"bar\" }));\n expect(result.headers[\"Content-Type\"]).toBe(JSON_CONTENT_TYPE);\n });\n\n it(\"should not override an explicit Content-Type header\", () => {\n const result = buildBodyAndHeaders({\n method: \"POST\",\n body: { foo: \"bar\" },\n defaultHeaders: {},\n perRequestHeaders: { \"content-type\": \"application/vnd.custom+json\" },\n });\n expect(result.body).toBe(JSON.stringify({ foo: \"bar\" }));\n expect(result.headers[\"content-type\"]).toBe(\n \"application/vnd.custom+json\",\n );\n expect(result.headers[\"Content-Type\"]).toBeUndefined();\n });\n\n it(\"should pass raw BodyInit values through unchanged without JSON headers\", () => {\n const formData = new FormData();\n formData.set(\"field\", \"value\");\n const result = buildBodyAndHeaders({\n method: \"POST\",\n body: formData,\n defaultHeaders: {},\n });\n expect(result.body).toBe(formData);\n expect(result.headers[\"Content-Type\"]).toBeUndefined();\n });\n\n it(\"should return an undefined body when the body itself is undefined\", () => {\n const result = buildBodyAndHeaders({\n method: \"POST\",\n body: undefined,\n defaultHeaders: { \"X-Default\": \"d\" },\n });\n expect(result.body).toBeUndefined();\n expect(result.headers).toEqual({ \"X-Default\": \"d\" });\n });\n });\n\n describe(\"buildSignal\", () => {\n it(\"should return undefined when no timeout and no external signal\", () => {\n expect(\n buildSignal({\n timeoutMs: undefined,\n externalSignal: undefined,\n }),\n ).toBeUndefined();\n });\n\n it(\"should return undefined when timeout is zero and no external signal\", () => {\n expect(\n buildSignal({\n timeoutMs: 0,\n externalSignal: undefined,\n }),\n ).toBeUndefined();\n });\n\n it(\"should return the external signal alone when no timeout is configured\", () => {\n const controller = new AbortController();\n const signal = buildSignal({\n timeoutMs: undefined,\n externalSignal: controller.signal,\n });\n expect(signal).toBe(controller.signal);\n });\n\n it(\"should return a timeout signal when only a timeout is configured\", () => {\n const signal = buildSignal({\n timeoutMs: 1000,\n externalSignal: undefined,\n });\n expect(signal).toBeInstanceOf(AbortSignal);\n });\n\n it(\"should use the provided timeout value for AbortSignal.timeout\", () => {\n const timeoutSpy = vi.spyOn(AbortSignal, \"timeout\");\n buildSignal({\n timeoutMs: 50,\n externalSignal: undefined,\n });\n expect(timeoutSpy).toHaveBeenCalledWith(50);\n timeoutSpy.mockRestore();\n });\n\n it(\"should compose both signals with AbortSignal.any when both are set\", () => {\n const anySpy = vi.spyOn(AbortSignal, \"any\");\n const controller = new AbortController();\n const signal = buildSignal({\n timeoutMs: 100,\n externalSignal: controller.signal,\n });\n expect(signal).toBeInstanceOf(AbortSignal);\n expect(anySpy).toHaveBeenCalledTimes(1);\n anySpy.mockRestore();\n });\n });\n\n describe(\"parseBody\", () => {\n it(\"should return undefined for 'void' response type without consuming the body\", async () => {\n const response = new Response(\"ignored\");\n const result = await parseBody(response, \"void\");\n expect(result).toBeUndefined();\n expect(response.bodyUsed).toBe(false);\n });\n\n it(\"should return text for 'text' response type\", async () => {\n const response = new Response(\"plain-body\");\n await expect(parseBody(response, \"text\")).resolves.toBe(\"plain-body\");\n });\n\n it(\"should return a Blob for 'blob' response type\", async () => {\n const response = new Response(\"blob-body\");\n const result = await parseBody(response, \"blob\");\n expect(result).toBeInstanceOf(Blob);\n });\n\n it(\"should return an ArrayBuffer for 'arrayBuffer' response type\", async () => {\n const response = new Response(new Uint8Array([1, 2, 3]));\n const result = await parseBody(response, \"arrayBuffer\");\n expect(result).toBeInstanceOf(ArrayBuffer);\n expect(new Uint8Array(result as ArrayBuffer)).toEqual(\n new Uint8Array([1, 2, 3]),\n );\n });\n\n it(\"should parse JSON for 'json' response type\", async () => {\n const response = new Response(JSON.stringify({ hello: \"world\" }));\n await expect(parseBody(response, \"json\")).resolves.toEqual({\n hello: \"world\",\n });\n });\n\n it(\"should resolve to undefined for an empty JSON body\", async () => {\n const response = new Response(\"\");\n await expect(parseBody(response, \"json\")).resolves.toBeUndefined();\n });\n\n it(\"should throw a DmkNetworkClientError for malformed JSON\", async () => {\n const response = new Response(\"not-json\", {\n status: 200,\n statusText: \"OK\",\n });\n const error = await parseBody(response, \"json\").catch((e: unknown) => e);\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n const dmkError = error as DmkNetworkClientError;\n expect(dmkError.status).toBe(200);\n expect(dmkError.statusText).toBe(\"OK\");\n expect(dmkError.responseBody).toBe(\"not-json\");\n expect(dmkError.cause).toBeInstanceOf(SyntaxError);\n });\n });\n\n describe(\"safeReadText\", () => {\n it(\"should return the text body\", async () => {\n await expect(safeReadText(new Response(\"hello\"))).resolves.toBe(\"hello\");\n });\n\n it(\"should return undefined when reading the body throws\", async () => {\n const response = {\n text: () => Promise.reject(new Error(\"read failed\")),\n } as unknown as Response;\n await expect(safeReadText(response)).resolves.toBeUndefined();\n });\n });\n\n describe(\"wrapFetchError\", () => {\n it(\"should wrap a generic Error with its message\", () => {\n const cause = new TypeError(\"network down\");\n const error = wrapFetchError({\n cause,\n externalSignal: undefined,\n timeoutMs: undefined,\n });\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n expect(error.message).toBe(\"network down\");\n expect(error.cause).toBe(cause);\n expect(error.isTimeout).toBe(false);\n expect(error.isAbort).toBe(false);\n });\n\n it(\"should fall back to a generic message for non-Error causes\", () => {\n const error = wrapFetchError({\n cause: \"something\",\n externalSignal: undefined,\n timeoutMs: undefined,\n });\n expect(error.message).toBe(\"Network request failed\");\n expect(error.cause).toBe(\"something\");\n });\n\n it(\"should flag TimeoutError as a timeout\", () => {\n const cause = new Error(\"timed out\");\n cause.name = \"TimeoutError\";\n const error = wrapFetchError({\n cause,\n externalSignal: undefined,\n timeoutMs: 10,\n });\n expect(error.isTimeout).toBe(true);\n expect(error.isAbort).toBe(false);\n expect(error.message).toBe(\"Request timed out\");\n });\n\n it(\"should flag AbortError as a timeout when a timeout is configured and no external abort\", () => {\n const cause = new Error(\"aborted\");\n cause.name = \"AbortError\";\n const error = wrapFetchError({\n cause,\n externalSignal: undefined,\n timeoutMs: 1000,\n });\n expect(error.isTimeout).toBe(true);\n expect(error.isAbort).toBe(false);\n });\n\n it(\"should flag AbortError as an external abort when the caller signal is aborted\", () => {\n const controller = new AbortController();\n controller.abort();\n const cause = new Error(\"aborted\");\n cause.name = \"AbortError\";\n const error = wrapFetchError({\n cause,\n externalSignal: controller.signal,\n timeoutMs: undefined,\n });\n expect(error.isAbort).toBe(true);\n expect(error.isTimeout).toBe(false);\n expect(error.message).toBe(\"Request aborted\");\n });\n\n it(\"should treat AbortError with no timeout and no external abort as a plain abort\", () => {\n const cause = new Error(\"aborted\");\n cause.name = \"AbortError\";\n const error = wrapFetchError({\n cause,\n externalSignal: undefined,\n timeoutMs: undefined,\n });\n expect(error.isTimeout).toBe(false);\n expect(error.isAbort).toBe(false);\n expect(error.message).toBe(\"Request aborted\");\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "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
|
|
6
|
-
"names": ["DmkNetworkClientError", "buildBodyAndHeaders", "buildSignal", "buildUrl", "hasHeader", "isRawBody", "joinPath", "JSON_CONTENT_TYPE", "parseBody", "safeReadText", "wrapFetchError", "url", "parsed", "original", "globals", "names", "saved", "name", "headers", "result", "formData", "
|
|
4
|
+
"sourcesContent": ["import { DmkNetworkClientError } from \"./DmkNetworkClientError\";\nimport {\n buildBodyAndHeaders,\n buildSignal,\n buildUrl,\n hasHeader,\n isRawBody,\n joinPath,\n JSON_CONTENT_TYPE,\n parseBody,\n safeReadText,\n wrapFetchError,\n} from \"./DmkNetworkClientHelpers\";\n\ndescribe(\"DmkNetworkClientHelpers\", () => {\n describe(\"joinPath\", () => {\n it(\"should return the base when the path is empty\", () => {\n expect(joinPath(\"https://api.example.com\", \"\")).toBe(\n \"https://api.example.com\",\n );\n });\n\n it(\"should insert a single slash when neither side has one\", () => {\n expect(joinPath(\"https://api.example.com\", \"items\")).toBe(\n \"https://api.example.com/items\",\n );\n });\n\n it(\"should collapse a trailing base slash with a leading path slash\", () => {\n expect(joinPath(\"https://api.example.com/\", \"/items\")).toBe(\n \"https://api.example.com/items\",\n );\n });\n\n it(\"should keep a single slash when only one side has one\", () => {\n expect(joinPath(\"https://api.example.com/\", \"items\")).toBe(\n \"https://api.example.com/items\",\n );\n expect(joinPath(\"https://api.example.com\", \"/items\")).toBe(\n \"https://api.example.com/items\",\n );\n });\n });\n\n describe(\"buildUrl\", () => {\n it(\"should keep an absolute URL as-is\", () => {\n const url = buildUrl({ url: \"https://api.example.com/items\" });\n expect(url).toBe(\"https://api.example.com/items\");\n });\n\n it(\"should prepend the base URL to a relative path\", () => {\n const url = buildUrl({\n url: \"/items\",\n baseUrl: \"https://api.example.com/\",\n });\n expect(url).toBe(\"https://api.example.com/items\");\n });\n\n it(\"should ignore the base URL when the input URL is absolute\", () => {\n const url = buildUrl({\n url: \"https://other.example.com/items\",\n baseUrl: \"https://api.example.com\",\n });\n expect(url).toBe(\"https://other.example.com/items\");\n });\n\n it(\"should append query params and skip null/undefined entries\", () => {\n const url = buildUrl({\n url: \"https://api.example.com/items\",\n params: {\n chain: 1,\n contract: \"0xabc\",\n active: true,\n skip: null,\n alsoSkip: undefined,\n },\n });\n expect(typeof url).toBe(\"string\");\n const parsed = new URL(url);\n expect(parsed.searchParams.get(\"chain\")).toBe(\"1\");\n expect(parsed.searchParams.get(\"contract\")).toBe(\"0xabc\");\n expect(parsed.searchParams.get(\"active\")).toBe(\"true\");\n expect(parsed.searchParams.has(\"skip\")).toBe(false);\n expect(parsed.searchParams.has(\"alsoSkip\")).toBe(false);\n });\n\n it(\"should preserve a pre-existing query string in the input URL\", () => {\n const url = buildUrl({\n url: \"https://api.example.com/items?keep=1\",\n params: { chain: 2 },\n });\n const parsed = new URL(url);\n expect(parsed.searchParams.get(\"keep\")).toBe(\"1\");\n expect(parsed.searchParams.get(\"chain\")).toBe(\"2\");\n });\n\n it(\"should percent-encode keys and values\", () => {\n const url = buildUrl({\n url: \"https://api.example.com/items\",\n params: { \"a key\": \"a value&b\" },\n });\n expect(url).toBe(\"https://api.example.com/items?a%20key=a%20value%26b\");\n });\n\n it(\"should not append a trailing slash after the last query value (facebook/react-native#54242)\", () => {\n const url = buildUrl({\n url: \"https://manager.api.live.ledger.com/api/get_device_version\",\n params: { target_id: 858783748, provider: 1 },\n });\n expect(typeof url).toBe(\"string\");\n expect(url).toBe(\n \"https://manager.api.live.ledger.com/api/get_device_version?target_id=858783748&provider=1\",\n );\n expect(url.endsWith(\"/\")).toBe(false);\n });\n\n it(\"should return a plain string (not a URL instance) so RN URL serialization is bypassed\", () => {\n const url = buildUrl({\n url: \"https://api.example.com/items\",\n params: { chain: 1 },\n });\n expect(typeof url).toBe(\"string\");\n expect(url).not.toBeInstanceOf(URL);\n });\n\n it(\"should still build the URL when URLSearchParams.set is unavailable (React Native regression)\", () => {\n const original = URLSearchParams.prototype.set;\n URLSearchParams.prototype.set = function notImplemented(): never {\n throw new Error(\"URLSearchParams.set is not implemented\");\n };\n try {\n const url = buildUrl({\n url: \"https://api.example.com/items\",\n params: { chain: 1, contract: \"0xabc\" },\n });\n expect(url).toContain(\"chain=1\");\n expect(url).toContain(\"contract=0xabc\");\n } finally {\n URLSearchParams.prototype.set = original;\n }\n });\n });\n\n describe(\"hasHeader\", () => {\n it(\"should find a header regardless of case\", () => {\n expect(hasHeader({ \"Content-Type\": \"json\" }, \"content-type\")).toBe(true);\n expect(hasHeader({ \"content-type\": \"json\" }, \"Content-Type\")).toBe(true);\n });\n\n it(\"should return false when no matching header exists\", () => {\n expect(hasHeader({ Accept: \"json\" }, \"content-type\")).toBe(false);\n expect(hasHeader({}, \"content-type\")).toBe(false);\n });\n });\n\n describe(\"isRawBody\", () => {\n it(\"should accept native BodyInit values\", () => {\n expect(isRawBody(\"raw-string\")).toBe(true);\n expect(isRawBody(new ArrayBuffer(4))).toBe(true);\n expect(isRawBody(new Uint8Array([1, 2, 3]))).toBe(true);\n expect(isRawBody(new Blob([\"a\"]))).toBe(true);\n expect(isRawBody(new FormData())).toBe(true);\n expect(isRawBody(new URLSearchParams({ a: \"1\" }))).toBe(true);\n expect(isRawBody(new ReadableStream())).toBe(true);\n });\n\n it(\"should reject plain objects and primitives\", () => {\n expect(isRawBody({ foo: \"bar\" })).toBe(false);\n expect(isRawBody([1, 2, 3])).toBe(false);\n expect(isRawBody(42)).toBe(false);\n expect(isRawBody(null)).toBe(false);\n expect(isRawBody(undefined)).toBe(false);\n });\n\n it(\"should not throw when optional Web globals are missing (React Native regression)\", () => {\n const globals = globalThis as unknown as Record<string, unknown>;\n const names = [\"Blob\", \"FormData\", \"URLSearchParams\", \"ReadableStream\"];\n const saved: Record<string, unknown> = {};\n for (const name of names) {\n saved[name] = globals[name];\n delete globals[name];\n }\n try {\n expect(() => isRawBody({ foo: \"bar\" })).not.toThrow();\n expect(isRawBody({ foo: \"bar\" })).toBe(false);\n expect(isRawBody(\"raw\")).toBe(true);\n expect(isRawBody(new Uint8Array([1]))).toBe(true);\n } finally {\n for (const name of names) {\n globals[name] = saved[name];\n }\n }\n });\n });\n\n describe(\"buildBodyAndHeaders\", () => {\n it(\"should merge default and per-request headers with per-request winning\", () => {\n const { headers } = buildBodyAndHeaders({\n method: \"GET\",\n body: undefined,\n defaultHeaders: { \"X-Default\": \"default\", \"X-Shared\": \"from-default\" },\n perRequestHeaders: { \"X-Shared\": \"overridden\", \"X-Per\": \"per\" },\n });\n expect(headers).toEqual({\n \"X-Default\": \"default\",\n \"X-Shared\": \"overridden\",\n \"X-Per\": \"per\",\n });\n });\n\n it(\"should not emit a body on GET/HEAD even when a body is provided\", () => {\n const result = buildBodyAndHeaders({\n method: \"GET\",\n body: { foo: \"bar\" },\n defaultHeaders: {},\n });\n expect(result.body).toBeUndefined();\n expect(result.headers[\"Content-Type\"]).toBeUndefined();\n });\n\n it(\"should JSON-stringify plain objects and set the Content-Type\", () => {\n const result = buildBodyAndHeaders({\n method: \"POST\",\n body: { foo: \"bar\" },\n defaultHeaders: {},\n });\n expect(result.body).toBe(JSON.stringify({ foo: \"bar\" }));\n expect(result.headers[\"Content-Type\"]).toBe(JSON_CONTENT_TYPE);\n });\n\n it(\"should not override an explicit Content-Type header\", () => {\n const result = buildBodyAndHeaders({\n method: \"POST\",\n body: { foo: \"bar\" },\n defaultHeaders: {},\n perRequestHeaders: { \"content-type\": \"application/vnd.custom+json\" },\n });\n expect(result.body).toBe(JSON.stringify({ foo: \"bar\" }));\n expect(result.headers[\"content-type\"]).toBe(\n \"application/vnd.custom+json\",\n );\n expect(result.headers[\"Content-Type\"]).toBeUndefined();\n });\n\n it(\"should pass raw BodyInit values through unchanged without JSON headers\", () => {\n const formData = new FormData();\n formData.set(\"field\", \"value\");\n const result = buildBodyAndHeaders({\n method: \"POST\",\n body: formData,\n defaultHeaders: {},\n });\n expect(result.body).toBe(formData);\n expect(result.headers[\"Content-Type\"]).toBeUndefined();\n });\n\n it(\"should return an undefined body when the body itself is undefined\", () => {\n const result = buildBodyAndHeaders({\n method: \"POST\",\n body: undefined,\n defaultHeaders: { \"X-Default\": \"d\" },\n });\n expect(result.body).toBeUndefined();\n expect(result.headers).toEqual({ \"X-Default\": \"d\" });\n });\n });\n\n describe(\"buildSignal\", () => {\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it(\"GIVEN no timeout WHEN building a signal THEN it returns no signal\", () => {\n const result = buildSignal({\n timeoutMs: undefined,\n });\n\n expect(result.signal).toBeUndefined();\n expect(result.cleanup).toEqual(expect.any(Function));\n });\n\n it(\"GIVEN a zero timeout WHEN building a signal THEN it returns no signal\", () => {\n const result = buildSignal({\n timeoutMs: 0,\n });\n\n expect(result.signal).toBeUndefined();\n expect(result.cleanup).toEqual(expect.any(Function));\n });\n\n it(\"GIVEN a negative timeout WHEN building a signal THEN it returns no signal\", () => {\n const result = buildSignal({\n timeoutMs: -1,\n });\n\n expect(result.signal).toBeUndefined();\n expect(result.cleanup).toEqual(expect.any(Function));\n });\n\n it(\"GIVEN a positive timeout WHEN building a signal THEN it returns an AbortSignal\", () => {\n const { signal, cleanup } = buildSignal({\n timeoutMs: 1000,\n });\n\n expect(signal).toBeInstanceOf(AbortSignal);\n expect(signal?.aborted).toBe(false);\n cleanup();\n });\n\n it(\"GIVEN a positive timeout WHEN the delay elapses THEN it aborts the signal\", () => {\n vi.useFakeTimers();\n const { signal, cleanup } = buildSignal({\n timeoutMs: 1000,\n });\n\n expect(signal?.aborted).toBe(false);\n vi.advanceTimersByTime(999);\n expect(signal?.aborted).toBe(false);\n vi.advanceTimersByTime(1);\n expect(signal?.aborted).toBe(true);\n cleanup();\n });\n\n it(\"GIVEN a timeout signal WHEN cleanup runs before the delay THEN it does not abort\", () => {\n vi.useFakeTimers();\n const { signal, cleanup } = buildSignal({\n timeoutMs: 100,\n });\n\n cleanup();\n vi.advanceTimersByTime(100);\n\n expect(signal?.aborted).toBe(false);\n });\n });\n\n describe(\"parseBody\", () => {\n it(\"should return undefined for 'void' response type without consuming the body\", async () => {\n const response = new Response(\"ignored\");\n const result = await parseBody(response, \"void\");\n expect(result).toBeUndefined();\n expect(response.bodyUsed).toBe(false);\n });\n\n it(\"should return text for 'text' response type\", async () => {\n const response = new Response(\"plain-body\");\n await expect(parseBody(response, \"text\")).resolves.toBe(\"plain-body\");\n });\n\n it(\"should return a Blob for 'blob' response type\", async () => {\n const response = new Response(\"blob-body\");\n const result = await parseBody(response, \"blob\");\n expect(result).toBeInstanceOf(Blob);\n });\n\n it(\"should return an ArrayBuffer for 'arrayBuffer' response type\", async () => {\n const response = new Response(new Uint8Array([1, 2, 3]));\n const result = await parseBody(response, \"arrayBuffer\");\n expect(result).toBeInstanceOf(ArrayBuffer);\n expect(new Uint8Array(result as ArrayBuffer)).toEqual(\n new Uint8Array([1, 2, 3]),\n );\n });\n\n it(\"should parse JSON for 'json' response type\", async () => {\n const response = new Response(JSON.stringify({ hello: \"world\" }));\n await expect(parseBody(response, \"json\")).resolves.toEqual({\n hello: \"world\",\n });\n });\n\n it(\"should resolve to undefined for an empty JSON body\", async () => {\n const response = new Response(\"\");\n await expect(parseBody(response, \"json\")).resolves.toBeUndefined();\n });\n\n it(\"should throw a DmkNetworkClientError for malformed JSON\", async () => {\n const response = new Response(\"not-json\", {\n status: 200,\n statusText: \"OK\",\n });\n const error = await parseBody(response, \"json\").catch((e: unknown) => e);\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n const dmkError = error as DmkNetworkClientError;\n expect(dmkError.status).toBe(200);\n expect(dmkError.statusText).toBe(\"OK\");\n expect(dmkError.responseBody).toBe(\"not-json\");\n expect(dmkError.cause).toBeInstanceOf(SyntaxError);\n });\n });\n\n describe(\"safeReadText\", () => {\n it(\"should return the text body\", async () => {\n await expect(safeReadText(new Response(\"hello\"))).resolves.toBe(\"hello\");\n });\n\n it(\"should return undefined when reading the body throws\", async () => {\n const response = {\n text: () => Promise.reject(new Error(\"read failed\")),\n } as unknown as Response;\n await expect(safeReadText(response)).resolves.toBeUndefined();\n });\n });\n\n describe(\"wrapFetchError\", () => {\n it(\"should wrap a generic Error with its message\", () => {\n const cause = new TypeError(\"network down\");\n const error = wrapFetchError({\n cause,\n timeoutMs: undefined,\n });\n expect(error).toBeInstanceOf(DmkNetworkClientError);\n expect(error.message).toBe(\"network down\");\n expect(error.cause).toBe(cause);\n expect(error.isTimeout).toBe(false);\n });\n\n it(\"should fall back to a generic message for non-Error causes\", () => {\n const error = wrapFetchError({\n cause: \"something\",\n timeoutMs: undefined,\n });\n expect(error.message).toBe(\"Network request failed\");\n expect(error.cause).toBe(\"something\");\n });\n\n it(\"should flag TimeoutError as a timeout\", () => {\n const cause = new Error(\"timed out\");\n cause.name = \"TimeoutError\";\n const error = wrapFetchError({\n cause,\n timeoutMs: 10,\n });\n expect(error.isTimeout).toBe(true);\n expect(error.message).toBe(\"Request timed out\");\n });\n\n it(\"should flag AbortError as a timeout when a timeout is configured and no external abort\", () => {\n const cause = new Error(\"aborted\");\n cause.name = \"AbortError\";\n const error = wrapFetchError({\n cause,\n timeoutMs: 1000,\n });\n expect(error.isTimeout).toBe(true);\n });\n\n it(\"should treat AbortError with no timeout and no external abort as a plain abort\", () => {\n const cause = new Error(\"aborted\");\n cause.name = \"AbortError\";\n const error = wrapFetchError({\n cause,\n timeoutMs: undefined,\n });\n expect(error.isTimeout).toBe(false);\n expect(error.message).toBe(\"Request aborted\");\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["DmkNetworkClientError", "buildBodyAndHeaders", "buildSignal", "buildUrl", "hasHeader", "isRawBody", "joinPath", "JSON_CONTENT_TYPE", "parseBody", "safeReadText", "wrapFetchError", "url", "parsed", "original", "globals", "names", "saved", "name", "headers", "result", "formData", "signal", "cleanup", "response", "error", "e", "dmkError", "cause"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function f(
|
|
1
|
+
function f(n){return n.replace(/\s/g,"")}function a(n){const e=f(n);return/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)}function u(){if(typeof window<"u"&&typeof window.atob=="function")return window.atob.bind(window);if(typeof atob=="function")return atob}function d(){if(typeof window<"u"&&typeof window.btoa=="function")return window.btoa.bind(window);if(typeof btoa=="function")return btoa}function s(n){const e=f(n);if(e.length===0)return new Uint8Array;if(!a(e))return null;const r=u();if(r){const t=r(e),i=new Uint8Array(t.length);for(let o=0;o<t.length;o++)i[o]=t.charCodeAt(o);return i}if(typeof globalThis.Buffer<"u")return Uint8Array.from(globalThis.Buffer.from(e,"base64"));throw new Error("No Base64 decoder available in this environment.")}function l(n){const e=d();if(e){let r="";for(let t=0;t<n.length;t++){const i=n[t];if(i===void 0)throw new Error("Unexpected undefined byte in array.");r+=String.fromCharCode(i)}return e(r)}if(typeof globalThis.Buffer<"u")return globalThis.Buffer.from(n).toString("base64");throw new Error("No Base64 encoder available in this environment.")}export{s as base64StringToBuffer,l as bufferToBase64String,a as isBase64String};
|
|
2
2
|
//# sourceMappingURL=Base64String.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/api/utils/Base64String.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["function normalizeBase64String(value: string): string {\n return value.replace(/\\s/g, \"\");\n}\n\nexport function isBase64String(value: string): boolean {\n const normalizedValue = normalizeBase64String(value);\n // Valid base64 characters are [A-Za-z0-9+/]\n // They are always grouped by 4 characters.\n // Optional padding at the end with one or two '='.\n // ASCII whitespace is ignored because some native APIs emit MIME-style\n // Base64 with line breaks.\n // see section 4 of: https://www.rfc-editor.org/rfc/rfc4648.txt\n return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(\n normalizedValue,\n );\n}\n\n/**\n * Prefer `window.atob` in browser runtimes where Base64 helpers are exposed on\n * `window`; fall back to global `atob` for runtimes such as Hermes.\n */\nfunction getAtob(): ((data: string) => string) | undefined {\n if (typeof window !== \"undefined\" && typeof window.atob === \"function\") {\n return window.atob.bind(window);\n }\n // eslint-disable-next-line no-restricted-globals -- portable smart-switch: probe the bare global as a Hermes/RN fallback.\n if (typeof atob === \"function\") {\n // eslint-disable-next-line no-restricted-globals -- portable smart-switch: probe the bare global as a Hermes/RN fallback.\n return atob;\n }\n return undefined;\n}\n\n/**\n * Prefer `window.btoa` in browser runtimes where Base64 helpers are exposed on\n * `window`; fall back to global `btoa` for runtimes such as Hermes.\n */\nfunction getBtoa(): ((data: string) => string) | undefined {\n if (typeof window !== \"undefined\" && typeof window.btoa === \"function\") {\n return window.btoa.bind(window);\n }\n // eslint-disable-next-line no-restricted-globals -- portable smart-switch: probe the bare global as a Hermes/RN fallback.\n if (typeof btoa === \"function\") {\n // eslint-disable-next-line no-restricted-globals -- portable smart-switch: probe the bare global as a Hermes/RN fallback.\n return btoa;\n }\n return undefined;\n}\n\nexport function base64StringToBuffer(value: string): Uint8Array | null {\n const normalizedValue = normalizeBase64String(value);\n if (normalizedValue.length === 0) {\n return new Uint8Array();\n }\n if (!isBase64String(normalizedValue)) {\n return null;\n }\n const atobFn = getAtob();\n\n if (atobFn) {\n const base64Decoded = atobFn(normalizedValue);\n const buffer = new Uint8Array(base64Decoded.length);\n for (let i = 0; i < base64Decoded.length; i++) {\n buffer[i] = base64Decoded.charCodeAt(i);\n }\n return buffer;\n }\n\n if (typeof globalThis.Buffer !== \"undefined\") {\n return Uint8Array.from(globalThis.Buffer.from(normalizedValue, \"base64\"));\n }\n\n throw new Error(\"No Base64 decoder available in this environment.\");\n}\n\nexport function bufferToBase64String(bytes: Uint8Array): string {\n const btoaFn = getBtoa();\n\n if (btoaFn) {\n // convert bytes to a binary string for btoa\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n const byte = bytes[i];\n if (byte === undefined) {\n throw new Error(\"Unexpected undefined byte in array.\");\n }\n binary += String.fromCharCode(byte);\n }\n return btoaFn(binary);\n }\n\n if (typeof globalThis.Buffer !== \"undefined\") {\n return globalThis.Buffer.from(bytes).toString(\"base64\");\n }\n\n throw new Error(\"No Base64 encoder available in this environment.\");\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAASA,EAAsBC,EAAuB,CACpD,OAAOA,EAAM,QAAQ,MAAO,EAAE,CAChC,CAEO,SAASC,EAAeD,EAAwB,CACrD,MAAME,EAAkBH,EAAsBC,CAAK,EAOnD,MAAO,mEAAmE,KACxEE,CACF,CACF,CAMA,SAASC,GAAkD,CACzD,GAAI,OAAO,OAAW,KAAe,OAAO,OAAO,MAAS,WAC1D,OAAO,OAAO,KAAK,KAAK,MAAM,EAGhC,GAAI,OAAO,MAAS,WAElB,OAAO,IAGX,CAMA,SAASC,GAAkD,CACzD,GAAI,OAAO,OAAW,KAAe,OAAO,OAAO,MAAS,WAC1D,OAAO,OAAO,KAAK,KAAK,MAAM,EAGhC,GAAI,OAAO,MAAS,WAElB,OAAO,IAGX,CAEO,SAASC,EAAqBL,EAAkC,CACrE,MAAME,EAAkBH,EAAsBC,CAAK,EACnD,GAAIE,EAAgB,SAAW,EAC7B,OAAO,IAAI,WAEb,GAAI,CAACD,EAAeC,CAAe,EACjC,OAAO,KAET,MAAMI,EAASH,EAAQ,EAEvB,GAAIG,EAAQ,CACV,MAAMC,EAAgBD,EAAOJ,CAAe,EACtCM,EAAS,IAAI,WAAWD,EAAc,MAAM,EAClD,QAASE,EAAI,EAAGA,EAAIF,EAAc,OAAQE,IACxCD,EAAOC,CAAC,EAAIF,EAAc,WAAWE,CAAC,EAExC,OAAOD,CACT,CAEA,GAAI,OAAO,WAAW,OAAW,IAC/B,OAAO,WAAW,KAAK,WAAW,OAAO,KAAKN,EAAiB,QAAQ,CAAC,EAG1E,MAAM,IAAI,MAAM,kDAAkD,CACpE,CAEO,SAASQ,EAAqBC,EAA2B,CAC9D,MAAMC,EAASR,EAAQ,EAEvB,GAAIQ,EAAQ,CAEV,IAAIC,EAAS,GACb,QAASJ,EAAI,EAAGA,EAAIE,EAAM,OAAQF,IAAK,CACrC,MAAMK,EAAOH,EAAMF,CAAC,EACpB,GAAIK,IAAS,OACX,MAAM,IAAI,MAAM,qCAAqC,EAEvDD,GAAU,OAAO,aAAaC,CAAI,CACpC,CACA,OAAOF,EAAOC,CAAM,CACtB,CAEA,GAAI,OAAO,WAAW,OAAW,IAC/B,OAAO,WAAW,OAAO,KAAKF,CAAK,EAAE,SAAS,QAAQ,EAGxD,MAAM,IAAI,MAAM,kDAAkD,CACpE",
|
|
6
|
+
"names": ["normalizeBase64String", "value", "isBase64String", "normalizedValue", "getAtob", "getBtoa", "base64StringToBuffer", "atobFn", "base64Decoded", "buffer", "i", "bufferToBase64String", "bytes", "btoaFn", "binary", "byte"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import{base64StringToBuffer as
|
|
1
|
+
import{base64StringToBuffer as l,bufferToBase64String as r,isBase64String as i}from"./Base64String";describe("Base64String",()=>{describe("isBase64String function",()=>{it("should return true if the value is a valid base64 string",()=>{const t=i("Zmlyc3QgdG/zdGluZyBz+HI9");expect(t).toBeTruthy()}),it("should return true if the value is a valid base64 string, one padding",()=>{const t=i("Zmlyc3QgdGVzdGluZyBzdHI=");expect(t).toBeTruthy()}),it("should return true if the value is a valid base64 string, two paddings",()=>{const t=i("Zmlyc3QgdGVzdGluZyBzdH==");expect(t).toBeTruthy()}),it("should return true for an empty string",()=>{const t=i("");expect(t).toBeTruthy()}),it("GIVEN a base64 string with whitespace WHEN validating THEN it returns true",()=>{const t=i(`AQID
|
|
2
|
+
kAA=`);expect(t).toBeTruthy()}),it("should return false for an invalid base64 string",()=>{const t=i("invalid base64 string");expect(t).toBeFalsy()}),it("should return false with 3 paddings",()=>{const t=i("Zmlyc3QgdGVzdGluZyBzd===");expect(t).toBeFalsy()}),it("should return false on incomplete string (not multiple of 4)",()=>{const t=i("Zmlyc3QgdGVzdGluZyBzdHI");expect(t).toBeFalsy()})}),describe("base64StringToBuffer function",()=>{const n=globalThis.atob,t=globalThis.Buffer,c=globalThis.window;beforeEach(()=>{vi.restoreAllMocks(),globalThis.atob=n,globalThis.Buffer=t,globalThis.window=void 0}),afterAll(()=>{globalThis.atob=n,globalThis.Buffer=t,globalThis.window=c}),it("should convert empty input to empty buffer",()=>{const a=l("");expect(a).toStrictEqual(new Uint8Array)}),it("invalid base64 string converted to null",()=>{const a=l("invalid string");expect(a).toStrictEqual(null)}),it("GIVEN a base64 string with whitespace WHEN decoding THEN it ignores the whitespace",()=>{const a=l(`AQID
|
|
3
|
+
kAA=`);expect(a).toStrictEqual(Uint8Array.from([1,2,3,144,0]))}),describe("runtime compatibility fallbacks",()=>{it("GIVEN window.atob is available WHEN decoding THEN it uses window.atob",()=>{const e="Zmlyc3QgdGVzdCBzdHJpbmc=",a=vi.fn(()=>"first test string"),o=vi.fn(()=>"unexpected");globalThis.window={atob:a},globalThis.atob=o;const s=l(e);expect(s).toStrictEqual(Uint8Array.from([102,105,114,115,116,32,116,101,115,116,32,115,116,114,105,110,103])),expect(a).toHaveBeenCalledWith(e),expect(o).not.toHaveBeenCalled()}),it("GIVEN global atob is available WHEN decoding THEN it uses global atob",()=>{const e="Zmlyc3QgdGVzdCBzdHJpbmc=",a=vi.fn(()=>"first test string");globalThis.atob=a;const o=l(e);expect(o).toStrictEqual(Uint8Array.from([102,105,114,115,116,32,116,101,115,116,32,115,116,114,105,110,103])),expect(a).toHaveBeenCalledWith(e)}),it("GIVEN atob is not available WHEN decoding THEN it uses Buffer",()=>{globalThis.atob=void 0;const e="Zmlyc3QgdGVzdCBzdHJpbmc=",a=vi.spyOn(Buffer,"from"),o=l(e);expect(o).toStrictEqual(Uint8Array.from([102,105,114,115,116,32,116,101,115,116,32,115,116,114,105,110,103])),expect(a).toHaveBeenCalledWith(e,"base64")}),it("GIVEN no decoder is available WHEN decoding THEN it throws",()=>{globalThis.atob=void 0,globalThis.Buffer=void 0;const e="Zmlyc3QgdGVzdCBzdHJpbmc=";expect(()=>l(e)).toThrowError("No Base64 decoder available in this environment.")})})})});describe("bufferToBase64String",()=>{const n=globalThis.btoa,t=globalThis.Buffer,c=globalThis.window;beforeEach(()=>{vi.restoreAllMocks(),globalThis.btoa=n,globalThis.Buffer=t,globalThis.window=void 0}),afterAll(()=>{globalThis.btoa=n,globalThis.Buffer=t,globalThis.window=c}),it("should encode an empty buffer to an empty base64 string when btoa is available",()=>{globalThis.btoa=vi.fn(o=>(expect(o).toBe(""),""));const e=new Uint8Array,a=r(e);expect(a).toBe(""),expect(globalThis.btoa).toHaveBeenCalledTimes(1)}),describe("runtime compatibility fallbacks",()=>{it("GIVEN global btoa is available WHEN encoding THEN it uses global btoa",()=>{const e="first testing str",a=Uint8Array.from(e.split("").map(s=>s.charCodeAt(0)));globalThis.btoa=vi.fn(s=>(expect(s).toBe(e),"Zmlyc3QgdGVzdGluZyBzdHI="));const o=r(a);expect(o).toBe("Zmlyc3QgdGVzdGluZyBzdHI="),expect(globalThis.btoa).toHaveBeenCalledTimes(1)}),it("GIVEN window.btoa is available WHEN encoding THEN it uses window.btoa",()=>{const e="first testing str",a=Uint8Array.from(e.split("").map(u=>u.charCodeAt(0))),o=vi.fn(()=>"Zmlyc3QgdGVzdGluZyBzdHI="),s=vi.fn(()=>"unexpected");globalThis.window={btoa:o},globalThis.btoa=s;const d=r(a);expect(d).toBe("Zmlyc3QgdGVzdGluZyBzdHI="),expect(o).toHaveBeenCalledWith(e),expect(s).not.toHaveBeenCalled()}),it("GIVEN btoa is not available WHEN encoding THEN it uses Buffer",()=>{globalThis.btoa=void 0;const e="testing str",a=Buffer.from(e,"binary").toString("base64"),o=Uint8Array.from(e.split("").map(u=>u.charCodeAt(0))),s=vi.spyOn(Buffer,"from"),d=r(o);expect(d).toBe(a),expect(s).toHaveBeenCalledTimes(1)}),it("GIVEN no encoder is available WHEN encoding THEN it throws",()=>{globalThis.btoa=void 0,globalThis.Buffer=void 0;const e=Uint8Array.from([1,2,3]);expect(()=>r(e)).toThrowError("No Base64 encoder available in this environment.")})}),it("should throw if an undefined byte is encountered (defensive check)",()=>{const e={length:3,0:102,1:void 0,2:111};globalThis.btoa=vi.fn(),expect(()=>r(e)).toThrowError("Unexpected undefined byte in array.")})});
|
|
2
4
|
//# sourceMappingURL=Base64String.test.js.map
|