@ryuzaki13/react-foundation-api 1.1.13 → 1.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/adt/index.js +5 -3
- package/dist/adt/index.js.map +1 -1
- package/dist/async/index.js +1 -4
- package/dist/async/index.js.map +1 -1
- package/dist/chunks/{fetch-PmN9NBra.js → fetch-Cq29VQlt.js} +3 -2
- package/dist/chunks/{fetch-PmN9NBra.js.map → fetch-Cq29VQlt.js.map} +1 -1
- package/dist/chunks/{odataFetchFn-CzhXMYXj.js → odataFetchFn-BdCJe4_T.js} +13 -13
- package/dist/chunks/{odataFetchFn-CzhXMYXj.js.map → odataFetchFn-BdCJe4_T.js.map} +1 -1
- package/dist/error-report/index.js +2 -1
- package/dist/error-report/index.js.map +1 -1
- package/dist/odata/index.js +24 -24
- package/dist/odata/index.js.map +1 -1
- package/dist/persisted/index.js +1 -1
- package/dist/transport/index.js +1 -1
- package/package.json +20 -40
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ import type { ODataCollectionConfig } from "@ryuzaki13/react-foundation-api/odat
|
|
|
44
44
|
|
|
45
45
|
`@ryuzaki13/react-foundation-lib` является обязательной peer-зависимостью: этот пакет использует его как нижний технический слой.
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
Внешние пакеты, которые этот пакет импортирует напрямую, объявлены как optional peers. Это означает только то, что их не нужно ставить для каждого сценария. Дополнительные зависимости entrypoint, поступающие через `@ryuzaki13/react-foundation-lib`, определяются peer-контрактом этого нижнего слоя.
|
|
48
48
|
|
|
49
49
|
| Entry point | Что может потребоваться в host-проекте |
|
|
50
50
|
| ----------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
package/dist/adt/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as e } from "../chunks/fetch-
|
|
1
|
+
import { t as e } from "../chunks/fetch-Cq29VQlt.js";
|
|
2
2
|
import { isRecord as t } from "@ryuzaki13/react-foundation-lib/validators";
|
|
3
3
|
import { normalizeText as n } from "@ryuzaki13/react-foundation-lib/formatters";
|
|
4
4
|
import { arrayUniqueBy as r } from "@ryuzaki13/react-foundation-lib/array";
|
|
@@ -40,7 +40,8 @@ function c(e) {
|
|
|
40
40
|
let t = s(e);
|
|
41
41
|
return t ? [t] : [];
|
|
42
42
|
});
|
|
43
|
-
|
|
43
|
+
if (c.length > 0) return r(c, "transportNo");
|
|
44
|
+
let l = o(i, "TRKORR").map((e) => n(e)).filter((e) => e !== void 0).map((e) => ({
|
|
44
45
|
transportNo: e,
|
|
45
46
|
description: void 0,
|
|
46
47
|
owner: void 0,
|
|
@@ -48,7 +49,8 @@ function c(e) {
|
|
|
48
49
|
functionCode: void 0,
|
|
49
50
|
statusCode: void 0,
|
|
50
51
|
parentTransportNo: void 0
|
|
51
|
-
}))
|
|
52
|
+
}));
|
|
53
|
+
return r(l, "transportNo");
|
|
52
54
|
}
|
|
53
55
|
//#endregion
|
|
54
56
|
//#region src/adt/fetchUserTransports.ts
|
package/dist/adt/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/adt/parseUserTransportsXml.ts","../../src/adt/fetchUserTransports.ts"],"sourcesContent":["import { arrayUniqueBy } from \"@ryuzaki13/react-foundation-lib/array\";\nimport { normalizeText } from \"@ryuzaki13/react-foundation-lib/formatters\";\nimport { isRecord } from \"@ryuzaki13/react-foundation-lib/validators\";\nimport { XMLParser } from \"fast-xml-parser\";\n\nimport type { UserTransport } from \"./types\";\n\nconst parser = new XMLParser({\n\tignoreAttributes: false,\n\tattributeNamePrefix: \"\",\n\tparseTagValue: false,\n\ttrimValues: true\n});\n\nfunction collectByKey(value: unknown, key: string, result: unknown[] = []): unknown[] {\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) {\n\t\t\tcollectByKey(item, key, result);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tif (!isRecord(value)) return result;\n\n\tfor (const [entryKey, entryValue] of Object.entries(value)) {\n\t\tif (entryKey === key) {\n\t\t\tresult.push(entryValue);\n\t\t}\n\n\t\tcollectByKey(entryValue, key, result);\n\t}\n\n\treturn result;\n}\n\nfunction toTransportRecord(value: unknown): UserTransport | null {\n\tif (!isRecord(value)) return null;\n\n\tconst transportNo = normalizeText(value.TRKORR);\n\tif (!transportNo) return null;\n\n\treturn {\n\t\ttransportNo,\n\t\tdescription: normalizeText(value.AS4TEXT),\n\t\towner: normalizeText(value.AS4USER),\n\t\ttargetSystem: normalizeText(value.TARSYSTEM),\n\t\tfunctionCode: normalizeText(value.TRFUNCTION),\n\t\tstatusCode: normalizeText(value.TRSTATUS),\n\t\tparentTransportNo: normalizeText(value.STRKORR)\n\t};\n}\n\nexport function parseUserTransportsXml(xml: string): UserTransport[] {\n\tconst normalizedXml = xml.trim();\n\tif (!normalizedXml) return [];\n\n\tconst parsed = parser.parse(normalizedXml) as unknown;\n\tconst transportHeaders = collectByKey(parsed, \"CTS_REQ_HEADER\").flatMap((entry) => {\n\t\tif (Array.isArray(entry)) {\n\t\t\treturn entry.map(toTransportRecord).filter((item): item is UserTransport => item !== null);\n\t\t}\n\n\t\tconst transport = toTransportRecord(entry);\n\t\treturn transport ? [transport] : [];\n\t});\n\n\tif (transportHeaders.length > 0) {\n\t\treturn arrayUniqueBy(transportHeaders, \"transportNo\");\n\t}\n\n\tconst transportNos = collectByKey(parsed, \"TRKORR\")\n\t\t.map((value) => normalizeText(value))\n\t\t.filter((value): value is string => value !== undefined)\n\t\t.map((transportNo): UserTransport => ({\n\t\t\ttransportNo,\n\t\t\tdescription: undefined,\n\t\t\towner: undefined,\n\t\t\ttargetSystem: undefined,\n\t\t\tfunctionCode: undefined,\n\t\t\tstatusCode: undefined,\n\t\t\tparentTransportNo: undefined\n\t\t}));\n\n\treturn arrayUniqueBy(transportNos, \"transportNo\");\n}\n","import { fetchBase } from \"../odata/transport\";\n\nimport { parseUserTransportsXml } from \"./parseUserTransportsXml\";\n\nconst USER_TRANSPORTS_URL = \"/sap/bc/adt/cts/transports?_action=FIND&trfunction=K\";\n\nfunction isHtmlResponse(text: string, contentType: string) {\n\treturn contentType.includes(\"text/html\") || /^\\s*<!doctype html/i.test(text) || /^\\s*<html/i.test(text);\n}\n\nexport async function fetchUserTransports() {\n\tconst response = await fetchBase(\n\t\tUSER_TRANSPORTS_URL,\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/xml, text/xml, */*\"\n\t\t\t}\n\t\t},\n\t\t\"\"\n\t);\n\n\tconst responseText = await response.text();\n\tconst contentType = (response.headers.get(\"Content-Type\") || \"\").toLowerCase();\n\n\tif (isHtmlResponse(responseText, contentType)) {\n\t\tthrow new Error(\"ADT вернул HTML вместо XML при запросе списка транспортов\");\n\t}\n\n\treturn parseUserTransportsXml(responseText);\n}\n"],"mappings":";;;;;;AAOA,IAAM,IAAS,IAAI,EAAU;CAC5B,kBAAkB;CAClB,qBAAqB;CACrB,eAAe;CACf,YAAY;AACb,CAAC;AAED,SAAS,EAAa,GAAgB,GAAa,IAAoB,CAAC,GAAc;CACrF,IAAI,MAAM,QAAQ,CAAK,GAAG;EACzB,KAAK,IAAM,KAAQ,GAClB,EAAa,GAAM,GAAK,CAAM;EAG/B,OAAO;CACR;CAEA,IAAI,CAAC,EAAS,CAAK,GAAG,OAAO;CAE7B,KAAK,IAAM,CAAC,GAAU,MAAe,OAAO,QAAQ,CAAK,GAKxD,AAJI,MAAa,KAChB,EAAO,KAAK,CAAU,GAGvB,EAAa,GAAY,GAAK,CAAM;CAGrC,OAAO;AACR;AAEA,SAAS,EAAkB,GAAsC;CAChE,IAAI,CAAC,EAAS,CAAK,GAAG,OAAO;CAE7B,IAAM,IAAc,EAAc,EAAM,MAAM;CAG9C,OAFK,IAEE;EACN;EACA,aAAa,EAAc,EAAM,OAAO;EACxC,OAAO,EAAc,EAAM,OAAO;EAClC,cAAc,EAAc,EAAM,SAAS;EAC3C,cAAc,EAAc,EAAM,UAAU;EAC5C,YAAY,EAAc,EAAM,QAAQ;EACxC,mBAAmB,EAAc,EAAM,OAAO;CAC/C,IAVyB;AAW1B;AAEA,SAAgB,EAAuB,GAA8B;CACpE,IAAM,IAAgB,EAAI,KAAK;CAC/B,IAAI,CAAC,GAAe,OAAO,CAAC;CAE5B,IAAM,IAAS,EAAO,MAAM,CAAa,GACnC,IAAmB,EAAa,GAAQ,gBAAgB,CAAC,CAAC,SAAS,MAAU;EAClF,IAAI,MAAM,QAAQ,CAAK,GACtB,OAAO,EAAM,IAAI,CAAiB,CAAC,CAAC,QAAQ,MAAgC,MAAS,IAAI;EAG1F,IAAM,IAAY,EAAkB,CAAK;EACzC,OAAO,IAAY,CAAC,CAAS,IAAI,CAAC;CACnC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/adt/parseUserTransportsXml.ts","../../src/adt/fetchUserTransports.ts"],"sourcesContent":["import { arrayUniqueBy } from \"@ryuzaki13/react-foundation-lib/array\";\nimport { normalizeText } from \"@ryuzaki13/react-foundation-lib/formatters\";\nimport { isRecord } from \"@ryuzaki13/react-foundation-lib/validators\";\nimport { XMLParser } from \"fast-xml-parser\";\n\nimport type { UserTransport } from \"./types\";\n\nconst parser = new XMLParser({\n\tignoreAttributes: false,\n\tattributeNamePrefix: \"\",\n\tparseTagValue: false,\n\ttrimValues: true\n});\n\nfunction collectByKey(value: unknown, key: string, result: unknown[] = []): unknown[] {\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) {\n\t\t\tcollectByKey(item, key, result);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tif (!isRecord(value)) return result;\n\n\tfor (const [entryKey, entryValue] of Object.entries(value)) {\n\t\tif (entryKey === key) {\n\t\t\tresult.push(entryValue);\n\t\t}\n\n\t\tcollectByKey(entryValue, key, result);\n\t}\n\n\treturn result;\n}\n\nfunction toTransportRecord(value: unknown): UserTransport | null {\n\tif (!isRecord(value)) return null;\n\n\tconst transportNo = normalizeText(value.TRKORR);\n\tif (!transportNo) return null;\n\n\treturn {\n\t\ttransportNo,\n\t\tdescription: normalizeText(value.AS4TEXT),\n\t\towner: normalizeText(value.AS4USER),\n\t\ttargetSystem: normalizeText(value.TARSYSTEM),\n\t\tfunctionCode: normalizeText(value.TRFUNCTION),\n\t\tstatusCode: normalizeText(value.TRSTATUS),\n\t\tparentTransportNo: normalizeText(value.STRKORR)\n\t};\n}\n\nexport function parseUserTransportsXml(xml: string): UserTransport[] {\n\tconst normalizedXml = xml.trim();\n\tif (!normalizedXml) return [];\n\n\tconst parsed = parser.parse(normalizedXml) as unknown;\n\tconst transportHeaders = collectByKey(parsed, \"CTS_REQ_HEADER\").flatMap((entry) => {\n\t\tif (Array.isArray(entry)) {\n\t\t\treturn entry.map(toTransportRecord).filter((item): item is UserTransport => item !== null);\n\t\t}\n\n\t\tconst transport = toTransportRecord(entry);\n\t\treturn transport ? [transport] : [];\n\t});\n\n\tif (transportHeaders.length > 0) {\n\t\treturn arrayUniqueBy(transportHeaders, \"transportNo\");\n\t}\n\n\tconst transportNos = collectByKey(parsed, \"TRKORR\")\n\t\t.map((value) => normalizeText(value))\n\t\t.filter((value): value is string => value !== undefined)\n\t\t.map((transportNo): UserTransport => ({\n\t\t\ttransportNo,\n\t\t\tdescription: undefined,\n\t\t\towner: undefined,\n\t\t\ttargetSystem: undefined,\n\t\t\tfunctionCode: undefined,\n\t\t\tstatusCode: undefined,\n\t\t\tparentTransportNo: undefined\n\t\t}));\n\n\treturn arrayUniqueBy(transportNos, \"transportNo\");\n}\n","import { fetchBase } from \"../odata/transport\";\n\nimport { parseUserTransportsXml } from \"./parseUserTransportsXml\";\n\nconst USER_TRANSPORTS_URL = \"/sap/bc/adt/cts/transports?_action=FIND&trfunction=K\";\n\nfunction isHtmlResponse(text: string, contentType: string) {\n\treturn contentType.includes(\"text/html\") || /^\\s*<!doctype html/i.test(text) || /^\\s*<html/i.test(text);\n}\n\nexport async function fetchUserTransports() {\n\tconst response = await fetchBase(\n\t\tUSER_TRANSPORTS_URL,\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/xml, text/xml, */*\"\n\t\t\t}\n\t\t},\n\t\t\"\"\n\t);\n\n\tconst responseText = await response.text();\n\tconst contentType = (response.headers.get(\"Content-Type\") || \"\").toLowerCase();\n\n\tif (isHtmlResponse(responseText, contentType)) {\n\t\tthrow new Error(\"ADT вернул HTML вместо XML при запросе списка транспортов\");\n\t}\n\n\treturn parseUserTransportsXml(responseText);\n}\n"],"mappings":";;;;;;AAOA,IAAM,IAAS,IAAI,EAAU;CAC5B,kBAAkB;CAClB,qBAAqB;CACrB,eAAe;CACf,YAAY;AACb,CAAC;AAED,SAAS,EAAa,GAAgB,GAAa,IAAoB,CAAC,GAAc;CACrF,IAAI,MAAM,QAAQ,CAAK,GAAG;EACzB,KAAK,IAAM,KAAQ,GAClB,EAAa,GAAM,GAAK,CAAM;EAG/B,OAAO;CACR;CAEA,IAAI,CAAC,EAAS,CAAK,GAAG,OAAO;CAE7B,KAAK,IAAM,CAAC,GAAU,MAAe,OAAO,QAAQ,CAAK,GAKxD,AAJI,MAAa,KAChB,EAAO,KAAK,CAAU,GAGvB,EAAa,GAAY,GAAK,CAAM;CAGrC,OAAO;AACR;AAEA,SAAS,EAAkB,GAAsC;CAChE,IAAI,CAAC,EAAS,CAAK,GAAG,OAAO;CAE7B,IAAM,IAAc,EAAc,EAAM,MAAM;CAG9C,OAFK,IAEE;EACN;EACA,aAAa,EAAc,EAAM,OAAO;EACxC,OAAO,EAAc,EAAM,OAAO;EAClC,cAAc,EAAc,EAAM,SAAS;EAC3C,cAAc,EAAc,EAAM,UAAU;EAC5C,YAAY,EAAc,EAAM,QAAQ;EACxC,mBAAmB,EAAc,EAAM,OAAO;CAC/C,IAVyB;AAW1B;AAEA,SAAgB,EAAuB,GAA8B;CACpE,IAAM,IAAgB,EAAI,KAAK;CAC/B,IAAI,CAAC,GAAe,OAAO,CAAC;CAE5B,IAAM,IAAS,EAAO,MAAM,CAAa,GACnC,IAAmB,EAAa,GAAQ,gBAAgB,CAAC,CAAC,SAAS,MAAU;EAClF,IAAI,MAAM,QAAQ,CAAK,GACtB,OAAO,EAAM,IAAI,CAAiB,CAAC,CAAC,QAAQ,MAAgC,MAAS,IAAI;EAG1F,IAAM,IAAY,EAAkB,CAAK;EACzC,OAAO,IAAY,CAAC,CAAS,IAAI,CAAC;CACnC,CAAC;CAED,IAAI,EAAiB,SAAS,GAC7B,OAAO,EAAc,GAAkB,aAAa;CAGrD,IAAM,IAAe,EAAa,GAAQ,QAAQ,CAAC,CACjD,KAAK,MAAU,EAAc,CAAK,CAAC,CAAC,CACpC,QAAQ,MAA2B,MAAU,KAAA,CAAS,CAAC,CACvD,KAAK,OAAgC;EACrC;EACA,aAAa,KAAA;EACb,OAAO,KAAA;EACP,cAAc,KAAA;EACd,cAAc,KAAA;EACd,YAAY,KAAA;EACZ,mBAAmB,KAAA;CACpB,EAAE;CAEH,OAAO,EAAc,GAAc,aAAa;AACjD;;;ACjFA,IAAM,IAAsB;AAE5B,SAAS,EAAe,GAAc,GAAqB;CAC1D,OAAO,EAAY,SAAS,WAAW,KAAK,sBAAsB,KAAK,CAAI,KAAK,aAAa,KAAK,CAAI;AACvG;AAEA,eAAsB,IAAsB;CAC3C,IAAM,IAAW,MAAM,EACtB,GACA;EACC,QAAQ;EACR,SAAS,EACR,QAAQ,iCACT;CACD,GACA,EACD,GAEM,IAAe,MAAM,EAAS,KAAK;CAGzC,IAAI,EAAe,IAFE,EAAS,QAAQ,IAAI,cAAc,KAAK,GAAA,CAAI,YAEhC,CAAW,GAC3C,MAAU,MAAM,2DAA2D;CAG5E,OAAO,EAAuB,CAAY;AAC3C"}
|
package/dist/async/index.js
CHANGED
package/dist/async/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/async/AsyncTasksError.ts","../../src/async/ConcurrencyPartialError.ts","../../src/async/runAsyncTasks.ts","../../src/async/runConcurrentTasks.ts"],"sourcesContent":["import type { RunAsyncTasksResult } from \"./runAsyncTasks\";\n\nexport class AsyncTasksError<TResult = unknown> extends Error {\n\tpublic readonly result: RunAsyncTasksResult<TResult>;\n\n\tconstructor(message: string, result: RunAsyncTasksResult<TResult>) {\n\t\tsuper(message);\n\t\tthis.name = \"AsyncTasksError\";\n\t\tthis.result = result;\n\t}\n}\n","import { RunConcurrentTasksResult } from \"./runConcurrentTasks\";\n\nexport class ConcurrencyPartialError<TInput, TResult> extends Error {\n\tpublic readonly result: RunConcurrentTasksResult<TInput, TResult>;\n\n\tconstructor(message: string, result: RunConcurrentTasksResult<TInput, TResult>) {\n\t\tsuper(message);\n\t\tthis.name = \"ConcurrencyPartialError\";\n\t\tthis.result = result;\n\t}\n}\n","import { AsyncTasksError } from \"./AsyncTasksError\";\n\nexport type AsyncTask<TResult = unknown> = {\n\treadonly name: string;\n\treadonly run: () => Promise<TResult>;\n};\n\nexport type AsyncTaskSuccess<TResult> = {\n\treadonly status: \"fulfilled\";\n\treadonly index: number;\n\treadonly name: string;\n\treadonly data: TResult;\n};\n\nexport type AsyncTaskFailure = {\n\treadonly status: \"rejected\";\n\treadonly index: number;\n\treadonly name: string;\n\treadonly error: unknown;\n};\n\nexport type AsyncTaskSettled<TResult> = AsyncTaskSuccess<TResult> | AsyncTaskFailure;\n\nexport type RunAsyncTasksResult<TResult = unknown> = {\n\treadonly settled: readonly AsyncTaskSettled<TResult>[];\n\treadonly successes: readonly AsyncTaskSuccess<TResult>[];\n\treadonly errors: readonly AsyncTaskFailure[];\n\treadonly summary: {\n\t\treadonly total: number;\n\t\treadonly succeeded: number;\n\t\treadonly failed: number;\n\t};\n};\n\nexport type RunAsyncTasksOptions = {\n\treadonly errorMessage?: string;\n};\n\nconst DEFAULT_ASYNC_TASKS_ERROR_MESSAGE = \"Не удалось выполнить все асинхронные задачи.\";\n\nasync function runSingleAsyncTask<TResult>(task: AsyncTask<TResult>, index: number): Promise<AsyncTaskSettled<TResult>> {\n\ttry {\n\t\tconst data = await task.run();\n\n\t\treturn {\n\t\t\tstatus: \"fulfilled\",\n\t\t\tindex,\n\t\t\tname: task.name,\n\t\t\tdata\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\tstatus: \"rejected\",\n\t\t\tindex,\n\t\t\tname: task.name,\n\t\t\terror\n\t\t};\n\t}\n}\n\nfunction splitAsyncTaskSettled<TResult>(\n\tsettled: readonly AsyncTaskSettled<TResult>[]\n): Pick<RunAsyncTasksResult<TResult>, \"successes\" | \"errors\"> {\n\tconst successes: AsyncTaskSuccess<TResult>[] = [];\n\tconst errors: AsyncTaskFailure[] = [];\n\n\tfor (const item of settled) {\n\t\tswitch (item.status) {\n\t\t\tcase \"fulfilled\": {\n\t\t\t\tsuccesses.push(item);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"rejected\": {\n\t\t\t\terrors.push(item);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst checker: never = item;\n\t\t\t\tvoid checker;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tsuccesses,\n\t\terrors\n\t};\n}\n\nfunction createRunAsyncTasksResult<TResult>(settled: readonly AsyncTaskSettled<TResult>[]): RunAsyncTasksResult<TResult> {\n\tconst { successes, errors } = splitAsyncTaskSettled(settled);\n\n\treturn {\n\t\tsettled,\n\t\tsuccesses,\n\t\terrors,\n\t\tsummary: {\n\t\t\ttotal: settled.length,\n\t\t\tsucceeded: successes.length,\n\t\t\tfailed: errors.length\n\t\t}\n\t};\n}\n\nexport async function runAsyncTasks<TResult>(\n\ttasks: readonly AsyncTask<TResult>[],\n\toptions: RunAsyncTasksOptions = {}\n): Promise<RunAsyncTasksResult<TResult>> {\n\tconst settled = await Promise.all(tasks.map((task, index) => runSingleAsyncTask(task, index)));\n\tconst result = createRunAsyncTasksResult(settled);\n\n\tif (result.errors.length > 0) {\n\t\tthrow new AsyncTasksError(options.errorMessage ?? DEFAULT_ASYNC_TASKS_ERROR_MESSAGE, result);\n\t}\n\n\treturn result;\n}\n","export type ConcurrentTaskContext = {\n\t/**\n\t * Индекс элемента во входном массиве.\n\t */\n\tindex: number;\n\n\t/**\n\t * Внешний AbortSignal.\n\t * Важно: helper сам не может \"магически\" отменить уже начатую async-операцию.\n\t * Для реальной отмены нужно пробрасывать signal внутрь task\n\t * и чтобы сама реализация task его поддерживала.\n\t */\n\tsignal?: AbortSignal;\n};\n\nexport type ConcurrentTaskFn<TInput, TResult> = (input: TInput, context: ConcurrentTaskContext) => Promise<TResult>;\n\nexport type ConcurrentTaskSuccess<TInput, TResult> = {\n\tstatus: \"fulfilled\";\n\tindex: number;\n\tinput: TInput;\n\tdata: TResult;\n};\n\nexport type ConcurrentTaskError<TInput> = {\n\tstatus: \"rejected\";\n\tindex: number;\n\tinput: TInput;\n\terror: unknown;\n};\n\nexport type ConcurrentTaskSettled<TInput, TResult> = ConcurrentTaskSuccess<TInput, TResult> | ConcurrentTaskError<TInput>;\n\nexport type ConcurrentTaskUnprocessed<TInput> = {\n\tindex: number;\n\tinput: TInput;\n};\n\nexport type ConcurrentTaskProgress<TInput, TResult> = {\n\ttotal: number;\n\tcompleted: number;\n\tsucceeded: number;\n\tfailed: number;\n\trunning: number;\n\tpending: number;\n\tpercentage: number;\n\taborted: boolean;\n\tlastSettled?: ConcurrentTaskSettled<TInput, TResult>;\n};\n\nexport type RunConcurrentTasksOptions<TInput, TResult> = {\n\t/**\n\t * Максимальное количество одновременно выполняемых задач.\n\t *\n\t * @default 4\n\t */\n\tconcurrency?: number;\n\n\t/**\n\t * Внешний AbortSignal.\n\t *\n\t * Поведение при abort:\n\t * - новые задачи больше не стартуют;\n\t * - уже начатые задачи helper не прерывает сам;\n\t * - функция возвращает partial result с `aborted: true`.\n\t */\n\tsignal?: AbortSignal;\n\n\t/**\n\t * Вызывается после каждого завершенного элемента.\n\t *\n\t * ### Важно: callback не должен бросать исключения.\n\t */\n\tonProgress?: (progress: ConcurrentTaskProgress<TInput, TResult>) => void;\n\n\t/**\n\t * Вызывается при успешной обработке одного элемента.\n\t *\n\t * ### Важно: callback не должен бросать исключения.\n\t */\n\tonItemSuccess?: (item: ConcurrentTaskSuccess<TInput, TResult>) => void;\n\n\t/**\n\t * Вызывается при ошибке одного элемента.\n\t *\n\t * ### Важно: callback не должен бросать исключения.\n\t */\n\tonItemError?: (item: ConcurrentTaskError<TInput>) => void;\n};\n\nexport type RunConcurrentTasksResult<TInput, TResult> = {\n\t/**\n\t * Итоги по каждому обработанному элементу в порядке исходного массива.\n\t * Необработанные элементы сюда не попадают.\n\t */\n\tsettled: ConcurrentTaskSettled<TInput, TResult>[];\n\n\t/**\n\t * Только успешные элементы.\n\t */\n\tsuccesses: ConcurrentTaskSuccess<TInput, TResult>[];\n\n\t/**\n\t * Только ошибки.\n\t */\n\terrors: ConcurrentTaskError<TInput>[];\n\n\t/**\n\t * Элементы, которые не были запущены.\n\t * Обычно это актуально при abort.\n\t */\n\tunprocessed: ConcurrentTaskUnprocessed<TInput>[];\n\n\t/**\n\t * Был ли batch прерван внешним signal.\n\t */\n\taborted: boolean;\n\n\t/**\n\t * Сводка для UI/логов.\n\t */\n\tsummary: {\n\t\ttotal: number;\n\t\tcompleted: number;\n\t\tsucceeded: number;\n\t\tfailed: number;\n\t\tunprocessed: number;\n\t};\n};\n\nfunction validateConcurrency(concurrency: number): void {\n\tif (!Number.isInteger(concurrency)) {\n\t\tthrow new TypeError(\"concurrency должен быть целым числом\");\n\t}\n\n\tif (concurrency < 1) {\n\t\tthrow new RangeError(\"concurrency должен быть >= 1\");\n\t}\n}\n\n/**\n * Выполняет задачи над набором входных данных с ограничением по параллелизму.\n *\n * Ключевые свойства:\n * - не останавливается на первой ошибке;\n * - всегда собирает полный список success/error для уже стартовавших задач;\n * - поддерживает progress callbacks;\n * - поддерживает abort на уровне постановки новых задач;\n * - не зависит от конкретного transport/query stack.\n *\n * Исключения:\n * - выбрасывает только при невалидных аргументах;\n * - ошибки отдельных задач НЕ выбрасываются наружу, а попадают в `result.errors`.\n */\nexport async function runConcurrentTasks<TInput, TResult>(\n\tinputs: readonly TInput[],\n\ttask: ConcurrentTaskFn<TInput, TResult>,\n\toptions: RunConcurrentTasksOptions<TInput, TResult> = {}\n): Promise<RunConcurrentTasksResult<TInput, TResult>> {\n\tconst { concurrency = 4, signal, onProgress, onItemSuccess, onItemError } = options;\n\n\tvalidateConcurrency(concurrency);\n\n\tif (inputs.length === 0) {\n\t\treturn {\n\t\t\tsettled: [],\n\t\t\tsuccesses: [],\n\t\t\terrors: [],\n\t\t\tunprocessed: [],\n\t\t\taborted: Boolean(signal?.aborted),\n\t\t\tsummary: {\n\t\t\t\ttotal: 0,\n\t\t\t\tcompleted: 0,\n\t\t\t\tsucceeded: 0,\n\t\t\t\tfailed: 0,\n\t\t\t\tunprocessed: 0\n\t\t\t}\n\t\t};\n\t}\n\n\tconst settledByIndex = new Array<ConcurrentTaskSettled<TInput, TResult> | undefined>(inputs.length);\n\n\tlet nextIndex = 0;\n\tlet completed = 0;\n\tlet succeeded = 0;\n\tlet failed = 0;\n\tlet running = 0;\n\n\tconst isAborted = (): boolean => Boolean(signal?.aborted);\n\n\tconst emitProgress = (lastSettled?: ConcurrentTaskSettled<TInput, TResult>): void => {\n\t\tonProgress?.({\n\t\t\ttotal: inputs.length,\n\t\t\tcompleted,\n\t\t\tsucceeded,\n\t\t\tfailed,\n\t\t\trunning,\n\t\t\tpending: Math.max(inputs.length - completed - running, 0),\n\t\t\tpercentage: inputs.length === 0 ? 100 : Math.round((completed / inputs.length) * 100),\n\t\t\taborted: isAborted(),\n\t\t\tlastSettled\n\t\t});\n\t};\n\n\tconst workerCount = Math.min(concurrency, inputs.length);\n\n\tconst worker = async (): Promise<void> => {\n\t\twhile (true) {\n\t\t\tif (isAborted()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = nextIndex;\n\t\t\tnextIndex += 1;\n\n\t\t\tif (currentIndex >= inputs.length) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst input = inputs[currentIndex];\n\t\t\trunning += 1;\n\n\t\t\ttry {\n\t\t\t\tconst data = await task(input, {\n\t\t\t\t\tindex: currentIndex,\n\t\t\t\t\tsignal\n\t\t\t\t});\n\n\t\t\t\tconst item: ConcurrentTaskSuccess<TInput, TResult> = {\n\t\t\t\t\tstatus: \"fulfilled\",\n\t\t\t\t\tindex: currentIndex,\n\t\t\t\t\tinput,\n\t\t\t\t\tdata\n\t\t\t\t};\n\n\t\t\t\tsettledByIndex[currentIndex] = item;\n\t\t\t\tsucceeded += 1;\n\t\t\t\tonItemSuccess?.(item);\n\t\t\t} catch (error) {\n\t\t\t\tconst item: ConcurrentTaskError<TInput> = {\n\t\t\t\t\tstatus: \"rejected\",\n\t\t\t\t\tindex: currentIndex,\n\t\t\t\t\tinput,\n\t\t\t\t\terror\n\t\t\t\t};\n\n\t\t\t\tsettledByIndex[currentIndex] = item;\n\t\t\t\tfailed += 1;\n\t\t\t\tonItemError?.(item);\n\t\t\t} finally {\n\t\t\t\trunning -= 1;\n\t\t\t\tcompleted += 1;\n\n\t\t\t\tconst settledItem = settledByIndex[currentIndex];\n\t\t\t\tif (settledItem) {\n\t\t\t\t\temitProgress(settledItem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tawait Promise.all(Array.from({ length: workerCount }, () => worker()));\n\n\tconst settled: ConcurrentTaskSettled<TInput, TResult>[] = [];\n\tconst successes: ConcurrentTaskSuccess<TInput, TResult>[] = [];\n\tconst errors: ConcurrentTaskError<TInput>[] = [];\n\tconst unprocessed: ConcurrentTaskUnprocessed<TInput>[] = [];\n\n\tfor (const [index, input] of inputs.entries()) {\n\t\tconst item = settledByIndex[index];\n\n\t\tif (!item) {\n\t\t\tunprocessed.push({ index, input });\n\t\t\tcontinue;\n\t\t}\n\n\t\tsettled.push(item);\n\n\t\tif (item.status === \"fulfilled\") {\n\t\t\tsuccesses.push(item);\n\t\t} else {\n\t\t\terrors.push(item);\n\t\t}\n\t}\n\n\treturn {\n\t\tsettled,\n\t\tsuccesses,\n\t\terrors,\n\t\tunprocessed,\n\t\taborted: isAborted(),\n\t\tsummary: {\n\t\t\ttotal: inputs.length,\n\t\t\tcompleted: settled.length,\n\t\t\tsucceeded: successes.length,\n\t\t\tfailed: errors.length,\n\t\t\tunprocessed: unprocessed.length\n\t\t}\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/async/AsyncTasksError.ts","../../src/async/ConcurrencyPartialError.ts","../../src/async/runAsyncTasks.ts","../../src/async/runConcurrentTasks.ts"],"sourcesContent":["import type { RunAsyncTasksResult } from \"./runAsyncTasks\";\n\nexport class AsyncTasksError<TResult = unknown> extends Error {\n\tpublic readonly result: RunAsyncTasksResult<TResult>;\n\n\tconstructor(message: string, result: RunAsyncTasksResult<TResult>) {\n\t\tsuper(message);\n\t\tthis.name = \"AsyncTasksError\";\n\t\tthis.result = result;\n\t}\n}\n","import { RunConcurrentTasksResult } from \"./runConcurrentTasks\";\n\nexport class ConcurrencyPartialError<TInput, TResult> extends Error {\n\tpublic readonly result: RunConcurrentTasksResult<TInput, TResult>;\n\n\tconstructor(message: string, result: RunConcurrentTasksResult<TInput, TResult>) {\n\t\tsuper(message);\n\t\tthis.name = \"ConcurrencyPartialError\";\n\t\tthis.result = result;\n\t}\n}\n","import { AsyncTasksError } from \"./AsyncTasksError\";\n\nexport type AsyncTask<TResult = unknown> = {\n\treadonly name: string;\n\treadonly run: () => Promise<TResult>;\n};\n\nexport type AsyncTaskSuccess<TResult> = {\n\treadonly status: \"fulfilled\";\n\treadonly index: number;\n\treadonly name: string;\n\treadonly data: TResult;\n};\n\nexport type AsyncTaskFailure = {\n\treadonly status: \"rejected\";\n\treadonly index: number;\n\treadonly name: string;\n\treadonly error: unknown;\n};\n\nexport type AsyncTaskSettled<TResult> = AsyncTaskSuccess<TResult> | AsyncTaskFailure;\n\nexport type RunAsyncTasksResult<TResult = unknown> = {\n\treadonly settled: readonly AsyncTaskSettled<TResult>[];\n\treadonly successes: readonly AsyncTaskSuccess<TResult>[];\n\treadonly errors: readonly AsyncTaskFailure[];\n\treadonly summary: {\n\t\treadonly total: number;\n\t\treadonly succeeded: number;\n\t\treadonly failed: number;\n\t};\n};\n\nexport type RunAsyncTasksOptions = {\n\treadonly errorMessage?: string;\n};\n\nconst DEFAULT_ASYNC_TASKS_ERROR_MESSAGE = \"Не удалось выполнить все асинхронные задачи.\";\n\nasync function runSingleAsyncTask<TResult>(task: AsyncTask<TResult>, index: number): Promise<AsyncTaskSettled<TResult>> {\n\ttry {\n\t\tconst data = await task.run();\n\n\t\treturn {\n\t\t\tstatus: \"fulfilled\",\n\t\t\tindex,\n\t\t\tname: task.name,\n\t\t\tdata\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\tstatus: \"rejected\",\n\t\t\tindex,\n\t\t\tname: task.name,\n\t\t\terror\n\t\t};\n\t}\n}\n\nfunction splitAsyncTaskSettled<TResult>(\n\tsettled: readonly AsyncTaskSettled<TResult>[]\n): Pick<RunAsyncTasksResult<TResult>, \"successes\" | \"errors\"> {\n\tconst successes: AsyncTaskSuccess<TResult>[] = [];\n\tconst errors: AsyncTaskFailure[] = [];\n\n\tfor (const item of settled) {\n\t\tswitch (item.status) {\n\t\t\tcase \"fulfilled\": {\n\t\t\t\tsuccesses.push(item);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"rejected\": {\n\t\t\t\terrors.push(item);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst checker: never = item;\n\t\t\t\tvoid checker;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tsuccesses,\n\t\terrors\n\t};\n}\n\nfunction createRunAsyncTasksResult<TResult>(settled: readonly AsyncTaskSettled<TResult>[]): RunAsyncTasksResult<TResult> {\n\tconst { successes, errors } = splitAsyncTaskSettled(settled);\n\n\treturn {\n\t\tsettled,\n\t\tsuccesses,\n\t\terrors,\n\t\tsummary: {\n\t\t\ttotal: settled.length,\n\t\t\tsucceeded: successes.length,\n\t\t\tfailed: errors.length\n\t\t}\n\t};\n}\n\nexport async function runAsyncTasks<TResult>(\n\ttasks: readonly AsyncTask<TResult>[],\n\toptions: RunAsyncTasksOptions = {}\n): Promise<RunAsyncTasksResult<TResult>> {\n\tconst settled = await Promise.all(tasks.map((task, index) => runSingleAsyncTask(task, index)));\n\tconst result = createRunAsyncTasksResult(settled);\n\n\tif (result.errors.length > 0) {\n\t\tthrow new AsyncTasksError(options.errorMessage ?? DEFAULT_ASYNC_TASKS_ERROR_MESSAGE, result);\n\t}\n\n\treturn result;\n}\n","export type ConcurrentTaskContext = {\n\t/**\n\t * Индекс элемента во входном массиве.\n\t */\n\tindex: number;\n\n\t/**\n\t * Внешний AbortSignal.\n\t * Важно: helper сам не может \"магически\" отменить уже начатую async-операцию.\n\t * Для реальной отмены нужно пробрасывать signal внутрь task\n\t * и чтобы сама реализация task его поддерживала.\n\t */\n\tsignal?: AbortSignal;\n};\n\nexport type ConcurrentTaskFn<TInput, TResult> = (input: TInput, context: ConcurrentTaskContext) => Promise<TResult>;\n\nexport type ConcurrentTaskSuccess<TInput, TResult> = {\n\tstatus: \"fulfilled\";\n\tindex: number;\n\tinput: TInput;\n\tdata: TResult;\n};\n\nexport type ConcurrentTaskError<TInput> = {\n\tstatus: \"rejected\";\n\tindex: number;\n\tinput: TInput;\n\terror: unknown;\n};\n\nexport type ConcurrentTaskSettled<TInput, TResult> = ConcurrentTaskSuccess<TInput, TResult> | ConcurrentTaskError<TInput>;\n\nexport type ConcurrentTaskUnprocessed<TInput> = {\n\tindex: number;\n\tinput: TInput;\n};\n\nexport type ConcurrentTaskProgress<TInput, TResult> = {\n\ttotal: number;\n\tcompleted: number;\n\tsucceeded: number;\n\tfailed: number;\n\trunning: number;\n\tpending: number;\n\tpercentage: number;\n\taborted: boolean;\n\tlastSettled?: ConcurrentTaskSettled<TInput, TResult>;\n};\n\nexport type RunConcurrentTasksOptions<TInput, TResult> = {\n\t/**\n\t * Максимальное количество одновременно выполняемых задач.\n\t *\n\t * @default 4\n\t */\n\tconcurrency?: number;\n\n\t/**\n\t * Внешний AbortSignal.\n\t *\n\t * Поведение при abort:\n\t * - новые задачи больше не стартуют;\n\t * - уже начатые задачи helper не прерывает сам;\n\t * - функция возвращает partial result с `aborted: true`.\n\t */\n\tsignal?: AbortSignal;\n\n\t/**\n\t * Вызывается после каждого завершенного элемента.\n\t *\n\t * ### Важно: callback не должен бросать исключения.\n\t */\n\tonProgress?: (progress: ConcurrentTaskProgress<TInput, TResult>) => void;\n\n\t/**\n\t * Вызывается при успешной обработке одного элемента.\n\t *\n\t * ### Важно: callback не должен бросать исключения.\n\t */\n\tonItemSuccess?: (item: ConcurrentTaskSuccess<TInput, TResult>) => void;\n\n\t/**\n\t * Вызывается при ошибке одного элемента.\n\t *\n\t * ### Важно: callback не должен бросать исключения.\n\t */\n\tonItemError?: (item: ConcurrentTaskError<TInput>) => void;\n};\n\nexport type RunConcurrentTasksResult<TInput, TResult> = {\n\t/**\n\t * Итоги по каждому обработанному элементу в порядке исходного массива.\n\t * Необработанные элементы сюда не попадают.\n\t */\n\tsettled: ConcurrentTaskSettled<TInput, TResult>[];\n\n\t/**\n\t * Только успешные элементы.\n\t */\n\tsuccesses: ConcurrentTaskSuccess<TInput, TResult>[];\n\n\t/**\n\t * Только ошибки.\n\t */\n\terrors: ConcurrentTaskError<TInput>[];\n\n\t/**\n\t * Элементы, которые не были запущены.\n\t * Обычно это актуально при abort.\n\t */\n\tunprocessed: ConcurrentTaskUnprocessed<TInput>[];\n\n\t/**\n\t * Был ли batch прерван внешним signal.\n\t */\n\taborted: boolean;\n\n\t/**\n\t * Сводка для UI/логов.\n\t */\n\tsummary: {\n\t\ttotal: number;\n\t\tcompleted: number;\n\t\tsucceeded: number;\n\t\tfailed: number;\n\t\tunprocessed: number;\n\t};\n};\n\nfunction validateConcurrency(concurrency: number): void {\n\tif (!Number.isInteger(concurrency)) {\n\t\tthrow new TypeError(\"concurrency должен быть целым числом\");\n\t}\n\n\tif (concurrency < 1) {\n\t\tthrow new RangeError(\"concurrency должен быть >= 1\");\n\t}\n}\n\n/**\n * Выполняет задачи над набором входных данных с ограничением по параллелизму.\n *\n * Ключевые свойства:\n * - не останавливается на первой ошибке;\n * - всегда собирает полный список success/error для уже стартовавших задач;\n * - поддерживает progress callbacks;\n * - поддерживает abort на уровне постановки новых задач;\n * - не зависит от конкретного transport/query stack.\n *\n * Исключения:\n * - выбрасывает только при невалидных аргументах;\n * - ошибки отдельных задач НЕ выбрасываются наружу, а попадают в `result.errors`.\n */\nexport async function runConcurrentTasks<TInput, TResult>(\n\tinputs: readonly TInput[],\n\ttask: ConcurrentTaskFn<TInput, TResult>,\n\toptions: RunConcurrentTasksOptions<TInput, TResult> = {}\n): Promise<RunConcurrentTasksResult<TInput, TResult>> {\n\tconst { concurrency = 4, signal, onProgress, onItemSuccess, onItemError } = options;\n\n\tvalidateConcurrency(concurrency);\n\n\tif (inputs.length === 0) {\n\t\treturn {\n\t\t\tsettled: [],\n\t\t\tsuccesses: [],\n\t\t\terrors: [],\n\t\t\tunprocessed: [],\n\t\t\taborted: Boolean(signal?.aborted),\n\t\t\tsummary: {\n\t\t\t\ttotal: 0,\n\t\t\t\tcompleted: 0,\n\t\t\t\tsucceeded: 0,\n\t\t\t\tfailed: 0,\n\t\t\t\tunprocessed: 0\n\t\t\t}\n\t\t};\n\t}\n\n\tconst settledByIndex = new Array<ConcurrentTaskSettled<TInput, TResult> | undefined>(inputs.length);\n\n\tlet nextIndex = 0;\n\tlet completed = 0;\n\tlet succeeded = 0;\n\tlet failed = 0;\n\tlet running = 0;\n\n\tconst isAborted = (): boolean => Boolean(signal?.aborted);\n\n\tconst emitProgress = (lastSettled?: ConcurrentTaskSettled<TInput, TResult>): void => {\n\t\tonProgress?.({\n\t\t\ttotal: inputs.length,\n\t\t\tcompleted,\n\t\t\tsucceeded,\n\t\t\tfailed,\n\t\t\trunning,\n\t\t\tpending: Math.max(inputs.length - completed - running, 0),\n\t\t\tpercentage: inputs.length === 0 ? 100 : Math.round((completed / inputs.length) * 100),\n\t\t\taborted: isAborted(),\n\t\t\tlastSettled\n\t\t});\n\t};\n\n\tconst workerCount = Math.min(concurrency, inputs.length);\n\n\tconst worker = async (): Promise<void> => {\n\t\twhile (true) {\n\t\t\tif (isAborted()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = nextIndex;\n\t\t\tnextIndex += 1;\n\n\t\t\tif (currentIndex >= inputs.length) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst input = inputs[currentIndex];\n\t\t\trunning += 1;\n\n\t\t\ttry {\n\t\t\t\tconst data = await task(input, {\n\t\t\t\t\tindex: currentIndex,\n\t\t\t\t\tsignal\n\t\t\t\t});\n\n\t\t\t\tconst item: ConcurrentTaskSuccess<TInput, TResult> = {\n\t\t\t\t\tstatus: \"fulfilled\",\n\t\t\t\t\tindex: currentIndex,\n\t\t\t\t\tinput,\n\t\t\t\t\tdata\n\t\t\t\t};\n\n\t\t\t\tsettledByIndex[currentIndex] = item;\n\t\t\t\tsucceeded += 1;\n\t\t\t\tonItemSuccess?.(item);\n\t\t\t} catch (error) {\n\t\t\t\tconst item: ConcurrentTaskError<TInput> = {\n\t\t\t\t\tstatus: \"rejected\",\n\t\t\t\t\tindex: currentIndex,\n\t\t\t\t\tinput,\n\t\t\t\t\terror\n\t\t\t\t};\n\n\t\t\t\tsettledByIndex[currentIndex] = item;\n\t\t\t\tfailed += 1;\n\t\t\t\tonItemError?.(item);\n\t\t\t} finally {\n\t\t\t\trunning -= 1;\n\t\t\t\tcompleted += 1;\n\n\t\t\t\tconst settledItem = settledByIndex[currentIndex];\n\t\t\t\tif (settledItem) {\n\t\t\t\t\temitProgress(settledItem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tawait Promise.all(Array.from({ length: workerCount }, () => worker()));\n\n\tconst settled: ConcurrentTaskSettled<TInput, TResult>[] = [];\n\tconst successes: ConcurrentTaskSuccess<TInput, TResult>[] = [];\n\tconst errors: ConcurrentTaskError<TInput>[] = [];\n\tconst unprocessed: ConcurrentTaskUnprocessed<TInput>[] = [];\n\n\tfor (const [index, input] of inputs.entries()) {\n\t\tconst item = settledByIndex[index];\n\n\t\tif (!item) {\n\t\t\tunprocessed.push({ index, input });\n\t\t\tcontinue;\n\t\t}\n\n\t\tsettled.push(item);\n\n\t\tif (item.status === \"fulfilled\") {\n\t\t\tsuccesses.push(item);\n\t\t} else {\n\t\t\terrors.push(item);\n\t\t}\n\t}\n\n\treturn {\n\t\tsettled,\n\t\tsuccesses,\n\t\terrors,\n\t\tunprocessed,\n\t\taborted: isAborted(),\n\t\tsummary: {\n\t\t\ttotal: inputs.length,\n\t\t\tcompleted: settled.length,\n\t\t\tsucceeded: successes.length,\n\t\t\tfailed: errors.length,\n\t\t\tunprocessed: unprocessed.length\n\t\t}\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -66,7 +66,8 @@ function oe(e, t) {
|
|
|
66
66
|
return Array.from(new Set(n)).slice(0, te);
|
|
67
67
|
}
|
|
68
68
|
function se(e, t) {
|
|
69
|
-
|
|
69
|
+
let n = t?.body?.textContent ?? e.replace(/<script\b[\s\S]*?<\/script>/gi, " ").replace(/<style\b[\s\S]*?<\/style>/gi, " ").replace(/<[^>]+>/g, " ");
|
|
70
|
+
return a(n, ne);
|
|
70
71
|
}
|
|
71
72
|
function ce(e) {
|
|
72
73
|
let t = re(e);
|
|
@@ -506,4 +507,4 @@ function Se(e, t) {
|
|
|
506
507
|
//#endregion
|
|
507
508
|
export { u as C, l as S, h as _, be as a, s as b, me as c, D as d, ue as f, f as g, p as h, xe as i, O as l, ee as m, Se as n, Q as o, m as p, $ as r, ye as s, Z as t, S as u, g as v, d as w, c as x, _ as y };
|
|
508
509
|
|
|
509
|
-
//# sourceMappingURL=fetch-
|
|
510
|
+
//# sourceMappingURL=fetch-Cq29VQlt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-PmN9NBra.js","names":[],"sources":["../../src/odata/odataProjectAdapter.ts","../../src/odata/transport/url.ts","../../src/odata/transport/errorReport.ts","../../src/odata/transport/SsoRequiredError.ts","../../src/odata/transport/fetch.ts"],"sourcesContent":["import type { BaseURLType } from \"./transport/types\";\n\nexport type ODataProjectTechnicalEndpoint = {\n\tservice: string;\n\ttarget: string;\n\tbaseUrl?: BaseURLType;\n};\n\nexport type ODataProjectAdapter = {\n\t/**\n\t * OData-сервис, который в dev/preview нужно проксировать через DP0.\n\t * В проектах без SAP/OData оставляется пустым.\n\t */\n\tdevDp0Service?: string;\n\tresolveSapClient?: () => string | null | undefined;\n\tmetadataVersion?: ODataProjectTechnicalEndpoint;\n\tcollectionUpdates?: ODataProjectTechnicalEndpoint;\n};\n\nlet odataProjectAdapter: ODataProjectAdapter = {};\n\nexport function configureODataProjectAdapter(adapter: ODataProjectAdapter) {\n\todataProjectAdapter = adapter;\n}\n\nexport function getODataProjectAdapter() {\n\treturn odataProjectAdapter;\n}\n\nexport function normalizeODataServiceName(service: string) {\n\treturn service.split(\";\")[0] ?? service;\n}\n\nexport function resolveODataBaseUrl(service: string, baseUrl?: BaseURLType): BaseURLType {\n\tconst devDp0Service = odataProjectAdapter.devDp0Service;\n\tif ((__DEV__ || __PREVIEW__) && devDp0Service && normalizeODataServiceName(service) === normalizeODataServiceName(devDp0Service)) {\n\t\treturn \"odataDp0\";\n\t}\n\n\treturn baseUrl ?? \"odata\";\n}\n\nexport function resolveODataSapClient() {\n\treturn odataProjectAdapter.resolveSapClient?.() ?? null;\n}\n","import { BaseURLType } from \"./types\";\n\nexport const BaseODataURL = \"/sap/opu/odata/sap\";\n/**\n * DP0-прокси используется только для сервиса, который проект явно указывает\n * через `odataProjectAdapter.devDp0Service`.\n */\nexport const BaseODataDp0URL = __DEV__ || __PREVIEW__ ? \"/sap-dp0/opu/odata/sap\" : \"/sap/opu/odata/sap\";\nexport const BaseODataUI2URL = __DEV__ || __PREVIEW__ ? \"/sap-dp0/opu/odata/UI2\" : \"/sap/opu/odata/UI2\";\nexport const BaseAppConfigURL = __BASE_APP_CONFIG_URL__;\n\nexport const BaseUrlMap = Object.freeze<Record<BaseURLType, string>>({\n\t[\"\"]: \"\",\n\todata: BaseODataURL,\n\todataDp0: BaseODataDp0URL,\n\todataUi2: BaseODataUI2URL,\n\tconfig: BaseAppConfigURL\n});\n\nexport function getInputUrl(input: RequestInfo) {\n\tif (typeof input === \"string\") return input;\n\tif (typeof Request !== \"undefined\" && input instanceof Request) {\n\t\treturn input.url;\n\t}\n\treturn input.toString();\n}\n\nexport function normalizeRelativePath(url: string) {\n\tconst path = url.split(\"?\")[0]?.split(\"#\")[0] ?? \"\";\n\tif (!path) return \"/\";\n\treturn path.startsWith(\"/\") ? path : `/${path}`;\n}\n","import { reportTransportError } from \"@ryuzaki13/react-foundation-lib/error-report\";\nimport { truncateText } from \"@ryuzaki13/react-foundation-lib/formatters\";\n\nimport { FetchErrorReportContext } from \"./types\";\nimport { BaseUrlMap, getInputUrl, normalizeRelativePath } from \"./url\";\n\nconst MAX_HTML_INPUT_NAMES = 40;\nconst MAX_HTML_PREVIEW_LENGTH = 1000;\n\nfunction normalizeUrlForReport(url: string) {\n\ttry {\n\t\tconst baseOrigin = typeof window !== \"undefined\" ? window.location.origin : \"http://localhost\";\n\t\tconst parsedUrl = new URL(url, baseOrigin);\n\t\tconst sameOrigin = parsedUrl.origin === baseOrigin;\n\t\treturn `${sameOrigin ? \"\" : parsedUrl.origin}${parsedUrl.pathname}`;\n\t} catch {\n\t\treturn normalizeRelativePath(url);\n\t}\n}\n\nfunction readHtmlDocument(html: string) {\n\tif (typeof DOMParser === \"undefined\") return undefined;\n\n\ttry {\n\t\treturn new DOMParser().parseFromString(html, \"text/html\");\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction extractHtmlTitle(html: string, doc: Document | undefined) {\n\tconst title = doc?.querySelector(\"title\")?.textContent;\n\tif (title) return title;\n\n\treturn /<title[^>]*>([\\s\\S]*?)<\\/title>/i.exec(html)?.[1];\n}\n\nfunction countHtmlForms(html: string, doc: Document | undefined) {\n\tconst formsCount = doc?.querySelectorAll(\"form\").length;\n\tif (formsCount !== undefined) return formsCount;\n\n\treturn Array.from(html.matchAll(/<form\\b/gi)).length;\n}\n\nfunction collectHtmlInputNames(html: string, doc: Document | undefined) {\n\tconst names = doc\n\t\t? Array.from(\n\t\t\t\tdoc.querySelectorAll<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>(\"input[name],textarea[name],select[name]\")\n\t\t\t)\n\t\t\t\t.map((element) => element.name)\n\t\t\t\t.filter(Boolean)\n\t\t: Array.from(html.matchAll(/\\bname\\s*=\\s*[\"']([^\"']+)[\"']/gi))\n\t\t\t\t.map((match) => match[1])\n\t\t\t\t.filter((name): name is string => !!name);\n\n\treturn Array.from(new Set(names)).slice(0, MAX_HTML_INPUT_NAMES);\n}\n\nfunction extractHtmlTextPreview(html: string, doc: Document | undefined) {\n\tconst text =\n\t\tdoc?.body?.textContent ??\n\t\thtml\n\t\t\t.replace(/<script\\b[\\s\\S]*?<\\/script>/gi, \" \")\n\t\t\t.replace(/<style\\b[\\s\\S]*?<\\/style>/gi, \" \")\n\t\t\t.replace(/<[^>]+>/g, \" \");\n\treturn truncateText(text, MAX_HTML_PREVIEW_LENGTH);\n}\n\nfunction createHtmlResponseSummary(html: string) {\n\tconst doc = readHtmlDocument(html);\n\n\treturn {\n\t\tlength: html.length,\n\t\ttitle: truncateText(extractHtmlTitle(html, doc), 200),\n\t\tformCount: countHtmlForms(html, doc),\n\t\tinputNames: collectHtmlInputNames(html, doc),\n\t\ttextPreview: extractHtmlTextPreview(html, doc)\n\t};\n}\n\nexport function reportUnexpectedHtmlResponse(\n\terror: Error,\n\tsource: \"fetch.parseResponse\" | \"fetch.buildHttpError\",\n\tres: Response,\n\ttext: string,\n\tcontext: FetchErrorReportContext | undefined\n) {\n\tconst inputUrl = context ? getInputUrl(context.input) : undefined;\n\tconst requestUrl = inputUrl?.startsWith(\"http\")\n\t\t? inputUrl\n\t\t: inputUrl\n\t\t\t? `${BaseUrlMap[context?.baseUrlType ?? \"\"]}${inputUrl}`\n\t\t\t: undefined;\n\n\treportTransportError(error, {\n\t\tsource,\n\t\trequestUrl: requestUrl ? normalizeUrlForReport(requestUrl) : undefined,\n\t\tresponseUrl: res.url ? normalizeUrlForReport(res.url) : undefined,\n\t\tmethod: context?.init.method?.toUpperCase() ?? \"GET\",\n\t\tbaseUrlType: context?.baseUrlType,\n\t\tsapClient: context?.sapClient,\n\t\tstatus: res.status,\n\t\tstatusText: res.statusText,\n\t\tcontentType: res.headers.get(\"Content-Type\") || undefined,\n\t\tredirected: res.redirected,\n\t\tresponseType: res.type,\n\t\thtml: createHtmlResponseSummary(text)\n\t});\n}\n","export type SsoForm = {\n\taction: string;\n\tmethod: string;\n\tinputs: Record<string, string>;\n};\n\nexport type SsoRecoveryArgs = {\n\tform?: SsoForm;\n\trecoveryUrl?: string;\n};\n\nexport type SsoRequiredErrorOptions = {\n\trecoverable?: boolean;\n};\n\nlet ssoRecoveryPromise: Promise<boolean> | null = null;\nlet ssoIframeCounter = 0;\n\nfunction normalizeSsoAction(action: string) {\n\tif (typeof window === \"undefined\") return action;\n\n\ttry {\n\t\tconst originRegExp = new RegExp(__ORIGIN_REG_EXP__, \"i\");\n\t\tconst url = new URL(action, window.location.origin);\n\t\tconst isSapHost = originRegExp.test(url.origin);\n\t\tconst isSsoHost = url.origin === __SSO_ORIGIN__;\n\n\t\tif (isSapHost || isSsoHost || url.origin === window.location.origin) {\n\t\t\treturn `${url.pathname}${url.search}${url.hash}`;\n\t\t}\n\n\t\treturn url.toString();\n\t} catch {\n\t\treturn action;\n\t}\n}\n\nexport function isSsoForm(form?: SsoForm): form is SsoForm {\n\tif (!form) return false;\n\n\treturn typeof form.inputs.SAMLRequest === \"string\" || typeof form.inputs.SAMLResponse === \"string\";\n}\n\nfunction createHiddenIframe() {\n\tconst iframeName = `${__APP_ID__}-sso-iframe-${++ssoIframeCounter}`;\n\tconst iframe = document.createElement(\"iframe\");\n\tiframe.name = iframeName;\n\tiframe.style.display = \"none\";\n\treturn iframe;\n}\n\nfunction waitForIframe(iframe: HTMLIFrameElement, cleanup: () => void) {\n\treturn new Promise<boolean>((resolve) => {\n\t\tlet settleTimer: number | null = null;\n\t\tconst complete = () => {\n\t\t\tif (settleTimer !== null) {\n\t\t\t\twindow.clearTimeout(settleTimer);\n\t\t\t}\n\n\t\t\tsettleTimer = window.setTimeout(() => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve(true);\n\t\t\t}, 400);\n\t\t};\n\n\t\tiframe.addEventListener(\"load\", complete);\n\t\tiframe.addEventListener(\"error\", complete);\n\t});\n}\n\nfunction createSsoFormElement(form: SsoForm, target: string) {\n\tconst formElement = document.createElement(\"form\");\n\tformElement.method = form.method === \"GET\" ? \"GET\" : \"POST\";\n\tformElement.action = normalizeSsoAction(form.action);\n\tformElement.target = target;\n\tformElement.style.display = \"none\";\n\n\tfor (const [name, value] of Object.entries(form.inputs)) {\n\t\tconst input = document.createElement(\"input\");\n\t\tinput.type = \"hidden\";\n\t\tinput.name = name;\n\t\tinput.value = value;\n\t\tformElement.appendChild(input);\n\t}\n\n\treturn formElement;\n}\n\nfunction getMountPoint() {\n\tif (typeof document === \"undefined\") return null;\n\treturn document.body ?? document.documentElement;\n}\n\nexport function submitSsoForm(form?: SsoForm) {\n\tif (!isSsoForm(form)) return false;\n\tif (typeof document === \"undefined\") return false;\n\n\tconst mountPoint = getMountPoint();\n\tif (!mountPoint) return false;\n\n\tconst iframe = createHiddenIframe();\n\tconst formElement = createSsoFormElement(form, iframe.name);\n\n\tmountPoint.appendChild(iframe);\n\tmountPoint.appendChild(formElement);\n\tformElement.submit();\n\treturn true;\n}\n\nfunction recoverBySsoForm(form: SsoForm) {\n\tconst mountPoint = getMountPoint();\n\tif (!mountPoint) return Promise.resolve(false);\n\n\tconst iframe = createHiddenIframe();\n\tconst formElement = createSsoFormElement(form, iframe.name);\n\tconst recovery = waitForIframe(iframe, () => {\n\t\tiframe.remove();\n\t\tformElement.remove();\n\t});\n\n\tmountPoint.appendChild(iframe);\n\tmountPoint.appendChild(formElement);\n\tformElement.submit();\n\n\treturn recovery;\n}\n\nfunction recoverByDocumentNavigation(recoveryUrl: string) {\n\tconst mountPoint = getMountPoint();\n\tif (!mountPoint) return Promise.resolve(false);\n\n\tconst iframe = createHiddenIframe();\n\tconst recovery = waitForIframe(iframe, () => {\n\t\tiframe.remove();\n\t});\n\n\tmountPoint.appendChild(iframe);\n\tiframe.src = normalizeSsoAction(recoveryUrl);\n\n\treturn recovery;\n}\n\nexport function recoverSsoSession({ form, recoveryUrl }: SsoRecoveryArgs = {}) {\n\tif (ssoRecoveryPromise) return ssoRecoveryPromise;\n\tif (typeof window === \"undefined\") return false;\n\n\tssoRecoveryPromise = (async () => {\n\t\tif (isSsoForm(form)) return recoverBySsoForm(form);\n\t\tif (recoveryUrl) return recoverByDocumentNavigation(recoveryUrl);\n\t\treturn false;\n\t})().finally(() => {\n\t\tssoRecoveryPromise = null;\n\t});\n\n\treturn ssoRecoveryPromise;\n}\n\nexport class SsoRequiredError extends Error {\n\tpublic readonly form?: SsoForm;\n\tpublic readonly recoveryUrl?: string;\n\tpublic readonly recoverable: boolean;\n\tconstructor(message: string, form?: SsoForm, recoveryUrl?: string, options: SsoRequiredErrorOptions = {}) {\n\t\tsuper(message);\n\t\tthis.form = form;\n\t\tthis.recoveryUrl = recoveryUrl;\n\t\tthis.recoverable = options.recoverable ?? true;\n\t\tObject.setPrototypeOf(this, SsoRequiredError.prototype);\n\t}\n}\n","import { logError } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { asRecord, isRecord, isSafe } from \"@ryuzaki13/react-foundation-lib/validators\";\n\nimport { normalizeODataServiceName, resolveODataBaseUrl, resolveODataSapClient } from \"../odataProjectAdapter\";\n\nimport { reportUnexpectedHtmlResponse } from \"./errorReport\";\nimport { isSsoForm, recoverSsoSession, SsoForm, SsoRequiredError } from \"./SsoRequiredError\";\nimport { BaseURLType, FetchErrorReportContext, RequestInitType } from \"./types\";\nimport { BaseUrlMap, getInputUrl, normalizeRelativePath } from \"./url\";\n\nconst csrfTokenCache = new Map<string, string>();\nconst csrfFetchInProgressCache = new Map<string, Promise<string>>();\nlet ssoRecoveryGate: Promise<void> | null = null;\nlet ssoBlockedError: SsoRequiredError | null = null;\n\nexport { normalizeODataServiceName, resolveODataBaseUrl };\n\nfunction isSapRequest(input: RequestInfo, baseUrlType: BaseURLType) {\n\tif (baseUrlType !== \"\") return true;\n\n\tconst path = normalizeRelativePath(getInputUrl(input));\n\treturn path.startsWith(\"/sap/\") || path.startsWith(\"/sap-dp0/\");\n}\n\nfunction getSapClient(input: RequestInfo, baseUrlType: BaseURLType): string | null {\n\tif (__DEV__ || __PREVIEW__) {\n\t\tif (!isSapRequest(input, baseUrlType)) return null;\n\t\tif (baseUrlType === \"odataDp0\") return \"300\";\n\t\tif (baseUrlType === \"\" && normalizeRelativePath(getInputUrl(input)).startsWith(\"/sap-dp0/\")) {\n\t\t\treturn \"300\";\n\t\t}\n\t\treturn `${__SAP_CLIENT__}`;\n\t}\n\n\treturn resolveODataSapClient();\n}\n\nfunction createUnrecoverableSsoError(source: SsoRequiredError) {\n\treturn new SsoRequiredError(\n\t\t\"Не удалось автоматически восстановить SSO-сессию. Перезагрузите страницу и выполните вход заново.\",\n\t\tsource.form,\n\t\tsource.recoveryUrl,\n\t\t{ recoverable: false }\n\t);\n}\n\nfunction markSsoBlocked(source: SsoRequiredError) {\n\tconst error = createUnrecoverableSsoError(source);\n\tif (typeof window !== \"undefined\") {\n\t\tssoBlockedError = error;\n\t}\n\treturn error;\n}\n\nasync function waitForSsoRecoveryGate() {\n\tconst gate = ssoRecoveryGate;\n\tif (gate) {\n\t\tawait gate.catch(() => {});\n\t}\n\n\tif (ssoBlockedError) {\n\t\tthrow ssoBlockedError;\n\t}\n}\n\nasync function recoverSsoSessionAndRetry<T>(error: SsoRequiredError, retry: () => Promise<T>) {\n\tif (ssoBlockedError) {\n\t\tthrow ssoBlockedError;\n\t}\n\n\tlet retryResult: { value: T } | undefined;\n\n\tif (!ssoRecoveryGate) {\n\t\tssoRecoveryGate = (async () => {\n\t\t\tconst recovered = await Promise.resolve(recoverSsoSession({ form: error.form, recoveryUrl: error.recoveryUrl })).catch(\n\t\t\t\t() => false\n\t\t\t);\n\n\t\t\tif (!recovered) {\n\t\t\t\tthrow markSsoBlocked(error);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tretryResult = { value: await retry() };\n\t\t\t\tssoBlockedError = null;\n\t\t\t} catch (retryError: unknown) {\n\t\t\t\tif (retryError instanceof SsoRequiredError) {\n\t\t\t\t\tthrow markSsoBlocked(retryError);\n\t\t\t\t}\n\n\t\t\t\tthrow retryError;\n\t\t\t}\n\t\t})().finally(() => {\n\t\t\tssoRecoveryGate = null;\n\t\t});\n\n\t\tawait ssoRecoveryGate;\n\n\t\tif (!retryResult) {\n\t\t\tthrow ssoBlockedError ?? createUnrecoverableSsoError(error);\n\t\t}\n\n\t\treturn retryResult.value;\n\t}\n\n\tawait waitForSsoRecoveryGate();\n\ttry {\n\t\treturn await retry();\n\t} catch (retryError: unknown) {\n\t\tif (retryError instanceof SsoRequiredError) {\n\t\t\tthrow markSsoBlocked(retryError);\n\t\t}\n\n\t\tthrow retryError;\n\t}\n}\n\nfunction resolveCsrfScope(input: RequestInfo, baseUrlType: BaseURLType, sapClient: string | null) {\n\tif (baseUrlType === \"config\") {\n\t\treturn {\n\t\t\tcacheKey: `${__APP_ID__}:${sapClient ?? \"\"}`,\n\t\t\tfetchUrl: \"/Statistics\"\n\t\t};\n\t}\n\n\tconst requestPath = normalizeRelativePath(getInputUrl(input));\n\tconst [serviceName] = requestPath.split(\"/\").filter(Boolean);\n\tif (!serviceName) {\n\t\tthrow new Error(\"Не удалось определить сервис для получения CSRF-токена\");\n\t}\n\n\treturn {\n\t\tcacheKey: `${baseUrlType}:${sapClient ?? \"\"}:${serviceName}`,\n\t\tfetchUrl: `/${serviceName}/`\n\t};\n}\n\nasync function getCsrfToken(input: RequestInfo, baseUrlType: BaseURLType, sapClient: string | null): Promise<string> {\n\tconst scope = resolveCsrfScope(input, baseUrlType, sapClient);\n\tconst cachedToken = csrfTokenCache.get(scope.cacheKey);\n\tif (cachedToken) return cachedToken;\n\n\tconst inflightToken = csrfFetchInProgressCache.get(scope.cacheKey);\n\tif (inflightToken) return inflightToken;\n\n\tconst headers = new Headers({ \"x-csrf-token\": \"Fetch\" });\n\theaders.set(\"sap-language\", \"ru\");\n\theaders.set(\"sap-contextid-accept\", \"header\");\n\theaders.set(\"Accept-Language\", \"ru\");\n\tif (sapClient) {\n\t\theaders.set(\"sap-client\", sapClient);\n\t}\n\n\tconst baseUrl = (baseUrlType && BaseUrlMap[baseUrlType]) ?? \"\";\n\tconst tokenPromise = fetch(baseUrl + scope.fetchUrl, {\n\t\tmethod: \"GET\",\n\t\theaders,\n\t\tcredentials: \"include\",\n\t\tredirect: \"manual\"\n\t})\n\t\t.then(async (res) => {\n\t\t\tif (isSsoRedirectResponse(res)) {\n\t\t\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", undefined, baseUrl + scope.fetchUrl);\n\t\t\t}\n\n\t\t\tif (!res.ok) throw new Error(\"Не удалось получить CSRF-токен\");\n\n\t\t\tconst token = res.headers.get(\"x-csrf-token\");\n\t\t\tif (!token) {\n\t\t\t\tconst contentType = (res.headers.get(\"Content-Type\") || \"\").toLowerCase();\n\t\t\t\tconst text = await res.text();\n\t\t\t\tif (looksLikeHtmlResponse(contentType, text)) {\n\t\t\t\t\tconst form = extractFormFromHtml(text);\n\t\t\t\t\tif (isSsoForm(form)) {\n\t\t\t\t\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", form, baseUrl + scope.fetchUrl);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthrow new Error(\"CSRF-токен отсутствует в ответе\");\n\t\t\t}\n\n\t\t\tcsrfTokenCache.set(scope.cacheKey, token);\n\t\t\tcsrfFetchInProgressCache.delete(scope.cacheKey);\n\t\t\treturn token;\n\t\t})\n\t\t.catch((err) => {\n\t\t\tcsrfFetchInProgressCache.delete(scope.cacheKey);\n\t\t\tthrow err;\n\t\t});\n\n\tcsrfFetchInProgressCache.set(scope.cacheKey, tokenPromise);\n\treturn tokenPromise;\n}\n\nfunction extractHtmlAttribute(source: string, attributeName: string) {\n\tconst escapedAttributeName = attributeName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\tconst match = new RegExp(`${escapedAttributeName}\\\\s*=\\\\s*[\"']([^\"']*)[\"']`, \"i\").exec(source);\n\treturn match?.[1];\n}\n\n/**\n * Попытка извлечь форму (действие + скрытые входные данные) из HTML, возвращаемого ADFS/SSO.\n * Возвращает undefined, если форма не найдена.\n */\nfunction extractFormFromHtml(html: string): SsoForm | undefined {\n\ttry {\n\t\tif (typeof DOMParser !== \"undefined\") {\n\t\t\tconst parser = new DOMParser();\n\t\t\tconst doc = parser.parseFromString(html, \"text/html\");\n\t\t\tconst form = doc.querySelector(\"form\");\n\t\t\tif (form) {\n\t\t\t\tconst action = form.getAttribute(\"action\") || (typeof window !== \"undefined\" ? window.location.href : \"\");\n\t\t\t\tconst method = (form.getAttribute(\"method\") || \"GET\").toUpperCase();\n\t\t\t\tconst inputs: Record<string, string> = {};\n\t\t\t\tform.querySelectorAll<HTMLInputElement>(\"input[name]\").forEach((i) => {\n\t\t\t\t\tinputs[i.name] = i.value ?? \"\";\n\t\t\t\t});\n\t\t\t\treturn { action, method, inputs };\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Игнорируем и переходим к текстовому fallback-разбору.\n\t}\n\n\tconst formMatch = /<form\\b([^>]*)>([\\s\\S]*?)<\\/form>/i.exec(html);\n\tif (!formMatch) return undefined;\n\n\tconst [, formAttributes = \"\", formBody = \"\"] = formMatch;\n\tconst action = extractHtmlAttribute(formAttributes, \"action\") || (typeof window !== \"undefined\" ? window.location.href : \"\");\n\tconst method = (extractHtmlAttribute(formAttributes, \"method\") || \"GET\").toUpperCase();\n\tconst inputs: Record<string, string> = {};\n\tconst inputTagPattern = /<input\\b([^>]*)>/gi;\n\n\tfor (const match of formBody.matchAll(inputTagPattern)) {\n\t\tconst inputAttributes = match[1] ?? \"\";\n\t\tconst inputName = extractHtmlAttribute(inputAttributes, \"name\");\n\t\tif (!inputName) continue;\n\n\t\tinputs[inputName] = extractHtmlAttribute(inputAttributes, \"value\") ?? \"\";\n\t}\n\n\treturn { action, method, inputs };\n}\n\nfunction looksLikeHtmlResponse(contentType: string, text: string) {\n\treturn contentType.includes(\"text/html\") || /<html/i.test(text) || /<form/i.test(text);\n}\n\nfunction stripODataMetadata(value: unknown) {\n\tif (!isRecord(value)) return value;\n\n\tconst record = { ...value };\n\tdelete record.__metadata;\n\treturn record;\n}\n\nfunction extractJson<T>(json: unknown) {\n\tif (isRecord(json) && isRecord(json.d) && Array.isArray(json.d.results)) {\n\t\tlet totalCount: number | undefined = undefined;\n\t\tif (json.d.__count) {\n\t\t\ttotalCount = Number(json.d.__count);\n\t\t}\n\n\t\tconst data = json.d.results.map(stripODataMetadata) as T;\n\n\t\treturn { data, totalCount };\n\t}\n\tif (isRecord(json) && json.d !== undefined) {\n\t\tconst data = stripODataMetadata(json.d);\n\n\t\treturn { data: data as T };\n\t}\n\treturn {\n\t\tdata: json as T\n\t};\n}\n\nconst NO_CONTENT_RESPONSE = Object.freeze({ __noContent: true } as const);\n\nexport function isNoContentResponse(value: unknown): value is typeof NO_CONTENT_RESPONSE {\n\treturn !!value && typeof value === \"object\" && \"__noContent\" in value;\n}\n\nasync function parseResponse<T>(res: Response, reportContext?: FetchErrorReportContext): Promise<{ data: T; totalCount?: number }> {\n\tif (res.status === 204 || res.status === 205 /*|| res.headers.get(\"Content-Length\") === \"0\"*/) {\n\t\treturn { data: NO_CONTENT_RESPONSE as T };\n\t}\n\n\tconst contentType = (res.headers.get(\"Content-Type\") || \"\").toLowerCase();\n\n\t// Если явный JSON — безопасно парсим\n\tif (contentType.includes(\"application/json\") || contentType.includes(\"application/odata+json\")) {\n\t\tconst json = await res.json();\n\t\treturn extractJson<T>(json);\n\t}\n\n\t// Попытка парсинга как текст (на случай, если server неправильно прописал content-type)\n\tconst text = await res.text();\n\n\t// если в теле HTML — проверяем, есть ли форма (SSO)\n\tif (looksLikeHtmlResponse(contentType, text)) {\n\t\tconst form = extractFormFromHtml(text);\n\t\tif (isSsoForm(form)) {\n\t\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", form);\n\t\t}\n\t\tconst error = new Error(\"Unexpected HTML response from OData endpoint\");\n\t\treportUnexpectedHtmlResponse(error, \"fetch.parseResponse\", res, text, reportContext);\n\t\tthrow error;\n\t}\n\n\t// Попытка безопасно распарсить JSON, если сервер не установил content-type\n\ttry {\n\t\tconst maybeJson = JSON.parse(text);\n\t\treturn extractJson<T>(maybeJson);\n\t} catch (e) {\n\t\tlogError(e);\n\t\t// ни текст, ни JSON — возвращаем ошибку\n\t\tthrow new Error(\"Unsupported response content type and body is not JSON\");\n\t}\n}\n\n/**\n * Безопасно извлекает текстовое сообщение из неизвестного значения.\n */\nfunction asNonEmptyString(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst normalized = value.trim();\n\treturn normalized.length ? normalized : null;\n}\n\nfunction pushUniqueMessage(parts: string[], value: unknown) {\n\tconst normalized = asNonEmptyString(value);\n\tif (!normalized || parts.includes(normalized)) return;\n\tparts.push(normalized);\n}\n\nfunction extractJsonErrorParts(payload: Record<string, unknown>) {\n\tconst parts: string[] = [];\n\tconst errorValue = payload.error;\n\n\tif (typeof errorValue === \"string\") {\n\t\tpushUniqueMessage(parts, errorValue);\n\t}\n\n\tconst errorRecord = asRecord(errorValue);\n\tif (errorRecord) {\n\t\tpushUniqueMessage(parts, errorRecord.code);\n\n\t\tconst errorMessage = asRecord(errorRecord.message);\n\t\tpushUniqueMessage(parts, errorMessage?.value ?? errorRecord.message);\n\n\t\t// const innerError = asRecord(errorRecord.innererror);\n\t\t// const errorDetails = innerError?.errordetails;\n\t\t// if (Array.isArray(errorDetails)) {\n\t\t// \tfor (const detail of errorDetails) {\n\t\t// \t\tpushUniqueMessage(parts, asRecord(detail)?.message);\n\t\t// \t}\n\t\t// }\n\t}\n\n\tpushUniqueMessage(parts, payload.details);\n\tpushUniqueMessage(parts, payload.message);\n\n\treturn parts;\n}\n\n/**\n * Строит детализированную ошибку HTTP на основе статуса и тела ответа.\n * Для JSON-ответов приоритетно используются поля `error`, `details`, `message`.\n */\nasync function buildHttpError(res: Response, reportContext?: FetchErrorReportContext): Promise<Error> {\n\tconst contentType = (res.headers.get(\"Content-Type\") || \"\").toLowerCase();\n\n\ttry {\n\t\tif (contentType.includes(\"application/json\") || contentType.includes(\"application/odata+json\")) {\n\t\t\tconst payload = (await res.json()) as Record<string, unknown>;\n\t\t\tconst parts = extractJsonErrorParts(payload);\n\n\t\t\tif (parts.length) {\n\t\t\t\treturn new Error(parts.join(\" | \"));\n\t\t\t}\n\t\t} else {\n\t\t\tconst text = await res.text();\n\t\t\tconst normalizedText = asNonEmptyString(text);\n\t\t\tif (normalizedText) {\n\t\t\t\tif (looksLikeHtmlResponse(contentType, normalizedText)) {\n\t\t\t\t\tconst form = extractFormFromHtml(normalizedText);\n\t\t\t\t\tif (isSsoForm(form)) {\n\t\t\t\t\t\treturn new SsoRequiredError(\"Требуется повторная аутентификация\", form);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst error = new Error(\"Unexpected HTML response from OData endpoint\");\n\t\t\t\t\treportUnexpectedHtmlResponse(error, \"fetch.buildHttpError\", res, normalizedText, reportContext);\n\t\t\t\t\treturn error;\n\t\t\t\t}\n\n\t\t\t\treturn new Error(normalizedText);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ничего не делаем: в этом случае вернем стандартный текст ошибки по статусу.\n\t}\n\n\treturn new Error(`HTTP error: ${res.status} ${res.statusText}`);\n}\n\nfunction isSsoRedirectResponse(res: Response) {\n\treturn res.type === \"opaqueredirect\";\n}\n\nasync function sendFetchBaseRequest(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\"): Promise<Response> {\n\tconst method = init.method?.toUpperCase() || \"GET\";\n\tconst headers = new Headers(init.headers);\n\tconst isWrite = ![\"GET\", \"HEAD\"].includes(method);\n\tconst hasBody = isSafe(init.body);\n\tconst sapRequest = isSapRequest(input, baseUrlType);\n\tconst sapClient = getSapClient(input, baseUrlType);\n\n\theaders.set(\"sap-language\", \"ru\");\n\tif (sapRequest) {\n\t\theaders.set(\"sap-language\", \"ru\");\n\t\theaders.set(\"sap-contextid-accept\", \"header\");\n\t}\n\tif (sapClient) {\n\t\theaders.set(\"sap-client\", sapClient);\n\t}\n\tif (isWrite && sapRequest) {\n\t\tconst token = await getCsrfToken(input, baseUrlType, sapClient);\n\t\theaders.set(\"x-csrf-token\", token);\n\t}\n\n\tif (!headers.has(\"Accept\")) {\n\t\theaders.set(\"Accept\", \"application/json\");\n\t}\n\n\tif (hasBody && isWrite && !headers.has(\"Content-Type\")) {\n\t\theaders.set(\"Content-Type\", \"application/json\");\n\t}\n\n\tconst baseUrl = (baseUrlType && BaseUrlMap[baseUrlType]) ?? \"\";\n\tconst url = typeof input === \"string\" ? input : input.toString();\n\tlet res = await fetch(baseUrl + url, {\n\t\t...init,\n\t\theaders,\n\t\tcredentials: \"include\",\n\t\tredirect: sapRequest ? \"manual\" : init.redirect\n\t});\n\n\tif (sapRequest && isSsoRedirectResponse(res)) {\n\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", undefined, baseUrl + url);\n\t}\n\n\t// Если 401 — возможно, токен истёк, пробуем получить заново и повторить\n\tif ((res.status === 401 || res.status === 403) && isWrite && sapRequest && !init.retried) {\n\t\tconst scope = resolveCsrfScope(input, baseUrlType, sapClient);\n\t\tcsrfTokenCache.delete(scope.cacheKey);\n\t\tcsrfFetchInProgressCache.delete(scope.cacheKey);\n\t\tconst token = await getCsrfToken(input, baseUrlType, sapClient);\n\n\t\tconst retryHeaders = new Headers(headers);\n\t\tretryHeaders.set(\"x-csrf-token\", token);\n\n\t\tres = await fetch(baseUrl + url, {\n\t\t\t...init,\n\t\t\theaders: retryHeaders,\n\t\t\tcredentials: \"include\",\n\t\t\tredirect: \"manual\",\n\t\t\tretried: true // кастомная метка, чтобы избежать бесконечного цикла\n\t\t} as RequestInitType);\n\n\t\tif (isSsoRedirectResponse(res)) {\n\t\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", undefined, baseUrl + url);\n\t\t}\n\t}\n\n\treturn res;\n}\n\nasync function finalizeFetchBaseResponse(\n\tres: Response,\n\tinput: RequestInfo,\n\tinit: RequestInitType,\n\tbaseUrlType: BaseURLType,\n\tsapClient: string | null\n) {\n\tif (!res.ok) {\n\t\tif (res.status === 0) {\n\t\t\tthrow new Error(\"Ошибка сети или CORS. Проверьте подключение и настройки сервера.\");\n\t\t}\n\n\t\tthrow await buildHttpError(res, { input, init, baseUrlType, sapClient });\n\t}\n\n\treturn res;\n}\n\nasync function fetchBaseWithoutSsoRecovery(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\") {\n\tconst sapClient = getSapClient(input, baseUrlType);\n\tconst res = await sendFetchBaseRequest(input, init, baseUrlType);\n\treturn finalizeFetchBaseResponse(res, input, init, baseUrlType, sapClient);\n}\n\nexport async function fetchBase(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\"): Promise<Response> {\n\tconst sapRequest = isSapRequest(input, baseUrlType);\n\tconst sapClient = getSapClient(input, baseUrlType);\n\tconst retry = () => fetchBaseWithoutSsoRecovery(input, { ...init, ssoRetried: true }, baseUrlType);\n\n\tif (sapRequest) {\n\t\tawait waitForSsoRecoveryGate();\n\t}\n\n\tlet res: Response;\n\ttry {\n\t\tres = await sendFetchBaseRequest(input, init, baseUrlType);\n\t} catch (error: unknown) {\n\t\tif (sapRequest && error instanceof SsoRequiredError && error.recoverable && !init.ssoRetried) {\n\t\t\tres = await recoverSsoSessionAndRetry(error, retry);\n\t\t} else {\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\ttry {\n\t\treturn await finalizeFetchBaseResponse(res, input, init, baseUrlType, sapClient);\n\t} catch (error: unknown) {\n\t\tif (sapRequest && error instanceof SsoRequiredError && error.recoverable && !init.ssoRetried) {\n\t\t\tconst recoveredResponse = await recoverSsoSessionAndRetry(error, retry);\n\t\t\treturn finalizeFetchBaseResponse(recoveredResponse, input, init, baseUrlType, sapClient);\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n\nexport async function fetchODataJson<T = unknown>(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\") {\n\tconst headers = new Headers(init.headers);\n\n\theaders.set(\"DataServiceVersion\", \"2.0\");\n\theaders.set(\"MaxDataServiceVersion\", \"2.0\");\n\n\tconst requestInit = { ...init, headers };\n\tconst parseContext = { input, init, baseUrlType, sapClient: getSapClient(input, baseUrlType) };\n\n\ttry {\n\t\tconst res = await fetchBase(input, requestInit, baseUrlType);\n\t\treturn await parseResponse<T>(res, parseContext);\n\t} catch (error: unknown) {\n\t\tif (isSapRequest(input, baseUrlType) && error instanceof SsoRequiredError && error.recoverable && !init.ssoRetried) {\n\t\t\treturn recoverSsoSessionAndRetry(error, async () => {\n\t\t\t\tconst retryInit = { ...requestInit, ssoRetried: true };\n\t\t\t\tconst res = await fetchBaseWithoutSsoRecovery(input, retryInit, baseUrlType);\n\t\t\t\treturn parseResponse<T>(res, { input, init: retryInit, baseUrlType, sapClient: getSapClient(input, baseUrlType) });\n\t\t\t});\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n\nexport async function fetchJson<T = unknown>(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\") {\n\tconst response = await fetchODataJson<T>(input, init, baseUrlType);\n\treturn response.data;\n}\n\ninterface FetchQueryFnBaseOptions {\n\tinit?: RequestInit;\n\tbaseUrl?: BaseURLType;\n\t/** Политика кеширования в Service Worker (`\"off\"` | `\"ttl=24h\"` | `\"ttl=24h;max=100;name=ref\"` | `\"bust=24h\"` и т.д.) */\n\tswCache?: string;\n}\n\ninterface FetchQueryFnOptions<R> extends FetchQueryFnBaseOptions {\n\ttransform: (data: Response) => Promise<R>;\n}\n\nexport function fetchQueryFn<R = unknown>(url: string, options: FetchQueryFnOptions<R>) {\n\tconst baseUrlValue = options.baseUrl;\n\tconst transform = options.transform;\n\n\treturn async (params?: { signal?: AbortSignal }): Promise<R> => {\n\t\t/**\n\t\t * QueryFn может запускаться повторно после отмены предыдущего refetch.\n\t\t * Нельзя сохранять signal в замыкании: отменённый signal сразу прервёт следующий запрос.\n\t\t */\n\t\tconst initValue = { ...options.init };\n\t\tif (!initValue.signal && params?.signal) {\n\t\t\tinitValue.signal = params.signal;\n\t\t}\n\t\tif (options.swCache) {\n\t\t\tconst headers = new Headers(initValue.headers);\n\t\t\theaders.set(\"x-sw-cache\", options.swCache);\n\t\t\tinitValue.headers = headers;\n\t\t}\n\n\t\tconst data = await fetchBase(url, initValue, baseUrlValue);\n\n\t\tif (typeof transform !== \"function\") {\n\t\t\tthrow new Error(\"fetchQueryFn requires a transformation function!\");\n\t\t}\n\n\t\treturn await transform(data);\n\t};\n}\n\ninterface FetchJsonQueryFnOptions<T, R> extends FetchQueryFnBaseOptions {\n\ttransform?: (data: T) => R;\n}\n\n/**\n * @deprecated скоро будет замена\n */\nexport function fetchJsonQueryFn<T, R = T>(url: string, options?: FetchJsonQueryFnOptions<T, R>) {\n\tconst baseUrlValue = options?.baseUrl || \"odata\";\n\tconst transform = options?.transform;\n\n\treturn async (params?: { signal: AbortSignal }) => {\n\t\tconst initValue = options?.init || {};\n\t\tif (!initValue.signal && params?.signal) {\n\t\t\tinitValue.signal = params.signal;\n\t\t}\n\n\t\tif (options?.swCache) {\n\t\t\tconst headers = new Headers(initValue.headers);\n\t\t\theaders.set(\"x-sw-cache\", options.swCache);\n\t\t\tinitValue.headers = headers;\n\t\t}\n\n\t\tconst data = await fetchJson<T>(url, initValue, baseUrlValue);\n\n\t\tif (!transform) {\n\t\t\treturn data as unknown as R;\n\t\t}\n\n\t\treturn transform ? transform(data) : (data as unknown as R);\n\t};\n}\n\n/**\n * @deprecated скоро будет замена\n */\nexport function fetchJsonMutationFn<T = unknown, TBody = unknown>(url: string, method: \"POST\" | \"PUT\" = \"POST\", baseUrl?: BaseURLType) {\n\treturn async (body: TBody, signal?: AbortSignal) => {\n\t\treturn fetchJson<T>(\n\t\t\turl,\n\t\t\t{\n\t\t\t\tmethod,\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal\n\t\t\t},\n\t\t\tbaseUrl\n\t\t);\n\t};\n}\n\n/**\n * @deprecated скоро будет замена\n */\nexport function fetchDeleteFn<T = unknown>(url: string, baseUrl?: BaseURLType) {\n\treturn async (signal?: AbortSignal) => {\n\t\treturn fetchJson<T>(url, { method: \"DELETE\", signal }, baseUrl);\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fetch-Cq29VQlt.js","names":[],"sources":["../../src/odata/odataProjectAdapter.ts","../../src/odata/transport/url.ts","../../src/odata/transport/errorReport.ts","../../src/odata/transport/SsoRequiredError.ts","../../src/odata/transport/fetch.ts"],"sourcesContent":["import type { BaseURLType } from \"./transport/types\";\n\nexport type ODataProjectTechnicalEndpoint = {\n\tservice: string;\n\ttarget: string;\n\tbaseUrl?: BaseURLType;\n};\n\nexport type ODataProjectAdapter = {\n\t/**\n\t * OData-сервис, который в dev/preview нужно проксировать через DP0.\n\t * В проектах без SAP/OData оставляется пустым.\n\t */\n\tdevDp0Service?: string;\n\tresolveSapClient?: () => string | null | undefined;\n\tmetadataVersion?: ODataProjectTechnicalEndpoint;\n\tcollectionUpdates?: ODataProjectTechnicalEndpoint;\n};\n\nlet odataProjectAdapter: ODataProjectAdapter = {};\n\nexport function configureODataProjectAdapter(adapter: ODataProjectAdapter) {\n\todataProjectAdapter = adapter;\n}\n\nexport function getODataProjectAdapter() {\n\treturn odataProjectAdapter;\n}\n\nexport function normalizeODataServiceName(service: string) {\n\treturn service.split(\";\")[0] ?? service;\n}\n\nexport function resolveODataBaseUrl(service: string, baseUrl?: BaseURLType): BaseURLType {\n\tconst devDp0Service = odataProjectAdapter.devDp0Service;\n\tif ((__DEV__ || __PREVIEW__) && devDp0Service && normalizeODataServiceName(service) === normalizeODataServiceName(devDp0Service)) {\n\t\treturn \"odataDp0\";\n\t}\n\n\treturn baseUrl ?? \"odata\";\n}\n\nexport function resolveODataSapClient() {\n\treturn odataProjectAdapter.resolveSapClient?.() ?? null;\n}\n","import { BaseURLType } from \"./types\";\n\nexport const BaseODataURL = \"/sap/opu/odata/sap\";\n/**\n * DP0-прокси используется только для сервиса, который проект явно указывает\n * через `odataProjectAdapter.devDp0Service`.\n */\nexport const BaseODataDp0URL = __DEV__ || __PREVIEW__ ? \"/sap-dp0/opu/odata/sap\" : \"/sap/opu/odata/sap\";\nexport const BaseODataUI2URL = __DEV__ || __PREVIEW__ ? \"/sap-dp0/opu/odata/UI2\" : \"/sap/opu/odata/UI2\";\nexport const BaseAppConfigURL = __BASE_APP_CONFIG_URL__;\n\nexport const BaseUrlMap = Object.freeze<Record<BaseURLType, string>>({\n\t[\"\"]: \"\",\n\todata: BaseODataURL,\n\todataDp0: BaseODataDp0URL,\n\todataUi2: BaseODataUI2URL,\n\tconfig: BaseAppConfigURL\n});\n\nexport function getInputUrl(input: RequestInfo) {\n\tif (typeof input === \"string\") return input;\n\tif (typeof Request !== \"undefined\" && input instanceof Request) {\n\t\treturn input.url;\n\t}\n\treturn input.toString();\n}\n\nexport function normalizeRelativePath(url: string) {\n\tconst path = url.split(\"?\")[0]?.split(\"#\")[0] ?? \"\";\n\tif (!path) return \"/\";\n\treturn path.startsWith(\"/\") ? path : `/${path}`;\n}\n","import { reportTransportError } from \"@ryuzaki13/react-foundation-lib/error-report\";\nimport { truncateText } from \"@ryuzaki13/react-foundation-lib/formatters\";\n\nimport { FetchErrorReportContext } from \"./types\";\nimport { BaseUrlMap, getInputUrl, normalizeRelativePath } from \"./url\";\n\nconst MAX_HTML_INPUT_NAMES = 40;\nconst MAX_HTML_PREVIEW_LENGTH = 1000;\n\nfunction normalizeUrlForReport(url: string) {\n\ttry {\n\t\tconst baseOrigin = typeof window !== \"undefined\" ? window.location.origin : \"http://localhost\";\n\t\tconst parsedUrl = new URL(url, baseOrigin);\n\t\tconst sameOrigin = parsedUrl.origin === baseOrigin;\n\t\treturn `${sameOrigin ? \"\" : parsedUrl.origin}${parsedUrl.pathname}`;\n\t} catch {\n\t\treturn normalizeRelativePath(url);\n\t}\n}\n\nfunction readHtmlDocument(html: string) {\n\tif (typeof DOMParser === \"undefined\") return undefined;\n\n\ttry {\n\t\treturn new DOMParser().parseFromString(html, \"text/html\");\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction extractHtmlTitle(html: string, doc: Document | undefined) {\n\tconst title = doc?.querySelector(\"title\")?.textContent;\n\tif (title) return title;\n\n\treturn /<title[^>]*>([\\s\\S]*?)<\\/title>/i.exec(html)?.[1];\n}\n\nfunction countHtmlForms(html: string, doc: Document | undefined) {\n\tconst formsCount = doc?.querySelectorAll(\"form\").length;\n\tif (formsCount !== undefined) return formsCount;\n\n\treturn Array.from(html.matchAll(/<form\\b/gi)).length;\n}\n\nfunction collectHtmlInputNames(html: string, doc: Document | undefined) {\n\tconst names = doc\n\t\t? Array.from(\n\t\t\t\tdoc.querySelectorAll<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>(\"input[name],textarea[name],select[name]\")\n\t\t\t)\n\t\t\t\t.map((element) => element.name)\n\t\t\t\t.filter(Boolean)\n\t\t: Array.from(html.matchAll(/\\bname\\s*=\\s*[\"']([^\"']+)[\"']/gi))\n\t\t\t\t.map((match) => match[1])\n\t\t\t\t.filter((name): name is string => !!name);\n\n\treturn Array.from(new Set(names)).slice(0, MAX_HTML_INPUT_NAMES);\n}\n\nfunction extractHtmlTextPreview(html: string, doc: Document | undefined) {\n\tconst text =\n\t\tdoc?.body?.textContent ??\n\t\thtml\n\t\t\t.replace(/<script\\b[\\s\\S]*?<\\/script>/gi, \" \")\n\t\t\t.replace(/<style\\b[\\s\\S]*?<\\/style>/gi, \" \")\n\t\t\t.replace(/<[^>]+>/g, \" \");\n\treturn truncateText(text, MAX_HTML_PREVIEW_LENGTH);\n}\n\nfunction createHtmlResponseSummary(html: string) {\n\tconst doc = readHtmlDocument(html);\n\n\treturn {\n\t\tlength: html.length,\n\t\ttitle: truncateText(extractHtmlTitle(html, doc), 200),\n\t\tformCount: countHtmlForms(html, doc),\n\t\tinputNames: collectHtmlInputNames(html, doc),\n\t\ttextPreview: extractHtmlTextPreview(html, doc)\n\t};\n}\n\nexport function reportUnexpectedHtmlResponse(\n\terror: Error,\n\tsource: \"fetch.parseResponse\" | \"fetch.buildHttpError\",\n\tres: Response,\n\ttext: string,\n\tcontext: FetchErrorReportContext | undefined\n) {\n\tconst inputUrl = context ? getInputUrl(context.input) : undefined;\n\tconst requestUrl = inputUrl?.startsWith(\"http\")\n\t\t? inputUrl\n\t\t: inputUrl\n\t\t\t? `${BaseUrlMap[context?.baseUrlType ?? \"\"]}${inputUrl}`\n\t\t\t: undefined;\n\n\treportTransportError(error, {\n\t\tsource,\n\t\trequestUrl: requestUrl ? normalizeUrlForReport(requestUrl) : undefined,\n\t\tresponseUrl: res.url ? normalizeUrlForReport(res.url) : undefined,\n\t\tmethod: context?.init.method?.toUpperCase() ?? \"GET\",\n\t\tbaseUrlType: context?.baseUrlType,\n\t\tsapClient: context?.sapClient,\n\t\tstatus: res.status,\n\t\tstatusText: res.statusText,\n\t\tcontentType: res.headers.get(\"Content-Type\") || undefined,\n\t\tredirected: res.redirected,\n\t\tresponseType: res.type,\n\t\thtml: createHtmlResponseSummary(text)\n\t});\n}\n","export type SsoForm = {\n\taction: string;\n\tmethod: string;\n\tinputs: Record<string, string>;\n};\n\nexport type SsoRecoveryArgs = {\n\tform?: SsoForm;\n\trecoveryUrl?: string;\n};\n\nexport type SsoRequiredErrorOptions = {\n\trecoverable?: boolean;\n};\n\nlet ssoRecoveryPromise: Promise<boolean> | null = null;\nlet ssoIframeCounter = 0;\n\nfunction normalizeSsoAction(action: string) {\n\tif (typeof window === \"undefined\") return action;\n\n\ttry {\n\t\tconst originRegExp = new RegExp(__ORIGIN_REG_EXP__, \"i\");\n\t\tconst url = new URL(action, window.location.origin);\n\t\tconst isSapHost = originRegExp.test(url.origin);\n\t\tconst isSsoHost = url.origin === __SSO_ORIGIN__;\n\n\t\tif (isSapHost || isSsoHost || url.origin === window.location.origin) {\n\t\t\treturn `${url.pathname}${url.search}${url.hash}`;\n\t\t}\n\n\t\treturn url.toString();\n\t} catch {\n\t\treturn action;\n\t}\n}\n\nexport function isSsoForm(form?: SsoForm): form is SsoForm {\n\tif (!form) return false;\n\n\treturn typeof form.inputs.SAMLRequest === \"string\" || typeof form.inputs.SAMLResponse === \"string\";\n}\n\nfunction createHiddenIframe() {\n\tconst iframeName = `${__APP_ID__}-sso-iframe-${++ssoIframeCounter}`;\n\tconst iframe = document.createElement(\"iframe\");\n\tiframe.name = iframeName;\n\tiframe.style.display = \"none\";\n\treturn iframe;\n}\n\nfunction waitForIframe(iframe: HTMLIFrameElement, cleanup: () => void) {\n\treturn new Promise<boolean>((resolve) => {\n\t\tlet settleTimer: number | null = null;\n\t\tconst complete = () => {\n\t\t\tif (settleTimer !== null) {\n\t\t\t\twindow.clearTimeout(settleTimer);\n\t\t\t}\n\n\t\t\tsettleTimer = window.setTimeout(() => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve(true);\n\t\t\t}, 400);\n\t\t};\n\n\t\tiframe.addEventListener(\"load\", complete);\n\t\tiframe.addEventListener(\"error\", complete);\n\t});\n}\n\nfunction createSsoFormElement(form: SsoForm, target: string) {\n\tconst formElement = document.createElement(\"form\");\n\tformElement.method = form.method === \"GET\" ? \"GET\" : \"POST\";\n\tformElement.action = normalizeSsoAction(form.action);\n\tformElement.target = target;\n\tformElement.style.display = \"none\";\n\n\tfor (const [name, value] of Object.entries(form.inputs)) {\n\t\tconst input = document.createElement(\"input\");\n\t\tinput.type = \"hidden\";\n\t\tinput.name = name;\n\t\tinput.value = value;\n\t\tformElement.appendChild(input);\n\t}\n\n\treturn formElement;\n}\n\nfunction getMountPoint() {\n\tif (typeof document === \"undefined\") return null;\n\treturn document.body ?? document.documentElement;\n}\n\nexport function submitSsoForm(form?: SsoForm) {\n\tif (!isSsoForm(form)) return false;\n\tif (typeof document === \"undefined\") return false;\n\n\tconst mountPoint = getMountPoint();\n\tif (!mountPoint) return false;\n\n\tconst iframe = createHiddenIframe();\n\tconst formElement = createSsoFormElement(form, iframe.name);\n\n\tmountPoint.appendChild(iframe);\n\tmountPoint.appendChild(formElement);\n\tformElement.submit();\n\treturn true;\n}\n\nfunction recoverBySsoForm(form: SsoForm) {\n\tconst mountPoint = getMountPoint();\n\tif (!mountPoint) return Promise.resolve(false);\n\n\tconst iframe = createHiddenIframe();\n\tconst formElement = createSsoFormElement(form, iframe.name);\n\tconst recovery = waitForIframe(iframe, () => {\n\t\tiframe.remove();\n\t\tformElement.remove();\n\t});\n\n\tmountPoint.appendChild(iframe);\n\tmountPoint.appendChild(formElement);\n\tformElement.submit();\n\n\treturn recovery;\n}\n\nfunction recoverByDocumentNavigation(recoveryUrl: string) {\n\tconst mountPoint = getMountPoint();\n\tif (!mountPoint) return Promise.resolve(false);\n\n\tconst iframe = createHiddenIframe();\n\tconst recovery = waitForIframe(iframe, () => {\n\t\tiframe.remove();\n\t});\n\n\tmountPoint.appendChild(iframe);\n\tiframe.src = normalizeSsoAction(recoveryUrl);\n\n\treturn recovery;\n}\n\nexport function recoverSsoSession({ form, recoveryUrl }: SsoRecoveryArgs = {}) {\n\tif (ssoRecoveryPromise) return ssoRecoveryPromise;\n\tif (typeof window === \"undefined\") return false;\n\n\tssoRecoveryPromise = (async () => {\n\t\tif (isSsoForm(form)) return recoverBySsoForm(form);\n\t\tif (recoveryUrl) return recoverByDocumentNavigation(recoveryUrl);\n\t\treturn false;\n\t})().finally(() => {\n\t\tssoRecoveryPromise = null;\n\t});\n\n\treturn ssoRecoveryPromise;\n}\n\nexport class SsoRequiredError extends Error {\n\tpublic readonly form?: SsoForm;\n\tpublic readonly recoveryUrl?: string;\n\tpublic readonly recoverable: boolean;\n\tconstructor(message: string, form?: SsoForm, recoveryUrl?: string, options: SsoRequiredErrorOptions = {}) {\n\t\tsuper(message);\n\t\tthis.form = form;\n\t\tthis.recoveryUrl = recoveryUrl;\n\t\tthis.recoverable = options.recoverable ?? true;\n\t\tObject.setPrototypeOf(this, SsoRequiredError.prototype);\n\t}\n}\n","import { logError } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { asRecord, isRecord, isSafe } from \"@ryuzaki13/react-foundation-lib/validators\";\n\nimport { normalizeODataServiceName, resolveODataBaseUrl, resolveODataSapClient } from \"../odataProjectAdapter\";\n\nimport { reportUnexpectedHtmlResponse } from \"./errorReport\";\nimport { isSsoForm, recoverSsoSession, SsoForm, SsoRequiredError } from \"./SsoRequiredError\";\nimport { BaseURLType, FetchErrorReportContext, RequestInitType } from \"./types\";\nimport { BaseUrlMap, getInputUrl, normalizeRelativePath } from \"./url\";\n\nconst csrfTokenCache = new Map<string, string>();\nconst csrfFetchInProgressCache = new Map<string, Promise<string>>();\nlet ssoRecoveryGate: Promise<void> | null = null;\nlet ssoBlockedError: SsoRequiredError | null = null;\n\nexport { normalizeODataServiceName, resolveODataBaseUrl };\n\nfunction isSapRequest(input: RequestInfo, baseUrlType: BaseURLType) {\n\tif (baseUrlType !== \"\") return true;\n\n\tconst path = normalizeRelativePath(getInputUrl(input));\n\treturn path.startsWith(\"/sap/\") || path.startsWith(\"/sap-dp0/\");\n}\n\nfunction getSapClient(input: RequestInfo, baseUrlType: BaseURLType): string | null {\n\tif (__DEV__ || __PREVIEW__) {\n\t\tif (!isSapRequest(input, baseUrlType)) return null;\n\t\tif (baseUrlType === \"odataDp0\") return \"300\";\n\t\tif (baseUrlType === \"\" && normalizeRelativePath(getInputUrl(input)).startsWith(\"/sap-dp0/\")) {\n\t\t\treturn \"300\";\n\t\t}\n\t\treturn `${__SAP_CLIENT__}`;\n\t}\n\n\treturn resolveODataSapClient();\n}\n\nfunction createUnrecoverableSsoError(source: SsoRequiredError) {\n\treturn new SsoRequiredError(\n\t\t\"Не удалось автоматически восстановить SSO-сессию. Перезагрузите страницу и выполните вход заново.\",\n\t\tsource.form,\n\t\tsource.recoveryUrl,\n\t\t{ recoverable: false }\n\t);\n}\n\nfunction markSsoBlocked(source: SsoRequiredError) {\n\tconst error = createUnrecoverableSsoError(source);\n\tif (typeof window !== \"undefined\") {\n\t\tssoBlockedError = error;\n\t}\n\treturn error;\n}\n\nasync function waitForSsoRecoveryGate() {\n\tconst gate = ssoRecoveryGate;\n\tif (gate) {\n\t\tawait gate.catch(() => {});\n\t}\n\n\tif (ssoBlockedError) {\n\t\tthrow ssoBlockedError;\n\t}\n}\n\nasync function recoverSsoSessionAndRetry<T>(error: SsoRequiredError, retry: () => Promise<T>) {\n\tif (ssoBlockedError) {\n\t\tthrow ssoBlockedError;\n\t}\n\n\tlet retryResult: { value: T } | undefined;\n\n\tif (!ssoRecoveryGate) {\n\t\tssoRecoveryGate = (async () => {\n\t\t\tconst recovered = await Promise.resolve(recoverSsoSession({ form: error.form, recoveryUrl: error.recoveryUrl })).catch(\n\t\t\t\t() => false\n\t\t\t);\n\n\t\t\tif (!recovered) {\n\t\t\t\tthrow markSsoBlocked(error);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tretryResult = { value: await retry() };\n\t\t\t\tssoBlockedError = null;\n\t\t\t} catch (retryError: unknown) {\n\t\t\t\tif (retryError instanceof SsoRequiredError) {\n\t\t\t\t\tthrow markSsoBlocked(retryError);\n\t\t\t\t}\n\n\t\t\t\tthrow retryError;\n\t\t\t}\n\t\t})().finally(() => {\n\t\t\tssoRecoveryGate = null;\n\t\t});\n\n\t\tawait ssoRecoveryGate;\n\n\t\tif (!retryResult) {\n\t\t\tthrow ssoBlockedError ?? createUnrecoverableSsoError(error);\n\t\t}\n\n\t\treturn retryResult.value;\n\t}\n\n\tawait waitForSsoRecoveryGate();\n\ttry {\n\t\treturn await retry();\n\t} catch (retryError: unknown) {\n\t\tif (retryError instanceof SsoRequiredError) {\n\t\t\tthrow markSsoBlocked(retryError);\n\t\t}\n\n\t\tthrow retryError;\n\t}\n}\n\nfunction resolveCsrfScope(input: RequestInfo, baseUrlType: BaseURLType, sapClient: string | null) {\n\tif (baseUrlType === \"config\") {\n\t\treturn {\n\t\t\tcacheKey: `${__APP_ID__}:${sapClient ?? \"\"}`,\n\t\t\tfetchUrl: \"/Statistics\"\n\t\t};\n\t}\n\n\tconst requestPath = normalizeRelativePath(getInputUrl(input));\n\tconst [serviceName] = requestPath.split(\"/\").filter(Boolean);\n\tif (!serviceName) {\n\t\tthrow new Error(\"Не удалось определить сервис для получения CSRF-токена\");\n\t}\n\n\treturn {\n\t\tcacheKey: `${baseUrlType}:${sapClient ?? \"\"}:${serviceName}`,\n\t\tfetchUrl: `/${serviceName}/`\n\t};\n}\n\nasync function getCsrfToken(input: RequestInfo, baseUrlType: BaseURLType, sapClient: string | null): Promise<string> {\n\tconst scope = resolveCsrfScope(input, baseUrlType, sapClient);\n\tconst cachedToken = csrfTokenCache.get(scope.cacheKey);\n\tif (cachedToken) return cachedToken;\n\n\tconst inflightToken = csrfFetchInProgressCache.get(scope.cacheKey);\n\tif (inflightToken) return inflightToken;\n\n\tconst headers = new Headers({ \"x-csrf-token\": \"Fetch\" });\n\theaders.set(\"sap-language\", \"ru\");\n\theaders.set(\"sap-contextid-accept\", \"header\");\n\theaders.set(\"Accept-Language\", \"ru\");\n\tif (sapClient) {\n\t\theaders.set(\"sap-client\", sapClient);\n\t}\n\n\tconst baseUrl = (baseUrlType && BaseUrlMap[baseUrlType]) ?? \"\";\n\tconst tokenPromise = fetch(baseUrl + scope.fetchUrl, {\n\t\tmethod: \"GET\",\n\t\theaders,\n\t\tcredentials: \"include\",\n\t\tredirect: \"manual\"\n\t})\n\t\t.then(async (res) => {\n\t\t\tif (isSsoRedirectResponse(res)) {\n\t\t\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", undefined, baseUrl + scope.fetchUrl);\n\t\t\t}\n\n\t\t\tif (!res.ok) throw new Error(\"Не удалось получить CSRF-токен\");\n\n\t\t\tconst token = res.headers.get(\"x-csrf-token\");\n\t\t\tif (!token) {\n\t\t\t\tconst contentType = (res.headers.get(\"Content-Type\") || \"\").toLowerCase();\n\t\t\t\tconst text = await res.text();\n\t\t\t\tif (looksLikeHtmlResponse(contentType, text)) {\n\t\t\t\t\tconst form = extractFormFromHtml(text);\n\t\t\t\t\tif (isSsoForm(form)) {\n\t\t\t\t\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", form, baseUrl + scope.fetchUrl);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthrow new Error(\"CSRF-токен отсутствует в ответе\");\n\t\t\t}\n\n\t\t\tcsrfTokenCache.set(scope.cacheKey, token);\n\t\t\tcsrfFetchInProgressCache.delete(scope.cacheKey);\n\t\t\treturn token;\n\t\t})\n\t\t.catch((err) => {\n\t\t\tcsrfFetchInProgressCache.delete(scope.cacheKey);\n\t\t\tthrow err;\n\t\t});\n\n\tcsrfFetchInProgressCache.set(scope.cacheKey, tokenPromise);\n\treturn tokenPromise;\n}\n\nfunction extractHtmlAttribute(source: string, attributeName: string) {\n\tconst escapedAttributeName = attributeName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\tconst match = new RegExp(`${escapedAttributeName}\\\\s*=\\\\s*[\"']([^\"']*)[\"']`, \"i\").exec(source);\n\treturn match?.[1];\n}\n\n/**\n * Попытка извлечь форму (действие + скрытые входные данные) из HTML, возвращаемого ADFS/SSO.\n * Возвращает undefined, если форма не найдена.\n */\nfunction extractFormFromHtml(html: string): SsoForm | undefined {\n\ttry {\n\t\tif (typeof DOMParser !== \"undefined\") {\n\t\t\tconst parser = new DOMParser();\n\t\t\tconst doc = parser.parseFromString(html, \"text/html\");\n\t\t\tconst form = doc.querySelector(\"form\");\n\t\t\tif (form) {\n\t\t\t\tconst action = form.getAttribute(\"action\") || (typeof window !== \"undefined\" ? window.location.href : \"\");\n\t\t\t\tconst method = (form.getAttribute(\"method\") || \"GET\").toUpperCase();\n\t\t\t\tconst inputs: Record<string, string> = {};\n\t\t\t\tform.querySelectorAll<HTMLInputElement>(\"input[name]\").forEach((i) => {\n\t\t\t\t\tinputs[i.name] = i.value ?? \"\";\n\t\t\t\t});\n\t\t\t\treturn { action, method, inputs };\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Игнорируем и переходим к текстовому fallback-разбору.\n\t}\n\n\tconst formMatch = /<form\\b([^>]*)>([\\s\\S]*?)<\\/form>/i.exec(html);\n\tif (!formMatch) return undefined;\n\n\tconst [, formAttributes = \"\", formBody = \"\"] = formMatch;\n\tconst action = extractHtmlAttribute(formAttributes, \"action\") || (typeof window !== \"undefined\" ? window.location.href : \"\");\n\tconst method = (extractHtmlAttribute(formAttributes, \"method\") || \"GET\").toUpperCase();\n\tconst inputs: Record<string, string> = {};\n\tconst inputTagPattern = /<input\\b([^>]*)>/gi;\n\n\tfor (const match of formBody.matchAll(inputTagPattern)) {\n\t\tconst inputAttributes = match[1] ?? \"\";\n\t\tconst inputName = extractHtmlAttribute(inputAttributes, \"name\");\n\t\tif (!inputName) continue;\n\n\t\tinputs[inputName] = extractHtmlAttribute(inputAttributes, \"value\") ?? \"\";\n\t}\n\n\treturn { action, method, inputs };\n}\n\nfunction looksLikeHtmlResponse(contentType: string, text: string) {\n\treturn contentType.includes(\"text/html\") || /<html/i.test(text) || /<form/i.test(text);\n}\n\nfunction stripODataMetadata(value: unknown) {\n\tif (!isRecord(value)) return value;\n\n\tconst record = { ...value };\n\tdelete record.__metadata;\n\treturn record;\n}\n\nfunction extractJson<T>(json: unknown) {\n\tif (isRecord(json) && isRecord(json.d) && Array.isArray(json.d.results)) {\n\t\tlet totalCount: number | undefined = undefined;\n\t\tif (json.d.__count) {\n\t\t\ttotalCount = Number(json.d.__count);\n\t\t}\n\n\t\tconst data = json.d.results.map(stripODataMetadata) as T;\n\n\t\treturn { data, totalCount };\n\t}\n\tif (isRecord(json) && json.d !== undefined) {\n\t\tconst data = stripODataMetadata(json.d);\n\n\t\treturn { data: data as T };\n\t}\n\treturn {\n\t\tdata: json as T\n\t};\n}\n\nconst NO_CONTENT_RESPONSE = Object.freeze({ __noContent: true } as const);\n\nexport function isNoContentResponse(value: unknown): value is typeof NO_CONTENT_RESPONSE {\n\treturn !!value && typeof value === \"object\" && \"__noContent\" in value;\n}\n\nasync function parseResponse<T>(res: Response, reportContext?: FetchErrorReportContext): Promise<{ data: T; totalCount?: number }> {\n\tif (res.status === 204 || res.status === 205 /*|| res.headers.get(\"Content-Length\") === \"0\"*/) {\n\t\treturn { data: NO_CONTENT_RESPONSE as T };\n\t}\n\n\tconst contentType = (res.headers.get(\"Content-Type\") || \"\").toLowerCase();\n\n\t// Если явный JSON — безопасно парсим\n\tif (contentType.includes(\"application/json\") || contentType.includes(\"application/odata+json\")) {\n\t\tconst json = await res.json();\n\t\treturn extractJson<T>(json);\n\t}\n\n\t// Попытка парсинга как текст (на случай, если server неправильно прописал content-type)\n\tconst text = await res.text();\n\n\t// если в теле HTML — проверяем, есть ли форма (SSO)\n\tif (looksLikeHtmlResponse(contentType, text)) {\n\t\tconst form = extractFormFromHtml(text);\n\t\tif (isSsoForm(form)) {\n\t\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", form);\n\t\t}\n\t\tconst error = new Error(\"Unexpected HTML response from OData endpoint\");\n\t\treportUnexpectedHtmlResponse(error, \"fetch.parseResponse\", res, text, reportContext);\n\t\tthrow error;\n\t}\n\n\t// Попытка безопасно распарсить JSON, если сервер не установил content-type\n\ttry {\n\t\tconst maybeJson = JSON.parse(text);\n\t\treturn extractJson<T>(maybeJson);\n\t} catch (e) {\n\t\tlogError(e);\n\t\t// ни текст, ни JSON — возвращаем ошибку\n\t\tthrow new Error(\"Unsupported response content type and body is not JSON\");\n\t}\n}\n\n/**\n * Безопасно извлекает текстовое сообщение из неизвестного значения.\n */\nfunction asNonEmptyString(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst normalized = value.trim();\n\treturn normalized.length ? normalized : null;\n}\n\nfunction pushUniqueMessage(parts: string[], value: unknown) {\n\tconst normalized = asNonEmptyString(value);\n\tif (!normalized || parts.includes(normalized)) return;\n\tparts.push(normalized);\n}\n\nfunction extractJsonErrorParts(payload: Record<string, unknown>) {\n\tconst parts: string[] = [];\n\tconst errorValue = payload.error;\n\n\tif (typeof errorValue === \"string\") {\n\t\tpushUniqueMessage(parts, errorValue);\n\t}\n\n\tconst errorRecord = asRecord(errorValue);\n\tif (errorRecord) {\n\t\tpushUniqueMessage(parts, errorRecord.code);\n\n\t\tconst errorMessage = asRecord(errorRecord.message);\n\t\tpushUniqueMessage(parts, errorMessage?.value ?? errorRecord.message);\n\n\t\t// const innerError = asRecord(errorRecord.innererror);\n\t\t// const errorDetails = innerError?.errordetails;\n\t\t// if (Array.isArray(errorDetails)) {\n\t\t// \tfor (const detail of errorDetails) {\n\t\t// \t\tpushUniqueMessage(parts, asRecord(detail)?.message);\n\t\t// \t}\n\t\t// }\n\t}\n\n\tpushUniqueMessage(parts, payload.details);\n\tpushUniqueMessage(parts, payload.message);\n\n\treturn parts;\n}\n\n/**\n * Строит детализированную ошибку HTTP на основе статуса и тела ответа.\n * Для JSON-ответов приоритетно используются поля `error`, `details`, `message`.\n */\nasync function buildHttpError(res: Response, reportContext?: FetchErrorReportContext): Promise<Error> {\n\tconst contentType = (res.headers.get(\"Content-Type\") || \"\").toLowerCase();\n\n\ttry {\n\t\tif (contentType.includes(\"application/json\") || contentType.includes(\"application/odata+json\")) {\n\t\t\tconst payload = (await res.json()) as Record<string, unknown>;\n\t\t\tconst parts = extractJsonErrorParts(payload);\n\n\t\t\tif (parts.length) {\n\t\t\t\treturn new Error(parts.join(\" | \"));\n\t\t\t}\n\t\t} else {\n\t\t\tconst text = await res.text();\n\t\t\tconst normalizedText = asNonEmptyString(text);\n\t\t\tif (normalizedText) {\n\t\t\t\tif (looksLikeHtmlResponse(contentType, normalizedText)) {\n\t\t\t\t\tconst form = extractFormFromHtml(normalizedText);\n\t\t\t\t\tif (isSsoForm(form)) {\n\t\t\t\t\t\treturn new SsoRequiredError(\"Требуется повторная аутентификация\", form);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst error = new Error(\"Unexpected HTML response from OData endpoint\");\n\t\t\t\t\treportUnexpectedHtmlResponse(error, \"fetch.buildHttpError\", res, normalizedText, reportContext);\n\t\t\t\t\treturn error;\n\t\t\t\t}\n\n\t\t\t\treturn new Error(normalizedText);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ничего не делаем: в этом случае вернем стандартный текст ошибки по статусу.\n\t}\n\n\treturn new Error(`HTTP error: ${res.status} ${res.statusText}`);\n}\n\nfunction isSsoRedirectResponse(res: Response) {\n\treturn res.type === \"opaqueredirect\";\n}\n\nasync function sendFetchBaseRequest(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\"): Promise<Response> {\n\tconst method = init.method?.toUpperCase() || \"GET\";\n\tconst headers = new Headers(init.headers);\n\tconst isWrite = ![\"GET\", \"HEAD\"].includes(method);\n\tconst hasBody = isSafe(init.body);\n\tconst sapRequest = isSapRequest(input, baseUrlType);\n\tconst sapClient = getSapClient(input, baseUrlType);\n\n\theaders.set(\"sap-language\", \"ru\");\n\tif (sapRequest) {\n\t\theaders.set(\"sap-language\", \"ru\");\n\t\theaders.set(\"sap-contextid-accept\", \"header\");\n\t}\n\tif (sapClient) {\n\t\theaders.set(\"sap-client\", sapClient);\n\t}\n\tif (isWrite && sapRequest) {\n\t\tconst token = await getCsrfToken(input, baseUrlType, sapClient);\n\t\theaders.set(\"x-csrf-token\", token);\n\t}\n\n\tif (!headers.has(\"Accept\")) {\n\t\theaders.set(\"Accept\", \"application/json\");\n\t}\n\n\tif (hasBody && isWrite && !headers.has(\"Content-Type\")) {\n\t\theaders.set(\"Content-Type\", \"application/json\");\n\t}\n\n\tconst baseUrl = (baseUrlType && BaseUrlMap[baseUrlType]) ?? \"\";\n\tconst url = typeof input === \"string\" ? input : input.toString();\n\tlet res = await fetch(baseUrl + url, {\n\t\t...init,\n\t\theaders,\n\t\tcredentials: \"include\",\n\t\tredirect: sapRequest ? \"manual\" : init.redirect\n\t});\n\n\tif (sapRequest && isSsoRedirectResponse(res)) {\n\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", undefined, baseUrl + url);\n\t}\n\n\t// Если 401 — возможно, токен истёк, пробуем получить заново и повторить\n\tif ((res.status === 401 || res.status === 403) && isWrite && sapRequest && !init.retried) {\n\t\tconst scope = resolveCsrfScope(input, baseUrlType, sapClient);\n\t\tcsrfTokenCache.delete(scope.cacheKey);\n\t\tcsrfFetchInProgressCache.delete(scope.cacheKey);\n\t\tconst token = await getCsrfToken(input, baseUrlType, sapClient);\n\n\t\tconst retryHeaders = new Headers(headers);\n\t\tretryHeaders.set(\"x-csrf-token\", token);\n\n\t\tres = await fetch(baseUrl + url, {\n\t\t\t...init,\n\t\t\theaders: retryHeaders,\n\t\t\tcredentials: \"include\",\n\t\t\tredirect: \"manual\",\n\t\t\tretried: true // кастомная метка, чтобы избежать бесконечного цикла\n\t\t} as RequestInitType);\n\n\t\tif (isSsoRedirectResponse(res)) {\n\t\t\tthrow new SsoRequiredError(\"Требуется повторная аутентификация\", undefined, baseUrl + url);\n\t\t}\n\t}\n\n\treturn res;\n}\n\nasync function finalizeFetchBaseResponse(\n\tres: Response,\n\tinput: RequestInfo,\n\tinit: RequestInitType,\n\tbaseUrlType: BaseURLType,\n\tsapClient: string | null\n) {\n\tif (!res.ok) {\n\t\tif (res.status === 0) {\n\t\t\tthrow new Error(\"Ошибка сети или CORS. Проверьте подключение и настройки сервера.\");\n\t\t}\n\n\t\tthrow await buildHttpError(res, { input, init, baseUrlType, sapClient });\n\t}\n\n\treturn res;\n}\n\nasync function fetchBaseWithoutSsoRecovery(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\") {\n\tconst sapClient = getSapClient(input, baseUrlType);\n\tconst res = await sendFetchBaseRequest(input, init, baseUrlType);\n\treturn finalizeFetchBaseResponse(res, input, init, baseUrlType, sapClient);\n}\n\nexport async function fetchBase(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\"): Promise<Response> {\n\tconst sapRequest = isSapRequest(input, baseUrlType);\n\tconst sapClient = getSapClient(input, baseUrlType);\n\tconst retry = () => fetchBaseWithoutSsoRecovery(input, { ...init, ssoRetried: true }, baseUrlType);\n\n\tif (sapRequest) {\n\t\tawait waitForSsoRecoveryGate();\n\t}\n\n\tlet res: Response;\n\ttry {\n\t\tres = await sendFetchBaseRequest(input, init, baseUrlType);\n\t} catch (error: unknown) {\n\t\tif (sapRequest && error instanceof SsoRequiredError && error.recoverable && !init.ssoRetried) {\n\t\t\tres = await recoverSsoSessionAndRetry(error, retry);\n\t\t} else {\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\ttry {\n\t\treturn await finalizeFetchBaseResponse(res, input, init, baseUrlType, sapClient);\n\t} catch (error: unknown) {\n\t\tif (sapRequest && error instanceof SsoRequiredError && error.recoverable && !init.ssoRetried) {\n\t\t\tconst recoveredResponse = await recoverSsoSessionAndRetry(error, retry);\n\t\t\treturn finalizeFetchBaseResponse(recoveredResponse, input, init, baseUrlType, sapClient);\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n\nexport async function fetchODataJson<T = unknown>(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\") {\n\tconst headers = new Headers(init.headers);\n\n\theaders.set(\"DataServiceVersion\", \"2.0\");\n\theaders.set(\"MaxDataServiceVersion\", \"2.0\");\n\n\tconst requestInit = { ...init, headers };\n\tconst parseContext = { input, init, baseUrlType, sapClient: getSapClient(input, baseUrlType) };\n\n\ttry {\n\t\tconst res = await fetchBase(input, requestInit, baseUrlType);\n\t\treturn await parseResponse<T>(res, parseContext);\n\t} catch (error: unknown) {\n\t\tif (isSapRequest(input, baseUrlType) && error instanceof SsoRequiredError && error.recoverable && !init.ssoRetried) {\n\t\t\treturn recoverSsoSessionAndRetry(error, async () => {\n\t\t\t\tconst retryInit = { ...requestInit, ssoRetried: true };\n\t\t\t\tconst res = await fetchBaseWithoutSsoRecovery(input, retryInit, baseUrlType);\n\t\t\t\treturn parseResponse<T>(res, { input, init: retryInit, baseUrlType, sapClient: getSapClient(input, baseUrlType) });\n\t\t\t});\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n\nexport async function fetchJson<T = unknown>(input: RequestInfo, init: RequestInitType = {}, baseUrlType: BaseURLType = \"odata\") {\n\tconst response = await fetchODataJson<T>(input, init, baseUrlType);\n\treturn response.data;\n}\n\ninterface FetchQueryFnBaseOptions {\n\tinit?: RequestInit;\n\tbaseUrl?: BaseURLType;\n\t/** Политика кеширования в Service Worker (`\"off\"` | `\"ttl=24h\"` | `\"ttl=24h;max=100;name=ref\"` | `\"bust=24h\"` и т.д.) */\n\tswCache?: string;\n}\n\ninterface FetchQueryFnOptions<R> extends FetchQueryFnBaseOptions {\n\ttransform: (data: Response) => Promise<R>;\n}\n\nexport function fetchQueryFn<R = unknown>(url: string, options: FetchQueryFnOptions<R>) {\n\tconst baseUrlValue = options.baseUrl;\n\tconst transform = options.transform;\n\n\treturn async (params?: { signal?: AbortSignal }): Promise<R> => {\n\t\t/**\n\t\t * QueryFn может запускаться повторно после отмены предыдущего refetch.\n\t\t * Нельзя сохранять signal в замыкании: отменённый signal сразу прервёт следующий запрос.\n\t\t */\n\t\tconst initValue = { ...options.init };\n\t\tif (!initValue.signal && params?.signal) {\n\t\t\tinitValue.signal = params.signal;\n\t\t}\n\t\tif (options.swCache) {\n\t\t\tconst headers = new Headers(initValue.headers);\n\t\t\theaders.set(\"x-sw-cache\", options.swCache);\n\t\t\tinitValue.headers = headers;\n\t\t}\n\n\t\tconst data = await fetchBase(url, initValue, baseUrlValue);\n\n\t\tif (typeof transform !== \"function\") {\n\t\t\tthrow new Error(\"fetchQueryFn requires a transformation function!\");\n\t\t}\n\n\t\treturn await transform(data);\n\t};\n}\n\ninterface FetchJsonQueryFnOptions<T, R> extends FetchQueryFnBaseOptions {\n\ttransform?: (data: T) => R;\n}\n\n/**\n * @deprecated скоро будет замена\n */\nexport function fetchJsonQueryFn<T, R = T>(url: string, options?: FetchJsonQueryFnOptions<T, R>) {\n\tconst baseUrlValue = options?.baseUrl || \"odata\";\n\tconst transform = options?.transform;\n\n\treturn async (params?: { signal: AbortSignal }) => {\n\t\tconst initValue = options?.init || {};\n\t\tif (!initValue.signal && params?.signal) {\n\t\t\tinitValue.signal = params.signal;\n\t\t}\n\n\t\tif (options?.swCache) {\n\t\t\tconst headers = new Headers(initValue.headers);\n\t\t\theaders.set(\"x-sw-cache\", options.swCache);\n\t\t\tinitValue.headers = headers;\n\t\t}\n\n\t\tconst data = await fetchJson<T>(url, initValue, baseUrlValue);\n\n\t\tif (!transform) {\n\t\t\treturn data as unknown as R;\n\t\t}\n\n\t\treturn transform ? transform(data) : (data as unknown as R);\n\t};\n}\n\n/**\n * @deprecated скоро будет замена\n */\nexport function fetchJsonMutationFn<T = unknown, TBody = unknown>(url: string, method: \"POST\" | \"PUT\" = \"POST\", baseUrl?: BaseURLType) {\n\treturn async (body: TBody, signal?: AbortSignal) => {\n\t\treturn fetchJson<T>(\n\t\t\turl,\n\t\t\t{\n\t\t\t\tmethod,\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal\n\t\t\t},\n\t\t\tbaseUrl\n\t\t);\n\t};\n}\n\n/**\n * @deprecated скоро будет замена\n */\nexport function fetchDeleteFn<T = unknown>(url: string, baseUrl?: BaseURLType) {\n\treturn async (signal?: AbortSignal) => {\n\t\treturn fetchJson<T>(url, { method: \"DELETE\", signal }, baseUrl);\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as e, S as t, _ as n, c as r, o as i, s as a, x as o } from "./fetch-
|
|
1
|
+
import { C as e, S as t, _ as n, c as r, o as i, s as a, x as o } from "./fetch-Cq29VQlt.js";
|
|
2
2
|
import { isRecord as s } from "@ryuzaki13/react-foundation-lib/validators";
|
|
3
3
|
import { formatDateAsODataDatetime as c, parseDate as l } from "@ryuzaki13/react-foundation-lib/formatters";
|
|
4
4
|
import { useEffect as u, useMemo as d } from "react";
|
|
@@ -10,7 +10,7 @@ var S = ["odata"];
|
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/odata/odataFetch.ts
|
|
12
12
|
function C(e, t, n) {
|
|
13
|
-
n
|
|
13
|
+
n !== void 0 && n !== "" && e.set(t, String(n));
|
|
14
14
|
}
|
|
15
15
|
function w(e, t = {}, r = {}) {
|
|
16
16
|
let [i, a = ""] = e.split("?"), o = new URLSearchParams(a);
|
|
@@ -41,7 +41,7 @@ async function T(e, t = {}, n = {}) {
|
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
43
|
//#region src/odata/metadataVersionCheck.ts
|
|
44
|
-
var E = __APP_BUILD_ID__, D =
|
|
44
|
+
var E = __APP_BUILD_ID__, D = 864e5;
|
|
45
45
|
function O(e) {
|
|
46
46
|
if (e) return Array.isArray(e) ? e[0] : e;
|
|
47
47
|
}
|
|
@@ -64,11 +64,11 @@ function j(n) {
|
|
|
64
64
|
return async ({ signal: r }) => {
|
|
65
65
|
let i = o().metadataVersion;
|
|
66
66
|
if (!i) return A(n.service);
|
|
67
|
-
let a =
|
|
67
|
+
let a = O((await T(`/${i.service}/${i.target}('${t(n.service)}')`, { baseUrl: e(i.service, i.baseUrl) }, { signal: r })).data), s = l(a?.lastChanged);
|
|
68
68
|
return {
|
|
69
69
|
service: n.service,
|
|
70
|
-
changedAt:
|
|
71
|
-
version:
|
|
70
|
+
changedAt: s,
|
|
71
|
+
version: s ? c(s) : null
|
|
72
72
|
};
|
|
73
73
|
};
|
|
74
74
|
}
|
|
@@ -134,17 +134,17 @@ function R(e) {
|
|
|
134
134
|
let t = m(), n = d(() => ({
|
|
135
135
|
service: e.service,
|
|
136
136
|
baseUrl: e.baseUrl
|
|
137
|
-
}), [e.baseUrl, e.service]), r =
|
|
137
|
+
}), [e.baseUrl, e.service]), r = d(() => ({ service: e.service }), [e.service]), i = p(M(r)), a = p(I(n));
|
|
138
138
|
return u(() => {
|
|
139
|
-
!e.service || !
|
|
139
|
+
!e.service || !i.isSuccess || L(t, n, i.data);
|
|
140
140
|
}, [
|
|
141
141
|
n,
|
|
142
|
-
|
|
142
|
+
a.dataUpdatedAt,
|
|
143
143
|
e.service,
|
|
144
144
|
t,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
]),
|
|
145
|
+
i.data,
|
|
146
|
+
i.isSuccess
|
|
147
|
+
]), a;
|
|
148
148
|
}
|
|
149
149
|
function z(e) {
|
|
150
150
|
return p(M(e));
|
|
@@ -307,4 +307,4 @@ function ie(e) {
|
|
|
307
307
|
//#endregion
|
|
308
308
|
export { S, I as _, re as a, w as b, q as c, K as d, G as f, V as g, F as h, ie as i, H as l, L as m, te as n, ne as o, W as p, Q as r, ee as s, $ as t, U as u, R as v, T as x, z as y };
|
|
309
309
|
|
|
310
|
-
//# sourceMappingURL=odataFetchFn-
|
|
310
|
+
//# sourceMappingURL=odataFetchFn-BdCJe4_T.js.map
|