sst 2.20.1 → 2.21.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.
@@ -1,11 +1,13 @@
1
+ import http from "http";
2
+ import { spawn } from "child_process";
1
3
  import { useRuntimeHandlers } from "../handlers.js";
2
4
  import { useRuntimeWorkers } from "../workers.js";
5
+ import { useRuntimeServerConfig } from "../server.js";
3
6
  import { Context } from "../../context/context.js";
4
7
  import { VisibleError } from "../../error.js";
5
- import { spawn } from "child_process";
6
- import { useRuntimeServerConfig } from "../server.js";
7
8
  import { isChild } from "../../util/fs.js";
8
9
  import { execAsync } from "../../util/process.js";
10
+ import { useFunctions } from "../../constructs/Function.js";
9
11
  export const useContainerHandler = Context.memo(async () => {
10
12
  const workers = await useRuntimeWorkers();
11
13
  const server = await useRuntimeServerConfig();
@@ -21,36 +23,9 @@ export const useContainerHandler = Context.memo(async () => {
21
23
  },
22
24
  canHandle: (input) => input.startsWith("container"),
23
25
  startWorker: async (input) => {
24
- const name = `sst-workerID-${input.workerID}-${Date.now()}`;
25
- const proc = spawn("docker", [
26
- "run",
27
- "--rm",
28
- "--network=host",
29
- `--name=${name}`,
30
- ...Object.entries({
31
- ...input.environment,
32
- IS_LOCAL: "true",
33
- AWS_LAMBDA_RUNTIME_API: `host.docker.internal:${server.port}/${input.workerID}`,
34
- })
35
- .map(([key, value]) => ["-e", `${key}=${value}`])
36
- .flat(),
37
- `sst-dev:${input.functionID}`,
38
- ], {
39
- env: {
40
- ...process.env,
41
- },
42
- cwd: input.out,
43
- });
44
- proc.on("exit", () => {
45
- workers.exited(input.workerID);
46
- });
47
- proc.stdout.on("data", (data) => {
48
- workers.stdout(input.workerID, data.toString());
49
- });
50
- proc.stderr.on("data", (data) => {
51
- workers.stdout(input.workerID, data.toString());
52
- });
53
- containers.set(input.workerID, name);
26
+ input.environment.SST_DEBUG_JOB
27
+ ? startJobWorker(input)
28
+ : startLambdaWorker(input);
54
29
  },
55
30
  stopWorker: async (workerID) => {
56
31
  const name = containers.get(workerID);
@@ -121,4 +96,157 @@ export const useContainerHandler = Context.memo(async () => {
121
96
  };
122
97
  },
123
98
  });
99
+ function dockerRun(input, opts, onExit) {
100
+ const name = `sst-workerID-${input.workerID}-${Date.now()}`;
101
+ const proc = spawn("docker", [
102
+ "run",
103
+ "--rm",
104
+ "--network=host",
105
+ `--name=${name}`,
106
+ ...Object.entries({
107
+ ...input.environment,
108
+ ...opts.envs,
109
+ IS_LOCAL: "true",
110
+ })
111
+ .map(([key, value]) => ["-e", `${key}=${value}`])
112
+ .flat(),
113
+ ...(opts.entrypoint !== undefined
114
+ ? ["--entrypoint", opts.entrypoint]
115
+ : []),
116
+ `sst-dev:${input.functionID}`,
117
+ ...(opts.cmd ?? []),
118
+ ], {
119
+ env: {
120
+ ...process.env,
121
+ },
122
+ cwd: input.out,
123
+ });
124
+ proc.on("exit", (code) => {
125
+ onExit(code);
126
+ });
127
+ proc.stdout.on("data", (data) => {
128
+ workers.stdout(input.workerID, data.toString());
129
+ });
130
+ proc.stderr.on("data", (data) => {
131
+ workers.stdout(input.workerID, data.toString());
132
+ });
133
+ containers.set(input.workerID, name);
134
+ }
135
+ function startLambdaWorker(input) {
136
+ const fn = useFunctions().fromID(input.functionID);
137
+ dockerRun(input, {
138
+ cmd: fn?.container?.cmd,
139
+ envs: {
140
+ AWS_LAMBDA_RUNTIME_API: `host.docker.internal:${server.port}/${input.workerID}`,
141
+ },
142
+ }, () => {
143
+ workers.exited(input.workerID);
144
+ });
145
+ }
146
+ async function startJobWorker(input) {
147
+ // Job container is special:
148
+ // 1. Not capable of receiving the `event` payload
149
+ // - on `sst deploy`, the CodeBuild job is started with `SST_PAYLOAD` env var
150
+ // - on `sst dev`, set `SST_DEBUG_JOB` env var here
151
+ // 2. Worker exits at the end of the run.
152
+ // Fetch request
153
+ const result = await init();
154
+ const awsRequestId = result.headers["lambda-runtime-aws-request-id"];
155
+ const fn = useFunctions().fromID(input.functionID);
156
+ try {
157
+ dockerRun(input, {
158
+ entrypoint: "",
159
+ cmd: fn?.container?.cmd,
160
+ envs: {
161
+ SST_PAYLOAD: result.body,
162
+ },
163
+ }, async (code) => {
164
+ code === 0 ? await success() : await error();
165
+ workers.exited(input.workerID);
166
+ });
167
+ }
168
+ catch (ex) {
169
+ await initError(ex);
170
+ workers.exited(input.workerID);
171
+ }
172
+ async function init() {
173
+ return await fetch({
174
+ path: `/runtime/invocation/next`,
175
+ method: "GET",
176
+ headers: {},
177
+ });
178
+ }
179
+ async function initError(ex) {
180
+ return await fetch({
181
+ path: `/runtime/init/error`,
182
+ method: "POST",
183
+ headers: {
184
+ "Content-Type": "application/json",
185
+ },
186
+ body: JSON.stringify({
187
+ errorType: "Error",
188
+ errorMessage: ex.message,
189
+ trace: ex.stack?.split("\n"),
190
+ }),
191
+ });
192
+ }
193
+ async function success() {
194
+ while (true) {
195
+ try {
196
+ await fetch({
197
+ path: `/runtime/invocation/${awsRequestId}/response`,
198
+ method: "POST",
199
+ headers: {
200
+ "Content-Type": "application/json",
201
+ },
202
+ body: JSON.stringify("Job completed successfully"),
203
+ });
204
+ break;
205
+ }
206
+ catch (ex) {
207
+ console.error(ex);
208
+ await new Promise((resolve) => setTimeout(resolve, 500));
209
+ }
210
+ }
211
+ }
212
+ async function error() {
213
+ return await fetch({
214
+ path: `/runtime/invocation/${awsRequestId}/error`,
215
+ method: "POST",
216
+ headers: {
217
+ "Content-Type": "application/json",
218
+ },
219
+ body: JSON.stringify({
220
+ errorType: "Error",
221
+ errorMessage: "Failed to run job",
222
+ trace: [],
223
+ }),
224
+ });
225
+ }
226
+ function fetch(req) {
227
+ return new Promise((resolve, reject) => {
228
+ const request = http.request(input.url + req.path, {
229
+ headers: req.headers,
230
+ method: req.method,
231
+ }, (res) => {
232
+ let body = "";
233
+ res.setEncoding("utf8");
234
+ res.on("data", (chunk) => {
235
+ body += chunk.toString();
236
+ });
237
+ res.on("end", () => {
238
+ resolve({
239
+ statusCode: res.statusCode,
240
+ headers: res.headers,
241
+ body,
242
+ });
243
+ });
244
+ });
245
+ request.on("error", reject);
246
+ if (req.body)
247
+ request.write(req.body);
248
+ request.end();
249
+ });
250
+ }
251
+ }
124
252
  });
@@ -19,7 +19,7 @@ interface BuildInput {
19
19
  out: string;
20
20
  props: FunctionProps;
21
21
  }
22
- interface StartWorkerInput {
22
+ export interface StartWorkerInput {
23
23
  url: string;
24
24
  workerID: string;
25
25
  functionID: string;
package/sst.mjs CHANGED
@@ -5718,16 +5718,18 @@ var container_exports = {};
5718
5718
  __export(container_exports, {
5719
5719
  useContainerHandler: () => useContainerHandler
5720
5720
  });
5721
+ import http from "http";
5721
5722
  import { spawn as spawn3 } from "child_process";
5723
+ import { useFunctions as useFunctions3 } from "../src/constructs/Function.js";
5722
5724
  var useContainerHandler;
5723
5725
  var init_container = __esm({
5724
5726
  "src/runtime/handlers/container.ts"() {
5725
5727
  "use strict";
5726
5728
  init_handlers2();
5727
5729
  init_workers();
5730
+ init_server();
5728
5731
  init_context();
5729
5732
  init_error();
5730
- init_server();
5731
5733
  init_fs();
5732
5734
  init_process();
5733
5735
  useContainerHandler = Context.memo(async () => {
@@ -5745,38 +5747,7 @@ var init_container = __esm({
5745
5747
  },
5746
5748
  canHandle: (input) => input.startsWith("container"),
5747
5749
  startWorker: async (input) => {
5748
- const name = `sst-workerID-${input.workerID}-${Date.now()}`;
5749
- const proc = spawn3(
5750
- "docker",
5751
- [
5752
- "run",
5753
- "--rm",
5754
- "--network=host",
5755
- `--name=${name}`,
5756
- ...Object.entries({
5757
- ...input.environment,
5758
- IS_LOCAL: "true",
5759
- AWS_LAMBDA_RUNTIME_API: `host.docker.internal:${server.port}/${input.workerID}`
5760
- }).map(([key, value]) => ["-e", `${key}=${value}`]).flat(),
5761
- `sst-dev:${input.functionID}`
5762
- ],
5763
- {
5764
- env: {
5765
- ...process.env
5766
- },
5767
- cwd: input.out
5768
- }
5769
- );
5770
- proc.on("exit", () => {
5771
- workers.exited(input.workerID);
5772
- });
5773
- proc.stdout.on("data", (data2) => {
5774
- workers.stdout(input.workerID, data2.toString());
5775
- });
5776
- proc.stderr.on("data", (data2) => {
5777
- workers.stdout(input.workerID, data2.toString());
5778
- });
5779
- containers.set(input.workerID, name);
5750
+ input.environment.SST_DEBUG_JOB ? startJobWorker(input) : startLambdaWorker(input);
5780
5751
  },
5781
5752
  stopWorker: async (workerID) => {
5782
5753
  const name = containers.get(workerID);
@@ -5845,6 +5816,163 @@ var init_container = __esm({
5845
5816
  };
5846
5817
  }
5847
5818
  });
5819
+ function dockerRun(input, opts, onExit) {
5820
+ const name = `sst-workerID-${input.workerID}-${Date.now()}`;
5821
+ const proc = spawn3(
5822
+ "docker",
5823
+ [
5824
+ "run",
5825
+ "--rm",
5826
+ "--network=host",
5827
+ `--name=${name}`,
5828
+ ...Object.entries({
5829
+ ...input.environment,
5830
+ ...opts.envs,
5831
+ IS_LOCAL: "true"
5832
+ }).map(([key, value]) => ["-e", `${key}=${value}`]).flat(),
5833
+ ...opts.entrypoint !== void 0 ? ["--entrypoint", opts.entrypoint] : [],
5834
+ `sst-dev:${input.functionID}`,
5835
+ ...opts.cmd ?? []
5836
+ ],
5837
+ {
5838
+ env: {
5839
+ ...process.env
5840
+ },
5841
+ cwd: input.out
5842
+ }
5843
+ );
5844
+ proc.on("exit", (code) => {
5845
+ onExit(code);
5846
+ });
5847
+ proc.stdout.on("data", (data2) => {
5848
+ workers.stdout(input.workerID, data2.toString());
5849
+ });
5850
+ proc.stderr.on("data", (data2) => {
5851
+ workers.stdout(input.workerID, data2.toString());
5852
+ });
5853
+ containers.set(input.workerID, name);
5854
+ }
5855
+ function startLambdaWorker(input) {
5856
+ const fn = useFunctions3().fromID(input.functionID);
5857
+ dockerRun(
5858
+ input,
5859
+ {
5860
+ cmd: fn?.container?.cmd,
5861
+ envs: {
5862
+ AWS_LAMBDA_RUNTIME_API: `host.docker.internal:${server.port}/${input.workerID}`
5863
+ }
5864
+ },
5865
+ () => {
5866
+ workers.exited(input.workerID);
5867
+ }
5868
+ );
5869
+ }
5870
+ async function startJobWorker(input) {
5871
+ const result = await init();
5872
+ const awsRequestId = result.headers["lambda-runtime-aws-request-id"];
5873
+ const fn = useFunctions3().fromID(input.functionID);
5874
+ try {
5875
+ dockerRun(
5876
+ input,
5877
+ {
5878
+ entrypoint: "",
5879
+ cmd: fn?.container?.cmd,
5880
+ envs: {
5881
+ SST_PAYLOAD: result.body
5882
+ }
5883
+ },
5884
+ async (code) => {
5885
+ code === 0 ? await success() : await error3();
5886
+ workers.exited(input.workerID);
5887
+ }
5888
+ );
5889
+ } catch (ex) {
5890
+ await initError(ex);
5891
+ workers.exited(input.workerID);
5892
+ }
5893
+ async function init() {
5894
+ return await fetch({
5895
+ path: `/runtime/invocation/next`,
5896
+ method: "GET",
5897
+ headers: {}
5898
+ });
5899
+ }
5900
+ async function initError(ex) {
5901
+ return await fetch({
5902
+ path: `/runtime/init/error`,
5903
+ method: "POST",
5904
+ headers: {
5905
+ "Content-Type": "application/json"
5906
+ },
5907
+ body: JSON.stringify({
5908
+ errorType: "Error",
5909
+ errorMessage: ex.message,
5910
+ trace: ex.stack?.split("\n")
5911
+ })
5912
+ });
5913
+ }
5914
+ async function success() {
5915
+ while (true) {
5916
+ try {
5917
+ await fetch({
5918
+ path: `/runtime/invocation/${awsRequestId}/response`,
5919
+ method: "POST",
5920
+ headers: {
5921
+ "Content-Type": "application/json"
5922
+ },
5923
+ body: JSON.stringify("Job completed successfully")
5924
+ });
5925
+ break;
5926
+ } catch (ex) {
5927
+ console.error(ex);
5928
+ await new Promise((resolve2) => setTimeout(resolve2, 500));
5929
+ }
5930
+ }
5931
+ }
5932
+ async function error3() {
5933
+ return await fetch({
5934
+ path: `/runtime/invocation/${awsRequestId}/error`,
5935
+ method: "POST",
5936
+ headers: {
5937
+ "Content-Type": "application/json"
5938
+ },
5939
+ body: JSON.stringify({
5940
+ errorType: "Error",
5941
+ errorMessage: "Failed to run job",
5942
+ trace: []
5943
+ })
5944
+ });
5945
+ }
5946
+ function fetch(req) {
5947
+ return new Promise((resolve2, reject) => {
5948
+ const request = http.request(
5949
+ input.url + req.path,
5950
+ {
5951
+ headers: req.headers,
5952
+ method: req.method
5953
+ },
5954
+ (res) => {
5955
+ let body = "";
5956
+ res.setEncoding("utf8");
5957
+ res.on("data", (chunk) => {
5958
+ body += chunk.toString();
5959
+ });
5960
+ res.on("end", () => {
5961
+ resolve2({
5962
+ statusCode: res.statusCode,
5963
+ headers: res.headers,
5964
+ body
5965
+ });
5966
+ });
5967
+ }
5968
+ );
5969
+ request.on("error", reject);
5970
+ if (req.body)
5971
+ request.write(req.body);
5972
+ request.end();
5973
+ });
5974
+ }
5975
+ }
5848
5976
  });
5849
5977
  }
5850
5978
  });
@@ -6855,7 +6983,7 @@ import express2 from "express";
6855
6983
  import fs14 from "fs/promises";
6856
6984
  import { WebSocketServer } from "ws";
6857
6985
  import https3 from "https";
6858
- import http from "http";
6986
+ import http2 from "http";
6859
6987
  import { applyWSSHandler } from "@trpc/server/adapters/ws/dist/trpc-server-adapters-ws.cjs.js";
6860
6988
  import { optimise } from "dendriform-immer-patch-optimiser";
6861
6989
  import { sync } from "cross-spawn";
@@ -6951,7 +7079,7 @@ async function useLocalServer(opts) {
6951
7079
  rest
6952
7080
  );
6953
7081
  }
6954
- return http.createServer({}, rest);
7082
+ return http2.createServer({}, rest);
6955
7083
  })();
6956
7084
  const wss = new WebSocketServer({ server });
6957
7085
  wss.on("connection", (socket, req) => {
@@ -8210,7 +8338,7 @@ var dev = (program2) => program2.command(
8210
8338
  const { useLocalServer: useLocalServer2 } = await Promise.resolve().then(() => (init_server2(), server_exports2));
8211
8339
  const fs19 = await import("fs/promises");
8212
8340
  const crypto2 = await import("crypto");
8213
- const { useFunctions: useFunctions3 } = await import("../src/constructs/Function.js");
8341
+ const { useFunctions: useFunctions4 } = await import("../src/constructs/Function.js");
8214
8342
  const { useSites } = await import("../src/constructs/SsrSite.js");
8215
8343
  const { usePothosBuilder: usePothosBuilder2 } = await Promise.resolve().then(() => (init_pothos2(), pothos_exports2));
8216
8344
  const { useKyselyTypeGenerator: useKyselyTypeGenerator2 } = await Promise.resolve().then(() => (init_kysely(), kysely_exports));
@@ -8255,12 +8383,12 @@ var dev = (program2) => program2.command(
8255
8383
  prefix(evt.properties.requestID),
8256
8384
  Colors2.dim.bold("Invoked"),
8257
8385
  Colors2.dim(
8258
- useFunctions3().fromID(evt.properties.functionID)?.handler
8386
+ useFunctions4().fromID(evt.properties.functionID)?.handler
8259
8387
  )
8260
8388
  );
8261
8389
  });
8262
8390
  bus.subscribe("worker.stdout", async (evt) => {
8263
- const info = useFunctions3().fromID(evt.properties.functionID);
8391
+ const info = useFunctions4().fromID(evt.properties.functionID);
8264
8392
  prefix(evt.properties.requestID);
8265
8393
  const { started } = pending.get(evt.properties.requestID);
8266
8394
  for (let line of evt.properties.message.split("\n")) {
@@ -8278,7 +8406,7 @@ var dev = (program2) => program2.command(
8278
8406
  }
8279
8407
  });
8280
8408
  bus.subscribe("function.build.started", async (evt) => {
8281
- const info = useFunctions3().fromID(evt.properties.functionID);
8409
+ const info = useFunctions4().fromID(evt.properties.functionID);
8282
8410
  if (!info)
8283
8411
  return;
8284
8412
  if (info.enableLiveDev === false)
@@ -8290,7 +8418,7 @@ var dev = (program2) => program2.command(
8290
8418
  );
8291
8419
  });
8292
8420
  bus.subscribe("function.build.success", async (evt) => {
8293
- const info = useFunctions3().fromID(evt.properties.functionID);
8421
+ const info = useFunctions4().fromID(evt.properties.functionID);
8294
8422
  if (!info)
8295
8423
  return;
8296
8424
  if (info.enableLiveDev === false)
@@ -8300,7 +8428,7 @@ var dev = (program2) => program2.command(
8300
8428
  );
8301
8429
  });
8302
8430
  bus.subscribe("function.build.failed", async (evt) => {
8303
- const info = useFunctions3().fromID(evt.properties.functionID);
8431
+ const info = useFunctions4().fromID(evt.properties.functionID);
8304
8432
  if (!info)
8305
8433
  return;
8306
8434
  if (info.enableLiveDev === false)