@aloma.io/integration-sdk 3.8.54 → 3.8.55

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.
@@ -32,6 +32,10 @@ export declare class OpenAPIToConnector {
32
32
  * Generate method signature with options object
33
33
  */
34
34
  private generateMethodSignature;
35
+ /**
36
+ * Get TypeScript type for a parameter based on its schema
37
+ */
38
+ private getParameterType;
35
39
  /**
36
40
  * Generate method implementation code
37
41
  */
@@ -186,7 +186,12 @@ export class OpenAPIToConnector {
186
186
  else {
187
187
  // Options object documentation
188
188
  lines.push(' *');
189
- lines.push(` * @param {Object} options (optional) - Request options`);
189
+ // Check if there are any required parameters
190
+ const hasRequiredParams = pathParams.some(p => p.required) ||
191
+ queryParams.some(p => p.required) ||
192
+ (operation.requestBody && operation.requestBody.required);
193
+ const optionsRequired = hasRequiredParams ? '(required)' : '(optional)';
194
+ lines.push(` * @param {Object} options ${optionsRequired} - Request options`);
190
195
  // Document path parameters
191
196
  for (const param of pathParams) {
192
197
  const paramType = param.schema?.type || 'string';
@@ -228,15 +233,20 @@ export class OpenAPIToConnector {
228
233
  const pathParams = [];
229
234
  const queryParams = [];
230
235
  const hasBody = !!operation.requestBody;
231
- // Identify path and query parameters
236
+ // Identify path and query parameters with their types and required status
232
237
  if (operation.parameters) {
233
238
  for (const param of operation.parameters) {
234
239
  if (typeof param === 'object' && 'name' in param && 'in' in param) {
240
+ const paramInfo = {
241
+ name: param.name,
242
+ required: param.required || false,
243
+ type: this.getParameterType(param)
244
+ };
235
245
  if (param.in === 'path') {
236
- pathParams.push(param.name);
246
+ pathParams.push(paramInfo);
237
247
  }
238
248
  else if (param.in === 'query') {
239
- queryParams.push(param.name);
249
+ queryParams.push(paramInfo);
240
250
  }
241
251
  }
242
252
  }
@@ -244,21 +254,114 @@ export class OpenAPIToConnector {
244
254
  // If there are no query params, no body, and only path params, use simple signature
245
255
  if (queryParams.length === 0 && !hasBody && pathParams.length <= 1) {
246
256
  const params = [];
247
- for (const paramName of pathParams) {
248
- params.push(`${paramName}: string`);
257
+ for (const paramInfo of pathParams) {
258
+ params.push(`${paramInfo.name}: ${paramInfo.type}`);
249
259
  }
250
260
  params.push(`options?: {headers?: {[key: string]: any}}`);
251
261
  return `(${params.join(', ')})`;
252
262
  }
253
- // Otherwise, use options object pattern
254
- return `(options?: {${[
255
- ...pathParams.map((p) => `${p}?: string`),
256
- ...queryParams.map((p) => `${p}?: any`),
257
- hasBody ? 'body?: any' : '',
258
- 'headers?: {[key: string]: any}',
259
- ]
260
- .filter(Boolean)
261
- .join(', ')}})`;
263
+ // Check if there are any required parameters
264
+ const hasRequiredParams = pathParams.some(p => p.required) ||
265
+ queryParams.some(p => p.required) ||
266
+ (hasBody && operation.requestBody?.required);
267
+ // Build detailed options object with proper types
268
+ // Group nested properties into objects (e.g., PrimaryContact.FirstName -> PrimaryContact: {FirstName: string})
269
+ const nestedObjects = new Map();
270
+ const flatProps = [];
271
+ // Process all parameters (path + query)
272
+ const allParams = [...pathParams, ...queryParams];
273
+ for (const paramInfo of allParams) {
274
+ if (paramInfo.name.includes('.')) {
275
+ // This is a nested property like PrimaryContact.FirstName
276
+ const parts = paramInfo.name.split('.');
277
+ const objectName = parts[0];
278
+ const propertyName = parts.slice(1).join('.');
279
+ if (!nestedObjects.has(objectName)) {
280
+ nestedObjects.set(objectName, []);
281
+ }
282
+ nestedObjects.get(objectName).push({
283
+ name: propertyName,
284
+ type: paramInfo.type,
285
+ required: paramInfo.required
286
+ });
287
+ }
288
+ else {
289
+ // This is a flat property
290
+ flatProps.push({
291
+ name: paramInfo.name,
292
+ type: paramInfo.type,
293
+ required: paramInfo.required
294
+ });
295
+ }
296
+ }
297
+ // Build the options properties array
298
+ const optionProps = [];
299
+ // Add flat properties
300
+ for (const prop of flatProps) {
301
+ const optional = prop.required ? '' : '?';
302
+ optionProps.push(`${prop.name}${optional}: ${prop.type}`);
303
+ }
304
+ // Add nested objects
305
+ for (const [objectName, properties] of nestedObjects) {
306
+ const nestedProps = properties.map(p => {
307
+ const optional = p.required ? '' : '?';
308
+ return `${p.name}${optional}: ${p.type}`;
309
+ }).join(', ');
310
+ // Check if all properties are optional
311
+ const allOptional = properties.every(p => !p.required);
312
+ const optional = allOptional ? '?' : '';
313
+ optionProps.push(`${objectName}${optional}: {${nestedProps}}`);
314
+ }
315
+ // Add request body
316
+ if (hasBody) {
317
+ optionProps.push('body?: any');
318
+ }
319
+ // Add custom headers
320
+ optionProps.push('headers?: {[key: string]: any}');
321
+ // If there are too many parameters, use simplified signature to avoid parsing issues
322
+ // Also check if any parameter name is too long (over 100 chars) which can cause issues
323
+ const hasLongParamNames = optionProps.some(prop => prop.length > 100);
324
+ if (optionProps.length > 15 || hasLongParamNames) {
325
+ const required = hasRequiredParams ? '' : '?';
326
+ return `(options${required}: {[key: string]: any})`;
327
+ }
328
+ const required = hasRequiredParams ? '' : '?';
329
+ return `(options${required}: {${optionProps.join(', ')}})`;
330
+ }
331
+ /**
332
+ * Get TypeScript type for a parameter based on its schema
333
+ */
334
+ getParameterType(param) {
335
+ if (param.schema) {
336
+ const schema = param.schema;
337
+ // Handle different schema types
338
+ if (schema.type) {
339
+ switch (schema.type) {
340
+ case 'string':
341
+ return 'string';
342
+ case 'integer':
343
+ case 'number':
344
+ return 'number';
345
+ case 'boolean':
346
+ return 'boolean';
347
+ case 'array':
348
+ return 'any[]';
349
+ case 'object':
350
+ return 'any';
351
+ default:
352
+ return 'any';
353
+ }
354
+ }
355
+ // Handle enum
356
+ if (schema.enum) {
357
+ return 'string';
358
+ }
359
+ // Handle $ref
360
+ if (schema.$ref) {
361
+ return 'any';
362
+ }
363
+ }
364
+ return 'any';
262
365
  }
263
366
  /**
264
367
  * Generate method implementation code
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aloma.io/integration-sdk",
3
- "version": "3.8.54",
3
+ "version": "3.8.55",
4
4
  "description": "",
5
5
  "author": "aloma.io",
6
6
  "license": "Apache-2.0",
@@ -225,7 +225,15 @@ export class OpenAPIToConnector {
225
225
  } else {
226
226
  // Options object documentation
227
227
  lines.push(' *');
228
- lines.push(` * @param {Object} options (optional) - Request options`);
228
+
229
+ // Check if there are any required parameters
230
+ const hasRequiredParams =
231
+ pathParams.some((p) => p.required) ||
232
+ queryParams.some((p) => p.required) ||
233
+ (operation.requestBody && operation.requestBody.required);
234
+
235
+ const optionsRequired = hasRequiredParams ? '(required)' : '(optional)';
236
+ lines.push(` * @param {Object} options ${optionsRequired} - Request options`);
229
237
 
230
238
  // Document path parameters
231
239
  for (const param of pathParams) {
@@ -272,18 +280,24 @@ export class OpenAPIToConnector {
272
280
  * Generate method signature with options object
273
281
  */
274
282
  private generateMethodSignature(operation: OperationInfo): string {
275
- const pathParams: string[] = [];
276
- const queryParams: string[] = [];
283
+ const pathParams: Array<{name: string; required: boolean; type: string}> = [];
284
+ const queryParams: Array<{name: string; required: boolean; type: string}> = [];
277
285
  const hasBody = !!operation.requestBody;
278
286
 
279
- // Identify path and query parameters
287
+ // Identify path and query parameters with their types and required status
280
288
  if (operation.parameters) {
281
289
  for (const param of operation.parameters) {
282
290
  if (typeof param === 'object' && 'name' in param && 'in' in param) {
291
+ const paramInfo = {
292
+ name: param.name,
293
+ required: param.required || false,
294
+ type: this.getParameterType(param),
295
+ };
296
+
283
297
  if (param.in === 'path') {
284
- pathParams.push(param.name);
298
+ pathParams.push(paramInfo);
285
299
  } else if (param.in === 'query') {
286
- queryParams.push(param.name);
300
+ queryParams.push(paramInfo);
287
301
  }
288
302
  }
289
303
  }
@@ -292,22 +306,135 @@ export class OpenAPIToConnector {
292
306
  // If there are no query params, no body, and only path params, use simple signature
293
307
  if (queryParams.length === 0 && !hasBody && pathParams.length <= 1) {
294
308
  const params: string[] = [];
295
- for (const paramName of pathParams) {
296
- params.push(`${paramName}: string`);
309
+ for (const paramInfo of pathParams) {
310
+ params.push(`${paramInfo.name}: ${paramInfo.type}`);
297
311
  }
298
312
  params.push(`options?: {headers?: {[key: string]: any}}`);
299
313
  return `(${params.join(', ')})`;
300
314
  }
301
315
 
302
- // Otherwise, use options object pattern
303
- return `(options?: {${[
304
- ...pathParams.map((p) => `${p}?: string`),
305
- ...queryParams.map((p) => `${p}?: any`),
306
- hasBody ? 'body?: any' : '',
307
- 'headers?: {[key: string]: any}',
308
- ]
309
- .filter(Boolean)
310
- .join(', ')}})`;
316
+ // Check if there are any required parameters
317
+ const hasRequiredParams =
318
+ pathParams.some((p) => p.required) ||
319
+ queryParams.some((p) => p.required) ||
320
+ (hasBody && operation.requestBody?.required);
321
+
322
+ // Build detailed options object with proper types
323
+ // Group nested properties into objects (e.g., PrimaryContact.FirstName -> PrimaryContact: {FirstName: string})
324
+ const nestedObjects: Map<string, Array<{name: string; type: string; required: boolean}>> = new Map();
325
+ const flatProps: Array<{name: string; type: string; required: boolean}> = [];
326
+
327
+ // Process all parameters (path + query)
328
+ const allParams = [...pathParams, ...queryParams];
329
+
330
+ for (const paramInfo of allParams) {
331
+ if (paramInfo.name.includes('.')) {
332
+ // This is a nested property like PrimaryContact.FirstName
333
+ const parts = paramInfo.name.split('.');
334
+ const objectName = parts[0];
335
+ const propertyName = parts.slice(1).join('.');
336
+
337
+ if (!nestedObjects.has(objectName)) {
338
+ nestedObjects.set(objectName, []);
339
+ }
340
+ nestedObjects.get(objectName)!.push({
341
+ name: propertyName,
342
+ type: paramInfo.type,
343
+ required: paramInfo.required,
344
+ });
345
+ } else {
346
+ // This is a flat property
347
+ flatProps.push({
348
+ name: paramInfo.name,
349
+ type: paramInfo.type,
350
+ required: paramInfo.required,
351
+ });
352
+ }
353
+ }
354
+
355
+ // Build the options properties array
356
+ const optionProps: string[] = [];
357
+
358
+ // Add flat properties
359
+ for (const prop of flatProps) {
360
+ const optional = prop.required ? '' : '?';
361
+ optionProps.push(`${prop.name}${optional}: ${prop.type}`);
362
+ }
363
+
364
+ // Add nested objects
365
+ for (const [objectName, properties] of nestedObjects) {
366
+ const nestedProps = properties
367
+ .map((p) => {
368
+ const optional = p.required ? '' : '?';
369
+ return `${p.name}${optional}: ${p.type}`;
370
+ })
371
+ .join(', ');
372
+
373
+ // Check if all properties are optional
374
+ const allOptional = properties.every((p) => !p.required);
375
+ const optional = allOptional ? '?' : '';
376
+
377
+ optionProps.push(`${objectName}${optional}: {${nestedProps}}`);
378
+ }
379
+
380
+ // Add request body
381
+ if (hasBody) {
382
+ optionProps.push('body?: any');
383
+ }
384
+
385
+ // Add custom headers
386
+ optionProps.push('headers?: {[key: string]: any}');
387
+
388
+ // If there are too many parameters, use simplified signature to avoid parsing issues
389
+ // Also check if any parameter name is too long (over 100 chars) which can cause issues
390
+ const hasLongParamNames = optionProps.some((prop) => prop.length > 100);
391
+ if (optionProps.length > 15 || hasLongParamNames) {
392
+ const required = hasRequiredParams ? '' : '?';
393
+ return `(options${required}: {[key: string]: any})`;
394
+ }
395
+
396
+ const required = hasRequiredParams ? '' : '?';
397
+ return `(options${required}: {${optionProps.join(', ')}})`;
398
+ }
399
+
400
+ /**
401
+ * Get TypeScript type for a parameter based on its schema
402
+ */
403
+ private getParameterType(param: any): string {
404
+ if (param.schema) {
405
+ const schema = param.schema;
406
+
407
+ // Handle different schema types
408
+ if (schema.type) {
409
+ switch (schema.type) {
410
+ case 'string':
411
+ return 'string';
412
+ case 'integer':
413
+ case 'number':
414
+ return 'number';
415
+ case 'boolean':
416
+ return 'boolean';
417
+ case 'array':
418
+ return 'any[]';
419
+ case 'object':
420
+ return 'any';
421
+ default:
422
+ return 'any';
423
+ }
424
+ }
425
+
426
+ // Handle enum
427
+ if (schema.enum) {
428
+ return 'string';
429
+ }
430
+
431
+ // Handle $ref
432
+ if (schema.$ref) {
433
+ return 'any';
434
+ }
435
+ }
436
+
437
+ return 'any';
311
438
  }
312
439
 
313
440
  /**
@@ -1,32 +0,0 @@
1
- {
2
- "openapi": "3.0.0",
3
- "info": {
4
- "title": "Test API",
5
- "version": "1.0.0",
6
- "description": "API without servers definition"
7
- },
8
- "paths": {
9
- "/users": {
10
- "get": {
11
- "summary": "List users",
12
- "operationId": "listUsers",
13
- "parameters": [
14
- {
15
- "name": "limit",
16
- "in": "query",
17
- "schema": {
18
- "type": "integer"
19
- },
20
- "description": "Maximum number of users"
21
- }
22
- ],
23
- "responses": {
24
- "200": {
25
- "description": "Success"
26
- }
27
- }
28
- }
29
- }
30
- }
31
- }
32
-