diff --git a/servers/fdr/src/controllers/api/getRegisterApiService.ts b/servers/fdr/src/controllers/api/getRegisterApiService.ts index 44dadacac6..85b8ddfe5d 100644 --- a/servers/fdr/src/controllers/api/getRegisterApiService.ts +++ b/servers/fdr/src/controllers/api/getRegisterApiService.ts @@ -1,8 +1,11 @@ -import { SDKSnippetHolder, convertAPIDefinitionToDb } from "@fern-api/fdr-sdk"; +import { APIV1Write, SDKSnippetHolder, convertAPIDefinitionToDb } from "@fern-api/fdr-sdk"; import { v4 as uuidv4 } from "uuid"; import { APIV1WriteService } from "../../api"; import { SdkRequest } from "../../api/generated/api"; import type { FdrApplication } from "../../app"; +import { LOGGER } from "../../app/FdrApplication"; +import { SdkIdForPackage } from "../../db/sdk/SdkDao"; +import { SnippetTemplatesByEndpoint } from "../../db/snippets/SnippetTemplate"; import { writeBuffer } from "../../util"; const REGISTER_API_DEFINITION_META = { @@ -22,62 +25,30 @@ export function getRegisterApiService(app: FdrApplication): APIV1WriteService { const snippetsConfigurationWithSdkIds = await app.dao.sdks().getSdkIdsForPackages(snippetsConfiguration); const sdkIds: string[] = []; - const sdkRequests: SdkRequest[] = []; if (snippetsConfigurationWithSdkIds.typescriptSdk != null) { sdkIds.push(snippetsConfigurationWithSdkIds.typescriptSdk.sdkId); - sdkRequests.push({ - type: "typescript", - package: snippetsConfigurationWithSdkIds.typescriptSdk.package, - version: snippetsConfigurationWithSdkIds.typescriptSdk.version, - }); } if (snippetsConfigurationWithSdkIds.pythonSdk != null) { sdkIds.push(snippetsConfigurationWithSdkIds.pythonSdk.sdkId); - sdkRequests.push({ - type: "python", - package: snippetsConfigurationWithSdkIds.pythonSdk.package, - version: snippetsConfigurationWithSdkIds.pythonSdk.version, - }); } if (snippetsConfigurationWithSdkIds.javaSdk != null) { sdkIds.push(snippetsConfigurationWithSdkIds.javaSdk.sdkId); - const coordinate = snippetsConfigurationWithSdkIds.javaSdk.coordinate; - const [group, artifact] = coordinate.split(":"); - if (group == null || artifact == null) { - throw new Error( - `Invalid coordinate for Java SDK: ${coordinate}. Must be in the format group:artifact`, - ); - } - sdkRequests.push({ - type: "java", - group, - artifact, - version: snippetsConfigurationWithSdkIds.javaSdk.version, - }); } if (snippetsConfigurationWithSdkIds.goSdk != null) { sdkIds.push(snippetsConfigurationWithSdkIds.goSdk.sdkId); - sdkRequests.push({ - type: "go", - githubRepo: snippetsConfigurationWithSdkIds.goSdk.githubRepo, - version: snippetsConfigurationWithSdkIds.goSdk.version, - }); } if (snippetsConfigurationWithSdkIds.rubySdk != null) { sdkIds.push(snippetsConfigurationWithSdkIds.rubySdk.sdkId); - sdkRequests.push({ - type: "ruby", - gem: snippetsConfigurationWithSdkIds.rubySdk.gem, - version: snippetsConfigurationWithSdkIds.rubySdk.version, - }); } const snippetsBySdkId = await app.dao.snippets().loadAllSnippetsForSdkIds(sdkIds); - const snippetTemplatesByEndpoint = await app.dao.snippetTemplates().loadSnippetTemplatesByEndpoint({ + const snippetTemplatesByEndpoint = await getSnippetTemplatesIfEnabled({ + app, + authorization: req.headers.authorization, orgId: req.body.orgId, apiId: req.body.apiId, - sdkRequests, definition: req.body.definition, + snippetsConfigurationWithSdkIds, }); const apiDefinitionId = uuidv4(); const snippetHolder = new SDKSnippetHolder({ @@ -109,3 +80,84 @@ export function getRegisterApiService(app: FdrApplication): APIV1WriteService { }, }); } + +async function getSnippetTemplatesIfEnabled({ + app, + authorization, + orgId, + apiId, + definition, + snippetsConfigurationWithSdkIds, +}: { + app: FdrApplication; + authorization: string | undefined; + orgId: string; + apiId: string; + definition: APIV1Write.ApiDefinition; + snippetsConfigurationWithSdkIds: SdkIdForPackage; +}): Promise { + try { + const hasSnippetTemplatesAccess = await app.services.auth.checkOrgHasSnippetsApiAccess({ + authHeader: authorization, + orgId, + failHard: false, + }); + let snippetTemplatesByEndpoint: SnippetTemplatesByEndpoint = {}; + if (hasSnippetTemplatesAccess) { + const sdkRequests: SdkRequest[] = []; + if (snippetsConfigurationWithSdkIds.typescriptSdk != null) { + sdkRequests.push({ + type: "typescript", + package: snippetsConfigurationWithSdkIds.typescriptSdk.package, + version: snippetsConfigurationWithSdkIds.typescriptSdk.version, + }); + } + if (snippetsConfigurationWithSdkIds.pythonSdk != null) { + sdkRequests.push({ + type: "python", + package: snippetsConfigurationWithSdkIds.pythonSdk.package, + version: snippetsConfigurationWithSdkIds.pythonSdk.version, + }); + } + if (snippetsConfigurationWithSdkIds.javaSdk != null) { + const coordinate = snippetsConfigurationWithSdkIds.javaSdk.coordinate; + const [group, artifact] = coordinate.split(":"); + if (group == null || artifact == null) { + throw new Error( + `Invalid coordinate for Java SDK: ${coordinate}. Must be in the format group:artifact`, + ); + } + sdkRequests.push({ + type: "java", + group, + artifact, + version: snippetsConfigurationWithSdkIds.javaSdk.version, + }); + } + if (snippetsConfigurationWithSdkIds.goSdk != null) { + sdkRequests.push({ + type: "go", + githubRepo: snippetsConfigurationWithSdkIds.goSdk.githubRepo, + version: snippetsConfigurationWithSdkIds.goSdk.version, + }); + } + if (snippetsConfigurationWithSdkIds.rubySdk != null) { + sdkRequests.push({ + type: "ruby", + gem: snippetsConfigurationWithSdkIds.rubySdk.gem, + version: snippetsConfigurationWithSdkIds.rubySdk.version, + }); + } + snippetTemplatesByEndpoint = await app.dao.snippetTemplates().loadSnippetTemplatesByEndpoint({ + orgId, + apiId, + sdkRequests, + definition, + }); + } + return snippetTemplatesByEndpoint; + } catch (e) { + LOGGER.error("Failed to load snippet templates", e); + return {}; + } +} diff --git a/servers/fdr/src/db/snippets/SnippetTemplate.ts b/servers/fdr/src/db/snippets/SnippetTemplate.ts index e5a934e32a..40f87014fb 100644 --- a/servers/fdr/src/db/snippets/SnippetTemplate.ts +++ b/servers/fdr/src/db/snippets/SnippetTemplate.ts @@ -29,6 +29,11 @@ export interface LoadSnippetAPIsRequest { apiName: string | undefined; } +export type SnippetTemplatesByEndpoint = Record< + FdrAPI.EndpointPath, + Record +>; + export interface SnippetTemplateDao { loadSnippetTemplate({ loadSnippetTemplateRequest, @@ -41,7 +46,7 @@ export interface SnippetTemplateDao { apiId: FdrAPI.ApiId; sdkRequests: SdkRequest[]; definition: APIV1Write.ApiDefinition; - }): Promise>>; + }): Promise; storeSnippetTemplate({ storeSnippetsInfo,