sst-http 0.1.6 → 0.2.0
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.
- package/README.md +13 -15
- package/dist/infra.cjs +59 -44
- package/dist/infra.d.cts +3 -3
- package/dist/infra.d.ts +3 -3
- package/dist/infra.js +59 -44
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ Mark a route with `@FirebaseAuth()` and the manifest records it as protected. Th
|
|
|
97
97
|
|
|
98
98
|
## Wire API Gateway
|
|
99
99
|
|
|
100
|
-
`sst-http/infra` ships with a manifest-driven wiring utility plus adapters for HTTP API (ApiGatewayV2) and REST API (ApiGateway). The example below
|
|
100
|
+
`sst-http/infra` ships with a manifest-driven wiring utility plus adapters for HTTP API (ApiGatewayV2) and REST API (ApiGateway). The example below wires all routes to a single Lambda function inside `sst.config.ts`.
|
|
101
101
|
|
|
102
102
|
```ts
|
|
103
103
|
// sst.config.ts
|
|
@@ -113,23 +113,18 @@ export default $config({
|
|
|
113
113
|
} = await import("sst-http/infra");
|
|
114
114
|
|
|
115
115
|
const manifest = loadRoutesManifest("routes.manifest.json");
|
|
116
|
-
const { api, registerRoute, ensureJwtAuthorizer } = httpApiAdapter({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
memory: "512 MB",
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
},
|
|
116
|
+
const { api, registerRoute, ensureJwtAuthorizer } = httpApiAdapter({ apiName: "Api" });
|
|
117
|
+
|
|
118
|
+
// Single Lambda for all routes
|
|
119
|
+
const handler = new sst.aws.Function("Handler", {
|
|
120
|
+
handler: "src/server.handler",
|
|
121
|
+
runtime: "nodejs20.x",
|
|
122
|
+
timeout: "10 seconds",
|
|
123
|
+
memory: "512 MB",
|
|
129
124
|
});
|
|
130
125
|
|
|
131
126
|
wireApiFromManifest(manifest, {
|
|
132
|
-
|
|
127
|
+
handler,
|
|
133
128
|
firebaseProjectId: process.env.FIREBASE_PROJECT_ID!,
|
|
134
129
|
registerRoute,
|
|
135
130
|
ensureJwtAuthorizer,
|
|
@@ -142,6 +137,9 @@ export default $config({
|
|
|
142
137
|
|
|
143
138
|
Swap in `restApiAdapter` if you prefer API Gateway REST APIs—the wiring contract is identical.
|
|
144
139
|
|
|
140
|
+
> Tip
|
|
141
|
+
> Set `FIREBASE_PROJECT_ID` in your environment when using `@FirebaseAuth()` so the JWT authorizer is configured correctly.
|
|
142
|
+
|
|
145
143
|
## Publishing
|
|
146
144
|
|
|
147
145
|
```bash
|
package/dist/infra.cjs
CHANGED
|
@@ -66,7 +66,7 @@ function wireApiFromManifest(manifest, opts) {
|
|
|
66
66
|
ref: firebaseAuthorizerRef
|
|
67
67
|
} : void 0;
|
|
68
68
|
opts.registerRoute(route.method, path, {
|
|
69
|
-
handler: opts.
|
|
69
|
+
handler: opts.handler,
|
|
70
70
|
protected: isProtected,
|
|
71
71
|
authorizer: authConfig
|
|
72
72
|
});
|
|
@@ -90,25 +90,34 @@ function httpApiAdapter(args) {
|
|
|
90
90
|
return authorizers.get(name);
|
|
91
91
|
}
|
|
92
92
|
const apiAny = api;
|
|
93
|
-
let ref =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
issuer: cfg.issuer,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
if (typeof apiAny.addAuthorizers === "function") {
|
|
93
|
+
let ref = void 0;
|
|
94
|
+
if (typeof apiAny["addAuthorizer"] === "function") {
|
|
95
|
+
const created = apiAny.addAuthorizer({
|
|
96
|
+
name,
|
|
97
|
+
jwt: { issuer: cfg.issuer, audiences: cfg.audiences }
|
|
98
|
+
});
|
|
99
|
+
ref = created.id;
|
|
100
|
+
} else if (typeof apiAny.addAuthorizers === "function") {
|
|
102
101
|
apiAny.addAuthorizers({
|
|
103
|
-
[name]:
|
|
102
|
+
[name]: {
|
|
103
|
+
type: "jwt",
|
|
104
|
+
jwt: {
|
|
105
|
+
issuer: cfg.issuer,
|
|
106
|
+
audience: cfg.audiences
|
|
107
|
+
}
|
|
108
|
+
}
|
|
104
109
|
});
|
|
110
|
+
ref = name;
|
|
105
111
|
} else if (typeof apiAny.authorizer === "function") {
|
|
106
|
-
ref = apiAny.authorizer(name,
|
|
112
|
+
ref = apiAny.authorizer(name, {
|
|
113
|
+
type: "jwt",
|
|
114
|
+
jwt: {
|
|
115
|
+
issuer: cfg.issuer,
|
|
116
|
+
audience: cfg.audiences
|
|
117
|
+
}
|
|
118
|
+
});
|
|
107
119
|
} else {
|
|
108
|
-
|
|
109
|
-
...apiAny.authorizers ?? {},
|
|
110
|
-
[name]: payload
|
|
111
|
-
};
|
|
120
|
+
throw new Error("ApiGatewayV2 instance does not support authorizers");
|
|
112
121
|
}
|
|
113
122
|
authorizers.set(name, ref);
|
|
114
123
|
return ref;
|
|
@@ -116,31 +125,34 @@ function httpApiAdapter(args) {
|
|
|
116
125
|
const registerRoute = (method, path, config) => {
|
|
117
126
|
const apiAny = api;
|
|
118
127
|
const routeKey = `${method} ${path}`;
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
128
|
+
const asAny = config.handler;
|
|
129
|
+
const handlerInput = typeof asAny === "string" ? asAny : asAny && typeof asAny.arn !== "undefined" ? asAny.arn : asAny && typeof asAny.handler === "string" ? asAny.handler : asAny === void 0 ? void 0 : (() => {
|
|
130
|
+
throw new Error("Unsupported handler type: provide a handler string, FunctionArgs, or a Function ARN/output");
|
|
131
|
+
})();
|
|
132
|
+
const args2 = {};
|
|
122
133
|
if (config.protected && config.authorizer) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
routeConfig.authorizerOptional = true;
|
|
130
|
-
}
|
|
134
|
+
args2.auth = {
|
|
135
|
+
jwt: {
|
|
136
|
+
authorizer: config.authorizer.ref ?? config.authorizer.name,
|
|
137
|
+
scopes: config.authorizer.roles
|
|
138
|
+
}
|
|
139
|
+
};
|
|
131
140
|
}
|
|
132
141
|
if (typeof apiAny.route === "function") {
|
|
133
|
-
apiAny.route(routeKey,
|
|
142
|
+
apiAny.route(routeKey, handlerInput, args2);
|
|
134
143
|
return;
|
|
135
144
|
}
|
|
136
145
|
if (typeof apiAny.addRoutes === "function") {
|
|
137
146
|
apiAny.addRoutes({
|
|
138
|
-
[routeKey]:
|
|
147
|
+
[routeKey]: {
|
|
148
|
+
handler: handlerInput,
|
|
149
|
+
...args2
|
|
150
|
+
}
|
|
139
151
|
});
|
|
140
152
|
return;
|
|
141
153
|
}
|
|
142
154
|
if (typeof apiAny.addRoute === "function") {
|
|
143
|
-
apiAny.addRoute(routeKey,
|
|
155
|
+
apiAny.addRoute(routeKey, { handler: handlerInput, ...args2 });
|
|
144
156
|
return;
|
|
145
157
|
}
|
|
146
158
|
throw new Error("Unsupported ApiGatewayV2 instance: expected route() or addRoutes() method.");
|
|
@@ -186,31 +198,34 @@ function restApiAdapter(args) {
|
|
|
186
198
|
const registerRoute = (method, path, config) => {
|
|
187
199
|
const apiAny = api;
|
|
188
200
|
const routeKey = `${method} ${path}`;
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
201
|
+
const asAny = config.handler;
|
|
202
|
+
const handlerInput = typeof asAny === "string" ? asAny : asAny && typeof asAny.arn !== "undefined" ? asAny.arn : asAny && typeof asAny.handler === "string" ? asAny.handler : asAny === void 0 ? void 0 : (() => {
|
|
203
|
+
throw new Error("Unsupported handler type: provide a handler string, FunctionArgs, or a Function ARN/output");
|
|
204
|
+
})();
|
|
205
|
+
const args2 = {};
|
|
192
206
|
if (config.protected && config.authorizer) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
routeConfig.authorizerOptional = true;
|
|
200
|
-
}
|
|
207
|
+
args2.auth = {
|
|
208
|
+
jwt: {
|
|
209
|
+
authorizer: config.authorizer.ref ?? config.authorizer.name,
|
|
210
|
+
scopes: config.authorizer.roles
|
|
211
|
+
}
|
|
212
|
+
};
|
|
201
213
|
}
|
|
202
214
|
if (typeof apiAny.route === "function") {
|
|
203
|
-
apiAny.route(routeKey,
|
|
215
|
+
apiAny.route(routeKey, handlerInput, args2);
|
|
204
216
|
return;
|
|
205
217
|
}
|
|
206
218
|
if (typeof apiAny.addRoutes === "function") {
|
|
207
219
|
apiAny.addRoutes({
|
|
208
|
-
[routeKey]:
|
|
220
|
+
[routeKey]: {
|
|
221
|
+
handler: handlerInput,
|
|
222
|
+
...args2
|
|
223
|
+
}
|
|
209
224
|
});
|
|
210
225
|
return;
|
|
211
226
|
}
|
|
212
227
|
if (typeof apiAny.addRoute === "function") {
|
|
213
|
-
apiAny.addRoute(routeKey,
|
|
228
|
+
apiAny.addRoute(routeKey, { handler: handlerInput, ...args2 });
|
|
214
229
|
return;
|
|
215
230
|
}
|
|
216
231
|
throw new Error("Unsupported ApiGateway instance: expected route() or addRoutes() method.");
|
package/dist/infra.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ export { b as RoutesManifestAuth, a as RoutesManifestRoute } from './types-D69iu
|
|
|
3
3
|
import 'aws-lambda';
|
|
4
4
|
|
|
5
5
|
type SstApiGateway = {
|
|
6
|
-
route?: (routeKey: string,
|
|
6
|
+
route?: (routeKey: string, handlerOrConfig: unknown, args?: Record<string, unknown>) => unknown;
|
|
7
7
|
addRoutes?: (routes: Record<string, Record<string, unknown>>) => unknown;
|
|
8
8
|
addRoute?: (routeKey: string, config: Record<string, unknown>) => unknown;
|
|
9
9
|
addAuthorizers?: (authorizers: Record<string, unknown>) => unknown;
|
|
@@ -21,7 +21,7 @@ type AwsSource = {
|
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
type RegisterRouteConfig = {
|
|
24
|
-
handler:
|
|
24
|
+
handler: unknown;
|
|
25
25
|
protected: boolean;
|
|
26
26
|
authorizer?: {
|
|
27
27
|
name: string;
|
|
@@ -36,7 +36,7 @@ type EnsureJwtAuthorizer = (name: string, cfg: {
|
|
|
36
36
|
audiences: string[];
|
|
37
37
|
}) => unknown;
|
|
38
38
|
declare function wireApiFromManifest(manifest: RoutesManifest, opts: {
|
|
39
|
-
|
|
39
|
+
handler: unknown;
|
|
40
40
|
firebaseProjectId: string;
|
|
41
41
|
registerRoute: RegisterRoute;
|
|
42
42
|
ensureJwtAuthorizer: EnsureJwtAuthorizer;
|
package/dist/infra.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { b as RoutesManifestAuth, a as RoutesManifestRoute } from './types-D69iu
|
|
|
3
3
|
import 'aws-lambda';
|
|
4
4
|
|
|
5
5
|
type SstApiGateway = {
|
|
6
|
-
route?: (routeKey: string,
|
|
6
|
+
route?: (routeKey: string, handlerOrConfig: unknown, args?: Record<string, unknown>) => unknown;
|
|
7
7
|
addRoutes?: (routes: Record<string, Record<string, unknown>>) => unknown;
|
|
8
8
|
addRoute?: (routeKey: string, config: Record<string, unknown>) => unknown;
|
|
9
9
|
addAuthorizers?: (authorizers: Record<string, unknown>) => unknown;
|
|
@@ -21,7 +21,7 @@ type AwsSource = {
|
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
type RegisterRouteConfig = {
|
|
24
|
-
handler:
|
|
24
|
+
handler: unknown;
|
|
25
25
|
protected: boolean;
|
|
26
26
|
authorizer?: {
|
|
27
27
|
name: string;
|
|
@@ -36,7 +36,7 @@ type EnsureJwtAuthorizer = (name: string, cfg: {
|
|
|
36
36
|
audiences: string[];
|
|
37
37
|
}) => unknown;
|
|
38
38
|
declare function wireApiFromManifest(manifest: RoutesManifest, opts: {
|
|
39
|
-
|
|
39
|
+
handler: unknown;
|
|
40
40
|
firebaseProjectId: string;
|
|
41
41
|
registerRoute: RegisterRoute;
|
|
42
42
|
ensureJwtAuthorizer: EnsureJwtAuthorizer;
|
package/dist/infra.js
CHANGED
|
@@ -39,7 +39,7 @@ function wireApiFromManifest(manifest, opts) {
|
|
|
39
39
|
ref: firebaseAuthorizerRef
|
|
40
40
|
} : void 0;
|
|
41
41
|
opts.registerRoute(route.method, path, {
|
|
42
|
-
handler: opts.
|
|
42
|
+
handler: opts.handler,
|
|
43
43
|
protected: isProtected,
|
|
44
44
|
authorizer: authConfig
|
|
45
45
|
});
|
|
@@ -63,25 +63,34 @@ function httpApiAdapter(args) {
|
|
|
63
63
|
return authorizers.get(name);
|
|
64
64
|
}
|
|
65
65
|
const apiAny = api;
|
|
66
|
-
let ref =
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
issuer: cfg.issuer,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
if (typeof apiAny.addAuthorizers === "function") {
|
|
66
|
+
let ref = void 0;
|
|
67
|
+
if (typeof apiAny["addAuthorizer"] === "function") {
|
|
68
|
+
const created = apiAny.addAuthorizer({
|
|
69
|
+
name,
|
|
70
|
+
jwt: { issuer: cfg.issuer, audiences: cfg.audiences }
|
|
71
|
+
});
|
|
72
|
+
ref = created.id;
|
|
73
|
+
} else if (typeof apiAny.addAuthorizers === "function") {
|
|
75
74
|
apiAny.addAuthorizers({
|
|
76
|
-
[name]:
|
|
75
|
+
[name]: {
|
|
76
|
+
type: "jwt",
|
|
77
|
+
jwt: {
|
|
78
|
+
issuer: cfg.issuer,
|
|
79
|
+
audience: cfg.audiences
|
|
80
|
+
}
|
|
81
|
+
}
|
|
77
82
|
});
|
|
83
|
+
ref = name;
|
|
78
84
|
} else if (typeof apiAny.authorizer === "function") {
|
|
79
|
-
ref = apiAny.authorizer(name,
|
|
85
|
+
ref = apiAny.authorizer(name, {
|
|
86
|
+
type: "jwt",
|
|
87
|
+
jwt: {
|
|
88
|
+
issuer: cfg.issuer,
|
|
89
|
+
audience: cfg.audiences
|
|
90
|
+
}
|
|
91
|
+
});
|
|
80
92
|
} else {
|
|
81
|
-
|
|
82
|
-
...apiAny.authorizers ?? {},
|
|
83
|
-
[name]: payload
|
|
84
|
-
};
|
|
93
|
+
throw new Error("ApiGatewayV2 instance does not support authorizers");
|
|
85
94
|
}
|
|
86
95
|
authorizers.set(name, ref);
|
|
87
96
|
return ref;
|
|
@@ -89,31 +98,34 @@ function httpApiAdapter(args) {
|
|
|
89
98
|
const registerRoute = (method, path, config) => {
|
|
90
99
|
const apiAny = api;
|
|
91
100
|
const routeKey = `${method} ${path}`;
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
const asAny = config.handler;
|
|
102
|
+
const handlerInput = typeof asAny === "string" ? asAny : asAny && typeof asAny.arn !== "undefined" ? asAny.arn : asAny && typeof asAny.handler === "string" ? asAny.handler : asAny === void 0 ? void 0 : (() => {
|
|
103
|
+
throw new Error("Unsupported handler type: provide a handler string, FunctionArgs, or a Function ARN/output");
|
|
104
|
+
})();
|
|
105
|
+
const args2 = {};
|
|
95
106
|
if (config.protected && config.authorizer) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
routeConfig.authorizerOptional = true;
|
|
103
|
-
}
|
|
107
|
+
args2.auth = {
|
|
108
|
+
jwt: {
|
|
109
|
+
authorizer: config.authorizer.ref ?? config.authorizer.name,
|
|
110
|
+
scopes: config.authorizer.roles
|
|
111
|
+
}
|
|
112
|
+
};
|
|
104
113
|
}
|
|
105
114
|
if (typeof apiAny.route === "function") {
|
|
106
|
-
apiAny.route(routeKey,
|
|
115
|
+
apiAny.route(routeKey, handlerInput, args2);
|
|
107
116
|
return;
|
|
108
117
|
}
|
|
109
118
|
if (typeof apiAny.addRoutes === "function") {
|
|
110
119
|
apiAny.addRoutes({
|
|
111
|
-
[routeKey]:
|
|
120
|
+
[routeKey]: {
|
|
121
|
+
handler: handlerInput,
|
|
122
|
+
...args2
|
|
123
|
+
}
|
|
112
124
|
});
|
|
113
125
|
return;
|
|
114
126
|
}
|
|
115
127
|
if (typeof apiAny.addRoute === "function") {
|
|
116
|
-
apiAny.addRoute(routeKey,
|
|
128
|
+
apiAny.addRoute(routeKey, { handler: handlerInput, ...args2 });
|
|
117
129
|
return;
|
|
118
130
|
}
|
|
119
131
|
throw new Error("Unsupported ApiGatewayV2 instance: expected route() or addRoutes() method.");
|
|
@@ -159,31 +171,34 @@ function restApiAdapter(args) {
|
|
|
159
171
|
const registerRoute = (method, path, config) => {
|
|
160
172
|
const apiAny = api;
|
|
161
173
|
const routeKey = `${method} ${path}`;
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
174
|
+
const asAny = config.handler;
|
|
175
|
+
const handlerInput = typeof asAny === "string" ? asAny : asAny && typeof asAny.arn !== "undefined" ? asAny.arn : asAny && typeof asAny.handler === "string" ? asAny.handler : asAny === void 0 ? void 0 : (() => {
|
|
176
|
+
throw new Error("Unsupported handler type: provide a handler string, FunctionArgs, or a Function ARN/output");
|
|
177
|
+
})();
|
|
178
|
+
const args2 = {};
|
|
165
179
|
if (config.protected && config.authorizer) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
routeConfig.authorizerOptional = true;
|
|
173
|
-
}
|
|
180
|
+
args2.auth = {
|
|
181
|
+
jwt: {
|
|
182
|
+
authorizer: config.authorizer.ref ?? config.authorizer.name,
|
|
183
|
+
scopes: config.authorizer.roles
|
|
184
|
+
}
|
|
185
|
+
};
|
|
174
186
|
}
|
|
175
187
|
if (typeof apiAny.route === "function") {
|
|
176
|
-
apiAny.route(routeKey,
|
|
188
|
+
apiAny.route(routeKey, handlerInput, args2);
|
|
177
189
|
return;
|
|
178
190
|
}
|
|
179
191
|
if (typeof apiAny.addRoutes === "function") {
|
|
180
192
|
apiAny.addRoutes({
|
|
181
|
-
[routeKey]:
|
|
193
|
+
[routeKey]: {
|
|
194
|
+
handler: handlerInput,
|
|
195
|
+
...args2
|
|
196
|
+
}
|
|
182
197
|
});
|
|
183
198
|
return;
|
|
184
199
|
}
|
|
185
200
|
if (typeof apiAny.addRoute === "function") {
|
|
186
|
-
apiAny.addRoute(routeKey,
|
|
201
|
+
apiAny.addRoute(routeKey, { handler: handlerInput, ...args2 });
|
|
187
202
|
return;
|
|
188
203
|
}
|
|
189
204
|
throw new Error("Unsupported ApiGateway instance: expected route() or addRoutes() method.");
|