sst 2.0.0-rc.39 → 2.0.0-rc.40

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 CHANGED
@@ -1,5 +1,7 @@
1
1
  import url from "url";
2
2
  import path from "path";
3
+ import { bold, dim } from "colorette";
4
+ import { spawn } from "child_process";
3
5
  import { DescribeStacksCommand, CloudFormationClient, } from "@aws-sdk/client-cloudformation";
4
6
  import { Tags, Stack, RemovalPolicy, App, CfnOutput } from "aws-cdk-lib";
5
7
  import { Function, Runtime, Code } from "aws-cdk-lib/aws-lambda";
@@ -16,134 +18,181 @@ import { useAWSClient, useAWSCredentials, useSTSIdentity, } from "./credentials.
16
18
  import { VisibleError } from "./error.js";
17
19
  import { Logger } from "./logger.js";
18
20
  import { Stacks } from "./stacks/index.js";
19
- import { spawnSync } from "child_process";
20
21
  const STACK_NAME = "SSTBootstrap";
21
22
  const OUTPUT_VERSION = "Version";
22
23
  const OUTPUT_BUCKET = "BucketName";
23
- const LATEST_VERSION = "5";
24
+ const LATEST_VERSION = "6";
24
25
  const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
25
26
  const BootstrapContext = Context.create();
26
27
  export const useBootstrap = BootstrapContext.use;
27
28
  export async function initBootstrap() {
28
29
  Logger.debug("Initializing bootstrap context");
29
- await assertCDKToolkit();
30
- const status = await (async () => {
31
- const status = await load();
32
- if (status && status.version === LATEST_VERSION)
33
- return status;
34
- const project = useProject();
30
+ let [cdkStatus, sstStatus] = await Promise.all([
31
+ loadCDKStatus(),
32
+ loadSSTStatus(),
33
+ ]);
34
+ const needToBootstrapCDK = !cdkStatus;
35
+ const needToBootstrapSST = !sstStatus || sstStatus.version !== LATEST_VERSION;
36
+ if (needToBootstrapCDK || needToBootstrapSST) {
35
37
  const spinner = createSpinner("Deploying bootstrap stack, this only needs to happen once").start();
36
- // Create bootstrap stack
37
- const app = new App();
38
- const stack = new Stack(app, STACK_NAME, {
39
- env: {
40
- region: project.config.region,
41
- },
42
- });
43
- // Add tags to stack
44
- const tags = {};
45
- for (const [key, value] of Object.entries(tags)) {
46
- Tags.of(app).add(key, value);
38
+ if (needToBootstrapCDK) {
39
+ await bootstrapCDK();
47
40
  }
48
- // Create S3 bucket to store stacks metadata
49
- const bucket = new Bucket(stack, project.config.region, {
50
- encryption: BucketEncryption.S3_MANAGED,
51
- removalPolicy: RemovalPolicy.DESTROY,
52
- autoDeleteObjects: true,
53
- blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
54
- });
55
- // Create Function and subscribe to CloudFormation events
56
- const fn = new Function(stack, "MetadataHandler", {
57
- code: Code.fromAsset(path.resolve(__dirname, "support/bootstrap-metadata-function")),
58
- handler: "index.handler",
59
- runtime: Runtime.NODEJS_18_X,
60
- initialPolicy: [
61
- new PolicyStatement({
62
- actions: ["cloudformation:DescribeStacks"],
63
- resources: ["*"],
64
- }),
65
- new PolicyStatement({
66
- actions: ["s3:PutObject", "s3:DeleteObject"],
67
- resources: [bucket.bucketArn + "/*"],
68
- }),
69
- new PolicyStatement({
70
- actions: ["iot:Publish"],
71
- resources: [
72
- `arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`,
73
- ],
74
- }),
75
- ],
76
- });
77
- const queue = new Queue(stack, "MetadataQueue");
78
- fn.addEventSource(new SqsEventSource(queue));
79
- const rule = new Rule(stack, "MetadataRule", {
80
- eventPattern: {
81
- source: ["aws.cloudformation"],
82
- detailType: ["CloudFormation Stack Status Change"],
83
- detail: {
84
- "status-details": {
85
- status: [
86
- "CREATE_COMPLETE",
87
- "UPDATE_COMPLETE",
88
- "UPDATE_ROLLBACK_COMPLETE",
89
- "ROLLBACK_COMPLETE",
90
- "DELETE_COMPLETE",
91
- ],
92
- },
93
- },
94
- },
95
- });
96
- rule.addTarget(new SqsQueue(queue, {
97
- retryAttempts: 10,
98
- }));
99
- // Create stack outputs to store bootstrap stack info
100
- new CfnOutput(stack, OUTPUT_VERSION, { value: LATEST_VERSION });
101
- new CfnOutput(stack, OUTPUT_BUCKET, { value: bucket.bucketName });
102
- // Deploy bootstrap stack
103
- const asm = app.synth();
104
- const result = await Stacks.deploy(asm.stacks[0]);
105
- if (Stacks.isFailed(result.status)) {
106
- throw new VisibleError(`Failed to deploy bootstrap stack:\n${JSON.stringify(result.errors, null, 4)}`);
41
+ if (needToBootstrapSST) {
42
+ await bootstrapSST();
43
+ // fetch bootstrap status
44
+ sstStatus = await loadSSTStatus();
45
+ if (!sstStatus)
46
+ throw new VisibleError("Failed to load bootstrap stack status");
107
47
  }
108
48
  spinner.succeed();
109
- // Fetch bootstrap status
110
- const ret = await load();
111
- if (!ret)
112
- throw new VisibleError("Failed to load bootstrap stack status");
113
- return ret;
114
- })();
115
- BootstrapContext.provide(status);
116
- Logger.debug("Bootstrap context initialized", status);
49
+ }
50
+ BootstrapContext.provide(sstStatus);
51
+ Logger.debug("Bootstrap context initialized", sstStatus);
117
52
  }
118
- async function assertCDKToolkit() {
53
+ async function loadCDKStatus() {
119
54
  const client = useAWSClient(CloudFormationClient);
120
- const { Stacks: stacks } = await client.send(new DescribeStacksCommand({
121
- StackName: "CDKToolkit",
55
+ try {
56
+ const { Stacks: stacks } = await client.send(new DescribeStacksCommand({
57
+ StackName: "CDKToolkit",
58
+ }));
59
+ if (stacks && stacks.length > 0 && [
60
+ "CREATE_COMPLETE",
61
+ "UPDATE_COMPLETE",
62
+ ].includes(stacks[0].StackStatus)) {
63
+ return true;
64
+ }
65
+ }
66
+ catch (e) {
67
+ if (e.name === "ValidationError"
68
+ && e.message === "Stack with id CDKToolkit does not exist") {
69
+ return false;
70
+ }
71
+ else {
72
+ throw e;
73
+ }
74
+ }
75
+ return false;
76
+ }
77
+ async function bootstrapSST() {
78
+ // Create bootstrap stack
79
+ const project = useProject();
80
+ const app = new App();
81
+ const stack = new Stack(app, STACK_NAME, {
82
+ env: {
83
+ region: project.config.region,
84
+ },
85
+ });
86
+ // Add tags to stack
87
+ const tags = {};
88
+ for (const [key, value] of Object.entries(tags)) {
89
+ Tags.of(app).add(key, value);
90
+ }
91
+ // Create S3 bucket to store stacks metadata
92
+ const bucket = new Bucket(stack, project.config.region, {
93
+ encryption: BucketEncryption.S3_MANAGED,
94
+ removalPolicy: RemovalPolicy.DESTROY,
95
+ autoDeleteObjects: true,
96
+ blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
97
+ });
98
+ // Create Function and subscribe to CloudFormation events
99
+ const fn = new Function(stack, "MetadataHandler", {
100
+ code: Code.fromAsset(path.resolve(__dirname, "support/bootstrap-metadata-function")),
101
+ handler: "index.handler",
102
+ runtime: Runtime.NODEJS_18_X,
103
+ initialPolicy: [
104
+ new PolicyStatement({
105
+ actions: ["cloudformation:DescribeStacks"],
106
+ resources: ["*"],
107
+ }),
108
+ new PolicyStatement({
109
+ actions: ["s3:PutObject", "s3:DeleteObject"],
110
+ resources: [bucket.bucketArn + "/*"],
111
+ }),
112
+ new PolicyStatement({
113
+ actions: ["iot:Publish"],
114
+ resources: [
115
+ `arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`,
116
+ ],
117
+ }),
118
+ ],
119
+ });
120
+ const queue = new Queue(stack, "MetadataQueue");
121
+ fn.addEventSource(new SqsEventSource(queue));
122
+ const rule = new Rule(stack, "MetadataRule", {
123
+ eventPattern: {
124
+ source: ["aws.cloudformation"],
125
+ detailType: ["CloudFormation Stack Status Change"],
126
+ detail: {
127
+ "status-details": {
128
+ status: [
129
+ "CREATE_COMPLETE",
130
+ "UPDATE_COMPLETE",
131
+ "UPDATE_ROLLBACK_COMPLETE",
132
+ "ROLLBACK_COMPLETE",
133
+ "DELETE_COMPLETE",
134
+ ],
135
+ },
136
+ },
137
+ },
138
+ });
139
+ rule.addTarget(new SqsQueue(queue, {
140
+ retryAttempts: 10,
122
141
  }));
123
- if (!stacks || stacks.length === 0) {
124
- const identity = await useSTSIdentity();
125
- const credentials = await useAWSCredentials();
126
- const project = useProject();
127
- spawnSync([
142
+ // Create stack outputs to store bootstrap stack info
143
+ new CfnOutput(stack, OUTPUT_VERSION, { value: LATEST_VERSION });
144
+ new CfnOutput(stack, OUTPUT_BUCKET, { value: bucket.bucketName });
145
+ // Deploy bootstrap stack
146
+ const asm = app.synth();
147
+ const result = await Stacks.deploy(asm.stacks[0]);
148
+ if (Stacks.isFailed(result.status)) {
149
+ throw new VisibleError(`Failed to deploy bootstrap stack:\n${JSON.stringify(result.errors, null, 4)}`);
150
+ }
151
+ }
152
+ async function bootstrapCDK() {
153
+ const identity = await useSTSIdentity();
154
+ const credentials = await useAWSCredentials();
155
+ const { region, profile } = useProject().config;
156
+ await new Promise((resolve, reject) => {
157
+ const proc = spawn([
128
158
  "npx",
129
159
  "cdk",
130
160
  "bootstrap",
131
- `aws://${identity.Account}/${useProject().config.region}`,
161
+ `aws://${identity.Account}/${region}`,
162
+ "--no-version-reporting",
132
163
  ].join(" "), {
133
164
  env: {
134
165
  ...process.env,
135
166
  AWS_ACCESS_KEY_ID: credentials.accessKeyId,
136
167
  AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
137
168
  AWS_SESSION_TOKEN: credentials.sessionToken,
138
- AWS_REGION: project.config.region,
139
- AWS_PROFILE: project.config.profile,
169
+ AWS_REGION: region,
170
+ AWS_PROFILE: profile,
140
171
  },
141
- stdio: "inherit",
172
+ stdio: "pipe",
142
173
  shell: process.env.SHELL || true,
143
174
  });
144
- }
175
+ let stderr = "";
176
+ proc.stdout.on("data", (data) => {
177
+ Logger.debug(data.toString());
178
+ });
179
+ proc.stderr.on("data", (data) => {
180
+ Logger.debug(data.toString());
181
+ stderr += data;
182
+ });
183
+ proc.on("exit", (code) => {
184
+ Logger.debug("CDK bootstrap exited with code " + code);
185
+ if (code === 0) {
186
+ resolve();
187
+ }
188
+ else {
189
+ console.log(bold(dim(stderr)));
190
+ reject(new VisibleError(`Failed to bootstrap`));
191
+ }
192
+ });
193
+ });
145
194
  }
146
- async function load() {
195
+ async function loadSSTStatus() {
147
196
  // Get bootstrap CloudFormation stack
148
197
  const cf = useAWSClient(CloudFormationClient);
149
198
  let result;
@@ -2,14 +2,13 @@ export const consoleCommand = async (program) => program.command("console", "Sta
2
2
  const { blue } = await import("colorette");
3
3
  const { useRuntimeServer } = await import("../../runtime/server.js");
4
4
  const { useLocalServer } = await import("../local/server.js");
5
- await Promise.all([
5
+ const [_, local] = await Promise.all([
6
6
  useRuntimeServer(),
7
7
  useLocalServer({
8
8
  key: "",
9
9
  cert: "",
10
10
  live: false,
11
- port: 13557,
12
11
  }),
13
12
  ]);
14
- console.log(`Console started: ${blue(`https://console.sst.dev`)}`);
13
+ console.log(`Console started: ${blue(local.url)}`);
15
14
  });
@@ -208,12 +208,17 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
208
208
  const project = useProject();
209
209
  const primary = chalk.hex("#E27152");
210
210
  const link = chalk.cyan;
211
+ const local = await useLocalServer({
212
+ key: "",
213
+ cert: "",
214
+ live: true,
215
+ });
211
216
  console.clear();
212
217
  console.log();
213
218
  console.log(` ${Colors.primary(`${bold(`SST`)} v${project.version}`)} ${dim(`ready!`)}`);
214
219
  console.log();
215
220
  console.log(` ${primary(`➜`)} ${bold(`Stage:`)} ${dim(project.config.stage)}`);
216
- console.log(` ${primary(`➜`)} ${bold(`Console:`)} ${link(`https://console.sst.dev/${project.config.name}/${project.config.stage}`)}`);
221
+ console.log(` ${primary(`➜`)} ${bold(`Console:`)} ${link(local.url)}`);
217
222
  /*
218
223
  console.log(` ${primary(`➜`)} ${bold(dim(`Outputs:`))}`);
219
224
  for (let i = 0; i < 3; i++) {
@@ -226,12 +231,6 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
226
231
  }
227
232
  */
228
233
  await Promise.all([
229
- useLocalServer({
230
- key: "",
231
- cert: "",
232
- live: true,
233
- port: 13557,
234
- }),
235
234
  useRuntimeWorkers(),
236
235
  useIOTBridge(),
237
236
  useRuntimeServer(),
@@ -2,7 +2,6 @@ import { FunctionState, State } from "./router.js";
2
2
  import { WritableDraft } from "immer/dist/internal.js";
3
3
  import { DendriformPatch } from "dendriform-immer-patch-optimiser";
4
4
  type Opts = {
5
- port: number;
6
5
  key: any;
7
6
  cert: any;
8
7
  live: boolean;
@@ -14,6 +13,7 @@ declare module "../../bus.js" {
14
13
  }
15
14
  export declare function useLocalServer(opts: Opts): Promise<{
16
15
  port: number;
16
+ url: string;
17
17
  updateState: (cb: (draft: WritableDraft<State>) => void) => void;
18
18
  updateFunction: (id: string, cb: (draft: WritableDraft<FunctionState>) => void) => void;
19
19
  }>;
@@ -11,8 +11,12 @@ import { optimise } from "dendriform-immer-patch-optimiser";
11
11
  import { sync } from "cross-spawn";
12
12
  import { useProject } from "../../project.js";
13
13
  import { useBus } from "../../bus.js";
14
+ import getPort from "get-port";
14
15
  export async function useLocalServer(opts) {
15
16
  const project = useProject();
17
+ const port = await getPort({
18
+ port: 13557,
19
+ });
16
20
  let state = {
17
21
  app: project.config.name,
18
22
  stage: project.config.stage,
@@ -102,7 +106,7 @@ export async function useLocalServer(opts) {
102
106
  console.log("Rejecting unauthorized connection from " + req.headers.origin);
103
107
  socket.terminate();
104
108
  });
105
- server.listen(opts.port);
109
+ server.listen(port);
106
110
  const handler = applyWSSHandler({
107
111
  wss,
108
112
  router,
@@ -199,7 +203,8 @@ export async function useLocalServer(opts) {
199
203
  });
200
204
  });
201
205
  const result = {
202
- port: opts.port,
206
+ port,
207
+ url: `https://console.sst.dev/${project.config.name}/${project.config.stage}${port !== 13557 ? `?port=${port}` : ""}`,
203
208
  updateState,
204
209
  updateFunction,
205
210
  };
package/cli/ui/deploy.js CHANGED
@@ -83,7 +83,7 @@ export function printDeploymentResults(assembly, results) {
83
83
  return false;
84
84
  if (key.includes("SstSiteEnv"))
85
85
  return false;
86
- if (key === "SstMetadata")
86
+ if (key === "SSTMetadata")
87
87
  return false;
88
88
  return true;
89
89
  });
package/constructs/App.js CHANGED
@@ -303,7 +303,7 @@ export class App extends cdk.App {
303
303
  if (child instanceof Stack) {
304
304
  const stackName = child.node.id;
305
305
  child.addOutputs({
306
- SstMetadata: JSON.stringify({
306
+ SSTMetadata: JSON.stringify({
307
307
  app: this.name,
308
308
  stage: this.stage,
309
309
  version: useProject().version,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.0.0-rc.39",
3
+ "version": "2.0.0-rc.40",
4
4
  "bin": {
5
5
  "sst": "cli/sst.js"
6
6
  },
@@ -66,6 +66,7 @@
66
66
  "esbuild": "0.16.13",
67
67
  "express": "^4.18.2",
68
68
  "fast-jwt": "^1.6.1",
69
+ "get-port": "^6.1.2",
69
70
  "glob": "^8.0.3",
70
71
  "graphql": "*",
71
72
  "graphql-helix": "^1.12.0",
@@ -1 +1 @@
1
- export declare const useDotnetHandler: () => void;
1
+ export declare const useDotnetHandler: () => Promise<void>;
@@ -21,10 +21,10 @@ const BOOTSTRAP_MAP = {
21
21
  "dotnetcore3.1": "dotnet31-bootstrap",
22
22
  dotnet6: "dotnet6-bootstrap",
23
23
  };
24
- export const useDotnetHandler = Context.memo(() => {
25
- const workers = useRuntimeWorkers();
24
+ export const useDotnetHandler = Context.memo(async () => {
25
+ const workers = await useRuntimeWorkers();
26
+ const server = await useRuntimeServerConfig();
26
27
  const handlers = useRuntimeHandlers();
27
- const server = useRuntimeServerConfig();
28
28
  const processes = new Map();
29
29
  const sources = new Map();
30
30
  const handlerName = process.platform === "win32" ? `handler.exe` : `handler`;
@@ -1 +1 @@
1
- export declare const useGoHandler: () => void;
1
+ export declare const useGoHandler: () => Promise<void>;
@@ -9,10 +9,10 @@ import { promisify } from "util";
9
9
  import { useRuntimeServerConfig } from "../server.js";
10
10
  import { isChild } from "../../util/fs.js";
11
11
  const execAsync = promisify(exec);
12
- export const useGoHandler = Context.memo(() => {
13
- const workers = useRuntimeWorkers();
12
+ export const useGoHandler = Context.memo(async () => {
13
+ const workers = await useRuntimeWorkers();
14
+ const server = await useRuntimeServerConfig();
14
15
  const handlers = useRuntimeHandlers();
15
- const server = useRuntimeServerConfig();
16
16
  const processes = new Map();
17
17
  const sources = new Map();
18
18
  const handlerName = process.platform === "win32" ? `handler.exe` : `handler`;
@@ -1 +1 @@
1
- export declare const useJavaHandler: () => void;
1
+ export declare const useJavaHandler: () => Promise<void>;
@@ -11,10 +11,10 @@ import { existsAsync, findBelow, isChild } from "../../util/fs.js";
11
11
  import { useProject } from "../../project.js";
12
12
  import { execAsync } from "../../util/process.js";
13
13
  import url from "url";
14
- export const useJavaHandler = Context.memo(() => {
15
- const workers = useRuntimeWorkers();
14
+ export const useJavaHandler = Context.memo(async () => {
15
+ const workers = await useRuntimeWorkers();
16
+ const server = await useRuntimeServerConfig();
16
17
  const handlers = useRuntimeHandlers();
17
- const server = useRuntimeServerConfig();
18
18
  const processes = new Map();
19
19
  const sources = new Map();
20
20
  const handlerName = process.platform === "win32" ? `handler.exe` : `handler`;
@@ -1 +1 @@
1
- export declare const useNodeHandler: () => void;
1
+ export declare const useNodeHandler: () => Promise<void>;
@@ -10,8 +10,8 @@ import { useRuntimeHandlers } from "../handlers.js";
10
10
  import { useRuntimeWorkers } from "../workers.js";
11
11
  import { Context } from "../../context/context.js";
12
12
  import { VisibleError } from "../../error.js";
13
- export const useNodeHandler = Context.memo(() => {
14
- const workers = useRuntimeWorkers();
13
+ export const useNodeHandler = Context.memo(async () => {
14
+ const workers = await useRuntimeWorkers();
15
15
  const handlers = useRuntimeHandlers();
16
16
  const cache = {};
17
17
  const project = useProject();
@@ -1 +1 @@
1
- export declare const usePythonHandler: () => void;
1
+ export declare const usePythonHandler: () => Promise<void>;
@@ -18,10 +18,10 @@ const RUNTIME_MAP = {
18
18
  "python3.8": Runtime.PYTHON_3_8,
19
19
  "python3.9": Runtime.PYTHON_3_9,
20
20
  };
21
- export const usePythonHandler = Context.memo(() => {
22
- const workers = useRuntimeWorkers();
21
+ export const usePythonHandler = Context.memo(async () => {
22
+ const workers = await useRuntimeWorkers();
23
+ const server = await useRuntimeServerConfig();
23
24
  const handlers = useRuntimeHandlers();
24
- const server = useRuntimeServerConfig();
25
25
  const processes = new Map();
26
26
  const sources = new Map();
27
27
  handlers.register({
@@ -1,6 +1,6 @@
1
- export declare const useRuntimeServerConfig: () => {
1
+ export declare const useRuntimeServerConfig: () => Promise<{
2
2
  API_VERSION: string;
3
- url: string;
4
3
  port: number;
5
- };
4
+ url: string;
5
+ }>;
6
6
  export declare const useRuntimeServer: () => Promise<void>;
package/runtime/server.js CHANGED
@@ -4,18 +4,22 @@ import { useBus } from "../bus.js";
4
4
  import { Logger } from "../logger.js";
5
5
  import { useRuntimeWorkers } from "./workers.js";
6
6
  import https from "https";
7
- export const useRuntimeServerConfig = Context.memo(() => {
7
+ import getPort from "get-port";
8
+ export const useRuntimeServerConfig = Context.memo(async () => {
9
+ const port = await getPort({
10
+ port: 12557,
11
+ });
8
12
  return {
9
13
  API_VERSION: "2018-06-01",
10
- url: "http://localhost:12557",
11
- port: 12557,
14
+ port,
15
+ url: `http://localhost:${port}`,
12
16
  };
13
17
  });
14
18
  export const useRuntimeServer = Context.memo(async () => {
15
19
  const bus = useBus();
16
20
  const app = express();
17
- const workers = useRuntimeWorkers();
18
- const cfg = useRuntimeServerConfig();
21
+ const workers = await useRuntimeWorkers();
22
+ const cfg = await useRuntimeServerConfig();
19
23
  const workersWaiting = new Map();
20
24
  const invocationsQueued = new Map();
21
25
  function next(workerID) {
@@ -24,7 +24,7 @@ interface Worker {
24
24
  workerID: string;
25
25
  functionID: string;
26
26
  }
27
- export declare const useRuntimeWorkers: () => {
27
+ export declare const useRuntimeWorkers: () => Promise<{
28
28
  fromID(workerID: string): Worker;
29
29
  setCurrentRequestID(workerID: string, requestID: string): void;
30
30
  stdout(workerID: string, message: string): void;
@@ -33,5 +33,5 @@ export declare const useRuntimeWorkers: () => {
33
33
  type: keyof import("../bus.js").Events;
34
34
  cb: (payload: any) => void;
35
35
  };
36
- };
36
+ }>;
37
37
  export {};
@@ -3,12 +3,12 @@ import { useBus } from "../bus.js";
3
3
  import { useFunctionBuilder, useRuntimeHandlers } from "./handlers.js";
4
4
  import { useRuntimeServerConfig } from "./server.js";
5
5
  import { useFunctions } from "../constructs/Function.js";
6
- export const useRuntimeWorkers = Context.memo(() => {
6
+ export const useRuntimeWorkers = Context.memo(async () => {
7
7
  const workers = new Map();
8
8
  const bus = useBus();
9
9
  const handlers = useRuntimeHandlers();
10
10
  const builder = useFunctionBuilder();
11
- const server = useRuntimeServerConfig();
11
+ const server = await useRuntimeServerConfig();
12
12
  handlers.subscribe("function.build.success", async (evt) => {
13
13
  for (const [_, worker] of workers) {
14
14
  if (worker.functionID === evt.properties.functionID) {