diff --git a/fern/apis/fdr/definition/api/latest/__package__.yml b/fern/apis/fdr/definition/api/latest/__package__.yml index adb2944846..4eb2ee8ad3 100644 --- a/fern/apis/fdr/definition/api/latest/__package__.yml +++ b/fern/apis/fdr/definition/api/latest/__package__.yml @@ -8,7 +8,7 @@ imports: commons: commons.yml rootCommons: ../../commons.yml auth: auth.yml - + v1Register: ../v1/register/__package__.yml service: base-path: /registry/api/latest auth: true @@ -35,6 +35,7 @@ types: subpackages: map auths: map globalHeaders: optional> + snippetsConfiguration: optional errors: ApiDoesNotExistError: diff --git a/packages/fdr-sdk/src/api-definition/__test__/join.test.ts b/packages/fdr-sdk/src/api-definition/__test__/join.test.ts index f9a419b1ea..1c8d989f60 100644 --- a/packages/fdr-sdk/src/api-definition/__test__/join.test.ts +++ b/packages/fdr-sdk/src/api-definition/__test__/join.test.ts @@ -219,6 +219,7 @@ const api1: Latest.ApiDefinition = { availability: undefined, }, ], + snippetsConfiguration: undefined, }; const api2: Latest.ApiDefinition = { @@ -251,6 +252,7 @@ const api2: Latest.ApiDefinition = { availability: undefined, }, ], + snippetsConfiguration: undefined, }; const api3: Latest.ApiDefinition = { @@ -281,6 +283,7 @@ const api3: Latest.ApiDefinition = { availability: undefined, }, ], + snippetsConfiguration: undefined, }; describe("join", () => { diff --git a/packages/fdr-sdk/src/api-definition/__test__/prune.test.ts b/packages/fdr-sdk/src/api-definition/__test__/prune.test.ts index ab38bc51e0..38cb27393a 100644 --- a/packages/fdr-sdk/src/api-definition/__test__/prune.test.ts +++ b/packages/fdr-sdk/src/api-definition/__test__/prune.test.ts @@ -226,6 +226,7 @@ const api: Latest.ApiDefinition = { availability: undefined, }, ], + snippetsConfiguration: undefined, }; describe("prune", () => { diff --git a/packages/fdr-sdk/src/api-definition/join.ts b/packages/fdr-sdk/src/api-definition/join.ts index 103be2bbc6..ef1477d48b 100644 --- a/packages/fdr-sdk/src/api-definition/join.ts +++ b/packages/fdr-sdk/src/api-definition/join.ts @@ -24,6 +24,9 @@ export function joiner( subpackages: { ...first.subpackages }, auths: { ...first.auths }, globalHeaders: first.globalHeaders ? [...first.globalHeaders] : undefined, + snippetsConfiguration: first.snippetsConfiguration + ? { ...first.snippetsConfiguration } + : undefined, }; let isJoined = false; diff --git a/packages/fdr-sdk/src/api-definition/migrators/v1ToV2.ts b/packages/fdr-sdk/src/api-definition/migrators/v1ToV2.ts index abe10a0b06..131d36b5d7 100644 --- a/packages/fdr-sdk/src/api-definition/migrators/v1ToV2.ts +++ b/packages/fdr-sdk/src/api-definition/migrators/v1ToV2.ts @@ -142,6 +142,7 @@ export class ApiDefinitionV1ToLatest { subpackages: this.subpackages, auths: this.v1.auth ? { [AUTH_SCHEME_ID]: this.v1.auth } : {}, globalHeaders: this.migrateParameters(this.v1.globalHeaders), + snippetsConfiguration: undefined, }; }; diff --git a/packages/fdr-sdk/src/api-definition/transformer.ts b/packages/fdr-sdk/src/api-definition/transformer.ts index 6ff0d90ce7..a2bb72e716 100644 --- a/packages/fdr-sdk/src/api-definition/transformer.ts +++ b/packages/fdr-sdk/src/api-definition/transformer.ts @@ -240,6 +240,7 @@ export class Transformer { globalHeaders, auths: api.auths, subpackages: api.subpackages, + snippetsConfiguration: api.snippetsConfiguration, }; }; diff --git a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/types/ApiDefinition.ts b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/types/ApiDefinition.ts index 1421a6ab19..6dbc0fc5e7 100644 --- a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/types/ApiDefinition.ts +++ b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/latest/types/ApiDefinition.ts @@ -13,4 +13,5 @@ export interface ApiDefinition { subpackages: Record; auths: Record; globalHeaders: FernRegistry.api.latest.ObjectProperty[] | undefined; + snippetsConfiguration: FernRegistry.api.v1.register.SnippetsConfig | undefined; } diff --git a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/client/Client.ts b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/client/Client.ts index c4fda5f617..8b136722fd 100644 --- a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/client/Client.ts +++ b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/client/Client.ts @@ -709,7 +709,39 @@ export class Register { * }, * description: "string", * availability: "Stable" - * }] + * }], + * snippetsConfiguration: { + * typescriptSdk: { + * package: "string", + * version: { + * "key": "value" + * } + * }, + * pythonSdk: { + * package: "string", + * version: { + * "key": "value" + * } + * }, + * goSdk: { + * githubRepo: "string", + * version: { + * "key": "value" + * } + * }, + * javaSdk: { + * coordinate: "string", + * version: { + * "key": "value" + * } + * }, + * rubySdk: { + * gem: "string", + * version: { + * "key": "value" + * } + * } + * } * }, * sources: { * "string": { diff --git a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/client/requests/RegisterApiDefinitionRequest.ts b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/client/requests/RegisterApiDefinitionRequest.ts index 286e1fed88..4f5fd3de78 100644 --- a/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/client/requests/RegisterApiDefinitionRequest.ts +++ b/packages/fdr-sdk/src/client/generated/api/resources/api/resources/v1/resources/register/client/requests/RegisterApiDefinitionRequest.ts @@ -682,7 +682,39 @@ import * as FernRegistry from "../../../../../../../../index"; * }, * description: "string", * availability: "Stable" - * }] + * }], + * snippetsConfiguration: { + * typescriptSdk: { + * package: "string", + * version: { + * "key": "value" + * } + * }, + * pythonSdk: { + * package: "string", + * version: { + * "key": "value" + * } + * }, + * goSdk: { + * githubRepo: "string", + * version: { + * "key": "value" + * } + * }, + * javaSdk: { + * coordinate: "string", + * version: { + * "key": "value" + * } + * }, + * rubySdk: { + * gem: "string", + * version: { + * "key": "value" + * } + * } + * } * }, * sources: { * "string": { diff --git a/packages/fern-docs/cache/src/__test__/ApiDefinitionLoader.test.ts b/packages/fern-docs/cache/src/__test__/ApiDefinitionLoader.test.ts index 61f80797a6..2739e5ec82 100644 --- a/packages/fern-docs/cache/src/__test__/ApiDefinitionLoader.test.ts +++ b/packages/fern-docs/cache/src/__test__/ApiDefinitionLoader.test.ts @@ -96,6 +96,7 @@ describe("curl snippet generation", () => { const apiDefinition = await loader .withApiDefinition({ id: ApiDefinitionId("id"), + snippetsConfiguration: undefined, webhooks: {}, websockets: {}, types: {}, diff --git a/packages/parsers/src/client/generated/api/resources/api/resources/latest/types/ApiDefinition.ts b/packages/parsers/src/client/generated/api/resources/api/resources/latest/types/ApiDefinition.ts index 1421a6ab19..6dbc0fc5e7 100644 --- a/packages/parsers/src/client/generated/api/resources/api/resources/latest/types/ApiDefinition.ts +++ b/packages/parsers/src/client/generated/api/resources/api/resources/latest/types/ApiDefinition.ts @@ -13,4 +13,5 @@ export interface ApiDefinition { subpackages: Record; auths: Record; globalHeaders: FernRegistry.api.latest.ObjectProperty[] | undefined; + snippetsConfiguration: FernRegistry.api.v1.register.SnippetsConfig | undefined; } diff --git a/packages/parsers/src/openapi/3.1/OpenApiDocumentConverter.node.ts b/packages/parsers/src/openapi/3.1/OpenApiDocumentConverter.node.ts index 5182426c58..7d60cfba80 100644 --- a/packages/parsers/src/openapi/3.1/OpenApiDocumentConverter.node.ts +++ b/packages/parsers/src/openapi/3.1/OpenApiDocumentConverter.node.ts @@ -154,6 +154,7 @@ export class OpenApiDocumentConverterNode extends BaseOpenApiV3_1ConverterNode< subpackages, auths: { ...auths, ...(this.auth?.convert() ?? {}) }, globalHeaders: this.globalHeaders?.convert(), + snippetsConfiguration: undefined, }; } } diff --git a/packages/parsers/src/openrpc/1.x/OpenrpcDocumentConverter.node.ts b/packages/parsers/src/openrpc/1.x/OpenrpcDocumentConverter.node.ts index ee76eccbaf..d6e0f4e13e 100644 --- a/packages/parsers/src/openrpc/1.x/OpenrpcDocumentConverter.node.ts +++ b/packages/parsers/src/openrpc/1.x/OpenrpcDocumentConverter.node.ts @@ -94,6 +94,7 @@ export class OpenrpcDocumentConverterNode extends BaseOpenrpcConverterNode< subpackages, auths: {}, globalHeaders: [], + snippetsConfiguration: undefined, }; } } diff --git a/servers/fdr/src/api/generated/api/resources/api/resources/latest/types/ApiDefinition.d.ts b/servers/fdr/src/api/generated/api/resources/api/resources/latest/types/ApiDefinition.d.ts index 00d5ec4c2e..9456727d16 100644 --- a/servers/fdr/src/api/generated/api/resources/api/resources/latest/types/ApiDefinition.d.ts +++ b/servers/fdr/src/api/generated/api/resources/api/resources/latest/types/ApiDefinition.d.ts @@ -11,4 +11,5 @@ export interface ApiDefinition { subpackages: Record; auths: Record; globalHeaders: FernRegistry.api.latest.ObjectProperty[] | undefined; + snippetsConfiguration: FernRegistry.api.v1.register.SnippetsConfig | undefined; } diff --git a/servers/fdr/src/controllers/api/getRegisterApiService.ts b/servers/fdr/src/controllers/api/getRegisterApiService.ts index 467ba8650c..d62804f014 100644 --- a/servers/fdr/src/controllers/api/getRegisterApiService.ts +++ b/servers/fdr/src/controllers/api/getRegisterApiService.ts @@ -1,11 +1,12 @@ import { APIV1Db, APIV1Write, + convertAPIDefinitionToDb, FdrAPI, SDKSnippetHolder, - convertAPIDefinitionToDb, } from "@fern-api/fdr-sdk"; import { v4 as uuidv4 } from "uuid"; +import { stringifyEndpointPathParts } from "../../../../../packages/fdr-sdk/src/navigation/utils/stringifyEndpointPathParts"; import { APIV1WriteService } from "../../api"; import { SdkRequest } from "../../api/generated/api"; import type { FdrApplication } from "../../app"; @@ -40,12 +41,9 @@ export function getRegisterApiService(app: FdrApplication): APIV1WriteService { | FdrAPI.api.latest.ApiDefinition | undefined; - if ( - req.body.definition != null && - Object.keys(req.body.definition).length > 0 - ) { - const snippetsConfiguration = req.body.definition - .snippetsConfiguration ?? { + const snippetsConfiguration = req.body.definition + ?.snippetsConfiguration ?? + req.body.definitionV2?.snippetsConfiguration ?? { typescriptSdk: undefined, pythonSdk: undefined, javaSdk: undefined, @@ -53,56 +51,66 @@ export function getRegisterApiService(app: FdrApplication): APIV1WriteService { rubySdk: undefined, }; - const snippetsConfigurationWithSdkIds = await app.dao - .sdks() - .getSdkIdsForPackages(snippetsConfiguration); - const sdkIds: string[] = []; - if (snippetsConfigurationWithSdkIds.typescriptSdk != null) { - sdkIds.push(snippetsConfigurationWithSdkIds.typescriptSdk.sdkId); - } - if (snippetsConfigurationWithSdkIds.pythonSdk != null) { - sdkIds.push(snippetsConfigurationWithSdkIds.pythonSdk.sdkId); - } - if (snippetsConfigurationWithSdkIds.javaSdk != null) { - sdkIds.push(snippetsConfigurationWithSdkIds.javaSdk.sdkId); - } - if (snippetsConfigurationWithSdkIds.goSdk != null) { - sdkIds.push(snippetsConfigurationWithSdkIds.goSdk.sdkId); - } - if (snippetsConfigurationWithSdkIds.rubySdk != null) { - sdkIds.push(snippetsConfigurationWithSdkIds.rubySdk.sdkId); - } + const snippetsConfigurationWithSdkIds = await app.dao + .sdks() + .getSdkIdsForPackages(snippetsConfiguration); + const sdkIds: string[] = []; + if (snippetsConfigurationWithSdkIds.typescriptSdk != null) { + sdkIds.push(snippetsConfigurationWithSdkIds.typescriptSdk.sdkId); + } + if (snippetsConfigurationWithSdkIds.pythonSdk != null) { + sdkIds.push(snippetsConfigurationWithSdkIds.pythonSdk.sdkId); + } + if (snippetsConfigurationWithSdkIds.javaSdk != null) { + sdkIds.push(snippetsConfigurationWithSdkIds.javaSdk.sdkId); + } + if (snippetsConfigurationWithSdkIds.goSdk != null) { + sdkIds.push(snippetsConfigurationWithSdkIds.goSdk.sdkId); + } + if (snippetsConfigurationWithSdkIds.rubySdk != null) { + sdkIds.push(snippetsConfigurationWithSdkIds.rubySdk.sdkId); + } - const snippetsBySdkId = await app.dao - .snippets() - .loadAllSnippetsForSdkIds(sdkIds); - const snippetsBySdkIdAndEndpointId = await app.dao - .snippets() - .loadAllSnippetsForSdkIdsByEndpointId(sdkIds); - const snippetTemplatesByEndpoint = await getSnippetTemplatesIfEnabled({ + const snippetsBySdkId = await app.dao + .snippets() + .loadAllSnippetsForSdkIds(sdkIds); + const snippetsBySdkIdAndEndpointId = await app.dao + .snippets() + .loadAllSnippetsForSdkIdsByEndpointId(sdkIds); + let snippetTemplatesByEndpoint: SnippetTemplatesByEndpoint = {}; + let snippetTemplatesByEndpointId: SnippetTemplatesByEndpointIdentifier = + {}; + + snippetTemplatesByEndpoint = await getSnippetTemplatesIfEnabled({ + app, + authorization: req.headers.authorization, + orgId: req.body.orgId, + apiId: req.body.apiId, + definition: req.body.definition ?? req.body.definitionV2, + snippetsConfigurationWithSdkIds, + }); + snippetTemplatesByEndpointId = + await getSnippetTemplatesByEndpointIdIfEnabled({ app, authorization: req.headers.authorization, orgId: req.body.orgId, apiId: req.body.apiId, - definition: req.body.definition, + definition: req.body.definition ?? req.body.definitionV2, snippetsConfigurationWithSdkIds, }); - const snippetTemplatesByEndpointId = - await getSnippetTemplatesByEndpointIdIfEnabled({ - app, - authorization: req.headers.authorization, - orgId: req.body.orgId, - apiId: req.body.apiId, - definition: req.body.definition, - snippetsConfigurationWithSdkIds, - }); - const snippetHolder = new SDKSnippetHolder({ - snippetsBySdkId, - snippetsBySdkIdAndEndpointId, - snippetsConfigWithSdkId: snippetsConfigurationWithSdkIds, - snippetTemplatesByEndpoint, - snippetTemplatesByEndpointId, - }); + + const snippetHolder = new SDKSnippetHolder({ + snippetsBySdkId, + snippetsBySdkIdAndEndpointId, + snippetsConfigWithSdkId: snippetsConfigurationWithSdkIds, + snippetTemplatesByEndpoint, + snippetTemplatesByEndpointId, + }); + + if ( + req.body.definition != null && + Object.keys(req.body.definition).length > 0 + ) { transformedApiDefinition = convertAPIDefinitionToDb( req.body.definition, apiDefinitionId, @@ -119,7 +127,10 @@ export function getRegisterApiService(app: FdrApplication): APIV1WriteService { ) { throw new Error("No latest definition provided"); } - transformedApiDefinition = req.body.definitionV2; + transformedApiDefinition = enrichApiLatestDefinitionWithSnippets( + req.body.definitionV2, + snippetHolder + ); isLatest = true; apiDefinitionId = transformedApiDefinition.id; } @@ -170,6 +181,117 @@ export function getRegisterApiService(app: FdrApplication): APIV1WriteService { }); } +function enrichApiLatestDefinitionWithSnippets( + definition: FdrAPI.api.latest.ApiDefinition, + snippetHolder: SDKSnippetHolder +): FdrAPI.api.latest.ApiDefinition { + Object.entries(definition.endpoints).forEach(([_, endpoint]) => { + endpoint.snippetTemplates = snippetHolder.getSnippetTemplateForEndpoint({ + endpointPath: FdrAPI.EndpointPathLiteral( + stringifyEndpointPathParts(endpoint.path) + ), + endpointMethod: endpoint.method, + endpointId: undefined, + }); + + const goSnippet = snippetHolder.getGoCodeSnippetForEndpoint({ + endpointPath: FdrAPI.EndpointPathLiteral( + stringifyEndpointPathParts(endpoint.path) + ), + endpointMethod: endpoint.method, + endpointId: undefined, + exampleId: undefined, + }); + const pythonSnippet = snippetHolder.getPythonCodeSnippetForEndpoint({ + endpointPath: FdrAPI.EndpointPathLiteral( + stringifyEndpointPathParts(endpoint.path) + ), + endpointMethod: endpoint.method, + endpointId: undefined, + exampleId: undefined, + }); + const rubySnippet = snippetHolder.getRubyCodeSnippetForEndpoint({ + endpointPath: FdrAPI.EndpointPathLiteral( + stringifyEndpointPathParts(endpoint.path) + ), + endpointMethod: endpoint.method, + endpointId: undefined, + exampleId: undefined, + }); + const typescriptSnippet = snippetHolder.getTypeScriptCodeSnippetForEndpoint( + { + endpointPath: FdrAPI.EndpointPathLiteral( + stringifyEndpointPathParts(endpoint.path) + ), + endpointMethod: endpoint.method, + endpointId: undefined, + exampleId: undefined, + } + ); + + endpoint.examples?.forEach((example) => { + if (goSnippet != null) { + example.snippets ??= {}; + example.snippets.go ??= []; + example.snippets.go.push({ + language: "go", + code: goSnippet.client, + install: goSnippet.install, + generated: true, + description: example.description, + name: undefined, + }); + } + if (pythonSnippet != null) { + example.snippets ??= {}; + example.snippets.python ??= []; + example.snippets.python.push({ + language: "python", + code: pythonSnippet.async_client, + install: pythonSnippet.install, + generated: true, + description: example.description, + name: "async_client", + }); + example.snippets.python.push({ + language: "python", + code: pythonSnippet.sync_client, + install: pythonSnippet.install, + generated: true, + description: example.description, + name: "sync_client", + }); + } + if (rubySnippet != null) { + example.snippets ??= {}; + example.snippets.ruby ??= []; + example.snippets.ruby.push({ + language: "ruby", + code: rubySnippet.client, + install: rubySnippet.install, + generated: true, + description: example.description, + name: undefined, + }); + } + if (typescriptSnippet != null) { + example.snippets ??= {}; + example.snippets.typescript ??= []; + example.snippets.typescript.push({ + language: "typescript", + code: typescriptSnippet.client, + install: typescriptSnippet.install, + generated: true, + description: example.description, + name: undefined, + }); + } + }); + }); + + return definition; +} + function getSnippetSdkRequests({ snippetsConfigurationWithSdkIds, }: { @@ -234,10 +356,16 @@ async function getSnippetTemplatesByEndpointIdIfEnabled({ authorization: string | undefined; orgId: FdrAPI.OrgId; apiId: FdrAPI.ApiId; - definition: APIV1Write.ApiDefinition; + definition: + | APIV1Write.ApiDefinition + | FdrAPI.api.latest.ApiDefinition + | undefined; snippetsConfigurationWithSdkIds: SdkIdForPackage; }): Promise { try { + if (definition == null) { + return {}; + } const hasSnippetTemplatesAccess = await app.services.auth.checkOrgHasSnippetTemplateAccess({ authHeader: authorization, @@ -277,10 +405,16 @@ async function getSnippetTemplatesIfEnabled({ authorization: string | undefined; orgId: FdrAPI.OrgId; apiId: FdrAPI.ApiId; - definition: APIV1Write.ApiDefinition; + definition: + | APIV1Write.ApiDefinition + | FdrAPI.api.latest.ApiDefinition + | undefined; snippetsConfigurationWithSdkIds: SdkIdForPackage; }): Promise { try { + if (definition == null) { + return {}; + } const hasSnippetTemplatesAccess = await app.services.auth.checkOrgHasSnippetTemplateAccess({ authHeader: authorization, diff --git a/servers/fdr/src/db/snippets/SnippetTemplate.ts b/servers/fdr/src/db/snippets/SnippetTemplate.ts index 78bb0fc9ec..987030e0d9 100644 --- a/servers/fdr/src/db/snippets/SnippetTemplate.ts +++ b/servers/fdr/src/db/snippets/SnippetTemplate.ts @@ -42,14 +42,14 @@ export interface SnippetTemplateDao { orgId: FdrAPI.OrgId; apiId: FdrAPI.ApiId; sdkRequests: FdrAPI.SdkRequest[]; - definition: APIV1Write.ApiDefinition; + definition: APIV1Write.ApiDefinition | FdrAPI.api.latest.ApiDefinition; }): Promise; loadSnippetTemplatesByEndpointIdentifier(opts: { orgId: FdrAPI.OrgId; apiId: FdrAPI.ApiId; sdkRequests: FdrAPI.SdkRequest[]; - definition: APIV1Write.ApiDefinition; + definition: APIV1Write.ApiDefinition | FdrAPI.api.latest.ApiDefinition; }): Promise; storeSnippetTemplate({ @@ -70,16 +70,34 @@ export class SnippetTemplateDaoImpl implements SnippetTemplateDao { orgId: FdrAPI.OrgId; apiId: FdrAPI.ApiId; sdkRequests: FdrAPI.SdkRequest[]; - definition: APIV1Write.ApiDefinition; + definition: APIV1Write.ApiDefinition | FdrAPI.api.latest.ApiDefinition; }): Promise { - const endpoints: APIV1Write.EndpointDefinition[] = []; - for (const endpoint of definition.rootPackage.endpoints) { - endpoints.push(endpoint); - } + const endpoints: { + path: APIV1Write.EndpointPathPart[]; + method: FdrAPI.HttpMethod; + }[] = []; + if (typeof definition === "object" && "rootPackage" in definition) { + for (const endpoint of definition.rootPackage.endpoints) { + endpoints.push({ + path: endpoint.path.parts, + method: endpoint.method, + }); + } - for (const subpackage of Object.values(definition.subpackages)) { - for (const endpoint of subpackage.endpoints) { - endpoints.push(endpoint); + for (const subpackage of Object.values(definition.subpackages)) { + for (const endpoint of subpackage.endpoints) { + endpoints.push({ + path: endpoint.path.parts, + method: endpoint.method, + }); + } + } + } else { + for (const endpoint of Object.values(definition.endpoints)) { + endpoints.push({ + path: endpoint.path, + method: endpoint.method, + }); } } @@ -95,7 +113,7 @@ export class SnippetTemplateDaoImpl implements SnippetTemplateDao { orgId, apiId, endpointId: { - path: getEndpointPathAsString(endpoint), + path: getEndpointPathAsString(endpoint.path), method: endpoint.method, identifierOverride: undefined, }, @@ -325,21 +343,40 @@ export class SnippetTemplateDaoImpl implements SnippetTemplateDao { orgId: FdrAPI.OrgId; apiId: FdrAPI.ApiId; sdkRequests: FdrAPI.SdkRequest[]; - definition: APIV1Write.ApiDefinition; + definition: APIV1Write.ApiDefinition | FdrAPI.api.latest.ApiDefinition; }): Promise< Record< FdrAPI.EndpointPathLiteral, Record > > { - const endpoints: APIV1Write.EndpointDefinition[] = []; - for (const endpoint of definition.rootPackage.endpoints) { - endpoints.push(endpoint); - } + const endpoints: { + path: APIV1Write.EndpointPathPart[]; + method: FdrAPI.HttpMethod; + }[] = []; - for (const subpackage of Object.values(definition.subpackages)) { - for (const endpoint of subpackage.endpoints) { - endpoints.push(endpoint); + if (typeof definition === "object" && "rootPackage" in definition) { + for (const endpoint of definition.rootPackage.endpoints) { + endpoints.push({ + path: endpoint.path.parts, + method: endpoint.method, + }); + } + + for (const subpackage of Object.values(definition.subpackages)) { + for (const endpoint of subpackage.endpoints) { + endpoints.push({ + path: endpoint.path.parts, + method: endpoint.method, + }); + } + } + } else { + for (const endpoint of Object.values(definition.endpoints)) { + endpoints.push({ + path: endpoint.path, + method: endpoint.method, + }); } } @@ -358,7 +395,7 @@ export class SnippetTemplateDaoImpl implements SnippetTemplateDao { orgId, apiId, endpointId: { - path: getEndpointPathAsString(endpoint), + path: getEndpointPathAsString(endpoint.path), method: endpoint.method, identifierOverride: undefined, }, @@ -384,9 +421,11 @@ export class SnippetTemplateDaoImpl implements SnippetTemplateDao { } } -function getEndpointPathAsString(endpoint: APIV1Write.EndpointDefinition) { +function getEndpointPathAsString( + endpointPathParts: APIV1Write.EndpointPathPart[] +) { let endpointPath = ""; - for (const part of endpoint.path.parts) { + for (const part of endpointPathParts) { if (part.type === "literal") { endpointPath += part.value; } else {