Skip to content

Commit

Permalink
feat: Codegen clients (#38)
Browse files Browse the repository at this point in the history
* refactor: Reorder types

* feat: Codegen clients

* refactor: Regenerate IAM client

* feat: add a choice what command must be tested, documentation

* revert: back to iam CreateRoleCommand test

---------

Co-authored-by: Victor Korzunin <[email protected]>
  • Loading branch information
godu and floydspace authored Mar 11, 2024
1 parent 5ca9867 commit 758d441
Show file tree
Hide file tree
Showing 8 changed files with 788 additions and 152 deletions.
10 changes: 10 additions & 0 deletions .projen/deps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .projenrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ new Docgen(project);

new Vitest(project);

project.addScripts({
"codegen-client": "tsx ./scripts/codegen-client.ts",
});
project.addDeps("effect@^2.3.1", "enquirer@^2.4.1");

const commonDeps = ["@aws-sdk/types@^3"];
const commonDevDeps = ["aws-sdk-client-mock", "aws-sdk-client-mock-jest"];
const commonPeerDeps = ["effect@>=2.3.1 <2.5.0"];
Expand Down
7 changes: 5 additions & 2 deletions package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 32 additions & 32 deletions packages/client-iam/src/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,51 +34,51 @@ export type TaggedException<T extends { name: string }> = T & {
readonly _tag: T["name"];
};

export type InvalidInputError = TaggedException<InvalidInputException>;
export type LimitExceededError = TaggedException<LimitExceededException>;
export type NoSuchEntityError = TaggedException<NoSuchEntityException>;
export type ServiceFailureError = TaggedException<ServiceFailureException>;
export type EntityAlreadyExistsError =
TaggedException<EntityAlreadyExistsException>;
export type UnmodifiableEntityError =
TaggedException<UnmodifiableEntityException>;
export type PolicyNotAttachableError =
TaggedException<PolicyNotAttachableException>;
export type EntityTemporarilyUnmodifiableError =
TaggedException<EntityTemporarilyUnmodifiableException>;
export type InvalidUserTypeError = TaggedException<InvalidUserTypeException>;
export type PasswordPolicyViolationError =
TaggedException<PasswordPolicyViolationException>;
export type ConcurrentModificationError =
TaggedException<ConcurrentModificationException>;
export type MalformedPolicyDocumentError =
TaggedException<MalformedPolicyDocumentException>;
export type ServiceNotSupportedError =
TaggedException<ServiceNotSupportedException>;
export type DeleteConflictError = TaggedException<DeleteConflictException>;
export type InvalidAuthenticationCodeError =
TaggedException<InvalidAuthenticationCodeException>;
export type ReportGenerationLimitExceededError =
TaggedException<ReportGenerationLimitExceededException>;
export type CredentialReportExpiredError =
TaggedException<CredentialReportExpiredException>;
export type CredentialReportNotPresentError =
TaggedException<CredentialReportNotPresentException>;
export type CredentialReportNotReadyError =
TaggedException<CredentialReportNotReadyException>;
export type UnrecognizedPublicKeyEncodingError =
TaggedException<UnrecognizedPublicKeyEncodingException>;
export type PolicyEvaluationError = TaggedException<PolicyEvaluationException>;
export type KeyPairMismatchError = TaggedException<KeyPairMismatchException>;
export type MalformedCertificateError =
TaggedException<MalformedCertificateException>;
export type DeleteConflictError = TaggedException<DeleteConflictException>;
export type DuplicateCertificateError =
TaggedException<DuplicateCertificateException>;
export type InvalidCertificateError =
TaggedException<InvalidCertificateException>;
export type DuplicateSSHPublicKeyError =
TaggedException<DuplicateSSHPublicKeyException>;
export type EntityAlreadyExistsError =
TaggedException<EntityAlreadyExistsException>;
export type EntityTemporarilyUnmodifiableError =
TaggedException<EntityTemporarilyUnmodifiableException>;
export type InvalidAuthenticationCodeError =
TaggedException<InvalidAuthenticationCodeException>;
export type InvalidCertificateError =
TaggedException<InvalidCertificateException>;
export type InvalidInputError = TaggedException<InvalidInputException>;
export type InvalidPublicKeyError = TaggedException<InvalidPublicKeyException>;
export type InvalidUserTypeError = TaggedException<InvalidUserTypeException>;
export type KeyPairMismatchError = TaggedException<KeyPairMismatchException>;
export type LimitExceededError = TaggedException<LimitExceededException>;
export type MalformedCertificateError =
TaggedException<MalformedCertificateException>;
export type MalformedPolicyDocumentError =
TaggedException<MalformedPolicyDocumentException>;
export type NoSuchEntityError = TaggedException<NoSuchEntityException>;
export type PasswordPolicyViolationError =
TaggedException<PasswordPolicyViolationException>;
export type PolicyEvaluationError = TaggedException<PolicyEvaluationException>;
export type PolicyNotAttachableError =
TaggedException<PolicyNotAttachableException>;
export type ReportGenerationLimitExceededError =
TaggedException<ReportGenerationLimitExceededException>;
export type ServiceFailureError = TaggedException<ServiceFailureException>;
export type ServiceNotSupportedError =
TaggedException<ServiceNotSupportedException>;
export type UnmodifiableEntityError =
TaggedException<UnmodifiableEntityException>;
export type UnrecognizedPublicKeyEncodingError =
TaggedException<UnrecognizedPublicKeyEncodingException>;

export type IAMServiceError = TaggedException<
IAMServiceException & { name: "IAMServiceError" }
Expand Down
6 changes: 3 additions & 3 deletions packages/client-iam/src/IAMService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ import {
import { type HttpHandlerOptions as __HttpHandlerOptions } from "@aws-sdk/types";
import { Context, Effect, Layer, ReadonlyRecord, Data } from "effect";
import {
IAMServiceError,
ConcurrentModificationError,
CredentialReportExpiredError,
CredentialReportNotPresentError,
Expand All @@ -493,7 +494,6 @@ import {
DuplicateSSHPublicKeyError,
EntityAlreadyExistsError,
EntityTemporarilyUnmodifiableError,
IAMServiceError,
InvalidAuthenticationCodeError,
InvalidCertificateError,
InvalidInputError,
Expand All @@ -508,12 +508,12 @@ import {
PolicyEvaluationError,
PolicyNotAttachableError,
ReportGenerationLimitExceededError,
SdkError,
ServiceFailureError,
ServiceNotSupportedError,
TaggedException,
UnmodifiableEntityError,
UnrecognizedPublicKeyEncodingError,
SdkError,
TaggedException,
} from "./Errors";
import { IAMClientInstance, IAMClientInstanceLayer } from "./IAMClientInstance";
import { DefaultIAMClientConfigLayer } from "./IAMClientInstanceConfig";
Expand Down
150 changes: 47 additions & 103 deletions packages/client-iam/test/IAM.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
type CreateRoleCommandInput,
CreateRoleCommand,
IAMClient,
CreateRoleCommandInput,
} from "@aws-sdk/client-iam";
import { mockClient } from "aws-sdk-client-mock";
import * as Effect from "effect/Effect";
Expand All @@ -21,29 +21,17 @@ import {

import "aws-sdk-client-mock-jest";

const iamMock = mockClient(IAMClient);
const { createRole } = Effect.serviceFunctions(IAMService);
const clientMock = mockClient(IAMClient);

describe("IAMClientImpl", () => {
it("default", async () => {
iamMock.reset().on(CreateRoleCommand).resolves({});

const args: CreateRoleCommandInput = {
RoleName: "test",
AssumeRolePolicyDocument: JSON.stringify({
Version: "2012-10-17",
Statement: [
{
Sid: "Statement1",
Effect: "Allow",
Principal: {},
Action: "sts:AssumeRole",
},
],
}),
};

const program = createRole(args);
clientMock.reset().on(CreateRoleCommand).resolves({});

const args = {} as unknown as CreateRoleCommandInput;

const program = Effect.flatMap(IAMService, (service) =>
service.createRole(args),
);

const result = await pipe(
program,
Expand All @@ -52,29 +40,18 @@ describe("IAMClientImpl", () => {
);

expect(result).toEqual(Exit.succeed({}));
expect(iamMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(iamMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
expect(clientMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(clientMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
});

it("configurable", async () => {
iamMock.reset().on(CreateRoleCommand).resolves({});

const args: CreateRoleCommandInput = {
RoleName: "test",
AssumeRolePolicyDocument: JSON.stringify({
Version: "2012-10-17",
Statement: [
{
Sid: "Statement1",
Effect: "Allow",
Principal: {},
Action: "sts:AssumeRole",
},
],
}),
};

const program = createRole(args);
clientMock.reset().on(CreateRoleCommand).resolves({});

const args = {} as unknown as CreateRoleCommandInput;

const program = Effect.flatMap(IAMService, (service) =>
service.createRole(args),
);

const IAMClientConfigLayer = Layer.succeed(IAMClientInstanceConfig, {
region: "eu-central-1",
Expand All @@ -90,29 +67,18 @@ describe("IAMClientImpl", () => {
);

expect(result).toEqual(Exit.succeed({}));
expect(iamMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(iamMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
expect(clientMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(clientMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
});

it("base", async () => {
iamMock.reset().on(CreateRoleCommand).resolves({});

const args: CreateRoleCommandInput = {
RoleName: "test",
AssumeRolePolicyDocument: JSON.stringify({
Version: "2012-10-17",
Statement: [
{
Sid: "Statement1",
Effect: "Allow",
Principal: {},
Action: "sts:AssumeRole",
},
],
}),
};

const program = createRole(args);
clientMock.reset().on(CreateRoleCommand).resolves({});

const args = {} as unknown as CreateRoleCommandInput;

const program = Effect.flatMap(IAMService, (service) =>
service.createRole(args),
);

const IAMClientInstanceLayer = Layer.succeed(
IAMClientInstance,
Expand All @@ -129,29 +95,18 @@ describe("IAMClientImpl", () => {
);

expect(result).toEqual(Exit.succeed({}));
expect(iamMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(iamMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
expect(clientMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(clientMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
});

it("extended", async () => {
iamMock.reset().on(CreateRoleCommand).resolves({});

const args: CreateRoleCommandInput = {
RoleName: "test",
AssumeRolePolicyDocument: JSON.stringify({
Version: "2012-10-17",
Statement: [
{
Sid: "Statement1",
Effect: "Allow",
Principal: {},
Action: "sts:AssumeRole",
},
],
}),
};

const program = createRole(args);
clientMock.reset().on(CreateRoleCommand).resolves({});

const args = {} as unknown as CreateRoleCommandInput;

const program = Effect.flatMap(IAMService, (service) =>
service.createRole(args),
);

const IAMClientInstanceLayer = Layer.effect(
IAMClientInstance,
Expand All @@ -172,29 +127,18 @@ describe("IAMClientImpl", () => {
);

expect(result).toEqual(Exit.succeed({}));
expect(iamMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(iamMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
expect(clientMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(clientMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
});

it("fail", async () => {
iamMock.reset().on(CreateRoleCommand).rejects(new Error("test"));

const args: CreateRoleCommandInput = {
RoleName: "test",
AssumeRolePolicyDocument: JSON.stringify({
Version: "2012-10-17",
Statement: [
{
Sid: "Statement1",
Effect: "Allow",
Principal: {},
Action: "sts:AssumeRole",
},
],
}),
};

const program = createRole(args, { requestTimeout: 1000 });
clientMock.reset().on(CreateRoleCommand).rejects(new Error("test"));

const args = {} as unknown as CreateRoleCommandInput;

const program = Effect.flatMap(IAMService, (service) =>
service.createRole(args),
);

const result = await pipe(
program,
Expand All @@ -212,7 +156,7 @@ describe("IAMClientImpl", () => {
}),
),
);
expect(iamMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(iamMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
expect(clientMock).toHaveReceivedCommandTimes(CreateRoleCommand, 1);
expect(clientMock).toHaveReceivedCommandWith(CreateRoleCommand, args);
});
});
Loading

0 comments on commit 758d441

Please sign in to comment.