@hyperframes/aws-lambda 0.7.70 → 0.7.72

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/README.md CHANGED
@@ -37,7 +37,7 @@ smoke flow; the SDK + CDK are the supported public surface for adopters.
37
37
  │ pure functions over local paths
38
38
 
39
39
  ┌──────────────────────────────────────────────────────────────────┐
40
- │ S3 bucket — plan tarball + per-chunk outputs + final mp4
40
+ │ S3 bucket — v1 plan tar or v2 manifest/blobs + chunks + output
41
41
  └──────────────────────────────────────────────────────────────────┘
42
42
  ```
43
43
 
@@ -45,6 +45,26 @@ The handler downloads inputs from S3 into `/tmp`, calls the OSS primitive,
45
45
  uploads outputs back to S3, and returns a small JSON result that fits
46
46
  inside Step Functions' history budget (under 200 bytes per chunk).
47
47
 
48
+ ### Plan transport selection
49
+
50
+ `renderToLambda` defaults to the existing monolithic v1 plan transport.
51
+ Plan v2 is an explicit whole-render opt-in:
52
+
53
+ ```ts
54
+ await renderToLambda({
55
+ // ...bucket, state machine, project, and config...
56
+ planProtocol: "v2",
57
+ });
58
+ ```
59
+
60
+ V2 never overloads `PlanS3Uri`. The planner returns
61
+ `PlanV2ManifestS3Uri` and `PlanV2ArtifactS3Prefix`; chunk workers fetch
62
+ only manifest-selected chunk artifacts, while the assembler fetches its
63
+ own metadata and audio subset. Blobs are immutable SHA-256-addressed
64
+ objects, verified on upload and download, and the manifest is published
65
+ last. Unknown protocols and digest mismatches are terminal Step Functions
66
+ errors. Omit the selector—or use `"v1"`—to retain the prior wire contract.
67
+
48
68
  ## Chrome runtime
49
69
 
50
70
  The package supports two Chromium sources:
@@ -1 +1 @@
1
- {"version":3,"file":"HyperframesRenderStack.d.ts","sourceRoot":"","sources":["../../src/cdk/HyperframesRenderStack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAY,aAAa,EAAQ,MAAM,aAAa,CAAC;AAE5D,OAAO,KAAK,MAAM,MAAM,wBAAwB,CAAC;AAEjD,OAAO,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,KAAK,GAAG,MAAM,+BAA+B,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,kEAAkE;AAClE,MAAM,WAAW,2BAA2B;IAC1C,8FAA8F;IAC9F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC;IAC/E,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,YAAY,CAAC,EAAE,WAAW,GAAG,uBAAuB,CAAC;IACrD,kFAAkF;IAClF,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,aAAa,CAAC;CACrC;AAOD,qBAAa,sBAAuB,SAAQ,SAAS;IACnD,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC;IACzC,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC;gBAE5B,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,GAAE,2BAAgC;IAoHjF;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;CAoJpC"}
1
+ {"version":3,"file":"HyperframesRenderStack.d.ts","sourceRoot":"","sources":["../../src/cdk/HyperframesRenderStack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAY,aAAa,EAAQ,MAAM,aAAa,CAAC;AAE5D,OAAO,KAAK,MAAM,MAAM,wBAAwB,CAAC;AAEjD,OAAO,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,KAAK,GAAG,MAAM,+BAA+B,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,kEAAkE;AAClE,MAAM,WAAW,2BAA2B;IAC1C,8FAA8F;IAC9F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC;IAC/E,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,YAAY,CAAC,EAAE,WAAW,GAAG,uBAAuB,CAAC;IACrD,kFAAkF;IAClF,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,aAAa,CAAC;CACrC;AAOD,qBAAa,sBAAuB,SAAQ,SAAS;IACnD,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC;IACzC,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC;gBAE5B,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,GAAE,2BAAgC;IAoHjF;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;CA+RpC"}
package/dist/cdk/index.js CHANGED
@@ -132,6 +132,12 @@ var HyperframesRenderStack = class extends Construct {
132
132
  "BROWSER_GPU_NOT_SOFTWARE",
133
133
  "FONT_FETCH_FAILED",
134
134
  "PLAN_TOO_LARGE",
135
+ "PlanTooLargeError",
136
+ "PLAN_PROTOCOL_UNSUPPORTED",
137
+ "PlanProtocolUnsupportedError",
138
+ "PLAN_V2_INTEGRITY_UNRECOVERABLE",
139
+ "PlanV2IntegrityError",
140
+ "PLAN_ARTIFACT_DIGEST_MISMATCH",
135
141
  "FORMAT_NOT_SUPPORTED_IN_DISTRIBUTED",
136
142
  "ChromeBinaryUnavailableError"
137
143
  ];
@@ -140,13 +146,27 @@ var HyperframesRenderStack = class extends Construct {
140
146
  "PLAN_HASH_MISMATCH",
141
147
  "S3_URI_NOT_ALLOWED",
142
148
  "BROWSER_GPU_NOT_SOFTWARE",
149
+ "PLAN_TOO_LARGE",
150
+ "PlanTooLargeError",
151
+ "PLAN_PROTOCOL_UNSUPPORTED",
152
+ "PlanProtocolUnsupportedError",
153
+ "PLAN_V2_INTEGRITY_UNRECOVERABLE",
154
+ "PlanV2IntegrityError",
155
+ "PLAN_ARTIFACT_DIGEST_MISMATCH",
143
156
  "ChromeBinaryUnavailableError"
144
157
  ];
145
158
  const NON_RETRYABLE_ASSEMBLE = [
146
159
  "FFMPEG_VERSION_MISMATCH",
147
160
  "PLAN_HASH_MISMATCH",
148
161
  "S3_URI_NOT_ALLOWED",
162
+ "PLAN_PROTOCOL_UNSUPPORTED",
163
+ "PlanProtocolUnsupportedError",
164
+ "PLAN_V2_INTEGRITY_UNRECOVERABLE",
165
+ "PlanV2IntegrityError",
149
166
  "FORMAT_NOT_SUPPORTED_IN_DISTRIBUTED",
167
+ "PLAN_TOO_LARGE",
168
+ "PlanTooLargeError",
169
+ "PLAN_ARTIFACT_DIGEST_MISMATCH",
150
170
  "ChromeBinaryUnavailableError"
151
171
  ];
152
172
  const plan = new tasks.LambdaInvoke(this, "Plan", {
@@ -158,6 +178,7 @@ var HyperframesRenderStack = class extends Construct {
158
178
  "Config.$": "$.Config"
159
179
  }),
160
180
  resultSelector: {
181
+ PlanProtocol: "v1",
161
182
  "PlanS3Uri.$": "$.Payload.PlanS3Uri",
162
183
  "PlanHash.$": "$.Payload.PlanHash",
163
184
  "ChunkCount.$": "$.Payload.ChunkCount",
@@ -178,6 +199,34 @@ var HyperframesRenderStack = class extends Construct {
178
199
  backoffRate: 2,
179
200
  maxDelay: Duration.seconds(60)
180
201
  });
202
+ const planV2 = new tasks.LambdaInvoke(this, "PlanV2", {
203
+ lambdaFunction: this.renderFunction,
204
+ payload: sfn.TaskInput.fromObject({
205
+ Action: "plan",
206
+ PlanProtocol: "v2",
207
+ "ProjectS3Uri.$": "$.ProjectS3Uri",
208
+ "PlanOutputS3Prefix.$": "$.PlanOutputS3Prefix",
209
+ "Config.$": "$.Config"
210
+ }),
211
+ resultSelector: {
212
+ PlanProtocol: "v2",
213
+ "PlanV2ManifestS3Uri.$": "$.Payload.PlanV2ManifestS3Uri",
214
+ "PlanV2ArtifactS3Prefix.$": "$.Payload.PlanV2ArtifactS3Prefix",
215
+ "PlanHash.$": "$.Payload.PlanHash",
216
+ "ChunkCount.$": "$.Payload.ChunkCount",
217
+ "Format.$": "$.Payload.Format",
218
+ "HasAudio.$": "$.Payload.HasAudio"
219
+ },
220
+ resultPath: "$.Plan"
221
+ });
222
+ planV2.addRetry({ errors: NON_RETRYABLE_PLAN, maxAttempts: 0 });
223
+ planV2.addRetry({
224
+ errors: ["States.ALL"],
225
+ interval: Duration.seconds(2),
226
+ maxAttempts: 4,
227
+ backoffRate: 2,
228
+ maxDelay: Duration.seconds(60)
229
+ });
181
230
  const buildChunkList = new sfn.Pass(this, "BuildChunkList", {
182
231
  parameters: {
183
232
  "ChunkIndexes.$": "States.ArrayRange(0, States.MathAdd($.Plan.ChunkCount, -1), 1)"
@@ -256,8 +305,87 @@ var HyperframesRenderStack = class extends Construct {
256
305
  backoffRate: 2,
257
306
  maxDelay: Duration.seconds(60)
258
307
  });
259
- const assertChunkCount = new sfn.Choice(this, "AssertChunkCount").when(sfn.Condition.numberGreaterThan("$.Plan.ChunkCount", 0), renderChunks.next(assemble)).otherwise(planProducedZero);
260
- return plan.next(buildChunkList).next(assertChunkCount);
308
+ const renderChunkV2Task = new tasks.LambdaInvoke(this, "RenderChunkV2", {
309
+ lambdaFunction: this.renderFunction,
310
+ payload: sfn.TaskInput.fromObject({
311
+ Action: "renderChunk",
312
+ PlanProtocol: "v2",
313
+ "ChunkIndex.$": "$.ChunkIndex",
314
+ "PlanV2ManifestS3Uri.$": "$.PlanV2ManifestS3Uri",
315
+ "PlanV2ArtifactS3Prefix.$": "$.PlanV2ArtifactS3Prefix",
316
+ "PlanHash.$": "$.PlanHash",
317
+ "ChunkOutputS3Prefix.$": "$.ChunkOutputS3Prefix",
318
+ "Format.$": "$.Format"
319
+ }),
320
+ resultSelector: {
321
+ "ChunkS3Uri.$": "$.Payload.ChunkS3Uri",
322
+ "ChunkIndex.$": "$.Payload.ChunkIndex",
323
+ "Sha256.$": "$.Payload.Sha256"
324
+ }
325
+ });
326
+ renderChunkV2Task.addRetry({ errors: NON_RETRYABLE_CHUNK, maxAttempts: 0 });
327
+ renderChunkV2Task.addRetry({
328
+ errors: ["States.ALL"],
329
+ interval: Duration.seconds(2),
330
+ maxAttempts: 4,
331
+ backoffRate: 2,
332
+ maxDelay: Duration.seconds(60)
333
+ });
334
+ const renderChunksV2 = new sfn.Map(this, "RenderChunksV2", {
335
+ itemsPath: "$.Iterator.ChunkIndexes",
336
+ itemSelector: {
337
+ "ChunkIndex.$": "$$.Map.Item.Value",
338
+ "PlanV2ManifestS3Uri.$": "$.Plan.PlanV2ManifestS3Uri",
339
+ "PlanV2ArtifactS3Prefix.$": "$.Plan.PlanV2ArtifactS3Prefix",
340
+ "PlanHash.$": "$.Plan.PlanHash",
341
+ "ChunkOutputS3Prefix.$": "$.PlanOutputS3Prefix",
342
+ "Format.$": "$.Plan.Format"
343
+ },
344
+ maxConcurrencyPath: "$.Plan.ChunkCount",
345
+ resultPath: "$.Chunks"
346
+ });
347
+ renderChunksV2.itemProcessor(renderChunkV2Task);
348
+ const assembleV2 = new tasks.LambdaInvoke(this, "AssembleV2", {
349
+ lambdaFunction: this.renderFunction,
350
+ payload: sfn.TaskInput.fromObject({
351
+ Action: "assemble",
352
+ PlanProtocol: "v2",
353
+ "PlanV2ManifestS3Uri.$": "$.Plan.PlanV2ManifestS3Uri",
354
+ "PlanV2ArtifactS3Prefix.$": "$.Plan.PlanV2ArtifactS3Prefix",
355
+ "PlanHash.$": "$.Plan.PlanHash",
356
+ "ChunkS3Uris.$": "$.Chunks[*].ChunkS3Uri",
357
+ AudioS3Uri: null,
358
+ "OutputS3Uri.$": "$.OutputS3Uri",
359
+ "Format.$": "$.Plan.Format"
360
+ }),
361
+ resultSelector: {
362
+ "OutputS3Uri.$": "$.Payload.OutputS3Uri",
363
+ "FramesEncoded.$": "$.Payload.FramesEncoded",
364
+ "FileSize.$": "$.Payload.FileSize"
365
+ },
366
+ resultPath: "$.Output"
367
+ });
368
+ assembleV2.addRetry({ errors: NON_RETRYABLE_ASSEMBLE, maxAttempts: 0 });
369
+ assembleV2.addRetry({
370
+ errors: ["States.ALL"],
371
+ interval: Duration.seconds(2),
372
+ maxAttempts: 4,
373
+ backoffRate: 2,
374
+ maxDelay: Duration.seconds(60)
375
+ });
376
+ const selectWorkerProtocol = new sfn.Choice(this, "SelectWorkerProtocol").when(
377
+ sfn.Condition.stringEquals("$.Plan.PlanProtocol", "v2"),
378
+ renderChunksV2.next(assembleV2)
379
+ ).otherwise(renderChunks.next(assemble));
380
+ const assertChunkCount = new sfn.Choice(this, "AssertChunkCount").when(sfn.Condition.numberGreaterThan("$.Plan.ChunkCount", 0), selectWorkerProtocol).otherwise(planProducedZero);
381
+ plan.next(buildChunkList);
382
+ planV2.next(buildChunkList);
383
+ buildChunkList.next(assertChunkCount);
384
+ const unsupportedPlanProtocol = new sfn.Fail(this, "UnsupportedPlanProtocol", {
385
+ error: "PLAN_PROTOCOL_UNSUPPORTED",
386
+ cause: 'PlanProtocol must be "v1", "v2", or absent (defaults to v1).'
387
+ });
388
+ return new sfn.Choice(this, "SelectPlanProtocol").when(sfn.Condition.stringEquals("$.PlanProtocol", "v2"), planV2).when(sfn.Condition.stringEquals("$.PlanProtocol", "v1"), plan).when(sfn.Condition.isPresent("$.PlanProtocol"), unsupportedPlanProtocol).otherwise(plan);
261
389
  }
262
390
  };
263
391
  function defaultHandlerZipPath() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cdk/HyperframesRenderStack.ts"],
4
- "sourcesContent": ["/**\n * `HyperframesRenderStack` \u2014 aws-cdk-lib L2 construct that emits the same\n * topology as `examples/aws-lambda/template.yaml`.\n *\n * Adopters who embed HyperFrames inside their own CDK app can extend this\n * construct or compose alongside it; the construct exposes its `.bucket`,\n * `.renderFunction`, and `.stateMachine` properties so additional\n * resources (alarms, dashboards, SNS topics) can be wired without\n * re-deriving the ARNs from a stack export.\n *\n * `aws-cdk-lib` and `constructs` are **peerDependencies**. The package\n * still type-checks (and the snapshot test still runs) because they're\n * also `devDependencies`, but adopters who only consume the SDK side of\n * `@hyperframes/aws-lambda` don't pull the CDK tree at runtime.\n *\n * Drift from the SAM template is guarded by the snapshot test\n * (`HyperframesRenderStack.snapshot.test.ts`), which diffs the synthed\n * CloudFormation against the SAM-rendered CloudFormation modulo\n * normalisation.\n */\n\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Duration, RemovalPolicy, Size } from \"aws-cdk-lib\";\nimport * as cloudwatch from \"aws-cdk-lib/aws-cloudwatch\";\nimport * as lambda from \"aws-cdk-lib/aws-lambda\";\nimport * as logs from \"aws-cdk-lib/aws-logs\";\nimport * as s3 from \"aws-cdk-lib/aws-s3\";\nimport * as sfn from \"aws-cdk-lib/aws-stepfunctions\";\nimport * as tasks from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { Construct } from \"constructs\";\n\n/** Construction-time props for {@link HyperframesRenderStack}. */\nexport interface HyperframesRenderStackProps {\n /** Name prefix applied to function / state-machine / alarm names. Default `\"hyperframes\"`. */\n projectName?: string;\n /** Lambda memory in MB. Allowed: 2048..10240 in 1024 steps. Default 10240. */\n lambdaMemoryMb?: 2048 | 3072 | 4096 | 5120 | 6144 | 7168 | 8192 | 9216 | 10240;\n /** Per-invocation Lambda timeout. Default 900 (15 min, Lambda hard cap). */\n lambdaTimeoutSec?: number;\n /** Lambda reserved concurrency cap. `undefined` = unreserved (account default). */\n reservedConcurrency?: number;\n /** Which Chrome runtime was bundled into the handler ZIP. Default `\"sparticuz\"`. */\n chromeSource?: \"sparticuz\" | \"chrome-headless-shell\";\n /** Threshold for the runaway-invocations alarm. Default 1000 invocations/hour. */\n chunkInvocationAlarmThreshold?: number;\n /**\n * Absolute path to the handler ZIP produced by\n * `bun run --cwd packages/aws-lambda build:zip`. Defaults to the\n * package-relative path the build script writes to. Adopters who\n * deploy the published handler ZIP set this explicitly.\n */\n handlerZipPath?: string;\n /** S3 bucket retention policy on stack delete. Default RETAIN. */\n bucketRemovalPolicy?: RemovalPolicy;\n}\n\nconst DEFAULT_MEMORY_MB = 10240;\nconst DEFAULT_TIMEOUT_SEC = 900;\nconst DEFAULT_CHROME_SOURCE = \"sparticuz\";\nconst DEFAULT_ALARM_THRESHOLD = 1000;\n\nexport class HyperframesRenderStack extends Construct {\n /** S3 bucket for plan tarballs, chunk outputs, and final renders. */\n readonly bucket: s3.Bucket;\n /** The single Lambda function dispatching plan / renderChunk / assemble. */\n readonly renderFunction: lambda.Function;\n /** The Step Functions state machine orchestrating the render. */\n readonly stateMachine: sfn.StateMachine;\n\n constructor(scope: Construct, id: string, props: HyperframesRenderStackProps = {}) {\n super(scope, id);\n\n const projectName = props.projectName ?? \"hyperframes\";\n const memorySize = props.lambdaMemoryMb ?? DEFAULT_MEMORY_MB;\n const timeoutSec = props.lambdaTimeoutSec ?? DEFAULT_TIMEOUT_SEC;\n const chromeSource = props.chromeSource ?? DEFAULT_CHROME_SOURCE;\n const alarmThreshold = props.chunkInvocationAlarmThreshold ?? DEFAULT_ALARM_THRESHOLD;\n const handlerZipPath = props.handlerZipPath ?? defaultHandlerZipPath();\n\n this.bucket = new s3.Bucket(this, \"RenderBucket\", {\n removalPolicy: props.bucketRemovalPolicy ?? RemovalPolicy.RETAIN,\n blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,\n // `Suspended` is the cheapest mode that still satisfies KMS / replication\n // prerequisites callers can layer on later. Adopters who treat the final\n // mp4 as user-keepable can switch to `Enabled`.\n versioned: false,\n lifecycleRules: [\n {\n id: \"ExpireIntermediates\",\n enabled: true,\n prefix: \"renders/\",\n expiration: Duration.days(7),\n },\n ],\n });\n\n this.renderFunction = new lambda.Function(this, \"RenderFunction\", {\n functionName: `${projectName}-render`,\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: \"handler.handler\",\n code: lambda.Code.fromAsset(handlerZipPath),\n memorySize,\n timeout: Duration.seconds(timeoutSec),\n ephemeralStorageSize: Size.gibibytes(10),\n architecture: lambda.Architecture.X86_64,\n reservedConcurrentExecutions: props.reservedConcurrency,\n tracing: lambda.Tracing.ACTIVE,\n environment: {\n NODE_OPTIONS: \"--enable-source-maps\",\n TMPDIR: \"/tmp\",\n HYPERFRAMES_LAMBDA_CHROME_SOURCE: chromeSource,\n HYPERFRAMES_RENDER_BUCKET: this.bucket.bucketName,\n },\n });\n\n // Scoped S3 perms only \u2014 explicitly NOT `CloudWatchLogsFullAccess`,\n // which would grant `logs:*` on `*` and overscope adopter accounts.\n // SAM's AWSLambdaBasicExecutionRole equivalent is included by the\n // default `new lambda.Function` execution role.\n this.bucket.grantReadWrite(this.renderFunction);\n\n const stateMachineLogGroup = new logs.LogGroup(this, \"RenderStateMachineLogGroup\", {\n logGroupName: `/aws/states/${projectName}-render`,\n retention: logs.RetentionDays.ONE_MONTH,\n removalPolicy: RemovalPolicy.DESTROY,\n });\n\n const definition = this.buildStateMachineDefinition();\n\n this.stateMachine = new sfn.StateMachine(this, \"RenderStateMachine\", {\n stateMachineName: `${projectName}-render`,\n stateMachineType: sfn.StateMachineType.STANDARD,\n definitionBody: sfn.DefinitionBody.fromChainable(definition),\n tracingEnabled: true,\n timeout: Duration.hours(1),\n logs: {\n destination: stateMachineLogGroup,\n level: sfn.LogLevel.ERROR,\n includeExecutionData: false,\n },\n });\n\n this.renderFunction.grantInvoke(this.stateMachine);\n\n new cloudwatch.Alarm(this, \"RenderChunkInvocationAlarm\", {\n alarmName: `${projectName}-runaway-chunk-invocations`,\n alarmDescription:\n \"Fires if RenderChunk Lambda invocations exceed the configured threshold in a 1-hour window.\",\n metric: this.renderFunction.metricInvocations({\n period: Duration.hours(1),\n statistic: cloudwatch.Stats.SUM,\n }),\n threshold: alarmThreshold,\n evaluationPeriods: 1,\n comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,\n treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,\n });\n\n new cloudwatch.Alarm(this, \"RenderFunctionErrorsAlarm\", {\n alarmName: `${projectName}-render-function-errors`,\n alarmDescription: \"Fires if the render Lambda reports any errors in a 5-minute window.\",\n metric: this.renderFunction.metricErrors({\n period: Duration.minutes(5),\n statistic: cloudwatch.Stats.SUM,\n }),\n threshold: 1,\n evaluationPeriods: 1,\n comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,\n treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,\n });\n\n new cloudwatch.Alarm(this, \"RenderStateMachineFailedAlarm\", {\n alarmName: `${projectName}-render-state-machine-failed`,\n alarmDescription: \"Fires when the render state machine reports a failed execution.\",\n metric: this.stateMachine.metricFailed({\n period: Duration.minutes(5),\n statistic: cloudwatch.Stats.SUM,\n }),\n threshold: 1,\n evaluationPeriods: 1,\n comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,\n treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,\n });\n }\n\n /**\n * Build the state-machine chain. Kept in a single method so the SAM\n * template and this construct can be diffed shape-for-shape during\n * the snapshot test.\n */\n private buildStateMachineDefinition(): sfn.IChainable {\n // `ChromeBinaryUnavailableError` is non-retryable: a wedged warm\n // instance keeps returning the same falsy executablePath until the\n // env recycles, so retries just burn the 4\u00D7 15-min budget.\n const NON_RETRYABLE_PLAN = [\n \"FFMPEG_VERSION_MISMATCH\",\n \"PLAN_HASH_MISMATCH\",\n \"S3_URI_NOT_ALLOWED\",\n \"BROWSER_GPU_NOT_SOFTWARE\",\n \"FONT_FETCH_FAILED\",\n \"PLAN_TOO_LARGE\",\n \"FORMAT_NOT_SUPPORTED_IN_DISTRIBUTED\",\n \"ChromeBinaryUnavailableError\",\n ];\n const NON_RETRYABLE_CHUNK = [\n \"FFMPEG_VERSION_MISMATCH\",\n \"PLAN_HASH_MISMATCH\",\n \"S3_URI_NOT_ALLOWED\",\n \"BROWSER_GPU_NOT_SOFTWARE\",\n \"ChromeBinaryUnavailableError\",\n ];\n const NON_RETRYABLE_ASSEMBLE = [\n \"FFMPEG_VERSION_MISMATCH\",\n \"PLAN_HASH_MISMATCH\",\n \"S3_URI_NOT_ALLOWED\",\n \"FORMAT_NOT_SUPPORTED_IN_DISTRIBUTED\",\n \"ChromeBinaryUnavailableError\",\n ];\n\n const plan = new tasks.LambdaInvoke(this, \"Plan\", {\n lambdaFunction: this.renderFunction,\n payload: sfn.TaskInput.fromObject({\n Action: \"plan\",\n \"ProjectS3Uri.$\": \"$.ProjectS3Uri\",\n \"PlanOutputS3Prefix.$\": \"$.PlanOutputS3Prefix\",\n \"Config.$\": \"$.Config\",\n }),\n resultSelector: {\n \"PlanS3Uri.$\": \"$.Payload.PlanS3Uri\",\n \"PlanHash.$\": \"$.Payload.PlanHash\",\n \"ChunkCount.$\": \"$.Payload.ChunkCount\",\n \"Format.$\": \"$.Payload.Format\",\n \"HasAudio.$\": \"$.Payload.HasAudio\",\n \"AudioS3Uri.$\": \"$.Payload.AudioS3Uri\",\n },\n resultPath: \"$.Plan\",\n });\n plan.addRetry({\n errors: NON_RETRYABLE_PLAN,\n maxAttempts: 0,\n });\n plan.addRetry({\n errors: [\"States.ALL\"],\n interval: Duration.seconds(2),\n maxAttempts: 4,\n backoffRate: 2,\n maxDelay: Duration.seconds(60),\n });\n\n const buildChunkList = new sfn.Pass(this, \"BuildChunkList\", {\n parameters: {\n \"ChunkIndexes.$\": \"States.ArrayRange(0, States.MathAdd($.Plan.ChunkCount, -1), 1)\",\n },\n resultPath: \"$.Iterator\",\n });\n\n const planProducedZero = new sfn.Fail(this, \"PlanProducedZeroChunks\", {\n error: \"PLAN_TOO_LARGE\",\n cause: \"Plan returned ChunkCount=0 \u2014 non-retryable producer-side invariant violation.\",\n });\n\n const renderChunkTask = new tasks.LambdaInvoke(this, \"RenderChunk\", {\n lambdaFunction: this.renderFunction,\n payload: sfn.TaskInput.fromObject({\n Action: \"renderChunk\",\n \"ChunkIndex.$\": \"$.ChunkIndex\",\n \"PlanS3Uri.$\": \"$.PlanS3Uri\",\n \"PlanHash.$\": \"$.PlanHash\",\n \"ChunkOutputS3Prefix.$\": \"$.ChunkOutputS3Prefix\",\n \"Format.$\": \"$.Format\",\n }),\n resultSelector: {\n \"ChunkS3Uri.$\": \"$.Payload.ChunkS3Uri\",\n \"ChunkIndex.$\": \"$.Payload.ChunkIndex\",\n \"Sha256.$\": \"$.Payload.Sha256\",\n },\n });\n renderChunkTask.addRetry({\n errors: NON_RETRYABLE_CHUNK,\n maxAttempts: 0,\n });\n renderChunkTask.addRetry({\n errors: [\"States.ALL\"],\n interval: Duration.seconds(2),\n maxAttempts: 4,\n backoffRate: 2,\n maxDelay: Duration.seconds(60),\n });\n\n const renderChunks = new sfn.Map(this, \"RenderChunks\", {\n itemsPath: \"$.Iterator.ChunkIndexes\",\n itemSelector: {\n \"ChunkIndex.$\": \"$$.Map.Item.Value\",\n \"PlanS3Uri.$\": \"$.Plan.PlanS3Uri\",\n \"PlanHash.$\": \"$.Plan.PlanHash\",\n \"ChunkOutputS3Prefix.$\": \"$.PlanOutputS3Prefix\",\n \"Format.$\": \"$.Plan.Format\",\n },\n maxConcurrencyPath: \"$.Plan.ChunkCount\",\n resultPath: \"$.Chunks\",\n });\n renderChunks.itemProcessor(renderChunkTask);\n\n const assemble = new tasks.LambdaInvoke(this, \"Assemble\", {\n lambdaFunction: this.renderFunction,\n payload: sfn.TaskInput.fromObject({\n Action: \"assemble\",\n \"PlanS3Uri.$\": \"$.Plan.PlanS3Uri\",\n \"ChunkS3Uris.$\": \"$.Chunks[*].ChunkS3Uri\",\n \"AudioS3Uri.$\": \"$.Plan.AudioS3Uri\",\n \"OutputS3Uri.$\": \"$.OutputS3Uri\",\n \"Format.$\": \"$.Plan.Format\",\n }),\n resultSelector: {\n \"OutputS3Uri.$\": \"$.Payload.OutputS3Uri\",\n \"FramesEncoded.$\": \"$.Payload.FramesEncoded\",\n \"FileSize.$\": \"$.Payload.FileSize\",\n },\n resultPath: \"$.Output\",\n });\n assemble.addRetry({\n errors: NON_RETRYABLE_ASSEMBLE,\n maxAttempts: 0,\n });\n assemble.addRetry({\n errors: [\"States.ALL\"],\n interval: Duration.seconds(2),\n maxAttempts: 4,\n backoffRate: 2,\n maxDelay: Duration.seconds(60),\n });\n\n const assertChunkCount = new sfn.Choice(this, \"AssertChunkCount\")\n .when(sfn.Condition.numberGreaterThan(\"$.Plan.ChunkCount\", 0), renderChunks.next(assemble))\n .otherwise(planProducedZero);\n\n return plan.next(buildChunkList).next(assertChunkCount);\n }\n}\n\n/**\n * Default location of the handler ZIP relative to this source file. Two\n * parents up = `packages/aws-lambda/`; the build script writes the ZIP\n * to `packages/aws-lambda/dist/handler.zip`. The package is published with\n * `main: \"./src/index.ts\"`, so this path resolves correctly both in the\n * source tree (during `bun test` / local CDK synth) and in a consumer's\n * `node_modules/@hyperframes/aws-lambda/` install.\n */\nfunction defaultHandlerZipPath(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n return resolve(here, \"..\", \"..\", \"dist\", \"handler.zip\");\n}\n"],
5
- "mappings": ";AAqBA,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAC9B,SAAS,UAAU,eAAe,YAAY;AAC9C,YAAY,gBAAgB;AAC5B,YAAY,YAAY;AACxB,YAAY,UAAU;AACtB,YAAY,QAAQ;AACpB,YAAY,SAAS;AACrB,YAAY,WAAW;AACvB,SAAS,iBAAiB;AA2B1B,IAAM,oBAAoB;AAC1B,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAC9B,IAAM,0BAA0B;AAEzB,IAAM,yBAAN,cAAqC,UAAU;AAAA;AAAA,EAE3C;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,OAAkB,IAAY,QAAqC,CAAC,GAAG;AACjF,UAAM,OAAO,EAAE;AAEf,UAAM,cAAc,MAAM,eAAe;AACzC,UAAM,aAAa,MAAM,kBAAkB;AAC3C,UAAM,aAAa,MAAM,oBAAoB;AAC7C,UAAM,eAAe,MAAM,gBAAgB;AAC3C,UAAM,iBAAiB,MAAM,iCAAiC;AAC9D,UAAM,iBAAiB,MAAM,kBAAkB,sBAAsB;AAErE,SAAK,SAAS,IAAO,UAAO,MAAM,gBAAgB;AAAA,MAChD,eAAe,MAAM,uBAAuB,cAAc;AAAA,MAC1D,mBAAsB,qBAAkB;AAAA;AAAA;AAAA;AAAA,MAIxC,WAAW;AAAA,MACX,gBAAgB;AAAA,QACd;AAAA,UACE,IAAI;AAAA,UACJ,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,YAAY,SAAS,KAAK,CAAC;AAAA,QAC7B;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,iBAAiB,IAAW,gBAAS,MAAM,kBAAkB;AAAA,MAChE,cAAc,GAAG,WAAW;AAAA,MAC5B,SAAgB,eAAQ;AAAA,MACxB,SAAS;AAAA,MACT,MAAa,YAAK,UAAU,cAAc;AAAA,MAC1C;AAAA,MACA,SAAS,SAAS,QAAQ,UAAU;AAAA,MACpC,sBAAsB,KAAK,UAAU,EAAE;AAAA,MACvC,cAAqB,oBAAa;AAAA,MAClC,8BAA8B,MAAM;AAAA,MACpC,SAAgB,eAAQ;AAAA,MACxB,aAAa;AAAA,QACX,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,kCAAkC;AAAA,QAClC,2BAA2B,KAAK,OAAO;AAAA,MACzC;AAAA,IACF,CAAC;AAMD,SAAK,OAAO,eAAe,KAAK,cAAc;AAE9C,UAAM,uBAAuB,IAAS,cAAS,MAAM,8BAA8B;AAAA,MACjF,cAAc,eAAe,WAAW;AAAA,MACxC,WAAgB,mBAAc;AAAA,MAC9B,eAAe,cAAc;AAAA,IAC/B,CAAC;AAED,UAAM,aAAa,KAAK,4BAA4B;AAEpD,SAAK,eAAe,IAAQ,iBAAa,MAAM,sBAAsB;AAAA,MACnE,kBAAkB,GAAG,WAAW;AAAA,MAChC,kBAAsB,qBAAiB;AAAA,MACvC,gBAAoB,mBAAe,cAAc,UAAU;AAAA,MAC3D,gBAAgB;AAAA,MAChB,SAAS,SAAS,MAAM,CAAC;AAAA,MACzB,MAAM;AAAA,QACJ,aAAa;AAAA,QACb,OAAW,aAAS;AAAA,QACpB,sBAAsB;AAAA,MACxB;AAAA,IACF,CAAC;AAED,SAAK,eAAe,YAAY,KAAK,YAAY;AAEjD,QAAe,iBAAM,MAAM,8BAA8B;AAAA,MACvD,WAAW,GAAG,WAAW;AAAA,MACzB,kBACE;AAAA,MACF,QAAQ,KAAK,eAAe,kBAAkB;AAAA,QAC5C,QAAQ,SAAS,MAAM,CAAC;AAAA,QACxB,WAAsB,iBAAM;AAAA,MAC9B,CAAC;AAAA,MACD,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,oBAA+B,8BAAmB;AAAA,MAClD,kBAA6B,4BAAiB;AAAA,IAChD,CAAC;AAED,QAAe,iBAAM,MAAM,6BAA6B;AAAA,MACtD,WAAW,GAAG,WAAW;AAAA,MACzB,kBAAkB;AAAA,MAClB,QAAQ,KAAK,eAAe,aAAa;AAAA,QACvC,QAAQ,SAAS,QAAQ,CAAC;AAAA,QAC1B,WAAsB,iBAAM;AAAA,MAC9B,CAAC;AAAA,MACD,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,oBAA+B,8BAAmB;AAAA,MAClD,kBAA6B,4BAAiB;AAAA,IAChD,CAAC;AAED,QAAe,iBAAM,MAAM,iCAAiC;AAAA,MAC1D,WAAW,GAAG,WAAW;AAAA,MACzB,kBAAkB;AAAA,MAClB,QAAQ,KAAK,aAAa,aAAa;AAAA,QACrC,QAAQ,SAAS,QAAQ,CAAC;AAAA,QAC1B,WAAsB,iBAAM;AAAA,MAC9B,CAAC;AAAA,MACD,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,oBAA+B,8BAAmB;AAAA,MAClD,kBAA6B,4BAAiB;AAAA,IAChD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,8BAA8C;AAIpD,UAAM,qBAAqB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,sBAAsB;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,yBAAyB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,OAAO,IAAU,mBAAa,MAAM,QAAQ;AAAA,MAChD,gBAAgB,KAAK;AAAA,MACrB,SAAa,cAAU,WAAW;AAAA,QAChC,QAAQ;AAAA,QACR,kBAAkB;AAAA,QAClB,wBAAwB;AAAA,QACxB,YAAY;AAAA,MACd,CAAC;AAAA,MACD,gBAAgB;AAAA,QACd,eAAe;AAAA,QACf,cAAc;AAAA,QACd,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,gBAAgB;AAAA,MAClB;AAAA,MACA,YAAY;AAAA,IACd,CAAC;AACD,SAAK,SAAS;AAAA,MACZ,QAAQ;AAAA,MACR,aAAa;AAAA,IACf,CAAC;AACD,SAAK,SAAS;AAAA,MACZ,QAAQ,CAAC,YAAY;AAAA,MACrB,UAAU,SAAS,QAAQ,CAAC;AAAA,MAC5B,aAAa;AAAA,MACb,aAAa;AAAA,MACb,UAAU,SAAS,QAAQ,EAAE;AAAA,IAC/B,CAAC;AAED,UAAM,iBAAiB,IAAQ,SAAK,MAAM,kBAAkB;AAAA,MAC1D,YAAY;AAAA,QACV,kBAAkB;AAAA,MACpB;AAAA,MACA,YAAY;AAAA,IACd,CAAC;AAED,UAAM,mBAAmB,IAAQ,SAAK,MAAM,0BAA0B;AAAA,MACpE,OAAO;AAAA,MACP,OAAO;AAAA,IACT,CAAC;AAED,UAAM,kBAAkB,IAAU,mBAAa,MAAM,eAAe;AAAA,MAClE,gBAAgB,KAAK;AAAA,MACrB,SAAa,cAAU,WAAW;AAAA,QAChC,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,eAAe;AAAA,QACf,cAAc;AAAA,QACd,yBAAyB;AAAA,QACzB,YAAY;AAAA,MACd,CAAC;AAAA,MACD,gBAAgB;AAAA,QACd,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,QAChB,YAAY;AAAA,MACd;AAAA,IACF,CAAC;AACD,oBAAgB,SAAS;AAAA,MACvB,QAAQ;AAAA,MACR,aAAa;AAAA,IACf,CAAC;AACD,oBAAgB,SAAS;AAAA,MACvB,QAAQ,CAAC,YAAY;AAAA,MACrB,UAAU,SAAS,QAAQ,CAAC;AAAA,MAC5B,aAAa;AAAA,MACb,aAAa;AAAA,MACb,UAAU,SAAS,QAAQ,EAAE;AAAA,IAC/B,CAAC;AAED,UAAM,eAAe,IAAQ,QAAI,MAAM,gBAAgB;AAAA,MACrD,WAAW;AAAA,MACX,cAAc;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,QACf,cAAc;AAAA,QACd,yBAAyB;AAAA,QACzB,YAAY;AAAA,MACd;AAAA,MACA,oBAAoB;AAAA,MACpB,YAAY;AAAA,IACd,CAAC;AACD,iBAAa,cAAc,eAAe;AAE1C,UAAM,WAAW,IAAU,mBAAa,MAAM,YAAY;AAAA,MACxD,gBAAgB,KAAK;AAAA,MACrB,SAAa,cAAU,WAAW;AAAA,QAChC,QAAQ;AAAA,QACR,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,QACjB,YAAY;AAAA,MACd,CAAC;AAAA,MACD,gBAAgB;AAAA,QACd,iBAAiB;AAAA,QACjB,mBAAmB;AAAA,QACnB,cAAc;AAAA,MAChB;AAAA,MACA,YAAY;AAAA,IACd,CAAC;AACD,aAAS,SAAS;AAAA,MAChB,QAAQ;AAAA,MACR,aAAa;AAAA,IACf,CAAC;AACD,aAAS,SAAS;AAAA,MAChB,QAAQ,CAAC,YAAY;AAAA,MACrB,UAAU,SAAS,QAAQ,CAAC;AAAA,MAC5B,aAAa;AAAA,MACb,aAAa;AAAA,MACb,UAAU,SAAS,QAAQ,EAAE;AAAA,IAC/B,CAAC;AAED,UAAM,mBAAmB,IAAQ,WAAO,MAAM,kBAAkB,EAC7D,KAAS,cAAU,kBAAkB,qBAAqB,CAAC,GAAG,aAAa,KAAK,QAAQ,CAAC,EACzF,UAAU,gBAAgB;AAE7B,WAAO,KAAK,KAAK,cAAc,EAAE,KAAK,gBAAgB;AAAA,EACxD;AACF;AAUA,SAAS,wBAAgC;AACvC,QAAM,OAAO,QAAQ,cAAc,YAAY,GAAG,CAAC;AACnD,SAAO,QAAQ,MAAM,MAAM,MAAM,QAAQ,aAAa;AACxD;",
4
+ "sourcesContent": ["/**\n * `HyperframesRenderStack` \u2014 aws-cdk-lib L2 construct that emits the same\n * topology as `examples/aws-lambda/template.yaml`.\n *\n * Adopters who embed HyperFrames inside their own CDK app can extend this\n * construct or compose alongside it; the construct exposes its `.bucket`,\n * `.renderFunction`, and `.stateMachine` properties so additional\n * resources (alarms, dashboards, SNS topics) can be wired without\n * re-deriving the ARNs from a stack export.\n *\n * `aws-cdk-lib` and `constructs` are **peerDependencies**. The package\n * still type-checks (and the snapshot test still runs) because they're\n * also `devDependencies`, but adopters who only consume the SDK side of\n * `@hyperframes/aws-lambda` don't pull the CDK tree at runtime.\n *\n * Drift from the SAM template is guarded by the snapshot test\n * (`HyperframesRenderStack.snapshot.test.ts`), which diffs the synthed\n * CloudFormation against the SAM-rendered CloudFormation modulo\n * normalisation.\n */\n\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Duration, RemovalPolicy, Size } from \"aws-cdk-lib\";\nimport * as cloudwatch from \"aws-cdk-lib/aws-cloudwatch\";\nimport * as lambda from \"aws-cdk-lib/aws-lambda\";\nimport * as logs from \"aws-cdk-lib/aws-logs\";\nimport * as s3 from \"aws-cdk-lib/aws-s3\";\nimport * as sfn from \"aws-cdk-lib/aws-stepfunctions\";\nimport * as tasks from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { Construct } from \"constructs\";\n\n/** Construction-time props for {@link HyperframesRenderStack}. */\nexport interface HyperframesRenderStackProps {\n /** Name prefix applied to function / state-machine / alarm names. Default `\"hyperframes\"`. */\n projectName?: string;\n /** Lambda memory in MB. Allowed: 2048..10240 in 1024 steps. Default 10240. */\n lambdaMemoryMb?: 2048 | 3072 | 4096 | 5120 | 6144 | 7168 | 8192 | 9216 | 10240;\n /** Per-invocation Lambda timeout. Default 900 (15 min, Lambda hard cap). */\n lambdaTimeoutSec?: number;\n /** Lambda reserved concurrency cap. `undefined` = unreserved (account default). */\n reservedConcurrency?: number;\n /** Which Chrome runtime was bundled into the handler ZIP. Default `\"sparticuz\"`. */\n chromeSource?: \"sparticuz\" | \"chrome-headless-shell\";\n /** Threshold for the runaway-invocations alarm. Default 1000 invocations/hour. */\n chunkInvocationAlarmThreshold?: number;\n /**\n * Absolute path to the handler ZIP produced by\n * `bun run --cwd packages/aws-lambda build:zip`. Defaults to the\n * package-relative path the build script writes to. Adopters who\n * deploy the published handler ZIP set this explicitly.\n */\n handlerZipPath?: string;\n /** S3 bucket retention policy on stack delete. Default RETAIN. */\n bucketRemovalPolicy?: RemovalPolicy;\n}\n\nconst DEFAULT_MEMORY_MB = 10240;\nconst DEFAULT_TIMEOUT_SEC = 900;\nconst DEFAULT_CHROME_SOURCE = \"sparticuz\";\nconst DEFAULT_ALARM_THRESHOLD = 1000;\n\nexport class HyperframesRenderStack extends Construct {\n /** S3 bucket for plan tarballs, chunk outputs, and final renders. */\n readonly bucket: s3.Bucket;\n /** The single Lambda function dispatching plan / renderChunk / assemble. */\n readonly renderFunction: lambda.Function;\n /** The Step Functions state machine orchestrating the render. */\n readonly stateMachine: sfn.StateMachine;\n\n constructor(scope: Construct, id: string, props: HyperframesRenderStackProps = {}) {\n super(scope, id);\n\n const projectName = props.projectName ?? \"hyperframes\";\n const memorySize = props.lambdaMemoryMb ?? DEFAULT_MEMORY_MB;\n const timeoutSec = props.lambdaTimeoutSec ?? DEFAULT_TIMEOUT_SEC;\n const chromeSource = props.chromeSource ?? DEFAULT_CHROME_SOURCE;\n const alarmThreshold = props.chunkInvocationAlarmThreshold ?? DEFAULT_ALARM_THRESHOLD;\n const handlerZipPath = props.handlerZipPath ?? defaultHandlerZipPath();\n\n this.bucket = new s3.Bucket(this, \"RenderBucket\", {\n removalPolicy: props.bucketRemovalPolicy ?? RemovalPolicy.RETAIN,\n blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,\n // `Suspended` is the cheapest mode that still satisfies KMS / replication\n // prerequisites callers can layer on later. Adopters who treat the final\n // mp4 as user-keepable can switch to `Enabled`.\n versioned: false,\n lifecycleRules: [\n {\n id: \"ExpireIntermediates\",\n enabled: true,\n prefix: \"renders/\",\n expiration: Duration.days(7),\n },\n ],\n });\n\n this.renderFunction = new lambda.Function(this, \"RenderFunction\", {\n functionName: `${projectName}-render`,\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: \"handler.handler\",\n code: lambda.Code.fromAsset(handlerZipPath),\n memorySize,\n timeout: Duration.seconds(timeoutSec),\n ephemeralStorageSize: Size.gibibytes(10),\n architecture: lambda.Architecture.X86_64,\n reservedConcurrentExecutions: props.reservedConcurrency,\n tracing: lambda.Tracing.ACTIVE,\n environment: {\n NODE_OPTIONS: \"--enable-source-maps\",\n TMPDIR: \"/tmp\",\n HYPERFRAMES_LAMBDA_CHROME_SOURCE: chromeSource,\n HYPERFRAMES_RENDER_BUCKET: this.bucket.bucketName,\n },\n });\n\n // Scoped S3 perms only \u2014 explicitly NOT `CloudWatchLogsFullAccess`,\n // which would grant `logs:*` on `*` and overscope adopter accounts.\n // SAM's AWSLambdaBasicExecutionRole equivalent is included by the\n // default `new lambda.Function` execution role.\n this.bucket.grantReadWrite(this.renderFunction);\n\n const stateMachineLogGroup = new logs.LogGroup(this, \"RenderStateMachineLogGroup\", {\n logGroupName: `/aws/states/${projectName}-render`,\n retention: logs.RetentionDays.ONE_MONTH,\n removalPolicy: RemovalPolicy.DESTROY,\n });\n\n const definition = this.buildStateMachineDefinition();\n\n this.stateMachine = new sfn.StateMachine(this, \"RenderStateMachine\", {\n stateMachineName: `${projectName}-render`,\n stateMachineType: sfn.StateMachineType.STANDARD,\n definitionBody: sfn.DefinitionBody.fromChainable(definition),\n tracingEnabled: true,\n timeout: Duration.hours(1),\n logs: {\n destination: stateMachineLogGroup,\n level: sfn.LogLevel.ERROR,\n includeExecutionData: false,\n },\n });\n\n this.renderFunction.grantInvoke(this.stateMachine);\n\n new cloudwatch.Alarm(this, \"RenderChunkInvocationAlarm\", {\n alarmName: `${projectName}-runaway-chunk-invocations`,\n alarmDescription:\n \"Fires if RenderChunk Lambda invocations exceed the configured threshold in a 1-hour window.\",\n metric: this.renderFunction.metricInvocations({\n period: Duration.hours(1),\n statistic: cloudwatch.Stats.SUM,\n }),\n threshold: alarmThreshold,\n evaluationPeriods: 1,\n comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,\n treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,\n });\n\n new cloudwatch.Alarm(this, \"RenderFunctionErrorsAlarm\", {\n alarmName: `${projectName}-render-function-errors`,\n alarmDescription: \"Fires if the render Lambda reports any errors in a 5-minute window.\",\n metric: this.renderFunction.metricErrors({\n period: Duration.minutes(5),\n statistic: cloudwatch.Stats.SUM,\n }),\n threshold: 1,\n evaluationPeriods: 1,\n comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,\n treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,\n });\n\n new cloudwatch.Alarm(this, \"RenderStateMachineFailedAlarm\", {\n alarmName: `${projectName}-render-state-machine-failed`,\n alarmDescription: \"Fires when the render state machine reports a failed execution.\",\n metric: this.stateMachine.metricFailed({\n period: Duration.minutes(5),\n statistic: cloudwatch.Stats.SUM,\n }),\n threshold: 1,\n evaluationPeriods: 1,\n comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,\n treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,\n });\n }\n\n /**\n * Build the state-machine chain. Kept in a single method so the SAM\n * template and this construct can be diffed shape-for-shape during\n * the snapshot test.\n */\n private buildStateMachineDefinition(): sfn.IChainable {\n // `ChromeBinaryUnavailableError` is non-retryable: a wedged warm\n // instance keeps returning the same falsy executablePath until the\n // env recycles, so retries just burn the 4\u00D7 15-min budget.\n const NON_RETRYABLE_PLAN = [\n \"FFMPEG_VERSION_MISMATCH\",\n \"PLAN_HASH_MISMATCH\",\n \"S3_URI_NOT_ALLOWED\",\n \"BROWSER_GPU_NOT_SOFTWARE\",\n \"FONT_FETCH_FAILED\",\n \"PLAN_TOO_LARGE\",\n \"PlanTooLargeError\",\n \"PLAN_PROTOCOL_UNSUPPORTED\",\n \"PlanProtocolUnsupportedError\",\n \"PLAN_V2_INTEGRITY_UNRECOVERABLE\",\n \"PlanV2IntegrityError\",\n \"PLAN_ARTIFACT_DIGEST_MISMATCH\",\n \"FORMAT_NOT_SUPPORTED_IN_DISTRIBUTED\",\n \"ChromeBinaryUnavailableError\",\n ];\n const NON_RETRYABLE_CHUNK = [\n \"FFMPEG_VERSION_MISMATCH\",\n \"PLAN_HASH_MISMATCH\",\n \"S3_URI_NOT_ALLOWED\",\n \"BROWSER_GPU_NOT_SOFTWARE\",\n \"PLAN_TOO_LARGE\",\n \"PlanTooLargeError\",\n \"PLAN_PROTOCOL_UNSUPPORTED\",\n \"PlanProtocolUnsupportedError\",\n \"PLAN_V2_INTEGRITY_UNRECOVERABLE\",\n \"PlanV2IntegrityError\",\n \"PLAN_ARTIFACT_DIGEST_MISMATCH\",\n \"ChromeBinaryUnavailableError\",\n ];\n const NON_RETRYABLE_ASSEMBLE = [\n \"FFMPEG_VERSION_MISMATCH\",\n \"PLAN_HASH_MISMATCH\",\n \"S3_URI_NOT_ALLOWED\",\n \"PLAN_PROTOCOL_UNSUPPORTED\",\n \"PlanProtocolUnsupportedError\",\n \"PLAN_V2_INTEGRITY_UNRECOVERABLE\",\n \"PlanV2IntegrityError\",\n \"FORMAT_NOT_SUPPORTED_IN_DISTRIBUTED\",\n \"PLAN_TOO_LARGE\",\n \"PlanTooLargeError\",\n \"PLAN_ARTIFACT_DIGEST_MISMATCH\",\n \"ChromeBinaryUnavailableError\",\n ];\n\n const plan = new tasks.LambdaInvoke(this, \"Plan\", {\n lambdaFunction: this.renderFunction,\n payload: sfn.TaskInput.fromObject({\n Action: \"plan\",\n \"ProjectS3Uri.$\": \"$.ProjectS3Uri\",\n \"PlanOutputS3Prefix.$\": \"$.PlanOutputS3Prefix\",\n \"Config.$\": \"$.Config\",\n }),\n resultSelector: {\n PlanProtocol: \"v1\",\n \"PlanS3Uri.$\": \"$.Payload.PlanS3Uri\",\n \"PlanHash.$\": \"$.Payload.PlanHash\",\n \"ChunkCount.$\": \"$.Payload.ChunkCount\",\n \"Format.$\": \"$.Payload.Format\",\n \"HasAudio.$\": \"$.Payload.HasAudio\",\n \"AudioS3Uri.$\": \"$.Payload.AudioS3Uri\",\n },\n resultPath: \"$.Plan\",\n });\n plan.addRetry({\n errors: NON_RETRYABLE_PLAN,\n maxAttempts: 0,\n });\n plan.addRetry({\n errors: [\"States.ALL\"],\n interval: Duration.seconds(2),\n maxAttempts: 4,\n backoffRate: 2,\n maxDelay: Duration.seconds(60),\n });\n\n const planV2 = new tasks.LambdaInvoke(this, \"PlanV2\", {\n lambdaFunction: this.renderFunction,\n payload: sfn.TaskInput.fromObject({\n Action: \"plan\",\n PlanProtocol: \"v2\",\n \"ProjectS3Uri.$\": \"$.ProjectS3Uri\",\n \"PlanOutputS3Prefix.$\": \"$.PlanOutputS3Prefix\",\n \"Config.$\": \"$.Config\",\n }),\n resultSelector: {\n PlanProtocol: \"v2\",\n \"PlanV2ManifestS3Uri.$\": \"$.Payload.PlanV2ManifestS3Uri\",\n \"PlanV2ArtifactS3Prefix.$\": \"$.Payload.PlanV2ArtifactS3Prefix\",\n \"PlanHash.$\": \"$.Payload.PlanHash\",\n \"ChunkCount.$\": \"$.Payload.ChunkCount\",\n \"Format.$\": \"$.Payload.Format\",\n \"HasAudio.$\": \"$.Payload.HasAudio\",\n },\n resultPath: \"$.Plan\",\n });\n planV2.addRetry({ errors: NON_RETRYABLE_PLAN, maxAttempts: 0 });\n planV2.addRetry({\n errors: [\"States.ALL\"],\n interval: Duration.seconds(2),\n maxAttempts: 4,\n backoffRate: 2,\n maxDelay: Duration.seconds(60),\n });\n\n const buildChunkList = new sfn.Pass(this, \"BuildChunkList\", {\n parameters: {\n \"ChunkIndexes.$\": \"States.ArrayRange(0, States.MathAdd($.Plan.ChunkCount, -1), 1)\",\n },\n resultPath: \"$.Iterator\",\n });\n\n const planProducedZero = new sfn.Fail(this, \"PlanProducedZeroChunks\", {\n error: \"PLAN_TOO_LARGE\",\n cause: \"Plan returned ChunkCount=0 \u2014 non-retryable producer-side invariant violation.\",\n });\n\n const renderChunkTask = new tasks.LambdaInvoke(this, \"RenderChunk\", {\n lambdaFunction: this.renderFunction,\n payload: sfn.TaskInput.fromObject({\n Action: \"renderChunk\",\n \"ChunkIndex.$\": \"$.ChunkIndex\",\n \"PlanS3Uri.$\": \"$.PlanS3Uri\",\n \"PlanHash.$\": \"$.PlanHash\",\n \"ChunkOutputS3Prefix.$\": \"$.ChunkOutputS3Prefix\",\n \"Format.$\": \"$.Format\",\n }),\n resultSelector: {\n \"ChunkS3Uri.$\": \"$.Payload.ChunkS3Uri\",\n \"ChunkIndex.$\": \"$.Payload.ChunkIndex\",\n \"Sha256.$\": \"$.Payload.Sha256\",\n },\n });\n renderChunkTask.addRetry({\n errors: NON_RETRYABLE_CHUNK,\n maxAttempts: 0,\n });\n renderChunkTask.addRetry({\n errors: [\"States.ALL\"],\n interval: Duration.seconds(2),\n maxAttempts: 4,\n backoffRate: 2,\n maxDelay: Duration.seconds(60),\n });\n\n const renderChunks = new sfn.Map(this, \"RenderChunks\", {\n itemsPath: \"$.Iterator.ChunkIndexes\",\n itemSelector: {\n \"ChunkIndex.$\": \"$$.Map.Item.Value\",\n \"PlanS3Uri.$\": \"$.Plan.PlanS3Uri\",\n \"PlanHash.$\": \"$.Plan.PlanHash\",\n \"ChunkOutputS3Prefix.$\": \"$.PlanOutputS3Prefix\",\n \"Format.$\": \"$.Plan.Format\",\n },\n maxConcurrencyPath: \"$.Plan.ChunkCount\",\n resultPath: \"$.Chunks\",\n });\n renderChunks.itemProcessor(renderChunkTask);\n\n const assemble = new tasks.LambdaInvoke(this, \"Assemble\", {\n lambdaFunction: this.renderFunction,\n payload: sfn.TaskInput.fromObject({\n Action: \"assemble\",\n \"PlanS3Uri.$\": \"$.Plan.PlanS3Uri\",\n \"ChunkS3Uris.$\": \"$.Chunks[*].ChunkS3Uri\",\n \"AudioS3Uri.$\": \"$.Plan.AudioS3Uri\",\n \"OutputS3Uri.$\": \"$.OutputS3Uri\",\n \"Format.$\": \"$.Plan.Format\",\n }),\n resultSelector: {\n \"OutputS3Uri.$\": \"$.Payload.OutputS3Uri\",\n \"FramesEncoded.$\": \"$.Payload.FramesEncoded\",\n \"FileSize.$\": \"$.Payload.FileSize\",\n },\n resultPath: \"$.Output\",\n });\n assemble.addRetry({\n errors: NON_RETRYABLE_ASSEMBLE,\n maxAttempts: 0,\n });\n assemble.addRetry({\n errors: [\"States.ALL\"],\n interval: Duration.seconds(2),\n maxAttempts: 4,\n backoffRate: 2,\n maxDelay: Duration.seconds(60),\n });\n\n const renderChunkV2Task = new tasks.LambdaInvoke(this, \"RenderChunkV2\", {\n lambdaFunction: this.renderFunction,\n payload: sfn.TaskInput.fromObject({\n Action: \"renderChunk\",\n PlanProtocol: \"v2\",\n \"ChunkIndex.$\": \"$.ChunkIndex\",\n \"PlanV2ManifestS3Uri.$\": \"$.PlanV2ManifestS3Uri\",\n \"PlanV2ArtifactS3Prefix.$\": \"$.PlanV2ArtifactS3Prefix\",\n \"PlanHash.$\": \"$.PlanHash\",\n \"ChunkOutputS3Prefix.$\": \"$.ChunkOutputS3Prefix\",\n \"Format.$\": \"$.Format\",\n }),\n resultSelector: {\n \"ChunkS3Uri.$\": \"$.Payload.ChunkS3Uri\",\n \"ChunkIndex.$\": \"$.Payload.ChunkIndex\",\n \"Sha256.$\": \"$.Payload.Sha256\",\n },\n });\n renderChunkV2Task.addRetry({ errors: NON_RETRYABLE_CHUNK, maxAttempts: 0 });\n renderChunkV2Task.addRetry({\n errors: [\"States.ALL\"],\n interval: Duration.seconds(2),\n maxAttempts: 4,\n backoffRate: 2,\n maxDelay: Duration.seconds(60),\n });\n\n const renderChunksV2 = new sfn.Map(this, \"RenderChunksV2\", {\n itemsPath: \"$.Iterator.ChunkIndexes\",\n itemSelector: {\n \"ChunkIndex.$\": \"$$.Map.Item.Value\",\n \"PlanV2ManifestS3Uri.$\": \"$.Plan.PlanV2ManifestS3Uri\",\n \"PlanV2ArtifactS3Prefix.$\": \"$.Plan.PlanV2ArtifactS3Prefix\",\n \"PlanHash.$\": \"$.Plan.PlanHash\",\n \"ChunkOutputS3Prefix.$\": \"$.PlanOutputS3Prefix\",\n \"Format.$\": \"$.Plan.Format\",\n },\n maxConcurrencyPath: \"$.Plan.ChunkCount\",\n resultPath: \"$.Chunks\",\n });\n renderChunksV2.itemProcessor(renderChunkV2Task);\n\n const assembleV2 = new tasks.LambdaInvoke(this, \"AssembleV2\", {\n lambdaFunction: this.renderFunction,\n payload: sfn.TaskInput.fromObject({\n Action: \"assemble\",\n PlanProtocol: \"v2\",\n \"PlanV2ManifestS3Uri.$\": \"$.Plan.PlanV2ManifestS3Uri\",\n \"PlanV2ArtifactS3Prefix.$\": \"$.Plan.PlanV2ArtifactS3Prefix\",\n \"PlanHash.$\": \"$.Plan.PlanHash\",\n \"ChunkS3Uris.$\": \"$.Chunks[*].ChunkS3Uri\",\n AudioS3Uri: null,\n \"OutputS3Uri.$\": \"$.OutputS3Uri\",\n \"Format.$\": \"$.Plan.Format\",\n }),\n resultSelector: {\n \"OutputS3Uri.$\": \"$.Payload.OutputS3Uri\",\n \"FramesEncoded.$\": \"$.Payload.FramesEncoded\",\n \"FileSize.$\": \"$.Payload.FileSize\",\n },\n resultPath: \"$.Output\",\n });\n assembleV2.addRetry({ errors: NON_RETRYABLE_ASSEMBLE, maxAttempts: 0 });\n assembleV2.addRetry({\n errors: [\"States.ALL\"],\n interval: Duration.seconds(2),\n maxAttempts: 4,\n backoffRate: 2,\n maxDelay: Duration.seconds(60),\n });\n\n const selectWorkerProtocol = new sfn.Choice(this, \"SelectWorkerProtocol\")\n .when(\n sfn.Condition.stringEquals(\"$.Plan.PlanProtocol\", \"v2\"),\n renderChunksV2.next(assembleV2),\n )\n .otherwise(renderChunks.next(assemble));\n const assertChunkCount = new sfn.Choice(this, \"AssertChunkCount\")\n .when(sfn.Condition.numberGreaterThan(\"$.Plan.ChunkCount\", 0), selectWorkerProtocol)\n .otherwise(planProducedZero);\n\n plan.next(buildChunkList);\n planV2.next(buildChunkList);\n buildChunkList.next(assertChunkCount);\n\n const unsupportedPlanProtocol = new sfn.Fail(this, \"UnsupportedPlanProtocol\", {\n error: \"PLAN_PROTOCOL_UNSUPPORTED\",\n cause: 'PlanProtocol must be \"v1\", \"v2\", or absent (defaults to v1).',\n });\n return new sfn.Choice(this, \"SelectPlanProtocol\")\n .when(sfn.Condition.stringEquals(\"$.PlanProtocol\", \"v2\"), planV2)\n .when(sfn.Condition.stringEquals(\"$.PlanProtocol\", \"v1\"), plan)\n .when(sfn.Condition.isPresent(\"$.PlanProtocol\"), unsupportedPlanProtocol)\n .otherwise(plan);\n }\n}\n\n/**\n * Default location of the handler ZIP relative to this source file. Two\n * parents up = `packages/aws-lambda/`; the build script writes the ZIP\n * to `packages/aws-lambda/dist/handler.zip`. The package is published with\n * `main: \"./src/index.ts\"`, so this path resolves correctly both in the\n * source tree (during `bun test` / local CDK synth) and in a consumer's\n * `node_modules/@hyperframes/aws-lambda/` install.\n */\nfunction defaultHandlerZipPath(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n return resolve(here, \"..\", \"..\", \"dist\", \"handler.zip\");\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/events.d.ts CHANGED
@@ -19,6 +19,8 @@ import type { DistributedFormat, SerializableDistributedRenderConfig } from "@hy
19
19
  export type { SerializableDistributedRenderConfig } from "@hyperframes/producer/distributed";
20
20
  /** Discriminator for the three roles the one Lambda image fulfills. */
21
21
  export type LambdaAction = "plan" | "renderChunk" | "assemble";
22
+ /** Transport protocol selected for one complete distributed render. */
23
+ export type LambdaPlanProtocol = "v1" | "v2";
22
24
  /**
23
25
  * Top-level shape of any event the handler may receive.
24
26
  *
@@ -33,7 +35,7 @@ export type LambdaEvent = PlanEvent | RenderChunkEvent | AssembleEvent | {
33
35
  Input: LambdaEvent;
34
36
  };
35
37
  /** Activity A: produce a planDir, upload to S3. */
36
- export interface PlanEvent {
38
+ interface PlanEventBase {
37
39
  Action: "plan";
38
40
  /** S3 URI pointing at a `tar -czf`-archived project directory (`s3://bucket/key.tar.gz`). */
39
41
  ProjectS3Uri: string;
@@ -42,17 +44,24 @@ export interface PlanEvent {
42
44
  /** `DistributedRenderConfig` minus runtime-only fields (logger, abortSignal). */
43
45
  Config: SerializableDistributedRenderConfig;
44
46
  }
47
+ /** Legacy/default plan transport. Absence is deliberately interpreted as v1. */
48
+ export interface PlanV1Event extends PlanEventBase {
49
+ PlanProtocol?: "v1";
50
+ }
51
+ /** Explicit opt-in to the content-addressed v2 plan transport. */
52
+ export interface PlanV2Event extends PlanEventBase {
53
+ PlanProtocol: "v2";
54
+ }
55
+ export type PlanEvent = PlanV1Event | PlanV2Event;
45
56
  /** Activity B: fetch planDir, render one chunk, upload result. */
46
- export interface RenderChunkEvent {
57
+ interface RenderChunkEventBase {
47
58
  Action: "renderChunk";
48
- /** S3 URI of the plan tar produced by a PlanEvent invocation. */
49
- PlanS3Uri: string;
50
59
  /**
51
- * `PlanResult.planHash` from the Plan invocation. The handler verifies
52
- * this against the untarred planDir's `plan.json` before invoking the
53
- * producer, throwing a typed `PLAN_HASH_MISMATCH` on divergence so the
54
- * state machine routes it as non-retryable. Defense-in-depth the
55
- * producer also re-checks internally.
60
+ * `PlanResult.planHash` from the Plan invocation. For v1, the handler
61
+ * verifies it against the untarred planDir's `plan.json`; for v2, it
62
+ * verifies it against the content-addressed manifest before invoking the
63
+ * producer. Divergence throws a typed `PLAN_HASH_MISMATCH` so the state
64
+ * machine routes it as non-retryable.
56
65
  */
57
66
  PlanHash: string;
58
67
  /** 0-based chunk index this invocation should render. */
@@ -62,11 +71,25 @@ export interface RenderChunkEvent {
62
71
  /** Output container format from the plan's encoder.json; drives file vs frame-dir handling. */
63
72
  Format: DistributedFormat;
64
73
  }
74
+ /** Legacy/default chunk event. */
75
+ export interface RenderChunkV1Event extends RenderChunkEventBase {
76
+ PlanProtocol?: "v1";
77
+ /** S3 URI of the v1 plan tar produced by a PlanEvent invocation. */
78
+ PlanS3Uri: string;
79
+ }
80
+ /**
81
+ * V2 chunk event. It intentionally cannot carry `PlanS3Uri`: the manifest
82
+ * describes the exact content-addressed artifacts needed by this chunk.
83
+ */
84
+ export interface RenderChunkV2Event extends RenderChunkEventBase {
85
+ PlanProtocol: "v2";
86
+ PlanV2ManifestS3Uri: string;
87
+ PlanV2ArtifactS3Prefix: string;
88
+ }
89
+ export type RenderChunkEvent = RenderChunkV1Event | RenderChunkV2Event;
65
90
  /** Activity C: fetch planDir + all chunks + audio, assemble, upload final. */
66
- export interface AssembleEvent {
91
+ interface AssembleEventBase {
67
92
  Action: "assemble";
68
- /** S3 URI of the plan tar produced by a PlanEvent invocation. */
69
- PlanS3Uri: string;
70
93
  /** S3 URIs of every chunk, ordered by chunk index. Length must equal `chunkCount`. */
71
94
  ChunkS3Uris: string[];
72
95
  /** S3 URI of the planDir's `audio.aac` if the composition has audio; `null` otherwise. */
@@ -86,10 +109,23 @@ export interface AssembleEvent {
86
109
  */
87
110
  Cfr?: boolean;
88
111
  }
112
+ /** Legacy/default assemble event. */
113
+ export interface AssembleV1Event extends AssembleEventBase {
114
+ PlanProtocol?: "v1";
115
+ /** S3 URI of the v1 plan tar produced by a PlanEvent invocation. */
116
+ PlanS3Uri: string;
117
+ }
118
+ /** V2 assemble event, scoped to manifest-declared assembler artifacts. */
119
+ export interface AssembleV2Event extends AssembleEventBase {
120
+ PlanProtocol: "v2";
121
+ PlanV2ManifestS3Uri: string;
122
+ PlanV2ArtifactS3Prefix: string;
123
+ PlanHash: string;
124
+ }
125
+ export type AssembleEvent = AssembleV1Event | AssembleV2Event;
89
126
  /** Result of a `plan` invocation. Carries enough to size the Map(N) state. */
90
- export interface PlanLambdaResult {
127
+ interface PlanLambdaResultBase {
91
128
  Action: "plan";
92
- PlanS3Uri: string;
93
129
  PlanHash: string;
94
130
  ChunkCount: number;
95
131
  TotalFrames: number;
@@ -103,6 +139,17 @@ export interface PlanLambdaResult {
103
139
  ProducerVersion: string;
104
140
  DurationMs: number;
105
141
  }
142
+ /** Existing v1 result. Kept unchanged for wire compatibility. */
143
+ export interface PlanV1LambdaResult extends PlanLambdaResultBase {
144
+ PlanS3Uri: string;
145
+ }
146
+ /** V2 result. The two v2 locators are never aliases for `PlanS3Uri`. */
147
+ export interface PlanV2LambdaResult extends PlanLambdaResultBase {
148
+ PlanProtocol: "v2";
149
+ PlanV2ManifestS3Uri: string;
150
+ PlanV2ArtifactS3Prefix: string;
151
+ }
152
+ export type PlanLambdaResult = PlanV1LambdaResult | PlanV2LambdaResult;
106
153
  /** Result of a `renderChunk` invocation. Sized ≤200 bytes per §2.4. */
107
154
  export interface RenderChunkLambdaResult {
108
155
  Action: "renderChunk";
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,mCAAmC,EACpC,MAAM,mCAAmC,CAAC;AAE3C,YAAY,EAAE,mCAAmC,EAAE,MAAM,mCAAmC,CAAC;AAE7F,uEAAuE;AACvE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,CAAC;AAE/D;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,gBAAgB,GAChB,aAAa,GACb;IAAE,OAAO,EAAE,WAAW,CAAA;CAAE,GACxB;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC;AAE3B,mDAAmD;AACnD,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,YAAY,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iFAAiF;IACjF,MAAM,EAAE,mCAAmC,CAAC;CAC7C;AAED,kEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,aAAa,CAAC;IACtB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,+FAA+F;IAC/F,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,0FAA0F;IAC1F,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAID,8EAA8E;AAC9E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,uEAAuE;AACvE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,uBAAuB,GAAG,oBAAoB,CAAC"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
package/dist/handler.d.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  * primitive → S3 upload → return small JSON result.
12
12
  */
13
13
  import { S3Client } from "@aws-sdk/client-s3";
14
- import { assemble, plan, renderChunk } from "@hyperframes/producer/distributed";
14
+ import { assemble, plan, planV2, renderChunk } from "@hyperframes/producer/distributed";
15
15
  import type { AssembleEvent, LambdaEvent, LambdaResult, PlanEvent, RenderChunkEvent } from "./events.js";
16
16
  /**
17
17
  * Optional injection points used by the handler's unit tests. Production
@@ -24,6 +24,7 @@ export interface HandlerDeps {
24
24
  s3?: S3Client;
25
25
  primitives?: {
26
26
  plan: typeof plan;
27
+ planV2?: typeof planV2;
27
28
  renderChunk: typeof renderChunk;
28
29
  assemble: typeof assemble;
29
30
  };
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EACL,QAAQ,EAIR,IAAI,EAEJ,WAAW,EACZ,MAAM,mCAAmC,CAAC;AAG3C,OAAO,KAAK,EACV,aAAa,EAGb,WAAW,EACX,YAAY,EACZ,SAAS,EAET,gBAAgB,EAEjB,MAAM,aAAa,CAAC;AAoBrB;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,OAAO,IAAI,CAAC;QAClB,WAAW,EAAE,OAAO,WAAW,CAAC;QAChC,QAAQ,EAAE,OAAO,QAAQ,CAAC;KAC3B,CAAC;IACF,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAwC3F;AAWD,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,aAAa,CAsB5F"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EACL,QAAQ,EAMR,IAAI,EACJ,MAAM,EAMN,WAAW,EACZ,MAAM,mCAAmC,CAAC;AAG3C,OAAO,KAAK,EACV,aAAa,EAGb,WAAW,EACX,YAAY,EACZ,SAAS,EAET,gBAAgB,EAEjB,MAAM,aAAa,CAAC;AAuBrB;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,OAAO,IAAI,CAAC;QAClB,MAAM,CAAC,EAAE,OAAO,MAAM,CAAC;QACvB,WAAW,EAAE,OAAO,WAAW,CAAC;QAChC,QAAQ,EAAE,OAAO,QAAQ,CAAC;KAC3B,CAAC;IACF,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CA0C3F;AA8BD,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,aAAa,CAsB5F"}