sst 2.0.0-rc.2 → 2.0.0-rc.21

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.
Files changed (107) hide show
  1. package/bootstrap.js +3 -3
  2. package/bus.d.ts +3 -3
  3. package/cache.js +1 -1
  4. package/cdk/deploy-stack.d.ts +2 -2
  5. package/cdk/deploy-stack.js +24 -16
  6. package/cli/commands/bind.js +2 -2
  7. package/cli/commands/build.js +4 -4
  8. package/cli/commands/deploy.js +11 -6
  9. package/cli/commands/dev.js +14 -16
  10. package/cli/commands/env.js +4 -3
  11. package/cli/commands/plugins/kysely.js +2 -2
  12. package/cli/commands/remove.js +4 -5
  13. package/cli/commands/update.js +12 -6
  14. package/cli/local/router.d.ts +6 -6
  15. package/cli/local/router.js +3 -3
  16. package/cli/local/server.d.ts +1 -1
  17. package/cli/local/server.js +7 -12
  18. package/cli/program.d.ts +1 -1
  19. package/cli/program.js +1 -1
  20. package/cli/telemetry/environment.d.ts +1 -1
  21. package/cli/telemetry/environment.js +1 -1
  22. package/cli/ui/deploy.js +2 -2
  23. package/config.js +5 -5
  24. package/constructs/Api.d.ts +3 -3
  25. package/constructs/ApiGatewayV1Api.d.ts +2 -2
  26. package/constructs/App.d.ts +2 -2
  27. package/constructs/App.js +1 -1
  28. package/constructs/AppSyncApi.d.ts +1 -1
  29. package/constructs/AppSyncApi.js +1 -1
  30. package/constructs/Function.d.ts +4 -5
  31. package/constructs/Function.js +6 -14
  32. package/constructs/FunctionalStack.d.ts +2 -2
  33. package/constructs/Job.d.ts +1 -1
  34. package/constructs/Job.js +2 -2
  35. package/constructs/Metadata.d.ts +19 -19
  36. package/constructs/NextjsSite.d.ts +1 -1
  37. package/constructs/NextjsSite.js +21 -4
  38. package/constructs/RDS.d.ts +1 -1
  39. package/constructs/RDS.js +1 -1
  40. package/constructs/ReactStaticSite.d.ts +2 -2
  41. package/constructs/ReactStaticSite.js +2 -1
  42. package/constructs/Script.js +1 -1
  43. package/constructs/SsrSite.d.ts +11 -6
  44. package/constructs/SsrSite.js +56 -43
  45. package/constructs/Stack.d.ts +1 -1
  46. package/constructs/Stack.js +1 -1
  47. package/constructs/StaticSite.d.ts +3 -3
  48. package/constructs/StaticSite.js +9 -9
  49. package/constructs/Table.d.ts +1 -1
  50. package/constructs/ViteStaticSite.d.ts +1 -1
  51. package/constructs/ViteStaticSite.js +2 -1
  52. package/constructs/deferred_task.d.ts +1 -1
  53. package/constructs/deprecated/NextjsSite.js +1 -1
  54. package/constructs/util/apiGatewayV1AccessLog.d.ts +1 -1
  55. package/constructs/util/duration.d.ts +1 -1
  56. package/constructs/util/permission.d.ts +3 -3
  57. package/constructs/util/size.d.ts +1 -1
  58. package/context/handler.d.ts +1 -1
  59. package/credentials.d.ts +1 -1
  60. package/credentials.js +8 -6
  61. package/index.d.ts +1 -0
  62. package/index.js +1 -0
  63. package/iot.js +2 -2
  64. package/logger.js +1 -1
  65. package/node/api/index.d.ts +2 -0
  66. package/node/api/index.js +8 -0
  67. package/node/auth/adapter/adapter.d.ts +1 -1
  68. package/node/auth/adapter/github.js +4 -4
  69. package/node/auth/adapter/google.d.ts +1 -1
  70. package/node/auth/session.d.ts +1 -1
  71. package/node/config/index.d.ts +2 -2
  72. package/node/job/index.d.ts +2 -2
  73. package/package.json +8 -13
  74. package/project.d.ts +44 -0
  75. package/{app.js → project.js} +56 -51
  76. package/runtime/handlers/dotnet.js +1 -1
  77. package/runtime/handlers/java.js +1 -1
  78. package/runtime/handlers/node.js +6 -5
  79. package/runtime/handlers.js +14 -11
  80. package/runtime/runtime.d.ts +4 -0
  81. package/runtime/workers.js +4 -0
  82. package/site-env.js +1 -1
  83. package/sst.mjs +807 -16608
  84. package/stacks/build.d.ts +1 -1
  85. package/stacks/build.js +13 -21
  86. package/stacks/metadata.js +5 -5
  87. package/stacks/monitor.d.ts +1 -1
  88. package/stacks/synth.js +4 -4
  89. package/support/base-site-archiver.mjs +79 -0
  90. package/support/bridge/bridge.mjs +83 -22
  91. package/support/custom-resources/index.mjs +22 -1
  92. package/support/edge-function/edge-lambda.mjs +2 -2
  93. package/support/nodejs-runtime/index.mjs +79 -72
  94. package/support/rds-migrator/index.mjs +27 -23
  95. package/support/script-function/index.mjs +30485 -0
  96. package/support/ssr-site-function-archiver.mjs +96 -0
  97. package/watcher.js +1 -1
  98. package/app.d.ts +0 -36
  99. package/constructs/Script/cfn-response.d.ts +0 -19
  100. package/constructs/Script/cfn-response.js +0 -77
  101. package/constructs/Script/index.d.ts +0 -1
  102. package/constructs/Script/index.js +0 -78
  103. package/constructs/Script/outbound.d.ts +0 -10
  104. package/constructs/Script/outbound.js +0 -42
  105. package/constructs/Script/util.d.ts +0 -2
  106. package/constructs/Script/util.js +0 -11
  107. package/support/base-site-archiver.cjs +0 -116
package/watcher.js CHANGED
@@ -2,7 +2,7 @@ import { Context } from "./context/context.js";
2
2
  import chokidar from "chokidar";
3
3
  import { useBus } from "./bus.js";
4
4
  import path from "path";
5
- import { useProject } from "./app.js";
5
+ import { useProject } from "./project.js";
6
6
  export const useWatcher = Context.memo(() => {
7
7
  const project = useProject();
8
8
  const bus = useBus();
package/app.d.ts DELETED
@@ -1,36 +0,0 @@
1
- export interface Project {
2
- name: string;
3
- region: string;
4
- stage?: string;
5
- profile?: string;
6
- main?: string;
7
- ssmPrefix?: string;
8
- }
9
- declare const DEFAULTS: {
10
- readonly main: "stacks/index.ts";
11
- readonly stage: undefined;
12
- readonly ssmPrefix: undefined;
13
- };
14
- declare type ProjectWithDefaults = Project & Required<{
15
- [key in keyof typeof DEFAULTS]: Exclude<Project[key], undefined>;
16
- }> & {
17
- version: string;
18
- paths: {
19
- root: string;
20
- out: string;
21
- artifacts: string;
22
- };
23
- };
24
- export declare const ProjectContext: {
25
- use(): ProjectWithDefaults;
26
- provide(value: ProjectWithDefaults): void;
27
- };
28
- export declare function useProject(): ProjectWithDefaults;
29
- interface GlobalOptions {
30
- profile?: string;
31
- stage?: string;
32
- root?: string;
33
- region?: string;
34
- }
35
- export declare function initProject(globals: GlobalOptions): Promise<void>;
36
- export {};
@@ -1,19 +0,0 @@
1
- export declare const CREATE_FAILED_PHYSICAL_ID_MARKER = "AWSCDK::CustomResourceProviderFramework::CREATE_FAILED";
2
- export declare const MISSING_PHYSICAL_ID_MARKER = "AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";
3
- export interface CloudFormationResponseOptions {
4
- readonly reason?: string;
5
- readonly noEcho?: boolean;
6
- }
7
- export interface CloudFormationEventContext {
8
- StackId: string;
9
- RequestId: string;
10
- PhysicalResourceId?: string;
11
- LogicalResourceId: string;
12
- ResponseURL: string;
13
- Data?: any;
14
- }
15
- export declare function submitResponse(status: "SUCCESS" | "FAILED", event: CloudFormationEventContext, options?: CloudFormationResponseOptions): Promise<void>;
16
- export declare const includeStackTraces = true;
17
- export declare function safeHandler(block: (event: any) => Promise<void>): (event: any) => Promise<void>;
18
- export declare class Retry extends Error {
19
- }
@@ -1,77 +0,0 @@
1
- /* eslint-disable max-len */
2
- /* eslint-disable no-console */
3
- import url from "url";
4
- import { httpRequest } from "./outbound.js";
5
- import { log } from "./util.js";
6
- export const CREATE_FAILED_PHYSICAL_ID_MARKER = "AWSCDK::CustomResourceProviderFramework::CREATE_FAILED";
7
- export const MISSING_PHYSICAL_ID_MARKER = "AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";
8
- export async function submitResponse(status, event, options = {}) {
9
- const json = {
10
- Status: status,
11
- Reason: options.reason || status,
12
- StackId: event.StackId,
13
- RequestId: event.RequestId,
14
- PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER,
15
- LogicalResourceId: event.LogicalResourceId,
16
- NoEcho: options.noEcho,
17
- Data: event.Data,
18
- };
19
- log("submit response to cloudformation", json);
20
- const responseBody = JSON.stringify(json);
21
- const parsedUrl = url.parse(event.ResponseURL);
22
- await httpRequest({
23
- hostname: parsedUrl.hostname,
24
- path: parsedUrl.path,
25
- method: "PUT",
26
- headers: {
27
- "content-type": "",
28
- "content-length": responseBody.length,
29
- },
30
- }, responseBody);
31
- }
32
- export const includeStackTraces = true; // for unit tests
33
- export function safeHandler(block) {
34
- return async (event) => {
35
- // ignore DELETE event when the physical resource ID is the marker that
36
- // indicates that this DELETE is a subsequent DELETE to a failed CREATE
37
- // operation.
38
- if (event.RequestType === "Delete" &&
39
- event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) {
40
- log("ignoring DELETE event caused by a failed CREATE event");
41
- await submitResponse("SUCCESS", event);
42
- return;
43
- }
44
- try {
45
- await block(event);
46
- }
47
- catch (e) {
48
- // tell waiter state machine to retry
49
- if (e instanceof Retry) {
50
- log("retry requested by handler");
51
- throw e;
52
- }
53
- if (!event.PhysicalResourceId) {
54
- // special case: if CREATE fails, which usually implies, we usually don't
55
- // have a physical resource id. in this case, the subsequent DELETE
56
- // operation does not have any meaning, and will likely fail as well. to
57
- // address this, we use a marker so the provider framework can simply
58
- // ignore the subsequent DELETE.
59
- if (event.RequestType === "Create") {
60
- log("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored");
61
- event.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER;
62
- }
63
- else {
64
- // otherwise, if PhysicalResourceId is not specified, something is
65
- // terribly wrong because all other events should have an ID.
66
- log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`);
67
- }
68
- }
69
- // this is an actual error, fail the activity altogether and exist.
70
- await submitResponse("FAILED", event, {
71
- reason: includeStackTraces ? e.stack : e.message,
72
- });
73
- }
74
- };
75
- }
76
- export class Retry extends Error {
77
- }
@@ -1 +0,0 @@
1
- export declare const handler: (event: any) => Promise<void>;
@@ -1,78 +0,0 @@
1
- import * as cfnResponse from "./cfn-response.js";
2
- import { invokeFunction } from "./outbound.js";
3
- import { log } from "./util.js";
4
- export const handler = cfnResponse.safeHandler(async (cfnRequest) => {
5
- log("onEventHandler", cfnRequest);
6
- // Invoke user function on Create and on Update
7
- const fnCreate = cfnRequest.ResourceProperties.UserCreateFunction;
8
- const fnUpdate = cfnRequest.ResourceProperties.UserUpdateFunction;
9
- const fnDelete = cfnRequest.ResourceProperties.UserDeleteFunction;
10
- const fnParams = JSON.parse(cfnRequest.ResourceProperties.UserParams);
11
- if (cfnRequest.RequestType === "Create" && fnCreate) {
12
- await invokeUserFunction(fnCreate, { params: fnParams });
13
- }
14
- else if (cfnRequest.RequestType === "Update" && fnUpdate) {
15
- await invokeUserFunction(fnUpdate, { params: fnParams });
16
- }
17
- else if (cfnRequest.RequestType === "Delete" && fnDelete) {
18
- await invokeUserFunction(fnDelete, { params: fnParams });
19
- }
20
- // Build response
21
- return cfnResponse.submitResponse("SUCCESS", {
22
- ...cfnRequest,
23
- PhysicalResourceId: defaultPhysicalResourceId(cfnRequest),
24
- });
25
- });
26
- async function invokeUserFunction(functionName, payload) {
27
- log(`executing user function ${functionName} with payload`, payload);
28
- const resp = await invokeFunction({
29
- FunctionName: functionName,
30
- Payload: JSON.stringify(payload),
31
- });
32
- log("user function response:", resp, typeof resp);
33
- if (resp.FunctionError) {
34
- log("user function threw an error:", resp.FunctionError);
35
- const jsonPayload = parseJsonPayload(resp.Payload);
36
- // Note: custom resources have a response limit of 4k. Limit the
37
- // error message to 1000 characters.
38
- const errorMessage = (jsonPayload.errorMessage || "error").substring(0, 1000);
39
- // append a reference to the log group.
40
- const message = [
41
- errorMessage,
42
- "",
43
- `Logs: /aws/lambda/${functionName}`,
44
- "",
45
- ].join("\n");
46
- const e = new Error(message);
47
- // the output that goes to CFN is what's in `stack`, not the error message.
48
- // if we have a remote trace, construct a nice message with log group information
49
- if (jsonPayload.trace) {
50
- // skip first trace line because it's the message
51
- e.stack = [message, ...jsonPayload.trace.slice(1)].join("\n");
52
- }
53
- throw e;
54
- }
55
- }
56
- function parseJsonPayload(payload) {
57
- if (!payload) {
58
- return {};
59
- }
60
- const text = payload.toString();
61
- try {
62
- return JSON.parse(text);
63
- }
64
- catch (e) {
65
- throw new Error(`return values from user-handlers must be JSON objects. got: "${text}"`);
66
- }
67
- }
68
- function defaultPhysicalResourceId(req) {
69
- switch (req.RequestType) {
70
- case "Create":
71
- return req.RequestId;
72
- case "Update":
73
- case "Delete":
74
- return req.PhysicalResourceId;
75
- default:
76
- throw new Error(`Invalid "RequestType" in request "${JSON.stringify(req)}"`);
77
- }
78
- }
@@ -1,10 +0,0 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import * as https from "https";
3
- import type { StepFunctions, Lambda } from "aws-sdk";
4
- declare function defaultHttpRequest(options: https.RequestOptions, responseBody: string): Promise<unknown>;
5
- declare function defaultStartExecution(req: StepFunctions.StartExecutionInput): Promise<StepFunctions.StartExecutionOutput>;
6
- declare function defaultInvokeFunction(req: Lambda.InvocationRequest): Promise<Lambda.InvocationResponse>;
7
- export declare const startExecution: typeof defaultStartExecution;
8
- export declare const invokeFunction: typeof defaultInvokeFunction;
9
- export declare const httpRequest: typeof defaultHttpRequest;
10
- export {};
@@ -1,42 +0,0 @@
1
- /* istanbul ignore file */
2
- import * as https from "https";
3
- import { createRequire } from "module";
4
- const require = createRequire(import.meta.url);
5
- const AWS = require("aws-sdk");
6
- const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes
7
- // In order to honor the overall maximum timeout set for the target process,
8
- // the default 2 minutes from AWS SDK has to be overriden:
9
- // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property
10
- const awsSdkConfig = {
11
- httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT },
12
- };
13
- async function defaultHttpRequest(options, responseBody) {
14
- return new Promise((resolve, reject) => {
15
- try {
16
- const request = https.request(options, resolve);
17
- request.on("error", reject);
18
- request.write(responseBody);
19
- request.end();
20
- }
21
- catch (e) {
22
- reject(e);
23
- }
24
- });
25
- }
26
- let sfn;
27
- let lambda;
28
- async function defaultStartExecution(req) {
29
- if (!sfn) {
30
- sfn = new AWS.StepFunctions(awsSdkConfig);
31
- }
32
- return sfn.startExecution(req).promise();
33
- }
34
- async function defaultInvokeFunction(req) {
35
- if (!lambda) {
36
- lambda = new AWS.Lambda(awsSdkConfig);
37
- }
38
- return lambda.invoke(req).promise();
39
- }
40
- export const startExecution = defaultStartExecution;
41
- export const invokeFunction = defaultInvokeFunction;
42
- export const httpRequest = defaultHttpRequest;
@@ -1,2 +0,0 @@
1
- export declare function getEnv(name: string): string;
2
- export declare function log(title: any, ...args: any[]): void;
@@ -1,11 +0,0 @@
1
- /* eslint-disable no-console */
2
- export function getEnv(name) {
3
- const value = process.env[name];
4
- if (!value) {
5
- throw new Error(`The environment variable "${name}" is not defined`);
6
- }
7
- return value;
8
- }
9
- export function log(title, ...args) {
10
- console.log("[provider-framework]", title, ...args.map((x) => typeof x === "object" ? JSON.stringify(x, undefined, 2) : x));
11
- }
@@ -1,116 +0,0 @@
1
- /**
2
- * Based on https://github.com/aws/aws-cdk/blob/master/packages/cdk-assets/lib/private/archive.ts
3
- */
4
- "use strict";
5
-
6
- process.on("unhandledRejection", (err) => {
7
- throw err;
8
- });
9
-
10
- const path = require("path");
11
- const fs = require("fs/promises");
12
- const fsSync = require("fs")
13
- const archiver = require("archiver");
14
- const glob = require("glob");
15
-
16
- // Parse arguments
17
- const argv = process.argv.slice(2);
18
- const SITE_PATH = argv[0];
19
- const ZIP_PATH = argv[1];
20
- const FILE_SIZE_LIMIT_IN_MB = argv[2];
21
- const FILE_SIZE_LIMIT_IN_BYTES = FILE_SIZE_LIMIT_IN_MB * 1024 * 1024;
22
-
23
- // Get files
24
- // The below options are needed to support following symlinks when building zip files:
25
- // - nodir: This will prevent symlinks themselves from being copied into the zip.
26
- // - follow: This will follow symlinks and copy the files within.
27
- const globOptions = {
28
- dot: true,
29
- nodir: true,
30
- follow: true,
31
- cwd: SITE_PATH,
32
- };
33
- const files = glob.sync("**", globOptions); // The output here is already sorted
34
-
35
- generateZips().catch(() => {
36
- process.exit(1);
37
- });
38
-
39
- function generateZips() {
40
- // eslint-disable-next-line no-async-promise-executor
41
- return new Promise(async (ok, fail) => {
42
- let output;
43
- let archive;
44
- let totalSize;
45
- const statuses = [];
46
-
47
- async function openZip() {
48
- const partId = statuses.length;
49
- const filePath = path.join(ZIP_PATH, `part${partId}.zip`);
50
- await fs.mkdir(path.dirname(filePath), {
51
- recursive: true
52
- })
53
- output = fsSync.createWriteStream(filePath);
54
- archive = archiver("zip");
55
- totalSize = 0, "w";
56
- statuses.push({
57
- output,
58
- archive,
59
- isOutputClosed: false,
60
- });
61
-
62
- archive.on("warning", fail);
63
- archive.on("error", fail);
64
- // archive has been finalized and the output file descriptor has closed, resolve promise
65
- // this has to be done before calling `finalize` since the events may fire immediately after.
66
- // see https://www.npmjs.com/package/archiver
67
- output.once("close", () => {
68
- statuses[partId].isOutputClosed = true;
69
- if (statuses.every(({ isOutputClosed }) => isOutputClosed)) {
70
- ok();
71
- }
72
- });
73
- archive.pipe(output);
74
- }
75
-
76
- // Create the first zip file
77
- await openZip();
78
-
79
- // Append files serially to ensure file order
80
- for (const file of files) {
81
- const fullPath = path.join(SITE_PATH, file);
82
- const [data, stat] = await Promise.all([
83
- fs.readFile(fullPath),
84
- fs.stat(fullPath),
85
- ]);
86
-
87
- // Validate single file size cannot be greater than filesize limit
88
- const filesize = stat.size;
89
- if (filesize > FILE_SIZE_LIMIT_IN_BYTES) {
90
- throw new Error(
91
- `Cannot package file "${fullPath}". The file is larger than ${FILE_SIZE_LIMIT_IN_MB}MB.`
92
- );
93
- }
94
-
95
- // Create a new zip file if current filesize exceeds
96
- if (totalSize + filesize > FILE_SIZE_LIMIT_IN_BYTES) {
97
- await archive.finalize();
98
- openZip();
99
- }
100
-
101
- archive.append(data, {
102
- name: file,
103
- date: new Date("1980-01-01T00:00:00.000Z"), // reset dates to get the same hash for the same content
104
- mode: stat.mode,
105
- });
106
-
107
- totalSize += filesize;
108
- }
109
-
110
- await archive.finalize();
111
-
112
- // Create a filenames file
113
- const filenamesPath = path.join(ZIP_PATH, `filenames`);
114
- await fs.writeFile(filenamesPath, files.join("\n"));
115
- });
116
- }