@onlineapps/conn-orch-api-mapper 1.0.11 → 1.0.12

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/ApiMapper.js +63 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/conn-orch-api-mapper",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "API mapping connector for OA Drive - maps cookbook operations to HTTP endpoints",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/ApiMapper.js CHANGED
@@ -407,8 +407,12 @@ class ApiMapper {
407
407
  // Resolve variables in input using context
408
408
  const resolvedInput = this._resolveVariables(input, context);
409
409
 
410
+ // CRITICAL: Resolve Content Descriptors to raw data BEFORE calling handler
411
+ // Handler receives RAW DATA, not Descriptors! ApiMapper is the boundary.
412
+ const handlerInput = await this._resolveContentDescriptors(resolvedInput, operation);
413
+
410
414
  // Build request
411
- const request = this._buildRequest(operation, resolvedInput);
415
+ const request = this._buildRequest(operation, handlerInput);
412
416
 
413
417
  // Make the call
414
418
  let response;
@@ -431,6 +435,64 @@ class ApiMapper {
431
435
  }
432
436
  }
433
437
 
438
+ /**
439
+ * Resolve Content Descriptors in input to raw data
440
+ * CRITICAL: Handler receives RAW DATA, not Descriptors!
441
+ * This is the boundary between orchestration (Descriptors) and business logic (raw data).
442
+ *
443
+ * @private
444
+ * @param {Object} input - Input with potential Content Descriptors
445
+ * @param {Object} operation - Operation definition (for type hints)
446
+ * @returns {Promise<Object>} Input with Descriptors resolved to raw data
447
+ */
448
+ async _resolveContentDescriptors(input, operation) {
449
+ if (!input || typeof input !== 'object') {
450
+ return input;
451
+ }
452
+
453
+ const resolver = new ContentAccessor();
454
+ const result = { ...input };
455
+
456
+ // Get input schema from operation (if available)
457
+ const inputSchema = operation?.input || {};
458
+
459
+ for (const [key, value] of Object.entries(result)) {
460
+ // Check if this is a Content Descriptor
461
+ const isDescriptor = value && typeof value === 'object' &&
462
+ (value._descriptor === true || value.ref || value.storage_ref);
463
+
464
+ if (isDescriptor) {
465
+ const fieldSchema = inputSchema[key] || {};
466
+ const fieldType = fieldSchema.type;
467
+
468
+ // Get storage reference
469
+ const storageRef = value.ref || value.storage_ref;
470
+
471
+ if (storageRef) {
472
+ // Resolve based on field type from operations.json
473
+ if (fieldType === 'file') {
474
+ // For file type, handler expects the Descriptor (pass through)
475
+ // Handler will use ContentResolver itself
476
+ console.log(`[ApiMapper:INPUT_RESOLVE] Field '${key}' type=file, passing Descriptor through`);
477
+ // Keep as-is
478
+ } else {
479
+ // For content/string types, resolve to raw string
480
+ console.log(`[ApiMapper:INPUT_RESOLVE] Field '${key}' type=${fieldType || 'content'}, resolving Descriptor to string`);
481
+ try {
482
+ result[key] = await resolver.getAsString(storageRef);
483
+ console.log(`[ApiMapper:INPUT_RESOLVE] ✓ Resolved '${key}' from ${storageRef} (${result[key].length} chars)`);
484
+ } catch (err) {
485
+ console.error(`[ApiMapper:INPUT_RESOLVE] ✗ Failed to resolve '${key}': ${err.message}`);
486
+ throw new Error(`Failed to resolve Content Descriptor for '${key}': ${err.message}`);
487
+ }
488
+ }
489
+ }
490
+ }
491
+ }
492
+
493
+ return result;
494
+ }
495
+
434
496
  /**
435
497
  * Parse OpenAPI specification or operations.json to extract operations
436
498
  * @private