@kensio/yulin 1.21.7 → 1.21.9

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 (99) hide show
  1. package/README.md +22 -2
  2. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-properties.js +2 -0
  3. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-rules.js +1 -1
  4. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.d.ts +2 -0
  5. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.js +4 -0
  6. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-refusals.js +0 -5
  7. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.d.ts +2 -0
  8. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.js +2 -0
  9. package/dist/service/lambda/command/event-source-mapping/sim-lambda-event-source-mapping-commands.d.ts +2 -0
  10. package/dist/service/lambda/destination/sim-lambda-destination-targets.d.ts +2 -1
  11. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.d.ts +0 -4
  12. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.js +10 -15
  13. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.d.ts +1 -6
  14. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.js +9 -27
  15. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-polling.d.ts +19 -0
  16. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-polling.js +27 -0
  17. package/dist/service/lambda/event-source/poll/sim-lambda-event-source-function.d.ts +1 -1
  18. package/dist/service/lambda/event-source/poll/sim-lambda-event-source-function.js +3 -1
  19. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-age.d.ts +13 -0
  20. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-age.js +27 -0
  21. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-info.d.ts +15 -0
  22. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-info.js +26 -0
  23. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-outcome.d.ts +1 -0
  24. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-outcome.js +7 -1
  25. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-processing.d.ts +17 -0
  26. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-processing.js +12 -0
  27. package/dist/service/lambda/event-source/poll/sim-lambda-stream-cursor.d.ts +15 -0
  28. package/dist/service/lambda/event-source/poll/sim-lambda-stream-cursor.js +28 -0
  29. package/dist/service/lambda/event-source/poll/sim-lambda-stream-expiry.d.ts +19 -0
  30. package/dist/service/lambda/event-source/poll/sim-lambda-stream-expiry.js +23 -0
  31. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-context.d.ts +3 -0
  32. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-context.js +19 -0
  33. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-destination.d.ts +15 -0
  34. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-destination.js +38 -0
  35. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-record.d.ts +41 -0
  36. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-record.js +17 -0
  37. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress-state.d.ts +21 -0
  38. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress-state.js +39 -0
  39. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress.d.ts +7 -37
  40. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress.js +22 -62
  41. package/dist/service/lambda/event-source/poll/sim-lambda-stream-retry.d.ts +4 -39
  42. package/dist/service/lambda/event-source/poll/sim-lambda-stream-retry.js +12 -64
  43. package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.d.ts +10 -3
  44. package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.js +12 -3
  45. package/dist/service/lambda/event-source/sim-lambda-stream-destination-config.d.ts +7 -0
  46. package/dist/service/lambda/event-source/sim-lambda-stream-destination-config.js +38 -0
  47. package/dist/service/lambda/event-source/stream/kinesis/sim-kinesis-event-source-streams.js +1 -0
  48. package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-reader.js +1 -0
  49. package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-shard.d.ts +1 -0
  50. package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-shard.js +7 -0
  51. package/dist/service/lambda/event-source/stream/sim-lambda-event-source-streams.d.ts +1 -0
  52. package/dist/service/lambda/index.d.ts +1 -0
  53. package/dist/service/lambda/sim-lambda-commands.js +1 -0
  54. package/dist/service/ses/command/authorize/sim-ses-authorizer.d.ts +9 -0
  55. package/dist/service/ses/command/authorize/sim-ses-authorizer.js +18 -2
  56. package/dist/service/ses/command/send/sim-ses-send-email.js +2 -1
  57. package/docs/README.md +7 -0
  58. package/docs/ai-skill/README.md +6 -1
  59. package/docs/sdk/README.md +15 -0
  60. package/docs/services/acm/README.md +24 -40
  61. package/docs/services/apigateway/README.md +52 -71
  62. package/docs/services/apigatewayv2/README.md +55 -74
  63. package/docs/services/athena/README.md +17 -26
  64. package/docs/services/backup/README.md +29 -39
  65. package/docs/services/bedrock/README.md +38 -52
  66. package/docs/services/cloudformation/README.md +43 -55
  67. package/docs/services/cloudfront/README.md +69 -95
  68. package/docs/services/cloudwatch/README.md +40 -54
  69. package/docs/services/cognito/README.md +30 -45
  70. package/docs/services/dynamodb/README.md +34 -51
  71. package/docs/services/ecr/README.md +36 -77
  72. package/docs/services/ecs/README.md +26 -46
  73. package/docs/services/elbv2/README.md +19 -29
  74. package/docs/services/eventbridge/README.md +14 -18
  75. package/docs/services/firehose/README.md +24 -32
  76. package/docs/services/glue/README.md +41 -78
  77. package/docs/services/iam/README.md +13 -15
  78. package/docs/services/kinesis/README.md +53 -93
  79. package/docs/services/kms/README.md +22 -32
  80. package/docs/services/lambda/README.md +112 -85
  81. package/docs/services/logs/README.md +41 -50
  82. package/docs/services/organizations/README.md +50 -85
  83. package/docs/services/personalize/README.md +28 -44
  84. package/docs/services/rekognition/README.md +26 -38
  85. package/docs/services/route53/README.md +17 -17
  86. package/docs/services/s3/README.md +47 -51
  87. package/docs/services/scheduler/README.md +41 -52
  88. package/docs/services/secretsmanager/README.md +27 -42
  89. package/docs/services/ses/README.md +24 -34
  90. package/docs/services/sns/README.md +18 -26
  91. package/docs/services/sqs/README.md +14 -14
  92. package/docs/services/ssm/README.md +13 -17
  93. package/docs/services/stepfunctions/README.md +18 -20
  94. package/docs/services/sts/README.md +32 -45
  95. package/docs/services/wafv2/README.md +12 -17
  96. package/docs/testing/README.md +228 -0
  97. package/docs/time/README.md +10 -0
  98. package/llms.txt +1 -0
  99. package/package.json +1 -1
@@ -1,17 +1,15 @@
1
1
  # Simulated Personalize
2
2
 
3
- Simulated Personalize holds the resources a recommendation is served from. No model is trained and
4
- no data is read, in the way simulated ACM issues certificates without producing real TLS
5
- certificates. A dataset group, a solution, a solution version and a campaign all exist, carry what
6
- the request gave them, and reach `ACTIVE` straight away.
3
+ Yulin simulates the Personalize resources and API calls used to serve recommendations. It does not
4
+ train a model or derive results from datasets. Tests declare the recommendations that a campaign or
5
+ recommender should return. Created resources become `ACTIVE` immediately.
7
6
 
8
7
  Personalize-specific types are imported from the `@kensio/yulin/personalize` subpath.
9
8
 
10
9
  ## Building the chain to a campaign
11
10
 
12
- Every runtime recommendation names a campaign, and a campaign is the far end of a chain. The dataset
13
- group holds the data, the solution picks a recipe, the solution version is the trained model, and
14
- the campaign serves it.
11
+ A campaign is built from a resource chain. A dataset group contains the datasets, a solution selects
12
+ a recipe, a solution version represents the trained model, and a campaign serves that version.
15
13
 
16
14
  ```typescript sim-personalize-campaign-chain
17
15
  /**
@@ -73,9 +71,8 @@ expects.
73
71
 
74
72
  ## Recommendations from a campaign
75
73
 
76
- A campaign answers the runtime API from results declared against it. No model is fitted and no
77
- interaction history is held. A test says what one campaign recommends for one item, and the code
78
- under test makes the calls it would make against AWS.
74
+ A campaign returns results declared during test setup. Application code still sends the same
75
+ Personalize Runtime commands it sends to AWS.
79
76
 
80
77
  The two runtime operations live on `simAws.personalizeRuntime()`, and an intercepted
81
78
  `PersonalizeRuntimeClient` reaches the same place. They arrive from a separate SDK package
@@ -140,9 +137,8 @@ const recommended = await simAws.personalizeRuntime().getRecommendations(
140
137
  console.log(recommended.itemList?.map((item) => item.itemId).join(" "));
141
138
  ```
142
139
 
143
- Results are declared per campaign, through `recommendations()` and `rankings()`. A campaign serves
144
- one solution version trained on one recipe, and two campaigns in a dataset group answer the same
145
- entry differently.
140
+ Declare results per campaign through `recommendations()` and `rankings()`. Two campaigns in the same
141
+ dataset group can return different results for the same input.
146
142
 
147
143
  An item rule is read first where the request carries an item, then a user rule, then the default.
148
144
  That order follows the recipes. `aws-similar-items` requires an `itemId` and looks at no user, and
@@ -152,9 +148,8 @@ would have used. Matching is exact, with no pattern syntax.
152
148
  `numResults` cuts a declared list to length. A request no rule matches gets the campaign's default,
153
149
  and an empty `itemList` where no default is declared.
154
150
 
155
- An item is declared as an id on its own, or as an id with a score for a test to assert on. The
156
- number comes from the declaration, and a rule that leaves it out answers with an item carrying no
157
- score.
151
+ Declare an item as an ID or as an ID with a score. An item declared without a score is returned
152
+ without one.
158
153
 
159
154
  ```typescript sim-personalize-recommendation-scores
160
155
  /**
@@ -228,10 +223,8 @@ Runtime does.
228
223
 
229
224
  ## Datasets and schemas
230
225
 
231
- A dataset belongs to a dataset group and has one of five types. The dataset ARN carries the group
232
- and the type rather than the name the request gave, which is how real Personalize builds it. One
233
- dataset group therefore holds one dataset of each type, and two dataset groups can each hold an
234
- `INTERACTIONS` dataset without colliding.
226
+ A dataset belongs to a dataset group and has one of five types. Its ARN contains the group and type,
227
+ not the requested name. Each group can contain one dataset of each type.
235
228
 
236
229
  ```typescript sim-personalize-dataset
237
230
  /**
@@ -289,8 +282,8 @@ domain dataset group refuses them here too.
289
282
 
290
283
  ## Recording events
291
284
 
292
- An event tracker is where `PutEvents` sends item interactions. It is created against a dataset
293
- group and reports a tracking ID back, and every `PutEvents` names that ID.
285
+ An event tracker records the item interactions sent through `PutEvents`. Create it for a dataset
286
+ group, then pass its tracking ID to each request.
294
287
 
295
288
  ```typescript sim-personalize-event-tracker
296
289
  /**
@@ -464,10 +457,9 @@ console.log(group.domain);
464
457
 
465
458
  ## Recommenders and their use cases
466
459
 
467
- A recommender goes straight onto a Domain dataset group, for one of the ten use cases AWS trained.
468
- There is no solution and no solution version in between. `GetRecommendations` then names a
469
- `recommenderArn` where the custom path names a `campaignArn`, and results are declared against it
470
- through the same `recommendations()` rules.
460
+ A recommender belongs directly to a domain dataset group and selects one of ten AWS use cases. It
461
+ does not use a solution or solution version. Pass its ARN to `GetRecommendations` and declare its
462
+ results with the same `recommendations()` API used for campaigns.
471
463
 
472
464
  ```typescript sim-personalize-recommender
473
465
  /**
@@ -525,9 +517,8 @@ Real Personalize trains for hours and retrains every seven days.
525
517
 
526
518
  ### The ten use cases
527
519
 
528
- The recipe ARN picks the use case, and the use case decides what a request has to carry. A request
529
- leaving out a parameter its use case requires is refused, which is what real Personalize does with
530
- it. That refusal is the part of the domain path worth simulating, and everything else here is state.
520
+ The recipe ARN selects the use case. Each use case defines whether `itemId` and `userId` are
521
+ required, optional, or unused. Requests missing a required parameter are rejected.
531
522
 
532
523
  | Use case | Recipe ARN suffix | `itemId` | `userId` |
533
524
  | ---------------------------------- | ---------------------------------------------- | -------- | -------- |
@@ -555,9 +546,6 @@ A parameter marked unused is ignored rather than matched on. A `Top picks for yo
555
546
  an `itemId` as well as its `userId` is answered from the user rule, since that is the tier real
556
547
  Personalize would have used. An optional one is matched where the request carries it.
557
548
 
558
- These are the requirements AWS documents against each use case. Both pages are worth reading before
559
- writing a request, since two of them differ from the e-commerce use case they otherwise mirror.
560
-
561
549
  ### Starting and stopping
562
550
 
563
551
  `StopRecommender` leaves the recommender in place and stops it serving. `GetRecommendations` against
@@ -602,8 +590,7 @@ and solutions gone. A group still holding one is reported as `ResourceInUseExcep
602
590
 
603
591
  `AWS::Personalize::DatasetGroup`, `AWS::Personalize::Schema`, `AWS::Personalize::Dataset`,
604
592
  `AWS::Personalize::Solution` and `AWS::Personalize::EventTracker` deploy into simulated Personalize.
605
- A project that declares them in CDK or CloudFormation can deploy the same template its application
606
- deploys, with no hand-written test setup.
593
+ A project can deploy its synthesized template without hand-written Personalize setup.
607
594
 
608
595
  Each one goes through the ordinary create command. A template and an SDK caller get the same
609
596
  validation, the same refusals and the same ARN.
@@ -710,19 +697,16 @@ wiring one resource into another reads `Fn::GetAtt`. An event tracker publishes
710
697
  does not publish fails the deploy, since answering one would let a template deploy here and fail on
711
698
  AWS.
712
699
 
713
- ### A stack stops at the solution
700
+ ### Resources without CloudFormation types
714
701
 
715
- CloudFormation has no `AWS::Personalize::Campaign` type and no `AWS::Personalize::Recommender` type.
716
- A campaign is what every runtime call names, and it is always created out of band through the SDK,
717
- the CLI or the console. A deployed stack gets as far as a solution and stops there. A test creates
718
- the solution version and the campaign itself, as the example above does. This is real Personalize
719
- behaviour and worth knowing before reading it as a gap in the simulation.
702
+ CloudFormation has no `AWS::Personalize::Campaign` or `AWS::Personalize::Recommender` type. Create
703
+ these resources through the SDK after deploying the stack, as the example above does.
720
704
 
721
705
  The domain path stops in the same place. `Domain` is a property of `AWS::Personalize::DatasetGroup`,
722
706
  and a template can declare a Domain dataset group. No `AWS::Personalize::Recommender` type exists to
723
707
  put a recommender on it.
724
708
 
725
- ### Types a stack steps over
709
+ ### Skipped resource types
726
710
 
727
711
  `AWS::Personalize::BatchInferenceJob`, `AWS::Personalize::BatchSegmentJob`,
728
712
  `AWS::Personalize::DataDeletionJob`, `AWS::Personalize::MetricAttribution` and
@@ -763,9 +747,9 @@ console.log(group?.name, group?.status);
763
747
 
764
748
  ## Deleting resources
765
749
 
766
- Deletion follows real Personalize. A dataset group holding datasets, solutions or an event tracker
767
- is reported as `ResourceInUseException`, and so is a solution a campaign still deploys. Tear a chain
768
- down from the campaign end.
750
+ Delete resources from the campaign end of the chain. A dataset group that still contains datasets,
751
+ solutions, or an event tracker raises `ResourceInUseException`. A solution still used by a campaign
752
+ raises the same error.
769
753
 
770
754
  Deleting an event tracker leaves the events it accepted recorded, as real Personalize leaves the
771
755
  interactions it wrote in the dataset behind it.
@@ -1,8 +1,8 @@
1
1
  # Simulated Rekognition
2
2
 
3
- Simulated Rekognition answers detection calls from results declared against images. A test can say
4
- which image fails moderation or holds a cat, with no image analysis happening. The bytes are never
5
- looked at.
3
+ Yulin simulates Rekognition by returning results declared for an image name or content hash. It does
4
+ not analyze the image. Tests can define labels, moderation results, faces, and face matches while
5
+ application code uses the normal Rekognition commands.
6
6
 
7
7
  Rekognition-specific types are imported from the `@kensio/yulin/rekognition` subpath.
8
8
 
@@ -67,9 +67,8 @@ const detected = await simAws
67
67
 
68
68
  ## Detecting labels in an image
69
69
 
70
- `DetectLabels` answers with the objects, scenes and concepts an image is declared to hold. Each
71
- label carries the parents, aliases, categories and instances it was declared with, and no more. A
72
- label is reported as written.
70
+ `DetectLabels` returns the objects, scenes, and concepts declared for an image. Each label contains
71
+ only the parents, aliases, categories, and instances in its declaration.
73
72
 
74
73
  ```typescript sim-rekognition-detect-labels
75
74
  /**
@@ -131,19 +130,16 @@ console.log(detected.LabelModelVersion); // "3.0"
131
130
  Labels come back in descending order of confidence, which is the order real Rekognition reports them
132
131
  in. A declared instance with no confidence of its own takes its label's.
133
132
 
134
- An image no rule matches gets the built-in default result. That is the one `Mobile Phone` label from
135
- the example response in the AWS `DetectLabels` documentation, with the parent, alias, category and
136
- bounding box AWS documents it with. It is a real Rekognition response, though which labels an
137
- unconfigured image gets is a simulator convention rather than what AWS would return for it.
133
+ An image that matches no rule gets a built-in `Mobile Phone` result based on the AWS
134
+ `DetectLabels` example response. This default is a Yulin convention. AWS results depend on the image.
138
135
 
139
- A label name fills in nothing of its own. Declaring `Cat` with no parents reports `Cat` with no
140
- parents, and declaring a `Pizza` nobody has heard of reports `Pizza`. Yulin ships no general label
141
- ontology to check a name against or to expand one from.
136
+ Yulin does not validate or expand general detection labels. Declaring `Cat` without parents returns
137
+ `Cat` without parents.
142
138
 
143
139
  ## Detecting faces in an image
144
140
 
145
- `DetectFaces` answers with the faces an image is declared to hold. A face says where it is and what
146
- it looks like, and the response carries the attributes the request asked for.
141
+ `DetectFaces` returns the faces declared for an image, including their positions and requested
142
+ attributes.
147
143
 
148
144
  ```typescript sim-rekognition-detect-faces
149
145
  /**
@@ -204,8 +200,7 @@ Faces come back in the order they were declared. An attribute with no confidence
204
200
  the face's, and a face detected at 99.4 is reported as smiling at 99.4. A face declared with no
205
201
  confidence at all is detected at the built-in one.
206
202
 
207
- An image with nobody in it is `{ faces: [] }`. Two built-in results cover the counting a test
208
- usually does:
203
+ Use `{ faces: [] }` for an image with no faces. Two built-in results cover common face-count tests:
209
204
 
210
205
  ```typescript
211
206
  import {
@@ -219,10 +214,8 @@ faces.onName("incoming/landscape.png", simRekognitionNoFaces);
219
214
  faces.onName("incoming/crowd.png", simRekognitionSeveralFaces);
220
215
  ```
221
216
 
222
- An image no rule matches gets the built-in default result. That is the one face from the example
223
- response in the AWS `DetectFaces` documentation, with the attributes and all thirty landmarks AWS
224
- documents it with. It is a real Rekognition response, though which face an unconfigured image gets is
225
- a simulator convention rather than what AWS would return for it.
217
+ An image that matches no rule gets the face from the AWS `DetectFaces` example response, including
218
+ its attributes and 30 landmarks. This default is a Yulin convention.
226
219
 
227
220
  ## Choosing the facial attributes
228
221
 
@@ -305,11 +298,10 @@ excludes the chin.
305
298
 
306
299
  ## Declaring results
307
300
 
308
- Results are declared per operation. `moderation()` holds the rules `DetectModerationLabels` answers
309
- from, `labels()` holds the rules `DetectLabels` answers from, `faces()` holds the rules
310
- `DetectFaces` answers from, and `faceMatches()` holds the rules `SearchFacesByImage` answers from.
311
- All four take the same three kinds of rule, being an exact S3 object name, an exact content hash, or
312
- anything at all.
301
+ Declare results separately for each operation. Use `moderation()` for `DetectModerationLabels`,
302
+ `labels()` for `DetectLabels`, `faces()` for `DetectFaces`, and `faceMatches()` for
303
+ `SearchFacesByImage`. Each API accepts rules for an exact S3 object name, an exact content hash, or a
304
+ default result.
313
305
 
314
306
  ```typescript sim-rekognition-moderation-rules
315
307
  /**
@@ -340,8 +332,8 @@ moderation.onHash(simRekognitionImageHash(fixture), {
340
332
  });
341
333
  ```
342
334
 
343
- A hash rule wins, then a name rule, then the default. Matching is exact, with no pattern syntax.
344
- Which rule applies never depends on how specific a pattern looks.
335
+ Rules use exact matching. Hash rules take precedence over name rules, which take precedence over the
336
+ default.
345
337
 
346
338
  A name is the `Name` in the request, the S3 object key. It is matched on its own, with the Bucket
347
339
  left out, so a rule for a key applies to that key in whichever Bucket the request names. An image
@@ -412,9 +404,8 @@ refused where the rule is written.
412
404
 
413
405
  ## Sample images
414
406
 
415
- Simulated Rekognition ships with five images whose hashes are already declared. A test uploads one
416
- through its own code and gets a known answer without registering anything. That is what makes an
417
- application generating its own object keys testable, since the test never has to know the key.
407
+ Yulin includes five small images with predeclared hash rules. Application code can upload one under
408
+ any object key and receive a known result without registering another rule.
418
409
 
419
410
  | Image | Format | Detected as |
420
411
  | -------------------------------------------------- | ------ | ------------------------------------------------- |
@@ -477,9 +468,8 @@ simAws
477
468
  .onHash(simRekognitionImageHash(sample), { labels: [] });
478
469
  ```
479
470
 
480
- The images are real 16 by 16 PNG and JPEG files, 1,909 bytes in total. The format check reads their
481
- magic bytes as it does for any other image. What they are pictures of decides nothing, since no
482
- image is looked at.
471
+ The images are valid 16 by 16 PNG and JPEG files. Rekognition checks their file signatures but does
472
+ not inspect their visual content.
483
473
 
484
474
  ## Moderation labels come back with their parents
485
475
 
@@ -772,7 +762,7 @@ ever. Filter the notification configuration by prefix or suffix, as this one doe
772
762
 
773
763
  ## Face collections
774
764
 
775
- A collection is what lets an application recognise the same person twice, where a detection answers what is in one image.
765
+ A collection stores indexed faces so an application can search for the same person later.
776
766
 
777
767
  ```typescript sim-rekognition-collections
778
768
  /**
@@ -970,9 +960,7 @@ An image is read from a Bucket in another Account when that Bucket's policy allo
970
960
  real Rekognition reads across Accounts. A Bucket in another Region is refused, as real Rekognition
971
961
  reads only Buckets in its own Region.
972
962
 
973
- ## Available functionality
974
-
975
- Simulated Rekognition currently supports:
963
+ ## Supported operations
976
964
 
977
965
  - `DetectModerationLabelsCommand`, `DetectLabelsCommand` and `DetectFacesCommand`, for an image
978
966
  supplied as `Image.Bytes` or as `Image.S3Object`
@@ -1,11 +1,12 @@
1
1
  # Simulated Route53
2
2
 
3
- Yulin includes a simulated Route53 service for tests and local development.
3
+ Yulin simulates Amazon Route 53 hosted zones, records and DNSSEC configuration for tests and local
4
+ development. You can manage them through the AWS SDK or deploy them from CloudFormation and CDK
5
+ templates. When Yulin serves the simulation on localhost, Route 53 records can route local hostnames
6
+ to simulated services such as CloudFront distributions and S3 bucket websites.
4
7
 
5
- Sim Route53 can be used directly through `SimAws`, instantiated on its own as `SimRoute53`, and used
6
- by sim CloudFormation when deploying Route53 resources from CloudFormation or CDK templates. When
7
- served on localhost, Route53 records can route custom local hostnames to other simulated AWS
8
- services, such as simulated CloudFront distributions or simulated S3 bucket websites.
8
+ Use Route 53 through `SimAws` when it should share state with other services. Use `SimRoute53`
9
+ directly when you need an isolated Route 53 simulation.
9
10
 
10
11
  ## Basic Hosted Zone usage
11
12
 
@@ -54,8 +55,8 @@ console.log(hostedZoneOut.HostedZone?.ResourceRecordSetCount);
54
55
  Hosted Zone names are normalised with a trailing dot in Route53-style outputs, so `example.test`
55
56
  becomes `example.test.`.
56
57
 
57
- Hosted Zone creation uses background tasks to move the zone to `INSYNC`. If your test needs final
58
- state, call `await simAws.backgroundTasksComplete()` before continuing.
58
+ Hosted zone creation moves the zone to `INSYNC` in a background task. Call
59
+ `await simAws.backgroundTasksComplete()` before asserting on the final state.
59
60
 
60
61
  Hosted Zone IDs are accepted in any real Route53 shape, being a `Z` prefix followed by uppercase
61
62
  alphanumerics, up to 32 characters. A real Hosted Zone ID copied out of an AWS account, such as
@@ -65,14 +66,12 @@ alphanumerics, up to 32 characters. A real Hosted Zone ID copied out of an AWS a
65
66
 
66
67
  ## Registering a Hosted Zone with a chosen ID
67
68
 
68
- `CreateHostedZoneCommand` allocates its own Hosted Zone ID, as real Route53 does, and takes none
69
- from you. When something else already decided the ID, register the Hosted Zone as part of your test
70
- setup instead.
69
+ `CreateHostedZoneCommand` allocates the hosted zone ID. When a synthesized template already contains
70
+ an ID, register that hosted zone during test setup instead.
71
71
 
72
- The usual reason is a CDK app that looks its zone up with `HostedZone.fromLookup` instead of
73
- creating it. That bakes the real Hosted Zone ID into the synthesized template, and every
74
- `AWS::Route53::RecordSet` in the template names that ID. Registering the zone first lets the
75
- template deploy as it is, with no rewriting.
72
+ For example, `HostedZone.fromLookup` writes the resolved hosted zone ID into the synthesized
73
+ template. Registering that ID before deployment lets its `AWS::Route53::RecordSet` resources deploy
74
+ without changing the template.
76
75
 
77
76
  ```typescript sim-route53-register-hosted-zone
78
77
  /**
@@ -1701,8 +1700,9 @@ await scopedRoute53.createHostedZone(
1701
1700
  );
1702
1701
  ```
1703
1702
 
1704
- Each `SimAws` instance has its own isolated state. Create a fresh instance per test, or share one
1705
- across related local setup.
1703
+ Each `SimAws` instance has its own isolated state. Application tests should normally use the instance
1704
+ from their shared [test suite setup](https://yulinsim.dev/testing/). A fresh instance remains useful
1705
+ when a test specifically needs an empty simulated account.
1706
1706
 
1707
1707
  ## Standalone SimRoute53
1708
1708
 
@@ -1732,7 +1732,7 @@ console.log(hostedZoneCreation.HostedZone?.Id);
1732
1732
  A standalone `SimRoute53` instance has its own isolated state, standing apart from any wider
1733
1733
  `SimAws` environment. Use `SimAws` when Route53 needs to resolve names to other simulated services.
1734
1734
 
1735
- ## Available functionality
1735
+ ## Supported operations
1736
1736
 
1737
1737
  Sim Route53 currently supports:
1738
1738
 
@@ -1,13 +1,12 @@
1
1
  # Simulated S3
2
2
 
3
- Yulin includes a simulated S3 service for tests and local development.
3
+ Yulin simulates S3 buckets, objects, policies, notifications and website hosting. Use
4
+ `simAws.s3()` as part of a simulated AWS environment or create a standalone `SimS3`.
5
+ `serveSimAws` exposes the S3 API and website endpoints over localhost.
4
6
 
5
- Sim S3 can be used directly through `SimAws` or instantiated on its own as `SimS3` with isolated
6
- state. Yulin can serve a simulated S3 service on localhost.
7
+ ## Create a bucket and object
7
8
 
8
- ## Basic usage
9
-
10
- Create a simulated AWS environment, get simulated S3, create a Bucket, and put an Object into it.
9
+ Create a bucket, write an object and read it back.
11
10
 
12
11
  ```typescript sim-s3-bucket
13
12
  /**
@@ -104,15 +103,15 @@ await scopedS3.createBucket(
104
103
  );
105
104
  ```
106
105
 
107
- Within one `SimAws` instance, Bucket names are globally registered across Accounts and Regions.
108
- Creating a Bucket with a name already used in another simulated Region or Account throws an error.
106
+ Bucket names are global within a `SimAws` instance. Creating the same name in another simulated
107
+ account or region fails.
109
108
 
110
- Each `SimAws` instance has its own isolated state. Create a fresh one per test or share one across
111
- all tests, as you prefer.
109
+ Each `SimAws` instance has isolated state.
112
110
 
113
- ## Listing Buckets
111
+ ## Listing buckets
114
112
 
115
- Use `ListBucketsCommand` to inspect Buckets in the selected simulated S3 scope. Each Bucket reports the instant it was created, taken from [simulated time](https://yulinsim.dev/time/) rather than the host clock.
113
+ `ListBucketsCommand` lists buckets in the selected account and region. Each bucket reports its
114
+ creation time from the [simulated clock](https://yulinsim.dev/time/).
116
115
 
117
116
  ```typescript sim-s3-list-buckets
118
117
  /**
@@ -137,17 +136,20 @@ console.log(listBucketsOutput.Buckets?.map((bucket) => bucket.Name));
137
136
  console.log(listBucketsOutput.Buckets?.[0]?.CreationDate);
138
137
  ```
139
138
 
140
- ## Asking whether something is there
139
+ ## Checking whether a bucket or object exists
141
140
 
142
- `HeadObjectCommand` reports what a read would say about an Object without returning the Object, and `HeadBucketCommand` reports whether a Bucket is there and reachable. `HeadBucket` also reports the Region it was found in.
141
+ `HeadObjectCommand` returns object metadata without the body. `HeadBucketCommand` checks that a
142
+ bucket exists and is accessible, and reports its region.
143
143
 
144
- A HEAD response carries no body, so there is no document for an error code to travel in. Real S3 answers a `HeadObject` with `403` or `404`, and a `HeadBucket` with `400`, `403` or `404`, leaving the SDK to name the failure from the status alone. The simulator answers `404` for an absent Bucket and an absent Object alike, which an SDK client raises as `NotFound`, and `403` for a caller the permission is missing for. A read distinguishes `NoSuchBucket` from `NoSuchKey`, because a read has a body to say which.
144
+ A HEAD response has no error document. Yulin returns 404 for a missing bucket or object, which the
145
+ SDK raises as `NotFound`. It returns 403 when the caller lacks permission. `GetObject` can distinguish
146
+ `NoSuchBucket` from `NoSuchKey` because its error response has a body.
145
147
 
146
148
  `HeadObject` authorizes against `s3:GetObject` and `HeadBucket` against `s3:ListBucket`, as real S3 does, so knowing something is there needs the permission to read it.
147
149
 
148
- ## Listing Objects
150
+ ## Listing objects
149
151
 
150
- Use `ListObjectsV2Command` to list the Objects in a Bucket. The simulator supports `Prefix`,
152
+ Use `ListObjectsV2Command` to list objects in a bucket. Yulin supports `Prefix`,
151
153
  `Delimiter`, `MaxKeys`, `ContinuationToken` and `StartAfter`, and answers with `Contents`,
152
154
  `CommonPrefixes`, `KeyCount`, `IsTruncated` and `NextContinuationToken`.
153
155
 
@@ -197,18 +199,16 @@ for (const object of listedObjects) {
197
199
  }
198
200
  ```
199
201
 
200
- Listings are sorted by key, and a page holds at most 1,000 keys, as in real S3. `MaxKeys` above that
201
- is lowered to it, and the response reports the page size that was actually used. A `MaxKeys` of zero
202
- returns no keys and completes the listing, and a negative one is refused with `InvalidArgument`.
202
+ Listings sort objects by key and return at most 1,000 entries. Larger `MaxKeys` values are capped at
203
+ 1,000. Zero returns an empty complete page, and a negative value raises `InvalidArgument`.
203
204
 
204
205
  A listing that found no keys has no `Contents` at all, and the example reaches for `Contents ?? []`
205
206
  for that reason. `KeyCount` is the count either way.
206
207
 
207
208
  ### Walking a truncated listing
208
209
 
209
- A truncated response carries `NextContinuationToken`, which the next request passes as
210
- `ContinuationToken`. The token is opaque, as it is in real S3. Pass it back unchanged, read nothing
211
- out of it, and simulated S3 refuses one it did not issue.
210
+ A truncated response includes `NextContinuationToken`. Pass it unchanged as `ContinuationToken` in
211
+ the next request. Yulin rejects tokens it did not issue.
212
212
 
213
213
  ```typescript sim-s3-list-objects-v2-pagination
214
214
  /**
@@ -533,9 +533,8 @@ An Object uploaded in parts gets a different form. See
533
533
 
534
534
  ## Uploading an Object in parts
535
535
 
536
- `aws s3 cp` switches to a multipart upload above eight megabytes, and `@aws-sdk/lib-storage` uploads
537
- in parts whatever the size. Sim S3 answers the six operations that path is made of, over the SDK and
538
- over a served endpoint alike.
536
+ Yulin supports multipart upload through the SDK and served S3 endpoint. This covers the operations
537
+ used by `aws s3 cp` for files above eight megabytes and by `@aws-sdk/lib-storage`.
539
538
 
540
539
  ```bash
541
540
  aws s3 cp ./big.bin s3://widgets/big.bin # 12MB, multipart under the covers
@@ -846,9 +845,8 @@ See [Serve simulated S3 on localhost](#serve-simulated-s3-on-localhost) for sett
846
845
 
847
846
  ## Deleting Objects
848
847
 
849
- Use `DeleteObjectCommand` to remove one Object, and `DeleteObjectsCommand` to remove several in one
850
- request. Both are authorized against `s3:DeleteObject` on the Object ARN. A caller allowed to read a
851
- Bucket cannot empty it.
848
+ Use `DeleteObjectCommand` to remove one object or `DeleteObjectsCommand` to remove several. Each
849
+ object requires `s3:DeleteObject` permission on its ARN.
852
850
 
853
851
  ```typescript sim-s3-delete-object
854
852
  /**
@@ -931,9 +929,9 @@ failures come back.
931
929
 
932
930
  ## Object versioning
933
931
 
934
- A versioned Bucket keeps every write of a key instead of overwriting it, and answers a delete with a
935
- marker rather than removing anything. Turn it on with `PutBucketVersioningCommand`, or with
936
- `VersioningConfiguration` on an `AWS::S3::Bucket` resource.
932
+ A versioned bucket keeps each write as a separate version. Deleting a key adds a delete marker. Enable
933
+ versioning with `PutBucketVersioningCommand` or the `VersioningConfiguration` property of an
934
+ `AWS::S3::Bucket`.
937
935
 
938
936
  ```typescript sim-s3-object-versioning
939
937
  import {
@@ -1096,12 +1094,11 @@ A delete on a versioned Bucket raises `s3:ObjectRemoved:DeleteMarkerCreated` rat
1096
1094
 
1097
1095
  ## Object Lock
1098
1096
 
1099
- Object Lock holds a version of an Object against a delete. A version can be held by a retention
1100
- period, by a legal hold or by both, and a delete naming a held version is answered with
1101
- `AccessDenied`. One way past exists and it is narrow. A `GOVERNANCE` retention period gives way to a
1102
- request carrying `BypassGovernanceRetention` from a caller allowed to use it. A `COMPLIANCE` period
1103
- and a legal hold hold against everyone, the account root included. Turn it on with `PutObjectLockConfigurationCommand`, or with
1104
- `ObjectLockEnabled` on an `AWS::S3::Bucket` resource.
1097
+ Object Lock protects an object version with a retention period, a legal hold, or both. Deleting a
1098
+ protected version raises `AccessDenied`. A caller with `s3:BypassGovernanceRetention` may bypass
1099
+ `GOVERNANCE` retention by setting `BypassGovernanceRetention`. `COMPLIANCE` retention and legal
1100
+ holds cannot be bypassed. Enable Object Lock with `PutObjectLockConfigurationCommand` or
1101
+ `ObjectLockEnabled` on an `AWS::S3::Bucket`.
1105
1102
 
1106
1103
  Object Lock holds a version, and versioning has to be on underneath it. Turning it on over a Bucket
1107
1104
  with versioning off is refused with `InvalidBucketState`, as real S3 refuses it, and a template
@@ -1256,8 +1253,8 @@ Bucket created around the property would report a default retention it never app
1256
1253
 
1257
1254
  ## Event notifications
1258
1255
 
1259
- A simulated S3 Bucket can notify a simulated Lambda function, a simulated SQS queue or a simulated
1260
- SNS topic when an Object is created or removed. The configuration is applied with
1256
+ A simulated bucket can notify Lambda, SQS or SNS when an object is created or removed. Apply the
1257
+ configuration with
1261
1258
  `PutBucketNotificationConfigurationCommand` and read back with
1262
1259
  `GetBucketNotificationConfigurationCommand`.
1263
1260
 
@@ -1360,10 +1357,10 @@ can take the `.jpg` files under a prefix while another takes the `.png` files un
1360
1357
  The rule applies across the destination groups. A function and a queue that both want the same
1361
1358
  event are refused as readily as two functions.
1362
1359
 
1363
- `PutBucketNotificationConfigurationCommand` replaces the whole configuration rather than adding to
1364
- it. `GetBucketNotificationConfigurationCommand` answers an empty configuration for a Bucket that has
1365
- none. Note that the response carries the destination groups at the top level, while the request nests
1366
- them under `NotificationConfiguration`:
1360
+ `PutBucketNotificationConfigurationCommand` replaces the complete configuration.
1361
+ `GetBucketNotificationConfigurationCommand` returns an empty configuration when none is set. The
1362
+ request nests destination groups under `NotificationConfiguration`, while the response puts them at
1363
+ the top level:
1367
1364
 
1368
1365
  ```typescript
1369
1366
  const read = await simAws
@@ -1476,9 +1473,9 @@ function is.
1476
1473
 
1477
1474
  ### To an SQS queue
1478
1475
 
1479
- A `QueueConfigurations` entry names a queue by ARN. The whole `Records` document arrives as one
1480
- message body, and a consumer parses `record.body` to get at the event. Put a Lambda event source
1481
- mapping on the queue and the chain runs end to end after one `backgroundTasksComplete()`.
1476
+ A `QueueConfigurations` entry names a queue by ARN. S3 sends the complete `Records` document as one
1477
+ message body. Add a Lambda event source mapping to consume it, then call
1478
+ `backgroundTasksComplete()` to finish the delivery chain.
1482
1479
 
1483
1480
  The queue's `Policy` attribute has to allow `sqs:SendMessage` for the `s3.amazonaws.com` service
1484
1481
  principal. S3 supplies `aws:SourceArn` and `aws:SourceAccount`. The `ArnLike` condition CDK's
@@ -1633,10 +1630,9 @@ its own policy and its own Account's IAM are what admit the Bucket. A FIFO queue
1633
1630
 
1634
1631
  ### To an SNS topic
1635
1632
 
1636
- A `TopicConfigurations` entry names a topic by ARN. The whole `Records` document is published as the
1637
- SNS `Message`, with a `Subject` of `Amazon S3 Notification`, as real S3 publishes it. A queue
1638
- subscribed to the topic therefore has two envelopes to reach through. Parse the message body for the
1639
- SNS envelope, then parse its `Message` for the S3 event.
1633
+ A `TopicConfigurations` entry names a topic by ARN. S3 publishes the complete `Records` document as
1634
+ the SNS `Message` with the subject `Amazon S3 Notification`. A subscribed queue receives an SNS
1635
+ envelope whose `Message` contains the S3 event.
1640
1636
 
1641
1637
  The topic's `Policy` attribute has to allow `sns:Publish` for the `s3.amazonaws.com` service
1642
1638
  principal. S3 supplies `aws:SourceArn` and `aws:SourceAccount`. The `ArnLike` condition CDK's