sst 2.25.6 → 2.26.1
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/bootstrap.js +3 -3
- package/bus.js +2 -2
- package/cache.js +2 -2
- package/cdk/deployments-wrapper.js +2 -2
- package/cli/commands/dev.js +6 -5
- package/cli/commands/plugins/kysely.js +2 -2
- package/cli/commands/plugins/pothos.js +2 -2
- package/cli/commands/plugins/warmer.js +2 -2
- package/cli/local/server.js +75 -26
- package/cli/spinner.js +2 -2
- package/constructs/App.js +4 -3
- package/constructs/Function.d.ts +2 -2
- package/constructs/Function.js +1 -1
- package/constructs/context.d.ts +2 -7
- package/constructs/context.js +26 -8
- package/context/context2.d.ts +16 -0
- package/context/context2.js +108 -0
- package/context/handler.js +3 -4
- package/credentials.d.ts +3 -10
- package/credentials.js +5 -5
- package/iot.js +3 -3
- package/logger.js +2 -2
- package/node/actor/index.d.ts +2 -2
- package/node/actor/index.js +3 -3
- package/node/api/index.js +7 -7
- package/node/auth/session.js +1 -1
- package/node/event-bus/index.js +0 -1
- package/node/future/auth/session.js +1 -1
- package/node/util/loader.js +4 -4
- package/package.json +20 -19
- package/project.d.ts +0 -5
- package/project.js +5 -5
- package/runtime/handlers/python.js +1 -3
- package/runtime/handlers.js +3 -3
- package/runtime/iot.js +2 -2
- package/runtime/server.js +3 -3
- package/runtime/workers.js +2 -2
- package/stacks/app-metadata.js +2 -3
- package/stacks/metadata.d.ts +1 -1
- package/stacks/metadata.js +2 -5
- package/support/bootstrap-metadata-function/index.mjs +41338 -45328
- package/support/bridge/bridge.mjs +55 -65
- package/support/custom-resources/index.mjs +90699 -90561
- package/support/event-bus-retrier/index.mjs +57 -27
- package/support/job-manager/index.mjs +22257 -7697
- package/support/rds-migrator/index.mjs +41 -17
- package/support/script-function/index.mjs +33731 -35450
- package/support/signing-function/index.mjs +578 -32
- package/support/ssr-warmer/index.mjs +26855 -26892
- package/util/lazy.d.ts +1 -0
- package/util/lazy.js +11 -0
- package/watcher.js +2 -2
package/bootstrap.js
CHANGED
|
@@ -11,18 +11,18 @@ import { LambdaFunction } from "aws-cdk-lib/aws-events-targets";
|
|
|
11
11
|
import { BlockPublicAccess, Bucket, BucketEncryption, } from "aws-cdk-lib/aws-s3";
|
|
12
12
|
import { useProject } from "./project.js";
|
|
13
13
|
import { createSpinner } from "./cli/spinner.js";
|
|
14
|
-
import { Context } from "./context/context.js";
|
|
15
14
|
import { useAWSClient, useAWSCredentials, useSTSIdentity, } from "./credentials.js";
|
|
16
15
|
import { VisibleError } from "./error.js";
|
|
17
16
|
import { Logger } from "./logger.js";
|
|
18
17
|
import { Stacks } from "./stacks/index.js";
|
|
18
|
+
import { lazy } from "./util/lazy.js";
|
|
19
19
|
const CDK_STACK_NAME = "CDKToolkit";
|
|
20
20
|
const SST_STACK_NAME = "SSTBootstrap";
|
|
21
21
|
const OUTPUT_VERSION = "Version";
|
|
22
22
|
const OUTPUT_BUCKET = "BucketName";
|
|
23
23
|
const LATEST_VERSION = "7.2";
|
|
24
24
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
25
|
-
export const useBootstrap =
|
|
25
|
+
export const useBootstrap = lazy(async () => {
|
|
26
26
|
Logger.debug("Initializing bootstrap context");
|
|
27
27
|
let [cdkStatus, sstStatus] = await Promise.all([
|
|
28
28
|
loadCDKStatus(),
|
|
@@ -53,7 +53,7 @@ export const useBootstrap = Context.memo(async () => {
|
|
|
53
53
|
}
|
|
54
54
|
Logger.debug("Bootstrap context initialized", sstStatus);
|
|
55
55
|
return sstStatus;
|
|
56
|
-
}
|
|
56
|
+
});
|
|
57
57
|
async function loadCDKStatus() {
|
|
58
58
|
const { cdk } = useProject().config;
|
|
59
59
|
const client = useAWSClient(CloudFormationClient);
|
package/bus.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import crypto from "crypto";
|
|
2
|
-
import { Context } from "./context/context.js";
|
|
3
2
|
import { Logger } from "./logger.js";
|
|
3
|
+
import { lazy } from "./util/lazy.js";
|
|
4
4
|
const DO_NOT_LOG = new Set(["stacks.metadata"]);
|
|
5
|
-
export const useBus =
|
|
5
|
+
export const useBus = lazy(() => {
|
|
6
6
|
const subscriptions = {};
|
|
7
7
|
function subscribers(type) {
|
|
8
8
|
let arr = subscriptions[type];
|
package/cache.js
CHANGED
|
@@ -2,8 +2,8 @@ import path from "path";
|
|
|
2
2
|
import fs from "fs/promises";
|
|
3
3
|
import { useProject } from "./project.js";
|
|
4
4
|
import { Logger } from "./logger.js";
|
|
5
|
-
import {
|
|
6
|
-
export const useCache =
|
|
5
|
+
import { lazy } from "./util/lazy.js";
|
|
6
|
+
export const useCache = lazy(async () => {
|
|
7
7
|
const project = useProject();
|
|
8
8
|
const cache = path.join(project.paths.out, "cache");
|
|
9
9
|
await fs.mkdir(cache, {
|
|
@@ -9,7 +9,7 @@ import { publishAssets } from "sst-aws-cdk/lib/util/asset-publishing.js";
|
|
|
9
9
|
import { AssetManifestBuilder } from "sst-aws-cdk/lib/util/asset-manifest-builder.js";
|
|
10
10
|
import { Deployments, } from "./deployments.js";
|
|
11
11
|
import { makeBodyParameter } from "./deploy-stack.js";
|
|
12
|
-
import {
|
|
12
|
+
import { lazy } from "../util/lazy.js";
|
|
13
13
|
export async function publishDeployAssets(sdkProvider, options) {
|
|
14
14
|
const { deployment, toolkitInfo, stackSdk, resolvedEnvironment, cloudFormationRoleArn, } = await useDeployment().get(sdkProvider, options);
|
|
15
15
|
// TODO
|
|
@@ -60,7 +60,7 @@ export async function publishDeployAssets(sdkProvider, options) {
|
|
|
60
60
|
assetParallelism: options.assetParallelism,
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
|
-
const useDeployment =
|
|
63
|
+
const useDeployment = lazy(() => {
|
|
64
64
|
const state = new Map();
|
|
65
65
|
return {
|
|
66
66
|
async get(sdkProvider, options) {
|
package/cli/commands/dev.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { lazy } from "../../util/lazy.js";
|
|
1
2
|
export const dev = (program) => program.command(["dev", "start"], "Work on your app locally", (yargs) => yargs.option("increase-timeout", {
|
|
2
3
|
type: "boolean",
|
|
3
4
|
description: "Increase function timeout",
|
|
@@ -29,7 +30,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
29
30
|
const { useKyselyTypeGenerator } = await import("./plugins/kysely.js");
|
|
30
31
|
const { useRDSWarmer } = await import("./plugins/warmer.js");
|
|
31
32
|
const { useProject } = await import("../../project.js");
|
|
32
|
-
const {
|
|
33
|
+
const { useMetadataCache } = await import("../../stacks/metadata.js");
|
|
33
34
|
const { useIOT } = await import("../../iot.js");
|
|
34
35
|
const { clear } = await import("../terminal.js");
|
|
35
36
|
const { getCiInfo } = await import("../ci-info.js");
|
|
@@ -38,7 +39,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
38
39
|
console.log(yellow(`Warning: ${bold(`sst start`)} has been renamed to ${bold(`sst dev`)}`));
|
|
39
40
|
}
|
|
40
41
|
const project = useProject();
|
|
41
|
-
const useFunctionLogger =
|
|
42
|
+
const useFunctionLogger = lazy(async () => {
|
|
42
43
|
const bus = useBus();
|
|
43
44
|
const colors = ["#01cdfe", "#ff71ce", "#05ffa1", "#b967ff"];
|
|
44
45
|
let index = 0;
|
|
@@ -138,7 +139,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
138
139
|
}, 100);
|
|
139
140
|
});
|
|
140
141
|
});
|
|
141
|
-
const useStackBuilder =
|
|
142
|
+
const useStackBuilder = lazy(async () => {
|
|
142
143
|
const watcher = useWatcher();
|
|
143
144
|
const scriptVersion = Date.now().toString();
|
|
144
145
|
let lastDeployed;
|
|
@@ -277,7 +278,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
277
278
|
});
|
|
278
279
|
await build();
|
|
279
280
|
});
|
|
280
|
-
const useDisconnector =
|
|
281
|
+
const useDisconnector = lazy(async () => {
|
|
281
282
|
const bus = useBus();
|
|
282
283
|
const iot = await useIOT();
|
|
283
284
|
bus.subscribe("cli.dev", async (evt) => {
|
|
@@ -338,7 +339,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
338
339
|
useIOTBridge(),
|
|
339
340
|
useRuntimeServer(),
|
|
340
341
|
usePothosBuilder(),
|
|
341
|
-
|
|
342
|
+
useMetadataCache(),
|
|
342
343
|
useKyselyTypeGenerator(),
|
|
343
344
|
useRDSWarmer(),
|
|
344
345
|
useFunctionLogger(),
|
|
@@ -3,11 +3,11 @@ import { DataApiDialect } from "kysely-data-api";
|
|
|
3
3
|
import { RDSData } from "@aws-sdk/client-rds-data";
|
|
4
4
|
import * as fs from "fs/promises";
|
|
5
5
|
import { PostgresDialect, MysqlDialect, Serializer, Transformer, } from "kysely-codegen";
|
|
6
|
-
import { Context } from "../../../context/context.js";
|
|
7
6
|
import { useBus } from "../../../bus.js";
|
|
8
7
|
import { Logger } from "../../../logger.js";
|
|
9
8
|
import { useAWSClient } from "../../../credentials.js";
|
|
10
|
-
|
|
9
|
+
import { lazy } from "../../../util/lazy.js";
|
|
10
|
+
export const useKyselyTypeGenerator = lazy(async () => {
|
|
11
11
|
let databases = [];
|
|
12
12
|
const bus = useBus();
|
|
13
13
|
const logger = Logger.debug.bind(null, "[kysely-codegen]");
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useBus } from "../../../bus.js";
|
|
2
|
-
import { Context } from "../../../context/context.js";
|
|
3
2
|
import { Pothos } from "../../../pothos.js";
|
|
4
3
|
import fs from "fs/promises";
|
|
5
4
|
import { exec } from "child_process";
|
|
@@ -7,7 +6,8 @@ import { promisify } from "util";
|
|
|
7
6
|
const execAsync = promisify(exec);
|
|
8
7
|
import path from "path";
|
|
9
8
|
import { Colors } from "../../colors.js";
|
|
10
|
-
|
|
9
|
+
import { lazy } from "../../../util/lazy.js";
|
|
10
|
+
export const usePothosBuilder = lazy(() => {
|
|
11
11
|
let routes = [];
|
|
12
12
|
const bus = useBus();
|
|
13
13
|
async function build(route) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useBus } from "../../../bus.js";
|
|
2
|
-
import { Context } from "../../../context/context.js";
|
|
3
2
|
import { RDSDataClient, ExecuteStatementCommand, } from "@aws-sdk/client-rds-data";
|
|
4
3
|
import { useAWSClient } from "../../../credentials.js";
|
|
5
|
-
|
|
4
|
+
import { lazy } from "../../../util/lazy.js";
|
|
5
|
+
export const useRDSWarmer = lazy(async () => {
|
|
6
6
|
let interval;
|
|
7
7
|
const bus = useBus();
|
|
8
8
|
const client = useAWSClient(RDSDataClient);
|
package/cli/local/server.js
CHANGED
|
@@ -12,9 +12,8 @@ import { sync } from "cross-spawn";
|
|
|
12
12
|
import { useProject } from "../../project.js";
|
|
13
13
|
import { useBus } from "../../bus.js";
|
|
14
14
|
import getPort from "get-port";
|
|
15
|
-
import {
|
|
16
|
-
export const useLocalServerConfig =
|
|
17
|
-
const project = useProject();
|
|
15
|
+
import { lazy } from "../../util/lazy.js";
|
|
16
|
+
export const useLocalServerConfig = lazy(async () => {
|
|
18
17
|
const port = await getPort({
|
|
19
18
|
port: 13557,
|
|
20
19
|
});
|
|
@@ -104,28 +103,29 @@ export async function useLocalServer(opts) {
|
|
|
104
103
|
const wss = new WebSocketServer({ noServer: true });
|
|
105
104
|
const wss2 = new WebSocketServer({ noServer: true });
|
|
106
105
|
const sockets = new Set();
|
|
107
|
-
let
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
},
|
|
115
|
-
];
|
|
116
|
-
function publish(type, properties) {
|
|
117
|
-
const msg = {
|
|
118
|
-
type,
|
|
119
|
-
properties,
|
|
120
|
-
};
|
|
121
|
-
buffer.push(msg);
|
|
122
|
-
const json = JSON.stringify(msg);
|
|
106
|
+
let invocations = [];
|
|
107
|
+
function publish(invocation) {
|
|
108
|
+
invocations.push(invocation);
|
|
109
|
+
const json = JSON.stringify({
|
|
110
|
+
type: "invocation",
|
|
111
|
+
properties: [invocation],
|
|
112
|
+
});
|
|
123
113
|
[...sockets.values()].map((s) => s.send(json));
|
|
124
114
|
}
|
|
125
115
|
wss2.on("connection", (socket, req) => {
|
|
126
116
|
sockets.add(socket);
|
|
127
|
-
|
|
128
|
-
|
|
117
|
+
socket.send(JSON.stringify({
|
|
118
|
+
type: "cli.dev",
|
|
119
|
+
properties: {
|
|
120
|
+
app: project.config.name,
|
|
121
|
+
stage: project.config.stage,
|
|
122
|
+
},
|
|
123
|
+
}));
|
|
124
|
+
for (const invocation of invocations) {
|
|
125
|
+
socket.send(JSON.stringify({
|
|
126
|
+
type: "invocation",
|
|
127
|
+
properties: [invocation],
|
|
128
|
+
}));
|
|
129
129
|
}
|
|
130
130
|
socket.on("close", () => {
|
|
131
131
|
sockets.delete(socket);
|
|
@@ -133,7 +133,11 @@ export async function useLocalServer(opts) {
|
|
|
133
133
|
socket.on("message", (data) => {
|
|
134
134
|
const parsed = JSON.parse(data.toString());
|
|
135
135
|
if (parsed.type === "log.cleared") {
|
|
136
|
-
|
|
136
|
+
if (parsed.properties.source === "all") {
|
|
137
|
+
invocations = [];
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
invocations = invocations.filter((item) => item.source === parsed.properties.source);
|
|
137
141
|
}
|
|
138
142
|
});
|
|
139
143
|
});
|
|
@@ -207,7 +211,15 @@ export async function useLocalServer(opts) {
|
|
|
207
211
|
});
|
|
208
212
|
}
|
|
209
213
|
bus.subscribe("function.invoked", async (evt) => {
|
|
210
|
-
publish(
|
|
214
|
+
publish({
|
|
215
|
+
start: Date.now(),
|
|
216
|
+
cold: false,
|
|
217
|
+
input: evt.properties.event,
|
|
218
|
+
id: evt.properties.requestID,
|
|
219
|
+
errors: [],
|
|
220
|
+
logs: [],
|
|
221
|
+
source: evt.properties.functionID,
|
|
222
|
+
});
|
|
211
223
|
updateFunction(evt.properties.functionID, (draft) => {
|
|
212
224
|
if (draft.invocations.length >= 25)
|
|
213
225
|
draft.invocations.pop();
|
|
@@ -222,7 +234,15 @@ export async function useLocalServer(opts) {
|
|
|
222
234
|
});
|
|
223
235
|
});
|
|
224
236
|
bus.subscribe("worker.stdout", (evt) => {
|
|
225
|
-
|
|
237
|
+
const invocation = invocations.findLast((i) => i.source === evt.properties.functionID);
|
|
238
|
+
if (invocation) {
|
|
239
|
+
invocation.logs.push({
|
|
240
|
+
id: Math.random().toString(),
|
|
241
|
+
message: evt.properties.message,
|
|
242
|
+
timestamp: Date.now(),
|
|
243
|
+
});
|
|
244
|
+
publish(invocation);
|
|
245
|
+
}
|
|
226
246
|
updateFunction(evt.properties.functionID, (draft) => {
|
|
227
247
|
const entry = draft.invocations.find((i) => i.id === evt.properties.requestID);
|
|
228
248
|
if (!entry)
|
|
@@ -234,7 +254,18 @@ export async function useLocalServer(opts) {
|
|
|
234
254
|
});
|
|
235
255
|
});
|
|
236
256
|
bus.subscribe("function.success", (evt) => {
|
|
237
|
-
|
|
257
|
+
const invocation = invocations.findLast((i) => i.source === evt.properties.functionID);
|
|
258
|
+
if (invocation) {
|
|
259
|
+
invocation.end = Date.now();
|
|
260
|
+
invocation.report = {
|
|
261
|
+
duration: invocation.end - invocation.start,
|
|
262
|
+
size: 0,
|
|
263
|
+
xray: "",
|
|
264
|
+
memory: 0,
|
|
265
|
+
};
|
|
266
|
+
invocation.output = evt.properties.body;
|
|
267
|
+
publish(invocation);
|
|
268
|
+
}
|
|
238
269
|
updateFunction(evt.properties.functionID, (draft) => {
|
|
239
270
|
const invocation = draft.invocations.find((x) => x.id === evt.properties.requestID);
|
|
240
271
|
if (!invocation)
|
|
@@ -247,7 +278,25 @@ export async function useLocalServer(opts) {
|
|
|
247
278
|
});
|
|
248
279
|
});
|
|
249
280
|
bus.subscribe("function.error", (evt) => {
|
|
250
|
-
|
|
281
|
+
const invocation = invocations.findLast((i) => i.source === evt.properties.functionID);
|
|
282
|
+
if (invocation) {
|
|
283
|
+
invocation.errors.push({
|
|
284
|
+
id: invocation.id,
|
|
285
|
+
error: evt.properties.errorType,
|
|
286
|
+
message: evt.properties.errorMessage,
|
|
287
|
+
stack: evt.properties.trace.map((t) => ({
|
|
288
|
+
raw: t,
|
|
289
|
+
})),
|
|
290
|
+
});
|
|
291
|
+
invocation.end = Date.now();
|
|
292
|
+
invocation.report = {
|
|
293
|
+
duration: invocation.end - invocation.start,
|
|
294
|
+
size: 0,
|
|
295
|
+
xray: "",
|
|
296
|
+
memory: 0,
|
|
297
|
+
};
|
|
298
|
+
publish(invocation);
|
|
299
|
+
}
|
|
251
300
|
updateFunction(evt.properties.functionID, (draft) => {
|
|
252
301
|
const invocation = draft.invocations.find((x) => x.id === evt.properties.requestID);
|
|
253
302
|
if (!invocation)
|
package/cli/spinner.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Context } from "../context/context.js";
|
|
2
1
|
import ora from "ora";
|
|
3
2
|
import { Colors } from "./colors.js";
|
|
4
|
-
|
|
3
|
+
import { lazy } from "../util/lazy.js";
|
|
4
|
+
export const useSpinners = lazy(() => {
|
|
5
5
|
const spinners = [];
|
|
6
6
|
return spinners;
|
|
7
7
|
});
|
package/constructs/App.js
CHANGED
|
@@ -7,7 +7,7 @@ import { bindParameters, bindType } from "./util/functionBinding.js";
|
|
|
7
7
|
import { stack } from "./FunctionalStack.js";
|
|
8
8
|
import { Auth } from "./Auth.js";
|
|
9
9
|
import { useDeferredTasks } from "./deferred_task.js";
|
|
10
|
-
import {
|
|
10
|
+
import { provideApp } from "./context.js";
|
|
11
11
|
import { useProject } from "../project.js";
|
|
12
12
|
import { VisibleError } from "../error.js";
|
|
13
13
|
import { Logger } from "../logger.js";
|
|
@@ -66,7 +66,7 @@ export class App extends CDKApp {
|
|
|
66
66
|
*/
|
|
67
67
|
constructor(deployProps, props = {}) {
|
|
68
68
|
super(props);
|
|
69
|
-
|
|
69
|
+
provideApp(this);
|
|
70
70
|
this.appPath = process.cwd();
|
|
71
71
|
this.mode = deployProps.mode;
|
|
72
72
|
this.local = this.mode === "dev";
|
|
@@ -221,10 +221,11 @@ export class App extends CDKApp {
|
|
|
221
221
|
stage: this.stage,
|
|
222
222
|
bootstrap: bootstrap.bucket,
|
|
223
223
|
bucket: sourcemaps[0].bucket.bucketName,
|
|
224
|
-
functions: sourcemaps.map((s) => [s.
|
|
224
|
+
functions: sourcemaps.map((s) => [s.func.functionArn, s.key]),
|
|
225
225
|
},
|
|
226
226
|
});
|
|
227
227
|
resource.node.addDependency(policy);
|
|
228
|
+
sourcemaps.forEach((s) => s.func.node.addDependency(resource));
|
|
228
229
|
}
|
|
229
230
|
}
|
|
230
231
|
// Set removal policy
|
package/constructs/Function.d.ts
CHANGED
|
@@ -673,14 +673,14 @@ export declare class Function extends CDKFunction implements SSTConstruct {
|
|
|
673
673
|
export declare const useFunctions: () => {
|
|
674
674
|
sourcemaps: {
|
|
675
675
|
add(stack: string, source: {
|
|
676
|
-
arn: string;
|
|
677
676
|
bucket: IBucket;
|
|
678
677
|
key: string;
|
|
678
|
+
func: Function;
|
|
679
679
|
}): void;
|
|
680
680
|
forStack(stack: string): {
|
|
681
|
-
arn: string;
|
|
682
681
|
bucket: IBucket;
|
|
683
682
|
key: string;
|
|
683
|
+
func: Function;
|
|
684
684
|
}[];
|
|
685
685
|
};
|
|
686
686
|
fromID(id: string): FunctionProps | undefined;
|
package/constructs/Function.js
CHANGED
package/constructs/context.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
1
|
import { App } from "./App.js";
|
|
2
|
-
export declare
|
|
3
|
-
|
|
4
|
-
reset(): void;
|
|
5
|
-
provide(value: App): void;
|
|
6
|
-
};
|
|
7
|
-
export declare const useApp: () => App;
|
|
8
|
-
export declare function createAppContext<C>(cb: () => C): () => C;
|
|
2
|
+
export declare function provideApp(app: App): void;
|
|
3
|
+
export declare const createAppContext: <C>(cb: () => C) => () => C;
|
package/constructs/context.js
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
const AppContext = (() => {
|
|
2
|
+
let app;
|
|
3
|
+
const children = new Map();
|
|
4
|
+
return {
|
|
5
|
+
set(input) {
|
|
6
|
+
children.clear();
|
|
7
|
+
app = input;
|
|
8
|
+
},
|
|
9
|
+
get current() {
|
|
10
|
+
return app;
|
|
11
|
+
},
|
|
12
|
+
createAppContext(cb) {
|
|
13
|
+
return () => {
|
|
14
|
+
const exists = children.get(cb);
|
|
15
|
+
if (exists)
|
|
16
|
+
return exists;
|
|
17
|
+
const val = cb();
|
|
18
|
+
children.set(cb, val);
|
|
19
|
+
return val;
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
export function provideApp(app) {
|
|
25
|
+
AppContext.set(app);
|
|
9
26
|
}
|
|
27
|
+
export const createAppContext = AppContext.createAppContext;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class ContextNotFoundError extends Error {
|
|
2
|
+
name: string;
|
|
3
|
+
constructor(name: string);
|
|
4
|
+
}
|
|
5
|
+
export type Context<T> = ReturnType<typeof create<T>>;
|
|
6
|
+
export declare function create<T>(name: string): {
|
|
7
|
+
name: string;
|
|
8
|
+
with<R>(value: T, cb: () => R): R;
|
|
9
|
+
use(): T;
|
|
10
|
+
version(): string;
|
|
11
|
+
};
|
|
12
|
+
export declare function memo<T>(cb: () => T): () => T;
|
|
13
|
+
export declare const Context: {
|
|
14
|
+
create: typeof create;
|
|
15
|
+
memo: typeof memo;
|
|
16
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
2
|
+
export class ContextNotFoundError extends Error {
|
|
3
|
+
name;
|
|
4
|
+
constructor(name) {
|
|
5
|
+
super(`${name} context was not provided. It is possible you have multiple versions of SST installed.`);
|
|
6
|
+
this.name = name;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
let count = 0;
|
|
10
|
+
export function create(name) {
|
|
11
|
+
const storage = new AsyncLocalStorage();
|
|
12
|
+
const children = [];
|
|
13
|
+
// notify all memos to reset
|
|
14
|
+
function reset() {
|
|
15
|
+
for (const child of children) {
|
|
16
|
+
child();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const ctx = {
|
|
20
|
+
name,
|
|
21
|
+
with(value, cb) {
|
|
22
|
+
const version = (++count).toString();
|
|
23
|
+
return storage.run({ value, version }, () => {
|
|
24
|
+
return runWithCleanup(cb, () => reset());
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
use() {
|
|
28
|
+
const memo = ContextMemo.getStore();
|
|
29
|
+
// use is being called within a memo, so track dependency
|
|
30
|
+
if (memo) {
|
|
31
|
+
memo.deps.push(ctx);
|
|
32
|
+
children.push(memo.reset);
|
|
33
|
+
}
|
|
34
|
+
const result = storage.getStore();
|
|
35
|
+
if (result === undefined)
|
|
36
|
+
throw new ContextNotFoundError(name);
|
|
37
|
+
return result.value;
|
|
38
|
+
},
|
|
39
|
+
version() {
|
|
40
|
+
const result = storage.getStore();
|
|
41
|
+
if (result === undefined)
|
|
42
|
+
throw new ContextNotFoundError(name);
|
|
43
|
+
return result.version;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
return ctx;
|
|
47
|
+
}
|
|
48
|
+
const ContextMemo = new AsyncLocalStorage();
|
|
49
|
+
export function memo(cb) {
|
|
50
|
+
const deps = [];
|
|
51
|
+
const cache = new Map();
|
|
52
|
+
const children = [];
|
|
53
|
+
let tracked = false;
|
|
54
|
+
function key() {
|
|
55
|
+
return deps.map((dep) => dep.version()).join(",");
|
|
56
|
+
}
|
|
57
|
+
function reset() {
|
|
58
|
+
cache.delete(key());
|
|
59
|
+
for (const child of children) {
|
|
60
|
+
child();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function save(value) {
|
|
64
|
+
cache.set(key(), value);
|
|
65
|
+
}
|
|
66
|
+
return () => {
|
|
67
|
+
const child = ContextMemo.getStore();
|
|
68
|
+
if (child) {
|
|
69
|
+
child.deps.push({ version: () => key() });
|
|
70
|
+
children.push(child.reset);
|
|
71
|
+
}
|
|
72
|
+
// Memo never run so build up dependency list
|
|
73
|
+
if (!tracked) {
|
|
74
|
+
return ContextMemo.run({ deps, reset }, () => {
|
|
75
|
+
return runWithCleanup(cb, (result) => {
|
|
76
|
+
tracked = true;
|
|
77
|
+
save(result);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const cached = cache.get(key());
|
|
82
|
+
if (cached) {
|
|
83
|
+
return cached;
|
|
84
|
+
}
|
|
85
|
+
const result = cb();
|
|
86
|
+
save(result);
|
|
87
|
+
return result;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function runWithCleanup(cb, cleanup) {
|
|
91
|
+
const result = cb();
|
|
92
|
+
if (result &&
|
|
93
|
+
typeof result === "object" &&
|
|
94
|
+
"then" in result &&
|
|
95
|
+
typeof result.then === "function") {
|
|
96
|
+
return result.then((value) => {
|
|
97
|
+
// cleanup
|
|
98
|
+
cleanup(result);
|
|
99
|
+
return value;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
cleanup(result);
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
export const Context = {
|
|
106
|
+
create,
|
|
107
|
+
memo,
|
|
108
|
+
};
|
package/context/handler.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const RequestContext =
|
|
1
|
+
import { create } from "./context2.js";
|
|
2
|
+
const RequestContext = create("RequestContext");
|
|
3
3
|
export function useContextType() {
|
|
4
4
|
const ctx = RequestContext.use();
|
|
5
5
|
return ctx.type;
|
|
@@ -16,7 +16,6 @@ export function useLambdaContext() {
|
|
|
16
16
|
}
|
|
17
17
|
export function Handler(type, cb) {
|
|
18
18
|
return function handler(event, context) {
|
|
19
|
-
RequestContext.
|
|
20
|
-
return cb(event, context);
|
|
19
|
+
return RequestContext.with({ type, event: event, context }, () => cb(event, context));
|
|
21
20
|
};
|
|
22
21
|
}
|
package/credentials.d.ts
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import { Client } from "@aws-sdk/smithy-client";
|
|
2
|
-
import { RegionInputConfig } from "@aws-sdk/config-resolver";
|
|
3
|
-
import { RetryInputConfig } from "@aws-sdk/middleware-retry";
|
|
4
|
-
import { AwsAuthInputConfig } from "@aws-sdk/middleware-signing";
|
|
5
1
|
import { SdkProvider } from "sst-aws-cdk/lib/api/aws-auth/sdk-provider.js";
|
|
6
|
-
|
|
7
|
-
export declare const
|
|
8
|
-
export declare const useAWSCredentials: () => Promise<import("@aws-sdk/types").AwsCredentialIdentity>;
|
|
2
|
+
export declare const useAWSCredentialsProvider: () => import("@smithy/types").AwsCredentialIdentityProvider;
|
|
3
|
+
export declare const useAWSCredentials: () => Promise<import("@smithy/types").AwsCredentialIdentity>;
|
|
9
4
|
export declare const useSTSIdentity: () => Promise<import("@aws-sdk/client-sts").GetCallerIdentityCommandOutput>;
|
|
10
|
-
export declare function useAWSClient<C extends
|
|
11
|
-
import { HostHeaderConditionConfig } from "aws-sdk/clients/elbv2.js";
|
|
5
|
+
export declare function useAWSClient<C extends any>(client: new (config: any) => C, force?: boolean): C;
|
|
12
6
|
/**
|
|
13
7
|
* Do not use this. It is only used for AWS CDK compatibility.
|
|
14
8
|
*/
|
|
15
9
|
export declare const useAWSProvider: () => Promise<SdkProvider>;
|
|
16
|
-
export {};
|
package/credentials.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { Context } from "./context/context.js";
|
|
2
1
|
import { fromNodeProviderChain } from "@aws-sdk/credential-providers";
|
|
3
2
|
import { GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
|
|
4
3
|
import { Logger } from "./logger.js";
|
|
5
4
|
import { SdkProvider } from "sst-aws-cdk/lib/api/aws-auth/sdk-provider.js";
|
|
6
5
|
import { StandardRetryStrategy } from "@aws-sdk/middleware-retry";
|
|
7
|
-
export const useAWSCredentialsProvider =
|
|
6
|
+
export const useAWSCredentialsProvider = lazy(() => {
|
|
8
7
|
const project = useProject();
|
|
9
8
|
Logger.debug("Using AWS profile", project.config.profile);
|
|
10
9
|
const provider = fromNodeProviderChain({
|
|
@@ -39,13 +38,13 @@ export const useAWSCredentials = () => {
|
|
|
39
38
|
const provider = useAWSCredentialsProvider();
|
|
40
39
|
return provider();
|
|
41
40
|
};
|
|
42
|
-
export const useSTSIdentity =
|
|
41
|
+
export const useSTSIdentity = lazy(async () => {
|
|
43
42
|
const sts = useAWSClient(STSClient);
|
|
44
43
|
const identity = await sts.send(new GetCallerIdentityCommand({}));
|
|
45
44
|
Logger.debug("Using identity", "Account:", identity.Account, "User:", identity.UserId);
|
|
46
45
|
return identity;
|
|
47
46
|
});
|
|
48
|
-
const useClientCache =
|
|
47
|
+
const useClientCache = lazy(() => new Map());
|
|
49
48
|
export function useAWSClient(client, force = false) {
|
|
50
49
|
const cache = useClientCache();
|
|
51
50
|
const existing = cache.get(client.name);
|
|
@@ -108,11 +107,12 @@ import stupid from "aws-sdk/lib/maintenance_mode_message.js";
|
|
|
108
107
|
stupid.suppress = true;
|
|
109
108
|
import aws from "aws-sdk";
|
|
110
109
|
import { useProject } from "./project.js";
|
|
110
|
+
import { lazy } from "./util/lazy.js";
|
|
111
111
|
const CredentialProviderChain = aws.CredentialProviderChain;
|
|
112
112
|
/**
|
|
113
113
|
* Do not use this. It is only used for AWS CDK compatibility.
|
|
114
114
|
*/
|
|
115
|
-
export const useAWSProvider =
|
|
115
|
+
export const useAWSProvider = lazy(async () => {
|
|
116
116
|
Logger.debug("Loading v2 AWS SDK");
|
|
117
117
|
const project = useProject();
|
|
118
118
|
const creds = await useAWSCredentials();
|