Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use sealed abstract case classes to reduce bincompat surface #257

Closed
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,24 @@ package events
import io.circe.Decoder
import natchez.Kernel

final case class Http(method: String)
sealed abstract case class Http private (method: String)
object Http {
private[lambda] def apply(method: String): Http = new Http(method) {}
private[lambda] def unapply(http: Http): Nothing = ???

implicit val decoder: Decoder[Http] = Decoder.forProduct1("method")(Http.apply)
}
final case class RequestContext(http: Http)

sealed abstract case class RequestContext private (http: Http)
object RequestContext {
private[lambda] def apply(http: Http): RequestContext = new RequestContext(http) {}
private[lambda] def unapply(requestContext: RequestContext): Nothing = ???

implicit val decoder: Decoder[RequestContext] =
Decoder.forProduct1("http")(RequestContext.apply)
}

final case class ApiGatewayProxyEventV2(
sealed abstract case class ApiGatewayProxyEventV2 private (
rawPath: String,
rawQueryString: String,
cookies: Option[List[String]],
Expand All @@ -42,6 +48,27 @@ final case class ApiGatewayProxyEventV2(
)

object ApiGatewayProxyEventV2 {
private[lambda] def apply(
rawPath: String,
rawQueryString: String,
cookies: Option[List[String]],
headers: Map[String, String],
requestContext: RequestContext,
body: Option[String],
isBase64Encoded: Boolean
): ApiGatewayProxyEventV2 =
new ApiGatewayProxyEventV2(
rawPath,
rawQueryString,
cookies,
headers,
requestContext,
body,
isBase64Encoded
) {}

private[lambda] def unapply(event: ApiGatewayProxyEventV2): Nothing = ???

implicit def decoder: Decoder[ApiGatewayProxyEventV2] = Decoder.forProduct7(
"rawPath",
"rawQueryString",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package feral.lambda.events

import io.circe.Encoder

final case class ApiGatewayProxyStructuredResultV2(
sealed abstract case class ApiGatewayProxyStructuredResultV2 private (
statusCode: Int,
headers: Map[String, String],
body: String,
Expand All @@ -27,6 +27,23 @@ final case class ApiGatewayProxyStructuredResultV2(
)

object ApiGatewayProxyStructuredResultV2 {
def apply(
statusCode: Int,
headers: Map[String, String],
body: String,
isBase64Encoded: Boolean,
cookies: List[String]
): ApiGatewayProxyStructuredResultV2 =
new ApiGatewayProxyStructuredResultV2(
statusCode,
headers,
body,
isBase64Encoded,
cookies
) {}

private[lambda] def unapply(result: ApiGatewayProxyStructuredResultV2): Nothing = ???

implicit def encoder: Encoder[ApiGatewayProxyStructuredResultV2] = Encoder.forProduct5(
"statusCode",
"headers",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ object StreamRecord {
)(StreamRecord.apply)
}

final case class DynamoDbRecord(
sealed abstract case class DynamoDbRecord private (
awsRegion: Option[String],
dynamodb: Option[StreamRecord],
eventID: Option[String],
Expand All @@ -93,6 +93,27 @@ final case class DynamoDbRecord(
)

object DynamoDbRecord {
private[lambda] def apply(
awsRegion: Option[String],
dynamodb: Option[StreamRecord],
eventID: Option[String],
eventName: Option[String],
eventSource: Option[String],
eventSourceArn: Option[String],
eventVersion: Option[String],
userIdentity: Option[Json]
): DynamoDbRecord =
new DynamoDbRecord(
awsRegion,
dynamodb,
eventID,
eventName,
eventSource,
eventSourceArn,
eventVersion,
userIdentity
) {}

implicit val decoder: Decoder[DynamoDbRecord] = Decoder.forProduct8(
"awsRegion",
"dynamodb",
Expand All @@ -105,11 +126,14 @@ object DynamoDbRecord {
)(DynamoDbRecord.apply)
}

final case class DynamoDbStreamEvent(
sealed abstract case class DynamoDbStreamEvent private (
records: List[DynamoDbRecord]
)

object DynamoDbStreamEvent {
private[lambda] def apply(records: List[DynamoDbRecord]): DynamoDbStreamEvent =
new DynamoDbStreamEvent(records) {}

implicit val decoder: Decoder[DynamoDbStreamEvent] =
Decoder.forProduct1("Records")(DynamoDbStreamEvent.apply)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import scodec.bits.ByteVector

import java.time.Instant

final case class KinesisStreamRecordPayload(
sealed abstract case class KinesisStreamRecordPayload private (
approximateArrivalTimestamp: Instant,
data: ByteVector,
kinesisSchemaVersion: String,
Expand All @@ -32,6 +32,23 @@ final case class KinesisStreamRecordPayload(
)

object KinesisStreamRecordPayload {
private[lambda] def apply(
approximateArrivalTimestamp: Instant,
data: ByteVector,
kinesisSchemaVersion: String,
partitionKey: String,
sequenceNumber: String
): KinesisStreamRecordPayload =
new KinesisStreamRecordPayload(
approximateArrivalTimestamp,
data,
kinesisSchemaVersion,
partitionKey,
sequenceNumber
) {}

private[lambda] def unapply(payload: KinesisStreamRecordPayload): Nothing = ???

implicit val decoder: Decoder[KinesisStreamRecordPayload] = Decoder.forProduct5(
"approximateArrivalTimestamp",
"data",
Expand All @@ -41,7 +58,7 @@ object KinesisStreamRecordPayload {
)(KinesisStreamRecordPayload.apply)
}

final case class KinesisStreamRecord(
sealed abstract case class KinesisStreamRecord private (
awsRegion: String,
eventID: String,
eventName: String,
Expand All @@ -53,6 +70,29 @@ final case class KinesisStreamRecord(
)

object KinesisStreamRecord {
private[lambda] def apply(
awsRegion: String,
eventID: String,
eventName: String,
eventSource: String,
eventSourceArn: String,
eventVersion: String,
invokeIdentityArn: String,
kinesis: KinesisStreamRecordPayload
): KinesisStreamRecord =
new KinesisStreamRecord(
awsRegion,
eventID,
eventName,
eventSource,
eventSourceArn,
eventVersion,
invokeIdentityArn,
kinesis
) {}

private[lambda] def unapply(record: KinesisStreamRecord): Nothing = ???

implicit val decoder: Decoder[KinesisStreamRecord] = Decoder.forProduct8(
"awsRegion",
"eventID",
Expand All @@ -65,11 +105,15 @@ object KinesisStreamRecord {
)(KinesisStreamRecord.apply)
}

final case class KinesisStreamEvent(
sealed abstract case class KinesisStreamEvent private (
records: List[KinesisStreamRecord]
)

object KinesisStreamEvent {
private[lambda] def apply(records: List[KinesisStreamRecord]): KinesisStreamEvent =
new KinesisStreamEvent(records) {}
private[lambda] def unapply(event: KinesisStreamEvent): Nothing = ???

implicit val decoder: Decoder[KinesisStreamEvent] =
Decoder.forProduct1("Records")(KinesisStreamEvent.apply)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,61 @@ import io.circe.Decoder

// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/aws-lambda/trigger/s3-batch.d.ts

final case class S3BatchEvent(
sealed abstract case class S3BatchEvent private (
invocationSchemaVersion: String,
invocationId: String,
job: S3BatchEventJob,
tasks: List[S3BatchEventTask]
)

object S3BatchEvent {
private[lambda] def apply(
invocationSchemaVersion: String,
invocationId: String,
job: S3BatchEventJob,
tasks: List[S3BatchEventTask]
): S3BatchEvent =
new S3BatchEvent(
invocationSchemaVersion,
invocationId,
job,
tasks
) {}

private[lambda] def unapply(event: S3BatchEvent): Nothing = ???

implicit val decoder: Decoder[S3BatchEvent] =
Decoder.forProduct4("invocationSchemaVersion", "invocationId", "job", "tasks")(
S3BatchEvent.apply)

implicit def kernelSource: KernelSource[S3BatchEvent] = KernelSource.emptyKernelSource
}

final case class S3BatchEventJob(id: String)
sealed abstract case class S3BatchEventJob private (id: String)

object S3BatchEventJob {
private[lambda] def apply(id: String): S3BatchEventJob =
new S3BatchEventJob(id) {}

implicit val decoder: Decoder[S3BatchEventJob] =
Decoder.forProduct1("id")(S3BatchEventJob.apply)
}

final case class S3BatchEventTask(
sealed abstract case class S3BatchEventTask private (
taskId: String,
s3Key: String,
s3VersionId: Option[String],
s3BucketArn: String)
s3BucketArn: String
)

object S3BatchEventTask {
private[lambda] def apply(
taskId: String,
s3Key: String,
s3VersionId: Option[String],
s3BucketArn: String
): S3BatchEventTask = new S3BatchEventTask(taskId, s3Key, s3VersionId, s3BucketArn) {}

implicit val decoder: Decoder[S3BatchEventTask] =
Decoder.forProduct4("taskId", "s3Key", "s3VersionId", "s3BucketArn")(S3BatchEventTask.apply)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,24 @@ import io.circe.Encoder

// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/aws-lambda/trigger/s3-batch.d.ts

final case class S3BatchResult(
sealed abstract case class S3BatchResult private (
invocationSchemaVersion: String,
treatMissingKeysAs: S3BatchResultResultCode,
invocationId: String,
results: List[S3BatchResultResult]
)

object S3BatchResult {
private[lambda] def apply(
invocationSchemaVersion: String,
treatMissingKeysAs: S3BatchResultResultCode,
invocationId: String,
results: List[S3BatchResultResult]
): S3BatchResult =
new S3BatchResult(invocationSchemaVersion, treatMissingKeysAs, invocationId, results) {}

private[lambda] def unapply(result: S3BatchResult): Nothing = ???

implicit val encoder: Encoder[S3BatchResult] =
Encoder.forProduct4(
"invocationSchemaVersion",
Expand All @@ -37,7 +47,7 @@ object S3BatchResult {
(r.invocationSchemaVersion, r.treatMissingKeysAs, r.invocationId, r.results))
}

sealed abstract class S3BatchResultResultCode
sealed abstract class S3BatchResultResultCode extends Product with Serializable

object S3BatchResultResultCode {
case object Succeeded extends S3BatchResultResultCode
Expand All @@ -51,12 +61,19 @@ object S3BatchResultResultCode {
}
}

final case class S3BatchResultResult(
sealed abstract case class S3BatchResultResult private (
taskId: String,
resultCode: S3BatchResultResultCode,
resultString: String)
resultString: String
)

object S3BatchResultResult {
private[lambda] def apply(
taskId: String,
resultCode: S3BatchResultResultCode,
resultString: String
): S3BatchResultResult = new S3BatchResultResult(taskId, resultCode, resultString) {}

implicit val encoder: Encoder[S3BatchResultResult] =
Encoder.forProduct3("taskId", "resultCode", "resultString")(r =>
(r.taskId, r.resultCode, r.resultString))
Expand Down
Loading