From 040ea58ba9ce2a555105d468605fb77c096f266b Mon Sep 17 00:00:00 2001 From: saeedjamshaid Date: Wed, 6 May 2026 12:22:44 +0500 Subject: [PATCH 1/9] feat: add container and input models in toc using new toc command --- src/actions/portal/toc/new-toc.ts | 11 ++++- .../portal/toc/toc-structure-generator.ts | 16 ++++++-- src/types/sdl/sdl.ts | 40 ++++++++++++++++++- src/types/toc/toc.ts | 13 ++++++ 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/actions/portal/toc/new-toc.ts b/src/actions/portal/toc/new-toc.ts index dfe01f8d..f697c606 100644 --- a/src/actions/portal/toc/new-toc.ts +++ b/src/actions/portal/toc/new-toc.ts @@ -9,7 +9,9 @@ import { FileService } from '../../../infrastructure/file-service.js'; import { BuildContext } from '../../../types/build-context.js'; import { extractCallbacksForToc, + extractContainerModelsForToc, extractEndpointGroupsForToc, + extractInputModelsForToc, extractModelsForToc, extractWebhooksForToc, SdlTocComponents @@ -71,6 +73,8 @@ export class PortalNewTocAction { const defaultComponents = { endpointGroups: new Map(), models: [], + containerModels: [], + inputModels : [], webhookGroups: new Map(), callbackGroups: new Map() }; @@ -102,6 +106,8 @@ export class PortalNewTocAction { return { endpointGroups: extractEndpointGroupsForToc(result.value), models: extractModelsForToc(result.value), + containerModels : extractContainerModelsForToc(result.value), + inputModels : extractInputModelsForToc(result.value), webhookGroups: extractWebhooksForToc(result.value), callbackGroups: extractCallbacksForToc(result.value) }; @@ -120,7 +126,10 @@ export class PortalNewTocAction { const toc = this.tocGenerator.createTocStructure( { data: sdlTocComponents.endpointGroups, expand: expandEndpoints }, - { data: sdlTocComponents.models, expand: expandModels }, + { modelsData: sdlTocComponents.models, + containerModelsData: sdlTocComponents.containerModels, + inputModelsData: sdlTocComponents.inputModels, expand: expandModels + }, { data: sdlTocComponents.webhookGroups, expand: expandWebhooks }, { data: sdlTocComponents.callbackGroups, expand: expandCallbacks }, contentGroups diff --git a/src/application/portal/toc/toc-structure-generator.ts b/src/application/portal/toc/toc-structure-generator.ts index cc497eec..a90baec4 100644 --- a/src/application/portal/toc/toc-structure-generator.ts +++ b/src/application/portal/toc/toc-structure-generator.ts @@ -7,7 +7,9 @@ import { TocGenerated, TocCallbackPage, TocWebhookPage, - TocEndpoint + TocEndpoint, + TocInputModelPage, + TocContainerModelPage } from '../../../types/toc/toc.js'; // TODO: Refactor @@ -28,7 +30,9 @@ type Callbacks = { }; type Models = { - data: TocModelPage[]; + modelsData: TocModelPage[]; + containerModelsData: TocContainerModelPage[]; + inputModelsData : TocInputModelPage[]; expand: boolean; }; @@ -166,7 +170,7 @@ export class TocStructureGenerator { } private getModelsSection(models: Models): (TocGroup | TocGenerated)[] { - if (models.data.length === 0) { + if (models.modelsData.length === 0 && models.containerModelsData.length === 0 && models.inputModelsData.length === 0) { return []; } if (!models.expand) { @@ -180,7 +184,11 @@ export class TocStructureGenerator { return [ { group: 'Models', - items: models.data + items: [ + ...models.modelsData, + ...models.containerModelsData, + ...models.inputModelsData + ] } ]; } diff --git a/src/types/sdl/sdl.ts b/src/types/sdl/sdl.ts index 528397d7..81df9ddf 100644 --- a/src/types/sdl/sdl.ts +++ b/src/types/sdl/sdl.ts @@ -1,4 +1,4 @@ -import { TocEndpoint, TocModelPage, TocCallback, TocWebhook, TocWebhookPage, TocCallbackPage } from '../toc/toc.js'; +import { TocEndpoint, TocModelPage, TocCallback, TocWebhook, TocWebhookPage, TocCallbackPage, TocContainerModelPage, TocInputModelPage } from '../toc/toc.js'; import { toTitleCase } from '../../utils/string-utils.js'; export type EndpointGroup = Map; @@ -8,6 +8,8 @@ export type CallbackGroup = Map; export type SdlTocComponents = { endpointGroups: EndpointGroup; models: TocModelPage[]; + containerModels: TocContainerModelPage[]; + inputModels : TocInputModelPage[]; webhookGroups: WebhookGroup; callbackGroups: CallbackGroup; }; @@ -16,6 +18,12 @@ export interface Sdl { readonly Endpoints: SdlEndpoint[]; readonly CustomTypes: SdlModel[]; readonly Webhooks: SdlWebhook[]; + readonly CodeGenSettings : SdlCodeGenSettings; + readonly GlobalTypeCombinators: Map; +} + +export interface SdlCodeGenSettings { + readonly CollapseParamsToArray: boolean; } export interface SdlEndpoint { @@ -23,6 +31,12 @@ export interface SdlEndpoint { readonly Description: string; readonly Group: string; readonly Callbacks: SdlCallback[]; + readonly Parameters: SdlParameter[]; + readonly CollectParameters: boolean; +} + +export interface SdlParameter { + readonly Constant: boolean; } export interface SdlModel { @@ -58,7 +72,9 @@ export function getEndpointGroupsFromSdl(sdl: Sdl): Map { Name: endpoint.Name, Description: endpoint.Description, Group: endpoint.Group, - Callbacks: endpoint.Callbacks + Callbacks: endpoint.Callbacks, + Parameters: endpoint.Parameters, + CollectParameters: endpoint.CollectParameters }); } return endpointGroups; @@ -97,6 +113,26 @@ export function extractModelsForToc(sdl: Sdl): TocModelPage[] { ); } +export function extractContainerModelsForToc(sdl: Sdl): TocContainerModelPage[] { + return Array.from(sdl.GlobalTypeCombinators.keys()).map(key => ({ + generate: null, + from: 'container-model', + containerName: key + })); +} + +export function extractInputModelsForToc(sdl: Sdl): TocInputModelPage[] { + const collapseParamsToArray = sdl.CodeGenSettings.CollapseParamsToArray; + return sdl.Endpoints.filter(x => (collapseParamsToArray || x.CollectParameters) && x.Parameters.filter(p => !p.Constant).length > 1).map( + (e: SdlEndpoint): TocInputModelPage => ({ + generate: null, + from: 'input-model', + endpointName: e.Name, + endpointGroup: e.Group + }) + ); +} + export function extractWebhooksForToc(sdl: Sdl): Map { if (sdl.Webhooks.length === 0) { return new Map(); diff --git a/src/types/toc/toc.ts b/src/types/toc/toc.ts index f20127d7..7154a282 100644 --- a/src/types/toc/toc.ts +++ b/src/types/toc/toc.ts @@ -37,6 +37,19 @@ export interface TocModelPage { readonly modelName: string; } +export interface TocContainerModelPage { + readonly generate: null; + readonly from: 'container-model'; + readonly containerName: string; +} + +export interface TocInputModelPage { + readonly generate: null; + readonly from: 'input-model'; + readonly endpointName: string; + readonly endpointGroup: string; +} + export interface TocWebhookOverview { readonly generate: null; readonly from: 'webhook-group-overview'; From 5ead88363a2e711d83a10e58315c7ab2a650e280 Mon Sep 17 00:00:00 2001 From: Ali Asghar <75574550+aliasghar98@users.noreply.github.com> Date: Thu, 7 May 2026 11:00:20 +0500 Subject: [PATCH 2/9] feat: migrate from transformed sdl to generate toc-data --- src/actions/portal/toc/new-toc.ts | 30 +-- src/infrastructure/services/portal-service.ts | 29 +++ src/prompts/portal/toc/new-toc.ts | 8 +- src/types/sdl/sdl.ts | 196 +----------------- src/types/toc/toc-data.ts | 139 +++++++++++++ 5 files changed, 190 insertions(+), 212 deletions(-) create mode 100644 src/types/toc/toc-data.ts diff --git a/src/actions/portal/toc/new-toc.ts b/src/actions/portal/toc/new-toc.ts index f697c606..1ee0d9e7 100644 --- a/src/actions/portal/toc/new-toc.ts +++ b/src/actions/portal/toc/new-toc.ts @@ -14,8 +14,8 @@ import { extractInputModelsForToc, extractModelsForToc, extractWebhooksForToc, - SdlTocComponents -} from '../../../types/sdl/sdl.js'; + TocComponents +} from '../../../types/toc/toc-data.js'; import { withDirPath } from '../../../infrastructure/tmp-extensions.js'; import { TempContext } from '../../../types/temp-context.js'; import { PortalService } from '../../../infrastructure/services/portal-service.js'; @@ -69,12 +69,12 @@ export class PortalNewTocAction { return ActionResult.cancelled(); } - const sdlTocComponents: SdlTocComponents = await (async () => { + const tocComponents: TocComponents = await (async () => { const defaultComponents = { endpointGroups: new Map(), models: [], containerModels: [], - inputModels : [], + inputModels: [], webhookGroups: new Map(), callbackGroups: new Map() }; @@ -90,8 +90,8 @@ export class PortalNewTocAction { const tempContext = new TempContext(tempDirectory); const specZipPath = await tempContext.zip(specDirectory); const specFileStream = await this.fileService.getStream(specZipPath); - const result = await this.prompts.extractComponents( - this.portalService.generateSdl(specFileStream, this.configDirectory, this.commandMetadata), + const result = await this.prompts.extractTocData( + this.portalService.generateTocData(specFileStream, this.configDirectory, this.commandMetadata), expandEndpoints, expandModels, expandWebhooks, @@ -106,8 +106,8 @@ export class PortalNewTocAction { return { endpointGroups: extractEndpointGroupsForToc(result.value), models: extractModelsForToc(result.value), - containerModels : extractContainerModelsForToc(result.value), - inputModels : extractInputModelsForToc(result.value), + containerModels: extractContainerModelsForToc(result.value), + inputModels: extractInputModelsForToc(result.value), webhookGroups: extractWebhooksForToc(result.value), callbackGroups: extractCallbacksForToc(result.value) }; @@ -125,13 +125,15 @@ export class PortalNewTocAction { } const toc = this.tocGenerator.createTocStructure( - { data: sdlTocComponents.endpointGroups, expand: expandEndpoints }, - { modelsData: sdlTocComponents.models, - containerModelsData: sdlTocComponents.containerModels, - inputModelsData: sdlTocComponents.inputModels, expand: expandModels + { data: tocComponents.endpointGroups, expand: expandEndpoints }, + { + modelsData: tocComponents.models, + containerModelsData: tocComponents.containerModels, + inputModelsData: tocComponents.inputModels, + expand: expandModels }, - { data: sdlTocComponents.webhookGroups, expand: expandWebhooks }, - { data: sdlTocComponents.callbackGroups, expand: expandCallbacks }, + { data: tocComponents.webhookGroups, expand: expandWebhooks }, + { data: tocComponents.callbackGroups, expand: expandCallbacks }, contentGroups ); const yamlString = this.tocGenerator.transformToYaml(toc); diff --git a/src/infrastructure/services/portal-service.ts b/src/infrastructure/services/portal-service.ts index a64533a5..b98f1bc7 100644 --- a/src/infrastructure/services/portal-service.ts +++ b/src/infrastructure/services/portal-service.ts @@ -28,6 +28,7 @@ import { Language } from "../../types/sdk/generate.js"; import { handleServiceError, ServiceError } from "../service-error.js"; import { ApiService } from "./api-service.js"; import { SemVersion } from "../../types/publish/version.js"; +import { TocData } from "../../types/toc/toc-data.js"; export interface GeneratedSdkResult { sdk: NodeJS.ReadableStream; @@ -258,6 +259,34 @@ export class PortalService { } } + public async generateTocData( + specFileStream: ReadStream, + configDir: DirectoryPath, + commandMetadata: CommandMetadata + ): Promise> { + const file = new FileWrapper(specFileStream); + const authInfo: AuthInfo | null = await getAuthInfo(configDir.toString()); + const authorizationHeader = this.createAuthorizationHeader(authInfo, null); + const client = apiClientFactory.createApiClient(authorizationHeader, commandMetadata.shell); + const transformationController = new TransformationController(client); + + try { + const response = await transformationController.transformToApiMaticFormat( + ContentType.EnumMultipartformdata, + file, + this.createOriginQueryParameter(commandMetadata.commandName) + ); + + if ((response.result as NodeJS.ReadableStream).readable) { + return ok((await parseStreamBodyToJson(response.result as NodeJS.ReadableStream)) as TocData); + } else { + return err(ServiceError.InvalidResponse); + } + } catch (error) { + return err(handleServiceError(error)); + } + } + private createAuthorizationHeader = (authInfo: AuthInfo | null, overrideAuthKey: string | null): string => { const key = overrideAuthKey || authInfo?.authKey; return `X-Auth-Key ${key ?? ""}`; diff --git a/src/prompts/portal/toc/new-toc.ts b/src/prompts/portal/toc/new-toc.ts index 8f668429..57b0a123 100644 --- a/src/prompts/portal/toc/new-toc.ts +++ b/src/prompts/portal/toc/new-toc.ts @@ -4,8 +4,8 @@ import { Result } from "neverthrow"; import { format as f } from "../../format.js"; import { DirectoryPath } from "../../../types/file/directoryPath.js"; import { ServiceError } from "../../../infrastructure/service-error.js"; -import { Sdl } from "../../../types/sdl/sdl.js"; import { withSpinner } from "../../prompt.js"; +import { TocData } from "../../../types/toc/toc-data.js"; export class PortalNewTocPrompts { public async overwriteToc(tocPath: FilePath): Promise { @@ -42,13 +42,13 @@ export class PortalNewTocPrompts { log.error(message); } - public extractComponents( - fn: Promise>, + public extractTocData( + fn: Promise>, expandEndpoints: boolean, expandModels: boolean, expandWebhooks: boolean, expandCallbacks: boolean - ): Promise> { + ): Promise> { const components = [ expandEndpoints && "Endpoint groups", expandModels && "Models", diff --git a/src/types/sdl/sdl.ts b/src/types/sdl/sdl.ts index 81df9ddf..91d469d2 100644 --- a/src/types/sdl/sdl.ts +++ b/src/types/sdl/sdl.ts @@ -1,24 +1,8 @@ -import { TocEndpoint, TocModelPage, TocCallback, TocWebhook, TocWebhookPage, TocCallbackPage, TocContainerModelPage, TocInputModelPage } from '../toc/toc.js'; -import { toTitleCase } from '../../utils/string-utils.js'; - -export type EndpointGroup = Map; -export type WebhookGroup = Map; -export type CallbackGroup = Map; - -export type SdlTocComponents = { - endpointGroups: EndpointGroup; - models: TocModelPage[]; - containerModels: TocContainerModelPage[]; - inputModels : TocInputModelPage[]; - webhookGroups: WebhookGroup; - callbackGroups: CallbackGroup; -}; - export interface Sdl { readonly Endpoints: SdlEndpoint[]; readonly CustomTypes: SdlModel[]; readonly Webhooks: SdlWebhook[]; - readonly CodeGenSettings : SdlCodeGenSettings; + readonly CodeGenSettings: SdlCodeGenSettings; readonly GlobalTypeCombinators: Map; } @@ -41,6 +25,7 @@ export interface SdlParameter { export interface SdlModel { readonly Name: string; + readonly ImplementationType: string; } export interface SdlCallback { @@ -79,180 +64,3 @@ export function getEndpointGroupsFromSdl(sdl: Sdl): Map { } return endpointGroups; } - -export function extractEndpointGroupsForToc(sdl: Sdl): Map { - const endpointGroups = new Map(); - - const endpoints = sdl.Endpoints.map( - (e: SdlEndpoint): TocEndpoint => ({ - generate: null, - from: 'endpoint', - endpointName: e.Name, - endpointGroup: e.Group - }) - ); - - endpoints.forEach((endpoint: TocEndpoint) => { - const group = endpoint.endpointGroup; - if (!endpointGroups.has(group)) { - endpointGroups.set(group, []); - } - endpointGroups.get(group)!.push(endpoint); - }); - - return endpointGroups; -} - -export function extractModelsForToc(sdl: Sdl): TocModelPage[] { - return sdl.CustomTypes.map( - (e: SdlModel): TocModelPage => ({ - generate: null, - from: 'model', - modelName: e.Name - }) - ); -} - -export function extractContainerModelsForToc(sdl: Sdl): TocContainerModelPage[] { - return Array.from(sdl.GlobalTypeCombinators.keys()).map(key => ({ - generate: null, - from: 'container-model', - containerName: key - })); -} - -export function extractInputModelsForToc(sdl: Sdl): TocInputModelPage[] { - const collapseParamsToArray = sdl.CodeGenSettings.CollapseParamsToArray; - return sdl.Endpoints.filter(x => (collapseParamsToArray || x.CollectParameters) && x.Parameters.filter(p => !p.Constant).length > 1).map( - (e: SdlEndpoint): TocInputModelPage => ({ - generate: null, - from: 'input-model', - endpointName: e.Name, - endpointGroup: e.Group - }) - ); -} - -export function extractWebhooksForToc(sdl: Sdl): Map { - if (sdl.Webhooks.length === 0) { - return new Map(); - } - - let groupedWebhooks = new Map(); - const ungrouped: TocWebhook[] = []; - - for (const webhook of sdl.Webhooks) { - const event: TocWebhook = { - generate: null, - from: 'webhook', - webhookName: webhook.Id, - webhookGroup: webhook.WebhookGroupName ?? null - }; - - if (webhook.WebhookGroupName) { - const groupTitle = toTitleCase(webhook.WebhookGroupName); - if (!groupedWebhooks.has(groupTitle)) { - groupedWebhooks.set(groupTitle, [ - { - generate: null, - from: 'webhook-group-overview', - webhookGroup: webhook.WebhookGroupName - } - ]); - } - groupedWebhooks.get(groupTitle)!.push(event); - } else { - ungrouped.push(event); - } - } - - let ungroupedWebhooks = new Map(); - - if (ungrouped.length > 0) { - const uniqueGroupName = getUniqueGroupName('Webhooks', new Set(groupedWebhooks.keys())); - const uniqueGroupTitle = toTitleCase(uniqueGroupName); - ungroupedWebhooks.set(uniqueGroupTitle, [ - { - generate: null, - from: 'webhook-group-overview', - webhookGroup: uniqueGroupName - }, - ...ungrouped.map( - (event): TocWebhook => ({ - ...event, - webhookGroup: uniqueGroupName - }) - ) - ]); - } - - return new Map([...[...groupedWebhooks].sort((a, b) => a[0].localeCompare(b[0])), ...ungroupedWebhooks]); -} - -export function extractCallbacksForToc(sdl: Sdl): Map { - if (sdl.Endpoints.length === 0) { - return new Map(); - } - - let groupedCallbacks = new Map(); - const ungrouped: TocCallback[] = []; - - for (const callback of sdl.Endpoints.flatMap((e) => e.Callbacks)) { - const event: TocCallback = { - generate: null, - from: 'callback', - callbackName: callback.Id, - callbackGroup: callback.CallbackGroupName ?? null - }; - - if (callback.CallbackGroupName) { - const groupTitle = toTitleCase(callback.CallbackGroupName); - if (!groupedCallbacks.has(groupTitle)) { - groupedCallbacks.set(groupTitle, [ - { - generate: null, - from: 'callback-group-overview', - callbackGroup: callback.CallbackGroupName - } - ]); - } - groupedCallbacks.get(groupTitle)!.push(event); - } else { - ungrouped.push(event); - } - } - - let ungroupedCallbacks = new Map(); - - if (ungrouped.length > 0) { - const uniqueGroupName = getUniqueGroupName('Callbacks', new Set(groupedCallbacks.keys())); - const uniqueGroupTitle = toTitleCase(uniqueGroupName); - ungroupedCallbacks.set(uniqueGroupTitle, [ - { - generate: null, - from: 'callback-group-overview', - callbackGroup: uniqueGroupName - }, - ...ungrouped.map( - (event): TocCallback => ({ - ...event, - callbackGroup: uniqueGroupName - }) - ) - ]); - } - - return new Map([...[...groupedCallbacks].sort((a, b) => a[0].localeCompare(b[0])), ...ungroupedCallbacks]); -} - -function getUniqueGroupName(baseName: string, existingGroups: Set): string { - let counter = 1; - let name = baseName; - - while (existingGroups.has(toTitleCase(name))) { - name = `${baseName}${counter}`; - counter++; - } - - return name; -} diff --git a/src/types/toc/toc-data.ts b/src/types/toc/toc-data.ts new file mode 100644 index 00000000..50214ae3 --- /dev/null +++ b/src/types/toc/toc-data.ts @@ -0,0 +1,139 @@ +import { + TocEndpoint, + TocModelPage, + TocCallback, + TocWebhook, + TocWebhookPage, + TocCallbackPage, + TocContainerModelPage, + TocInputModelPage +} from './toc.js'; +import { toTitleCase } from '../../utils/string-utils.js'; + +export interface InputModel { + readonly name: string; + readonly group: string; +} + +export interface TocData { + readonly endpoints: Record; + readonly models: string[]; + readonly enums: string[]; + readonly errors: string[]; + readonly webhooks: Record; + readonly callbacks: Record; + readonly containers: string[]; + readonly inputModels: InputModel[]; +} + +export type EndpointGroup = Map; +export type WebhookGroup = Map; +export type CallbackGroup = Map; + +export type TocComponents = { + endpointGroups: EndpointGroup; + models: TocModelPage[]; + containerModels: TocContainerModelPage[]; + inputModels: TocInputModelPage[]; + webhookGroups: WebhookGroup; + callbackGroups: CallbackGroup; +}; + +export function extractEndpointGroupsForToc(tocData: TocData): Map { + const endpointGroups = new Map(); + + for (const group in tocData.endpoints) { + const endpoints = tocData.endpoints[group].map( + (name: string): TocEndpoint => ({ + generate: null, + from: 'endpoint', + endpointName: name, + endpointGroup: group + }) + ); + endpointGroups.set(group, endpoints); + } + + return endpointGroups; +} + +export function extractModelsForToc(tocData: TocData): TocModelPage[] { + return tocData.models.map( + (name: string): TocModelPage => ({ + generate: null, + from: 'model', + modelName: name + }) + ); +} + +export function extractContainerModelsForToc(tocData: TocData): TocContainerModelPage[] { + return tocData.containers.map( + (name: string): TocContainerModelPage => ({ + generate: null, + from: 'container-model', + containerName: name + }) + ); +} + +export function extractInputModelsForToc(tocData: TocData): TocInputModelPage[] { + return tocData.inputModels.map( + (m: InputModel): TocInputModelPage => ({ + generate: null, + from: 'input-model', + endpointName: m.name, + endpointGroup: m.group + }) + ); +} + +export function extractWebhooksForToc(tocData: TocData): Map { + const groupedWebhooks = new Map(); + + for (const group in tocData.webhooks) { + const groupTitle = toTitleCase(group); + groupedWebhooks.set(groupTitle, [ + { + generate: null, + from: 'webhook-group-overview', + webhookGroup: group + }, + ...tocData.webhooks[group].map( + (name: string): TocWebhook => ({ + generate: null, + from: 'webhook', + webhookName: name, + webhookGroup: group + }) + ) + ]); + } + + return new Map([...groupedWebhooks].sort((a, b) => a[0].localeCompare(b[0]))); +} + +export function extractCallbacksForToc(tocData: TocData): Map { + const groupedCallbacks = new Map(); + + for (const group in tocData.callbacks) { + const groupTitle = toTitleCase(group); + groupedCallbacks.set(groupTitle, [ + { + generate: null, + from: 'callback-group-overview', + callbackGroup: group + }, + ...tocData.callbacks[group].map( + (name: string): TocCallback => ({ + generate: null, + from: 'callback', + callbackName: name, + callbackGroup: group + }) + ) + ]); + } + + return new Map([...groupedCallbacks].sort((a, b) => a[0].localeCompare(b[0]))); +} From 448396fd58cf52faa1debb4e9db1474572729536 Mon Sep 17 00:00:00 2001 From: Ali Asghar <75574550+aliasghar98@users.noreply.github.com> Date: Thu, 7 May 2026 12:09:37 +0500 Subject: [PATCH 3/9] fix: update infra controller and minor messaging fix --- src/infrastructure/services/portal-service.ts | 5 +++-- src/prompts/portal/toc/new-toc.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/infrastructure/services/portal-service.ts b/src/infrastructure/services/portal-service.ts index b98f1bc7..8662c1be 100644 --- a/src/infrastructure/services/portal-service.ts +++ b/src/infrastructure/services/portal-service.ts @@ -13,6 +13,7 @@ import { ExportFormats, SdkLanguages, Status, + TableOfContentsController, } from "@apimatic/sdk"; import { AuthInfo, getAuthInfo } from "../../client-utils/auth-manager.js"; import { parseStreamBodyToJson } from "../../utils/utils.js"; @@ -268,10 +269,10 @@ export class PortalService { const authInfo: AuthInfo | null = await getAuthInfo(configDir.toString()); const authorizationHeader = this.createAuthorizationHeader(authInfo, null); const client = apiClientFactory.createApiClient(authorizationHeader, commandMetadata.shell); - const transformationController = new TransformationController(client); + const tableOfContentsController = new TableOfContentsController(client); try { - const response = await transformationController.transformToApiMaticFormat( + const response = await tableOfContentsController.generateTocData( ContentType.EnumMultipartformdata, file, this.createOriginQueryParameter(commandMetadata.commandName) diff --git a/src/prompts/portal/toc/new-toc.ts b/src/prompts/portal/toc/new-toc.ts index 57b0a123..83de1d83 100644 --- a/src/prompts/portal/toc/new-toc.ts +++ b/src/prompts/portal/toc/new-toc.ts @@ -58,7 +58,7 @@ export class PortalNewTocPrompts { .filter(Boolean) .join(" and "); - return withSpinner(`Extracting ${components}`, `${components} extracted`, `${components} extraction failed`, fn); + return withSpinner(`Extracting ${components}`, `${components} Extracted`, `${components} Extraction Failed`, fn); } public tocCreated(tocPath: FilePath) { From 2babf3d6b4146f765ba71494479b1306852a335b Mon Sep 17 00:00:00 2001 From: Ayeshas09 Date: Thu, 7 May 2026 15:17:44 +0500 Subject: [PATCH 4/9] feat(toc): add grouping in models for expand models flag --- package-lock.json | 26 ++++------------- package.json | 5 ++-- src/actions/portal/toc/new-toc.ts | 8 ++++++ .../portal/toc/toc-structure-generator.ts | 28 ++++++++++++++----- src/types/toc/toc-data.ts | 24 +++++++++++++++- src/types/toc/toc.ts | 2 +- 6 files changed, 62 insertions(+), 31 deletions(-) diff --git a/package-lock.json b/package-lock.json index de2a563d..e9cc09b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@apimatic/cli", - "version": "1.1.0-beta.11", + "version": "1.1.0-beta.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@apimatic/cli", - "version": "1.1.0-beta.11", + "version": "1.1.0-beta.14", "license": "MIT", "dependencies": { - "@apimatic/sdk": "0.2.0-alpha.8", + "@apimatic/sdk": "file:./apimatic-sdk-0.2.0-alpha.9-test.tgz", "@clack/prompts": "1.0.0-alpha.1", "@oclif/core": "^4.2.8", "@oclif/plugin-autocomplete": "^3.2.24", @@ -275,9 +275,9 @@ } }, "node_modules/@apimatic/sdk": { - "version": "0.2.0-alpha.8", - "resolved": "https://registry.npmjs.org/@apimatic/sdk/-/sdk-0.2.0-alpha.8.tgz", - "integrity": "sha512-W7ReyVMPq8+V40S+YeUQbw6J00ymkZYi88zrs1fj5RvynamMjalEabSUZ64VxpR1U1uIEABqVEFzzxG71UXnEA==", + "version": "0.2.0-alpha.9-test", + "resolved": "file:apimatic-sdk-0.2.0-alpha.9-test.tgz", + "integrity": "sha512-UzFfyMUoJsYqI2LOqgrO6+irei5DXygqJYuU89XVitIjJiqFE3epUeedR2mJuWJikqzW7Kuwya7Gg3sMZIRxXg==", "license": "MIT", "dependencies": { "@apimatic/authentication-adapters": "^0.5.14", @@ -1271,7 +1271,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -3912,7 +3911,6 @@ "resolved": "https://registry.npmjs.org/@oclif/core/-/core-4.10.3.tgz", "integrity": "sha512-0mD8vcrrX5uRsxzvI8tbWmSVGngvZA/Qo6O0ZGvLPAWEauSf5GFniwgirhY0SkszuHwu0S1J1ivj/jHmqtIDuA==", "license": "MIT", - "peer": true, "dependencies": { "ansi-escapes": "^4.3.2", "ansis": "^3.17.0", @@ -4031,7 +4029,6 @@ "integrity": "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@octokit/auth-token": "^5.0.0", "@octokit/graphql": "^8.2.2", @@ -5845,7 +5842,6 @@ "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -6016,7 +6012,6 @@ "integrity": "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", @@ -6246,7 +6241,6 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6839,7 +6833,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -7630,7 +7623,6 @@ "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", @@ -8143,7 +8135,6 @@ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -8534,7 +8525,6 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -14525,7 +14515,6 @@ "dev": true, "inBundle": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -16613,7 +16602,6 @@ "integrity": "sha512-qqJDBhbtHsjUEMsojWKGuL5lQFCJuPtiXKEIlFKyTzDDGTAE/oyvznaP8GeOr5PvcqBJ6LQz4JCENWPLeehSpA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@semantic-release/commit-analyzer": "^12.0.0", "@semantic-release/error": "^4.0.0", @@ -17933,7 +17921,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -18280,7 +18267,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 66ee18f6..5e85a72d 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "./bin", "./lib", "/npm-shrinkwrap.json", - "/oclif.manifest.json" + "/oclif.manifest.json", + "/apimatic-sdk-0.2.0-alpha.9-test.tgz" ], "repository": "git://github.com/apimatic/apimatic-cli.git", "homepage": "https://docs.apimatic.io/apimatic-cli/intro-and-install/", @@ -47,7 +48,7 @@ "test": "tsx node_modules/mocha/bin/_mocha --forbid-only \"test/**/*.test.ts\" --timeout 99999" }, "dependencies": { - "@apimatic/sdk": "0.2.0-alpha.8", + "@apimatic/sdk": "file:./apimatic-sdk-0.2.0-alpha.9-test.tgz", "@clack/prompts": "1.0.0-alpha.1", "@oclif/core": "^4.2.8", "@oclif/plugin-autocomplete": "^3.2.24", diff --git a/src/actions/portal/toc/new-toc.ts b/src/actions/portal/toc/new-toc.ts index 1ee0d9e7..7afbb304 100644 --- a/src/actions/portal/toc/new-toc.ts +++ b/src/actions/portal/toc/new-toc.ts @@ -11,6 +11,8 @@ import { extractCallbacksForToc, extractContainerModelsForToc, extractEndpointGroupsForToc, + extractEnumsForToc, + extractErrorsForToc, extractInputModelsForToc, extractModelsForToc, extractWebhooksForToc, @@ -73,6 +75,8 @@ export class PortalNewTocAction { const defaultComponents = { endpointGroups: new Map(), models: [], + enums: [], + errors: [], containerModels: [], inputModels: [], webhookGroups: new Map(), @@ -106,6 +110,8 @@ export class PortalNewTocAction { return { endpointGroups: extractEndpointGroupsForToc(result.value), models: extractModelsForToc(result.value), + enums: extractEnumsForToc(result.value), + errors: extractErrorsForToc(result.value), containerModels: extractContainerModelsForToc(result.value), inputModels: extractInputModelsForToc(result.value), webhookGroups: extractWebhooksForToc(result.value), @@ -128,6 +134,8 @@ export class PortalNewTocAction { { data: tocComponents.endpointGroups, expand: expandEndpoints }, { modelsData: tocComponents.models, + enumsData: tocComponents.enums, + errorsData: tocComponents.errors, containerModelsData: tocComponents.containerModels, inputModelsData: tocComponents.inputModels, expand: expandModels diff --git a/src/application/portal/toc/toc-structure-generator.ts b/src/application/portal/toc/toc-structure-generator.ts index a90baec4..5b7a2f94 100644 --- a/src/application/portal/toc/toc-structure-generator.ts +++ b/src/application/portal/toc/toc-structure-generator.ts @@ -32,7 +32,9 @@ type Callbacks = { type Models = { modelsData: TocModelPage[]; containerModelsData: TocContainerModelPage[]; - inputModelsData : TocInputModelPage[]; + enumsData: TocModelPage[]; + errorsData: TocModelPage[]; + inputModelsData: TocInputModelPage[]; expand: boolean; }; @@ -170,7 +172,13 @@ export class TocStructureGenerator { } private getModelsSection(models: Models): (TocGroup | TocGenerated)[] { - if (models.modelsData.length === 0 && models.containerModelsData.length === 0 && models.inputModelsData.length === 0) { + if ( + models.modelsData.length === 0 && + models.enumsData.length === 0 && + models.errorsData.length === 0 && + models.containerModelsData.length === 0 && + models.inputModelsData.length === 0 + ) { return []; } if (!models.expand) { @@ -181,14 +189,20 @@ export class TocStructureGenerator { } ]; } + const subGroups: TocGroup[] = [ + ...(models.modelsData.length > 0 || models.inputModelsData.length > 0 + ? [{ group: 'Structures', items: [...models.modelsData, ...models.inputModelsData] }] + : []), + ...(models.enumsData.length > 0 ? [{ group: 'Enumerations', items: models.enumsData }] : []), + ...(models.errorsData.length > 0 ? [{ group: 'Exceptions', items: models.errorsData }] : []), + ...(models.containerModelsData.length > 0 + ? [{ group: 'OneOf/AnyOf Definitions', items: models.containerModelsData }] + : []) + ]; return [ { group: 'Models', - items: [ - ...models.modelsData, - ...models.containerModelsData, - ...models.inputModelsData - ] + items: subGroups } ]; } diff --git a/src/types/toc/toc-data.ts b/src/types/toc/toc-data.ts index 50214ae3..3c9cc342 100644 --- a/src/types/toc/toc-data.ts +++ b/src/types/toc/toc-data.ts @@ -33,6 +33,8 @@ export type CallbackGroup = Map; export type TocComponents = { endpointGroups: EndpointGroup; models: TocModelPage[]; + enums: TocModelPage[]; + errors: TocModelPage[]; containerModels: TocContainerModelPage[]; inputModels: TocInputModelPage[]; webhookGroups: WebhookGroup; @@ -67,11 +69,31 @@ export function extractModelsForToc(tocData: TocData): TocModelPage[] { ); } +export function extractEnumsForToc(tocData: TocData): TocModelPage[] { + return tocData.enums.map( + (name: string): TocModelPage => ({ + generate: null, + from: 'model', + modelName: name + }) + ); +} + +export function extractErrorsForToc(tocData: TocData): TocModelPage[] { + return tocData.errors.map( + (name: string): TocModelPage => ({ + generate: null, + from: 'model', + modelName: name + }) + ); +} + export function extractContainerModelsForToc(tocData: TocData): TocContainerModelPage[] { return tocData.containers.map( (name: string): TocContainerModelPage => ({ generate: null, - from: 'container-model', + from: 'container', containerName: name }) ); diff --git a/src/types/toc/toc.ts b/src/types/toc/toc.ts index 7154a282..2d300ec6 100644 --- a/src/types/toc/toc.ts +++ b/src/types/toc/toc.ts @@ -39,7 +39,7 @@ export interface TocModelPage { export interface TocContainerModelPage { readonly generate: null; - readonly from: 'container-model'; + readonly from: 'container'; readonly containerName: string; } From 293e7a686e3cd481d830bcac527c9cddbe652772 Mon Sep 17 00:00:00 2001 From: Ayeshas09 Date: Thu, 7 May 2026 16:23:47 +0500 Subject: [PATCH 5/9] resolve PR comments --- src/prompts/portal/toc/new-toc.ts | 4 ++-- src/types/sdl/sdl.ts | 17 +---------------- src/types/toc/toc-data.ts | 12 ++++++------ 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/prompts/portal/toc/new-toc.ts b/src/prompts/portal/toc/new-toc.ts index 83de1d83..d9f61040 100644 --- a/src/prompts/portal/toc/new-toc.ts +++ b/src/prompts/portal/toc/new-toc.ts @@ -56,9 +56,9 @@ export class PortalNewTocPrompts { expandCallbacks && "Callbacks" ] .filter(Boolean) - .join(" and "); + .join(" and ") || "TOC data"; - return withSpinner(`Extracting ${components}`, `${components} Extracted`, `${components} Extraction Failed`, fn); + return withSpinner(`Extracting ${components}`, `${components} extracted`, `${components} extraction Failed`, fn); } public tocCreated(tocPath: FilePath) { diff --git a/src/types/sdl/sdl.ts b/src/types/sdl/sdl.ts index 91d469d2..ee4550cb 100644 --- a/src/types/sdl/sdl.ts +++ b/src/types/sdl/sdl.ts @@ -2,12 +2,6 @@ export interface Sdl { readonly Endpoints: SdlEndpoint[]; readonly CustomTypes: SdlModel[]; readonly Webhooks: SdlWebhook[]; - readonly CodeGenSettings: SdlCodeGenSettings; - readonly GlobalTypeCombinators: Map; -} - -export interface SdlCodeGenSettings { - readonly CollapseParamsToArray: boolean; } export interface SdlEndpoint { @@ -15,17 +9,10 @@ export interface SdlEndpoint { readonly Description: string; readonly Group: string; readonly Callbacks: SdlCallback[]; - readonly Parameters: SdlParameter[]; - readonly CollectParameters: boolean; -} - -export interface SdlParameter { - readonly Constant: boolean; } export interface SdlModel { readonly Name: string; - readonly ImplementationType: string; } export interface SdlCallback { @@ -57,9 +44,7 @@ export function getEndpointGroupsFromSdl(sdl: Sdl): Map { Name: endpoint.Name, Description: endpoint.Description, Group: endpoint.Group, - Callbacks: endpoint.Callbacks, - Parameters: endpoint.Parameters, - CollectParameters: endpoint.CollectParameters + Callbacks: endpoint.Callbacks }); } return endpointGroups; diff --git a/src/types/toc/toc-data.ts b/src/types/toc/toc-data.ts index 3c9cc342..d3b3b929 100644 --- a/src/types/toc/toc-data.ts +++ b/src/types/toc/toc-data.ts @@ -44,8 +44,8 @@ export type TocComponents = { export function extractEndpointGroupsForToc(tocData: TocData): Map { const endpointGroups = new Map(); - for (const group in tocData.endpoints) { - const endpoints = tocData.endpoints[group].map( + for (const [group, names] of Object.entries(tocData.endpoints)) { + const endpoints = names.map( (name: string): TocEndpoint => ({ generate: null, from: 'endpoint', @@ -113,7 +113,7 @@ export function extractInputModelsForToc(tocData: TocData): TocInputModelPage[] export function extractWebhooksForToc(tocData: TocData): Map { const groupedWebhooks = new Map(); - for (const group in tocData.webhooks) { + for (const [group, names] of Object.entries(tocData.webhooks)) { const groupTitle = toTitleCase(group); groupedWebhooks.set(groupTitle, [ { @@ -121,7 +121,7 @@ export function extractWebhooksForToc(tocData: TocData): Map ({ generate: null, from: 'webhook', @@ -138,7 +138,7 @@ export function extractWebhooksForToc(tocData: TocData): Map { const groupedCallbacks = new Map(); - for (const group in tocData.callbacks) { + for (const [group, names] of Object.entries(tocData.callbacks)) { const groupTitle = toTitleCase(group); groupedCallbacks.set(groupTitle, [ { @@ -146,7 +146,7 @@ export function extractCallbacksForToc(tocData: TocData): Map ({ generate: null, from: 'callback', From 5889d0e19b6e6c067e835d5a8b1f4e5865ee656e Mon Sep 17 00:00:00 2001 From: Ayeshas09 Date: Thu, 7 May 2026 16:43:39 +0500 Subject: [PATCH 6/9] refactor: remove unused interfaces --- src/types/sdl/sdl.ts | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/types/sdl/sdl.ts b/src/types/sdl/sdl.ts index ee4550cb..948a7bb0 100644 --- a/src/types/sdl/sdl.ts +++ b/src/types/sdl/sdl.ts @@ -1,28 +1,11 @@ export interface Sdl { readonly Endpoints: SdlEndpoint[]; - readonly CustomTypes: SdlModel[]; - readonly Webhooks: SdlWebhook[]; } export interface SdlEndpoint { readonly Name: string; readonly Description: string; readonly Group: string; - readonly Callbacks: SdlCallback[]; -} - -export interface SdlModel { - readonly Name: string; -} - -export interface SdlCallback { - readonly Id: string; - readonly CallbackGroupName?: string; -} - -export interface SdlWebhook { - readonly Id: string; - readonly WebhookGroupName?: string; } export function getEndpointDescription( @@ -43,8 +26,7 @@ export function getEndpointGroupsFromSdl(sdl: Sdl): Map { endpointGroups.get(endpoint.Group)!.push({ Name: endpoint.Name, Description: endpoint.Description, - Group: endpoint.Group, - Callbacks: endpoint.Callbacks + Group: endpoint.Group }); } return endpointGroups; From d730b741edd5fd7fdd4cc67f00cc5cba58fe90b6 Mon Sep 17 00:00:00 2001 From: Ayeshas09 Date: Thu, 7 May 2026 18:22:17 +0500 Subject: [PATCH 7/9] refactor: resolve PR feedback --- src/actions/portal/toc/new-toc.ts | 52 +----- .../portal/toc/toc-structure-generator.ts | 143 +++++++------- src/infrastructure/services/portal-service.ts | 2 +- src/prompts/portal/toc/new-toc.ts | 2 +- src/types/toc/toc-components.ts | 175 ++++++++++++++++++ src/types/toc/toc-data.ts | 161 ---------------- src/utils/string-utils.ts | 47 ----- 7 files changed, 251 insertions(+), 331 deletions(-) create mode 100644 src/types/toc/toc-components.ts delete mode 100644 src/types/toc/toc-data.ts diff --git a/src/actions/portal/toc/new-toc.ts b/src/actions/portal/toc/new-toc.ts index 7afbb304..d7532a75 100644 --- a/src/actions/portal/toc/new-toc.ts +++ b/src/actions/portal/toc/new-toc.ts @@ -8,16 +8,8 @@ import { TocContext } from '../../../types/toc-context.js'; import { FileService } from '../../../infrastructure/file-service.js'; import { BuildContext } from '../../../types/build-context.js'; import { - extractCallbacksForToc, - extractContainerModelsForToc, - extractEndpointGroupsForToc, - extractEnumsForToc, - extractErrorsForToc, - extractInputModelsForToc, - extractModelsForToc, - extractWebhooksForToc, TocComponents -} from '../../../types/toc/toc-data.js'; +} from '../../../types/toc/toc-components.js'; import { withDirPath } from '../../../infrastructure/tmp-extensions.js'; import { TempContext } from '../../../types/temp-context.js'; import { PortalService } from '../../../infrastructure/services/portal-service.js'; @@ -72,22 +64,11 @@ export class PortalNewTocAction { } const tocComponents: TocComponents = await (async () => { - const defaultComponents = { - endpointGroups: new Map(), - models: [], - enums: [], - errors: [], - containerModels: [], - inputModels: [], - webhookGroups: new Map(), - callbackGroups: new Map() - }; - const specDirectory = buildDirectory.join('spec'); if (!(await this.fileService.directoryExists(specDirectory))) { this.prompts.fallingBackToDefault(); - return defaultComponents; + return TocComponents.empty(); } return await withDirPath(async (tempDirectory) => { @@ -104,19 +85,10 @@ export class PortalNewTocAction { specFileStream.close(); if (result.isErr()) { this.prompts.fallingBackToDefault(); - return defaultComponents; + return TocComponents.empty(); } - return { - endpointGroups: extractEndpointGroupsForToc(result.value), - models: extractModelsForToc(result.value), - enums: extractEnumsForToc(result.value), - errors: extractErrorsForToc(result.value), - containerModels: extractContainerModelsForToc(result.value), - inputModels: extractInputModelsForToc(result.value), - webhookGroups: extractWebhooksForToc(result.value), - callbackGroups: extractCallbacksForToc(result.value) - }; + return TocComponents.fromTocData(result.value); }); })(); const contentContext = new ContentContext(contentDirectory); @@ -131,17 +103,11 @@ export class PortalNewTocAction { } const toc = this.tocGenerator.createTocStructure( - { data: tocComponents.endpointGroups, expand: expandEndpoints }, - { - modelsData: tocComponents.models, - enumsData: tocComponents.enums, - errorsData: tocComponents.errors, - containerModelsData: tocComponents.containerModels, - inputModelsData: tocComponents.inputModels, - expand: expandModels - }, - { data: tocComponents.webhookGroups, expand: expandWebhooks }, - { data: tocComponents.callbackGroups, expand: expandCallbacks }, + tocComponents, + expandEndpoints, + expandModels, + expandWebhooks, + expandCallbacks, contentGroups ); const yamlString = this.tocGenerator.transformToYaml(toc); diff --git a/src/application/portal/toc/toc-structure-generator.ts b/src/application/portal/toc/toc-structure-generator.ts index 5b7a2f94..af6725c0 100644 --- a/src/application/portal/toc/toc-structure-generator.ts +++ b/src/application/portal/toc/toc-structure-generator.ts @@ -2,51 +2,31 @@ import { stringify } from 'yaml'; import { Toc, TocGroup, - TocEndpointGroupOverview, - TocModelPage, TocGenerated, - TocCallbackPage, - TocWebhookPage, - TocEndpoint, + TocModelPage, + TocContainerModelPage, TocInputModelPage, - TocContainerModelPage } from '../../../types/toc/toc.js'; - -// TODO: Refactor - -type Endpoints = { - data: Map; - expand: boolean; -}; - -type Webhooks = { - data: Map; - expand: boolean; -}; - -type Callbacks = { - data: Map; - expand: boolean; -}; - -type Models = { - modelsData: TocModelPage[]; - containerModelsData: TocContainerModelPage[]; - enumsData: TocModelPage[]; - errorsData: TocModelPage[]; - inputModelsData: TocInputModelPage[]; - expand: boolean; -}; +import { + TocComponents, + EndpointGroups, + WebhookGroups, + CallbackGroups +} from '../../../types/toc/toc-components.js'; export class TocStructureGenerator { createTocStructure( - endpoints: Endpoints, - models: Models, - webhooks: Webhooks, - callbacks: Callbacks, + tocComponents: TocComponents, + expandEndpoints: boolean, + expandModels: boolean, + expandWebhooks: boolean, + expandCallbacks: boolean, contentGroups: TocGroup[] = [] ): Toc { - const events = [...this.getCallbacksSection(callbacks), ...this.getWebhooksSection(webhooks)]; + const events = [ + ...this.getCallbacksSection(tocComponents.callbackGroups, expandCallbacks), + ...this.getWebhooksSection(tocComponents.webhookGroups, expandWebhooks) + ]; return { toc: [ @@ -60,7 +40,7 @@ export class TocStructureGenerator { ] }, ...contentGroups, - this.getEndpointsSection(endpoints), + this.getEndpointsSection(tocComponents.endpointGroups, expandEndpoints), ...(events.length > 0 ? [ { @@ -69,7 +49,14 @@ export class TocStructureGenerator { } ] : []), - ...this.getModelsSection(models), + ...this.getModelsSection( + tocComponents.models, + tocComponents.enums, + tocComponents.errors, + tocComponents.containerModels, + tocComponents.inputModels, + expandModels + ), { generate: 'SDK Infrastructure', from: 'sdk-infra' @@ -86,8 +73,8 @@ export class TocStructureGenerator { }); } - private getEndpointsSection(endpoints: Endpoints): TocGroup | TocGenerated { - if (!endpoints.expand || endpoints.data.size === 0) { + private getEndpointsSection(data: EndpointGroups, expand: boolean): TocGroup | TocGenerated { + if (!expand || data.size === 0) { return { generate: 'API Endpoints', from: 'endpoints' @@ -95,37 +82,30 @@ export class TocStructureGenerator { } return { group: 'API Endpoints', - items: Array.from(endpoints.data).map(([groupName, endpoints]) => ({ + items: Array.from(data).map(([groupName, pages]) => ({ group: groupName, - items: [ - { - generate: null, - from: 'endpoint-group-overview', - endpointGroup: groupName - } as TocEndpointGroupOverview, - ...endpoints - ] + items: pages })) }; } - private getCallbacksSection(callbacks: Callbacks): (TocGroup | TocGenerated)[] { - if (callbacks.data.size === 0) { + private getCallbacksSection(data: CallbackGroups, expand: boolean): (TocGroup | TocGenerated)[] { + if (data.size === 0) { return []; } - if (callbacks.expand === true) { - if (callbacks.data.size === 1) { + if (expand === true) { + if (data.size === 1) { return [ { - group: Array.from(callbacks.data.keys())[0], - items: Array.from(callbacks.data.values())[0] + group: Array.from(data.keys())[0], + items: Array.from(data.values())[0] } ]; } return [ { group: 'Callbacks', - items: Array.from(callbacks.data).map(([groupName, eventList]) => ({ + items: Array.from(data).map(([groupName, eventList]) => ({ group: groupName, items: eventList })) @@ -140,23 +120,23 @@ export class TocStructureGenerator { ]; } - private getWebhooksSection(webhooks: Webhooks): (TocGroup | TocGenerated)[] { - if (webhooks.data.size === 0) { + private getWebhooksSection(data: WebhookGroups, expand: boolean): (TocGroup | TocGenerated)[] { + if (data.size === 0) { return []; } - if (webhooks.expand === true) { - if (webhooks.data.size === 1) { + if (expand === true) { + if (data.size === 1) { return [ { - group: Array.from(webhooks.data.keys())[0], - items: Array.from(webhooks.data.values())[0] + group: Array.from(data.keys())[0], + items: Array.from(data.values())[0] } ]; } return [ { group: 'Webhooks', - items: Array.from(webhooks.data).map(([groupName, eventList]) => ({ + items: Array.from(data).map(([groupName, eventList]) => ({ group: groupName, items: eventList })) @@ -171,17 +151,24 @@ export class TocStructureGenerator { ]; } - private getModelsSection(models: Models): (TocGroup | TocGenerated)[] { + private getModelsSection( + modelsData: TocModelPage[], + enumsData: TocModelPage[], + errorsData: TocModelPage[], + containerModelsData: TocContainerModelPage[], + inputModelsData: TocInputModelPage[], + expand: boolean + ): (TocGroup | TocGenerated)[] { if ( - models.modelsData.length === 0 && - models.enumsData.length === 0 && - models.errorsData.length === 0 && - models.containerModelsData.length === 0 && - models.inputModelsData.length === 0 + modelsData.length === 0 && + enumsData.length === 0 && + errorsData.length === 0 && + containerModelsData.length === 0 && + inputModelsData.length === 0 ) { return []; } - if (!models.expand) { + if (!expand) { return [ { generate: 'Models', @@ -190,13 +177,13 @@ export class TocStructureGenerator { ]; } const subGroups: TocGroup[] = [ - ...(models.modelsData.length > 0 || models.inputModelsData.length > 0 - ? [{ group: 'Structures', items: [...models.modelsData, ...models.inputModelsData] }] + ...(modelsData.length > 0 || inputModelsData.length > 0 + ? [{ group: 'Structures', items: [...modelsData, ...inputModelsData] }] : []), - ...(models.enumsData.length > 0 ? [{ group: 'Enumerations', items: models.enumsData }] : []), - ...(models.errorsData.length > 0 ? [{ group: 'Exceptions', items: models.errorsData }] : []), - ...(models.containerModelsData.length > 0 - ? [{ group: 'OneOf/AnyOf Definitions', items: models.containerModelsData }] + ...(enumsData.length > 0 ? [{ group: 'Enumerations', items: enumsData }] : []), + ...(errorsData.length > 0 ? [{ group: 'Exceptions', items: errorsData }] : []), + ...(containerModelsData.length > 0 + ? [{ group: 'OneOf/AnyOf Definitions', items: containerModelsData }] : []) ]; return [ @@ -207,7 +194,7 @@ export class TocStructureGenerator { ]; } - private transformKeys(obj: any): any { + private transformKeys(obj: unknown): unknown { if (Array.isArray(obj)) { return obj.map((item) => this.transformKeys(item)); } diff --git a/src/infrastructure/services/portal-service.ts b/src/infrastructure/services/portal-service.ts index 8662c1be..363f12a8 100644 --- a/src/infrastructure/services/portal-service.ts +++ b/src/infrastructure/services/portal-service.ts @@ -29,7 +29,7 @@ import { Language } from "../../types/sdk/generate.js"; import { handleServiceError, ServiceError } from "../service-error.js"; import { ApiService } from "./api-service.js"; import { SemVersion } from "../../types/publish/version.js"; -import { TocData } from "../../types/toc/toc-data.js"; +import { TocData } from "../../types/toc/toc-components.js"; export interface GeneratedSdkResult { sdk: NodeJS.ReadableStream; diff --git a/src/prompts/portal/toc/new-toc.ts b/src/prompts/portal/toc/new-toc.ts index d9f61040..e4e8ea93 100644 --- a/src/prompts/portal/toc/new-toc.ts +++ b/src/prompts/portal/toc/new-toc.ts @@ -5,7 +5,7 @@ import { format as f } from "../../format.js"; import { DirectoryPath } from "../../../types/file/directoryPath.js"; import { ServiceError } from "../../../infrastructure/service-error.js"; import { withSpinner } from "../../prompt.js"; -import { TocData } from "../../../types/toc/toc-data.js"; +import { TocData } from "../../../types/toc/toc-components.js"; export class PortalNewTocPrompts { public async overwriteToc(tocPath: FilePath): Promise { diff --git a/src/types/toc/toc-components.ts b/src/types/toc/toc-components.ts new file mode 100644 index 00000000..3b40ed5d --- /dev/null +++ b/src/types/toc/toc-components.ts @@ -0,0 +1,175 @@ +import { + TocEndpoint, + TocEndpointPage, + TocModelPage, + TocCallback, + TocWebhook, + TocWebhookPage, + TocCallbackPage, + TocContainerModelPage, + TocInputModelPage +} from './toc.js'; + +export interface InputModel { + readonly name: string; + readonly group: string; +} + +export interface TocData { + readonly endpoints: Record; + readonly models: string[]; + readonly enums: string[]; + readonly errors: string[]; + readonly webhooks: Record; + readonly callbacks: Record; + readonly containers: string[]; + readonly inputModels: InputModel[]; +} + +export type EndpointGroups = Map; +export type WebhookGroups = Map; +export type CallbackGroups = Map; + +export class TocComponents { + readonly endpointGroups: EndpointGroups; + readonly models: TocModelPage[]; + readonly enums: TocModelPage[]; + readonly errors: TocModelPage[]; + readonly containerModels: TocContainerModelPage[]; + readonly inputModels: TocInputModelPage[]; + readonly webhookGroups: WebhookGroups; + readonly callbackGroups: CallbackGroups; + + private constructor( + endpointGroups: EndpointGroups, + models: TocModelPage[], + enums: TocModelPage[], + errors: TocModelPage[], + containerModels: TocContainerModelPage[], + inputModels: TocInputModelPage[], + webhookGroups: WebhookGroups, + callbackGroups: CallbackGroups + ) { + this.endpointGroups = endpointGroups; + this.models = models; + this.enums = enums; + this.errors = errors; + this.containerModels = containerModels; + this.inputModels = inputModels; + this.webhookGroups = webhookGroups; + this.callbackGroups = callbackGroups; + } + + static empty(): TocComponents { + return new TocComponents(new Map(), [], [], [], [], [], new Map(), new Map()); + } + + static fromTocData(tocData: TocData): TocComponents { + return new TocComponents( + TocComponents.toEndpointGroups(tocData.endpoints), + TocComponents.toTocModelPages(tocData.models), + TocComponents.toTocModelPages(tocData.enums), + TocComponents.toTocModelPages(tocData.errors), + TocComponents.toTocContainerModelPages(tocData.containers), + TocComponents.toTocInputModelPages(tocData.inputModels), + TocComponents.toWebhookGroups(tocData.webhooks), + TocComponents.toCallbackGroups(tocData.callbacks) + ); + } + + private static toEndpointGroups(endpoints: Record): EndpointGroups { + return new Map( + Object.entries(endpoints).map(([group, names]) => [ + group, + [ + { + generate: null, + from: 'endpoint-group-overview', + endpointGroup: group + }, + ...names.map((name): TocEndpoint => ({ + generate: null, + from: 'endpoint', + endpointName: name, + endpointGroup: group + })) + ] + ]) + ); + } + + private static toTocModelPages(models: string[]): TocModelPage[] { + return models.map( + (name: string): TocModelPage => ({ + generate: null, + from: 'model', + modelName: name + }) + ); + } + + private static toTocContainerModelPages(containers: string[]): TocContainerModelPage[] { + return containers.map( + (name: string): TocContainerModelPage => ({ + generate: null, + from: 'container', + containerName: name + }) + ); + } + + private static toTocInputModelPages(inputModels: InputModel[]): TocInputModelPage[] { + return inputModels.map( + (m: InputModel): TocInputModelPage => ({ + generate: null, + from: 'input-model', + endpointName: m.name, + endpointGroup: m.group + }) + ); + } + + private static toWebhookGroups(webhooks: Record): WebhookGroups { + return new Map( + Object.entries(webhooks) + .map(([group, names]): [string, TocWebhookPage[]] => [ + group, + [ + { + generate: null, + from: 'webhook-group-overview', + webhookGroup: group + }, + ...names.map((name): TocWebhook => ({ + generate: null, + from: 'webhook', + webhookName: name, + webhookGroup: group + })) + ] + ]) + ); + } + + private static toCallbackGroups(callbacks: Record): CallbackGroups { + return new Map( + Object.entries(callbacks) + .map(([group, names]): [string, TocCallbackPage[]] => [ + group, + [ + { + generate: null, + from: 'callback-group-overview', + callbackGroup: group + }, + ...names.map((name): TocCallback => ({ + generate: null, + from: 'callback', + callbackName: name, + callbackGroup: group + })) + ] + ]) + ); + } +} diff --git a/src/types/toc/toc-data.ts b/src/types/toc/toc-data.ts deleted file mode 100644 index d3b3b929..00000000 --- a/src/types/toc/toc-data.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { - TocEndpoint, - TocModelPage, - TocCallback, - TocWebhook, - TocWebhookPage, - TocCallbackPage, - TocContainerModelPage, - TocInputModelPage -} from './toc.js'; -import { toTitleCase } from '../../utils/string-utils.js'; - -export interface InputModel { - readonly name: string; - readonly group: string; -} - -export interface TocData { - readonly endpoints: Record; - readonly models: string[]; - readonly enums: string[]; - readonly errors: string[]; - readonly webhooks: Record; - readonly callbacks: Record; - readonly containers: string[]; - readonly inputModels: InputModel[]; -} - -export type EndpointGroup = Map; -export type WebhookGroup = Map; -export type CallbackGroup = Map; - -export type TocComponents = { - endpointGroups: EndpointGroup; - models: TocModelPage[]; - enums: TocModelPage[]; - errors: TocModelPage[]; - containerModels: TocContainerModelPage[]; - inputModels: TocInputModelPage[]; - webhookGroups: WebhookGroup; - callbackGroups: CallbackGroup; -}; - -export function extractEndpointGroupsForToc(tocData: TocData): Map { - const endpointGroups = new Map(); - - for (const [group, names] of Object.entries(tocData.endpoints)) { - const endpoints = names.map( - (name: string): TocEndpoint => ({ - generate: null, - from: 'endpoint', - endpointName: name, - endpointGroup: group - }) - ); - endpointGroups.set(group, endpoints); - } - - return endpointGroups; -} - -export function extractModelsForToc(tocData: TocData): TocModelPage[] { - return tocData.models.map( - (name: string): TocModelPage => ({ - generate: null, - from: 'model', - modelName: name - }) - ); -} - -export function extractEnumsForToc(tocData: TocData): TocModelPage[] { - return tocData.enums.map( - (name: string): TocModelPage => ({ - generate: null, - from: 'model', - modelName: name - }) - ); -} - -export function extractErrorsForToc(tocData: TocData): TocModelPage[] { - return tocData.errors.map( - (name: string): TocModelPage => ({ - generate: null, - from: 'model', - modelName: name - }) - ); -} - -export function extractContainerModelsForToc(tocData: TocData): TocContainerModelPage[] { - return tocData.containers.map( - (name: string): TocContainerModelPage => ({ - generate: null, - from: 'container', - containerName: name - }) - ); -} - -export function extractInputModelsForToc(tocData: TocData): TocInputModelPage[] { - return tocData.inputModels.map( - (m: InputModel): TocInputModelPage => ({ - generate: null, - from: 'input-model', - endpointName: m.name, - endpointGroup: m.group - }) - ); -} - -export function extractWebhooksForToc(tocData: TocData): Map { - const groupedWebhooks = new Map(); - - for (const [group, names] of Object.entries(tocData.webhooks)) { - const groupTitle = toTitleCase(group); - groupedWebhooks.set(groupTitle, [ - { - generate: null, - from: 'webhook-group-overview', - webhookGroup: group - }, - ...names.map( - (name: string): TocWebhook => ({ - generate: null, - from: 'webhook', - webhookName: name, - webhookGroup: group - }) - ) - ]); - } - - return new Map([...groupedWebhooks].sort((a, b) => a[0].localeCompare(b[0]))); -} - -export function extractCallbacksForToc(tocData: TocData): Map { - const groupedCallbacks = new Map(); - - for (const [group, names] of Object.entries(tocData.callbacks)) { - const groupTitle = toTitleCase(group); - groupedCallbacks.set(groupTitle, [ - { - generate: null, - from: 'callback-group-overview', - callbackGroup: group - }, - ...names.map( - (name: string): TocCallback => ({ - generate: null, - from: 'callback', - callbackName: name, - callbackGroup: group - }) - ) - ]); - } - - return new Map([...groupedCallbacks].sort((a, b) => a[0].localeCompare(b[0]))); -} diff --git a/src/utils/string-utils.ts b/src/utils/string-utils.ts index 1fabb218..25aff368 100644 --- a/src/utils/string-utils.ts +++ b/src/utils/string-utils.ts @@ -35,50 +35,3 @@ export function stripAnsi(str: string) { } return result; } - -export function toTitleCase(str: string): string { - if (str === '') { - return ''; - } - - let result = ''; - let shouldCapitalizeNext = true; - - for (let i = 0; i < str.length; i++) { - const char = str[i]; - const prevChar = i > 0 ? str[i - 1] : ''; - - if (isLowercase(char)) { - result += shouldCapitalizeNext ? ' ' + char.toUpperCase() : char; - shouldCapitalizeNext = false; - } else if (isUppercase(char)) { - if (prevChar && !isUppercase(prevChar)) { - result += ' '; - } - result += char; - shouldCapitalizeNext = false; - } else if (isDigit(char)) { - if (prevChar && !isDigit(prevChar)) { - result += ' '; - } - result += char; - shouldCapitalizeNext = true; - } else { - shouldCapitalizeNext = true; - } - } - - return result.trim(); -} - -function isLowercase(char: string): boolean { - return char >= 'a' && char <= 'z'; -} - -function isUppercase(char: string): boolean { - return char >= 'A' && char <= 'Z'; -} - -function isDigit(char: string): boolean { - return char.length === 1 && char >= '0' && char <= '9'; -} From eceaea6e70181c7650443c5768b8c68dbc9e6d86 Mon Sep 17 00:00:00 2001 From: Ayeshas09 Date: Fri, 8 May 2026 12:29:29 +0500 Subject: [PATCH 8/9] update package version of apimatic-sdk --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 5e85a72d..2283c739 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,7 @@ "./bin", "./lib", "/npm-shrinkwrap.json", - "/oclif.manifest.json", - "/apimatic-sdk-0.2.0-alpha.9-test.tgz" + "/oclif.manifest.json" ], "repository": "git://github.com/apimatic/apimatic-cli.git", "homepage": "https://docs.apimatic.io/apimatic-cli/intro-and-install/", @@ -48,7 +47,7 @@ "test": "tsx node_modules/mocha/bin/_mocha --forbid-only \"test/**/*.test.ts\" --timeout 99999" }, "dependencies": { - "@apimatic/sdk": "file:./apimatic-sdk-0.2.0-alpha.9-test.tgz", + "@apimatic/sdk": "0.2.0-alpha.9", "@clack/prompts": "1.0.0-alpha.1", "@oclif/core": "^4.2.8", "@oclif/plugin-autocomplete": "^3.2.24", From 785c02849a4cebc0b884ea2d6a8d557631b470f2 Mon Sep 17 00:00:00 2001 From: Ayeshas09 Date: Fri, 8 May 2026 15:50:04 +0500 Subject: [PATCH 9/9] update package-lock.json --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index e9cc09b9..eda3f4d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.1.0-beta.14", "license": "MIT", "dependencies": { - "@apimatic/sdk": "file:./apimatic-sdk-0.2.0-alpha.9-test.tgz", + "@apimatic/sdk": "0.2.0-alpha.9", "@clack/prompts": "1.0.0-alpha.1", "@oclif/core": "^4.2.8", "@oclif/plugin-autocomplete": "^3.2.24", @@ -275,9 +275,9 @@ } }, "node_modules/@apimatic/sdk": { - "version": "0.2.0-alpha.9-test", - "resolved": "file:apimatic-sdk-0.2.0-alpha.9-test.tgz", - "integrity": "sha512-UzFfyMUoJsYqI2LOqgrO6+irei5DXygqJYuU89XVitIjJiqFE3epUeedR2mJuWJikqzW7Kuwya7Gg3sMZIRxXg==", + "version": "0.2.0-alpha.9", + "resolved": "https://registry.npmjs.org/@apimatic/sdk/-/sdk-0.2.0-alpha.9.tgz", + "integrity": "sha512-lTZIToN43WuDGKJ8ny9IiusV7sJ+RJITQYxzhI1meD6cxCN7ryKEoS3tx2JOjCSRrRAxBmk3Wb2vDhXMYBAskA==", "license": "MIT", "dependencies": { "@apimatic/authentication-adapters": "^0.5.14",