@remotion/lambda-client 4.0.364 → 4.0.366
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/dist/cjs/index.js +1 -1
- package/dist/esm/index.mjs +1 -1
- package/package.json +4 -4
- package/.turbo/turbo-formatting.log +0 -4
- package/.turbo/turbo-lint.log +0 -25
- package/.turbo/turbo-make.log +0 -3
- package/bundle.ts +0 -20
- package/dist/cjs/test/concurrency-payload.test.d.ts +0 -1
- package/dist/cjs/test/encode-aws-url.test.d.ts +0 -1
- package/dist/cjs/test/price-calculation.test.d.ts +0 -1
- package/dist/cjs/test/pricing.test.d.ts +0 -1
- package/dist/cjs/test/request-handler.test.d.ts +0 -1
- package/dist/cjs/test/validate-disk-size-in-mb.test.d.ts +0 -1
- package/dist/test/concurrency-payload.test.d.ts +0 -1
- package/dist/test/concurrency-payload.test.js +0 -119
- package/dist/test/encode-aws-url.test.d.ts +0 -1
- package/dist/test/encode-aws-url.test.js +0 -8
- package/dist/test/price-calculation.test.d.ts +0 -1
- package/dist/test/price-calculation.test.js +0 -62
- package/dist/test/pricing.test.d.ts +0 -1
- package/dist/test/pricing.test.js +0 -27
- package/dist/test/request-handler.test.d.ts +0 -1
- package/dist/test/request-handler.test.js +0 -36
- package/dist/test/validate-disk-size-in-mb.test.d.ts +0 -1
- package/dist/test/validate-disk-size-in-mb.test.js +0 -14
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/eslint.config.mjs +0 -5
- package/src/app-router-webhook.ts +0 -73
- package/src/apply-lifecycle.ts +0 -30
- package/src/aws-clients.ts +0 -75
- package/src/aws-provider.ts +0 -139
- package/src/bucket-exists.ts +0 -35
- package/src/call-lambda-async.ts +0 -43
- package/src/call-lambda-streaming.ts +0 -226
- package/src/call-lambda-sync.ts +0 -59
- package/src/check-credentials.ts +0 -51
- package/src/clean-items.ts +0 -50
- package/src/constants.ts +0 -38
- package/src/content-disposition-header.ts +0 -64
- package/src/convert-to-serve-url.ts +0 -24
- package/src/create-bucket.ts +0 -87
- package/src/delete-file.ts +0 -38
- package/src/delete-function.ts +0 -28
- package/src/delete-render.ts +0 -114
- package/src/encode-aws-url-params.ts +0 -3
- package/src/estimate-price.ts +0 -95
- package/src/express-webhook.ts +0 -57
- package/src/get-account-id.ts +0 -22
- package/src/get-aws-client.ts +0 -63
- package/src/get-aws-urls.ts +0 -85
- package/src/get-buckets.ts +0 -84
- package/src/get-compositions-on-lambda.ts +0 -111
- package/src/get-credentials.ts +0 -81
- package/src/get-env-variable.ts +0 -15
- package/src/get-function-name.ts +0 -24
- package/src/get-function-version.ts +0 -49
- package/src/get-functions.ts +0 -114
- package/src/get-output-url-from-metadata.ts +0 -23
- package/src/get-render-progress.ts +0 -66
- package/src/get-s3-client.ts +0 -26
- package/src/get-service-client.ts +0 -195
- package/src/get-sites.ts +0 -136
- package/src/head-file.ts +0 -30
- package/src/index.ts +0 -152
- package/src/is-cli.ts +0 -7
- package/src/is-flaky-error.ts +0 -104
- package/src/is-in-lambda.ts +0 -5
- package/src/is-likely-to-have-aws-profile.ts +0 -55
- package/src/lambda-version-string.ts +0 -5
- package/src/lifecycle-rules.ts +0 -119
- package/src/lifecycle.ts +0 -44
- package/src/list-objects.ts +0 -87
- package/src/make-lambda-payload.ts +0 -328
- package/src/make-s3-url.ts +0 -13
- package/src/p-limit.ts +0 -75
- package/src/pages-router-webhook.ts +0 -68
- package/src/parse-function-name.ts +0 -24
- package/src/presign-url.ts +0 -121
- package/src/price-per-1s.ts +0 -863
- package/src/random-hash.ts +0 -10
- package/src/read-file.ts +0 -35
- package/src/regions.ts +0 -48
- package/src/render-media-on-lambda.ts +0 -227
- package/src/render-still-on-lambda.ts +0 -209
- package/src/runtime-preference.ts +0 -7
- package/src/speculate-function-name.ts +0 -60
- package/src/test/concurrency-payload.test.ts +0 -121
- package/src/test/encode-aws-url.test.ts +0 -7
- package/src/test/price-calculation.test.ts +0 -62
- package/src/test/pricing.test.ts +0 -32
- package/src/test/request-handler.test.ts +0 -42
- package/src/test/validate-disk-size-in-mb.test.ts +0 -15
- package/src/types.ts +0 -7
- package/src/validate-aws-region.ts +0 -14
- package/src/validate-bucketname.ts +0 -24
- package/src/validate-disk-size-in-mb.ts +0 -37
- package/src/validate-lambda-codec.ts +0 -28
- package/src/validate-memory-size.ts +0 -31
- package/src/validate-presign-expiration.ts +0 -46
- package/src/validate-serveurl.ts +0 -9
- package/src/validate-webhook-signature.ts +0 -42
- package/src/write-file.ts +0 -108
- package/tsconfig.json +0 -10
package/eslint.config.mjs
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
WebhookErrorPayload,
|
|
3
|
-
WebhookPayload,
|
|
4
|
-
WebhookSuccessPayload,
|
|
5
|
-
WebhookTimeoutPayload,
|
|
6
|
-
} from '@remotion/serverless-client';
|
|
7
|
-
import {validateWebhookSignature} from './validate-webhook-signature';
|
|
8
|
-
|
|
9
|
-
export type NextWebhookArgs = {
|
|
10
|
-
testing?: boolean;
|
|
11
|
-
extraHeaders?: Record<string, string>;
|
|
12
|
-
secret: string;
|
|
13
|
-
onSuccess?: (payload: WebhookSuccessPayload) => void | Promise<void>;
|
|
14
|
-
onTimeout?: (payload: WebhookTimeoutPayload) => void | Promise<void>;
|
|
15
|
-
onError?: (payload: WebhookErrorPayload) => void | Promise<void>;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const appRouterWebhook = (
|
|
19
|
-
options: NextWebhookArgs,
|
|
20
|
-
): ((req: Request) => Promise<Response>) => {
|
|
21
|
-
const {testing, extraHeaders, secret, onSuccess, onTimeout, onError} =
|
|
22
|
-
options;
|
|
23
|
-
return async function (req: Request): Promise<Response> {
|
|
24
|
-
let headers = extraHeaders || {};
|
|
25
|
-
|
|
26
|
-
if (testing) {
|
|
27
|
-
const testingheaders = {
|
|
28
|
-
'Access-Control-Allow-Origin': 'https://www.remotion.dev',
|
|
29
|
-
'Access-Control-Allow-Headers':
|
|
30
|
-
'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, X-Remotion-Status, X-Remotion-Signature, X-Remotion-Mode',
|
|
31
|
-
'Access-Control-Allow-Methods': 'OPTIONS,POST',
|
|
32
|
-
};
|
|
33
|
-
headers = {...headers, ...testingheaders};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (req.method === 'OPTIONS') {
|
|
37
|
-
// do we have any use of the OPTIONS method other than the tester on webhooks page ? if so we can add a condition here to only return this if testing mode enabled
|
|
38
|
-
return new Response(null, {
|
|
39
|
-
headers,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Parse the body properly
|
|
44
|
-
const body = await req.json();
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
validateWebhookSignature({
|
|
48
|
-
secret,
|
|
49
|
-
body,
|
|
50
|
-
signatureHeader: req.headers.get('X-Remotion-Signature') as string,
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const payload = body as WebhookPayload;
|
|
54
|
-
if (payload.type === 'success' && onSuccess) {
|
|
55
|
-
await onSuccess(payload);
|
|
56
|
-
} else if (payload.type === 'timeout' && onTimeout) {
|
|
57
|
-
await onTimeout(payload);
|
|
58
|
-
} else if (payload.type === 'error' && onError) {
|
|
59
|
-
await onError(payload);
|
|
60
|
-
}
|
|
61
|
-
} catch (err) {
|
|
62
|
-
return new Response(
|
|
63
|
-
JSON.stringify({
|
|
64
|
-
success: false,
|
|
65
|
-
error: err instanceof Error ? err.message : String(err),
|
|
66
|
-
}),
|
|
67
|
-
{status: 500, headers},
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return new Response(JSON.stringify({success: true}), {headers});
|
|
72
|
-
};
|
|
73
|
-
};
|
package/src/apply-lifecycle.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
DeleteBucketLifecycleCommandInput,
|
|
3
|
-
LifecycleRule,
|
|
4
|
-
PutBucketLifecycleConfigurationCommandInput,
|
|
5
|
-
} from '@aws-sdk/client-s3';
|
|
6
|
-
|
|
7
|
-
export const deleteLifeCycleInput = ({
|
|
8
|
-
bucketName,
|
|
9
|
-
}: {
|
|
10
|
-
bucketName: string;
|
|
11
|
-
}): DeleteBucketLifecycleCommandInput => {
|
|
12
|
-
return {
|
|
13
|
-
Bucket: bucketName,
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const createLifeCycleInput = ({
|
|
18
|
-
bucketName,
|
|
19
|
-
lcRules,
|
|
20
|
-
}: {
|
|
21
|
-
bucketName: string;
|
|
22
|
-
lcRules: LifecycleRule[];
|
|
23
|
-
}): PutBucketLifecycleConfigurationCommandInput => {
|
|
24
|
-
return {
|
|
25
|
-
Bucket: bucketName,
|
|
26
|
-
LifecycleConfiguration: {
|
|
27
|
-
Rules: lcRules,
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
};
|
package/src/aws-clients.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type {CloudWatchLogsClient} from '@aws-sdk/client-cloudwatch-logs';
|
|
2
|
-
import type {IAMClient} from '@aws-sdk/client-iam';
|
|
3
|
-
import type {LambdaClient} from '@aws-sdk/client-lambda';
|
|
4
|
-
import type {ServiceQuotasClient} from '@aws-sdk/client-service-quotas';
|
|
5
|
-
import type {STSClient} from '@aws-sdk/client-sts';
|
|
6
|
-
import {getServiceClient} from './get-service-client';
|
|
7
|
-
import type {AwsRegion} from './regions';
|
|
8
|
-
import type {RequestHandler} from './types';
|
|
9
|
-
|
|
10
|
-
export const getCloudWatchLogsClient = (
|
|
11
|
-
region: AwsRegion,
|
|
12
|
-
requestHandler: RequestHandler | null,
|
|
13
|
-
): CloudWatchLogsClient => {
|
|
14
|
-
return getServiceClient({
|
|
15
|
-
region,
|
|
16
|
-
service: 'cloudwatch',
|
|
17
|
-
customCredentials: null,
|
|
18
|
-
forcePathStyle: false,
|
|
19
|
-
requestHandler,
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const getLambdaClient = (
|
|
24
|
-
region: AwsRegion,
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
26
|
-
_timeoutInTest: number | undefined,
|
|
27
|
-
requestHandler: RequestHandler | null,
|
|
28
|
-
): LambdaClient => {
|
|
29
|
-
return getServiceClient({
|
|
30
|
-
region,
|
|
31
|
-
service: 'lambda',
|
|
32
|
-
customCredentials: null,
|
|
33
|
-
forcePathStyle: false,
|
|
34
|
-
requestHandler,
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export const getIamClient = (
|
|
39
|
-
region: AwsRegion,
|
|
40
|
-
requestHandler: RequestHandler | null,
|
|
41
|
-
): IAMClient => {
|
|
42
|
-
return getServiceClient({
|
|
43
|
-
region,
|
|
44
|
-
service: 'iam',
|
|
45
|
-
customCredentials: null,
|
|
46
|
-
forcePathStyle: false,
|
|
47
|
-
requestHandler,
|
|
48
|
-
});
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export const getServiceQuotasClient = (
|
|
52
|
-
region: AwsRegion,
|
|
53
|
-
requestHandler: RequestHandler | null,
|
|
54
|
-
): ServiceQuotasClient => {
|
|
55
|
-
return getServiceClient({
|
|
56
|
-
region,
|
|
57
|
-
service: 'servicequotas',
|
|
58
|
-
customCredentials: null,
|
|
59
|
-
forcePathStyle: false,
|
|
60
|
-
requestHandler,
|
|
61
|
-
});
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export const getStsClient = (
|
|
65
|
-
region: AwsRegion,
|
|
66
|
-
requestHandler: RequestHandler | null,
|
|
67
|
-
): STSClient => {
|
|
68
|
-
return getServiceClient({
|
|
69
|
-
region,
|
|
70
|
-
service: 'sts',
|
|
71
|
-
customCredentials: null,
|
|
72
|
-
forcePathStyle: false,
|
|
73
|
-
requestHandler,
|
|
74
|
-
});
|
|
75
|
-
};
|
package/src/aws-provider.ts
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import type {AwsRegion} from './regions';
|
|
2
|
-
|
|
3
|
-
export type AwsProvider = {
|
|
4
|
-
type: 'aws';
|
|
5
|
-
region: AwsRegion;
|
|
6
|
-
receivedArtifactType: {
|
|
7
|
-
s3Key: string;
|
|
8
|
-
s3Url: string;
|
|
9
|
-
};
|
|
10
|
-
creationFunctionOptions: {
|
|
11
|
-
createCloudWatchLogGroup: boolean;
|
|
12
|
-
accountId: string;
|
|
13
|
-
alreadyCreated: boolean;
|
|
14
|
-
retentionInDays: number;
|
|
15
|
-
customRoleArn: string;
|
|
16
|
-
enableLambdaInsights: boolean;
|
|
17
|
-
vpcSubnetIds: string;
|
|
18
|
-
vpcSecurityGroupIds: string;
|
|
19
|
-
runtimePreference: RuntimePreference;
|
|
20
|
-
};
|
|
21
|
-
storageClass: StorageClass;
|
|
22
|
-
requestHandler: RequestHandler | null | undefined;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
import type {StorageClass} from '@aws-sdk/client-s3';
|
|
26
|
-
import type {ProviderSpecifics} from '@remotion/serverless-client';
|
|
27
|
-
import {expiryDays} from '@remotion/serverless-client';
|
|
28
|
-
import {EventEmitter} from 'node:events';
|
|
29
|
-
import {bucketExistsInRegionImplementation} from './bucket-exists';
|
|
30
|
-
import {callFunctionAsyncImplementation} from './call-lambda-async';
|
|
31
|
-
import {callFunctionWithStreamingImplementation} from './call-lambda-streaming';
|
|
32
|
-
import {callFunctionSyncImplementation} from './call-lambda-sync';
|
|
33
|
-
import {checkCredentials} from './check-credentials';
|
|
34
|
-
import {MAX_EPHEMERAL_STORAGE_IN_MB, REMOTION_BUCKET_PREFIX} from './constants';
|
|
35
|
-
import {convertToServeUrlImplementation} from './convert-to-serve-url';
|
|
36
|
-
import {createBucket} from './create-bucket';
|
|
37
|
-
import {lambdaDeleteFileImplementation} from './delete-file';
|
|
38
|
-
import {deleteFunction} from './delete-function';
|
|
39
|
-
import {estimatePrice} from './estimate-price';
|
|
40
|
-
import {getAccountIdImplementation} from './get-account-id';
|
|
41
|
-
import {getCloudwatchMethodUrl, getCloudwatchRendererUrl} from './get-aws-urls';
|
|
42
|
-
import {getRemotionBuckets} from './get-buckets';
|
|
43
|
-
import {getFunctions} from './get-functions';
|
|
44
|
-
import {getOutputUrlFromMetadata} from './get-output-url-from-metadata';
|
|
45
|
-
import {lambdaHeadFileImplementation} from './head-file';
|
|
46
|
-
import {isFlakyError} from './is-flaky-error';
|
|
47
|
-
import {applyLifeCyleOperation} from './lifecycle-rules';
|
|
48
|
-
import {lambdaLsImplementation} from './list-objects';
|
|
49
|
-
import {parseFunctionName} from './parse-function-name';
|
|
50
|
-
import {randomHashImplementation} from './random-hash';
|
|
51
|
-
import {lambdaReadFileImplementation} from './read-file';
|
|
52
|
-
import type {RuntimePreference} from './runtime-preference';
|
|
53
|
-
import type {RequestHandler} from './types';
|
|
54
|
-
import {lambdaWriteFileImplementation} from './write-file';
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
/^AWS_Lambda_nodejs(?:18|20)[.]x$/.test(
|
|
58
|
-
process.env.AWS_EXECUTION_ENV ?? '',
|
|
59
|
-
) === true
|
|
60
|
-
) {
|
|
61
|
-
process.env.FONTCONFIG_PATH = '/opt';
|
|
62
|
-
process.env.FONTCONFIG_FILE = '/opt/fonts.conf';
|
|
63
|
-
|
|
64
|
-
process.env.DISABLE_FROM_SURFACE = '1';
|
|
65
|
-
process.env.NO_COLOR = '1';
|
|
66
|
-
|
|
67
|
-
// @ts-expect-error
|
|
68
|
-
globalThis._dumpUnreleasedBuffers = new EventEmitter();
|
|
69
|
-
|
|
70
|
-
// @ts-expect-error
|
|
71
|
-
(globalThis._dumpUnreleasedBuffers as EventEmitter).setMaxListeners(201);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const validateDeleteAfter = (lifeCycleValue: unknown) => {
|
|
75
|
-
if (lifeCycleValue === null) {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (lifeCycleValue === undefined) {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (typeof lifeCycleValue !== 'string') {
|
|
84
|
-
throw new TypeError(
|
|
85
|
-
`Expected life cycle value to be a string, got ${JSON.stringify(
|
|
86
|
-
lifeCycleValue,
|
|
87
|
-
)}`,
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (!(lifeCycleValue in expiryDays)) {
|
|
92
|
-
throw new TypeError(
|
|
93
|
-
`Expected deleteAfter value to be one of ${Object.keys(expiryDays).join(
|
|
94
|
-
', ',
|
|
95
|
-
)}, got ${lifeCycleValue}`,
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export const awsImplementation: ProviderSpecifics<AwsProvider> = {
|
|
101
|
-
getChromiumPath() {
|
|
102
|
-
return '/opt/bin/chromium';
|
|
103
|
-
},
|
|
104
|
-
getBuckets: getRemotionBuckets,
|
|
105
|
-
createBucket,
|
|
106
|
-
applyLifeCycle: applyLifeCyleOperation,
|
|
107
|
-
listObjects: lambdaLsImplementation,
|
|
108
|
-
deleteFile: lambdaDeleteFileImplementation,
|
|
109
|
-
bucketExists: bucketExistsInRegionImplementation,
|
|
110
|
-
randomHash: randomHashImplementation,
|
|
111
|
-
readFile: lambdaReadFileImplementation,
|
|
112
|
-
writeFile: lambdaWriteFileImplementation,
|
|
113
|
-
headFile: lambdaHeadFileImplementation,
|
|
114
|
-
convertToServeUrl: convertToServeUrlImplementation,
|
|
115
|
-
printLoggingHelper: true,
|
|
116
|
-
validateDeleteAfter,
|
|
117
|
-
callFunctionAsync: callFunctionAsyncImplementation,
|
|
118
|
-
callFunctionStreaming: callFunctionWithStreamingImplementation,
|
|
119
|
-
callFunctionSync: callFunctionSyncImplementation,
|
|
120
|
-
getEphemeralStorageForPriceCalculation() {
|
|
121
|
-
// We cannot determine the ephemeral storage size, so we
|
|
122
|
-
// overestimate the price, but will only have a miniscule effect (~0.2%)
|
|
123
|
-
return MAX_EPHEMERAL_STORAGE_IN_MB;
|
|
124
|
-
},
|
|
125
|
-
estimatePrice,
|
|
126
|
-
getLoggingUrlForMethod: getCloudwatchMethodUrl,
|
|
127
|
-
getLoggingUrlForRendererFunction: getCloudwatchRendererUrl,
|
|
128
|
-
isFlakyError,
|
|
129
|
-
getOutputUrl: getOutputUrlFromMetadata,
|
|
130
|
-
serverStorageProductName: () => 'S3',
|
|
131
|
-
getMaxStillInlinePayloadSize: () => 5_000_000,
|
|
132
|
-
getMaxNonInlinePayloadSizePerFunction: () => 200_000,
|
|
133
|
-
getAccountId: getAccountIdImplementation,
|
|
134
|
-
deleteFunction,
|
|
135
|
-
getFunctions,
|
|
136
|
-
parseFunctionName,
|
|
137
|
-
checkCredentials,
|
|
138
|
-
getBucketPrefix: () => REMOTION_BUCKET_PREFIX,
|
|
139
|
-
};
|
package/src/bucket-exists.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import {GetBucketLocationCommand} from '@aws-sdk/client-s3';
|
|
2
|
-
import type {ProviderSpecifics} from '@remotion/serverless-client';
|
|
3
|
-
import type {AwsProvider} from './aws-provider';
|
|
4
|
-
import {getS3Client} from './get-s3-client';
|
|
5
|
-
|
|
6
|
-
export const bucketExistsInRegionImplementation: ProviderSpecifics<AwsProvider>['bucketExists'] =
|
|
7
|
-
async ({
|
|
8
|
-
bucketName,
|
|
9
|
-
region,
|
|
10
|
-
expectedBucketOwner,
|
|
11
|
-
forcePathStyle,
|
|
12
|
-
requestHandler,
|
|
13
|
-
}) => {
|
|
14
|
-
try {
|
|
15
|
-
const bucket = await getS3Client({
|
|
16
|
-
region,
|
|
17
|
-
customCredentials: null,
|
|
18
|
-
forcePathStyle,
|
|
19
|
-
requestHandler,
|
|
20
|
-
}).send(
|
|
21
|
-
new GetBucketLocationCommand({
|
|
22
|
-
Bucket: bucketName,
|
|
23
|
-
ExpectedBucketOwner: expectedBucketOwner ?? undefined,
|
|
24
|
-
}),
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
return (bucket.LocationConstraint ?? 'us-east-1') === region;
|
|
28
|
-
} catch (err) {
|
|
29
|
-
if ((err as {Code: string}).Code === 'NoSuchBucket') {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
throw err;
|
|
34
|
-
}
|
|
35
|
-
};
|
package/src/call-lambda-async.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import {InvokeCommand} from '@aws-sdk/client-lambda';
|
|
2
|
-
import type {
|
|
3
|
-
CallFunctionOptions,
|
|
4
|
-
CloudProvider,
|
|
5
|
-
ServerlessRoutines,
|
|
6
|
-
} from '@remotion/serverless-client';
|
|
7
|
-
import {getLambdaClient} from './aws-clients';
|
|
8
|
-
import type {AwsRegion} from './regions';
|
|
9
|
-
|
|
10
|
-
export const callFunctionAsyncImplementation = async <
|
|
11
|
-
T extends ServerlessRoutines,
|
|
12
|
-
Provider extends CloudProvider,
|
|
13
|
-
>({
|
|
14
|
-
functionName,
|
|
15
|
-
payload,
|
|
16
|
-
region,
|
|
17
|
-
timeoutInTest,
|
|
18
|
-
}: CallFunctionOptions<T, Provider>): Promise<void> => {
|
|
19
|
-
const stringifiedPayload = JSON.stringify(payload);
|
|
20
|
-
if (stringifiedPayload.length > 256 * 1024) {
|
|
21
|
-
throw new Error(
|
|
22
|
-
`Payload is too big: ${stringifiedPayload.length} bytes. Maximum size is 256 KB. This should not happen, please report this to the Remotion team. Payload: ${stringifiedPayload}`,
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const result = await getLambdaClient(
|
|
27
|
-
region as AwsRegion,
|
|
28
|
-
timeoutInTest,
|
|
29
|
-
null,
|
|
30
|
-
).send(
|
|
31
|
-
new InvokeCommand({
|
|
32
|
-
FunctionName: functionName,
|
|
33
|
-
Payload: stringifiedPayload,
|
|
34
|
-
InvocationType: 'Event',
|
|
35
|
-
}),
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
if (result.FunctionError) {
|
|
39
|
-
throw new Error(
|
|
40
|
-
`Lambda function returned error: ${result.FunctionError} ${result.LogResult}`,
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
import type {InvokeWithResponseStreamCommandOutput} from '@aws-sdk/client-lambda';
|
|
3
|
-
import {
|
|
4
|
-
InvokeWithResponseStreamCommand,
|
|
5
|
-
type InvokeWithResponseStreamResponseEvent,
|
|
6
|
-
} from '@aws-sdk/client-lambda';
|
|
7
|
-
import type {
|
|
8
|
-
CallFunctionOptions,
|
|
9
|
-
CloudProvider,
|
|
10
|
-
MessageTypeId,
|
|
11
|
-
OnMessage,
|
|
12
|
-
ServerlessRoutines,
|
|
13
|
-
StreamingMessage,
|
|
14
|
-
} from '@remotion/serverless-client';
|
|
15
|
-
import {
|
|
16
|
-
formatMap,
|
|
17
|
-
makeStreamer,
|
|
18
|
-
messageTypeIdToMessageType,
|
|
19
|
-
} from '@remotion/serverless-client';
|
|
20
|
-
import {getLambdaClient} from './aws-clients';
|
|
21
|
-
import type {AwsRegion} from './regions';
|
|
22
|
-
|
|
23
|
-
const STREAM_STALL_TIMEOUT = 30000;
|
|
24
|
-
const LAMBDA_STREAM_STALL = `AWS did not invoke Lambda in ${STREAM_STALL_TIMEOUT}ms`;
|
|
25
|
-
|
|
26
|
-
export const parseJsonOrThrowSource = (data: Uint8Array, type: string) => {
|
|
27
|
-
const asString = new TextDecoder('utf-8').decode(data);
|
|
28
|
-
try {
|
|
29
|
-
return JSON.parse(asString);
|
|
30
|
-
} catch {
|
|
31
|
-
throw new Error(`Invalid JSON (${type}): ${asString}`);
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const invokeStreamOrTimeout = async <Provider extends CloudProvider>({
|
|
36
|
-
region,
|
|
37
|
-
timeoutInTest,
|
|
38
|
-
functionName,
|
|
39
|
-
type,
|
|
40
|
-
payload,
|
|
41
|
-
}: {
|
|
42
|
-
region: Provider['region'];
|
|
43
|
-
timeoutInTest: number;
|
|
44
|
-
functionName: string;
|
|
45
|
-
type: string;
|
|
46
|
-
payload: Record<string, unknown>;
|
|
47
|
-
}) => {
|
|
48
|
-
const resProm = getLambdaClient(
|
|
49
|
-
region as AwsRegion,
|
|
50
|
-
timeoutInTest,
|
|
51
|
-
null,
|
|
52
|
-
).send(
|
|
53
|
-
new InvokeWithResponseStreamCommand({
|
|
54
|
-
FunctionName: functionName,
|
|
55
|
-
Payload: JSON.stringify({type, ...payload}),
|
|
56
|
-
}),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
let cleanup = () => undefined;
|
|
60
|
-
|
|
61
|
-
const timeout = new Promise<InvokeWithResponseStreamCommandOutput>(
|
|
62
|
-
(_resolve, reject) => {
|
|
63
|
-
const int = setTimeout(() => {
|
|
64
|
-
reject(new Error(LAMBDA_STREAM_STALL));
|
|
65
|
-
}, STREAM_STALL_TIMEOUT);
|
|
66
|
-
cleanup = () => {
|
|
67
|
-
clearTimeout(int);
|
|
68
|
-
};
|
|
69
|
-
},
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
const res = await Promise.race([resProm, timeout]);
|
|
73
|
-
|
|
74
|
-
cleanup();
|
|
75
|
-
|
|
76
|
-
return res;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const INVALID_JSON_MESSAGE = 'Cannot parse Lambda response as JSON';
|
|
80
|
-
|
|
81
|
-
const callLambdaWithStreamingWithoutRetry = async <
|
|
82
|
-
T extends ServerlessRoutines,
|
|
83
|
-
Provider extends CloudProvider,
|
|
84
|
-
>({
|
|
85
|
-
functionName,
|
|
86
|
-
type,
|
|
87
|
-
payload,
|
|
88
|
-
region,
|
|
89
|
-
timeoutInTest,
|
|
90
|
-
receivedStreamingPayload,
|
|
91
|
-
}: CallFunctionOptions<T, Provider> & {
|
|
92
|
-
receivedStreamingPayload: OnMessage<Provider>;
|
|
93
|
-
}): Promise<void> => {
|
|
94
|
-
const res = await invokeStreamOrTimeout({
|
|
95
|
-
functionName,
|
|
96
|
-
payload,
|
|
97
|
-
region,
|
|
98
|
-
timeoutInTest,
|
|
99
|
-
type,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
const {onData, clear} = makeStreamer((status, messageTypeId, data) => {
|
|
103
|
-
const messageType = messageTypeIdToMessageType(
|
|
104
|
-
messageTypeId as MessageTypeId,
|
|
105
|
-
);
|
|
106
|
-
const innerPayload =
|
|
107
|
-
formatMap[messageType] === 'json'
|
|
108
|
-
? parseJsonOrThrowSource(data, messageType)
|
|
109
|
-
: data;
|
|
110
|
-
|
|
111
|
-
const message: StreamingMessage<Provider> = {
|
|
112
|
-
successType: status,
|
|
113
|
-
message: {
|
|
114
|
-
type: messageType,
|
|
115
|
-
payload: innerPayload,
|
|
116
|
-
},
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
receivedStreamingPayload(message);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
const dumpBuffers = () => {
|
|
123
|
-
clear();
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// @ts-expect-error - We are adding a listener to a global variable
|
|
127
|
-
if (globalThis._dumpUnreleasedBuffers) {
|
|
128
|
-
// @ts-expect-error - We are adding a listener to a global variable
|
|
129
|
-
(globalThis._dumpUnreleasedBuffers as EventEmitter).addListener(
|
|
130
|
-
'dump-unreleased-buffers',
|
|
131
|
-
dumpBuffers,
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const events =
|
|
136
|
-
res.EventStream as AsyncIterable<InvokeWithResponseStreamResponseEvent>;
|
|
137
|
-
|
|
138
|
-
for await (const event of events) {
|
|
139
|
-
// There are two types of events you can get on a stream.
|
|
140
|
-
|
|
141
|
-
// `PayloadChunk`: These contain the actual raw bytes of the chunk
|
|
142
|
-
// It has a single property: `Payload`
|
|
143
|
-
if (event.PayloadChunk && event.PayloadChunk.Payload) {
|
|
144
|
-
onData(event.PayloadChunk.Payload);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (event.InvokeComplete) {
|
|
148
|
-
if (event.InvokeComplete.ErrorCode) {
|
|
149
|
-
const logs = `https://${region}.console.aws.amazon.com/cloudwatch/home?region=${region}#logsV2:logs-insights$3FqueryDetail$3D~(end~0~start~-3600~timeType~'RELATIVE~unit~'seconds~editorString~'fields*20*40timestamp*2c*20*40requestId*2c*20*40message*0a*7c*20filter*20*40requestId*20like*20*${res.$metadata.requestId}*22*0a*7c*20sort*20*40timestamp*20asc~source~(~'*2faws*2flambda*2f${functionName}))`;
|
|
150
|
-
if (event.InvokeComplete.ErrorCode === 'Unhandled') {
|
|
151
|
-
throw new Error(
|
|
152
|
-
`Lambda function ${functionName} failed with an unhandled error: ${
|
|
153
|
-
event.InvokeComplete.ErrorDetails as string
|
|
154
|
-
} See ${logs} to see the logs of this invocation.`,
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
throw new Error(
|
|
159
|
-
`Lambda function ${functionName} failed with error code ${event.InvokeComplete.ErrorCode}: ${event.InvokeComplete.ErrorDetails}. See ${logs} to see the logs of this invocation.`,
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Don't put a `break` statement here, as it will cause the socket to not properly exit.
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// @ts-expect-error - We are adding a listener to a global variable
|
|
168
|
-
if (globalThis._dumpUnreleasedBuffers) {
|
|
169
|
-
// @ts-expect-error - We are adding a listener to a global variable
|
|
170
|
-
(globalThis._dumpUnreleasedBuffers as EventEmitter).removeListener(
|
|
171
|
-
'dump-unreleased-buffers',
|
|
172
|
-
dumpBuffers,
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
clear();
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
export const callFunctionWithStreamingImplementation = async <
|
|
180
|
-
Provider extends CloudProvider,
|
|
181
|
-
T extends ServerlessRoutines,
|
|
182
|
-
>(
|
|
183
|
-
options: CallFunctionOptions<T, Provider> & {
|
|
184
|
-
receivedStreamingPayload: OnMessage<Provider>;
|
|
185
|
-
retriesRemaining: number;
|
|
186
|
-
},
|
|
187
|
-
): Promise<void> => {
|
|
188
|
-
// As of August 2023, Lambda streaming sometimes misses parts of the JSON response.
|
|
189
|
-
// Handling this for now by applying a retry mechanism.
|
|
190
|
-
|
|
191
|
-
try {
|
|
192
|
-
// Do not remove this await
|
|
193
|
-
await callLambdaWithStreamingWithoutRetry<T, Provider>(options);
|
|
194
|
-
} catch (err) {
|
|
195
|
-
if (
|
|
196
|
-
(err as Error).stack?.includes('TooManyRequestsException') ||
|
|
197
|
-
(err as Error).message?.includes('ConcurrentInvocationLimitExceeded')
|
|
198
|
-
) {
|
|
199
|
-
throw new Error(
|
|
200
|
-
`AWS Concurrency limit reached (Original Error: ${(err as Error).message}). See https://www.remotion.dev/docs/lambda/troubleshooting/rate-limit for tips to fix this.`,
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (
|
|
205
|
-
!(err as Error).message.includes(INVALID_JSON_MESSAGE) &&
|
|
206
|
-
!(err as Error).message.includes(LAMBDA_STREAM_STALL) &&
|
|
207
|
-
// https://discord.com/channels/809501355504959528/1332166561242288220/1332166561242288220
|
|
208
|
-
!(err as Error).message.includes('Runtime.TruncatedResponse') &&
|
|
209
|
-
!(err as Error).message.includes('aborted')
|
|
210
|
-
) {
|
|
211
|
-
throw err;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
console.error('Retries remaining:', options.retriesRemaining);
|
|
215
|
-
if (options.retriesRemaining === 0) {
|
|
216
|
-
console.error('Throwing error:');
|
|
217
|
-
throw err;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
console.error(err);
|
|
221
|
-
return callFunctionWithStreamingImplementation({
|
|
222
|
-
...options,
|
|
223
|
-
retriesRemaining: options.retriesRemaining - 1,
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
};
|
package/src/call-lambda-sync.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import {InvokeCommand} from '@aws-sdk/client-lambda';
|
|
2
|
-
import type {
|
|
3
|
-
CallFunctionOptions,
|
|
4
|
-
CloudProvider,
|
|
5
|
-
OrError,
|
|
6
|
-
ServerlessReturnValues,
|
|
7
|
-
ServerlessRoutines,
|
|
8
|
-
} from '@remotion/serverless-client';
|
|
9
|
-
import {getLambdaClient} from './aws-clients';
|
|
10
|
-
import type {AwsRegion} from './regions';
|
|
11
|
-
|
|
12
|
-
const callLambdaSyncWithoutRetry = async <
|
|
13
|
-
T extends ServerlessRoutines,
|
|
14
|
-
Provider extends CloudProvider,
|
|
15
|
-
>({
|
|
16
|
-
functionName,
|
|
17
|
-
payload,
|
|
18
|
-
region,
|
|
19
|
-
timeoutInTest,
|
|
20
|
-
}: CallFunctionOptions<T, Provider>): Promise<
|
|
21
|
-
OrError<ServerlessReturnValues<Provider>[T]>
|
|
22
|
-
> => {
|
|
23
|
-
const Payload = JSON.stringify(payload);
|
|
24
|
-
const res = await getLambdaClient(
|
|
25
|
-
region as AwsRegion,
|
|
26
|
-
timeoutInTest,
|
|
27
|
-
null,
|
|
28
|
-
).send(
|
|
29
|
-
new InvokeCommand({
|
|
30
|
-
FunctionName: functionName,
|
|
31
|
-
Payload,
|
|
32
|
-
InvocationType: 'RequestResponse',
|
|
33
|
-
}),
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
const decoded = new TextDecoder('utf-8').decode(res.Payload);
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
return JSON.parse(decoded) as OrError<ServerlessReturnValues<Provider>[T]>;
|
|
40
|
-
} catch {
|
|
41
|
-
throw new Error(`Invalid JSON: ${JSON.stringify(decoded)}`);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const callFunctionSyncImplementation = async <
|
|
46
|
-
Provider extends CloudProvider,
|
|
47
|
-
T extends ServerlessRoutines,
|
|
48
|
-
>(
|
|
49
|
-
options: CallFunctionOptions<T, Provider>,
|
|
50
|
-
): Promise<ServerlessReturnValues<Provider>[T]> => {
|
|
51
|
-
const res = await callLambdaSyncWithoutRetry<T, Provider>(options);
|
|
52
|
-
if (res.type === 'error') {
|
|
53
|
-
const err = new Error(res.message);
|
|
54
|
-
err.stack = res.stack;
|
|
55
|
-
throw err;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return res;
|
|
59
|
-
};
|