sst-http 0.1.6
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/LICENSE +21 -0
- package/README.md +157 -0
- package/dist/cli.cjs +262 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +265 -0
- package/dist/index.cjs +558 -0
- package/dist/index.d.cts +42 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +512 -0
- package/dist/infra.cjs +230 -0
- package/dist/infra.d.cts +61 -0
- package/dist/infra.d.ts +61 -0
- package/dist/infra.js +202 -0
- package/dist/types-D69iuoxv.d.cts +54 -0
- package/dist/types-D69iuoxv.d.ts +54 -0
- package/package.json +79 -0
package/dist/infra.cjs
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/infra.ts
|
|
21
|
+
var infra_exports = {};
|
|
22
|
+
__export(infra_exports, {
|
|
23
|
+
httpApiAdapter: () => httpApiAdapter,
|
|
24
|
+
loadRoutesManifest: () => loadRoutesManifest,
|
|
25
|
+
restApiAdapter: () => restApiAdapter,
|
|
26
|
+
wireApiFromManifest: () => wireApiFromManifest
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(infra_exports);
|
|
29
|
+
var import_node_fs = require("fs");
|
|
30
|
+
var import_node_path = require("path");
|
|
31
|
+
function ensureSstAws(source) {
|
|
32
|
+
if (source?.sst?.aws) {
|
|
33
|
+
return source.sst.aws;
|
|
34
|
+
}
|
|
35
|
+
const aws = globalThis.sst?.aws;
|
|
36
|
+
if (!aws) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"SST aws namespace is not available. Ensure this code runs within an SST config."
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return aws;
|
|
42
|
+
}
|
|
43
|
+
function wireApiFromManifest(manifest, opts) {
|
|
44
|
+
if (!manifest || !Array.isArray(manifest.routes)) {
|
|
45
|
+
throw new Error("Invalid routes manifest");
|
|
46
|
+
}
|
|
47
|
+
const firebaseRoutes = manifest.routes.filter((route) => route.auth.type === "firebase");
|
|
48
|
+
let firebaseAuthorizerRef;
|
|
49
|
+
if (firebaseRoutes.length > 0) {
|
|
50
|
+
if (!opts.firebaseProjectId) {
|
|
51
|
+
throw new Error("firebaseProjectId is required when using @FirebaseAuth()");
|
|
52
|
+
}
|
|
53
|
+
const issuer = `https://securetoken.google.com/${opts.firebaseProjectId}`;
|
|
54
|
+
firebaseAuthorizerRef = opts.ensureJwtAuthorizer("firebase", {
|
|
55
|
+
issuer,
|
|
56
|
+
audiences: [opts.firebaseProjectId]
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
for (const route of manifest.routes) {
|
|
60
|
+
const isProtected = route.auth.type === "firebase";
|
|
61
|
+
const path = route.path.startsWith("/") ? route.path : `/${route.path}`;
|
|
62
|
+
const authConfig = isProtected && route.auth.type === "firebase" ? {
|
|
63
|
+
name: "firebase",
|
|
64
|
+
optional: route.auth.optional,
|
|
65
|
+
roles: route.auth.roles,
|
|
66
|
+
ref: firebaseAuthorizerRef
|
|
67
|
+
} : void 0;
|
|
68
|
+
opts.registerRoute(route.method, path, {
|
|
69
|
+
handler: opts.handlerFile,
|
|
70
|
+
protected: isProtected,
|
|
71
|
+
authorizer: authConfig
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function loadRoutesManifest(filePath) {
|
|
76
|
+
const resolved = (0, import_node_path.resolve)(filePath);
|
|
77
|
+
const contents = (0, import_node_fs.readFileSync)(resolved, "utf8");
|
|
78
|
+
const manifest = JSON.parse(contents);
|
|
79
|
+
if (!manifest || !Array.isArray(manifest.routes)) {
|
|
80
|
+
throw new Error(`Invalid routes manifest at ${resolved}`);
|
|
81
|
+
}
|
|
82
|
+
return manifest;
|
|
83
|
+
}
|
|
84
|
+
function httpApiAdapter(args) {
|
|
85
|
+
const aws = args?.api ? void 0 : ensureSstAws(args);
|
|
86
|
+
const api = args?.api ?? new aws.ApiGatewayV2(args?.apiName ?? "HttpApi", args?.apiArgs);
|
|
87
|
+
const authorizers = /* @__PURE__ */ new Map();
|
|
88
|
+
const ensureJwtAuthorizer = (name, cfg) => {
|
|
89
|
+
if (authorizers.has(name)) {
|
|
90
|
+
return authorizers.get(name);
|
|
91
|
+
}
|
|
92
|
+
const apiAny = api;
|
|
93
|
+
let ref = name;
|
|
94
|
+
const payload = {
|
|
95
|
+
type: "jwt",
|
|
96
|
+
jwt: {
|
|
97
|
+
issuer: cfg.issuer,
|
|
98
|
+
audience: cfg.audiences
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
if (typeof apiAny.addAuthorizers === "function") {
|
|
102
|
+
apiAny.addAuthorizers({
|
|
103
|
+
[name]: payload
|
|
104
|
+
});
|
|
105
|
+
} else if (typeof apiAny.authorizer === "function") {
|
|
106
|
+
ref = apiAny.authorizer(name, payload);
|
|
107
|
+
} else {
|
|
108
|
+
apiAny.authorizers = {
|
|
109
|
+
...apiAny.authorizers ?? {},
|
|
110
|
+
[name]: payload
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
authorizers.set(name, ref);
|
|
114
|
+
return ref;
|
|
115
|
+
};
|
|
116
|
+
const registerRoute = (method, path, config) => {
|
|
117
|
+
const apiAny = api;
|
|
118
|
+
const routeKey = `${method} ${path}`;
|
|
119
|
+
const routeConfig = {
|
|
120
|
+
handler: config.handler
|
|
121
|
+
};
|
|
122
|
+
if (config.protected && config.authorizer) {
|
|
123
|
+
routeConfig.authorizer = config.authorizer.ref ?? config.authorizer.name;
|
|
124
|
+
routeConfig.authorizationType = "JWT";
|
|
125
|
+
if (config.authorizer.roles && config.authorizer.roles.length > 0) {
|
|
126
|
+
routeConfig.authorizationScopes = config.authorizer.roles;
|
|
127
|
+
}
|
|
128
|
+
if (config.authorizer.optional) {
|
|
129
|
+
routeConfig.authorizerOptional = true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (typeof apiAny.route === "function") {
|
|
133
|
+
apiAny.route(routeKey, routeConfig);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (typeof apiAny.addRoutes === "function") {
|
|
137
|
+
apiAny.addRoutes({
|
|
138
|
+
[routeKey]: routeConfig
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (typeof apiAny.addRoute === "function") {
|
|
143
|
+
apiAny.addRoute(routeKey, routeConfig);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
throw new Error("Unsupported ApiGatewayV2 instance: expected route() or addRoutes() method.");
|
|
147
|
+
};
|
|
148
|
+
return {
|
|
149
|
+
api,
|
|
150
|
+
registerRoute,
|
|
151
|
+
ensureJwtAuthorizer
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function restApiAdapter(args) {
|
|
155
|
+
const aws = args?.api ? void 0 : ensureSstAws(args);
|
|
156
|
+
const api = args?.api ?? new aws.ApiGateway(args?.apiName ?? "RestApi", args?.apiArgs);
|
|
157
|
+
const authorizers = /* @__PURE__ */ new Map();
|
|
158
|
+
const ensureJwtAuthorizer = (name, cfg) => {
|
|
159
|
+
if (authorizers.has(name)) {
|
|
160
|
+
return authorizers.get(name);
|
|
161
|
+
}
|
|
162
|
+
const apiAny = api;
|
|
163
|
+
let ref = name;
|
|
164
|
+
const payload = {
|
|
165
|
+
type: "jwt",
|
|
166
|
+
jwt: {
|
|
167
|
+
issuer: cfg.issuer,
|
|
168
|
+
audience: cfg.audiences
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
if (typeof apiAny.addAuthorizers === "function") {
|
|
172
|
+
apiAny.addAuthorizers({
|
|
173
|
+
[name]: payload
|
|
174
|
+
});
|
|
175
|
+
} else if (typeof apiAny.authorizer === "function") {
|
|
176
|
+
ref = apiAny.authorizer(name, payload);
|
|
177
|
+
} else {
|
|
178
|
+
apiAny.authorizers = {
|
|
179
|
+
...apiAny.authorizers ?? {},
|
|
180
|
+
[name]: payload
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
authorizers.set(name, ref);
|
|
184
|
+
return ref;
|
|
185
|
+
};
|
|
186
|
+
const registerRoute = (method, path, config) => {
|
|
187
|
+
const apiAny = api;
|
|
188
|
+
const routeKey = `${method} ${path}`;
|
|
189
|
+
const routeConfig = {
|
|
190
|
+
handler: config.handler
|
|
191
|
+
};
|
|
192
|
+
if (config.protected && config.authorizer) {
|
|
193
|
+
routeConfig.authorizer = config.authorizer.ref ?? config.authorizer.name;
|
|
194
|
+
routeConfig.authorizationType = "JWT";
|
|
195
|
+
if (config.authorizer.roles && config.authorizer.roles.length > 0) {
|
|
196
|
+
routeConfig.authorizationScopes = config.authorizer.roles;
|
|
197
|
+
}
|
|
198
|
+
if (config.authorizer.optional) {
|
|
199
|
+
routeConfig.authorizerOptional = true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (typeof apiAny.route === "function") {
|
|
203
|
+
apiAny.route(routeKey, routeConfig);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (typeof apiAny.addRoutes === "function") {
|
|
207
|
+
apiAny.addRoutes({
|
|
208
|
+
[routeKey]: routeConfig
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (typeof apiAny.addRoute === "function") {
|
|
213
|
+
apiAny.addRoute(routeKey, routeConfig);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
throw new Error("Unsupported ApiGateway instance: expected route() or addRoutes() method.");
|
|
217
|
+
};
|
|
218
|
+
return {
|
|
219
|
+
api,
|
|
220
|
+
registerRoute,
|
|
221
|
+
ensureJwtAuthorizer
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
225
|
+
0 && (module.exports = {
|
|
226
|
+
httpApiAdapter,
|
|
227
|
+
loadRoutesManifest,
|
|
228
|
+
restApiAdapter,
|
|
229
|
+
wireApiFromManifest
|
|
230
|
+
});
|
package/dist/infra.d.cts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { H as HttpMethod, R as RoutesManifest } from './types-D69iuoxv.cjs';
|
|
2
|
+
export { b as RoutesManifestAuth, a as RoutesManifestRoute } from './types-D69iuoxv.cjs';
|
|
3
|
+
import 'aws-lambda';
|
|
4
|
+
|
|
5
|
+
type SstApiGateway = {
|
|
6
|
+
route?: (routeKey: string, config: Record<string, unknown>) => unknown;
|
|
7
|
+
addRoutes?: (routes: Record<string, Record<string, unknown>>) => unknown;
|
|
8
|
+
addRoute?: (routeKey: string, config: Record<string, unknown>) => unknown;
|
|
9
|
+
addAuthorizers?: (authorizers: Record<string, unknown>) => unknown;
|
|
10
|
+
authorizer?: (name: string, payload: unknown) => unknown;
|
|
11
|
+
authorizers?: Record<string, unknown>;
|
|
12
|
+
url?: string;
|
|
13
|
+
};
|
|
14
|
+
type SstAwsNamespace = {
|
|
15
|
+
ApiGatewayV2: new (name: string, args?: unknown, opts?: unknown) => SstApiGateway;
|
|
16
|
+
ApiGateway: new (name: string, args?: unknown, opts?: unknown) => SstApiGateway;
|
|
17
|
+
};
|
|
18
|
+
type AwsSource = {
|
|
19
|
+
sst?: {
|
|
20
|
+
aws?: SstAwsNamespace;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
type RegisterRouteConfig = {
|
|
24
|
+
handler: string;
|
|
25
|
+
protected: boolean;
|
|
26
|
+
authorizer?: {
|
|
27
|
+
name: string;
|
|
28
|
+
optional?: boolean;
|
|
29
|
+
roles?: string[];
|
|
30
|
+
ref?: unknown;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
type RegisterRoute = (method: HttpMethod, path: string, config: RegisterRouteConfig) => void;
|
|
34
|
+
type EnsureJwtAuthorizer = (name: string, cfg: {
|
|
35
|
+
issuer: string;
|
|
36
|
+
audiences: string[];
|
|
37
|
+
}) => unknown;
|
|
38
|
+
declare function wireApiFromManifest(manifest: RoutesManifest, opts: {
|
|
39
|
+
handlerFile: string;
|
|
40
|
+
firebaseProjectId: string;
|
|
41
|
+
registerRoute: RegisterRoute;
|
|
42
|
+
ensureJwtAuthorizer: EnsureJwtAuthorizer;
|
|
43
|
+
}): void;
|
|
44
|
+
declare function loadRoutesManifest(filePath: string): RoutesManifest;
|
|
45
|
+
type AdapterArgs = AwsSource & {
|
|
46
|
+
api?: SstApiGateway;
|
|
47
|
+
apiName?: string;
|
|
48
|
+
apiArgs?: unknown;
|
|
49
|
+
};
|
|
50
|
+
declare function httpApiAdapter(args?: AdapterArgs): {
|
|
51
|
+
api: SstApiGateway;
|
|
52
|
+
registerRoute: RegisterRoute;
|
|
53
|
+
ensureJwtAuthorizer: EnsureJwtAuthorizer;
|
|
54
|
+
};
|
|
55
|
+
declare function restApiAdapter(args?: AdapterArgs): {
|
|
56
|
+
api: SstApiGateway;
|
|
57
|
+
registerRoute: RegisterRoute;
|
|
58
|
+
ensureJwtAuthorizer: EnsureJwtAuthorizer;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export { type EnsureJwtAuthorizer, type RegisterRoute, type RegisterRouteConfig, RoutesManifest, httpApiAdapter, loadRoutesManifest, restApiAdapter, wireApiFromManifest };
|
package/dist/infra.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { H as HttpMethod, R as RoutesManifest } from './types-D69iuoxv.js';
|
|
2
|
+
export { b as RoutesManifestAuth, a as RoutesManifestRoute } from './types-D69iuoxv.js';
|
|
3
|
+
import 'aws-lambda';
|
|
4
|
+
|
|
5
|
+
type SstApiGateway = {
|
|
6
|
+
route?: (routeKey: string, config: Record<string, unknown>) => unknown;
|
|
7
|
+
addRoutes?: (routes: Record<string, Record<string, unknown>>) => unknown;
|
|
8
|
+
addRoute?: (routeKey: string, config: Record<string, unknown>) => unknown;
|
|
9
|
+
addAuthorizers?: (authorizers: Record<string, unknown>) => unknown;
|
|
10
|
+
authorizer?: (name: string, payload: unknown) => unknown;
|
|
11
|
+
authorizers?: Record<string, unknown>;
|
|
12
|
+
url?: string;
|
|
13
|
+
};
|
|
14
|
+
type SstAwsNamespace = {
|
|
15
|
+
ApiGatewayV2: new (name: string, args?: unknown, opts?: unknown) => SstApiGateway;
|
|
16
|
+
ApiGateway: new (name: string, args?: unknown, opts?: unknown) => SstApiGateway;
|
|
17
|
+
};
|
|
18
|
+
type AwsSource = {
|
|
19
|
+
sst?: {
|
|
20
|
+
aws?: SstAwsNamespace;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
type RegisterRouteConfig = {
|
|
24
|
+
handler: string;
|
|
25
|
+
protected: boolean;
|
|
26
|
+
authorizer?: {
|
|
27
|
+
name: string;
|
|
28
|
+
optional?: boolean;
|
|
29
|
+
roles?: string[];
|
|
30
|
+
ref?: unknown;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
type RegisterRoute = (method: HttpMethod, path: string, config: RegisterRouteConfig) => void;
|
|
34
|
+
type EnsureJwtAuthorizer = (name: string, cfg: {
|
|
35
|
+
issuer: string;
|
|
36
|
+
audiences: string[];
|
|
37
|
+
}) => unknown;
|
|
38
|
+
declare function wireApiFromManifest(manifest: RoutesManifest, opts: {
|
|
39
|
+
handlerFile: string;
|
|
40
|
+
firebaseProjectId: string;
|
|
41
|
+
registerRoute: RegisterRoute;
|
|
42
|
+
ensureJwtAuthorizer: EnsureJwtAuthorizer;
|
|
43
|
+
}): void;
|
|
44
|
+
declare function loadRoutesManifest(filePath: string): RoutesManifest;
|
|
45
|
+
type AdapterArgs = AwsSource & {
|
|
46
|
+
api?: SstApiGateway;
|
|
47
|
+
apiName?: string;
|
|
48
|
+
apiArgs?: unknown;
|
|
49
|
+
};
|
|
50
|
+
declare function httpApiAdapter(args?: AdapterArgs): {
|
|
51
|
+
api: SstApiGateway;
|
|
52
|
+
registerRoute: RegisterRoute;
|
|
53
|
+
ensureJwtAuthorizer: EnsureJwtAuthorizer;
|
|
54
|
+
};
|
|
55
|
+
declare function restApiAdapter(args?: AdapterArgs): {
|
|
56
|
+
api: SstApiGateway;
|
|
57
|
+
registerRoute: RegisterRoute;
|
|
58
|
+
ensureJwtAuthorizer: EnsureJwtAuthorizer;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export { type EnsureJwtAuthorizer, type RegisterRoute, type RegisterRouteConfig, RoutesManifest, httpApiAdapter, loadRoutesManifest, restApiAdapter, wireApiFromManifest };
|
package/dist/infra.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// src/infra.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
function ensureSstAws(source) {
|
|
5
|
+
if (source?.sst?.aws) {
|
|
6
|
+
return source.sst.aws;
|
|
7
|
+
}
|
|
8
|
+
const aws = globalThis.sst?.aws;
|
|
9
|
+
if (!aws) {
|
|
10
|
+
throw new Error(
|
|
11
|
+
"SST aws namespace is not available. Ensure this code runs within an SST config."
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
return aws;
|
|
15
|
+
}
|
|
16
|
+
function wireApiFromManifest(manifest, opts) {
|
|
17
|
+
if (!manifest || !Array.isArray(manifest.routes)) {
|
|
18
|
+
throw new Error("Invalid routes manifest");
|
|
19
|
+
}
|
|
20
|
+
const firebaseRoutes = manifest.routes.filter((route) => route.auth.type === "firebase");
|
|
21
|
+
let firebaseAuthorizerRef;
|
|
22
|
+
if (firebaseRoutes.length > 0) {
|
|
23
|
+
if (!opts.firebaseProjectId) {
|
|
24
|
+
throw new Error("firebaseProjectId is required when using @FirebaseAuth()");
|
|
25
|
+
}
|
|
26
|
+
const issuer = `https://securetoken.google.com/${opts.firebaseProjectId}`;
|
|
27
|
+
firebaseAuthorizerRef = opts.ensureJwtAuthorizer("firebase", {
|
|
28
|
+
issuer,
|
|
29
|
+
audiences: [opts.firebaseProjectId]
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
for (const route of manifest.routes) {
|
|
33
|
+
const isProtected = route.auth.type === "firebase";
|
|
34
|
+
const path = route.path.startsWith("/") ? route.path : `/${route.path}`;
|
|
35
|
+
const authConfig = isProtected && route.auth.type === "firebase" ? {
|
|
36
|
+
name: "firebase",
|
|
37
|
+
optional: route.auth.optional,
|
|
38
|
+
roles: route.auth.roles,
|
|
39
|
+
ref: firebaseAuthorizerRef
|
|
40
|
+
} : void 0;
|
|
41
|
+
opts.registerRoute(route.method, path, {
|
|
42
|
+
handler: opts.handlerFile,
|
|
43
|
+
protected: isProtected,
|
|
44
|
+
authorizer: authConfig
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function loadRoutesManifest(filePath) {
|
|
49
|
+
const resolved = resolve(filePath);
|
|
50
|
+
const contents = readFileSync(resolved, "utf8");
|
|
51
|
+
const manifest = JSON.parse(contents);
|
|
52
|
+
if (!manifest || !Array.isArray(manifest.routes)) {
|
|
53
|
+
throw new Error(`Invalid routes manifest at ${resolved}`);
|
|
54
|
+
}
|
|
55
|
+
return manifest;
|
|
56
|
+
}
|
|
57
|
+
function httpApiAdapter(args) {
|
|
58
|
+
const aws = args?.api ? void 0 : ensureSstAws(args);
|
|
59
|
+
const api = args?.api ?? new aws.ApiGatewayV2(args?.apiName ?? "HttpApi", args?.apiArgs);
|
|
60
|
+
const authorizers = /* @__PURE__ */ new Map();
|
|
61
|
+
const ensureJwtAuthorizer = (name, cfg) => {
|
|
62
|
+
if (authorizers.has(name)) {
|
|
63
|
+
return authorizers.get(name);
|
|
64
|
+
}
|
|
65
|
+
const apiAny = api;
|
|
66
|
+
let ref = name;
|
|
67
|
+
const payload = {
|
|
68
|
+
type: "jwt",
|
|
69
|
+
jwt: {
|
|
70
|
+
issuer: cfg.issuer,
|
|
71
|
+
audience: cfg.audiences
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
if (typeof apiAny.addAuthorizers === "function") {
|
|
75
|
+
apiAny.addAuthorizers({
|
|
76
|
+
[name]: payload
|
|
77
|
+
});
|
|
78
|
+
} else if (typeof apiAny.authorizer === "function") {
|
|
79
|
+
ref = apiAny.authorizer(name, payload);
|
|
80
|
+
} else {
|
|
81
|
+
apiAny.authorizers = {
|
|
82
|
+
...apiAny.authorizers ?? {},
|
|
83
|
+
[name]: payload
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
authorizers.set(name, ref);
|
|
87
|
+
return ref;
|
|
88
|
+
};
|
|
89
|
+
const registerRoute = (method, path, config) => {
|
|
90
|
+
const apiAny = api;
|
|
91
|
+
const routeKey = `${method} ${path}`;
|
|
92
|
+
const routeConfig = {
|
|
93
|
+
handler: config.handler
|
|
94
|
+
};
|
|
95
|
+
if (config.protected && config.authorizer) {
|
|
96
|
+
routeConfig.authorizer = config.authorizer.ref ?? config.authorizer.name;
|
|
97
|
+
routeConfig.authorizationType = "JWT";
|
|
98
|
+
if (config.authorizer.roles && config.authorizer.roles.length > 0) {
|
|
99
|
+
routeConfig.authorizationScopes = config.authorizer.roles;
|
|
100
|
+
}
|
|
101
|
+
if (config.authorizer.optional) {
|
|
102
|
+
routeConfig.authorizerOptional = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (typeof apiAny.route === "function") {
|
|
106
|
+
apiAny.route(routeKey, routeConfig);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (typeof apiAny.addRoutes === "function") {
|
|
110
|
+
apiAny.addRoutes({
|
|
111
|
+
[routeKey]: routeConfig
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (typeof apiAny.addRoute === "function") {
|
|
116
|
+
apiAny.addRoute(routeKey, routeConfig);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
throw new Error("Unsupported ApiGatewayV2 instance: expected route() or addRoutes() method.");
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
api,
|
|
123
|
+
registerRoute,
|
|
124
|
+
ensureJwtAuthorizer
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function restApiAdapter(args) {
|
|
128
|
+
const aws = args?.api ? void 0 : ensureSstAws(args);
|
|
129
|
+
const api = args?.api ?? new aws.ApiGateway(args?.apiName ?? "RestApi", args?.apiArgs);
|
|
130
|
+
const authorizers = /* @__PURE__ */ new Map();
|
|
131
|
+
const ensureJwtAuthorizer = (name, cfg) => {
|
|
132
|
+
if (authorizers.has(name)) {
|
|
133
|
+
return authorizers.get(name);
|
|
134
|
+
}
|
|
135
|
+
const apiAny = api;
|
|
136
|
+
let ref = name;
|
|
137
|
+
const payload = {
|
|
138
|
+
type: "jwt",
|
|
139
|
+
jwt: {
|
|
140
|
+
issuer: cfg.issuer,
|
|
141
|
+
audience: cfg.audiences
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
if (typeof apiAny.addAuthorizers === "function") {
|
|
145
|
+
apiAny.addAuthorizers({
|
|
146
|
+
[name]: payload
|
|
147
|
+
});
|
|
148
|
+
} else if (typeof apiAny.authorizer === "function") {
|
|
149
|
+
ref = apiAny.authorizer(name, payload);
|
|
150
|
+
} else {
|
|
151
|
+
apiAny.authorizers = {
|
|
152
|
+
...apiAny.authorizers ?? {},
|
|
153
|
+
[name]: payload
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
authorizers.set(name, ref);
|
|
157
|
+
return ref;
|
|
158
|
+
};
|
|
159
|
+
const registerRoute = (method, path, config) => {
|
|
160
|
+
const apiAny = api;
|
|
161
|
+
const routeKey = `${method} ${path}`;
|
|
162
|
+
const routeConfig = {
|
|
163
|
+
handler: config.handler
|
|
164
|
+
};
|
|
165
|
+
if (config.protected && config.authorizer) {
|
|
166
|
+
routeConfig.authorizer = config.authorizer.ref ?? config.authorizer.name;
|
|
167
|
+
routeConfig.authorizationType = "JWT";
|
|
168
|
+
if (config.authorizer.roles && config.authorizer.roles.length > 0) {
|
|
169
|
+
routeConfig.authorizationScopes = config.authorizer.roles;
|
|
170
|
+
}
|
|
171
|
+
if (config.authorizer.optional) {
|
|
172
|
+
routeConfig.authorizerOptional = true;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (typeof apiAny.route === "function") {
|
|
176
|
+
apiAny.route(routeKey, routeConfig);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (typeof apiAny.addRoutes === "function") {
|
|
180
|
+
apiAny.addRoutes({
|
|
181
|
+
[routeKey]: routeConfig
|
|
182
|
+
});
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (typeof apiAny.addRoute === "function") {
|
|
186
|
+
apiAny.addRoute(routeKey, routeConfig);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
throw new Error("Unsupported ApiGateway instance: expected route() or addRoutes() method.");
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
api,
|
|
193
|
+
registerRoute,
|
|
194
|
+
ensureJwtAuthorizer
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
export {
|
|
198
|
+
httpApiAdapter,
|
|
199
|
+
loadRoutesManifest,
|
|
200
|
+
restApiAdapter,
|
|
201
|
+
wireApiFromManifest
|
|
202
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { APIGatewayProxyResult, APIGatewayProxyResultV2, APIGatewayProxyEvent, APIGatewayProxyEventV2 } from 'aws-lambda';
|
|
2
|
+
|
|
3
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
|
|
4
|
+
type FirebaseClaims = Record<string, unknown>;
|
|
5
|
+
type FirebaseAuthOptions = {
|
|
6
|
+
roles?: string[];
|
|
7
|
+
optional?: boolean;
|
|
8
|
+
};
|
|
9
|
+
type FirebaseAuthMetadata = FirebaseAuthOptions & {
|
|
10
|
+
type: "firebase";
|
|
11
|
+
};
|
|
12
|
+
type ResponseLike = APIGatewayProxyResult | APIGatewayProxyResultV2 | {
|
|
13
|
+
statusCode: number;
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
body?: string;
|
|
16
|
+
cookies?: string[];
|
|
17
|
+
isBase64Encoded?: boolean;
|
|
18
|
+
};
|
|
19
|
+
type ResponseHelpers = {
|
|
20
|
+
json: (status: number, data: unknown, headers?: Record<string, string>) => ResponseLike;
|
|
21
|
+
text: (status: number, body: string, headers?: Record<string, string>) => ResponseLike;
|
|
22
|
+
noContent: (headers?: Record<string, string>) => ResponseLike;
|
|
23
|
+
};
|
|
24
|
+
type HandlerContext = {
|
|
25
|
+
event: APIGatewayProxyEvent | APIGatewayProxyEventV2;
|
|
26
|
+
lambdaContext: unknown;
|
|
27
|
+
params: Record<string, string>;
|
|
28
|
+
query: Record<string, string | undefined>;
|
|
29
|
+
body: unknown;
|
|
30
|
+
headers: Record<string, string | undefined>;
|
|
31
|
+
auth?: FirebaseClaims;
|
|
32
|
+
response: ResponseHelpers;
|
|
33
|
+
};
|
|
34
|
+
type Handler = (...args: unknown[]) => Promise<ResponseLike | void | undefined> | ResponseLike | void | undefined;
|
|
35
|
+
type RouteOptions = {
|
|
36
|
+
inferPathFromName?: boolean;
|
|
37
|
+
};
|
|
38
|
+
type RoutesManifestAuth = {
|
|
39
|
+
type: "none";
|
|
40
|
+
} | {
|
|
41
|
+
type: "firebase";
|
|
42
|
+
optional?: boolean;
|
|
43
|
+
roles?: string[];
|
|
44
|
+
};
|
|
45
|
+
type RoutesManifestRoute = {
|
|
46
|
+
method: HttpMethod;
|
|
47
|
+
path: string;
|
|
48
|
+
auth: RoutesManifestAuth;
|
|
49
|
+
};
|
|
50
|
+
type RoutesManifest = {
|
|
51
|
+
routes: RoutesManifestRoute[];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type { FirebaseAuthOptions as F, HttpMethod as H, RoutesManifest as R, RoutesManifestRoute as a, RoutesManifestAuth as b, ResponseLike as c, RouteOptions as d, Handler as e, HandlerContext as f, FirebaseAuthMetadata as g };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { APIGatewayProxyResult, APIGatewayProxyResultV2, APIGatewayProxyEvent, APIGatewayProxyEventV2 } from 'aws-lambda';
|
|
2
|
+
|
|
3
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
|
|
4
|
+
type FirebaseClaims = Record<string, unknown>;
|
|
5
|
+
type FirebaseAuthOptions = {
|
|
6
|
+
roles?: string[];
|
|
7
|
+
optional?: boolean;
|
|
8
|
+
};
|
|
9
|
+
type FirebaseAuthMetadata = FirebaseAuthOptions & {
|
|
10
|
+
type: "firebase";
|
|
11
|
+
};
|
|
12
|
+
type ResponseLike = APIGatewayProxyResult | APIGatewayProxyResultV2 | {
|
|
13
|
+
statusCode: number;
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
body?: string;
|
|
16
|
+
cookies?: string[];
|
|
17
|
+
isBase64Encoded?: boolean;
|
|
18
|
+
};
|
|
19
|
+
type ResponseHelpers = {
|
|
20
|
+
json: (status: number, data: unknown, headers?: Record<string, string>) => ResponseLike;
|
|
21
|
+
text: (status: number, body: string, headers?: Record<string, string>) => ResponseLike;
|
|
22
|
+
noContent: (headers?: Record<string, string>) => ResponseLike;
|
|
23
|
+
};
|
|
24
|
+
type HandlerContext = {
|
|
25
|
+
event: APIGatewayProxyEvent | APIGatewayProxyEventV2;
|
|
26
|
+
lambdaContext: unknown;
|
|
27
|
+
params: Record<string, string>;
|
|
28
|
+
query: Record<string, string | undefined>;
|
|
29
|
+
body: unknown;
|
|
30
|
+
headers: Record<string, string | undefined>;
|
|
31
|
+
auth?: FirebaseClaims;
|
|
32
|
+
response: ResponseHelpers;
|
|
33
|
+
};
|
|
34
|
+
type Handler = (...args: unknown[]) => Promise<ResponseLike | void | undefined> | ResponseLike | void | undefined;
|
|
35
|
+
type RouteOptions = {
|
|
36
|
+
inferPathFromName?: boolean;
|
|
37
|
+
};
|
|
38
|
+
type RoutesManifestAuth = {
|
|
39
|
+
type: "none";
|
|
40
|
+
} | {
|
|
41
|
+
type: "firebase";
|
|
42
|
+
optional?: boolean;
|
|
43
|
+
roles?: string[];
|
|
44
|
+
};
|
|
45
|
+
type RoutesManifestRoute = {
|
|
46
|
+
method: HttpMethod;
|
|
47
|
+
path: string;
|
|
48
|
+
auth: RoutesManifestAuth;
|
|
49
|
+
};
|
|
50
|
+
type RoutesManifest = {
|
|
51
|
+
routes: RoutesManifestRoute[];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type { FirebaseAuthOptions as F, HttpMethod as H, RoutesManifest as R, RoutesManifestRoute as a, RoutesManifestAuth as b, ResponseLike as c, RouteOptions as d, Handler as e, HandlerContext as f, FirebaseAuthMetadata as g };
|