@sdk-it/typescript 0.26.0 → 0.28.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 +1025 -43
- package/dist/index.js.map +4 -4
- package/dist/lib/emitters/snippet.d.ts +3 -2
- package/dist/lib/emitters/snippet.d.ts.map +1 -1
- package/dist/lib/emitters/zod.d.ts.map +1 -1
- package/dist/lib/generate.d.ts +2 -0
- package/dist/lib/generate.d.ts.map +1 -1
- package/dist/lib/options.d.ts +1 -0
- package/dist/lib/options.d.ts.map +1 -1
- package/dist/lib/readme/prop.emitter.d.ts +17 -0
- package/dist/lib/readme/prop.emitter.d.ts.map +1 -0
- package/dist/lib/readme/readme.d.ts +4 -0
- package/dist/lib/readme/readme.d.ts.map +1 -0
- package/dist/lib/typescript-snippet.d.ts +13 -1
- package/dist/lib/typescript-snippet.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -10,15 +10,18 @@ import {
|
|
|
10
10
|
getFolderExports,
|
|
11
11
|
writeFiles
|
|
12
12
|
} from "@sdk-it/core/file-system.js";
|
|
13
|
-
import { toReadme } from "@sdk-it/readme";
|
|
14
13
|
import {
|
|
15
14
|
augmentSpec,
|
|
16
15
|
cleanFiles,
|
|
16
|
+
forEachOperation as forEachOperation4,
|
|
17
17
|
readWriteMetadata,
|
|
18
18
|
sanitizeTag as sanitizeTag4,
|
|
19
19
|
securityToOptions as securityToOptions2
|
|
20
20
|
} from "@sdk-it/spec";
|
|
21
21
|
|
|
22
|
+
// packages/typescript/src/lib/agent/utils.txt
|
|
23
|
+
var utils_default = "function coerceContext(context?: any) {\n if (!context) {\n throw new Error('Context is required');\n }\n return context as {\n client: any\n };\n}\n/**\n * Takes a Zod object schema and makes all optional properties nullable as well.\n * This is useful for APIs where optional fields can be explicitly set to null.\n *\n * @param schema - The Zod object schema to transform\n * @returns A new Zod schema with optional properties made nullable\n */\nfunction makeOptionalPropsNullable<T extends z.ZodRawShape>(\n schema: z.ZodObject<T>,\n) {\n const shape = schema.shape;\n const newShape = {} as Record<string, z.ZodTypeAny>;\n\n for (const [key, value] of Object.entries(shape)) {\n if (value instanceof z.ZodOptional) {\n // Make optional properties also nullable\n newShape[key] = value._def.innerType.nullable().optional();\n } else {\n // Keep non-optional properties as they are\n newShape[key] = value;\n }\n }\n\n return z.object(newShape);\n}";
|
|
24
|
+
|
|
22
25
|
// packages/typescript/src/lib/client.ts
|
|
23
26
|
import { toLitObject } from "@sdk-it/core";
|
|
24
27
|
|
|
@@ -159,10 +162,10 @@ var ZodEmitter = class {
|
|
|
159
162
|
switch (schema.format) {
|
|
160
163
|
case "date-time":
|
|
161
164
|
case "datetime":
|
|
162
|
-
base = "z.
|
|
165
|
+
base = "z.string().datetime()";
|
|
163
166
|
break;
|
|
164
167
|
case "date":
|
|
165
|
-
base = "z.coerce.date()
|
|
168
|
+
base = "z.coerce.date()";
|
|
166
169
|
break;
|
|
167
170
|
case "time":
|
|
168
171
|
base = "z.string() /* optionally add .regex(...) for HH:MM:SS format */";
|
|
@@ -1594,17 +1597,403 @@ var offset_pagination_default = "type OffsetPaginationParams = {\n offset: numb
|
|
|
1594
1597
|
// packages/typescript/src/lib/paginations/page-pagination.txt
|
|
1595
1598
|
var page_pagination_default = "type InferPage<T> = T extends Page<infer U> ? U : never;\ntype PaginationParams<P extends number | bigint, S extends number | bigint> = {\n page?: P;\n pageSize?: S;\n};\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationResult<T, M extends Metadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<\n T,\n M extends Metadata,\n P extends number | bigint,\n S extends number | bigint,\n> = (input: Partial<PaginationParams<P, S>>) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class Pagination<\n T,\n M extends Metadata,\n P extends number | bigint,\n S extends number | bigint,\n> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: PaginationParams<P, S>;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M, P, S>;\n\n constructor(\n initialParams: Partial<PaginationParams<P, S>>,\n fetchFn: FetchFn<T, M, P, S>,\n ) {\n this.#fetchFn = fetchFn;\n this.#params = { ...initialParams, page: initialParams.page };\n }\n\n async getNextPage() {\n const result = await this.#fetchFn(this.#params);\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n page: ((this.#params.page as number) || 0 + 1) as never,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter() {\n if (!this.#currentPage) {\n yield await this.getNextPage();\n }\n\n while (this.hasMore) {\n yield await this.getNextPage();\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n";
|
|
1596
1599
|
|
|
1600
|
+
// packages/typescript/src/lib/readme/readme.ts
|
|
1601
|
+
import { isEmpty as isEmpty3 } from "@sdk-it/core";
|
|
1602
|
+
import { forEachOperation as forEachOperation2 } from "@sdk-it/spec";
|
|
1603
|
+
|
|
1604
|
+
// packages/typescript/src/lib/readme/prop.emitter.ts
|
|
1605
|
+
import { followRef as followRef4, isRef as isRef4 } from "@sdk-it/core";
|
|
1606
|
+
import { coerceTypes } from "@sdk-it/spec";
|
|
1607
|
+
var PropEmitter = class {
|
|
1608
|
+
#spec;
|
|
1609
|
+
constructor(spec) {
|
|
1610
|
+
this.#spec = spec;
|
|
1611
|
+
}
|
|
1612
|
+
/**
|
|
1613
|
+
* Handle objects (properties)
|
|
1614
|
+
*/
|
|
1615
|
+
#object(schema) {
|
|
1616
|
+
const lines = [];
|
|
1617
|
+
const properties = schema.properties || {};
|
|
1618
|
+
if (Object.keys(properties).length > 0) {
|
|
1619
|
+
lines.push(`**Properties:**`);
|
|
1620
|
+
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
1621
|
+
const isRequired = (schema.required ?? []).includes(propName);
|
|
1622
|
+
lines.push(...this.#property(propName, propSchema, isRequired));
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
if (schema.additionalProperties) {
|
|
1626
|
+
lines.push(`**Additional Properties:**`);
|
|
1627
|
+
if (typeof schema.additionalProperties === "boolean") {
|
|
1628
|
+
lines.push(`- Allowed: ${schema.additionalProperties}`);
|
|
1629
|
+
} else {
|
|
1630
|
+
lines.push(
|
|
1631
|
+
...this.handle(schema.additionalProperties).map((l) => ` ${l}`)
|
|
1632
|
+
);
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
return lines;
|
|
1636
|
+
}
|
|
1637
|
+
/**
|
|
1638
|
+
* Format a property with its type and description
|
|
1639
|
+
*/
|
|
1640
|
+
#property(name, schema, required) {
|
|
1641
|
+
const docs = this.handle(schema);
|
|
1642
|
+
const rawType = docs[0].replace("**Type:** ", "").replace(" (nullable)", "|null");
|
|
1643
|
+
const defaultVal = !isRef4(schema) && schema.default !== void 0 ? ` default: ${JSON.stringify(schema.default)}` : "";
|
|
1644
|
+
const reqMark = required ? " required" : "";
|
|
1645
|
+
const summary = `- \`${name}\` ${rawType}${reqMark}${defaultVal}:`;
|
|
1646
|
+
const detailLines = docs.slice(1).filter((it) => !it.startsWith("**Default:**")).map((it) => ` ${it}`);
|
|
1647
|
+
return [summary, ...detailLines];
|
|
1648
|
+
}
|
|
1649
|
+
/**
|
|
1650
|
+
* Handle array schemas
|
|
1651
|
+
*/
|
|
1652
|
+
#array(schema) {
|
|
1653
|
+
const lines = [];
|
|
1654
|
+
lines.push(`**Array items:**`);
|
|
1655
|
+
if (schema.items) {
|
|
1656
|
+
const itemDocs = this.handle(schema.items);
|
|
1657
|
+
lines.push(...itemDocs.map((line) => ` ${line}`));
|
|
1658
|
+
} else {
|
|
1659
|
+
lines.push(` **Type:** \`unknown\``);
|
|
1660
|
+
}
|
|
1661
|
+
if (schema.minItems !== void 0)
|
|
1662
|
+
lines.push(`- Minimum items: ${schema.minItems}`);
|
|
1663
|
+
if (schema.maxItems !== void 0)
|
|
1664
|
+
lines.push(`- Maximum items: ${schema.maxItems}`);
|
|
1665
|
+
if (schema.uniqueItems) lines.push(`- Items must be unique.`);
|
|
1666
|
+
return lines;
|
|
1667
|
+
}
|
|
1668
|
+
#ref($ref) {
|
|
1669
|
+
const schemaName = $ref.split("/").pop() || "object";
|
|
1670
|
+
const resolved = followRef4(this.#spec, $ref);
|
|
1671
|
+
const lines = [
|
|
1672
|
+
`**Type:** [\`${schemaName}\`](#${schemaName.toLowerCase()})`
|
|
1673
|
+
];
|
|
1674
|
+
if (resolved.description) {
|
|
1675
|
+
lines.push(resolved.description);
|
|
1676
|
+
}
|
|
1677
|
+
return lines;
|
|
1678
|
+
}
|
|
1679
|
+
#allOf(schemas) {
|
|
1680
|
+
const lines = ["**All of (Intersection):**"];
|
|
1681
|
+
schemas.forEach((subSchema, index) => {
|
|
1682
|
+
lines.push(`- **Constraint ${index + 1}:**`);
|
|
1683
|
+
const subLines = this.handle(subSchema);
|
|
1684
|
+
lines.push(...subLines.map((l) => ` ${l}`));
|
|
1685
|
+
});
|
|
1686
|
+
return lines;
|
|
1687
|
+
}
|
|
1688
|
+
#anyOf(schemas) {
|
|
1689
|
+
const lines = ["**Any of (Union):**"];
|
|
1690
|
+
schemas.forEach((subSchema, index) => {
|
|
1691
|
+
lines.push(`- **Option ${index + 1}:**`);
|
|
1692
|
+
const subLines = this.handle(subSchema);
|
|
1693
|
+
lines.push(...subLines.map((l) => ` ${l}`));
|
|
1694
|
+
});
|
|
1695
|
+
return lines;
|
|
1696
|
+
}
|
|
1697
|
+
#oneOf(schemas) {
|
|
1698
|
+
const lines = ["**One of (Exclusive Union):**"];
|
|
1699
|
+
schemas.forEach((subSchema, index) => {
|
|
1700
|
+
lines.push(`- **Option ${index + 1}:**`);
|
|
1701
|
+
const subLines = this.handle(subSchema);
|
|
1702
|
+
lines.push(...subLines.map((l) => ` ${l}`));
|
|
1703
|
+
});
|
|
1704
|
+
return lines;
|
|
1705
|
+
}
|
|
1706
|
+
#enum(schema) {
|
|
1707
|
+
const lines = [`**Type:** \`${schema.type || "unknown"}\` (enum)`];
|
|
1708
|
+
if (schema.description) lines.push(schema.description);
|
|
1709
|
+
lines.push("**Allowed values:**");
|
|
1710
|
+
lines.push(
|
|
1711
|
+
...(schema.enum || []).map((val) => `- \`${JSON.stringify(val)}\``)
|
|
1712
|
+
);
|
|
1713
|
+
if (schema.default !== void 0) {
|
|
1714
|
+
lines.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
1715
|
+
}
|
|
1716
|
+
return lines;
|
|
1717
|
+
}
|
|
1718
|
+
#normal(type, schema, nullable) {
|
|
1719
|
+
const lines = [];
|
|
1720
|
+
const nullableSuffix = nullable ? " (nullable)" : "";
|
|
1721
|
+
const description = schema.description ? [schema.description] : [];
|
|
1722
|
+
switch (type) {
|
|
1723
|
+
case "string":
|
|
1724
|
+
lines.push(
|
|
1725
|
+
`**Type:** \`string\`${schema.format ? ` (format: ${schema.format})` : ""}${nullableSuffix}`
|
|
1726
|
+
);
|
|
1727
|
+
lines.push(...description);
|
|
1728
|
+
if (schema.minLength !== void 0)
|
|
1729
|
+
lines.push(`- Minimum length: ${schema.minLength}`);
|
|
1730
|
+
if (schema.maxLength !== void 0)
|
|
1731
|
+
lines.push(`- Maximum length: ${schema.maxLength}`);
|
|
1732
|
+
if (schema.pattern !== void 0)
|
|
1733
|
+
lines.push(`- Pattern: \`${schema.pattern}\``);
|
|
1734
|
+
break;
|
|
1735
|
+
case "number":
|
|
1736
|
+
case "integer":
|
|
1737
|
+
lines.push(
|
|
1738
|
+
`**Type:** \`${type}\`${schema.format ? ` (format: ${schema.format})` : ""}${nullableSuffix}`
|
|
1739
|
+
);
|
|
1740
|
+
lines.push(...description);
|
|
1741
|
+
if (schema.minimum !== void 0) {
|
|
1742
|
+
const exclusiveMin = typeof schema.exclusiveMinimum === "number";
|
|
1743
|
+
lines.push(
|
|
1744
|
+
`- Minimum: ${schema.minimum}${exclusiveMin ? " (exclusive)" : ""}`
|
|
1745
|
+
);
|
|
1746
|
+
if (exclusiveMin) {
|
|
1747
|
+
lines.push(
|
|
1748
|
+
`- Must be strictly greater than: ${schema.exclusiveMinimum}`
|
|
1749
|
+
);
|
|
1750
|
+
}
|
|
1751
|
+
} else if (typeof schema.exclusiveMinimum === "number") {
|
|
1752
|
+
lines.push(
|
|
1753
|
+
`- Must be strictly greater than: ${schema.exclusiveMinimum}`
|
|
1754
|
+
);
|
|
1755
|
+
}
|
|
1756
|
+
if (schema.maximum !== void 0) {
|
|
1757
|
+
const exclusiveMax = typeof schema.exclusiveMaximum === "number";
|
|
1758
|
+
lines.push(
|
|
1759
|
+
`- Maximum: ${schema.maximum}${exclusiveMax ? " (exclusive)" : ""}`
|
|
1760
|
+
);
|
|
1761
|
+
if (exclusiveMax) {
|
|
1762
|
+
lines.push(
|
|
1763
|
+
`- Must be strictly less than: ${schema.exclusiveMaximum}`
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
} else if (typeof schema.exclusiveMaximum === "number") {
|
|
1767
|
+
lines.push(
|
|
1768
|
+
`- Must be strictly less than: ${schema.exclusiveMaximum}`
|
|
1769
|
+
);
|
|
1770
|
+
}
|
|
1771
|
+
if (schema.multipleOf !== void 0)
|
|
1772
|
+
lines.push(`- Must be a multiple of: ${schema.multipleOf}`);
|
|
1773
|
+
break;
|
|
1774
|
+
case "boolean":
|
|
1775
|
+
lines.push(`**Type:** \`boolean\`${nullableSuffix}`);
|
|
1776
|
+
lines.push(...description);
|
|
1777
|
+
break;
|
|
1778
|
+
case "object":
|
|
1779
|
+
lines.push(`**Type:** \`object\`${nullableSuffix}`);
|
|
1780
|
+
lines.push(...description);
|
|
1781
|
+
lines.push(...this.#object(schema));
|
|
1782
|
+
break;
|
|
1783
|
+
case "array":
|
|
1784
|
+
lines.push(`**Type:** \`array\`${nullableSuffix}`);
|
|
1785
|
+
lines.push(...description);
|
|
1786
|
+
lines.push(...this.#array(schema));
|
|
1787
|
+
break;
|
|
1788
|
+
case "null":
|
|
1789
|
+
lines.push(`**Type:** \`null\``);
|
|
1790
|
+
lines.push(...description);
|
|
1791
|
+
break;
|
|
1792
|
+
default:
|
|
1793
|
+
lines.push(`**Type:** \`${type}\`${nullableSuffix}`);
|
|
1794
|
+
lines.push(...description);
|
|
1795
|
+
}
|
|
1796
|
+
if (schema.default !== void 0) {
|
|
1797
|
+
lines.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
1798
|
+
}
|
|
1799
|
+
return lines.filter((l) => l);
|
|
1800
|
+
}
|
|
1801
|
+
/**
|
|
1802
|
+
* Handle schemas by resolving references and delegating to appropriate handler
|
|
1803
|
+
*/
|
|
1804
|
+
handle(schemaOrRef) {
|
|
1805
|
+
if (isRef4(schemaOrRef)) {
|
|
1806
|
+
return this.#ref(schemaOrRef.$ref);
|
|
1807
|
+
}
|
|
1808
|
+
const schema = schemaOrRef;
|
|
1809
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
1810
|
+
return this.#allOf(schema.allOf);
|
|
1811
|
+
}
|
|
1812
|
+
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
|
1813
|
+
return this.#anyOf(schema.anyOf);
|
|
1814
|
+
}
|
|
1815
|
+
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
1816
|
+
return this.#oneOf(schema.oneOf);
|
|
1817
|
+
}
|
|
1818
|
+
if (schema.enum && Array.isArray(schema.enum)) {
|
|
1819
|
+
return this.#enum(schema);
|
|
1820
|
+
}
|
|
1821
|
+
let types = coerceTypes(schema);
|
|
1822
|
+
let nullable = false;
|
|
1823
|
+
if (types.includes("null")) {
|
|
1824
|
+
nullable = true;
|
|
1825
|
+
types = types.filter((t) => t !== "null");
|
|
1826
|
+
}
|
|
1827
|
+
if (types.length === 0) {
|
|
1828
|
+
if (schema.properties || schema.additionalProperties) {
|
|
1829
|
+
types = ["object"];
|
|
1830
|
+
} else if (schema.items) {
|
|
1831
|
+
types = ["array"];
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
if (types.length === 0) {
|
|
1835
|
+
const lines2 = ["**Type:** `unknown`"];
|
|
1836
|
+
if (schema.description) lines2.push(schema.description);
|
|
1837
|
+
if (schema.default !== void 0)
|
|
1838
|
+
lines2.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
1839
|
+
return lines2;
|
|
1840
|
+
}
|
|
1841
|
+
if (types.length === 1) {
|
|
1842
|
+
return this.#normal(types[0], schema, nullable);
|
|
1843
|
+
}
|
|
1844
|
+
const typeString = types.join(" | ");
|
|
1845
|
+
const nullableSuffix = nullable ? " (nullable)" : "";
|
|
1846
|
+
const lines = [`**Type:** \`${typeString}\`${nullableSuffix}`];
|
|
1847
|
+
if (schema.description) lines.push(schema.description);
|
|
1848
|
+
if (schema.default !== void 0)
|
|
1849
|
+
lines.push(`**Default:** \`${JSON.stringify(schema.default)}\``);
|
|
1850
|
+
return lines;
|
|
1851
|
+
}
|
|
1852
|
+
/**
|
|
1853
|
+
* Process a request body and return markdown documentation
|
|
1854
|
+
*/
|
|
1855
|
+
requestBody(requestBody) {
|
|
1856
|
+
const lines = [];
|
|
1857
|
+
lines.push(`#### Input`);
|
|
1858
|
+
lines.push(requestBody.description || "");
|
|
1859
|
+
const contentEntries = Object.entries(requestBody.content);
|
|
1860
|
+
const multipleContentTypes = contentEntries.length > 1;
|
|
1861
|
+
if (multipleContentTypes) {
|
|
1862
|
+
for (const [contentType, mediaType] of contentEntries) {
|
|
1863
|
+
lines.push(`<details>`);
|
|
1864
|
+
lines.push(`<summary>Content Type: \`${contentType}\`</summary>`);
|
|
1865
|
+
lines.push("");
|
|
1866
|
+
if (mediaType.schema) {
|
|
1867
|
+
const schemaDocs = this.handle(mediaType.schema);
|
|
1868
|
+
lines.push(...schemaDocs.map((l) => l));
|
|
1869
|
+
}
|
|
1870
|
+
lines.push("");
|
|
1871
|
+
lines.push(`</details>`);
|
|
1872
|
+
}
|
|
1873
|
+
} else {
|
|
1874
|
+
const [contentType, mediaType] = contentEntries[0];
|
|
1875
|
+
lines.push(`Content Type: \`${contentType}\``);
|
|
1876
|
+
if (mediaType.schema) {
|
|
1877
|
+
const schemaDocs = this.handle(mediaType.schema);
|
|
1878
|
+
lines.push(...schemaDocs);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
return lines;
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
|
|
1885
|
+
// packages/typescript/src/lib/readme/readme.ts
|
|
1886
|
+
function toReadme(spec, generator) {
|
|
1887
|
+
const propEmitter = new PropEmitter(spec);
|
|
1888
|
+
const markdown = [];
|
|
1889
|
+
markdown.push(`# ${spec.info.title} TypeScript SDK`);
|
|
1890
|
+
markdown.push("");
|
|
1891
|
+
markdown.push(
|
|
1892
|
+
"A fully-typed TypeScript SDK with comprehensive IntelliSense support, automatic request/response validation, and modern async/await patterns. Built for seamless integration with TypeScript and JavaScript projects."
|
|
1893
|
+
);
|
|
1894
|
+
markdown.push("");
|
|
1895
|
+
markdown.push(generator.clientSetupDocs());
|
|
1896
|
+
markdown.push("");
|
|
1897
|
+
const securitySchemes = spec.components?.securitySchemes || {};
|
|
1898
|
+
if (Object.keys(securitySchemes).length > 0) {
|
|
1899
|
+
markdown.push(generator.authenticationDocs());
|
|
1900
|
+
markdown.push("");
|
|
1901
|
+
}
|
|
1902
|
+
const paginationDocs = generator.paginationDocs();
|
|
1903
|
+
if (paginationDocs) {
|
|
1904
|
+
markdown.push(paginationDocs);
|
|
1905
|
+
markdown.push("");
|
|
1906
|
+
}
|
|
1907
|
+
markdown.push(generator.errorHandlingDocs());
|
|
1908
|
+
markdown.push("");
|
|
1909
|
+
markdown.push(generator.generalUsageDocs());
|
|
1910
|
+
markdown.push("");
|
|
1911
|
+
markdown.push("## API Reference");
|
|
1912
|
+
markdown.push("");
|
|
1913
|
+
forEachOperation2(spec, (entry, operation) => {
|
|
1914
|
+
const { method, path } = entry;
|
|
1915
|
+
markdown.push(
|
|
1916
|
+
`### ${operation["x-fn-name"]} | ${`_${method.toUpperCase()} ${path}_`}`
|
|
1917
|
+
);
|
|
1918
|
+
markdown.push(operation.summary || "");
|
|
1919
|
+
const snippet = generator.snippet(entry, operation);
|
|
1920
|
+
markdown.push(`#### Example usage`);
|
|
1921
|
+
markdown.push(snippet);
|
|
1922
|
+
const requestBodyContent = propEmitter.requestBody(operation.requestBody);
|
|
1923
|
+
if (requestBodyContent.length > 1) {
|
|
1924
|
+
markdown.push(requestBodyContent.join("\n\n"));
|
|
1925
|
+
}
|
|
1926
|
+
markdown.push(`#### Output`);
|
|
1927
|
+
for (const status in operation.responses) {
|
|
1928
|
+
const response = operation.responses[status];
|
|
1929
|
+
if (!isEmpty3(response.content)) {
|
|
1930
|
+
const contentEntries = Object.entries(response.content);
|
|
1931
|
+
if (contentEntries.length === 1) {
|
|
1932
|
+
const [contentType, mediaType] = contentEntries[0];
|
|
1933
|
+
markdown.push(`**${status}** - ${response.description}`);
|
|
1934
|
+
markdown.push(`
|
|
1935
|
+
**Content Type:** \`${contentType}\``);
|
|
1936
|
+
if (mediaType.schema) {
|
|
1937
|
+
const schemaDocs = propEmitter.handle(mediaType.schema);
|
|
1938
|
+
markdown.push(...schemaDocs);
|
|
1939
|
+
}
|
|
1940
|
+
} else {
|
|
1941
|
+
markdown.push(`<details>`);
|
|
1942
|
+
markdown.push(
|
|
1943
|
+
`<summary><b>${status}</b> <i>${response.description}</i></summary>`
|
|
1944
|
+
);
|
|
1945
|
+
for (const [contentType, mediaType] of contentEntries) {
|
|
1946
|
+
markdown.push(`
|
|
1947
|
+
**Content Type:** \`${contentType}\``);
|
|
1948
|
+
if (mediaType.schema) {
|
|
1949
|
+
const schemaDocs = propEmitter.handle(mediaType.schema);
|
|
1950
|
+
markdown.push(...schemaDocs.map((l) => `
|
|
1951
|
+
${l}`));
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
markdown.push(`</details>`);
|
|
1955
|
+
}
|
|
1956
|
+
} else {
|
|
1957
|
+
markdown.push(`**${status}** - ${response.description}`);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
});
|
|
1961
|
+
if (spec.components?.schemas) {
|
|
1962
|
+
markdown.push("## Schemas");
|
|
1963
|
+
markdown.push("");
|
|
1964
|
+
for (const [schemaName, schema] of Object.entries(
|
|
1965
|
+
spec.components.schemas
|
|
1966
|
+
)) {
|
|
1967
|
+
if (schemaName === "ValidationError") {
|
|
1968
|
+
continue;
|
|
1969
|
+
}
|
|
1970
|
+
markdown.push(`<details>`);
|
|
1971
|
+
markdown.push(
|
|
1972
|
+
`<summary><h3 id="${schemaName.toLowerCase()}">${schemaName}</h3></summary>`
|
|
1973
|
+
);
|
|
1974
|
+
markdown.push("");
|
|
1975
|
+
const schemaDocs = propEmitter.handle(schema);
|
|
1976
|
+
markdown.push(...schemaDocs.map((line) => line.trim()));
|
|
1977
|
+
markdown.push("");
|
|
1978
|
+
markdown.push(`</details>`);
|
|
1979
|
+
markdown.push("");
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
return markdown.join("\n\n");
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1597
1985
|
// packages/typescript/src/lib/typescript-snippet.ts
|
|
1598
1986
|
import { camelcase as camelcase3, spinalcase as spinalcase2 } from "stringcase";
|
|
1599
|
-
import { isEmpty as
|
|
1987
|
+
import { isEmpty as isEmpty4, pascalcase as pascalcase4, resolveRef as resolveRef3 } from "@sdk-it/core";
|
|
1600
1988
|
import "@sdk-it/readme";
|
|
1601
1989
|
import {
|
|
1990
|
+
forEachOperation as forEachOperation3,
|
|
1602
1991
|
patchParameters,
|
|
1603
1992
|
securityToOptions
|
|
1604
1993
|
} from "@sdk-it/spec";
|
|
1605
1994
|
|
|
1606
1995
|
// packages/typescript/src/lib/emitters/snippet.ts
|
|
1607
|
-
import { followRef as
|
|
1996
|
+
import { followRef as followRef5, isRef as isRef5, resolveRef as resolveRef2 } from "@sdk-it/core";
|
|
1608
1997
|
var SnippetEmitter = class {
|
|
1609
1998
|
spec;
|
|
1610
1999
|
generatedRefs = /* @__PURE__ */ new Set();
|
|
@@ -1613,12 +2002,12 @@ var SnippetEmitter = class {
|
|
|
1613
2002
|
this.spec = spec;
|
|
1614
2003
|
}
|
|
1615
2004
|
object(schema) {
|
|
1616
|
-
const schemaObj =
|
|
2005
|
+
const schemaObj = resolveRef2(this.spec, schema);
|
|
1617
2006
|
const result = {};
|
|
1618
2007
|
const properties = schemaObj.properties || {};
|
|
1619
2008
|
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
1620
2009
|
const isRequired = (schemaObj.required ?? []).includes(propName);
|
|
1621
|
-
const resolvedProp =
|
|
2010
|
+
const resolvedProp = resolveRef2(this.spec, propSchema);
|
|
1622
2011
|
if (isRequired || resolvedProp.example !== void 0 || resolvedProp.default !== void 0 || Math.random() > 0.5) {
|
|
1623
2012
|
result[propName] = this.handle(propSchema);
|
|
1624
2013
|
}
|
|
@@ -1631,7 +2020,7 @@ var SnippetEmitter = class {
|
|
|
1631
2020
|
return result;
|
|
1632
2021
|
}
|
|
1633
2022
|
array(schema) {
|
|
1634
|
-
const schemaObj =
|
|
2023
|
+
const schemaObj = resolveRef2(this.spec, schema);
|
|
1635
2024
|
const itemsSchema = schemaObj.items;
|
|
1636
2025
|
if (!itemsSchema) {
|
|
1637
2026
|
return [];
|
|
@@ -1713,7 +2102,7 @@ var SnippetEmitter = class {
|
|
|
1713
2102
|
return this.cache.get($ref);
|
|
1714
2103
|
}
|
|
1715
2104
|
this.cache.set($ref, { _ref: refKey });
|
|
1716
|
-
const resolved =
|
|
2105
|
+
const resolved = followRef5(this.spec, $ref);
|
|
1717
2106
|
const result = this.handle(resolved);
|
|
1718
2107
|
this.cache.set($ref, result);
|
|
1719
2108
|
return result;
|
|
@@ -1740,10 +2129,10 @@ var SnippetEmitter = class {
|
|
|
1740
2129
|
return Array.isArray(schema.enum) && schema.enum.length > 0 ? schema.enum[0] : void 0;
|
|
1741
2130
|
}
|
|
1742
2131
|
handle(schemaOrRef) {
|
|
1743
|
-
if (
|
|
2132
|
+
if (isRef5(schemaOrRef)) {
|
|
1744
2133
|
return this.ref(schemaOrRef.$ref);
|
|
1745
2134
|
}
|
|
1746
|
-
const schema =
|
|
2135
|
+
const schema = resolveRef2(this.spec, schemaOrRef);
|
|
1747
2136
|
if (schema.example !== void 0) {
|
|
1748
2137
|
return schema.example;
|
|
1749
2138
|
}
|
|
@@ -1808,9 +2197,9 @@ var TypeScriptGenerator = class {
|
|
|
1808
2197
|
}
|
|
1809
2198
|
succinct(entry, operation, values) {
|
|
1810
2199
|
let payload = "{}";
|
|
1811
|
-
if (!
|
|
2200
|
+
if (!isEmpty4(operation.requestBody)) {
|
|
1812
2201
|
const contentTypes = Object.keys(operation.requestBody.content || {});
|
|
1813
|
-
const schema =
|
|
2202
|
+
const schema = resolveRef3(
|
|
1814
2203
|
this.#spec,
|
|
1815
2204
|
operation.requestBody.content[contentTypes[0]].schema
|
|
1816
2205
|
);
|
|
@@ -1870,31 +2259,31 @@ var TypeScriptGenerator = class {
|
|
|
1870
2259
|
return this.#streamDownload(entry, payload);
|
|
1871
2260
|
}
|
|
1872
2261
|
}
|
|
1873
|
-
if (!
|
|
2262
|
+
if (!isEmpty4(operation["x-pagination"])) {
|
|
1874
2263
|
return this.#pagination(operation, entry, payload);
|
|
1875
2264
|
}
|
|
1876
2265
|
return this.#normal(entry, payload);
|
|
1877
2266
|
}
|
|
1878
|
-
#pagination(
|
|
1879
|
-
const pagination =
|
|
2267
|
+
#pagination(operation, entry, payload) {
|
|
2268
|
+
const pagination = operation["x-pagination"];
|
|
1880
2269
|
switch (pagination.type) {
|
|
1881
2270
|
case "page":
|
|
1882
2271
|
return {
|
|
1883
|
-
content: `const result = ${this.#
|
|
2272
|
+
content: `const result = ${this.#toRequest(entry, payload)}`,
|
|
1884
2273
|
footer: `for await (const page of result) {
|
|
1885
2274
|
console.log(page);
|
|
1886
2275
|
}`
|
|
1887
2276
|
};
|
|
1888
2277
|
case "offset":
|
|
1889
2278
|
return {
|
|
1890
|
-
content: `const result = ${this.#
|
|
2279
|
+
content: `const result = ${this.#toRequest(entry, payload)}`,
|
|
1891
2280
|
footer: `for await (const page of result) {
|
|
1892
2281
|
console.log(page);
|
|
1893
2282
|
}`
|
|
1894
2283
|
};
|
|
1895
2284
|
case "cursor":
|
|
1896
2285
|
return {
|
|
1897
|
-
content: `const result = ${this.#
|
|
2286
|
+
content: `const result = ${this.#toRequest(entry, payload)}`,
|
|
1898
2287
|
footer: `for await (const page of result) {
|
|
1899
2288
|
console.log(page);
|
|
1900
2289
|
}`
|
|
@@ -1904,25 +2293,25 @@ var TypeScriptGenerator = class {
|
|
|
1904
2293
|
}
|
|
1905
2294
|
#normal(entry, payload) {
|
|
1906
2295
|
return {
|
|
1907
|
-
content: `const result = ${this.#
|
|
2296
|
+
content: `const result = ${this.#toRequest(entry, payload)};`,
|
|
1908
2297
|
footer: "console.log(result.data)"
|
|
1909
2298
|
};
|
|
1910
2299
|
}
|
|
1911
2300
|
#streamDownload(entry, payload) {
|
|
1912
2301
|
return {
|
|
1913
|
-
content: `const stream = ${this.#
|
|
2302
|
+
content: `const stream = ${this.#toRequest(entry, payload)}`,
|
|
1914
2303
|
footer: `await writeFile('./report.pdf', stream);`
|
|
1915
2304
|
};
|
|
1916
2305
|
}
|
|
1917
2306
|
#httpStreaming(entry, payload) {
|
|
1918
2307
|
return {
|
|
1919
|
-
content: `const stream = ${this.#
|
|
2308
|
+
content: `const stream = ${this.#toRequest(entry, payload)}`,
|
|
1920
2309
|
footer: `for await (const chunk of stream) {
|
|
1921
2310
|
console.log(chunk);
|
|
1922
2311
|
}`
|
|
1923
2312
|
};
|
|
1924
2313
|
}
|
|
1925
|
-
#
|
|
2314
|
+
#toRequest(entry, payload) {
|
|
1926
2315
|
return `await ${camelcase3(this.#clientName)}.request('${entry.method.toUpperCase()} ${entry.path}', ${payload});`;
|
|
1927
2316
|
}
|
|
1928
2317
|
snippet(entry, operation, config = {}) {
|
|
@@ -1935,8 +2324,7 @@ var TypeScriptGenerator = class {
|
|
|
1935
2324
|
payload.footer
|
|
1936
2325
|
];
|
|
1937
2326
|
if (config.frame !== false) {
|
|
1938
|
-
|
|
1939
|
-
content.push("```");
|
|
2327
|
+
return createCodeBlock("typescript", content);
|
|
1940
2328
|
}
|
|
1941
2329
|
return content.join("\n");
|
|
1942
2330
|
}
|
|
@@ -1948,26 +2336,578 @@ var TypeScriptGenerator = class {
|
|
|
1948
2336
|
);
|
|
1949
2337
|
}
|
|
1950
2338
|
client() {
|
|
1951
|
-
const
|
|
1952
|
-
|
|
1953
|
-
|
|
2339
|
+
const options = {
|
|
2340
|
+
baseUrl: this.#spec.servers?.[0]?.url ?? "http://localhost:3000"
|
|
2341
|
+
};
|
|
1954
2342
|
const authOptions = this.#authentication();
|
|
1955
|
-
if (!
|
|
2343
|
+
if (!isEmpty4(authOptions)) {
|
|
1956
2344
|
const [firstAuth] = authOptions;
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
);
|
|
2345
|
+
const optionName = firstAuth["x-optionName"] ?? firstAuth.name;
|
|
2346
|
+
options[optionName] = firstAuth.example;
|
|
1960
2347
|
}
|
|
1961
|
-
|
|
2348
|
+
const client = this.#constructClient(options);
|
|
2349
|
+
return `${client.import}
|
|
1962
2350
|
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
})
|
|
2351
|
+
${client.use}`;
|
|
2352
|
+
}
|
|
2353
|
+
#constructClient(options = {}) {
|
|
2354
|
+
return {
|
|
2355
|
+
import: `import { ${this.#clientName} } from '${this.#packageName}';`,
|
|
2356
|
+
use: `const ${camelcase3(this.#clientName)} = new ${this.#clientName}({
|
|
2357
|
+
${Object.entries(
|
|
2358
|
+
options
|
|
2359
|
+
).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(",\n ")}
|
|
2360
|
+
});`
|
|
2361
|
+
};
|
|
2362
|
+
}
|
|
2363
|
+
clientInstallDocs() {
|
|
2364
|
+
const sections = [];
|
|
2365
|
+
sections.push("## Installation");
|
|
2366
|
+
sections.push("");
|
|
2367
|
+
sections.push(
|
|
2368
|
+
createCodeBlock("bash", [`npm install ${this.#packageName}`])
|
|
2369
|
+
);
|
|
2370
|
+
sections.push("");
|
|
2371
|
+
sections.push("## Basic Usage");
|
|
2372
|
+
sections.push("");
|
|
2373
|
+
sections.push(createCodeBlock("typescript", [this.client()]));
|
|
2374
|
+
return sections.join("\n");
|
|
2375
|
+
}
|
|
2376
|
+
configurationOptions() {
|
|
2377
|
+
const sections = [];
|
|
2378
|
+
const hasServers = Boolean(
|
|
2379
|
+
this.#spec.servers && this.#spec.servers.length > 0
|
|
2380
|
+
);
|
|
2381
|
+
const baseUrl = this.#spec.servers?.[0]?.url || "https://api.example.com";
|
|
2382
|
+
const authOptions = this.#authentication();
|
|
2383
|
+
const hasApiKey = !isEmpty4(authOptions);
|
|
2384
|
+
sections.push("### Configuration Options");
|
|
2385
|
+
sections.push("");
|
|
2386
|
+
sections.push("| Option | Type | Required | Description |");
|
|
2387
|
+
sections.push("|--------|------|----------|-------------|");
|
|
2388
|
+
sections.push(
|
|
2389
|
+
"| `fetch` | `fetch compatible` | No | Fetch implementation to use for HTTP requests |"
|
|
2390
|
+
);
|
|
2391
|
+
if (hasServers) {
|
|
2392
|
+
sections.push(
|
|
2393
|
+
"| `baseUrl` | `string` | No | API base URL (default: `" + baseUrl + "`) |"
|
|
2394
|
+
);
|
|
2395
|
+
}
|
|
2396
|
+
for (const authOption of authOptions) {
|
|
2397
|
+
const optionName = authOption["x-optionName"] ?? authOption.name;
|
|
2398
|
+
const description = authOption.in === "header" && authOption.name === "authorization" ? "Bearer token for authentication" : `API key for authentication (${authOption.in}: ${authOption.name})`;
|
|
2399
|
+
sections.push(`| \`${optionName}\` | \`string\` | No | ${description} |`);
|
|
2400
|
+
}
|
|
2401
|
+
return { sections, hasServers, baseUrl, hasApiKey };
|
|
2402
|
+
}
|
|
2403
|
+
clientSetupDocs() {
|
|
2404
|
+
const sections = [];
|
|
2405
|
+
sections.push(this.clientInstallDocs());
|
|
2406
|
+
sections.push("");
|
|
2407
|
+
const config = this.configurationOptions();
|
|
2408
|
+
sections.push(...config.sections);
|
|
2409
|
+
sections.push("");
|
|
2410
|
+
sections.push(this.configurationUpdateDocs());
|
|
2411
|
+
return sections.join("\n");
|
|
2412
|
+
}
|
|
2413
|
+
paginationDocs() {
|
|
2414
|
+
const paginationTypes = availablePaginationTypes(this.#spec);
|
|
2415
|
+
if (!paginationTypes.offset && !paginationTypes.page && !paginationTypes.cursor) {
|
|
2416
|
+
return "";
|
|
2417
|
+
}
|
|
2418
|
+
const sections = [];
|
|
2419
|
+
sections.push("## Pagination");
|
|
2420
|
+
sections.push("");
|
|
2421
|
+
sections.push(
|
|
2422
|
+
"This SDK automatically handles pagination for endpoints that return multiple items."
|
|
2423
|
+
);
|
|
2424
|
+
sections.push("");
|
|
2425
|
+
sections.push("### How it Works");
|
|
2426
|
+
sections.push("");
|
|
2427
|
+
sections.push(
|
|
2428
|
+
"When you call a paginated endpoint, the SDK returns a pagination object that allows you to iterate through all results:"
|
|
2429
|
+
);
|
|
2430
|
+
sections.push("");
|
|
2431
|
+
const availableTypes = [];
|
|
2432
|
+
if (paginationTypes.offset) availableTypes.push("offset");
|
|
2433
|
+
if (paginationTypes.page) availableTypes.push("page");
|
|
2434
|
+
if (paginationTypes.cursor) availableTypes.push("cursor");
|
|
2435
|
+
const primaryPaginationType = availableTypes[0];
|
|
2436
|
+
const mockPaginatedOperation = {
|
|
2437
|
+
"x-pagination": { type: primaryPaginationType },
|
|
2438
|
+
tags: ["Products"],
|
|
2439
|
+
operationId: "listProducts",
|
|
2440
|
+
parameters: [],
|
|
2441
|
+
"x-fn-name": "listProducts",
|
|
2442
|
+
responses: {},
|
|
2443
|
+
requestBody: {}
|
|
2444
|
+
};
|
|
2445
|
+
const mockOperationEntry = {
|
|
2446
|
+
method: "get",
|
|
2447
|
+
path: "/products",
|
|
2448
|
+
tag: "Products"
|
|
2449
|
+
};
|
|
2450
|
+
const initialRequestPayload = createObjectLiteral({ limit: 20 });
|
|
2451
|
+
const paginationExample = this.#pagination(
|
|
2452
|
+
mockPaginatedOperation,
|
|
2453
|
+
mockOperationEntry,
|
|
2454
|
+
initialRequestPayload
|
|
2455
|
+
);
|
|
2456
|
+
sections.push(
|
|
2457
|
+
createCodeBlock("typescript", [
|
|
2458
|
+
"// The SDK automatically handles pagination",
|
|
2459
|
+
paginationExample.content,
|
|
2460
|
+
"",
|
|
2461
|
+
"// Access the current page data",
|
|
2462
|
+
"const currentPage = result.getCurrentPage();",
|
|
2463
|
+
"console.log(currentPage.data); // Array of product items",
|
|
2464
|
+
"",
|
|
2465
|
+
"// Check if more pages exist",
|
|
2466
|
+
"if (result.hasMore) {",
|
|
2467
|
+
" await result.getNextPage();",
|
|
2468
|
+
"}",
|
|
2469
|
+
"",
|
|
2470
|
+
"// Or iterate through all pages automatically",
|
|
2471
|
+
paginationExample.footer
|
|
2472
|
+
])
|
|
2473
|
+
);
|
|
2474
|
+
sections.push("");
|
|
2475
|
+
sections.push("### Iterating Through All Pages");
|
|
2476
|
+
sections.push("");
|
|
2477
|
+
const iterationExample = this.#pagination(
|
|
2478
|
+
mockPaginatedOperation,
|
|
2479
|
+
mockOperationEntry,
|
|
2480
|
+
createObjectLiteral({ limit: 100 })
|
|
2481
|
+
);
|
|
2482
|
+
sections.push(
|
|
2483
|
+
createCodeBlock("typescript", [
|
|
2484
|
+
"// Using async iteration to process all pages",
|
|
2485
|
+
iterationExample.content,
|
|
2486
|
+
"",
|
|
2487
|
+
iterationExample.footer
|
|
2488
|
+
])
|
|
2489
|
+
);
|
|
2490
|
+
sections.push("");
|
|
2491
|
+
if (availableTypes.length > 1) {
|
|
2492
|
+
sections.push("### Pagination Types");
|
|
2493
|
+
sections.push("");
|
|
2494
|
+
sections.push(
|
|
2495
|
+
"Your API uses the following pagination strategies, automatically detected by the SDK:"
|
|
2496
|
+
);
|
|
2497
|
+
sections.push("");
|
|
2498
|
+
} else {
|
|
2499
|
+
sections.push("### Pagination Strategy");
|
|
2500
|
+
sections.push("");
|
|
2501
|
+
sections.push(
|
|
2502
|
+
"Your API uses the following pagination strategy, automatically detected by the SDK:"
|
|
2503
|
+
);
|
|
2504
|
+
sections.push("");
|
|
2505
|
+
}
|
|
2506
|
+
for (const paginationType of availableTypes) {
|
|
2507
|
+
const typeSpecificOperation = {
|
|
2508
|
+
"x-pagination": { type: paginationType },
|
|
2509
|
+
tags: ["Products"],
|
|
2510
|
+
operationId: "listProducts",
|
|
2511
|
+
parameters: [],
|
|
2512
|
+
"x-fn-name": "listProducts",
|
|
2513
|
+
responses: {},
|
|
2514
|
+
requestBody: {}
|
|
2515
|
+
};
|
|
2516
|
+
const typeSpecificEntry = {
|
|
2517
|
+
method: "get",
|
|
2518
|
+
path: "/products",
|
|
2519
|
+
tag: "Products"
|
|
2520
|
+
};
|
|
2521
|
+
if (paginationType === "cursor") {
|
|
2522
|
+
sections.push("#### Cursor Pagination");
|
|
2523
|
+
sections.push("");
|
|
2524
|
+
sections.push("Uses a cursor token to fetch the next page:");
|
|
2525
|
+
sections.push("");
|
|
2526
|
+
const cursorPaginationExample = this.#pagination(
|
|
2527
|
+
typeSpecificOperation,
|
|
2528
|
+
typeSpecificEntry,
|
|
2529
|
+
createObjectLiteral({ limit: 20 })
|
|
2530
|
+
);
|
|
2531
|
+
sections.push(
|
|
2532
|
+
createCodeBlock("typescript", [
|
|
2533
|
+
cursorPaginationExample.content,
|
|
2534
|
+
"",
|
|
2535
|
+
"// Iterate through all pages using cursor",
|
|
2536
|
+
cursorPaginationExample.footer
|
|
2537
|
+
])
|
|
2538
|
+
);
|
|
2539
|
+
sections.push("");
|
|
2540
|
+
}
|
|
2541
|
+
if (paginationType === "offset") {
|
|
2542
|
+
sections.push("#### Offset Pagination");
|
|
2543
|
+
sections.push("");
|
|
2544
|
+
sections.push("Uses offset and limit parameters:");
|
|
2545
|
+
sections.push("");
|
|
2546
|
+
const offsetPaginationExample = this.#pagination(
|
|
2547
|
+
typeSpecificOperation,
|
|
2548
|
+
typeSpecificEntry,
|
|
2549
|
+
createObjectLiteral({ limit: 20, offset: 0 })
|
|
2550
|
+
);
|
|
2551
|
+
sections.push(
|
|
2552
|
+
createCodeBlock("typescript", [
|
|
2553
|
+
offsetPaginationExample.content,
|
|
2554
|
+
"",
|
|
2555
|
+
"// Iterate through all pages using offset",
|
|
2556
|
+
offsetPaginationExample.footer
|
|
2557
|
+
])
|
|
2558
|
+
);
|
|
2559
|
+
sections.push("");
|
|
2560
|
+
}
|
|
2561
|
+
if (paginationType === "page") {
|
|
2562
|
+
sections.push("#### Page Pagination");
|
|
2563
|
+
sections.push("");
|
|
2564
|
+
sections.push("Uses page number and page size:");
|
|
2565
|
+
sections.push("");
|
|
2566
|
+
const pagePaginationExample = this.#pagination(
|
|
2567
|
+
typeSpecificOperation,
|
|
2568
|
+
typeSpecificEntry,
|
|
2569
|
+
createObjectLiteral({ page: 1, pageSize: 20 })
|
|
2570
|
+
);
|
|
2571
|
+
sections.push(
|
|
2572
|
+
createCodeBlock("typescript", [
|
|
2573
|
+
pagePaginationExample.content,
|
|
2574
|
+
"",
|
|
2575
|
+
"// Iterate through all pages using page numbers",
|
|
2576
|
+
pagePaginationExample.footer
|
|
2577
|
+
])
|
|
2578
|
+
);
|
|
2579
|
+
sections.push("");
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
if (availableTypes.length > 1) {
|
|
2583
|
+
sections.push(
|
|
2584
|
+
"The SDK handles the differences transparently, providing a consistent interface regardless of the underlying pagination type."
|
|
2585
|
+
);
|
|
2586
|
+
}
|
|
2587
|
+
return sections.join("\n");
|
|
2588
|
+
}
|
|
2589
|
+
errorHandlingDocs() {
|
|
2590
|
+
const sections = [];
|
|
2591
|
+
sections.push("## Error Handling");
|
|
2592
|
+
sections.push("");
|
|
2593
|
+
sections.push(
|
|
2594
|
+
"The SDK provides structured error handling with typed HTTP error responses."
|
|
2595
|
+
);
|
|
2596
|
+
sections.push("");
|
|
2597
|
+
sections.push("### Error Response Types");
|
|
2598
|
+
sections.push("");
|
|
2599
|
+
sections.push(
|
|
2600
|
+
"All API errors extend from `APIError` and include the HTTP status code and response data:"
|
|
2601
|
+
);
|
|
2602
|
+
sections.push("");
|
|
2603
|
+
sections.push(
|
|
2604
|
+
createCodeBlock("typescript", [
|
|
2605
|
+
`import { BadRequest, Unauthorized, NotFound, TooManyRequests, InternalServerError, ParseError } from "${this.#packageName}";`,
|
|
2606
|
+
"try {",
|
|
2607
|
+
"const usersList = ",
|
|
2608
|
+
this.#toRequest(
|
|
2609
|
+
{
|
|
2610
|
+
method: "get",
|
|
2611
|
+
path: "/users",
|
|
2612
|
+
tag: "Users"
|
|
2613
|
+
},
|
|
2614
|
+
createObjectLiteral({})
|
|
2615
|
+
),
|
|
2616
|
+
" // Handle successful response",
|
|
2617
|
+
"} catch (error) {",
|
|
2618
|
+
" // Handle different error types",
|
|
2619
|
+
" if (error instanceof BadRequest) {",
|
|
2620
|
+
' console.error("Bad request:", error.data);',
|
|
2621
|
+
' console.log("Status:", error.status); // 400',
|
|
2622
|
+
" } else if (error instanceof Unauthorized) {",
|
|
2623
|
+
' console.error("Authentication failed:", error.data);',
|
|
2624
|
+
' console.log("Status:", error.status); // 401',
|
|
2625
|
+
" } else if (error instanceof NotFound) {",
|
|
2626
|
+
' console.error("Resource not found:", error.data);',
|
|
2627
|
+
' console.log("Status:", error.status); // 404',
|
|
2628
|
+
" } else if (error instanceof TooManyRequests) {",
|
|
2629
|
+
' console.error("Rate limited:", error.data);',
|
|
2630
|
+
" if (error.data.retryAfter) {",
|
|
2631
|
+
' console.log("Retry after:", error.data.retryAfter);',
|
|
2632
|
+
" }",
|
|
2633
|
+
" } else if (error instanceof InternalServerError) {",
|
|
2634
|
+
' console.error("Server error:", error.data);',
|
|
2635
|
+
' console.log("Status:", error.status); // 500',
|
|
2636
|
+
" } else if (error instanceof ParseError) {",
|
|
2637
|
+
' console.error("Input validation failed:", error.data);',
|
|
2638
|
+
" }",
|
|
2639
|
+
"}"
|
|
2640
|
+
])
|
|
2641
|
+
);
|
|
2642
|
+
sections.push("");
|
|
2643
|
+
sections.push("### Available Error Classes");
|
|
2644
|
+
sections.push("");
|
|
2645
|
+
sections.push("#### Input Validation Errors");
|
|
2646
|
+
sections.push(
|
|
2647
|
+
"- `ParseError` - Request input validation failed against API schema"
|
|
2648
|
+
);
|
|
2649
|
+
sections.push("");
|
|
2650
|
+
sections.push("#### Client Errors (4xx)");
|
|
2651
|
+
sections.push("- `BadRequest` (400) - Invalid request data");
|
|
2652
|
+
sections.push("- `Unauthorized` (401) - Authentication required");
|
|
2653
|
+
sections.push("- `PaymentRequired` (402) - Payment required");
|
|
2654
|
+
sections.push("- `Forbidden` (403) - Access denied");
|
|
2655
|
+
sections.push("- `NotFound` (404) - Resource not found");
|
|
2656
|
+
sections.push("- `MethodNotAllowed` (405) - HTTP method not allowed");
|
|
2657
|
+
sections.push("- `NotAcceptable` (406) - Content type not acceptable");
|
|
2658
|
+
sections.push("- `Conflict` (409) - Resource conflict");
|
|
2659
|
+
sections.push("- `Gone` (410) - Resource no longer available");
|
|
2660
|
+
sections.push("- `PreconditionFailed` (412) - Precondition failed");
|
|
2661
|
+
sections.push("- `PayloadTooLarge` (413) - Request payload too large");
|
|
2662
|
+
sections.push("- `UnsupportedMediaType` (415) - Unsupported content type");
|
|
2663
|
+
sections.push("- `UnprocessableEntity` (422) - Validation errors");
|
|
2664
|
+
sections.push("- `TooManyRequests` (429) - Rate limit exceeded");
|
|
2665
|
+
sections.push("");
|
|
2666
|
+
sections.push("#### Server Errors (5xx)");
|
|
2667
|
+
sections.push("- `InternalServerError` (500) - Server error");
|
|
2668
|
+
sections.push("- `NotImplemented` (501) - Not implemented");
|
|
2669
|
+
sections.push("- `BadGateway` (502) - Bad gateway");
|
|
2670
|
+
sections.push("- `ServiceUnavailable` (503) - Service unavailable");
|
|
2671
|
+
sections.push("- `GatewayTimeout` (504) - Gateway timeout");
|
|
2672
|
+
sections.push("");
|
|
2673
|
+
sections.push("### Validation Errors");
|
|
2674
|
+
sections.push("");
|
|
2675
|
+
sections.push(
|
|
2676
|
+
"Validation errors (422) include detailed field-level error information:"
|
|
2677
|
+
);
|
|
2678
|
+
sections.push("### Input Validation Errors");
|
|
2679
|
+
sections.push("");
|
|
2680
|
+
sections.push(
|
|
2681
|
+
"When request input fails validation against the API schema, a `ParseError` is thrown:"
|
|
2682
|
+
);
|
|
2683
|
+
sections.push("");
|
|
2684
|
+
sections.push(
|
|
2685
|
+
createCodeBlock("typescript", [
|
|
2686
|
+
`import { ParseError } from "${this.#packageName}";`,
|
|
2687
|
+
"",
|
|
2688
|
+
"try {",
|
|
2689
|
+
" // Invalid input that doesn't match the expected schema",
|
|
2690
|
+
" const newUser = ",
|
|
2691
|
+
this.#toRequest(
|
|
2692
|
+
{
|
|
2693
|
+
method: "post",
|
|
2694
|
+
path: "/users",
|
|
2695
|
+
tag: "Users"
|
|
2696
|
+
},
|
|
2697
|
+
createObjectLiteral({
|
|
2698
|
+
email: 123,
|
|
2699
|
+
// should be string
|
|
2700
|
+
firstName: "",
|
|
2701
|
+
// empty required field
|
|
2702
|
+
age: -5
|
|
2703
|
+
// invalid age value
|
|
2704
|
+
})
|
|
2705
|
+
),
|
|
2706
|
+
"} catch (error) {",
|
|
2707
|
+
" if (error instanceof ParseError) {",
|
|
2708
|
+
' console.log("Input validation failed:");',
|
|
2709
|
+
" ",
|
|
2710
|
+
" // Field-level errors",
|
|
2711
|
+
" if (error.data.fieldErrors) {",
|
|
2712
|
+
" Object.entries(error.data.fieldErrors).forEach(([fieldName, validationIssues]) => {",
|
|
2713
|
+
' console.log(` ${fieldName}: ${validationIssues.map(issue => issue.message).join(", ")}`);',
|
|
2714
|
+
" });",
|
|
2715
|
+
" }",
|
|
2716
|
+
" ",
|
|
2717
|
+
" // Form-level errors",
|
|
2718
|
+
" if (error.data.formErrors.length > 0) {",
|
|
2719
|
+
' console.log(` Form errors: ${error.data.formErrors.map(issue => issue.message).join(", ")}`);',
|
|
2720
|
+
" }",
|
|
2721
|
+
" }",
|
|
2722
|
+
"}"
|
|
2723
|
+
])
|
|
2724
|
+
);
|
|
2725
|
+
sections.push("");
|
|
2726
|
+
sections.push(
|
|
2727
|
+
"`ParseError` contains detailed validation information using Zod's flattened error format, providing specific field-level and form-level validation messages."
|
|
2728
|
+
);
|
|
2729
|
+
sections.push("");
|
|
2730
|
+
sections.push("### Rate Limiting");
|
|
2731
|
+
sections.push("");
|
|
2732
|
+
sections.push(
|
|
2733
|
+
"Rate limit responses may include a `retryAfter` field indicating when to retry:"
|
|
2734
|
+
);
|
|
2735
|
+
sections.push("");
|
|
2736
|
+
sections.push(
|
|
2737
|
+
createCodeBlock("typescript", [
|
|
2738
|
+
`import { TooManyRequests } from "${this.#packageName}";`,
|
|
2739
|
+
"",
|
|
2740
|
+
"try {",
|
|
2741
|
+
" const apiResponse = ",
|
|
2742
|
+
this.#toRequest(
|
|
2743
|
+
{
|
|
2744
|
+
method: "get",
|
|
2745
|
+
path: "/api/data",
|
|
2746
|
+
tag: "Data"
|
|
2747
|
+
},
|
|
2748
|
+
createObjectLiteral({})
|
|
2749
|
+
),
|
|
2750
|
+
"} catch (error) {",
|
|
2751
|
+
" if (error instanceof TooManyRequests) {",
|
|
2752
|
+
" const retryAfterSeconds = error.data.retryAfter;",
|
|
2753
|
+
" if (retryAfterSeconds) {",
|
|
2754
|
+
" console.log(`Rate limited. Retry after: ${retryAfterSeconds} seconds`);",
|
|
2755
|
+
" // Implement your own retry logic",
|
|
2756
|
+
" setTimeout(() => {",
|
|
2757
|
+
" // Retry the request",
|
|
2758
|
+
" }, retryAfterSeconds * 1000);",
|
|
2759
|
+
" }",
|
|
2760
|
+
" }",
|
|
2761
|
+
"}"
|
|
2762
|
+
])
|
|
2763
|
+
);
|
|
2764
|
+
return sections.join("\n");
|
|
2765
|
+
}
|
|
2766
|
+
authenticationDocs() {
|
|
2767
|
+
const authOptions = this.#authentication();
|
|
2768
|
+
if (isEmpty4(authOptions)) {
|
|
2769
|
+
return "";
|
|
2770
|
+
}
|
|
2771
|
+
const sections = [];
|
|
2772
|
+
sections.push("## Authentication");
|
|
2773
|
+
sections.push("");
|
|
2774
|
+
if (authOptions.length === 1) {
|
|
2775
|
+
sections.push(
|
|
2776
|
+
"The SDK requires authentication to access the API. Configure your client with the required credentials:"
|
|
2777
|
+
);
|
|
2778
|
+
} else {
|
|
2779
|
+
sections.push("The SDK supports the following authentication methods:");
|
|
2780
|
+
}
|
|
2781
|
+
sections.push("");
|
|
2782
|
+
for (const authOption of authOptions) {
|
|
2783
|
+
const optionName = authOption["x-optionName"] ?? authOption.name;
|
|
2784
|
+
const isBearer = authOption.in === "header" && authOption.name === "authorization";
|
|
2785
|
+
const isApiKey = authOption.in === "header" && authOption.name !== "authorization";
|
|
2786
|
+
const isQueryParam = authOption.in === "query";
|
|
2787
|
+
const headingLevel = authOptions.length === 1 ? "###" : "###";
|
|
2788
|
+
if (isBearer) {
|
|
2789
|
+
const authenticationHeading = authOptions.length === 1 ? "Bearer Token" : "Bearer Token Authentication";
|
|
2790
|
+
sections.push(`${headingLevel} ${authenticationHeading}`);
|
|
2791
|
+
sections.push("");
|
|
2792
|
+
sections.push(
|
|
2793
|
+
'Pass your bearer token directly - the "Bearer" prefix is automatically added:'
|
|
2794
|
+
);
|
|
2795
|
+
sections.push("");
|
|
2796
|
+
const bearerAuthClient = this.#constructClient({
|
|
2797
|
+
[optionName]: "sk_live_51234567890abcdef1234567890abcdef"
|
|
2798
|
+
});
|
|
2799
|
+
sections.push(createCodeBlock("typescript", [bearerAuthClient.use]));
|
|
2800
|
+
sections.push("");
|
|
2801
|
+
} else if (isApiKey) {
|
|
2802
|
+
const apiKeyHeading = authOptions.length === 1 ? "API Key (Header)" : "API Key Authentication (Header)";
|
|
2803
|
+
sections.push(`${headingLevel} ${apiKeyHeading}`);
|
|
2804
|
+
sections.push("");
|
|
2805
|
+
const apiKeyAuthClient = this.#constructClient({
|
|
2806
|
+
[optionName]: "api_key_1234567890abcdef1234567890abcdef"
|
|
2807
|
+
});
|
|
2808
|
+
sections.push(createCodeBlock("typescript", [apiKeyAuthClient.use]));
|
|
2809
|
+
sections.push("");
|
|
2810
|
+
} else if (isQueryParam) {
|
|
2811
|
+
const queryParamHeading = authOptions.length === 1 ? "API Key (Query Parameter)" : "API Key Authentication (Query Parameter)";
|
|
2812
|
+
sections.push(`${headingLevel} ${queryParamHeading}`);
|
|
2813
|
+
sections.push("");
|
|
2814
|
+
const queryParamAuthClient = this.#constructClient({
|
|
2815
|
+
[optionName]: "qp_key_1234567890abcdef1234567890abcdef"
|
|
2816
|
+
});
|
|
2817
|
+
sections.push(
|
|
2818
|
+
createCodeBlock("typescript", [queryParamAuthClient.use])
|
|
2819
|
+
);
|
|
2820
|
+
sections.push("");
|
|
2821
|
+
} else {
|
|
2822
|
+
const genericAuthHeading = authOptions.length === 1 ? authOption.name : `${authOption.name} Authentication`;
|
|
2823
|
+
sections.push(`${headingLevel} ${genericAuthHeading}`);
|
|
2824
|
+
sections.push("");
|
|
2825
|
+
const genericAuthClient = this.#constructClient({
|
|
2826
|
+
[optionName]: "auth_token_1234567890abcdef1234567890abcdef"
|
|
2827
|
+
});
|
|
2828
|
+
sections.push(createCodeBlock("typescript", [genericAuthClient.use]));
|
|
2829
|
+
sections.push("");
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
return sections.join("\n");
|
|
2833
|
+
}
|
|
2834
|
+
generalUsageDocs() {
|
|
2835
|
+
const sections = [];
|
|
2836
|
+
return sections.join("\n");
|
|
2837
|
+
}
|
|
2838
|
+
configurationUpdateDocs() {
|
|
2839
|
+
const sections = [];
|
|
2840
|
+
const authOptions = this.#authentication();
|
|
2841
|
+
sections.push("### Updating Configuration");
|
|
2842
|
+
sections.push("");
|
|
2843
|
+
sections.push(
|
|
2844
|
+
"You can update client configuration after initialization using the `setOptions` method:"
|
|
2845
|
+
);
|
|
2846
|
+
sections.push("");
|
|
2847
|
+
const initialClientOptions = {
|
|
2848
|
+
baseUrl: "https://api.production-service.com"
|
|
2849
|
+
};
|
|
2850
|
+
if (!isEmpty4(authOptions)) {
|
|
2851
|
+
const [primaryAuth] = authOptions;
|
|
2852
|
+
const authOptionName = primaryAuth["x-optionName"] ?? primaryAuth.name;
|
|
2853
|
+
initialClientOptions[authOptionName] = "prod_sk_1234567890abcdef";
|
|
2854
|
+
}
|
|
2855
|
+
const initialClientSetup = this.#constructClient(initialClientOptions);
|
|
2856
|
+
const configurationUpdateCode = [
|
|
2857
|
+
"// Initial client setup",
|
|
2858
|
+
initialClientSetup.use,
|
|
2859
|
+
"",
|
|
2860
|
+
"// Later, update specific options",
|
|
2861
|
+
"client.setOptions({",
|
|
2862
|
+
" baseUrl: 'https://api.staging-service.com',"
|
|
2863
|
+
];
|
|
2864
|
+
if (!isEmpty4(authOptions)) {
|
|
2865
|
+
const [primaryAuth] = authOptions;
|
|
2866
|
+
const authOptionName = primaryAuth["x-optionName"] ?? primaryAuth.name;
|
|
2867
|
+
configurationUpdateCode.push(
|
|
2868
|
+
` ${authOptionName}: 'staging_sk_abcdef1234567890'`
|
|
2869
|
+
);
|
|
2870
|
+
}
|
|
2871
|
+
configurationUpdateCode.push("});");
|
|
2872
|
+
sections.push(createCodeBlock("typescript", configurationUpdateCode));
|
|
2873
|
+
sections.push("");
|
|
2874
|
+
sections.push(
|
|
2875
|
+
"The `setOptions` method validates the provided options and only updates the specified fields, leaving other configuration unchanged."
|
|
2876
|
+
);
|
|
2877
|
+
return sections.join("\n");
|
|
1966
2878
|
}
|
|
1967
2879
|
};
|
|
1968
|
-
function
|
|
1969
|
-
|
|
1970
|
-
|
|
2880
|
+
function createCodeBlock(language, content) {
|
|
2881
|
+
return ["```" + language, ...content, "```"].join("\n");
|
|
2882
|
+
}
|
|
2883
|
+
function createObjectLiteral(obj, indent = " ") {
|
|
2884
|
+
return "{\n" + Object.entries(obj).map(([key, value]) => `${indent}${key}: ${JSON.stringify(value)}`).join(",\n") + `
|
|
2885
|
+
${indent.slice(0, -1)}}`;
|
|
2886
|
+
}
|
|
2887
|
+
function availablePaginationTypes(spec) {
|
|
2888
|
+
let offset = false;
|
|
2889
|
+
let page = false;
|
|
2890
|
+
let cursor = false;
|
|
2891
|
+
forEachOperation3(spec, (entry, operation) => {
|
|
2892
|
+
if (operation["x-pagination"]) {
|
|
2893
|
+
switch (operation["x-pagination"].type) {
|
|
2894
|
+
case "offset":
|
|
2895
|
+
offset = true;
|
|
2896
|
+
break;
|
|
2897
|
+
case "page":
|
|
2898
|
+
page = true;
|
|
2899
|
+
break;
|
|
2900
|
+
case "cursor":
|
|
2901
|
+
cursor = true;
|
|
2902
|
+
break;
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
});
|
|
2906
|
+
return {
|
|
2907
|
+
offset,
|
|
2908
|
+
page,
|
|
2909
|
+
cursor
|
|
2910
|
+
};
|
|
1971
2911
|
}
|
|
1972
2912
|
|
|
1973
2913
|
// packages/typescript/src/lib/generate.ts
|
|
@@ -2140,6 +3080,12 @@ ${template2(dispatcher_default, {})({ throwError: !style.errorAsValue, outputTyp
|
|
|
2140
3080
|
"models/index.ts": modelsIndex
|
|
2141
3081
|
// ...(modelsImports.length ? { 'models/index.ts': modelsIndex } : {}),
|
|
2142
3082
|
});
|
|
3083
|
+
if (settings.agentTools) {
|
|
3084
|
+
await settings.writer(output, {
|
|
3085
|
+
"agents.ts": `${generateAgentTools(spec)}
|
|
3086
|
+
${utils_default}`
|
|
3087
|
+
});
|
|
3088
|
+
}
|
|
2143
3089
|
await settings.writer(output, {
|
|
2144
3090
|
"index.ts": await getFolderExports(
|
|
2145
3091
|
output,
|
|
@@ -2204,11 +3150,13 @@ ${template2(dispatcher_default, {})({ throwError: !style.errorAsValue, outputTyp
|
|
|
2204
3150
|
)
|
|
2205
3151
|
}
|
|
2206
3152
|
};
|
|
2207
|
-
if (settings.readme) {
|
|
2208
|
-
configFiles["README.md"] = toReadme(spec, generator);
|
|
2209
|
-
}
|
|
2210
3153
|
await settings.writer(settings.output, configFiles);
|
|
2211
3154
|
}
|
|
3155
|
+
if (settings.readme) {
|
|
3156
|
+
await settings.writer(settings.mode === "full" ? settings.output : output, {
|
|
3157
|
+
"README.md": toReadme(spec, generator)
|
|
3158
|
+
});
|
|
3159
|
+
}
|
|
2212
3160
|
await settings.formatCode?.({
|
|
2213
3161
|
output,
|
|
2214
3162
|
env: npmRunPathEnv()
|
|
@@ -2296,10 +3244,44 @@ function toInputs(operationsSet, commonZod, makeImport) {
|
|
|
2296
3244
|
...inputs
|
|
2297
3245
|
};
|
|
2298
3246
|
}
|
|
3247
|
+
function generateAgentTools(spec) {
|
|
3248
|
+
const groups = {};
|
|
3249
|
+
forEachOperation4(spec, (entry, operation) => {
|
|
3250
|
+
groups[entry.tag] ??= [];
|
|
3251
|
+
groups[entry.tag].push(createTool(entry, operation));
|
|
3252
|
+
});
|
|
3253
|
+
const imports = [
|
|
3254
|
+
`import { z } from 'zod';`,
|
|
3255
|
+
`import { tool } from '@openai/agents';`,
|
|
3256
|
+
`import * as schemas from './inputs/index.ts';`
|
|
3257
|
+
];
|
|
3258
|
+
const tools = Object.entries(groups).map(([group, tools2]) => {
|
|
3259
|
+
return `export const ${spinalcase3(group)} = [${tools2.join(", ")}];`;
|
|
3260
|
+
});
|
|
3261
|
+
return [...imports, ...tools].join("\n\n");
|
|
3262
|
+
}
|
|
3263
|
+
function createTool(entry, operation) {
|
|
3264
|
+
const schemaName = camelcase4(`${operation.operationId} schema`);
|
|
3265
|
+
return `tool({
|
|
3266
|
+
description: \`${operation.description || operation.summary}\`,
|
|
3267
|
+
name: '${operation["x-fn-name"]}',
|
|
3268
|
+
parameters: makeOptionalPropsNullable(schemas.${schemaName}),
|
|
3269
|
+
execute: async (input, maybeContext) => {
|
|
3270
|
+
console.log('Executing ${operation.operationId} tool with input:', input);
|
|
3271
|
+
const context = coerceContext(maybeContext?.context);
|
|
3272
|
+
const client = context.client;
|
|
3273
|
+
const response = await client.request(
|
|
3274
|
+
'${entry.method.toUpperCase()} ${entry.path}' ,
|
|
3275
|
+
input as any,
|
|
3276
|
+
);
|
|
3277
|
+
return JSON.stringify(response);
|
|
3278
|
+
},
|
|
3279
|
+
})`;
|
|
3280
|
+
}
|
|
2299
3281
|
export {
|
|
2300
3282
|
TypeScriptGenerator,
|
|
2301
3283
|
generate,
|
|
2302
|
-
|
|
3284
|
+
generateAgentTools,
|
|
2303
3285
|
toInputs
|
|
2304
3286
|
};
|
|
2305
3287
|
//# sourceMappingURL=index.js.map
|