sst 3.0.20 → 3.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/auth/index.d.ts +7 -1
  2. package/dist/auth/index.js +7 -1
  3. package/dist/src/auth/adapter/adapter.d.ts +24 -0
  4. package/dist/src/auth/adapter/adapter.js +4 -0
  5. package/dist/src/auth/adapter/apple.d.ts +5 -0
  6. package/dist/src/auth/adapter/apple.js +22 -0
  7. package/dist/src/auth/adapter/code.d.ts +8 -0
  8. package/dist/src/auth/adapter/code.js +47 -0
  9. package/dist/src/auth/adapter/facebook.d.ts +5 -0
  10. package/dist/src/auth/adapter/facebook.js +27 -0
  11. package/dist/src/auth/adapter/github.d.ts +12 -0
  12. package/dist/src/auth/adapter/github.js +23 -0
  13. package/dist/src/auth/adapter/google.d.ts +17 -0
  14. package/dist/src/auth/adapter/google.js +22 -0
  15. package/dist/src/auth/adapter/index.d.ts +11 -0
  16. package/dist/src/auth/adapter/index.js +10 -0
  17. package/dist/src/auth/adapter/link.d.ts +6 -0
  18. package/dist/src/auth/adapter/link.js +27 -0
  19. package/dist/src/auth/adapter/microsoft.d.ts +11 -0
  20. package/dist/src/auth/adapter/microsoft.js +16 -0
  21. package/dist/src/auth/adapter/oauth.d.ts +33 -0
  22. package/dist/src/auth/adapter/oauth.js +79 -0
  23. package/dist/src/auth/adapter/oidc.d.ts +19 -0
  24. package/dist/src/auth/adapter/oidc.js +45 -0
  25. package/dist/src/auth/adapter/spotify.d.ts +12 -0
  26. package/dist/src/auth/adapter/spotify.js +22 -0
  27. package/dist/src/auth/example/bun.d.ts +2 -0
  28. package/dist/src/auth/example/bun.js +46 -0
  29. package/dist/src/auth/handler.d.ts +58 -0
  30. package/dist/src/auth/handler.js +207 -0
  31. package/dist/src/auth/index.d.ts +10 -0
  32. package/dist/src/auth/index.js +10 -0
  33. package/dist/src/auth/session.d.ts +25 -0
  34. package/dist/src/auth/session.js +28 -0
  35. package/dist/src/aws/bus.d.ts +29 -0
  36. package/dist/src/aws/bus.js +67 -0
  37. package/dist/src/aws/client.d.ts +3 -0
  38. package/dist/src/aws/client.js +7 -0
  39. package/dist/src/aws/realtime.d.ts +61 -0
  40. package/dist/src/aws/realtime.js +76 -0
  41. package/dist/src/event/index.d.ts +74 -0
  42. package/dist/src/event/index.js +41 -0
  43. package/dist/src/index.d.ts +3 -0
  44. package/dist/src/index.js +3 -0
  45. package/dist/src/realtime/index.d.ts +25 -0
  46. package/dist/src/realtime/index.js +24 -0
  47. package/dist/src/resource.d.ts +9 -0
  48. package/dist/src/resource.js +50 -0
  49. package/dist/src/util/prettify.d.ts +3 -0
  50. package/dist/src/util/prettify.js +1 -0
  51. package/dist/src/vector/index.d.ts +193 -0
  52. package/dist/src/vector/index.js +62 -0
  53. package/dist/test/event.test.d.ts +1 -0
  54. package/dist/test/event.test.js +12 -0
  55. package/package.json +2 -1
@@ -0,0 +1,58 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { Adapter } from "./adapter/adapter.js";
3
+ import { JWTPayload } from "jose";
4
+ import { SessionBuilder } from "./session.js";
5
+ import { Hono } from "hono/tiny";
6
+ interface OnSuccessResponder<T extends {
7
+ type: any;
8
+ properties: any;
9
+ }> {
10
+ session(input: T & JWTPayload): Promise<Response>;
11
+ }
12
+ export declare class UnknownProviderError extends Error {
13
+ provider?: string | undefined;
14
+ constructor(provider?: string | undefined);
15
+ }
16
+ export declare class MissingParameterError extends Error {
17
+ parameter: string;
18
+ constructor(parameter: string);
19
+ }
20
+ export declare class UnknownStateError extends Error {
21
+ constructor();
22
+ }
23
+ export declare class UnauthorizedClientError extends Error {
24
+ client: string;
25
+ redirect_uri: string;
26
+ constructor(client: string, redirect_uri: string);
27
+ }
28
+ export declare class InvalidSessionError extends Error {
29
+ constructor();
30
+ }
31
+ export type Prettify<T> = {
32
+ [K in keyof T]: T[K];
33
+ } & {};
34
+ export declare const aws: <E extends import("hono").Env = import("hono").Env, S extends import("hono").Schema = {}, BasePath extends string = "/">(app: import("hono").Hono<E, S, BasePath>) => (event: import("hono/aws-lambda").LambdaEvent, lambdaContext?: import("hono/aws-lambda").LambdaContext | undefined) => Promise<import("hono/aws-lambda").APIGatewayProxyResult>;
35
+ export declare function AuthHandler<Providers extends Record<string, Adapter<any>>, Sessions extends SessionBuilder = SessionBuilder, Result = {
36
+ [key in keyof Providers]: Prettify<{
37
+ provider: key;
38
+ } & (Providers[key] extends Adapter<infer T> ? T : {})>;
39
+ }[keyof Providers]>(input: {
40
+ session?: Sessions;
41
+ providers: Providers;
42
+ callbacks: {
43
+ index?(req: Request): Promise<Response>;
44
+ error?(error: UnknownStateError, req: Request): Promise<Response | undefined>;
45
+ auth: {
46
+ error?(error: MissingParameterError | UnauthorizedClientError | UnknownProviderError, req: Request): Promise<Response>;
47
+ start?(event: Request): Promise<void>;
48
+ allowClient(clientID: string, redirect: string, req: Request): Promise<boolean>;
49
+ success(response: OnSuccessResponder<Sessions["$typeValues"]>, input: Result, req: Request): Promise<Response>;
50
+ };
51
+ connect?: {
52
+ error?(error: InvalidSessionError | UnknownProviderError, req: Request): Promise<Response | undefined>;
53
+ start?(session: Sessions["$typeValues"], req: Request): Promise<void>;
54
+ success?(session: Sessions["$typeValues"], input: {}): Promise<Response>;
55
+ };
56
+ };
57
+ }): Hono<import("hono").Env, import("hono/types").BlankSchema, "/">;
58
+ export {};
@@ -0,0 +1,207 @@
1
+ import { SignJWT, importPKCS8, importSPKI, jwtVerify } from "jose";
2
+ import { Hono } from "hono/tiny";
3
+ import { handle as awsHandle } from "hono/aws-lambda";
4
+ import { deleteCookie, getCookie, setCookie } from "hono/cookie";
5
+ export class UnknownProviderError extends Error {
6
+ provider;
7
+ constructor(provider) {
8
+ super("Unknown provider: " + provider);
9
+ this.provider = provider;
10
+ }
11
+ }
12
+ export class MissingParameterError extends Error {
13
+ parameter;
14
+ constructor(parameter) {
15
+ super("Missing parameter: " + parameter);
16
+ this.parameter = parameter;
17
+ }
18
+ }
19
+ export class UnknownStateError extends Error {
20
+ constructor() {
21
+ super("The browser was in an unknown state. This could be because certain cookies expired or the browser was switched in the middle of an authentication flow");
22
+ }
23
+ }
24
+ export class UnauthorizedClientError extends Error {
25
+ client;
26
+ redirect_uri;
27
+ constructor(client, redirect_uri) {
28
+ super("Unauthorized client");
29
+ this.client = client;
30
+ this.redirect_uri = redirect_uri;
31
+ }
32
+ }
33
+ export class InvalidSessionError extends Error {
34
+ constructor() {
35
+ super("Invalid session");
36
+ }
37
+ }
38
+ import process from "node:process";
39
+ import { Resource } from "../resource.js";
40
+ export const aws = awsHandle;
41
+ export function AuthHandler(input) {
42
+ const app = new Hono();
43
+ if (!input.callbacks.auth.error) {
44
+ input.callbacks.auth.error = async (err) => {
45
+ return new Response(err.message, {
46
+ status: 400,
47
+ headers: {
48
+ "Content-Type": "text/plain",
49
+ },
50
+ });
51
+ };
52
+ }
53
+ const options = {
54
+ signing: {
55
+ privateKey: () => importPKCS8(
56
+ // @ts-expect-error
57
+ process.env.AUTH_PRIVATE_KEY || Resource.AUTH_PRIVATE_KEY, "RS512"),
58
+ publicKey: () => importSPKI(
59
+ // @ts-expect-error
60
+ process.env.AUTH_PUBLIC_KEY || Resource.AUTH_PUBLIC_KEY, "RS512"),
61
+ },
62
+ encryption: {
63
+ privateKey: () => importPKCS8(
64
+ // @ts-expect-error
65
+ process.env.AUTH_PRIVATE_KEY || Resource.AUTH_PRIVATE_KEY, "RSA-OAEP-512"),
66
+ publicKey: () => importSPKI(
67
+ // @ts-expect-error
68
+ process.env.AUTH_PUBLIC_KEY || Resource.AUTH_PUBLIC_KEY, "RSA-OAEP-512"),
69
+ },
70
+ algorithm: "RS512",
71
+ async success(ctx, properties) {
72
+ const redirect_uri = getCookie(ctx, "redirect_uri");
73
+ const response_type = getCookie(ctx, "response_type");
74
+ if (!redirect_uri) {
75
+ return options.forward(ctx, await input.callbacks.auth.error(new UnknownStateError(), ctx.req.raw));
76
+ }
77
+ return await input.callbacks.auth.success({
78
+ async session(session) {
79
+ const token = await new SignJWT(session)
80
+ .setProtectedHeader({ alg: "RS512" })
81
+ .setExpirationTime("1yr")
82
+ .sign(await options.signing.privateKey());
83
+ deleteCookie(ctx, "provider");
84
+ deleteCookie(ctx, "response_type");
85
+ deleteCookie(ctx, "redirect_uri");
86
+ deleteCookie(ctx, "state");
87
+ const client_id = getCookie(ctx, "client_id");
88
+ const state = getCookie(ctx, "state");
89
+ if (response_type === "token") {
90
+ const location = new URL(redirect_uri);
91
+ location.hash = `access_token=${token}&state=${state || ""}`;
92
+ return ctx.redirect(location.toString(), 302);
93
+ }
94
+ if (response_type === "code") {
95
+ // This allows the code to be reused within a 30 second window
96
+ // The code should be single use but we're making this tradeoff to remain stateless
97
+ // In the future can store this in a dynamo table to ensure single use
98
+ const code = await new SignJWT({
99
+ client_id,
100
+ redirect_uri,
101
+ token,
102
+ })
103
+ .setProtectedHeader({ alg: "RS512" })
104
+ .setExpirationTime("30s")
105
+ .sign(await options.signing.privateKey());
106
+ const location = new URL(redirect_uri);
107
+ location.searchParams.set("code", code);
108
+ location.searchParams.set("state", state || "");
109
+ return ctx.redirect(location.toString(), 302);
110
+ }
111
+ ctx.status(400);
112
+ return ctx.text(`Unsupported response_type: ${response_type}`);
113
+ },
114
+ }, {
115
+ provider: ctx.get("provider"),
116
+ ...properties,
117
+ }, ctx.req.raw);
118
+ },
119
+ forward(ctx, response) {
120
+ return ctx.newResponse(response.body, response.status, Object.fromEntries(response.headers.entries()));
121
+ },
122
+ cookie(c, key, value, maxAge) {
123
+ setCookie(c, key, value, {
124
+ maxAge,
125
+ httpOnly: true,
126
+ ...(c.req.url.startsWith("https://")
127
+ ? { secure: true, sameSite: "None" }
128
+ : {}),
129
+ });
130
+ },
131
+ };
132
+ app.post("/token", async (c) => {
133
+ console.log("token request");
134
+ const form = await c.req.formData();
135
+ if (form.get("grant_type") !== "authorization_code") {
136
+ c.status(400);
137
+ return c.text("Invalid grant_type");
138
+ }
139
+ const code = form.get("code");
140
+ if (!code) {
141
+ c.status(400);
142
+ return c.text("Missing code");
143
+ }
144
+ const { payload } = await jwtVerify(code, await options.signing.publicKey());
145
+ if (payload.redirect_uri !== form.get("redirect_uri")) {
146
+ c.status(400);
147
+ return c.text("redirect_uri mismatch");
148
+ }
149
+ if (payload.client_id !== form.get("client_id")) {
150
+ c.status(400);
151
+ return c.text("client_id mismatch");
152
+ }
153
+ return c.json({
154
+ access_token: payload.token,
155
+ });
156
+ });
157
+ app.use("/:provider/authorize", async (c, next) => {
158
+ const provider = c.req.param("provider");
159
+ console.log("authorize request for", provider);
160
+ const response_type = c.req.query("response_type") || getCookie(c, "response_type");
161
+ const redirect_uri = c.req.query("redirect_uri") || getCookie(c, "redirect_uri");
162
+ const state = c.req.query("state") || getCookie(c, "state");
163
+ const client_id = c.req.query("client_id") || getCookie(c, "client_id");
164
+ if (!provider) {
165
+ c.status(400);
166
+ return c.text("Missing provider");
167
+ }
168
+ if (!redirect_uri) {
169
+ c.status(400);
170
+ return c.text("Missing redirect_uri");
171
+ }
172
+ if (!response_type) {
173
+ c.status(400);
174
+ return c.text("Missing response_type");
175
+ }
176
+ if (!client_id) {
177
+ c.status(400);
178
+ return c.text("Missing client_id");
179
+ }
180
+ options.cookie(c, "provider", provider, 60 * 10);
181
+ options.cookie(c, "response_type", response_type, 60 * 10);
182
+ options.cookie(c, "redirect_uri", redirect_uri, 60 * 10);
183
+ options.cookie(c, "state", state || "", 60 * 10);
184
+ options.cookie(c, "client_id", client_id || "", 60 * 10);
185
+ if (input.callbacks.auth.start) {
186
+ await input.callbacks.auth.start(c.req.raw);
187
+ }
188
+ await next();
189
+ });
190
+ for (const [name, value] of Object.entries(input.providers)) {
191
+ const route = new Hono();
192
+ route.use(async (c, next) => {
193
+ c.set("provider", name);
194
+ await next();
195
+ });
196
+ value(route, {
197
+ name,
198
+ ...options,
199
+ });
200
+ app.route(`/${name}`, route);
201
+ }
202
+ app.all("/*", async (c) => {
203
+ return c.notFound();
204
+ });
205
+ console.log(app.routes);
206
+ return app;
207
+ }
@@ -0,0 +1,10 @@
1
+ export * from "./session.js";
2
+ export * from "./handler.js";
3
+ export { Issuer } from "openid-client";
4
+ import { AuthHandler } from "./handler.js";
5
+ import { createSessionBuilder } from "./session.js";
6
+ export declare namespace auth {
7
+ type Issuer = import("openid-client").Issuer;
8
+ const authorizer: typeof AuthHandler;
9
+ const sessions: typeof createSessionBuilder;
10
+ }
@@ -0,0 +1,10 @@
1
+ export * from "./session.js";
2
+ export * from "./handler.js";
3
+ export { Issuer } from "openid-client";
4
+ import { AuthHandler } from "./handler.js";
5
+ import { createSessionBuilder } from "./session.js";
6
+ export var auth;
7
+ (function (auth) {
8
+ auth.authorizer = AuthHandler;
9
+ auth.sessions = createSessionBuilder;
10
+ })(auth || (auth = {}));
@@ -0,0 +1,25 @@
1
+ export type SessionBuilder = ReturnType<typeof createSessionBuilder>;
2
+ export declare function createSessionBuilder<SessionTypes extends Record<string, any> = {}>(): {
3
+ verify(token: string): Promise<{ [type in keyof SessionTypes]: {
4
+ type: type;
5
+ properties: SessionTypes[type];
6
+ }; }[keyof SessionTypes] | {
7
+ type: "public";
8
+ properties: {};
9
+ }>;
10
+ create(session: { [type in keyof SessionTypes]: {
11
+ type: type;
12
+ properties: SessionTypes[type];
13
+ }; }[keyof SessionTypes] | {
14
+ type: "public";
15
+ properties: {};
16
+ }): Promise<string>;
17
+ $type: SessionTypes;
18
+ $typeValues: { [type in keyof SessionTypes]: {
19
+ type: type;
20
+ properties: SessionTypes[type];
21
+ }; }[keyof SessionTypes] | {
22
+ type: "public";
23
+ properties: {};
24
+ };
25
+ };
@@ -0,0 +1,28 @@
1
+ import { SignJWT, importPKCS8, importSPKI, jwtVerify } from "jose";
2
+ import { Resource } from "../resource.js";
3
+ import process from "node:process";
4
+ export function createSessionBuilder() {
5
+ return {
6
+ async verify(token) {
7
+ const auth = Object.values(Resource).find((value) => value.publicKey);
8
+ if (!auth) {
9
+ throw new Error("No auth resource found. Make sure to link the auth resource to this function.");
10
+ }
11
+ const publicKey = auth.publicKey;
12
+ const result = await jwtVerify(token, await importSPKI(publicKey, "RS512"));
13
+ return result.payload;
14
+ },
15
+ async create(session) {
16
+ const privateKey = await importPKCS8(
17
+ // @ts-expect-error
18
+ process.env.AUTH_PRIVATE_KEY || Resource.AUTH_PRIVATE_KEY, "RS512");
19
+ const token = await new SignJWT(session)
20
+ .setProtectedHeader({ alg: "RS512" })
21
+ .setExpirationTime("1yr")
22
+ .sign(privateKey);
23
+ return token;
24
+ },
25
+ $type: {},
26
+ $typeValues: {},
27
+ };
28
+ }
@@ -0,0 +1,29 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { AwsOptions } from "../aws/client.js";
3
+ import { Resource } from "../resource.js";
4
+ import { event } from "../event/index.js";
5
+ import { EventBridgeEvent, EventBridgeHandler } from "aws-lambda";
6
+ export declare namespace bus {
7
+ type Name = Extract<typeof Resource, {
8
+ type: "sst.aws.Bus";
9
+ }>["name"];
10
+ function subscriber<Events extends event.Definition>(_events: Events | Events[], cb: (input: {
11
+ [K in Events["type"]]: Extract<Events, {
12
+ type: K;
13
+ }>["$payload"];
14
+ }[Events["type"]], raw: EventBridgeEvent<string, any>) => Promise<void>): EventBridgeHandler<string, any, void>;
15
+ /** @deprecated
16
+ * use bus.subscriber instead
17
+ * */
18
+ const handler: typeof subscriber;
19
+ function publish<Definition extends event.Definition = any>(name: string | {
20
+ name: string;
21
+ }, def: Definition | string, properties: Definition["$input"], options?: {
22
+ metadata?: Definition["$metadata"];
23
+ aws?: AwsOptions;
24
+ }): Promise<any>;
25
+ class PublishError extends Error {
26
+ readonly response: Response;
27
+ constructor(response: Response);
28
+ }
29
+ }
@@ -0,0 +1,67 @@
1
+ import { client } from "../aws/client.js";
2
+ import { Resource } from "../resource.js";
3
+ export var bus;
4
+ (function (bus) {
5
+ function url(options) {
6
+ const region = options?.region || client.region;
7
+ return `https://events.${region}.amazonaws.com/`;
8
+ }
9
+ function subscriber(_events, cb) {
10
+ return async function (event) {
11
+ const payload = {
12
+ type: event["detail-type"],
13
+ properties: event.detail.properties,
14
+ metadata: event.detail.metadata,
15
+ };
16
+ return cb(payload, event);
17
+ };
18
+ }
19
+ bus.subscriber = subscriber;
20
+ /** @deprecated
21
+ * use bus.subscriber instead
22
+ * */
23
+ bus.handler = subscriber;
24
+ async function publish(name, def, properties, options) {
25
+ const u = url(options?.aws);
26
+ const evt = typeof def === "string"
27
+ ? {
28
+ type: def,
29
+ properties,
30
+ metadata: options?.metadata || {},
31
+ }
32
+ : await def.create(properties);
33
+ const res = await client.fetch(u, {
34
+ method: "POST",
35
+ aws: options?.aws,
36
+ headers: {
37
+ "X-Amz-Target": "AWSEvents.PutEvents",
38
+ "Content-Type": "application/x-amz-json-1.1",
39
+ },
40
+ body: JSON.stringify({
41
+ Entries: [
42
+ {
43
+ Source: [Resource.App.name, Resource.App.stage].join("."),
44
+ DetailType: evt.type,
45
+ Detail: JSON.stringify({
46
+ metadata: evt.metadata,
47
+ payload: evt.properties,
48
+ }),
49
+ EventBusName: typeof name === "string" ? name : name.name,
50
+ },
51
+ ],
52
+ }),
53
+ });
54
+ if (!res.ok)
55
+ throw new PublishError(res);
56
+ return res.json();
57
+ }
58
+ bus.publish = publish;
59
+ class PublishError extends Error {
60
+ response;
61
+ constructor(response) {
62
+ super("Failed to publish event to bus");
63
+ this.response = response;
64
+ }
65
+ }
66
+ bus.PublishError = PublishError;
67
+ })(bus || (bus = {}));
@@ -0,0 +1,3 @@
1
+ import { AwsClient } from "aws4fetch";
2
+ export declare const client: AwsClient;
3
+ export type AwsOptions = Exclude<Parameters<AwsClient["fetch"]>[1], null | undefined>["aws"];
@@ -0,0 +1,7 @@
1
+ import { AwsClient } from "aws4fetch";
2
+ export const client = new AwsClient({
3
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
4
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
5
+ sessionToken: process.env.AWS_SESSION_TOKEN,
6
+ region: process.env.AWS_REGION,
7
+ });
@@ -0,0 +1,61 @@
1
+ import { IoTCustomAuthorizerHandler } from "aws-lambda";
2
+ export declare namespace realtime {
3
+ interface AuthResult {
4
+ /**
5
+ * The topics the client can subscribe to.
6
+ * @example
7
+ * For example, this subscribes to specific topics.
8
+ * ```js
9
+ * {
10
+ * subscribe: ["chat/room1", "chat/room2"]
11
+ * }
12
+ * ```
13
+ *
14
+ * And to subscribe to all topics under a specific prefix.
15
+ * ```js
16
+ * {
17
+ * subscribe: ["chat/*"]
18
+ * }
19
+ * ```
20
+ */
21
+ subscribe?: string[];
22
+ /**
23
+ * The topics the client can publish to.
24
+ * @example
25
+ * For example, this publishes to specific topics.
26
+ * ```js
27
+ * {
28
+ * publish: ["chat/room1", "chat/room2"]
29
+ * }
30
+ * ```
31
+ * And to publish to all topics under a specific prefix.
32
+ * ```js
33
+ * {
34
+ * publish: ["chat/*"]
35
+ * }
36
+ * ```
37
+ */
38
+ publish?: string[];
39
+ }
40
+ /**
41
+ * Creates an authorization handler for the `Realtime` component, that validates
42
+ * the token and grants permissions for the topics the client can subscribe and publish to.
43
+ *
44
+ * @example
45
+ * ```js
46
+ * import { realtime } from "sst/aws/realtime";
47
+ *
48
+ * export const handler = realtime.authorizer(async (token) => {
49
+ * // Validate the token
50
+ * console.log(token);
51
+ *
52
+ * // Return the topics to subscribe and publish
53
+ * return {
54
+ * subscribe: [`${Resource.App.name}/${Resource.App.stage}/chat/room1`],
55
+ * publish: [`${Resource.App.name}/${Resource.App.stage}/chat/room1`],
56
+ * };
57
+ * });
58
+ * ```
59
+ */
60
+ function authorizer(input: (token: string) => Promise<AuthResult>): IoTCustomAuthorizerHandler;
61
+ }
@@ -0,0 +1,76 @@
1
+ export var realtime;
2
+ (function (realtime) {
3
+ /**
4
+ * Creates an authorization handler for the `Realtime` component, that validates
5
+ * the token and grants permissions for the topics the client can subscribe and publish to.
6
+ *
7
+ * @example
8
+ * ```js
9
+ * import { realtime } from "sst/aws/realtime";
10
+ *
11
+ * export const handler = realtime.authorizer(async (token) => {
12
+ * // Validate the token
13
+ * console.log(token);
14
+ *
15
+ * // Return the topics to subscribe and publish
16
+ * return {
17
+ * subscribe: [`${Resource.App.name}/${Resource.App.stage}/chat/room1`],
18
+ * publish: [`${Resource.App.name}/${Resource.App.stage}/chat/room1`],
19
+ * };
20
+ * });
21
+ * ```
22
+ */
23
+ function authorizer(input) {
24
+ return async (evt, context) => {
25
+ const [, , , region, accountId] = context.invokedFunctionArn.split(":");
26
+ const token = Buffer.from(evt.protocolData.mqtt?.password ?? "", "base64").toString();
27
+ const ret = await input(token);
28
+ return {
29
+ isAuthenticated: true,
30
+ principalId: Date.now().toString(),
31
+ disconnectAfterInSeconds: 86400,
32
+ refreshAfterInSeconds: 300,
33
+ policyDocuments: [
34
+ {
35
+ Version: "2012-10-17",
36
+ Statement: [
37
+ {
38
+ Action: "iot:Connect",
39
+ Effect: "Allow",
40
+ Resource: "*",
41
+ },
42
+ ...(ret.subscribe
43
+ ? [
44
+ {
45
+ Action: "iot:Receive",
46
+ Effect: "Allow",
47
+ Resource: ret.subscribe.map((t) => `arn:aws:iot:${region}:${accountId}:topic/${t}`),
48
+ },
49
+ ]
50
+ : []),
51
+ ...(ret.subscribe
52
+ ? [
53
+ {
54
+ Action: "iot:Subscribe",
55
+ Effect: "Allow",
56
+ Resource: ret.subscribe.map((t) => `arn:aws:iot:${region}:${accountId}:topicfilter/${t}`),
57
+ },
58
+ ]
59
+ : []),
60
+ ...(ret.publish
61
+ ? [
62
+ {
63
+ Action: "iot:Publish",
64
+ Effect: "Allow",
65
+ Resource: ret.publish.map((t) => `arn:aws:iot:${region}:${accountId}:topic/${t}`),
66
+ },
67
+ ]
68
+ : []),
69
+ ],
70
+ },
71
+ ],
72
+ };
73
+ };
74
+ }
75
+ realtime.authorizer = authorizer;
76
+ })(realtime || (realtime = {}));
@@ -0,0 +1,74 @@
1
+ import { ZodSchema, z } from "zod";
2
+ export declare namespace event {
3
+ export type Definition = {
4
+ type: string;
5
+ $input: any;
6
+ $output: any;
7
+ $metadata: any;
8
+ $payload: any;
9
+ create: (...args: any[]) => Promise<any>;
10
+ };
11
+ export function builder<Metadata extends ((type: string, properties: any) => any) | Parameters<Validator>[0], Validator extends (schema: any) => (input: any) => any = typeof ZodValidator>(input: {
12
+ validator?: Validator;
13
+ metadata?: Metadata;
14
+ }): {
15
+ <Type extends string, Schema extends Parameters<Validator>[0]>(type: Type, schema: Schema): {
16
+ create: Metadata extends (type: string, properties: any) => any ? (properties: inferParser<Schema>["in"]) => Promise<{
17
+ type: Type;
18
+ properties: inferParser<Schema>["out"];
19
+ metadata: Metadata extends (type: string, properties: any) => any ? ReturnType<Metadata> : inferParser<Metadata>["out"];
20
+ }> : (properties: inferParser<Schema>["in"], metadata: inferParser<Metadata>["in"]) => Promise<{
21
+ type: Type;
22
+ properties: inferParser<Schema>["out"];
23
+ metadata: Metadata extends (type: string, properties: any) => any ? ReturnType<Metadata> : inferParser<Metadata>["out"];
24
+ }>;
25
+ type: Type;
26
+ $input: inferParser<Schema>["in"];
27
+ $output: inferParser<Schema>["out"];
28
+ $payload: {
29
+ type: Type;
30
+ properties: inferParser<Schema>["out"];
31
+ metadata: Metadata extends (type: string, properties: any) => any ? ReturnType<Metadata> : inferParser<Metadata>["out"];
32
+ };
33
+ $metadata: Metadata extends (type: string, properties: any) => any ? ReturnType<Metadata> : inferParser<Metadata>["out"];
34
+ };
35
+ coerce<Events extends Definition>(_events: Events | Events[], raw: any): { [K in Events["type"]]: Extract<Events, {
36
+ type: K;
37
+ }>["$payload"]; }[Events["type"]];
38
+ };
39
+ export function ZodValidator<Schema extends ZodSchema>(schema: Schema): (input: z.input<Schema>) => z.output<Schema>;
40
+ type ParserZodEsque<TInput, TParsedInput> = {
41
+ _input: TInput;
42
+ _output: TParsedInput;
43
+ };
44
+ type ParserValibotEsque<TInput, TParsedInput> = {
45
+ _types?: {
46
+ input: TInput;
47
+ output: TParsedInput;
48
+ };
49
+ };
50
+ type ParserMyZodEsque<TInput> = {
51
+ parse: (input: any) => TInput;
52
+ };
53
+ type ParserSuperstructEsque<TInput> = {
54
+ create: (input: unknown) => TInput;
55
+ };
56
+ type ParserCustomValidatorEsque<TInput> = (input: unknown) => Promise<TInput> | TInput;
57
+ type ParserYupEsque<TInput> = {
58
+ validateSync: (input: unknown) => TInput;
59
+ };
60
+ type ParserScaleEsque<TInput> = {
61
+ assert(value: unknown): asserts value is TInput;
62
+ };
63
+ export type ParserWithoutInput<TInput> = ParserCustomValidatorEsque<TInput> | ParserMyZodEsque<TInput> | ParserScaleEsque<TInput> | ParserSuperstructEsque<TInput> | ParserYupEsque<TInput>;
64
+ export type ParserWithInputOutput<TInput, TParsedInput> = ParserZodEsque<TInput, TParsedInput> | ParserValibotEsque<TInput, TParsedInput>;
65
+ export type Parser = ParserWithInputOutput<any, any> | ParserWithoutInput<any>;
66
+ export type inferParser<TParser extends Parser> = TParser extends ParserWithInputOutput<infer $TIn, infer $TOut> ? {
67
+ in: $TIn;
68
+ out: $TOut;
69
+ } : TParser extends ParserWithoutInput<infer $InOut> ? {
70
+ in: $InOut;
71
+ out: $InOut;
72
+ } : never;
73
+ export {};
74
+ }