@kensio/yulin 1.21.30 → 1.21.32

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 (67) hide show
  1. package/dist/serve/message/sim-message-log-console.js +3 -3
  2. package/dist/service/apigateway/api/deployment/sim-rest-api-deployment.js +3 -3
  3. package/dist/service/apigateway/api/method/sim-rest-api-method.js +12 -12
  4. package/dist/service/apigateway/api/resource/sim-rest-api-resource.js +11 -9
  5. package/dist/service/apigateway/api/sim-rest-api-view.js +3 -3
  6. package/dist/service/apigateway/api/stage/sim-rest-api-stage.js +8 -10
  7. package/dist/service/apigatewayv2/api/integration/sim-http-api-integration.js +3 -3
  8. package/dist/service/apigatewayv2/api/route/sim-http-api-route-view.js +6 -6
  9. package/dist/service/apigatewayv2/api/sim-http-api-view.js +3 -3
  10. package/dist/service/apigatewayv2/api/stage/settings/sim-http-api-stage-route-settings.js +8 -7
  11. package/dist/service/apigatewayv2/api/stage/sim-http-api-stage.js +9 -9
  12. package/dist/service/athena/engine/sim-athena-partitioned-objects.js +7 -7
  13. package/dist/service/athena/sim-athena-engine.fixture.js +3 -0
  14. package/dist/service/athena/table/sim-athena-partition-filters.js +6 -5
  15. package/dist/service/backup/command/sim-backup-authorizer.js +5 -4
  16. package/dist/service/bedrock/response/sim-bedrock-declared-content.js +5 -10
  17. package/dist/service/cloudformation/stack/update/sim-cfn-stack-resource-changes.js +19 -10
  18. package/dist/service/cloudfront/cfn/response-headers-policy/sim-cfn-cf-rh-policy-security-values.js +2 -6
  19. package/dist/service/cognito/user-pool/trigger/sim-cognito-pre-sign-up-response.js +4 -7
  20. package/dist/service/dynamodb/command/transact/sim-dynamodb-transact-write.js +34 -25
  21. package/dist/service/dynamodb/secondary-index/sim-dynamodb-index-limits.js +5 -4
  22. package/dist/service/dynamodb/stream/sim-dynamodb-stream-shard-iterator.js +1 -3
  23. package/dist/service/dynamodb/time-to-live/sim-dynamodb-time-to-live.js +4 -3
  24. package/dist/service/iam/authorize/context/sim-iam-auth-z-allow-requirement.js +6 -6
  25. package/dist/service/kinesis/stream/sim-kinesis-shard-iterator.js +1 -3
  26. package/dist/service/lambda/destination/sim-lambda-destination-record.js +7 -7
  27. package/dist/service/lambda/function/outbound/sim-lambda-aws-api-outbound.d.ts +7 -1
  28. package/dist/service/lambda/function/outbound/sim-lambda-aws-api-outbound.js +15 -7
  29. package/dist/service/lambda/function/outbound/sim-lambda-http2-session.d.ts +3 -0
  30. package/dist/service/lambda/function/outbound/sim-lambda-http2-session.js +4 -0
  31. package/dist/service/lambda/function/policy/sim-lambda-permission.js +15 -14
  32. package/dist/service/lambda/metric/sim-lambda-function-metrics.js +11 -9
  33. package/dist/service/logs/metric/sim-logs-metric-filter.js +1 -8
  34. package/dist/service/route53/dns/answer/sim-route53-dns-zone-finder.js +5 -4
  35. package/dist/service/route53/resolve/sim-r53-zone-record-finder.js +8 -6
  36. package/dist/service/s3/bucket/notification/sim-s3-notification-filter.js +4 -7
  37. package/dist/service/s3/bucket/sim-s3-bucket.d.ts +8 -0
  38. package/dist/service/s3/bucket/sim-s3-bucket.js +11 -0
  39. package/dist/service/s3/bucket/sim-s3-key-writes.d.ts +16 -0
  40. package/dist/service/s3/bucket/sim-s3-key-writes.js +43 -0
  41. package/dist/service/s3/bucket/versioning/sim-s3-bucket-versioning.js +1 -3
  42. package/dist/service/s3/command/complete-multipart-upload/complete-multipart-upload.command.d.ts +2 -1
  43. package/dist/service/s3/command/complete-multipart-upload/complete-multipart-upload.handler.js +5 -1
  44. package/dist/service/s3/command/copy-object/copy-object-precondition.d.ts +23 -0
  45. package/dist/service/s3/command/copy-object/copy-object-precondition.js +34 -0
  46. package/dist/service/s3/command/copy-object/copy-object.command.d.ts +3 -1
  47. package/dist/service/s3/command/copy-object/copy-object.handler.d.ts +4 -0
  48. package/dist/service/s3/command/copy-object/copy-object.handler.js +11 -1
  49. package/dist/service/s3/command/object/sim-s3-write-precondition.d.ts +34 -0
  50. package/dist/service/s3/command/object/sim-s3-write-precondition.js +47 -0
  51. package/dist/service/s3/command/put-object/put-object.command.d.ts +2 -1
  52. package/dist/service/s3/command/put-object/put-object.handler.js +5 -1
  53. package/dist/service/s3/error/sim-s3.error.d.ts +10 -0
  54. package/dist/service/s3/error/sim-s3.error.js +12 -0
  55. package/dist/service/s3/object/s3-object-listing.js +4 -3
  56. package/dist/service/s3/serve/api/sim-s3-api-input.d.ts +4 -0
  57. package/dist/service/s3/serve/api/sim-s3-api-input.js +10 -0
  58. package/dist/service/s3/serve/api/sim-s3-api-multipart-input.js +2 -0
  59. package/dist/service/s3/serve/api/sim-s3-api-object-input.d.ts +6 -0
  60. package/dist/service/s3/serve/api/sim-s3-api-object-input.js +34 -2
  61. package/dist/service/s3/storage/filesystem/s3-filesystem-object-keys.js +9 -8
  62. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-template.test-support.js +15 -23
  63. package/dist/service/sqs/message/sim-sqs-message.js +3 -3
  64. package/dist/service/stepfunctions/machine/sim-state-machine.js +4 -3
  65. package/dist/util/schedule/cron/sim-cron-field-bounds.js +1 -1
  66. package/docs/services/s3/README.md +68 -3
  67. package/package.json +2 -2
@@ -53,10 +53,10 @@ export class SimMessageLogConsole {
53
53
  const medium = message.medium === "EMAIL" ? "email" : "SMS";
54
54
  const lines = [
55
55
  `sim Cognito ${message.userPoolId}: ${medium} to ${message.recipient} (${message.occasion})`,
56
+ ...(message.subject === undefined
57
+ ? []
58
+ : [`${bodyIndent}Subject: ${message.subject}`]),
56
59
  ];
57
- if (message.subject !== undefined) {
58
- lines.push(`${bodyIndent}Subject: ${message.subject}`);
59
- }
60
60
  return [...lines, ...indented(message.body)];
61
61
  }
62
62
  /**
@@ -31,10 +31,10 @@ export class SimRestApiDeployment {
31
31
  const view = {
32
32
  id: this.deploymentId,
33
33
  createdDate: new Date(this.createdDate),
34
+ ...(this.description !== undefined && {
35
+ description: this.description,
36
+ }),
34
37
  };
35
- if (this.description !== undefined) {
36
- view.description = this.description;
37
- }
38
38
  return view;
39
39
  }
40
40
  }
@@ -50,19 +50,19 @@ export class SimRestApiMethod {
50
50
  httpMethod: this.httpMethod,
51
51
  authorizationType: this.authorizationType,
52
52
  apiKeyRequired: this.apiKeyRequired,
53
+ ...(this.operationName !== undefined && {
54
+ operationName: this.operationName,
55
+ }),
56
+ ...(this.authorizerId !== undefined && {
57
+ authorizerId: this.authorizerId,
58
+ }),
59
+ ...(!this.authorizationScopes.isEmpty && {
60
+ authorizationScopes: [...this.authorizationScopes.values],
61
+ }),
62
+ ...(this.integration !== undefined && {
63
+ methodIntegration: this.integration.view(),
64
+ }),
53
65
  };
54
- if (this.operationName !== undefined) {
55
- view.operationName = this.operationName;
56
- }
57
- if (this.authorizerId !== undefined) {
58
- view.authorizerId = this.authorizerId;
59
- }
60
- if (!this.authorizationScopes.isEmpty) {
61
- view.authorizationScopes = [...this.authorizationScopes.values];
62
- }
63
- if (this.integration !== undefined) {
64
- view.methodIntegration = this.integration.view();
65
- }
66
66
  return view;
67
67
  }
68
68
  }
@@ -71,16 +71,18 @@ export class SimRestApiResource {
71
71
  const view = {
72
72
  id: this.resourceId,
73
73
  path: this.path,
74
+ ...(this.parentId !== undefined && { parentId: this.parentId }),
75
+ ...(this.pathPart !== undefined && {
76
+ pathPart: this.pathPart.pathPart,
77
+ }),
78
+ ...(options.methods === true &&
79
+ this.methods.size > 0 && {
80
+ resourceMethods: Object.fromEntries(this.listMethods().map((method) => [
81
+ method.httpMethod,
82
+ method.view(),
83
+ ])),
84
+ }),
74
85
  };
75
- if (this.parentId !== undefined) {
76
- view.parentId = this.parentId;
77
- }
78
- if (this.pathPart !== undefined) {
79
- view.pathPart = this.pathPart.pathPart;
80
- }
81
- if (options.methods === true && this.methods.size > 0) {
82
- view.resourceMethods = Object.fromEntries(this.listMethods().map((method) => [method.httpMethod, method.view()]));
83
- }
84
86
  return view;
85
87
  }
86
88
  }
@@ -11,9 +11,9 @@ export function simRestApiView(restApi) {
11
11
  createdDate: new Date(restApi.createdDate),
12
12
  rootResourceId: restApi.rootResource.resourceId,
13
13
  disableExecuteApiEndpoint: restApi.disableExecuteApiEndpoint,
14
+ ...(restApi.description !== undefined && {
15
+ description: restApi.description,
16
+ }),
14
17
  };
15
- if (restApi.description !== undefined) {
16
- view.description = restApi.description;
17
- }
18
18
  return view;
19
19
  }
@@ -59,22 +59,20 @@ export class SimRestApiStage {
59
59
  * the stored one could change when the stage says it was created.
60
60
  */
61
61
  view() {
62
+ const methodSettings = this.methodSettings?.view();
62
63
  const view = {
63
64
  stageName: this.stageName,
64
65
  deploymentId: this.deploymentId,
65
66
  createdDate: new Date(this.createdDate),
66
67
  lastUpdatedDate: new Date(this.lastUpdatedDate),
68
+ ...(Object.keys(this.variables).length > 0 && {
69
+ variables: { ...this.variables },
70
+ }),
71
+ ...(this.description !== undefined && {
72
+ description: this.description,
73
+ }),
74
+ ...(methodSettings !== undefined && { methodSettings }),
67
75
  };
68
- if (Object.keys(this.variables).length > 0) {
69
- view.variables = { ...this.variables };
70
- }
71
- if (this.description !== undefined) {
72
- view.description = this.description;
73
- }
74
- const methodSettings = this.methodSettings?.view();
75
- if (methodSettings !== undefined) {
76
- view.methodSettings = methodSettings;
77
- }
78
76
  return view;
79
77
  }
80
78
  }
@@ -44,10 +44,10 @@ export class SimHttpApiIntegration {
44
44
  IntegrationType: this.integrationType,
45
45
  IntegrationUri: this.integrationUri,
46
46
  PayloadFormatVersion: this.payloadFormatVersion,
47
+ ...(this.description !== undefined && {
48
+ Description: this.description,
49
+ }),
47
50
  };
48
- if (this.description !== undefined) {
49
- view.Description = this.description;
50
- }
51
51
  return view;
52
52
  }
53
53
  }
@@ -7,12 +7,12 @@ export function simHttpApiRouteView(route) {
7
7
  RouteKey: route.routeKey,
8
8
  Target: route.target,
9
9
  AuthorizationType: route.authorizationType,
10
+ ...(route.authorizerId !== undefined && {
11
+ AuthorizerId: route.authorizerId,
12
+ }),
13
+ ...(!route.authorizationScopes.isEmpty && {
14
+ AuthorizationScopes: [...route.authorizationScopes.values],
15
+ }),
10
16
  };
11
- if (route.authorizerId !== undefined) {
12
- view.AuthorizerId = route.authorizerId;
13
- }
14
- if (!route.authorizationScopes.isEmpty) {
15
- view.AuthorizationScopes = [...route.authorizationScopes.values];
16
- }
17
17
  return view;
18
18
  }
@@ -14,9 +14,9 @@ export function simHttpApiView(parts) {
14
14
  ProtocolType: parts.protocolType,
15
15
  CreatedDate: new Date(parts.createdDate),
16
16
  DisableExecuteApiEndpoint: parts.disableExecuteApiEndpoint,
17
+ ...(parts.description !== undefined && {
18
+ Description: parts.description,
19
+ }),
17
20
  };
18
- if (parts.description !== undefined) {
19
- view.Description = parts.description;
20
- }
21
21
  return view;
22
22
  }
@@ -38,13 +38,14 @@ export class SimHttpApiStageRouteSettings {
38
38
  * What CreateStage and GetStages report of these settings.
39
39
  */
40
40
  view() {
41
- const view = {};
42
- if (this.#defaultRouteSettings !== undefined) {
43
- view.DefaultRouteSettings = { ...this.#defaultRouteSettings };
44
- }
45
- if (this.#routeSettings.size > 0) {
46
- view.RouteSettings = Object.fromEntries(this.#routeSettings);
47
- }
41
+ const view = {
42
+ ...(this.#defaultRouteSettings !== undefined && {
43
+ DefaultRouteSettings: { ...this.#defaultRouteSettings },
44
+ }),
45
+ ...(this.#routeSettings.size > 0 && {
46
+ RouteSettings: Object.fromEntries(this.#routeSettings),
47
+ }),
48
+ };
48
49
  return view;
49
50
  }
50
51
  /**
@@ -56,16 +56,16 @@ export class SimHttpApiStage {
56
56
  AutoDeploy: this.autoDeploy,
57
57
  CreatedDate: new Date(this.createdDate),
58
58
  ...this.routeSettings?.view(),
59
+ ...(Object.keys(this.stageVariables).length > 0 && {
60
+ StageVariables: { ...this.stageVariables },
61
+ }),
62
+ ...(this.description !== undefined && {
63
+ Description: this.description,
64
+ }),
65
+ ...(this.accessLogSettings !== undefined && {
66
+ AccessLogSettings: this.accessLogSettings.view(),
67
+ }),
59
68
  };
60
- if (Object.keys(this.stageVariables).length > 0) {
61
- view.StageVariables = { ...this.stageVariables };
62
- }
63
- if (this.description !== undefined) {
64
- view.Description = this.description;
65
- }
66
- if (this.accessLogSettings !== undefined) {
67
- view.AccessLogSettings = this.accessLogSettings.view();
68
- }
69
69
  return view;
70
70
  }
71
71
  }
@@ -10,16 +10,16 @@ export async function simAthenaPartitionedObjects(listing, partitions) {
10
10
  values: partition.values,
11
11
  objects: await simAthenaObjectsUnder(listing, partition.prefix),
12
12
  })));
13
+ const reached = listed.flatMap((partition) => partition.objects.map((object) => ({ object, values: partition.values })));
13
14
  const seen = new Set();
14
15
  const objects = [];
15
- for (const partition of listed) {
16
- for (const object of partition.objects) {
17
- const identity = `${object.bucket}/${object.key}`;
18
- if (!seen.has(identity)) {
19
- seen.add(identity);
20
- objects.push({ object, values: partition.values });
21
- }
16
+ for (const entry of reached) {
17
+ const identity = `${entry.object.bucket}/${entry.object.key}`;
18
+ if (seen.has(identity)) {
19
+ continue;
22
20
  }
21
+ seen.add(identity);
22
+ objects.push(entry);
23
23
  }
24
24
  return objects;
25
25
  }
@@ -87,6 +87,9 @@ const writeCompressors = {
87
87
  ZSTD: (bytes) => new Uint8Array(zstdCompressSync(bytes)),
88
88
  BROTLI: (bytes) => new Uint8Array(brotliCompressSync(bytes)),
89
89
  DEFLATE: (bytes) => new Uint8Array(deflateSync(bytes)),
90
+ // A label without the compression. The reader has no LZ4 decompressor, and
91
+ // a file it has to turn down needs only to claim the codec.
92
+ LZ4_RAW: (bytes) => bytes,
90
93
  };
91
94
  /**
92
95
  * Put one Parquet object under the logs Bucket.
@@ -49,11 +49,12 @@ export function simAthenaPartitionFilters(sql) {
49
49
  }
50
50
  continue;
51
51
  }
52
- if (operator?.kind === "word" && operator.text === "in") {
53
- const values = literalList(tokens, position + 2);
54
- if (values !== undefined) {
55
- narrow(byColumn, token.text, values);
56
- }
52
+ if (operator?.kind !== "word" || operator.text !== "in") {
53
+ continue;
54
+ }
55
+ const values = literalList(tokens, position + 2);
56
+ if (values !== undefined) {
57
+ narrow(byColumn, token.text, values);
57
58
  }
58
59
  }
59
60
  for (const name of simAthenaNegatedColumns(tokens)) {
@@ -15,10 +15,11 @@ export class SimBackupAuthorizer {
15
15
  resource,
16
16
  caller: options?.caller,
17
17
  });
18
- if (decision.isDenied) {
19
- const caller = this.callerIdentifier.format(decision.caller.principal);
20
- throw new SimBackupAccessDeniedException(`User: ${caller} is not authorized to perform: ${action} on ` +
21
- `resource: ${resource}`);
18
+ if (!decision.isDenied) {
19
+ return;
22
20
  }
21
+ const caller = this.callerIdentifier.format(decision.caller.principal);
22
+ throw new SimBackupAccessDeniedException(`User: ${caller} is not authorized to perform: ${action} on ` +
23
+ `resource: ${resource}`);
23
24
  }
24
25
  }
@@ -19,16 +19,11 @@ function checkedBlock(subject, block) {
19
19
  * themselves.
20
20
  */
21
21
  function namedMessageMembers(declared) {
22
- const named = [];
23
- if (declared.text !== undefined) {
24
- named.push("text");
25
- }
26
- if (declared.chunks !== undefined) {
27
- named.push("chunks");
28
- }
29
- if (declared.content !== undefined) {
30
- named.push("content");
31
- }
22
+ const named = [
23
+ ...(declared.text === undefined ? [] : ["text"]),
24
+ ...(declared.chunks === undefined ? [] : ["chunks"]),
25
+ ...(declared.content === undefined ? [] : ["content"]),
26
+ ];
32
27
  return named;
33
28
  }
34
29
  function requireOneMessageMember(subject, declared) {
@@ -51,22 +51,31 @@ export function simCfnStackReplacedLogicalIds(properties) {
51
51
  * those.
52
52
  */
53
53
  function spreadToDependents(properties) {
54
- const { current, updated, replaced } = properties;
55
54
  // Each pass replaces the Resources naming one already being replaced, until a
56
55
  // pass finds none, which is the end of the dependency chain.
57
56
  let spreading = true;
58
57
  while (spreading) {
59
- spreading = false;
60
- for (const [logicalId, resource] of updated) {
61
- const spreads = current.has(logicalId) &&
62
- !replaced.has(logicalId) &&
63
- resource.dependencies().some((dependency) => replaced.has(dependency));
64
- if (spreads) {
65
- replaced.add(logicalId);
66
- spreading = true;
67
- }
58
+ spreading = spreadOnePass(properties);
59
+ }
60
+ }
61
+ /**
62
+ * Replace the Resources naming one already being replaced, saying whether there
63
+ * were any.
64
+ */
65
+ function spreadOnePass(properties) {
66
+ const { current, updated, replaced } = properties;
67
+ let spreading = false;
68
+ for (const [logicalId, resource] of updated) {
69
+ const spreads = current.has(logicalId) &&
70
+ !replaced.has(logicalId) &&
71
+ resource.dependencies().some((dependency) => replaced.has(dependency));
72
+ if (!spreads) {
73
+ continue;
68
74
  }
75
+ replaced.add(logicalId);
76
+ spreading = true;
69
77
  }
78
+ return spreading;
70
79
  }
71
80
  /**
72
81
  * The logical IDs whose resolved template entry differs from the deployed one.
@@ -19,13 +19,9 @@ const referrerPolicyValue = (item, context, refuse) => requiredEnum(item, "Refer
19
19
  const strictTransportSecurityValue = (item, context, refuse) => {
20
20
  const directives = [
21
21
  `max-age=${requiredInteger(item, "AccessControlMaxAgeSec", context, refuse)}`,
22
+ ...(item["IncludeSubdomains"] === true ? ["includeSubDomains"] : []),
23
+ ...(item["Preload"] === true ? ["preload"] : []),
22
24
  ];
23
- if (item["IncludeSubdomains"] === true) {
24
- directives.push("includeSubDomains");
25
- }
26
- if (item["Preload"] === true) {
27
- directives.push("preload");
28
- }
29
25
  return directives.join("; ");
30
26
  };
31
27
  /**
@@ -37,13 +37,10 @@ export class SimCognitoPreSignUpResponse {
37
37
  * The attributes the handler asked to have marked verified.
38
38
  */
39
39
  get verifiedAttributeNames() {
40
- const names = [];
41
- if (this.autoVerifyEmail) {
42
- names.push("email");
43
- }
44
- if (this.autoVerifyPhone) {
45
- names.push("phone_number");
46
- }
40
+ const names = [
41
+ ...(this.autoVerifyEmail ? ["email"] : []),
42
+ ...(this.autoVerifyPhone ? ["phone_number"] : []),
43
+ ];
47
44
  return names;
48
45
  }
49
46
  /**
@@ -32,30 +32,39 @@ export function readSimDynamoDbTransactWrite(item) {
32
32
  */
33
33
  function readersOf(item) {
34
34
  const { Put: put, Update: update, Delete: remove, ConditionCheck: check, } = item;
35
- const readers = [];
36
- if (put !== undefined) {
37
- readers.push({
38
- name: "Put",
39
- read: () => readSimDynamoDbTransactPut(put),
40
- });
41
- }
42
- if (update !== undefined) {
43
- readers.push({
44
- name: "Update",
45
- read: () => readSimDynamoDbTransactUpdate(update),
46
- });
47
- }
48
- if (remove !== undefined) {
49
- readers.push({
50
- name: "Delete",
51
- read: () => readSimDynamoDbTransactDelete(remove),
52
- });
53
- }
54
- if (check !== undefined) {
55
- readers.push({
56
- name: "ConditionCheck",
57
- read: () => readSimDynamoDbTransactConditionCheck(check),
58
- });
59
- }
35
+ const readers = [
36
+ ...(put === undefined
37
+ ? []
38
+ : [
39
+ {
40
+ name: "Put",
41
+ read: () => readSimDynamoDbTransactPut(put),
42
+ },
43
+ ]),
44
+ ...(update === undefined
45
+ ? []
46
+ : [
47
+ {
48
+ name: "Update",
49
+ read: () => readSimDynamoDbTransactUpdate(update),
50
+ },
51
+ ]),
52
+ ...(remove === undefined
53
+ ? []
54
+ : [
55
+ {
56
+ name: "Delete",
57
+ read: () => readSimDynamoDbTransactDelete(remove),
58
+ },
59
+ ]),
60
+ ...(check === undefined
61
+ ? []
62
+ : [
63
+ {
64
+ name: "ConditionCheck",
65
+ read: () => readSimDynamoDbTransactConditionCheck(check),
66
+ },
67
+ ]),
68
+ ];
60
69
  return readers;
61
70
  }
@@ -73,9 +73,10 @@ export function assertSimDynamoDbIndexAddable(elements, added) {
73
73
  */
74
74
  export function assertSimDynamoDbProjectedAttributeCount(elements) {
75
75
  const projected = elements.reduce((total, index) => total + index.projection.nonKeyAttributeCount, 0);
76
- if (projected > maxProjectedAttributes) {
77
- const most = maxProjectedAttributes.toString();
78
- throw new SimDynamoDbValidationException(`${projected.toString()} NonKeyAttributes are projected across the ` +
79
- `table's indexes, and a table projects at most ${most}`);
76
+ if (projected <= maxProjectedAttributes) {
77
+ return;
80
78
  }
79
+ const most = maxProjectedAttributes.toString();
80
+ throw new SimDynamoDbValidationException(`${projected.toString()} NonKeyAttributes are projected across the ` +
81
+ `table's indexes, and a table projects at most ${most}`);
81
82
  }
@@ -29,9 +29,7 @@ function readPosition(value) {
29
29
  if (typeof sequenceNumber !== "string") {
30
30
  refuse();
31
31
  }
32
- return kind === "at"
33
- ? { kind: "at", sequenceNumber }
34
- : { kind: "after", sequenceNumber };
32
+ return { kind: kind === "at" ? "at" : "after", sequenceNumber };
35
33
  }
36
34
  /**
37
35
  * The opaque token a caller is handed to read on from a place.
@@ -61,10 +61,11 @@ export class SimDynamoDbTimeToLive {
61
61
  this.#status = "ENABLED";
62
62
  return;
63
63
  }
64
- if (this.#status === "DISABLING") {
65
- this.#status = "DISABLED";
66
- this.#attributeName = undefined;
64
+ if (this.#status !== "DISABLING") {
65
+ return;
67
66
  }
67
+ this.#status = "DISABLED";
68
+ this.#attributeName = undefined;
68
69
  }
69
70
  /**
70
71
  * Describe this time to live the way DynamoDB reports it.
@@ -15,13 +15,13 @@ export class SimIamAuthZAllowRequirement {
15
15
  resolve(callerAccount, input) {
16
16
  const requirements = [
17
17
  callerAccount.allowRequirement,
18
+ ...(input.requiresResourcePolicyAllow === true
19
+ ? [new SimIamMandatoryResourcePolicyRequirement()]
20
+ : []),
21
+ ...(input.withCallerPermissions === true
22
+ ? [new SimIamCallerPermissionRequirement()]
23
+ : []),
18
24
  ];
19
- if (input.requiresResourcePolicyAllow === true) {
20
- requirements.push(new SimIamMandatoryResourcePolicyRequirement());
21
- }
22
- if (input.withCallerPermissions === true) {
23
- requirements.push(new SimIamCallerPermissionRequirement());
24
- }
25
25
  return new SimIamEveryAllowRequirement(requirements);
26
26
  }
27
27
  }
@@ -39,9 +39,7 @@ function readPosition(value) {
39
39
  if (typeof sequenceNumber !== "string") {
40
40
  refuse();
41
41
  }
42
- return kind === "at"
43
- ? { kind: "at", sequenceNumber }
44
- : { kind: "after", sequenceNumber };
42
+ return { kind: kind === "at" ? "at" : "after", sequenceNumber };
45
43
  }
46
44
  /**
47
45
  * The opaque token a caller is handed to read on from a place.
@@ -13,13 +13,13 @@ export function makeSimLambdaDestinationRecord(properties) {
13
13
  },
14
14
  requestPayload: properties.requestPayload,
15
15
  responsePayload: properties.responsePayload,
16
+ ...(properties.ran && {
17
+ responseContext: {
18
+ statusCode: 200,
19
+ executedVersion: properties.executedVersion,
20
+ functionError: properties.functionError,
21
+ },
22
+ }),
16
23
  };
17
- if (properties.ran) {
18
- record.responseContext = {
19
- statusCode: 200,
20
- executedVersion: properties.executedVersion,
21
- functionError: properties.functionError,
22
- };
23
- }
24
24
  return record;
25
25
  }
@@ -35,9 +35,10 @@ interface SimLambdaAwsApiOutboundProperties {
35
35
  * operation it names.
36
36
  */
37
37
  export declare class SimLambdaAwsApiOutbound implements SimLambdaOutboundHttp {
38
+ private readonly simAws;
38
39
  private readonly dispatcher;
39
40
  private readonly s3;
40
- constructor(properties: SimLambdaAwsApiOutboundProperties);
41
+ constructor({ simAws, regionName }: SimLambdaAwsApiOutboundProperties);
41
42
  /**
42
43
  * Whether a hostname is one of the AWS service API endpoints.
43
44
  */
@@ -51,6 +52,11 @@ export declare class SimLambdaAwsApiOutbound implements SimLambdaOutboundHttp {
51
52
  * credentials the runtime puts in the environment, and the invocation is
52
53
  * already running as the execution Role, the ambient caller every other call
53
54
  * out of function code runs as.
55
+ *
56
+ * Every answer is stamped with simulated time, as real AWS stamps every API
57
+ * response with server time. The SDK corrects its clock skew from that
58
+ * header, and an answer missing it would be stamped with host time by the
59
+ * HTTP/2 server answering it.
54
60
  */
55
61
  fetch(request: Request): Promise<Response>;
56
62
  }
@@ -75,11 +75,13 @@ export function isSimAwsApiRequest(request) {
75
75
  * operation it names.
76
76
  */
77
77
  export class SimLambdaAwsApiOutbound {
78
+ simAws;
78
79
  dispatcher;
79
80
  s3;
80
- constructor(properties) {
81
- this.dispatcher = new SimSdkWireDispatcher(properties.simAws, properties.regionName);
82
- this.s3 = new SimS3ApiEndpoint({ simAws: properties.simAws });
81
+ constructor({ simAws, regionName }) {
82
+ this.simAws = simAws;
83
+ this.dispatcher = new SimSdkWireDispatcher(simAws, regionName);
84
+ this.s3 = new SimS3ApiEndpoint({ simAws });
83
85
  }
84
86
  /**
85
87
  * Whether a hostname is one of the AWS service API endpoints.
@@ -96,13 +98,19 @@ export class SimLambdaAwsApiOutbound {
96
98
  * credentials the runtime puts in the environment, and the invocation is
97
99
  * already running as the execution Role, the ambient caller every other call
98
100
  * out of function code runs as.
101
+ *
102
+ * Every answer is stamped with simulated time, as real AWS stamps every API
103
+ * response with server time. The SDK corrects its clock skew from that
104
+ * header, and an answer missing it would be stamped with host time by the
105
+ * HTTP/2 server answering it.
99
106
  */
100
107
  async fetch(request) {
101
108
  const wireRequest = await simLambdaOutboundWireRequest(request);
102
109
  const scope = readSimSdkWireCredentialScope(wireRequest);
103
- if (scope?.signingName === s3SigningName) {
104
- return await this.s3.handle(request, wireRequest.body, undefined, scope.regionName);
105
- }
106
- return simLambdaOutboundWireResponse(await this.dispatcher.dispatch(wireRequest));
110
+ const response = scope?.signingName === s3SigningName
111
+ ? await this.s3.handle(request, wireRequest.body, undefined, scope.regionName)
112
+ : simLambdaOutboundWireResponse(await this.dispatcher.dispatch(wireRequest));
113
+ response.headers.set("date", this.simAws.now().toUTCString());
114
+ return response;
107
115
  }
108
116
  }
@@ -26,6 +26,9 @@ export declare class SimLambdaHttp2Session {
26
26
  *
27
27
  * A request the simulation cannot answer fails the client's stream with the
28
28
  * error that explains it, which is what the SDK rejects the call with.
29
+ *
30
+ * The answer carries the `date` the simulation gave it, or none. The server
31
+ * would otherwise date it from the host clock.
29
32
  */
30
33
  private respond;
31
34
  }