@keboola/api-client 53.0.0 → 55.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/API-SURFACE.md +2 -1
  2. package/CHANGELOG.md +68 -0
  3. package/README.md +1 -1
  4. package/dist/{admin-Di-MmGFP.cjs → admin-BZ7knTd0.cjs} +18 -2
  5. package/dist/admin-BZ7knTd0.cjs.map +1 -0
  6. package/dist/{admin-CbMOsfgs.js → admin-xFfHSZHQ.js} +13 -3
  7. package/dist/admin-xFfHSZHQ.js.map +1 -0
  8. package/dist/{componentId-DZP1rBix.js → componentId-Ba4gsJ9O.js} +3 -2
  9. package/dist/componentId-Ba4gsJ9O.js.map +1 -0
  10. package/dist/{componentId-olp0tltf.cjs → componentId-Ba_1Gv_A.cjs} +3 -2
  11. package/dist/componentId-Ba_1Gv_A.cjs.map +1 -0
  12. package/dist/{configurations-WI8H4zLk.cjs → configurations-BM63ep1s.cjs} +2 -2
  13. package/dist/{configurations-WI8H4zLk.cjs.map → configurations-BM63ep1s.cjs.map} +1 -1
  14. package/dist/{configurations-Cd6Nsox-.js → configurations-BqvtIQm4.js} +2 -2
  15. package/dist/{configurations-Cd6Nsox-.js.map → configurations-BqvtIQm4.js.map} +1 -1
  16. package/dist/constants/index.cjs +3 -2
  17. package/dist/constants/index.d.cts +2 -2
  18. package/dist/constants/index.d.ts +2 -2
  19. package/dist/constants/index.js +3 -3
  20. package/dist/{constants-DLPkpnGv.js → constants-HccvU5kx.js} +9 -2
  21. package/dist/constants-HccvU5kx.js.map +1 -0
  22. package/dist/{constants-Day8CU5i.cjs → constants-V9hAyPTo.cjs} +14 -1
  23. package/dist/constants-V9hAyPTo.cjs.map +1 -0
  24. package/dist/domain/permissions/index.cjs +4 -3
  25. package/dist/domain/permissions/index.d.cts +9 -1
  26. package/dist/domain/permissions/index.d.ts +9 -1
  27. package/dist/domain/permissions/index.js +4 -4
  28. package/dist/encryption/index.d.cts +1 -1
  29. package/dist/encryption/index.d.ts +1 -1
  30. package/dist/encryption/types.d.cts +1 -1
  31. package/dist/encryption/types.d.ts +1 -1
  32. package/dist/{index-B0prazAi.d.cts → index-BE6qM0vu.d.cts} +551 -30
  33. package/dist/{index-BoKrc8wy.d.ts → index-BGsP2QBc.d.ts} +2 -2
  34. package/dist/{index-BxgHNJ3Q.d.ts → index-CQPs3hrp.d.ts} +25 -40
  35. package/dist/{index-BL7uXOiY.d.cts → index-CWowDl63.d.cts} +2 -2
  36. package/dist/{index-BNwo-zaJ.d.cts → index-CYk7Aa8u.d.cts} +11 -3
  37. package/dist/{index-BUKMdbKh.d.cts → index-CmyFWQXn.d.cts} +25 -40
  38. package/dist/{index-CwUurckF.d.ts → index-D3hWR_e4.d.ts} +11 -3
  39. package/dist/{index-D0Gnp2QM.d.ts → index-DeWeUUfE.d.ts} +551 -30
  40. package/dist/index.cjs +12 -17
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +2 -2
  43. package/dist/index.d.ts +2 -2
  44. package/dist/index.js +11 -16
  45. package/dist/index.js.map +1 -1
  46. package/dist/management/index.cjs +1 -1
  47. package/dist/management/index.d.cts +1 -1
  48. package/dist/management/index.d.ts +1 -1
  49. package/dist/management/index.js +1 -1
  50. package/dist/management/types.d.cts +2 -2
  51. package/dist/management/types.d.ts +2 -2
  52. package/dist/{management-CmgsWmf0.js → management-BlMQnPNS.js} +40 -19
  53. package/dist/management-BlMQnPNS.js.map +1 -0
  54. package/dist/{management-Drs5G-hf.cjs → management-dIMrTTpI.cjs} +40 -19
  55. package/dist/management-dIMrTTpI.cjs.map +1 -0
  56. package/dist/metaObject-CSGF3d-o.js +53 -0
  57. package/dist/metaObject-CSGF3d-o.js.map +1 -0
  58. package/dist/metaObject-Ciyow2gr.cjs +64 -0
  59. package/dist/metaObject-Ciyow2gr.cjs.map +1 -0
  60. package/dist/metaObject-ClvW342q.d.ts +35 -0
  61. package/dist/metaObject-D7oudegV.d.cts +35 -0
  62. package/dist/oauth/index.cjs +2 -1
  63. package/dist/oauth/index.d.cts +41 -2
  64. package/dist/oauth/index.d.ts +41 -2
  65. package/dist/oauth/index.js +1 -1
  66. package/dist/oauth/types.d.cts +2 -2
  67. package/dist/oauth/types.d.ts +2 -2
  68. package/dist/{oauth-CSBChWuf.cjs → oauth-CEW2AvDV.cjs} +55 -1
  69. package/dist/oauth-CEW2AvDV.cjs.map +1 -0
  70. package/dist/{oauth-DOveZKUv.js → oauth-Fri6IthS.js} +51 -3
  71. package/dist/oauth-Fri6IthS.js.map +1 -0
  72. package/dist/{project-Onf-IcPW.cjs → project-BQ2oD6IW.cjs} +2 -2
  73. package/dist/{project-Onf-IcPW.cjs.map → project-BQ2oD6IW.cjs.map} +1 -1
  74. package/dist/{project-DmuC0bMK.js → project-aAVAOcmx.js} +2 -2
  75. package/dist/{project-DmuC0bMK.js.map → project-aAVAOcmx.js.map} +1 -1
  76. package/dist/queryService/index.d.cts +1 -1
  77. package/dist/queryService/index.d.ts +1 -1
  78. package/dist/queryService/types.d.cts +1 -1
  79. package/dist/queryService/types.d.ts +1 -1
  80. package/dist/queryService-B4h1Ez44.cjs +117 -0
  81. package/dist/queryService-B4h1Ez44.cjs.map +1 -0
  82. package/dist/queryService-DE_yE_S4.js +106 -0
  83. package/dist/queryService-DE_yE_S4.js.map +1 -0
  84. package/dist/queue/index.d.cts +1 -1
  85. package/dist/queue/index.d.ts +1 -1
  86. package/dist/sdk/configurations/index.cjs +48 -3
  87. package/dist/sdk/configurations/index.cjs.map +1 -1
  88. package/dist/sdk/configurations/index.d.cts +230 -2
  89. package/dist/sdk/configurations/index.d.ts +230 -2
  90. package/dist/sdk/configurations/index.js +48 -3
  91. package/dist/sdk/configurations/index.js.map +1 -1
  92. package/dist/sdk/dataAppServer/index.cjs +4 -40
  93. package/dist/sdk/dataAppServer/index.cjs.map +1 -1
  94. package/dist/sdk/dataAppServer/index.d.cts +1 -1
  95. package/dist/sdk/dataAppServer/index.d.ts +1 -1
  96. package/dist/sdk/dataAppServer/index.js +2 -38
  97. package/dist/sdk/dataAppServer/index.js.map +1 -1
  98. package/dist/sdk/queryService/index.cjs +3 -70
  99. package/dist/sdk/queryService/index.d.cts +2 -2
  100. package/dist/sdk/queryService/index.d.ts +2 -2
  101. package/dist/sdk/queryService/index.js +1 -70
  102. package/dist/sdk/securityPolicy/index.cjs +365 -0
  103. package/dist/sdk/securityPolicy/index.cjs.map +1 -0
  104. package/dist/sdk/securityPolicy/index.d.cts +110 -0
  105. package/dist/sdk/securityPolicy/index.d.ts +110 -0
  106. package/dist/sdk/securityPolicy/index.js +350 -0
  107. package/dist/sdk/securityPolicy/index.js.map +1 -0
  108. package/dist/sdk/securityPolicy/types.cjs +0 -0
  109. package/dist/sdk/securityPolicy/types.d.cts +2 -0
  110. package/dist/sdk/securityPolicy/types.d.ts +2 -0
  111. package/dist/sdk/securityPolicy/types.js +1 -0
  112. package/dist/sdk/semanticLayer/index.cjs +3 -2
  113. package/dist/sdk/semanticLayer/index.d.cts +3 -3
  114. package/dist/sdk/semanticLayer/index.d.ts +3 -3
  115. package/dist/sdk/semanticLayer/index.js +3 -1
  116. package/dist/sdk/semanticLayer/types.d.cts +1 -1
  117. package/dist/sdk/semanticLayer/types.d.ts +1 -1
  118. package/dist/sdk/vault/index.cjs +3 -12
  119. package/dist/sdk/vault/index.cjs.map +1 -1
  120. package/dist/sdk/vault/index.d.cts +1 -1
  121. package/dist/sdk/vault/index.d.ts +1 -1
  122. package/dist/sdk/vault/index.js +3 -12
  123. package/dist/sdk/vault/index.js.map +1 -1
  124. package/dist/{semanticLayer-D8D_3hk-.cjs → semanticLayer-BVpdWKJn.cjs} +4 -52
  125. package/dist/semanticLayer-BVpdWKJn.cjs.map +1 -0
  126. package/dist/{semanticLayer-CfjDnmsY.js → semanticLayer-Btj1Qy9O.js} +5 -47
  127. package/dist/semanticLayer-Btj1Qy9O.js.map +1 -0
  128. package/dist/storage/index.cjs +1 -1
  129. package/dist/storage/index.d.cts +2 -2
  130. package/dist/storage/index.d.ts +2 -2
  131. package/dist/storage/index.js +1 -1
  132. package/dist/storage/types.d.cts +2 -2
  133. package/dist/storage/types.d.ts +2 -2
  134. package/dist/{storage-BMrYlyLB.cjs → storage-BL-TfHp8.cjs} +2 -2
  135. package/dist/storage-BL-TfHp8.cjs.map +1 -0
  136. package/dist/{storage--2FvvLAw.js → storage-DEJN8sw-.js} +2 -2
  137. package/dist/storage-DEJN8sw-.js.map +1 -0
  138. package/dist/syncActions/index.cjs +1 -1
  139. package/dist/syncActions/index.js +1 -1
  140. package/dist/{syncActions-DToUhyP3.cjs → syncActions-B9JTiSao.cjs} +2 -2
  141. package/dist/{syncActions-DToUhyP3.cjs.map → syncActions-B9JTiSao.cjs.map} +1 -1
  142. package/dist/{syncActions-DV_aObTQ.js → syncActions-W98Jme2Z.js} +2 -2
  143. package/dist/{syncActions-DV_aObTQ.js.map → syncActions-W98Jme2Z.js.map} +1 -1
  144. package/dist/{types-iU1Sc1IM.d.ts → types-BDgOF2WN.d.ts} +6 -29
  145. package/dist/types-BXKL0wTI.d.cts +85 -0
  146. package/dist/{types-CsRfoHQw.d.cts → types-Bwvss_gW.d.cts} +1111 -412
  147. package/dist/{types-BljDxuWG.d.cts → types-DCARsJWs.d.cts} +6 -29
  148. package/dist/types-DK1bSUNr.d.ts +85 -0
  149. package/dist/{types-DjWubjvP.d.cts → types-DMhgKHCP.d.cts} +309 -74
  150. package/dist/{types-DNldEa7i.d.ts → types-J_dgwMjP.d.ts} +1111 -412
  151. package/dist/{types-CsVRsObb.d.ts → types-p_lWvuQJ.d.ts} +309 -74
  152. package/package.json +29 -3
  153. package/surface/management.md +29 -25
  154. package/dist/admin-CbMOsfgs.js.map +0 -1
  155. package/dist/admin-Di-MmGFP.cjs.map +0 -1
  156. package/dist/componentId-DZP1rBix.js.map +0 -1
  157. package/dist/componentId-olp0tltf.cjs.map +0 -1
  158. package/dist/constants-DLPkpnGv.js.map +0 -1
  159. package/dist/constants-Day8CU5i.cjs.map +0 -1
  160. package/dist/management-CmgsWmf0.js.map +0 -1
  161. package/dist/management-Drs5G-hf.cjs.map +0 -1
  162. package/dist/oauth-CSBChWuf.cjs.map +0 -1
  163. package/dist/oauth-DOveZKUv.js.map +0 -1
  164. package/dist/sdk/queryService/index.cjs.map +0 -1
  165. package/dist/sdk/queryService/index.js.map +0 -1
  166. package/dist/semanticLayer-CfjDnmsY.js.map +0 -1
  167. package/dist/semanticLayer-D8D_3hk-.cjs.map +0 -1
  168. package/dist/storage--2FvvLAw.js.map +0 -1
  169. package/dist/storage-BMrYlyLB.cjs.map +0 -1
@@ -1,11 +1,11 @@
1
1
  import { _ as HttpStatus, m as APP_USER_TOKEN_HEADER } from "../../createFetchClient-Dc_ZMuq7.js";
2
- import { t as createStorageClient } from "../../storage--2FvvLAw.js";
2
+ import { t as createStorageClient } from "../../storage-DEJN8sw-.js";
3
3
  import { n as isRowLevelSecurityError } from "../../RowLevelSecurityError-CObFqj3E.js";
4
4
  import { u as lazy } from "../../transientRetries-BORv47mH.js";
5
5
  import { t as isPlainObject } from "../../isPlainObject-BxsT8_t2.js";
6
6
  import { t as ServiceId } from "../../serviceIds-RAVtP4nK.js";
7
7
  import { t as createQueryServiceClient } from "../../queryService-DQHtHy2-.js";
8
- import { createQueryServiceSdk } from "../queryService/index.js";
8
+ import { n as createQueryServiceSdk, t as cellParser } from "../../queryService-DE_yE_S4.js";
9
9
  import { t as readJwtClaims } from "../../readJwtClaims-CMZ3cNC_.js";
10
10
  import { AsyncLocalStorage } from "node:async_hooks";
11
11
  import { readFile } from "node:fs/promises";
@@ -67,42 +67,6 @@ const createRequestContext = () => {
67
67
  }
68
68
  };
69
69
  };
70
- // src/sdks/dataAppServer/parseCell.ts
71
- const FLOAT_TYPE = /^(real|float|float64)$/i;
72
- const DECIMAL_TYPE = /^(fixed|integer|int64|numeric|bignumeric)$/i;
73
- const DECIMAL = /^-?\d+(\.\d+)?$/;
74
- const EPOCH = /^-?\d+(\.\d+)?( \d+)?$/;
75
- const BIGQUERY_TIMESTAMP = /^(\S+) (\S+) \+0000 UTC$/;
76
- const DAY_MS = 864e5;
77
- /** Every decimal of at most this many significant digits survives a round trip through a double. */
78
- const EXACT_DIGITS = 15;
79
- const significantDigits = (decimal) => decimal.replace(/[-.]/g, "").replace(/^0+/, "").replace(/0+$/, "").length;
80
- const decimalOf = (cell) => {
81
- const n = Number(cell);
82
- return DECIMAL.test(cell) && (Number.isSafeInteger(n) || significantDigits(cell) <= EXACT_DIGITS) ? n : cell;
83
- };
84
- const floatOf = (cell) => {
85
- const n = Number(cell);
86
- return Number.isFinite(n) ? n : cell;
87
- };
88
- const epochIso = (cell) => (/* @__PURE__ */ new Date(parseFloat(cell) * 1e3)).toISOString();
89
- const timestampOf = (cell) => EPOCH.test(cell) ? epochIso(cell) : cell.replace(BIGQUERY_TIMESTAMP, "$1T$2Z");
90
- /**
91
- * The parser for a Query Service cell (always a string) of one column type.
92
- *
93
- * 1. A decimal is a number only when it keeps every digit, else the string (`NUMBER(38,6)`, IDs).
94
- * 2. Floats and booleans are typed; a Snowflake `date` (epoch days) becomes `YYYY-MM-DD`.
95
- * 3. Timestamps become ISO (`timestamp_ntz` without `Z`); other types keep the string.
96
- */
97
- const cellParser = (type) => {
98
- if (DECIMAL_TYPE.test(type)) return decimalOf;
99
- if (FLOAT_TYPE.test(type)) return floatOf;
100
- if (/^bool(ean)?$/i.test(type)) return (cell) => cell === "true";
101
- if (/^date$/i.test(type)) return (cell) => EPOCH.test(cell) ? (/* @__PURE__ */ new Date(Number(cell) * DAY_MS)).toISOString().slice(0, 10) : cell;
102
- if (/^timestamp_ntz$/i.test(type)) return (cell) => EPOCH.test(cell) ? epochIso(cell).slice(0, -1) : cell;
103
- if (/^timestamp/i.test(type)) return timestampOf;
104
- return (cell) => cell;
105
- };
106
70
  // src/sdks/dataAppServer/runQuery.ts
107
71
  const PAGE_SIZE = 1e4;
108
72
  const TIMEOUT = 6e4;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/sdks/dataAppServer/express.ts","../../../src/sdks/dataAppServer/requestContext.ts","../../../src/sdks/dataAppServer/parseCell.ts","../../../src/sdks/dataAppServer/runQuery.ts","../../../src/sdks/dataAppServer/settings.ts","../../../src/sdks/dataAppServer/initializeApp.ts"],"sourcesContent":["import { isRowLevelSecurityError } from '../../errors';\nimport { HttpStatus } from '../../internal';\n\ntype ErrorResponse = {\n headersSent: boolean;\n status(code: number): { json(body: unknown): unknown };\n};\n\n/** Answers a row-level security refusal with 403 and passes any other error on. */\nexport const createExpressErrorHandler =\n () => (err: unknown, _req: unknown, res: ErrorResponse, next: (err?: unknown) => void) => {\n if (res.headersSent || !isRowLevelSecurityError(err)) {\n next(err);\n return;\n }\n res.status(HttpStatus.FORBIDDEN).json({ error: err.message, code: 'ROW_LEVEL_SECURITY' });\n };\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\nimport { APP_USER_TOKEN_HEADER } from '../../internal';\nimport { readJwtClaims } from '../../utils/readJwtClaims';\n\ntype NodeHeaders = Record<string, string | string[] | undefined>;\n\ntype HeadersLike = { get(name: string): string | null };\n\n/** A Fetch `Request` or `Headers`, or a Node request (Express, Fastify) with its lower-case `headers`. */\nexport type AppRequest = HeadersLike | { headers: HeadersLike | NodeHeaders };\n\n/** The signed-in user as the app user token names them; `email` only when the IdP verified it. */\nexport type AppUser = { idp: string; sub: string; email?: string };\n\ntype Scope = { appUserToken: string | undefined; user: AppUser | undefined };\n\nexport type RequestContext = ReturnType<typeof createRequestContext>;\n\nconst isHeadersLike = (headers: object): headers is HeadersLike =>\n 'get' in headers && typeof headers.get === 'function';\n\nconst appUserTokenOf = (request: AppRequest): string | undefined => {\n const headers = 'headers' in request ? request.headers : request;\n if (isHeadersLike(headers)) return headers.get(APP_USER_TOKEN_HEADER) || undefined;\n const value = headers[APP_USER_TOKEN_HEADER.toLowerCase()];\n return (Array.isArray(value) ? value[0] : value) || undefined;\n};\n\nconst userOf = (token: string): AppUser | undefined => {\n const { idp, sub, email } = readJwtClaims(token) ?? {};\n if (typeof idp !== 'string' || typeof sub !== 'string' || !idp || !sub) return undefined;\n return typeof email === 'string' && email ? { idp, sub, email } : { idp, sub };\n};\n\n/**\n * The signed-in user of the request being handled, kept across every `await` the request makes.\n *\n * - Work the request starts keeps its user: a timer, a promise cached at module level, a listener.\n * - `currentUser()` reads the token payload unverified: safe only behind Keboola's apps proxy.\n * - `currentUserKey()` is the same for every token of one user (`idp` + `sub`): a per-user cache key.\n */\nexport const createRequestContext = () => {\n const storage = new AsyncLocalStorage<Scope>();\n const current = () => storage.getStore();\n\n return {\n runWithRequest: <T>(request: AppRequest, fn: () => T): T => {\n const appUserToken = appUserTokenOf(request);\n return storage.run(\n { appUserToken, user: appUserToken ? userOf(appUserToken) : undefined },\n fn,\n );\n },\n current,\n currentUser: () => current()?.user,\n currentUserKey: () => {\n const user = current()?.user;\n return user && JSON.stringify([user.idp, user.sub]);\n },\n };\n};\n","const FLOAT_TYPE = /^(real|float|float64)$/i;\nconst DECIMAL_TYPE = /^(fixed|integer|int64|numeric|bignumeric)$/i;\nconst DECIMAL = /^-?\\d+(\\.\\d+)?$/;\nconst EPOCH = /^-?\\d+(\\.\\d+)?( \\d+)?$/;\nconst BIGQUERY_TIMESTAMP = /^(\\S+) (\\S+) \\+0000 UTC$/;\nconst DAY_MS = 86_400_000;\n/** Every decimal of at most this many significant digits survives a round trip through a double. */\nconst EXACT_DIGITS = 15;\n\nconst significantDigits = (decimal: string) =>\n decimal.replace(/[-.]/g, '').replace(/^0+/, '').replace(/0+$/, '').length;\n\nconst decimalOf = (cell: string) => {\n const n = Number(cell);\n return DECIMAL.test(cell) && (Number.isSafeInteger(n) || significantDigits(cell) <= EXACT_DIGITS)\n ? n\n : cell;\n};\n\nconst floatOf = (cell: string) => {\n const n = Number(cell);\n return Number.isFinite(n) ? n : cell;\n};\n\nconst epochIso = (cell: string) => new Date(parseFloat(cell) * 1000).toISOString();\n\nconst timestampOf = (cell: string) =>\n EPOCH.test(cell) ? epochIso(cell) : cell.replace(BIGQUERY_TIMESTAMP, '$1T$2Z');\n\n/**\n * The parser for a Query Service cell (always a string) of one column type.\n *\n * 1. A decimal is a number only when it keeps every digit, else the string (`NUMBER(38,6)`, IDs).\n * 2. Floats and booleans are typed; a Snowflake `date` (epoch days) becomes `YYYY-MM-DD`.\n * 3. Timestamps become ISO (`timestamp_ntz` without `Z`); other types keep the string.\n */\nexport const cellParser = (type: string): ((cell: string) => unknown) => {\n if (DECIMAL_TYPE.test(type)) return decimalOf;\n if (FLOAT_TYPE.test(type)) return floatOf;\n if (/^bool(ean)?$/i.test(type)) return (cell) => cell === 'true';\n if (/^date$/i.test(type)) {\n return (cell) =>\n EPOCH.test(cell) ? new Date(Number(cell) * DAY_MS).toISOString().slice(0, 10) : cell;\n }\n if (/^timestamp_ntz$/i.test(type)) {\n return (cell) => (EPOCH.test(cell) ? epochIso(cell).slice(0, -1) : cell);\n }\n if (/^timestamp/i.test(type)) return timestampOf;\n return (cell) => cell;\n};\n","import { createQueryServiceClient, type QueryServiceCredential } from '../../clients/queryService';\nimport type { QueryResult } from '../../clients/queryService/types';\nimport { isRowLevelSecurityError } from '../../errors';\nimport { APP_USER_TOKEN_HEADER } from '../../internal';\nimport { createQueryServiceSdk, type ExecuteQueryOptions } from '../queryService';\n\nimport { cellParser } from './parseCell';\nimport type { RequestContext } from './requestContext';\nimport type { Settings } from './settings';\n\nexport type RunQueryOptions = Pick<ExecuteQueryOptions, 'timeout' | 'maxRows' | 'signal'>;\n\nconst PAGE_SIZE = 10_000;\nconst TIMEOUT = 60_000;\n\nconst refusalWarning = (scope: ReturnType<RequestContext['current']>) => {\n const prefix = '[dataAppServer] row-level security refused';\n if (scope?.appUserToken) return `${prefix} the query for this user`;\n const reason = scope\n ? 'the request has none'\n : 'it ran outside a user request (startup, timer, background job)';\n return `${prefix} a query sent without ${APP_USER_TOKEN_HEADER}: ${reason}`;\n};\n\nconst toRecords = ({ columns = [], data = [], numberOfRows }: QueryResult, capped: boolean) => {\n const parsers = columns.map(({ name, type }) => ({\n key: name.toLowerCase(),\n parse: cellParser(type),\n }));\n const keys = new Set<string>();\n for (const { key } of parsers) {\n if (keys.has(key))\n throw new Error(`runQuery: two columns are named \"${key}\"; alias one with AS`);\n keys.add(key);\n }\n const rows = data.map((row) => {\n const record: Record<string, unknown> = {};\n parsers.forEach(({ key, parse }, i) => {\n const cell = row[i];\n record[key] = cell == null ? null : parse(cell);\n });\n return record;\n });\n if (!capped && numberOfRows !== undefined && rows.length < numberOfRows) {\n throw new Error(`runQuery: got ${rows.length} of ${numberOfRows} rows`);\n }\n return rows;\n};\n\n/**\n * Runs one SQL statement in the app's workspace and resolves every row as a record.\n *\n * - Sends the request's user token with the app's Storage token; without a user, the Storage token.\n * - A repeated column name, or fewer rows than counted (no `maxRows`), throws instead of losing data.\n */\nexport const createRunQuery = (settings: Settings, requestContext: RequestContext) => {\n const queryService = createQueryServiceSdk({\n queryServiceClient: createQueryServiceClient({\n baseUrl: settings.queryServiceUrl,\n auth: async (): Promise<QueryServiceCredential> => {\n const storageToken = await settings.storageToken();\n const appUserToken = requestContext.current()?.appUserToken;\n return appUserToken\n ? { type: 'app-user-token', token: appUserToken, storageToken }\n : { type: 'sapi-token', token: storageToken };\n },\n }),\n });\n\n return async (sql: string, options: RunQueryOptions = {}): Promise<Record<string, unknown>[]> => {\n const scope = requestContext.current();\n const [result] = await queryService\n .executeQuery(\n settings.branchId(),\n await settings.workspaceId(),\n { statements: [sql], transactional: false },\n { ...options, pageSize: PAGE_SIZE, timeout: options.timeout ?? TIMEOUT },\n )\n .catch((error: unknown) => {\n if (isRowLevelSecurityError(error)) console.warn(refusalWarning(scope));\n throw error;\n });\n return result ? toRecords(result, options.maxRows !== undefined) : [];\n };\n};\n","import { readFile } from 'node:fs/promises';\n\nimport { createStorageClient } from '../../clients/storage';\nimport { ServiceId } from '../../constants/serviceIds';\nimport { lazy } from '../../utils/async';\nimport { isPlainObject } from '../../utils/isPlainObject';\n\nexport type Env = Record<string, string | undefined>;\n\n/** A setting the app needs is missing or unreadable; the message names the variable or file. */\nexport class AppConfigError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'AppConfigError';\n }\n}\n\nexport type Settings = ReturnType<typeof createSettings>;\n\nconst STACK_INDEX_TIMEOUT = 10_000;\n\nconst required = (env: Env, name: string) => {\n const value = env[name];\n if (!value) throw new AppConfigError(`Missing environment variable ${name}`);\n return value;\n};\n\nconst storageTokenFrom = async (env: Env) => {\n const file = env.STORAGE_API_TOKEN_PATH;\n if (!file) {\n if (env.KBC_TOKEN) return env.KBC_TOKEN;\n throw new AppConfigError('Missing Storage token: set STORAGE_API_TOKEN_PATH or KBC_TOKEN');\n }\n const content = await readFile(file, 'utf8').catch((error: unknown) => {\n throw new AppConfigError(`Cannot read the file in STORAGE_API_TOKEN_PATH: ${file}`, {\n cause: error,\n });\n });\n const token = content.trim();\n if (!token)\n throw new AppConfigError(`The token file in STORAGE_API_TOKEN_PATH is empty: ${file}`);\n return token;\n};\n\nconst manifestWorkspaceId = async (file: string) => {\n let manifest: unknown;\n try {\n manifest = JSON.parse(await readFile(file, 'utf8'));\n } catch (error) {\n throw new AppConfigError(`Cannot read the JSON in KBC_WORKSPACE_MANIFEST_PATH: ${file}`, {\n cause: error,\n });\n }\n const id = isPlainObject(manifest) ? manifest.workspaceId : undefined;\n if ((typeof id === 'string' && id) || typeof id === 'number') return String(id);\n throw new AppConfigError(\n `The manifest in KBC_WORKSPACE_MANIFEST_PATH has no workspaceId: ${file}`,\n );\n};\n\nconst queryServiceUrlFromIndex = async (kbcUrl: string, token: string) => {\n const { services } = await createStorageClient({\n baseUrl: kbcUrl,\n auth: { type: 'sapi-token', token },\n }).getStackInfo({ exclude: 'components' }, AbortSignal.timeout(STACK_INDEX_TIMEOUT));\n const url = services.find(({ id }) => id === ServiceId.Query)?.url;\n if (!url) throw new AppConfigError('The stack index of KBC_URL lists no query service');\n return url;\n};\n\n/**\n * What the platform provides a data app, read on first use; a missing value throws `AppConfigError`.\n *\n * - The Storage token is read on every call: the platform rotates the file in `STORAGE_API_TOKEN_PATH`.\n * - The workspace ID and the Query Service URL are read once per process.\n * - The Query Service URL is `QUERY_SERVICE_URL`, or the stack index of `KBC_URL` (local runs).\n */\nexport const createSettings = (env: Env) => {\n const storageToken = () => storageTokenFrom(env);\n const manifest = env.KBC_WORKSPACE_MANIFEST_PATH;\n\n return {\n branchId: () => required(env, 'BRANCH_ID'),\n storageToken,\n workspaceId: lazy(() =>\n manifest ? manifestWorkspaceId(manifest) : required(env, 'WORKSPACE_ID'),\n ),\n queryServiceUrl: lazy(\n async () =>\n env.QUERY_SERVICE_URL ||\n queryServiceUrlFromIndex(required(env, 'KBC_URL'), await storageToken()),\n ),\n hasWorkspace: Boolean(manifest || env.WORKSPACE_ID),\n };\n};\n","import { createExpressErrorHandler } from './express';\nimport { type AppRequest, createRequestContext } from './requestContext';\nimport { createRunQuery } from './runQuery';\nimport { createSettings, type Env } from './settings';\n\n/** `env` replaces `process.env` (tests, local runs). */\nexport type DataAppServerOptions = { env?: Env };\n\n/**\n * Sets up Keboola access for this data app process; call it once.\n *\n * - Synchronous, no network call, never throws: each setting is read on first use.\n * - `workspace` is `undefined` when no workspace is configured (the app has no Storage access).\n * - `server.expressMiddleware()` goes first and `server.expressErrorHandler()` last.\n */\nexport const initializeApp = ({ env = process.env }: DataAppServerOptions = {}) => {\n const settings = createSettings(env);\n const requestContext = createRequestContext();\n\n return {\n server: {\n runWithRequest: requestContext.runWithRequest,\n currentUser: requestContext.currentUser,\n currentUserKey: requestContext.currentUserKey,\n expressMiddleware: () => (req: AppRequest, _res: unknown, next: () => void) =>\n requestContext.runWithRequest(req, next),\n expressErrorHandler: createExpressErrorHandler,\n },\n workspace: settings.hasWorkspace\n ? { runQuery: createRunQuery(settings, requestContext) }\n : undefined,\n };\n};\n\nexport type DataAppServer = ReturnType<typeof initializeApp>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/sdks/dataAppServer/express.ts","../../../src/sdks/dataAppServer/requestContext.ts","../../../src/sdks/dataAppServer/runQuery.ts","../../../src/sdks/dataAppServer/settings.ts","../../../src/sdks/dataAppServer/initializeApp.ts"],"sourcesContent":["import { isRowLevelSecurityError } from '../../errors';\nimport { HttpStatus } from '../../internal';\n\ntype ErrorResponse = {\n headersSent: boolean;\n status(code: number): { json(body: unknown): unknown };\n};\n\n/** Answers a row-level security refusal with 403 and passes any other error on. */\nexport const createExpressErrorHandler =\n () => (err: unknown, _req: unknown, res: ErrorResponse, next: (err?: unknown) => void) => {\n if (res.headersSent || !isRowLevelSecurityError(err)) {\n next(err);\n return;\n }\n res.status(HttpStatus.FORBIDDEN).json({ error: err.message, code: 'ROW_LEVEL_SECURITY' });\n };\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\nimport { APP_USER_TOKEN_HEADER } from '../../internal';\nimport { readJwtClaims } from '../../utils/readJwtClaims';\n\ntype NodeHeaders = Record<string, string | string[] | undefined>;\n\ntype HeadersLike = { get(name: string): string | null };\n\n/** A Fetch `Request` or `Headers`, or a Node request (Express, Fastify) with its lower-case `headers`. */\nexport type AppRequest = HeadersLike | { headers: HeadersLike | NodeHeaders };\n\n/** The signed-in user as the app user token names them; `email` only when the IdP verified it. */\nexport type AppUser = { idp: string; sub: string; email?: string };\n\ntype Scope = { appUserToken: string | undefined; user: AppUser | undefined };\n\nexport type RequestContext = ReturnType<typeof createRequestContext>;\n\nconst isHeadersLike = (headers: HeadersLike | NodeHeaders): headers is HeadersLike =>\n 'get' in headers && typeof headers.get === 'function';\n\nconst appUserTokenOf = (request: AppRequest): string | undefined => {\n const headers = 'headers' in request ? request.headers : request;\n if (isHeadersLike(headers)) return headers.get(APP_USER_TOKEN_HEADER) || undefined;\n const value = headers[APP_USER_TOKEN_HEADER.toLowerCase()];\n return (Array.isArray(value) ? value[0] : value) || undefined;\n};\n\nconst userOf = (token: string): AppUser | undefined => {\n const { idp, sub, email } = readJwtClaims(token) ?? {};\n if (typeof idp !== 'string' || typeof sub !== 'string' || !idp || !sub) return undefined;\n return typeof email === 'string' && email ? { idp, sub, email } : { idp, sub };\n};\n\n/**\n * The signed-in user of the request being handled, kept across every `await` the request makes.\n *\n * - Work the request starts keeps its user: a timer, a promise cached at module level, a listener.\n * - `currentUser()` reads the token payload unverified: safe only behind Keboola's apps proxy.\n * - `currentUserKey()` is the same for every token of one user (`idp` + `sub`): a per-user cache key.\n */\nexport const createRequestContext = () => {\n const storage = new AsyncLocalStorage<Scope>();\n const current = () => storage.getStore();\n\n return {\n runWithRequest: <T>(request: AppRequest, fn: () => T): T => {\n const appUserToken = appUserTokenOf(request);\n return storage.run(\n { appUserToken, user: appUserToken ? userOf(appUserToken) : undefined },\n fn,\n );\n },\n current,\n currentUser: () => current()?.user,\n currentUserKey: () => {\n const user = current()?.user;\n return user && JSON.stringify([user.idp, user.sub]);\n },\n };\n};\n","import { createQueryServiceClient, type QueryServiceCredential } from '../../clients/queryService';\nimport type { QueryResult } from '../../clients/queryService/types';\nimport { isRowLevelSecurityError } from '../../errors';\nimport { APP_USER_TOKEN_HEADER } from '../../internal';\nimport { cellParser, createQueryServiceSdk, type ExecuteQueryOptions } from '../queryService';\n\nimport type { RequestContext } from './requestContext';\nimport type { Settings } from './settings';\n\nexport type RunQueryOptions = Pick<ExecuteQueryOptions, 'timeout' | 'maxRows' | 'signal'>;\n\nconst PAGE_SIZE = 10_000;\nconst TIMEOUT = 60_000;\n\nconst refusalWarning = (scope: ReturnType<RequestContext['current']>) => {\n const prefix = '[dataAppServer] row-level security refused';\n if (scope?.appUserToken) return `${prefix} the query for this user`;\n const reason = scope\n ? 'the request has none'\n : 'it ran outside a user request (startup, timer, background job)';\n return `${prefix} a query sent without ${APP_USER_TOKEN_HEADER}: ${reason}`;\n};\n\nconst toRecords = ({ columns = [], data = [], numberOfRows }: QueryResult, capped: boolean) => {\n const parsers = columns.map(({ name, type }) => ({\n key: name.toLowerCase(),\n parse: cellParser(type),\n }));\n const keys = new Set<string>();\n for (const { key } of parsers) {\n if (keys.has(key))\n throw new Error(`runQuery: two columns are named \"${key}\"; alias one with AS`);\n keys.add(key);\n }\n const rows = data.map((row) => {\n const record: Record<string, unknown> = {};\n parsers.forEach(({ key, parse }, i) => {\n const cell = row[i];\n record[key] = cell == null ? null : parse(cell);\n });\n return record;\n });\n if (!capped && numberOfRows !== undefined && rows.length < numberOfRows) {\n throw new Error(`runQuery: got ${rows.length} of ${numberOfRows} rows`);\n }\n return rows;\n};\n\n/**\n * Runs one SQL statement in the app's workspace and resolves every row as a record.\n *\n * - Sends the request's user token with the app's Storage token; without a user, the Storage token.\n * - A repeated column name, or fewer rows than counted (no `maxRows`), throws instead of losing data.\n */\nexport const createRunQuery = (settings: Settings, requestContext: RequestContext) => {\n const queryService = createQueryServiceSdk({\n queryServiceClient: createQueryServiceClient({\n baseUrl: settings.queryServiceUrl,\n auth: async (): Promise<QueryServiceCredential> => {\n const storageToken = await settings.storageToken();\n const appUserToken = requestContext.current()?.appUserToken;\n return appUserToken\n ? { type: 'app-user-token', token: appUserToken, storageToken }\n : { type: 'sapi-token', token: storageToken };\n },\n }),\n });\n\n return async (sql: string, options: RunQueryOptions = {}): Promise<Record<string, unknown>[]> => {\n const scope = requestContext.current();\n const [result] = await queryService\n .executeQuery(\n settings.branchId(),\n await settings.workspaceId(),\n { statements: [sql], transactional: false },\n { ...options, pageSize: PAGE_SIZE, timeout: options.timeout ?? TIMEOUT },\n )\n .catch((error: unknown) => {\n if (isRowLevelSecurityError(error)) console.warn(refusalWarning(scope));\n throw error;\n });\n return result ? toRecords(result, options.maxRows !== undefined) : [];\n };\n};\n","import { readFile } from 'node:fs/promises';\n\nimport { createStorageClient } from '../../clients/storage';\nimport { ServiceId } from '../../constants/serviceIds';\nimport { lazy } from '../../utils/async';\nimport { isPlainObject } from '../../utils/isPlainObject';\n\nexport type Env = Record<string, string | undefined>;\n\n/** A setting the app needs is missing or unreadable; the message names the variable or file. */\nexport class AppConfigError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'AppConfigError';\n }\n}\n\nexport type Settings = ReturnType<typeof createSettings>;\n\nconst STACK_INDEX_TIMEOUT = 10_000;\n\nconst required = (env: Env, name: string) => {\n const value = env[name];\n if (!value) throw new AppConfigError(`Missing environment variable ${name}`);\n return value;\n};\n\nconst storageTokenFrom = async (env: Env) => {\n const file = env.STORAGE_API_TOKEN_PATH;\n if (!file) {\n if (env.KBC_TOKEN) return env.KBC_TOKEN;\n throw new AppConfigError('Missing Storage token: set STORAGE_API_TOKEN_PATH or KBC_TOKEN');\n }\n const content = await readFile(file, 'utf8').catch((error: unknown) => {\n throw new AppConfigError(`Cannot read the file in STORAGE_API_TOKEN_PATH: ${file}`, {\n cause: error,\n });\n });\n const token = content.trim();\n if (!token)\n throw new AppConfigError(`The token file in STORAGE_API_TOKEN_PATH is empty: ${file}`);\n return token;\n};\n\nconst manifestWorkspaceId = async (file: string) => {\n let manifest: unknown;\n try {\n manifest = JSON.parse(await readFile(file, 'utf8'));\n } catch (error) {\n throw new AppConfigError(`Cannot read the JSON in KBC_WORKSPACE_MANIFEST_PATH: ${file}`, {\n cause: error,\n });\n }\n const id = isPlainObject(manifest) ? manifest.workspaceId : undefined;\n if ((typeof id === 'string' && id) || typeof id === 'number') return String(id);\n throw new AppConfigError(\n `The manifest in KBC_WORKSPACE_MANIFEST_PATH has no workspaceId: ${file}`,\n );\n};\n\nconst queryServiceUrlFromIndex = async (kbcUrl: string, token: string) => {\n const { services } = await createStorageClient({\n baseUrl: kbcUrl,\n auth: { type: 'sapi-token', token },\n }).getStackInfo({ exclude: 'components' }, AbortSignal.timeout(STACK_INDEX_TIMEOUT));\n const url = services.find(({ id }) => id === ServiceId.Query)?.url;\n if (!url) throw new AppConfigError('The stack index of KBC_URL lists no query service');\n return url;\n};\n\n/**\n * What the platform provides a data app, read on first use; a missing value throws `AppConfigError`.\n *\n * - The Storage token is read on every call: the platform rotates the file in `STORAGE_API_TOKEN_PATH`.\n * - The workspace ID and the Query Service URL are read once per process.\n * - The Query Service URL is `QUERY_SERVICE_URL`, or the stack index of `KBC_URL` (local runs).\n */\nexport const createSettings = (env: Env) => {\n const storageToken = () => storageTokenFrom(env);\n const manifest = env.KBC_WORKSPACE_MANIFEST_PATH;\n\n return {\n branchId: () => required(env, 'BRANCH_ID'),\n storageToken,\n workspaceId: lazy(() =>\n manifest ? manifestWorkspaceId(manifest) : required(env, 'WORKSPACE_ID'),\n ),\n queryServiceUrl: lazy(\n async () =>\n env.QUERY_SERVICE_URL ||\n queryServiceUrlFromIndex(required(env, 'KBC_URL'), await storageToken()),\n ),\n hasWorkspace: Boolean(manifest || env.WORKSPACE_ID),\n };\n};\n","import { createExpressErrorHandler } from './express';\nimport { type AppRequest, createRequestContext } from './requestContext';\nimport { createRunQuery } from './runQuery';\nimport { createSettings, type Env } from './settings';\n\n/** `env` replaces `process.env` (tests, local runs). */\nexport type DataAppServerOptions = { env?: Env };\n\n/**\n * Sets up Keboola access for this data app process; call it once.\n *\n * - Synchronous, no network call, never throws: each setting is read on first use.\n * - `workspace` is `undefined` when no workspace is configured (the app has no Storage access).\n * - `server.expressMiddleware()` goes first and `server.expressErrorHandler()` last.\n */\nexport const initializeApp = ({ env = process.env }: DataAppServerOptions = {}) => {\n const settings = createSettings(env);\n const requestContext = createRequestContext();\n\n return {\n server: {\n runWithRequest: requestContext.runWithRequest,\n currentUser: requestContext.currentUser,\n currentUserKey: requestContext.currentUserKey,\n expressMiddleware: () => (req: AppRequest, _res: unknown, next: () => void) =>\n requestContext.runWithRequest(req, next),\n expressErrorHandler: createExpressErrorHandler,\n },\n workspace: settings.hasWorkspace\n ? { runQuery: createRunQuery(settings, requestContext) }\n : undefined,\n };\n};\n\nexport type DataAppServer = ReturnType<typeof initializeApp>;\n"],"mappings":"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"}
@@ -1,71 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_ValidationError = require("../../ValidationError-BXcFX4nD.cjs");
3
- const require_collectByOffset = require("../../collectByOffset-DgxJ3zT9.cjs");
4
- // src/sdks/queryService/queryServiceSdk.ts
5
- const DEFAULT_EXECUTE_QUERY_PAGE_SIZE = 5e3;
6
- const DEFAULT_POLL_INTERVAL = 500;
7
- const DEFAULT_TIMEOUT = 3e5;
8
- const assertPositiveInteger = (name, value) => {
9
- if (!Number.isInteger(value) || value <= 0) throw new require_ValidationError.ValidationError(`${name} must be a positive integer, got ${value}`);
10
- };
11
- /**
12
- * Higher-level SDK composing queryService client calls with job polling and result-page
13
- * auto-pagination for orchestrated workflows.
14
- */
15
- const createQueryServiceSdk = ({ queryServiceClient }) => {
16
- /**
17
- * Fetches every page of a statement's results, merging them into a single {@link QueryResult}.
18
- *
19
- * - `columns`, `status`, `rowsAffected` and `message` describe the statement, so they are read off
20
- * the first page; `collectByOffset` hands back only the rows.
21
- * - A second consumer that needs the envelope back is the cue for a `collectPagesByOffset`
22
- * sibling resolving `{ first, items }`, not for widening this closure.
23
- */
24
- const fetchAllResultPages = async (queryJobId, statementId, pageSize, maxRows) => {
25
- let firstPage;
26
- const data = await require_collectByOffset.collectByOffset({
27
- pageSize,
28
- limit: maxRows,
29
- fetchFrom: async (offset, pageSize) => {
30
- const page = await queryServiceClient.getQueryResults(queryJobId, statementId, {
31
- offset,
32
- pageSize
33
- });
34
- firstPage ??= page;
35
- return page.data ?? [];
36
- }
37
- });
38
- if (!firstPage) throw new Error(`No result pages returned for statement ${statementId}`);
39
- return {
40
- ...firstPage,
41
- data
42
- };
43
- };
44
- /**
45
- * Submits a query job, waits for completion, and fetches results for every statement —
46
- * auto-paginating each statement's results so sets larger than `pageSize` come back in full
47
- * instead of being truncated at the API's default page size.
48
- *
49
- * - Throws {@link QueryJobError} when the job ended `failed`, carrying the failed statements.
50
- * - Throws the poll's failure when the wait timed out, was aborted or ran out of attempts.
51
- */
52
- const executeQuery = async (branchId, workspaceId, body, options = {}) => {
53
- const { pageSize = DEFAULT_EXECUTE_QUERY_PAGE_SIZE, maxRows, interval = DEFAULT_POLL_INTERVAL, timeout = DEFAULT_TIMEOUT, ...pollOptions } = options;
54
- assertPositiveInteger("pageSize", pageSize);
55
- if (maxRows !== void 0) assertPositiveInteger("maxRows", maxRows);
56
- const { queryJobId } = await queryServiceClient.createQueryJob(branchId, workspaceId, body);
57
- const status = await queryServiceClient.poller({
58
- init: { id: queryJobId },
59
- interval,
60
- timeout,
61
- ...pollOptions
62
- }).wait();
63
- const results = [];
64
- for (const statement of status.statements) results.push(await fetchAllResultPages(queryJobId, statement.id, pageSize, maxRows));
65
- return results;
66
- };
67
- return { executeQuery };
68
- };
69
- exports.createQueryServiceSdk = createQueryServiceSdk;
70
-
71
- //# sourceMappingURL=index.cjs.map
2
+ const require_queryService = require("../../queryService-B4h1Ez44.cjs");
3
+ exports.cellParser = require_queryService.cellParser;
4
+ exports.createQueryServiceSdk = require_queryService.createQueryServiceSdk;
@@ -1,2 +1,2 @@
1
- import { b as ExecuteQueryOptions, x as createQueryServiceSdk } from "../../index-BUKMdbKh.cjs";
2
- export { ExecuteQueryOptions, createQueryServiceSdk };
1
+ import { S as createQueryServiceSdk, b as cellParser, x as ExecuteQueryOptions } from "../../index-CmyFWQXn.cjs";
2
+ export { ExecuteQueryOptions, cellParser, createQueryServiceSdk };
@@ -1,2 +1,2 @@
1
- import { b as ExecuteQueryOptions, x as createQueryServiceSdk } from "../../index-BxgHNJ3Q.js";
2
- export { ExecuteQueryOptions, createQueryServiceSdk };
1
+ import { S as createQueryServiceSdk, b as cellParser, x as ExecuteQueryOptions } from "../../index-CQPs3hrp.js";
2
+ export { ExecuteQueryOptions, cellParser, createQueryServiceSdk };
@@ -1,70 +1 @@
1
- import { t as ValidationError } from "../../ValidationError-BsdFDGY2.js";
2
- import { t as collectByOffset } from "../../collectByOffset-i8Tdoze7.js";
3
- // src/sdks/queryService/queryServiceSdk.ts
4
- const DEFAULT_EXECUTE_QUERY_PAGE_SIZE = 5e3;
5
- const DEFAULT_POLL_INTERVAL = 500;
6
- const DEFAULT_TIMEOUT = 3e5;
7
- const assertPositiveInteger = (name, value) => {
8
- if (!Number.isInteger(value) || value <= 0) throw new ValidationError(`${name} must be a positive integer, got ${value}`);
9
- };
10
- /**
11
- * Higher-level SDK composing queryService client calls with job polling and result-page
12
- * auto-pagination for orchestrated workflows.
13
- */
14
- const createQueryServiceSdk = ({ queryServiceClient }) => {
15
- /**
16
- * Fetches every page of a statement's results, merging them into a single {@link QueryResult}.
17
- *
18
- * - `columns`, `status`, `rowsAffected` and `message` describe the statement, so they are read off
19
- * the first page; `collectByOffset` hands back only the rows.
20
- * - A second consumer that needs the envelope back is the cue for a `collectPagesByOffset`
21
- * sibling resolving `{ first, items }`, not for widening this closure.
22
- */
23
- const fetchAllResultPages = async (queryJobId, statementId, pageSize, maxRows) => {
24
- let firstPage;
25
- const data = await collectByOffset({
26
- pageSize,
27
- limit: maxRows,
28
- fetchFrom: async (offset, pageSize) => {
29
- const page = await queryServiceClient.getQueryResults(queryJobId, statementId, {
30
- offset,
31
- pageSize
32
- });
33
- firstPage ??= page;
34
- return page.data ?? [];
35
- }
36
- });
37
- if (!firstPage) throw new Error(`No result pages returned for statement ${statementId}`);
38
- return {
39
- ...firstPage,
40
- data
41
- };
42
- };
43
- /**
44
- * Submits a query job, waits for completion, and fetches results for every statement —
45
- * auto-paginating each statement's results so sets larger than `pageSize` come back in full
46
- * instead of being truncated at the API's default page size.
47
- *
48
- * - Throws {@link QueryJobError} when the job ended `failed`, carrying the failed statements.
49
- * - Throws the poll's failure when the wait timed out, was aborted or ran out of attempts.
50
- */
51
- const executeQuery = async (branchId, workspaceId, body, options = {}) => {
52
- const { pageSize = DEFAULT_EXECUTE_QUERY_PAGE_SIZE, maxRows, interval = DEFAULT_POLL_INTERVAL, timeout = DEFAULT_TIMEOUT, ...pollOptions } = options;
53
- assertPositiveInteger("pageSize", pageSize);
54
- if (maxRows !== void 0) assertPositiveInteger("maxRows", maxRows);
55
- const { queryJobId } = await queryServiceClient.createQueryJob(branchId, workspaceId, body);
56
- const status = await queryServiceClient.poller({
57
- init: { id: queryJobId },
58
- interval,
59
- timeout,
60
- ...pollOptions
61
- }).wait();
62
- const results = [];
63
- for (const statement of status.statements) results.push(await fetchAllResultPages(queryJobId, statement.id, pageSize, maxRows));
64
- return results;
65
- };
66
- return { executeQuery };
67
- };
68
- export { createQueryServiceSdk };
69
-
70
- //# sourceMappingURL=index.js.map
1
+ export { t as cellParser, n as createQueryServiceSdk } from "../../queryService-DE_yE_S4.js";