@spfn/core 0.1.0-alpha.62 → 0.1.0-alpha.63

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.
@@ -250,9 +250,13 @@ async function generateClient(mappings, options) {
250
250
  const startTime = Date.now();
251
251
  const grouped = groupByResource(mappings);
252
252
  const resourceNames = Object.keys(grouped);
253
- const code = generateClientCode(mappings, grouped);
254
- await mkdir(dirname(options.outputPath), { recursive: true });
255
- await writeFile(options.outputPath, code, "utf-8");
253
+ if (options.splitByResource === false) {
254
+ const code = generateClientCode(mappings, grouped, options);
255
+ await mkdir(dirname(options.outputPath), { recursive: true });
256
+ await writeFile(options.outputPath, code, "utf-8");
257
+ } else {
258
+ await generateSplitClient(mappings, grouped, options);
259
+ }
256
260
  return {
257
261
  routesScanned: mappings.length,
258
262
  contractsFound: mappings.length,
@@ -269,7 +273,7 @@ function generateClientCode(mappings, grouped, options) {
269
273
  {
270
274
  code += generateTypes(mappings);
271
275
  }
272
- code += generateApiObject(grouped);
276
+ code += generateApiObject(grouped, options);
273
277
  code += generateFooter();
274
278
  return code;
275
279
  }
@@ -382,7 +386,7 @@ export const api = {
382
386
  `;
383
387
  for (let j = 0; j < routes.length; j++) {
384
388
  const route = routes[j];
385
- code += generateMethodCode(route);
389
+ code += generateMethodCode(route, options);
386
390
  }
387
391
  code += ` }`;
388
392
  if (i < resourceNames.length - 1) {
@@ -398,12 +402,11 @@ export const api = {
398
402
  }
399
403
  function generateMethodCode(mapping, options) {
400
404
  const methodName = generateMethodName(mapping);
401
- const contractType = `typeof ${mapping.contractName}`;
402
405
  const hasParams = mapping.hasParams || mapping.path.includes(":");
403
406
  const hasQuery = mapping.hasQuery || false;
404
407
  const hasBody = mapping.hasBody || false;
405
408
  let code = "";
406
- {
409
+ if (options.includeJsDoc !== false) {
407
410
  code += ` /**
408
411
  `;
409
412
  code += ` * ${mapping.method} ${mapping.path}
@@ -413,14 +416,15 @@ function generateMethodCode(mapping, options) {
413
416
  }
414
417
  code += ` ${methodName}: (`;
415
418
  const params = [];
419
+ const typeName = generateTypeName(mapping);
416
420
  if (hasParams) {
417
- params.push(`params: InferContract<${contractType}>['params']`);
421
+ params.push(`params: ${typeName}Params`);
418
422
  }
419
423
  if (hasQuery) {
420
- params.push(`query?: InferContract<${contractType}>['query']`);
424
+ params.push(`query?: ${typeName}Query`);
421
425
  }
422
426
  if (hasBody) {
423
- params.push(`body: InferContract<${contractType}>['body']`);
427
+ params.push(`body: ${typeName}Body`);
424
428
  }
425
429
  if (params.length > 0) {
426
430
  code += `options: { ${params.join(", ")} }`;
@@ -487,6 +491,130 @@ function countUniqueContractFiles(mappings) {
487
491
  }
488
492
  return files.size;
489
493
  }
494
+ async function generateSplitClient(_mappings, grouped, options) {
495
+ const outputPath = options.outputPath;
496
+ const outputDir = outputPath.endsWith(".ts") || outputPath.endsWith(".js") ? outputPath.replace(/\.[jt]s$/, "") : outputPath;
497
+ await mkdir(outputDir, { recursive: true });
498
+ const resourceNames = Object.keys(grouped);
499
+ for (let i = 0; i < resourceNames.length; i++) {
500
+ const resourceName = resourceNames[i];
501
+ const routes = grouped[resourceName];
502
+ const code = generateResourceFile(resourceName, routes, options);
503
+ const filePath = `${outputDir}/${resourceName}.ts`;
504
+ await writeFile(filePath, code, "utf-8");
505
+ }
506
+ const indexCode = generateIndexFile(resourceNames);
507
+ const indexPath = `${outputDir}/index.ts`;
508
+ await writeFile(indexPath, indexCode, "utf-8");
509
+ }
510
+ function generateResourceFile(resourceName, routes, options) {
511
+ let code = "";
512
+ code += generateHeader();
513
+ code += `import { client } from '@spfn/core/client';
514
+ `;
515
+ {
516
+ code += `import type { InferContract } from '@spfn/core';
517
+ `;
518
+ }
519
+ code += `
520
+ `;
521
+ const importGroups = groupContractsByImportPath(routes);
522
+ const importPaths = Object.keys(importGroups);
523
+ for (let i = 0; i < importPaths.length; i++) {
524
+ const importPath = importPaths[i];
525
+ const contracts = importGroups[importPath];
526
+ code += `import { ${contracts.join(", ")} } from '${importPath}';
527
+ `;
528
+ }
529
+ code += `
530
+ `;
531
+ {
532
+ code += `// ============================================
533
+ `;
534
+ code += `// Types
535
+ `;
536
+ code += `// ============================================
537
+
538
+ `;
539
+ for (let i = 0; i < routes.length; i++) {
540
+ const route = routes[i];
541
+ const typeName = generateTypeName(route);
542
+ const contractType = `typeof ${route.contractName}`;
543
+ code += `export type ${typeName}Response = InferContract<${contractType}>['response'];
544
+ `;
545
+ if (route.hasQuery) {
546
+ code += `export type ${typeName}Query = InferContract<${contractType}>['query'];
547
+ `;
548
+ }
549
+ if (route.hasParams || route.path.includes(":")) {
550
+ code += `export type ${typeName}Params = InferContract<${contractType}>['params'];
551
+ `;
552
+ }
553
+ if (route.hasBody) {
554
+ code += `export type ${typeName}Body = InferContract<${contractType}>['body'];
555
+ `;
556
+ }
557
+ code += `
558
+ `;
559
+ }
560
+ }
561
+ code += `/**
562
+ `;
563
+ code += ` * ${resourceName} API
564
+ `;
565
+ code += ` */
566
+ `;
567
+ code += `export const ${resourceName} = {
568
+ `;
569
+ for (let i = 0; i < routes.length; i++) {
570
+ const route = routes[i];
571
+ code += generateMethodCode(route, options);
572
+ }
573
+ code += `} as const;
574
+ `;
575
+ return code;
576
+ }
577
+ function generateIndexFile(resourceNames, _options) {
578
+ let code = "";
579
+ code += generateHeader();
580
+ code += `export { client } from '@spfn/core/client';
581
+
582
+ `;
583
+ for (let i = 0; i < resourceNames.length; i++) {
584
+ const resourceName = resourceNames[i];
585
+ code += `export * from './${resourceName}.js';
586
+ `;
587
+ }
588
+ code += `
589
+ `;
590
+ for (let i = 0; i < resourceNames.length; i++) {
591
+ const resourceName = resourceNames[i];
592
+ code += `import { ${resourceName} } from './${resourceName}.js';
593
+ `;
594
+ }
595
+ code += `
596
+ `;
597
+ code += `/**
598
+ `;
599
+ code += ` * Type-safe API client
600
+ `;
601
+ code += ` */
602
+ `;
603
+ code += `export const api = {
604
+ `;
605
+ for (let i = 0; i < resourceNames.length; i++) {
606
+ const resourceName = resourceNames[i];
607
+ code += ` ${resourceName}`;
608
+ if (i < resourceNames.length - 1) {
609
+ code += `,`;
610
+ }
611
+ code += `
612
+ `;
613
+ }
614
+ code += `} as const;
615
+ `;
616
+ return code;
617
+ }
490
618
  var PinoAdapter = class _PinoAdapter {
491
619
  logger;
492
620
  constructor(config) {
@@ -1281,7 +1409,9 @@ function createContractGenerator(config = {}) {
1281
1409
  }
1282
1410
  const stats = await generateClient(allContracts, {
1283
1411
  // For backwards compatibility
1284
- outputPath});
1412
+ outputPath,
1413
+ includeJsDoc: true
1414
+ });
1285
1415
  if (options.debug) {
1286
1416
  contractLogger.info("Client generated", {
1287
1417
  endpoints: stats.methodsGenerated,