Created
December 23, 2023 20:56
-
-
Save KONFeature/ade9d1dc1b3b323f5f3f8b6b8316ece8 to your computer and use it in GitHub Desktop.
Simple SST event builder using typebox instead of zod (missing a few stuff, like metadata)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
EventBridgeClient, | |
PutEventsCommand, | |
PutEventsCommandOutput, | |
PutEventsRequestEntry, | |
} from "@aws-sdk/client-eventbridge"; | |
import { Static, TSchema } from "@sinclair/typebox"; | |
import { TypeCompiler } from "@sinclair/typebox/compiler"; | |
import { EventBus } from "sst/node/event-bus"; | |
import { useLoader } from "./loaderReplica"; | |
/** | |
* PutEventsCommandOutput is used in return type of createEvent, in case the consumer of SST builds | |
* their project with declaration files, this is not portable. In order to allow TS to generate a | |
* declaration file without reference to @aws-sdk/client-eventbridge, we must re-export the type. | |
* | |
* More information here: https://github.com/microsoft/TypeScript/issues/47663#issuecomment-1519138189 | |
*/ | |
export { PutEventsCommandOutput }; | |
const client = new EventBridgeClient({}); | |
export function createTypeboxEventBuilder< | |
Bus extends keyof typeof EventBus, | |
>(props: { | |
bus: Bus; | |
}) { | |
return function createEvent< | |
Type extends string, | |
Shape extends TSchema, | |
Properties = Static<Shape>, | |
>(type: Type, properties: Shape) { | |
type Publish = ( | |
properties: Properties | |
) => Promise<PutEventsCommandOutput>; | |
const propertiesCompiler = TypeCompiler.Compile(properties); | |
const publish = async (properties: any, metadata: any) => { | |
return await useLoader( | |
"sst.bus.publish", | |
async (input: PutEventsRequestEntry[]) => { | |
const size = 10; | |
const promises: Promise<any>[] = []; | |
for (let i = 0; i < input.length; i += size) { | |
const chunk = input.slice(i, i + size); | |
promises.push( | |
client.send( | |
new PutEventsCommand({ | |
Entries: chunk, | |
}) | |
) | |
); | |
} | |
const settled = await Promise.allSettled(promises); | |
const result = new Array<PutEventsCommandOutput>( | |
input.length | |
); | |
for (let i = 0; i < result.length; i++) { | |
const item = settled[Math.floor(i / 10)]; | |
if (item.status === "rejected") { | |
result[i] = item.reason; | |
continue; | |
} | |
result[i] = item.value; | |
} | |
return result; | |
} | |
)({ | |
EventBusName: EventBus[props.bus].eventBusName, | |
// COnfig.APP of SST not exposed | |
Source: process.env.SST_APP, | |
Detail: JSON.stringify({ | |
properties: propertiesCompiler.Encode(properties), | |
metadata: (() => undefined)(), | |
}), | |
DetailType: type, | |
}); | |
}; | |
return { | |
publish: publish as Publish, | |
type, | |
shape: { | |
metadata: {}, | |
properties: {} as Properties, | |
metadataFn: {} as any, | |
}, | |
}; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment