Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
registry=https://registry.npmjs.org/
@apimatic:registry=https://registry.npmjs.org/
33 changes: 19 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ $ npm install -g @apimatic/cli
$ apimatic COMMAND
running command...
$ apimatic (--version)
@apimatic/cli/1.1.0-beta.11 win32-x64 node-v23.4.0
@apimatic/cli/1.1.0-beta.16 win32-x64 node-v23.4.0
$ apimatic --help [COMMAND]
USAGE
$ apimatic COMMAND
Expand Down Expand Up @@ -434,21 +434,26 @@ Generate an SDK for your API
```
USAGE
$ apimatic sdk generate -l csharp|java|php|python|ruby|typescript|go [-d <value>] [--skip-changes]
[--api-version <value>] [--zip] [--track-changes] [-i <value>] [-f] [-k <value>]
[--api-version <value>] [--zip] [--track-changes] [--codegen-version v3|v4] [--stability stable|beta] [-i <value>]
[-f] [-k <value>]

FLAGS
-d, --destination=<value> [default: <input>/sdk/<language> | <input>/sdk/<api-version>/<language>] path where the SDK
will be generated
-f, --force overwrite changes without asking for user consent.
-i, --input=<value> [default: ./] path to the parent directory containing the 'src' directory, which includes
API specifications and configuration files.
-k, --auth-key=<value> override current authentication state with an authentication key.
-l, --language=<option> (required) Programming language for SDK generation
<options: csharp|java|php|python|ruby|typescript|go>
--api-version=<value> Version of the API to use for SDK generation (if multiple versions exist)
--skip-changes Do not apply the saved changes to the generated SDK
--track-changes Enable change tracking for SDK generation (only required for initial setup)
--zip Download the generated SDK as a .zip archive
-d, --destination=<value> [default: <input>/sdk/<language> | <input>/sdk/<api-version>/<language>] path where
the SDK will be generated
-f, --force overwrite changes without asking for user consent.
-i, --input=<value> [default: ./] path to the parent directory containing the 'src' directory, which
includes API specifications and configuration files.
-k, --auth-key=<value> override current authentication state with an authentication key.
-l, --language=<option> (required) Programming language for SDK generation
<options: csharp|java|php|python|ruby|typescript|go>
--api-version=<value> Version of the API to use for SDK generation (if multiple versions exist)
--codegen-version=<option> [default: v3] Version of the code generator to use
<options: v3|v4>
--skip-changes Do not apply the saved changes to the generated SDK
--stability=<option> [default: stable] Stability level of the generated SDK
<options: stable|beta>
--track-changes Enable change tracking for SDK generation (only required for initial setup)
--zip Download the generated SDK as a .zip archive

DESCRIPTION
Generate an SDK for your API
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"test": "tsx node_modules/mocha/bin/_mocha --forbid-only \"test/**/*.test.ts\" --timeout 99999"
},
"dependencies": {
"@apimatic/sdk": "0.2.0-alpha.9",
"@apimatic/sdk": "0.2.0-alpha.10",
"@clack/core": "1.0.0-alpha.1",
"@clack/prompts": "1.0.0-alpha.1",
"@oclif/core": "^4.2.8",
Expand Down
769 changes: 441 additions & 328 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ overrides:
rimraf: ^6.0.1
glob: ^13.0.0
q: npm:promise@^8.3.0
semver: "^7.7.0"
'@oclif/core': "4.11.0"
oclif: "4.17.34"
browserslist: "4.24.4"
78 changes: 60 additions & 18 deletions src/actions/sdk/generate.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { PortalService } from "../../infrastructure/services/portal-service.js";
import { DirectoryPath } from "../../types/file/directoryPath.js";
import { ActionResult } from "../action-result.js";
import { withDirPath } from "../../infrastructure/tmp-extensions.js";
import { SdkContext } from "../../types/sdk-context.js";
import { SdkGeneratePrompts } from "../../prompts/sdk/generate.js";
import { CommandMetadata } from "../../types/common/command-metadata.js";
import { TempContext } from "../../types/temp-context.js";
import { Language } from "../../types/sdk/generate.js";
import { MergeSourceTreeAction } from "./merge-source-tree.js";
import { BuildContext } from "../../types/build-context.js";
import { SemVersion } from "../../types/publish/version.js";
import { PortalService } from '../../infrastructure/services/portal-service.js';
import { DirectoryPath } from '../../types/file/directoryPath.js';
import { ActionResult } from '../action-result.js';
import { withDirPath } from '../../infrastructure/tmp-extensions.js';
import { SdkContext } from '../../types/sdk-context.js';
import { SdkGeneratePrompts } from '../../prompts/sdk/generate.js';
import { CommandMetadata } from '../../types/common/command-metadata.js';
import { TempContext } from '../../types/temp-context.js';
import { CodeGenerationVersion, Language, Stability } from '../../types/sdk/generate.js';
import { MergeSourceTreeAction } from './merge-source-tree.js';
import { BuildContext } from '../../types/build-context.js';
import { SemVersion } from '../../types/publish/version.js';

export class GenerateAction {
private readonly prompts: SdkGeneratePrompts = new SdkGeneratePrompts();
Expand All @@ -32,10 +32,12 @@ export class GenerateAction {
zipSdk: boolean,
skipChanges: boolean,
trackChanges: boolean,
codeGenVersion: CodeGenerationVersion,
stability: Stability,
apiVersion?: string,
packageVersion?: SemVersion,
packageSettingsDirectory?: DirectoryPath
): Promise<ActionResult<{sourceTreeTrackingInitiated: boolean, conflictsResolved: boolean}>> => {
): Promise<ActionResult<{ sourceTreeTrackingInitiated: boolean; conflictsResolved: boolean }>> => {
if (buildDirectory.isEqual(destinationSdkDirectory)) {
this.prompts.sameBuildAndSdkDir(buildDirectory);
return ActionResult.failed();
Expand All @@ -48,7 +50,7 @@ export class GenerateAction {
}

const versionedContextGetter = async () => {
if (!await rootBuildContext.isVersionedBuild()) {
if (!(await rootBuildContext.isVersionedBuild())) {
if (apiVersion) this.prompts.apiVersionOnlyApplicableWithVersionedBuild();
return { version: undefined, buildContext: rootBuildContext };
}
Expand Down Expand Up @@ -95,7 +97,7 @@ export class GenerateAction {

const hasSdkSourceTree = await buildContext.hasSdkSourceTree(language);
const sdkContext = new SdkContext(language, destinationSdkDirectory, skipChanges && hasSdkSourceTree, version);
if (!force && await sdkContext.exists() && !(await this.prompts.overwriteSdk(destinationSdkDirectory))) {
if (!force && (await sdkContext.exists()) && !(await this.prompts.overwriteSdk(destinationSdkDirectory))) {
this.prompts.destinationDirNotEmpty();
return ActionResult.cancelled();
}
Expand All @@ -104,8 +106,40 @@ export class GenerateAction {
const tempContext = new TempContext(tempDirectory);
const buildZipPath = await buildContext.getBuildZipPath(tempDirectory, packageSettingsDirectory);

if (codeGenVersion === CodeGenerationVersion.V4) {
this.prompts.sdkCustomizationsNotSupportedForV4();

const response = await this.prompts.generateV4SDK(
this.portalService.generateV4Sdk(
buildZipPath,
language,
stability,
this.configDir,
this.commandMetadata,
this.authKey
)
);

if (response.isErr()) {
this.prompts.sdkGenerationServiceError(response.error);
return ActionResult.failed();
}

const responseSdkZipPath = await tempContext.save(response.value);
const tempSdk = await sdkContext.loadSdkInTempDirectory(tempDirectory, responseSdkZipPath);
this.prompts.sdkGenerated(await sdkContext.save(tempSdk, zipSdk));
return ActionResult.success();
}

const response = await this.prompts.generateSDK(
this.portalService.generateSdk(buildZipPath, language, this.configDir, this.commandMetadata, this.authKey, packageVersion)
this.portalService.generateSdk(
buildZipPath,
language,
this.configDir,
this.commandMetadata,
this.authKey,
packageVersion
)
);

if (response.isErr()) {
Expand All @@ -132,8 +166,16 @@ export class GenerateAction {

const mergeSourceTree = new MergeSourceTreeAction();
return await mergeSourceTree.execute(
tempSdkWithSourceTree, tempSdk, destinationSourceTreePath, trackChanges, skipChanges, hasSdkSourceTree,
language, destinationSdkDirectory, version, zipSdk
tempSdkWithSourceTree,
tempSdk,
destinationSourceTreePath,
trackChanges,
skipChanges,
hasSdkSourceTree,
language,
destinationSdkDirectory,
version,
zipSdk
);
});
};
Expand Down
4 changes: 3 additions & 1 deletion src/actions/sdk/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { PublishType } from '../../types/publish-api/publishing-profile-item.js'
import { PublishingInfo } from '../../types/publish-api/publishing-info.js';
import { ProfileId } from '../../types/publish/profile-id.js';
import { SemVersion } from '../../types/publish/version.js';
import { Language } from '../../types/sdk/generate.js';
import { CodeGenerationVersion, Language, Stability } from '../../types/sdk/generate.js';
import { PublishingProfile } from '../../types/publish/publishing-profile.js';
import { PackageSettingsContext } from '../../types/package-settings-context.js';
import { TempContext } from '../../types/temp-context.js';
Expand Down Expand Up @@ -55,6 +55,8 @@ export class SdkPublishAction {
false,
false,
false,
CodeGenerationVersion.V3,
Stability.STABLE,
undefined,
semVersion,
packageSettingsDirectory
Expand Down
12 changes: 10 additions & 2 deletions src/actions/sdk/quickstart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import { FileDownloadService } from '../../infrastructure/services/file-download-service.js';
import { FileService } from '../../infrastructure/file-service.js';
import { GenerateAction } from './generate.js';
import { Language } from '../../types/sdk/generate.js';
import { CodeGenerationVersion, Language, Stability } from '../../types/sdk/generate.js';
import { LauncherService } from '../../infrastructure/launcher-service.js';
import { ZipService } from '../../infrastructure/zip-service.js';
import { FileName } from '../../types/file/fileName.js';
Expand Down Expand Up @@ -179,7 +179,15 @@

const sdkDirectory = inputDirectory.join('sdk');
const sdkGenerateAction = new GenerateAction(this.configDir, this.commandMetadata);
const result = await sdkGenerateAction.execute(sourceDirectory, sdkDirectory, language as Language, true, false, false, false);
const result = await sdkGenerateAction.execute(sourceDirectory,
sdkDirectory,
language as Language,

Check warning on line 184 in src/actions/sdk/quickstart.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This assertion is unnecessary since it does not change the type of the expression.

See more on https://sonarcloud.io/project/issues?id=apimatic_apimatic-cli&issues=AZ4lJEUOhAnF2cQbXMpi&open=AZ4lJEUOhAnF2cQbXMpi&pullRequest=281
true,
false,
false,
false,
CodeGenerationVersion.V3,
Stability.STABLE);
if (result.isFailed()) {
return ActionResult.failed();
}
Expand Down
27 changes: 25 additions & 2 deletions src/commands/sdk/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Command, Flags } from "@oclif/core";
import { DirectoryPath } from "../../types/file/directoryPath.js";
import { FlagsProvider } from "../../types/flags-provider.js";
import { GenerateAction } from "../../actions/sdk/generate.js";
import { Language } from "../../types/sdk/generate.js";
import { CodeGenerationVersion, Language, Stability } from "../../types/sdk/generate.js";
import { CommandMetadata } from "../../types/common/command-metadata.js";
import { format, intro, outro } from "../../prompts/format.js";
import { SdkChangesTrackedEvent } from "../../types/events/sdk-changes-tracked.js";
Expand Down Expand Up @@ -43,6 +43,16 @@ Supports multiple programming languages including Java, C#, Python, JavaScript,
default: false,
description: "Enable change tracking for SDK generation (only required for initial setup)"
}),
"codegen-version": Flags.string({
description: "Version of the code generator to use",
options: Object.values(CodeGenerationVersion).map((v) => v.valueOf()),
default: CodeGenerationVersion.V3
}),
"stability": Flags.string({
description: "Stability level of the generated SDK",
options: Object.values(Stability).map((s) => s.valueOf()),
default: Stability.STABLE
}),
...FlagsProvider.input,
...FlagsProvider.force,
...FlagsProvider.authKey,
Expand All @@ -58,7 +68,18 @@ Supports multiple programming languages including Java, C#, Python, JavaScript,

async run() {
const {
flags: { language, input, destination, force, zip: zipSdk, "auth-key": authKey, "skip-changes": skipChanges, "track-changes": trackChanges,"api-version": apiVersion }
flags: { language,
input,
destination,
force,
zip: zipSdk,
"auth-key": authKey,
"skip-changes": skipChanges,
"track-changes": trackChanges,
"api-version": apiVersion,
"codegen-version": codegenVersion,
stability
}
} = await this.parse(SdkGenerate);

const workingDirectory = DirectoryPath.createInput(input);
Expand All @@ -81,6 +102,8 @@ Supports multiple programming languages including Java, C#, Python, JavaScript,
zipSdk,
skipChanges,
trackChanges,
codegenVersion as CodeGenerationVersion,
stability as Stability,
apiVersion
);
outro(result);
Expand Down
37 changes: 35 additions & 2 deletions src/infrastructure/services/api-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,40 @@ export class ApiService {
try {
const token = authKey || authInfo?.authKey;
const response = await this.axiosInstance(shell, token).get(`/sdk/${requestId}/status`, {
headers: { Accept: "application/json" },
headers: { Accept: 'application/json' },
maxRedirects: 0,
validateStatus: () => true
});

if (response.status === 200) {
return ok(response.data as SdkGenerationStatusResponse);
}

if (response.status === 302) {
return ok({ status: 'Completed' } as SdkGenerationStatusResponse);
}

return err(ServiceError.InvalidResponse);
} catch (error: unknown) {
return err(handleServiceError(error));
}
}

public async getV4SdkGenerationStatus(
requestId: string,
configDir: DirectoryPath,
shell: string,
authKey: string | null
): Promise<Result<SdkGenerationStatusResponse, ServiceError>> {
const authInfo: AuthInfo | null = await getAuthInfo(configDir.toString());
if (authInfo === null && !authKey) {
return err(ServiceError.UnAuthorized);
}

try {
const token = authKey || authInfo?.authKey;
const response = await this.axiosInstance(shell, token).get(`/sdk/v2/${requestId}/status`, {
headers: { Accept: 'application/json' },
maxRedirects: 0,
validateStatus: () => true
});
Expand All @@ -90,7 +123,7 @@ export class ApiService {
}

if (response.status === 302) {
return ok({ status: "Completed" } as SdkGenerationStatusResponse);
return ok({ status: 'Completed' } as SdkGenerationStatusResponse);
}

return err(ServiceError.InvalidResponse);
Expand Down
Loading
Loading