catalyst-relay 0.5.13 → 0.5.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/dist/index.mjs CHANGED
@@ -2346,16 +2346,64 @@ function parseDataPreview(xml, maxRows, isTable) {
2346
2346
  const namespace = "http://www.sap.com/adt/dataPreview";
2347
2347
  const metadataElements = doc.getElementsByTagNameNS(namespace, "metadata");
2348
2348
  const columns = [];
2349
+ const SAP_TYPE_MAP = {
2350
+ "8": "integer",
2351
+ // Int8
2352
+ "I": "integer",
2353
+ // Integer
2354
+ "P": "decimal",
2355
+ // Packed decimal
2356
+ "F": "float",
2357
+ // Floating point
2358
+ "D": "date",
2359
+ // Date (YYYYMMDD)
2360
+ "T": "time",
2361
+ // Time (HHMMSS)
2362
+ "S": "timestamp",
2363
+ // Timestamp
2364
+ "C": "string",
2365
+ // Character
2366
+ "N": "string",
2367
+ // Numeric character string
2368
+ "V": "string",
2369
+ // Variable-length character
2370
+ "X": "binary"
2371
+ // Raw binary/hex
2372
+ };
2349
2373
  for (let i = 0; i < metadataElements.length; i++) {
2350
2374
  const meta = metadataElements[i];
2351
2375
  if (!meta) continue;
2352
2376
  const nameAttr = isTable ? "name" : "camelCaseName";
2353
2377
  const name = meta.getAttributeNS(namespace, nameAttr) || meta.getAttribute("name");
2354
- const dataType = meta.getAttributeNS(namespace, "colType") || meta.getAttribute("colType");
2378
+ const colType = meta.getAttributeNS(namespace, "colType") || meta.getAttribute("colType");
2379
+ const rawType = meta.getAttributeNS(namespace, "type") || meta.getAttribute("type");
2380
+ const isKeyFigure = meta.getAttributeNS(namespace, "isKeyFigure") === "true";
2381
+ let dataType;
2382
+ if (colType && colType.trim() !== "") {
2383
+ dataType = colType;
2384
+ } else if (isKeyFigure) {
2385
+ dataType = "decimal";
2386
+ } else if (rawType && SAP_TYPE_MAP[rawType]) {
2387
+ dataType = SAP_TYPE_MAP[rawType];
2388
+ } else {
2389
+ dataType = "string";
2390
+ }
2391
+ const allAttrs = {};
2392
+ for (let j = 0; j < meta.attributes.length; j++) {
2393
+ const attr = meta.attributes[j];
2394
+ if (!attr) {
2395
+ continue;
2396
+ }
2397
+ allAttrs[attr.name] = attr.value;
2398
+ }
2355
2399
  if (!name || !dataType) continue;
2356
2400
  columns.push({ name, dataType });
2357
2401
  }
2358
2402
  const dataSetElements = doc.getElementsByTagNameNS(namespace, "dataSet");
2403
+ for (let i = 0; i < dataSetElements.length; i++) {
2404
+ const dataSet = dataSetElements[i];
2405
+ if (!dataSet) continue;
2406
+ }
2359
2407
  if (columns.length === 0 && dataSetElements.length > 0) {
2360
2408
  for (let i = 0; i < dataSetElements.length; i++) {
2361
2409
  const dataSet = dataSetElements[i];
@@ -2438,7 +2486,7 @@ async function previewData(client, query) {
2438
2486
 
2439
2487
  // src/core/adt/data_extraction/freestyle.ts
2440
2488
  var DEFAULT_ROW_LIMIT = 100;
2441
- async function freestyleQuery(client, sqlQuery, limit = DEFAULT_ROW_LIMIT) {
2489
+ async function freestyleQuery(client, sqlQuery, limit = DEFAULT_ROW_LIMIT, timeout) {
2442
2490
  debug(`Freestyle query: ${sqlQuery}`);
2443
2491
  const [response, requestErr] = await client.request({
2444
2492
  method: "POST",
@@ -2448,16 +2496,21 @@ async function freestyleQuery(client, sqlQuery, limit = DEFAULT_ROW_LIMIT) {
2448
2496
  },
2449
2497
  headers: {
2450
2498
  "Accept": "application/xml, application/vnd.sap.adt.datapreview.table.v1+xml",
2451
- "Content-Type": "text/plain"
2499
+ "Content-Type": "text/plain",
2500
+ // Override stateful base header: each preview request is independent; stateless
2501
+ // lets SAP route to any work process and recycle it after the request, preventing
2502
+ // GENERATE_SUBPOOL_DIR_FULL (36-pool limit per work process).
2503
+ "X-sap-adt-sessiontype": "stateless"
2452
2504
  },
2453
- body: sqlQuery
2505
+ body: sqlQuery,
2506
+ ...timeout !== void 0 && { timeout }
2454
2507
  });
2455
2508
  if (requestErr) return err(requestErr);
2456
2509
  if (!response.ok) {
2457
2510
  const text2 = await response.text();
2458
2511
  debug(`Freestyle query error response: ${text2.substring(0, 500)}`);
2459
2512
  const errorMsg = extractError(text2);
2460
- return err(new Error(`Freestyle query failed: ${errorMsg}`));
2513
+ return err(new Error(`Freestyle query failed: ${errorMsg}`, { cause: text2 }));
2461
2514
  }
2462
2515
  const text = await response.text();
2463
2516
  const [dataFrame, parseErr] = parseDataPreview(text, limit, true);
@@ -2718,7 +2771,16 @@ function parseTransportTasks(doc) {
2718
2771
  position: el.getAttribute("tm:position") || ""
2719
2772
  });
2720
2773
  }
2721
- tasks.push({ taskId, objects });
2774
+ const owner = taskEl.getAttribute("tm:owner");
2775
+ const description = taskEl.getAttribute("tm:desc");
2776
+ const status = taskEl.getAttribute("tm:status");
2777
+ tasks.push({
2778
+ taskId,
2779
+ ...owner ? { owner } : {},
2780
+ ...description ? { description } : {},
2781
+ ...status ? { status } : {},
2782
+ objects
2783
+ });
2722
2784
  }
2723
2785
  return tasks;
2724
2786
  }
@@ -3112,6 +3174,12 @@ async function countRows2(state, requestor, objectName, objectType, parameters =
3112
3174
  return countRows(requestor, objectName, objectType, parameters);
3113
3175
  }
3114
3176
 
3177
+ // src/client/methods/preview/freestyleQuery.ts
3178
+ async function freestyleQuery2(state, requestor, sqlQuery, limit, timeout) {
3179
+ if (!state.session) return err(new Error("Not logged in"));
3180
+ return freestyleQuery(requestor, sqlQuery, limit, timeout);
3181
+ }
3182
+
3115
3183
  // src/client/methods/search/search.ts
3116
3184
  async function search(state, requestor, query, options) {
3117
3185
  if (!state.session) return err(new Error("Not logged in"));
@@ -3295,7 +3363,7 @@ function buildUrl2(baseUrl, path, params) {
3295
3363
  // src/client/methods/internal/request.ts
3296
3364
  async function executeRequest(deps, options, selfRequest) {
3297
3365
  const { state, ssoCerts, getCookieHeader, storeCookies: storeCookies2 } = deps;
3298
- const { method, path, params, headers: customHeaders, body } = options;
3366
+ const { method, path, params, headers: customHeaders, body, timeout: requestTimeout } = options;
3299
3367
  const { config } = state;
3300
3368
  debug(`Request ${method} ${path} - CSRF token in state: ${state.csrfToken?.substring(0, 20) || "null"}...`);
3301
3369
  const headers = buildRequestHeaders(
@@ -3322,7 +3390,7 @@ async function executeRequest(deps, options, selfRequest) {
3322
3390
  cert: ssoCerts?.cert,
3323
3391
  key: ssoCerts?.key,
3324
3392
  rejectUnauthorized: !config.insecure,
3325
- timeout: config.timeout ?? DEFAULT_TIMEOUT
3393
+ timeout: requestTimeout ?? config.timeout ?? DEFAULT_TIMEOUT
3326
3394
  });
3327
3395
  storeCookies2(response);
3328
3396
  if (response.status === 403) {
@@ -3345,7 +3413,7 @@ async function executeRequest(deps, options, selfRequest) {
3345
3413
  cert: ssoCerts?.cert,
3346
3414
  key: ssoCerts?.key,
3347
3415
  rejectUnauthorized: !config.insecure,
3348
- timeout: config.timeout ?? DEFAULT_TIMEOUT
3416
+ timeout: requestTimeout ?? config.timeout ?? DEFAULT_TIMEOUT
3349
3417
  });
3350
3418
  storeCookies2(retryResponse);
3351
3419
  return ok(retryResponse);
@@ -3516,6 +3584,9 @@ var ADTClientImpl = class {
3516
3584
  async countRows(objectName, objectType, parameters = []) {
3517
3585
  return countRows2(this.state, this.requestor, objectName, objectType, parameters);
3518
3586
  }
3587
+ async freestyleQuery(sqlQuery, limit, timeout) {
3588
+ return freestyleQuery2(this.state, this.requestor, sqlQuery, limit, timeout);
3589
+ }
3519
3590
  // --- Search ---
3520
3591
  async search(query, options) {
3521
3592
  return search(this.state, this.requestor, query, options);