@contractkit/plugin-typescript 0.20.0 → 0.21.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.
package/dist/index.js CHANGED
@@ -2572,72 +2572,64 @@ function generateSdkOptions() {
2572
2572
  ].join("\n");
2573
2573
  }
2574
2574
  __name(generateSdkOptions, "generateSdkOptions");
2575
- function generateSdkAggregator(input) {
2576
- const sdkOptionsImportPath = input.sdkOptionsImportPath ?? "./sdk-options.js";
2577
- const sdkClassName = input.sdkClassName ?? "Sdk";
2578
- const inlinedByArea = /* @__PURE__ */ new Map();
2575
+ function generateAreaClient(input) {
2576
+ const { area, outPath, inlineFiles, subareaClients, sdkOptionsPath } = input;
2577
+ const className = deriveAreaClientClassName(area);
2578
+ const collectedMethodLines = [];
2579
+ const seenMethods = /* @__PURE__ */ new Set();
2579
2580
  const typesByImportPath = /* @__PURE__ */ new Map();
2580
2581
  const unresolvedTypes = /* @__PURE__ */ new Set();
2581
2582
  let needsJson = false;
2582
2583
  let needsBigIntReplacer = false;
2583
2584
  let needsBigIntReviver = false;
2584
2585
  let needsQueryString = false;
2585
- for (const area of input.areas) {
2586
- const collected = [];
2587
- const seenMethods = /* @__PURE__ */ new Set();
2588
- for (const inline of area.inlineFiles) {
2589
- const includeInternal = inline.codegenOptions.includeInternal ?? false;
2590
- const { lines: methodLines, methodNames } = generateClientMethods(inline.root, inline.codegenOptions);
2591
- for (const name of methodNames) {
2592
- if (seenMethods.has(name)) {
2593
- throw new Error(`[sdk] duplicate method '${name}' in area '${area.area}': two area-level files contribute the same method. Disambiguate via 'sdk:' or move one into a subarea.`);
2594
- }
2595
- seenMethods.add(name);
2586
+ for (const inline of inlineFiles) {
2587
+ const includeInternal = inline.codegenOptions.includeInternal ?? false;
2588
+ const { lines: methodLines, methodNames } = generateClientMethods(inline.root, inline.codegenOptions);
2589
+ for (const name of methodNames) {
2590
+ if (seenMethods.has(name)) {
2591
+ throw new Error(`[sdk] duplicate method '${name}' in area '${area}': two area-level files contribute the same method. Disambiguate via 'sdk:' or move one into a subarea.`);
2596
2592
  }
2597
- collected.push(...methodLines);
2598
- if (sdkNeedsJson(inline.root, includeInternal)) needsJson = true;
2599
- if (sdkNeedsBigIntReplacer(inline.root, includeInternal)) needsBigIntReplacer = true;
2600
- if (sdkNeedsBigIntReviver(inline.root, includeInternal)) needsBigIntReviver = true;
2601
- if (sdkNeedsQueryString(inline.root, includeInternal)) needsQueryString = true;
2602
- const typesForFile = collectTypes2(inline.root, inline.codegenOptions.modelsWithInput, inline.codegenOptions.modelsWithOutput, includeInternal);
2603
- const { modelOutPaths, outPath } = inline.codegenOptions;
2604
- if (modelOutPaths && outPath) {
2605
- const fromDir = dirname3(outPath);
2606
- for (const t of typesForFile) {
2607
- const typeOutPath = modelOutPaths.get(t);
2608
- if (typeOutPath) {
2609
- let rel = relative3(fromDir, typeOutPath).replace(/\.ts$/, ".js");
2610
- if (!rel.startsWith(".")) rel = "./" + rel;
2611
- const set = typesByImportPath.get(rel) ?? /* @__PURE__ */ new Set();
2612
- set.add(t);
2613
- typesByImportPath.set(rel, set);
2614
- } else {
2615
- unresolvedTypes.add(t);
2616
- }
2593
+ seenMethods.add(name);
2594
+ }
2595
+ collectedMethodLines.push(...methodLines);
2596
+ if (sdkNeedsJson(inline.root, includeInternal)) needsJson = true;
2597
+ if (sdkNeedsBigIntReplacer(inline.root, includeInternal)) needsBigIntReplacer = true;
2598
+ if (sdkNeedsBigIntReviver(inline.root, includeInternal)) needsBigIntReviver = true;
2599
+ if (sdkNeedsQueryString(inline.root, includeInternal)) needsQueryString = true;
2600
+ const typesForFile = collectTypes2(inline.root, inline.codegenOptions.modelsWithInput, inline.codegenOptions.modelsWithOutput, includeInternal);
2601
+ const { modelOutPaths } = inline.codegenOptions;
2602
+ if (modelOutPaths) {
2603
+ const fromDir = dirname3(outPath);
2604
+ for (const t of typesForFile) {
2605
+ const typeOutPath = modelOutPaths.get(t);
2606
+ if (typeOutPath) {
2607
+ let rel = relative3(fromDir, typeOutPath).replace(/\.ts$/, ".js");
2608
+ if (!rel.startsWith(".")) rel = "./" + rel;
2609
+ const set = typesByImportPath.get(rel) ?? /* @__PURE__ */ new Set();
2610
+ set.add(t);
2611
+ typesByImportPath.set(rel, set);
2612
+ } else {
2613
+ unresolvedTypes.add(t);
2617
2614
  }
2618
2615
  }
2619
2616
  }
2620
- inlinedByArea.set(area.area, {
2621
- lines: collected,
2622
- methodNames: seenMethods
2623
- });
2624
2617
  }
2618
+ let sdkOptionsRel = relative3(dirname3(outPath), sdkOptionsPath).replace(/\.ts$/, ".js");
2619
+ if (!sdkOptionsRel.startsWith(".")) sdkOptionsRel = "./" + sdkOptionsRel;
2625
2620
  const lines = [];
2626
2621
  const jsonImport = needsJson ? ", JsonValue" : "";
2627
- lines.push(`import type { SdkFetch${jsonImport} } from '${sdkOptionsImportPath}';`);
2622
+ lines.push(`import type { SdkFetch${jsonImport} } from '${sdkOptionsRel}';`);
2628
2623
  const valueImports = [];
2629
2624
  if (needsBigIntReplacer) valueImports.push("bigIntReplacer");
2630
2625
  if (needsBigIntReviver) valueImports.push("parseJson");
2631
2626
  if (needsQueryString) valueImports.push("buildQueryString");
2632
2627
  if (valueImports.length > 0) {
2633
- lines.push(`import { ${valueImports.join(", ")} } from '${sdkOptionsImportPath}';`);
2628
+ lines.push(`import { ${valueImports.join(", ")} } from '${sdkOptionsRel}';`);
2634
2629
  }
2635
- lines.push(`import type { SdkOptions } from '${sdkOptionsImportPath}';`);
2636
- lines.push(`import { createSdkFetch } from '${sdkOptionsImportPath}';`);
2637
- const typeImportPaths = [
2630
+ for (const path of [
2638
2631
  ...typesByImportPath.keys()
2639
- ].sort();
2640
- for (const path of typeImportPaths) {
2632
+ ].sort()) {
2641
2633
  const names = [
2642
2634
  ...typesByImportPath.get(path)
2643
2635
  ].sort();
@@ -2649,40 +2641,51 @@ function generateSdkAggregator(input) {
2649
2641
  lines.push(`import type { ${t} } from './${pascalToDotCase(t)}.js';`);
2650
2642
  }
2651
2643
  const importedClients = /* @__PURE__ */ new Set();
2644
+ for (const sc of subareaClients) {
2645
+ const key = `${sc.client.className}|${sc.client.importPath}`;
2646
+ if (importedClients.has(key)) continue;
2647
+ importedClients.add(key);
2648
+ lines.push(`import { ${sc.client.className} } from '${sc.client.importPath}';`);
2649
+ }
2650
+ lines.push("");
2651
+ lines.push(`export class ${className} {`);
2652
+ for (const sc of subareaClients) {
2653
+ lines.push(` readonly ${sc.propertyName}: ${sc.client.className};`);
2654
+ }
2655
+ if (subareaClients.length > 0) lines.push("");
2656
+ if (collectedMethodLines.length > 0 || subareaClients.length > 0) {
2657
+ const fetchModifier = collectedMethodLines.length > 0 ? "private " : "";
2658
+ lines.push(` constructor(${fetchModifier}fetch: SdkFetch) {`);
2659
+ for (const sc of subareaClients) {
2660
+ lines.push(` this.${sc.propertyName} = new ${sc.client.className}(fetch);`);
2661
+ }
2662
+ lines.push(" }");
2663
+ }
2664
+ for (const ln of collectedMethodLines) lines.push(ln);
2665
+ lines.push("}");
2666
+ lines.push("");
2667
+ return lines.join("\n");
2668
+ }
2669
+ __name(generateAreaClient, "generateAreaClient");
2670
+ function generateSdkAggregator(input) {
2671
+ const sdkOptionsImportPath = input.sdkOptionsImportPath ?? "./sdk-options.js";
2672
+ const sdkClassName = input.sdkClassName ?? "Sdk";
2673
+ const lines = [];
2674
+ lines.push(`import type { SdkOptions } from '${sdkOptionsImportPath}';`);
2675
+ lines.push(`import { createSdkFetch } from '${sdkOptionsImportPath}';`);
2676
+ const importedClients = /* @__PURE__ */ new Set();
2652
2677
  const pushClientImport = /* @__PURE__ */ __name((c) => {
2653
2678
  const key = `${c.className}|${c.importPath}`;
2654
2679
  if (importedClients.has(key)) return;
2655
2680
  importedClients.add(key);
2656
2681
  lines.push(`import { ${c.className} } from '${c.importPath}';`);
2657
2682
  }, "pushClientImport");
2683
+ for (const area of input.areas) pushClientImport(area.client);
2658
2684
  for (const c of input.topLevelClients) pushClientImport(c);
2659
- for (const area of input.areas) {
2660
- for (const sc of area.subareaClients) pushClientImport(sc.client);
2661
- }
2662
2685
  lines.push("");
2663
- for (const area of input.areas) {
2664
- const areaClassName = deriveAreaClientClassName(area.area);
2665
- const inlined = inlinedByArea.get(area.area);
2666
- lines.push(`class ${areaClassName} {`);
2667
- for (const sc of area.subareaClients) {
2668
- lines.push(` readonly ${sc.propertyName}: ${sc.client.className};`);
2669
- }
2670
- if (area.subareaClients.length > 0) lines.push("");
2671
- if (inlined.lines.length > 0 || area.subareaClients.length > 0) {
2672
- const fetchModifier = inlined.lines.length > 0 ? "private " : "";
2673
- lines.push(` constructor(${fetchModifier}fetch: SdkFetch) {`);
2674
- for (const sc of area.subareaClients) {
2675
- lines.push(` this.${sc.propertyName} = new ${sc.client.className}(fetch);`);
2676
- }
2677
- lines.push(" }");
2678
- }
2679
- for (const ln of inlined.lines) lines.push(ln);
2680
- lines.push("}");
2681
- lines.push("");
2682
- }
2683
2686
  lines.push(`export class ${sdkClassName} {`);
2684
2687
  for (const area of input.areas) {
2685
- lines.push(` readonly ${deriveAreaPropertyName(area.area)}: ${deriveAreaClientClassName(area.area)};`);
2688
+ lines.push(` readonly ${deriveAreaPropertyName(area.area)}: ${area.client.className};`);
2686
2689
  }
2687
2690
  for (const c of input.topLevelClients) {
2688
2691
  lines.push(` readonly ${c.propertyName}: ${c.className};`);
@@ -2691,7 +2694,7 @@ function generateSdkAggregator(input) {
2691
2694
  lines.push(" constructor(options: SdkOptions) {");
2692
2695
  lines.push(" const sdkFetch = options.fetch ?? createSdkFetch(options);");
2693
2696
  for (const area of input.areas) {
2694
- lines.push(` this.${deriveAreaPropertyName(area.area)} = new ${deriveAreaClientClassName(area.area)}(sdkFetch);`);
2697
+ lines.push(` this.${deriveAreaPropertyName(area.area)} = new ${area.client.className}(sdkFetch);`);
2695
2698
  }
2696
2699
  for (const c of input.topLevelClients) {
2697
2700
  lines.push(` this.${c.propertyName} = new ${c.className}(sdkFetch);`);
@@ -3017,6 +3020,34 @@ function computeSdkOutPath(filePath, rootDir, clientOutput, commonRoot, meta = {
3017
3020
  return join(baseOutDir, relDir, defaultOutName);
3018
3021
  }
3019
3022
  __name(computeSdkOutPath, "computeSdkOutPath");
3023
+ function computeSdkAreaClientOutPath(area, rootDir, clientOutput) {
3024
+ const filename = area;
3025
+ const baseOutDir = resolve(rootDir);
3026
+ const fixHiddenSegment = /* @__PURE__ */ __name((path) => {
3027
+ const segments = path.split("/");
3028
+ const last = segments[segments.length - 1] ?? "";
3029
+ if (last.startsWith(".")) segments[segments.length - 1] = `${filename}${last}`;
3030
+ return segments.join("/");
3031
+ }, "fixHiddenSegment");
3032
+ if (clientOutput && TEMPLATE_VAR_RE.test(clientOutput)) {
3033
+ const resolved = resolveTemplate(clientOutput, {
3034
+ filename,
3035
+ dir: "",
3036
+ ext: "ck",
3037
+ area,
3038
+ subarea: ""
3039
+ });
3040
+ const cleaned = fixHiddenSegment(resolved.replace(/\/+/g, "/").replace(/^\//, ""));
3041
+ if (includesFilename(cleaned)) return join(baseOutDir, cleaned);
3042
+ return join(baseOutDir, cleaned, `${filename}.client.ts`);
3043
+ }
3044
+ if (clientOutput) {
3045
+ if (includesFilename(clientOutput)) return join(baseOutDir, clientOutput);
3046
+ return join(baseOutDir, clientOutput, `${filename}.client.ts`);
3047
+ }
3048
+ return join(baseOutDir, `${filename}.client.ts`);
3049
+ }
3050
+ __name(computeSdkAreaClientOutPath, "computeSdkAreaClientOutPath");
3020
3051
  function computeSdkTypeOutPath(filePath, rootDir, typeOutput, commonRoot, meta = {}) {
3021
3052
  if (!filePath.endsWith(".ck")) return null;
3022
3053
  const baseName = filePath.split("/").pop();
@@ -3537,13 +3568,14 @@ function collectSdkOutput(config, rootDir, inputs, units, globalFiles) {
3537
3568
  content: generateSdkOptions()
3538
3569
  });
3539
3570
  const hasAnything = sdkClientInfos.length > 0 || areaBuckets.size > 0;
3571
+ const areaClientOutPaths = /* @__PURE__ */ new Map();
3540
3572
  if (hasAnything) {
3541
3573
  const sdkEntryDir = dirname6(sdkEntryPath);
3542
3574
  const sdkOptionsRel = relative6(sdkEntryDir, sdkOptionsPath).replace(/\.ts$/, ".js");
3543
3575
  const sdkOptionsImportPath = sdkOptionsRel.startsWith(".") ? sdkOptionsRel : "./" + sdkOptionsRel;
3544
3576
  const sdkClassName = sdkName ? sdkName.split(/[-._\s]+/).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("") + "Sdk" : "Sdk";
3545
- const toClientImport = /* @__PURE__ */ __name((info) => {
3546
- let rel = relative6(sdkEntryDir, info.outPath).replace(/\.ts$/, ".js");
3577
+ const toClientImport = /* @__PURE__ */ __name((sourceDir, info) => {
3578
+ let rel = relative6(sourceDir, info.outPath).replace(/\.ts$/, ".js");
3547
3579
  if (!rel.startsWith(".")) rel = "./" + rel;
3548
3580
  return {
3549
3581
  className: info.className,
@@ -3551,44 +3583,93 @@ function collectSdkOutput(config, rootDir, inputs, units, globalFiles) {
3551
3583
  importPath: rel
3552
3584
  };
3553
3585
  }, "toClientImport");
3554
- const topLevelClients = topLevelEntries.map((e) => ({
3586
+ const topLevelClients = topLevelEntries.map((e) => toClientImport(sdkEntryDir, {
3587
+ outPath: e.outPath,
3555
3588
  className: deriveClientClassName(e.ast.file),
3556
- propertyName: deriveClientPropertyName(e.ast.file),
3557
- importPath: (() => {
3558
- const rel = relative6(sdkEntryDir, e.outPath).replace(/\.ts$/, ".js");
3559
- return rel.startsWith(".") ? rel : "./" + rel;
3560
- })()
3589
+ propertyName: deriveClientPropertyName(e.ast.file)
3561
3590
  }));
3562
- const areas = [
3591
+ const areaInfos = [];
3592
+ const sortedAreas = [
3563
3593
  ...areaBuckets.entries()
3564
- ].sort(([a], [b]) => a.localeCompare(b)).map(([area, bucket]) => ({
3565
- area,
3566
- inlineFiles: bucket.inlineRoots.map((root) => ({
3594
+ ].sort(([a], [b]) => a.localeCompare(b));
3595
+ for (const [area, bucket] of sortedAreas) {
3596
+ const areaClientOutPath = computeSdkAreaClientOutPath(area, sdkBase, config.output.clients);
3597
+ areaClientOutPaths.set(area, areaClientOutPath);
3598
+ const areaClassName = deriveAreaClientClassName(area);
3599
+ const areaPropertyName = deriveAreaPropertyName(area);
3600
+ sdkClientInfos.push({
3601
+ outPath: areaClientOutPath,
3602
+ className: areaClassName,
3603
+ propertyName: areaPropertyName
3604
+ });
3605
+ const subareaClients = bucket.leaves.sort((a, b) => a.subarea.localeCompare(b.subarea)).map((l) => ({
3606
+ propertyName: deriveSubareaPropertyName(l.subarea),
3607
+ client: toClientImport(dirname6(areaClientOutPath), {
3608
+ outPath: l.outPath,
3609
+ className: deriveSubareaClientClassName(area, l.subarea),
3610
+ propertyName: deriveSubareaPropertyName(l.subarea)
3611
+ })
3612
+ }));
3613
+ const allInlineRefs = /* @__PURE__ */ new Set();
3614
+ for (const r of bucket.inlineRoots) {
3615
+ for (const ref of collectOpRootRefs(r, modelMap)) allInlineRefs.add(ref);
3616
+ }
3617
+ const fingerprint = hashFingerprint({
3618
+ kind: "sdk-area-client",
3619
+ v: TYPESCRIPT_CODEGEN_VERSION,
3620
+ outPath: areaClientOutPath,
3621
+ area,
3622
+ inlineRoots: bucket.inlineRoots,
3623
+ subareaClients,
3624
+ outPathSlice: sliceOutPathMap(allInlineRefs, sdkModelOutPaths, modelsWithInput, modelsWithOutput),
3625
+ modelsWithInput: sliceModelSet(allInlineRefs, /* @__PURE__ */ new Set(), modelsWithInput),
3626
+ modelsWithOutput: sliceModelSet(allInlineRefs, /* @__PURE__ */ new Set(), modelsWithOutput),
3627
+ sdkOptionsPath,
3628
+ includeInternal: config.includeInternal ?? false,
3629
+ sub: subConfigKey
3630
+ });
3631
+ const inlineFilesForGen = bucket.inlineRoots.map((root) => ({
3567
3632
  root,
3568
3633
  codegenOptions: {
3569
3634
  typeImportPathTemplate: void 0,
3570
- outPath: sdkEntryPath,
3635
+ outPath: areaClientOutPath,
3571
3636
  modelOutPaths: sdkModelOutPaths,
3572
3637
  sdkOptionsPath,
3573
3638
  modelsWithInput,
3574
3639
  modelsWithOutput,
3575
3640
  includeInternal: config.includeInternal
3576
3641
  }
3577
- })),
3578
- subareaClients: bucket.leaves.sort((a, b) => a.subarea.localeCompare(b.subarea)).map((l) => ({
3579
- propertyName: deriveSubareaPropertyName(l.subarea),
3580
- client: toClientImport({
3581
- outPath: l.outPath,
3582
- className: deriveSubareaClientClassName(area, l.subarea),
3583
- propertyName: deriveSubareaPropertyName(l.subarea)
3642
+ }));
3643
+ units.push({
3644
+ key: `sdk-area-client::${areaClientOutPath}`,
3645
+ fingerprint,
3646
+ render: /* @__PURE__ */ __name(() => [
3647
+ {
3648
+ relativePath: areaClientOutPath,
3649
+ content: generateAreaClient({
3650
+ area,
3651
+ outPath: areaClientOutPath,
3652
+ inlineFiles: inlineFilesForGen,
3653
+ subareaClients,
3654
+ sdkOptionsPath
3655
+ })
3656
+ }
3657
+ ], "render")
3658
+ });
3659
+ areaInfos.push({
3660
+ area,
3661
+ client: toClientImport(sdkEntryDir, {
3662
+ outPath: areaClientOutPath,
3663
+ className: areaClassName,
3664
+ propertyName: areaPropertyName
3584
3665
  })
3585
- }))
3586
- }));
3666
+ });
3667
+ }
3587
3668
  globalFiles.push({
3588
3669
  relativePath: sdkEntryPath,
3589
3670
  content: generateSdkAggregator({
3590
3671
  topLevelClients,
3591
- areas,
3672
+ areas: areaInfos,
3592
3673
  sdkOptionsImportPath,
3593
3674
  sdkClassName
3594
3675
  })