@kensio/yulin 1.21.27 → 1.21.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/eslint/cffjs2.eslint.config.js +4 -0
- package/dist/sdk/wire/sim-sdk-wire-bedrock-action.d.ts +18 -0
- package/dist/sdk/wire/sim-sdk-wire-bedrock-action.js +71 -0
- package/dist/sdk/wire/sim-sdk-wire-bedrock-input.d.ts +11 -0
- package/dist/sdk/wire/sim-sdk-wire-bedrock-input.js +45 -0
- package/dist/sdk/wire/sim-sdk-wire-bedrock.d.ts +10 -0
- package/dist/sdk/wire/sim-sdk-wire-bedrock.js +47 -0
- package/dist/sdk/wire/sim-sdk-wire-call.d.ts +30 -0
- package/dist/sdk/wire/sim-sdk-wire-call.js +32 -0
- package/dist/sdk/wire/sim-sdk-wire-dispatcher.js +7 -9
- package/dist/sdk/wire/sim-sdk-wire-event-stream.d.ts +16 -0
- package/dist/sdk/wire/sim-sdk-wire-event-stream.js +79 -0
- package/dist/sdk/wire/sim-sdk-wire-unbridged.js +2 -2
- package/dist/service/bedrock/command/authorize/sim-bedrock-authorizer.js +7 -3
- package/dist/service/cloudformation/parameters/sim-cfn-parameter-list-type.d.ts +7 -0
- package/dist/service/cloudformation/parameters/sim-cfn-parameter-list-type.js +9 -0
- package/dist/service/cloudformation/parameters/sim-cfn-parameter-values.d.ts +10 -0
- package/dist/service/cloudformation/parameters/sim-cfn-parameter-values.js +20 -0
- package/dist/service/cloudformation/parameters/sim-cfn-parameters.type.d.ts +7 -5
- package/dist/service/cloudformation/parameters/store/sim-cfn-parameter-store-value-type.js +2 -1
- package/dist/service/cloudformation/template/node/fn/join/sim-cfn-fn-join.d.ts +19 -14
- package/dist/service/cloudformation/template/node/fn/join/sim-cfn-fn-join.js +47 -28
- package/dist/service/cloudformation/template/parse/fn/join/sim-cfn-fn-join-parser.d.ts +7 -4
- package/dist/service/cloudformation/template/parse/fn/join/sim-cfn-fn-join-parser.js +11 -7
- package/dist/service/lambda/function/code/vm/sdk/sim-sdk-lambda-vm-module-provider.d.ts +2 -2
- package/dist/service/lambda/function/code/vm/sdk/sim-sdk-lambda-vm-module-provider.js +5 -9
- package/dist/service/lambda/function/code/vm/sim-lambda-vm-context.d.ts +1 -1
- package/dist/service/lambda/function/code/vm/sim-lambda-vm-context.js +11 -22
- package/dist/service/lambda/function/code/vm/sim-lambda-vm-host-globals.d.ts +4 -0
- package/dist/service/lambda/function/code/vm/sim-lambda-vm-host-globals.js +87 -0
- package/dist/service/lambda/function/invoke/sim-lambda-outbound-clients.d.ts +3 -0
- package/dist/service/lambda/function/invoke/sim-lambda-outbound-clients.js +10 -0
- package/dist/service/lambda/function/outbound/sim-lambda-http2-exchanges.d.ts +32 -0
- package/dist/service/lambda/function/outbound/sim-lambda-http2-exchanges.js +39 -0
- package/dist/service/lambda/function/outbound/sim-lambda-http2-messages.d.ts +33 -0
- package/dist/service/lambda/function/outbound/sim-lambda-http2-messages.js +87 -0
- package/dist/service/lambda/function/outbound/sim-lambda-http2-module.d.ts +27 -0
- package/dist/service/lambda/function/outbound/sim-lambda-http2-module.js +53 -0
- package/dist/service/lambda/function/outbound/sim-lambda-http2-session.d.ts +31 -0
- package/dist/service/lambda/function/outbound/sim-lambda-http2-session.js +57 -0
- package/dist/service/lambda/function/outbound/sim-lambda-transport-module.d.ts +11 -0
- package/dist/service/lambda/function/outbound/sim-lambda-transport-module.js +24 -0
- package/docs/serve/README.md +1 -1
- package/docs/services/cloudformation/README.md +28 -5
- package/docs/services/dynamodb/README.md +2 -2
- package/docs/services/lambda/README.md +18 -8
- package/docs/services/s3/README.md +1 -1
- package/docs/services/sqs/README.md +1 -1
- package/package.json +2 -2
|
@@ -13,6 +13,10 @@ export default defineConfig({
|
|
|
13
13
|
files: ["**/*.cff.js"],
|
|
14
14
|
extends: [tseslint.configs.disableTypeChecked],
|
|
15
15
|
languageOptions: {
|
|
16
|
+
// The typescript-eslint rules below read scope information only its own
|
|
17
|
+
// parser produces. Under ESLint's default parser, `no-unused-vars` takes
|
|
18
|
+
// every reference for a type-only one and reports each variable.
|
|
19
|
+
parser: tseslint.parser,
|
|
16
20
|
parserOptions: {
|
|
17
21
|
projectService: false,
|
|
18
22
|
},
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SimSdkWireRequest, SimSdkWireResponse } from "./sim-sdk-wire.types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The REST-JSON content type, for bodies and for errors.
|
|
4
|
+
*/
|
|
5
|
+
export declare const simSdkWireBedrockJsonContentType = "application/json";
|
|
6
|
+
/**
|
|
7
|
+
* How one Bedrock Runtime operation reads its input off a request and writes
|
|
8
|
+
* its output back.
|
|
9
|
+
*/
|
|
10
|
+
export interface SimSdkWireBedrockAction {
|
|
11
|
+
readonly commandName: string;
|
|
12
|
+
input(modelId: string, request: SimSdkWireRequest): unknown;
|
|
13
|
+
outputResponse(output: unknown): Promise<SimSdkWireResponse>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The invocation operations, keyed by the last segment of their path.
|
|
17
|
+
*/
|
|
18
|
+
export declare const simSdkWireBedrockActions: ReadonlyMap<string, SimSdkWireBedrockAction>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { simSdkWireConverseInput, simSdkWireInvokeInput, } from "./sim-sdk-wire-bedrock-input.js";
|
|
2
|
+
import { simSdkWireEventStreamBody, simSdkWireEventStreamContentType, } from "./sim-sdk-wire-event-stream.js";
|
|
3
|
+
import { simSdkWireOutputResponse } from "./sim-sdk-wire-response.js";
|
|
4
|
+
/**
|
|
5
|
+
* The REST-JSON content type, for bodies and for errors.
|
|
6
|
+
*/
|
|
7
|
+
export const simSdkWireBedrockJsonContentType = "application/json";
|
|
8
|
+
/**
|
|
9
|
+
* The invocation operations, keyed by the last segment of their path.
|
|
10
|
+
*/
|
|
11
|
+
export const simSdkWireBedrockActions = new Map([
|
|
12
|
+
[
|
|
13
|
+
"converse",
|
|
14
|
+
{
|
|
15
|
+
commandName: "ConverseCommand",
|
|
16
|
+
input: simSdkWireConverseInput,
|
|
17
|
+
outputResponse: (output) => Promise.resolve(simSdkWireOutputResponse(output, simSdkWireBedrockJsonContentType)),
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
[
|
|
21
|
+
"converse-stream",
|
|
22
|
+
{
|
|
23
|
+
commandName: "ConverseStreamCommand",
|
|
24
|
+
input: simSdkWireConverseInput,
|
|
25
|
+
outputResponse: async (output) => await eventStreamResponse(output.stream, {}),
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
[
|
|
29
|
+
"invoke",
|
|
30
|
+
{
|
|
31
|
+
commandName: "InvokeModelCommand",
|
|
32
|
+
input: (modelId, request) => simSdkWireInvokeInput(modelId, request, "accept"),
|
|
33
|
+
outputResponse: invokeModelResponse,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
"invoke-with-response-stream",
|
|
38
|
+
{
|
|
39
|
+
commandName: "InvokeModelWithResponseStreamCommand",
|
|
40
|
+
input: (modelId, request) => simSdkWireInvokeInput(modelId, request, "x-amzn-bedrock-accept"),
|
|
41
|
+
outputResponse: async (output) => {
|
|
42
|
+
const { body, contentType } = output;
|
|
43
|
+
return await eventStreamResponse(body, {
|
|
44
|
+
"x-amzn-bedrock-content-type": contentType,
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
]);
|
|
50
|
+
/**
|
|
51
|
+
* `InvokeModel` answers with the model's own body as it is, labelled with its
|
|
52
|
+
* content type.
|
|
53
|
+
*/
|
|
54
|
+
function invokeModelResponse(output) {
|
|
55
|
+
const { body, contentType } = output;
|
|
56
|
+
return Promise.resolve({
|
|
57
|
+
statusCode: 200,
|
|
58
|
+
headers: { "content-type": contentType },
|
|
59
|
+
body,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The streaming operations answer with an event stream body.
|
|
64
|
+
*/
|
|
65
|
+
async function eventStreamResponse(events, headers) {
|
|
66
|
+
return {
|
|
67
|
+
statusCode: 200,
|
|
68
|
+
headers: { "content-type": simSdkWireEventStreamContentType, ...headers },
|
|
69
|
+
body: await simSdkWireEventStreamBody(events),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SimSdkWireRequest } from "./sim-sdk-wire.types.js";
|
|
2
|
+
/**
|
|
3
|
+
* `Converse` and `ConverseStream` send their input as the JSON body, less the
|
|
4
|
+
* model id the path carries.
|
|
5
|
+
*/
|
|
6
|
+
export declare function simSdkWireConverseInput(modelId: string, request: SimSdkWireRequest): unknown;
|
|
7
|
+
/**
|
|
8
|
+
* The model invocations send the request body as it is, with every other
|
|
9
|
+
* member in a header.
|
|
10
|
+
*/
|
|
11
|
+
export declare function simSdkWireInvokeInput(modelId: string, request: SimSdkWireRequest, acceptHeaderName: string): unknown;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { readSimSdkWireInput } from "./sim-sdk-wire-json.js";
|
|
2
|
+
/**
|
|
3
|
+
* The Command input members `InvokeModel` and
|
|
4
|
+
* `InvokeModelWithResponseStream` carry in headers, with the header each one
|
|
5
|
+
* travels in. The two differ only in where they carry `accept`.
|
|
6
|
+
*
|
|
7
|
+
* Every one is read, including the ones the simulation refuses, so that a
|
|
8
|
+
* request naming a guardrail is refused here as it is through an intercepted
|
|
9
|
+
* client.
|
|
10
|
+
*/
|
|
11
|
+
const invokeHeaderMembers = [
|
|
12
|
+
["contentType", "content-type"],
|
|
13
|
+
["trace", "x-amzn-bedrock-trace"],
|
|
14
|
+
["guardrailIdentifier", "x-amzn-bedrock-guardrailidentifier"],
|
|
15
|
+
["guardrailVersion", "x-amzn-bedrock-guardrailversion"],
|
|
16
|
+
["performanceConfigLatency", "x-amzn-bedrock-performanceconfig-latency"],
|
|
17
|
+
["serviceTier", "x-amzn-bedrock-service-tier"],
|
|
18
|
+
["requestMetadata", "x-amzn-bedrock-request-metadata"],
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* `Converse` and `ConverseStream` send their input as the JSON body, less the
|
|
22
|
+
* model id the path carries.
|
|
23
|
+
*/
|
|
24
|
+
export function simSdkWireConverseInput(modelId, request) {
|
|
25
|
+
return { ...readSimSdkWireInput(request.body), modelId };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The model invocations send the request body as it is, with every other
|
|
29
|
+
* member in a header.
|
|
30
|
+
*/
|
|
31
|
+
export function simSdkWireInvokeInput(modelId, request, acceptHeaderName) {
|
|
32
|
+
const members = [
|
|
33
|
+
...invokeHeaderMembers,
|
|
34
|
+
["accept", acceptHeaderName],
|
|
35
|
+
].flatMap(([member, headerName]) => {
|
|
36
|
+
// oxlint-disable-next-line security/detect-object-injection -- this module's own fixed header names.
|
|
37
|
+
const value = request.headers[headerName];
|
|
38
|
+
return value === undefined ? [] : [[member, value]];
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
...Object.fromEntries(members),
|
|
42
|
+
modelId,
|
|
43
|
+
...(request.body.byteLength > 0 && { body: request.body }),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SimSdkWireCall } from "./sim-sdk-wire-call.js";
|
|
2
|
+
import type { SimSdkWireRequest } from "./sim-sdk-wire.types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Read a Bedrock Runtime model invocation, which names its operation and its
|
|
5
|
+
* model in the path rather than in a header.
|
|
6
|
+
*
|
|
7
|
+
* A request counts as one when it was signed for Bedrock, or, unsigned, sent
|
|
8
|
+
* to a Bedrock Runtime endpoint, and its path is a model invocation.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readSimSdkWireBedrockCall(request: SimSdkWireRequest): SimSdkWireCall | undefined;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { simSdkWireBedrockActions, simSdkWireBedrockJsonContentType, } from "./sim-sdk-wire-bedrock-action.js";
|
|
2
|
+
import { readSimSdkWireCredentialScope } from "./sim-sdk-wire-operation.js";
|
|
3
|
+
import { simSdkWireErrorResponse } from "./sim-sdk-wire-response.js";
|
|
4
|
+
/**
|
|
5
|
+
* The SDK `config.serviceId` of a `BedrockRuntimeClient`.
|
|
6
|
+
*/
|
|
7
|
+
const bedrockRuntimeServiceId = "Bedrock Runtime";
|
|
8
|
+
/**
|
|
9
|
+
* The SigV4 signing name Bedrock Runtime requests are signed with.
|
|
10
|
+
*/
|
|
11
|
+
const bedrockSigningName = "bedrock";
|
|
12
|
+
/**
|
|
13
|
+
* The path of a model invocation: `/model/{modelId}/{action}`, where the
|
|
14
|
+
* model id is URL-encoded and may be a whole ARN.
|
|
15
|
+
*/
|
|
16
|
+
const invocationPathPattern = /^\/model\/(?<modelId>[^/]+)\/(?<action>[a-z-]+)$/;
|
|
17
|
+
/**
|
|
18
|
+
* Read a Bedrock Runtime model invocation, which names its operation and its
|
|
19
|
+
* model in the path rather than in a header.
|
|
20
|
+
*
|
|
21
|
+
* A request counts as one when it was signed for Bedrock, or, unsigned, sent
|
|
22
|
+
* to a Bedrock Runtime endpoint, and its path is a model invocation.
|
|
23
|
+
*/
|
|
24
|
+
export function readSimSdkWireBedrockCall(request) {
|
|
25
|
+
const signingName = readSimSdkWireCredentialScope(request)?.signingName;
|
|
26
|
+
const isBedrock = signingName === undefined
|
|
27
|
+
? request.hostname.startsWith("bedrock-runtime.")
|
|
28
|
+
: signingName === bedrockSigningName;
|
|
29
|
+
if (!isBedrock || request.method.toUpperCase() !== "POST") {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const groups = invocationPathPattern.exec(request.path.split("?", 1)[0] ?? "")?.groups;
|
|
33
|
+
const action = simSdkWireBedrockActions.get(groups?.["action"] ?? "");
|
|
34
|
+
if (groups === undefined || action === undefined) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
// A malformed escape fails decoding, which is the service's answer to the
|
|
38
|
+
// request, so the model id is decoded when the input is read.
|
|
39
|
+
const encodedModelId = groups["modelId"] ?? "";
|
|
40
|
+
return {
|
|
41
|
+
serviceId: bedrockRuntimeServiceId,
|
|
42
|
+
commandName: action.commandName,
|
|
43
|
+
input: () => action.input(decodeURIComponent(encodedModelId), request),
|
|
44
|
+
outputResponse: async (output) => await action.outputResponse(output),
|
|
45
|
+
errorResponse: (error) => simSdkWireErrorResponse(error, simSdkWireBedrockJsonContentType),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SimSdkWireRequest, SimSdkWireResponse } from "./sim-sdk-wire.types.js";
|
|
2
|
+
/**
|
|
3
|
+
* One wire request read back into the Command it was serialized from, with
|
|
4
|
+
* the protocol it came in to encode the answer in.
|
|
5
|
+
*/
|
|
6
|
+
export interface SimSdkWireCall {
|
|
7
|
+
/** The SDK `config.serviceId` of the service the request is addressed to. */
|
|
8
|
+
readonly serviceId: string;
|
|
9
|
+
/** The SDK Command class name the request would have been sent as. */
|
|
10
|
+
readonly commandName: string;
|
|
11
|
+
/**
|
|
12
|
+
* The Command input. Reading it can fail on a malformed body, and that
|
|
13
|
+
* failure is the service's answer to the request, so it is read when the
|
|
14
|
+
* operation runs.
|
|
15
|
+
*/
|
|
16
|
+
input(): unknown;
|
|
17
|
+
/** The response for an output the simulated operation answered with. */
|
|
18
|
+
outputResponse(output: unknown): Promise<SimSdkWireResponse>;
|
|
19
|
+
/** The response for an error the simulated operation refused with. */
|
|
20
|
+
errorResponse(error: unknown): SimSdkWireResponse;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Read a wire request as the Command it was serialized from.
|
|
24
|
+
*
|
|
25
|
+
* Returns undefined for a request no reader here understands. The AWS JSON
|
|
26
|
+
* protocol services all name their operation in one header. Bedrock Runtime
|
|
27
|
+
* speaks REST-JSON, with the operation and model in the path, and has a
|
|
28
|
+
* reader of its own.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readSimSdkWireCall(request: SimSdkWireRequest): SimSdkWireCall | undefined;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readSimSdkWireBedrockCall } from "./sim-sdk-wire-bedrock.js";
|
|
2
|
+
import { readSimSdkWireInput } from "./sim-sdk-wire-json.js";
|
|
3
|
+
import { readSimSdkWireOperation } from "./sim-sdk-wire-operation.js";
|
|
4
|
+
import { simSdkWireErrorResponse, simSdkWireOutputResponse, } from "./sim-sdk-wire-response.js";
|
|
5
|
+
/**
|
|
6
|
+
* Read a wire request as the Command it was serialized from.
|
|
7
|
+
*
|
|
8
|
+
* Returns undefined for a request no reader here understands. The AWS JSON
|
|
9
|
+
* protocol services all name their operation in one header. Bedrock Runtime
|
|
10
|
+
* speaks REST-JSON, with the operation and model in the path, and has a
|
|
11
|
+
* reader of its own.
|
|
12
|
+
*/
|
|
13
|
+
export function readSimSdkWireCall(request) {
|
|
14
|
+
return readSimSdkWireJsonCall(request) ?? readSimSdkWireBedrockCall(request);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Read an AWS JSON protocol request, whose body is the Command input and
|
|
18
|
+
* whose response echoes the protocol version it was sent with.
|
|
19
|
+
*/
|
|
20
|
+
function readSimSdkWireJsonCall(request) {
|
|
21
|
+
const operation = readSimSdkWireOperation(request);
|
|
22
|
+
if (operation === undefined) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
const contentType = request.headers["content-type"];
|
|
26
|
+
return {
|
|
27
|
+
...operation,
|
|
28
|
+
input: () => readSimSdkWireInput(request.body),
|
|
29
|
+
outputResponse: (output) => Promise.resolve(simSdkWireOutputResponse(output, contentType)),
|
|
30
|
+
errorResponse: (error) => simSdkWireErrorResponse(error, contentType),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { SimSdkCommandDispatcher } from "../sim-sdk-command-dispatcher.js";
|
|
2
2
|
import { makeSimSdkWireClient, makeSimSdkWireCommand, } from "./sim-sdk-wire-command.js";
|
|
3
|
-
import {
|
|
4
|
-
import { readSimSdkWireCredentialScope
|
|
5
|
-
import { simSdkWireErrorResponse, simSdkWireOutputResponse, } from "./sim-sdk-wire-response.js";
|
|
3
|
+
import { readSimSdkWireCall } from "./sim-sdk-wire-call.js";
|
|
4
|
+
import { readSimSdkWireCredentialScope } from "./sim-sdk-wire-operation.js";
|
|
6
5
|
import { simSdkUnbridgedWireRequest } from "./sim-sdk-wire-unbridged.js";
|
|
7
6
|
/**
|
|
8
7
|
* Dispatches AWS API requests to simulated AWS service operations.
|
|
@@ -44,20 +43,19 @@ export class SimSdkWireDispatcher {
|
|
|
44
43
|
* relies on.
|
|
45
44
|
*/
|
|
46
45
|
async dispatch(request, caller) {
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
46
|
+
const call = readSimSdkWireCall(request);
|
|
47
|
+
if (call === undefined) {
|
|
49
48
|
throw simSdkUnbridgedWireRequest(request);
|
|
50
49
|
}
|
|
51
50
|
// The operation runs in the Region it was signed for or, unsigned, the
|
|
52
51
|
// Region of the code that sent it.
|
|
53
52
|
const scope = readSimSdkWireCredentialScope(request);
|
|
54
|
-
const contentType = request.headers["content-type"];
|
|
55
53
|
try {
|
|
56
|
-
const output = await this.dispatcher.dispatch(makeSimSdkWireCommand(
|
|
57
|
-
return
|
|
54
|
+
const output = await this.dispatcher.dispatch(makeSimSdkWireCommand(call.commandName, call.input()), makeSimSdkWireClient(call.serviceId, scope?.regionName ?? this.regionName), undefined, caller);
|
|
55
|
+
return await call.outputResponse(output);
|
|
58
56
|
}
|
|
59
57
|
catch (error) {
|
|
60
|
-
return
|
|
58
|
+
return call.errorResponse(error);
|
|
61
59
|
}
|
|
62
60
|
}
|
|
63
61
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The media type of an AWS event stream response body.
|
|
3
|
+
*/
|
|
4
|
+
export declare const simSdkWireEventStreamContentType = "application/vnd.amazon.eventstream";
|
|
5
|
+
/**
|
|
6
|
+
* Encode an event stream as the `application/vnd.amazon.eventstream` body an
|
|
7
|
+
* SDK reads it from.
|
|
8
|
+
*
|
|
9
|
+
* Each event is a union with one member set, as an SDK hands it to calling
|
|
10
|
+
* code (`{ chunk: { bytes } }` or `{ contentBlockDelta: { ... } }`). The
|
|
11
|
+
* member name is the message's event type, and its value is the JSON payload.
|
|
12
|
+
*
|
|
13
|
+
* The whole stream is read before the body is built. A simulated stream has
|
|
14
|
+
* every event available at once, so sending them together loses nothing.
|
|
15
|
+
*/
|
|
16
|
+
export declare function simSdkWireEventStreamBody(events: AsyncIterable<object>): Promise<Uint8Array>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { crc32 } from "../../util/zip/crc32.js";
|
|
2
|
+
import { simSdkWireJsonBody } from "./sim-sdk-wire-json.js";
|
|
3
|
+
/**
|
|
4
|
+
* The media type of an AWS event stream response body.
|
|
5
|
+
*/
|
|
6
|
+
export const simSdkWireEventStreamContentType = "application/vnd.amazon.eventstream";
|
|
7
|
+
/**
|
|
8
|
+
* The header value type code for a string, the only type written here.
|
|
9
|
+
*/
|
|
10
|
+
const stringHeaderType = 7;
|
|
11
|
+
/**
|
|
12
|
+
* The bytes of the prelude: the total length, the headers length and the
|
|
13
|
+
* prelude checksum, each four bytes.
|
|
14
|
+
*/
|
|
15
|
+
const preludeLength = 12;
|
|
16
|
+
/**
|
|
17
|
+
* The bytes of the checksum closing every message.
|
|
18
|
+
*/
|
|
19
|
+
const messageChecksumLength = 4;
|
|
20
|
+
/**
|
|
21
|
+
* Encode an event stream as the `application/vnd.amazon.eventstream` body an
|
|
22
|
+
* SDK reads it from.
|
|
23
|
+
*
|
|
24
|
+
* Each event is a union with one member set, as an SDK hands it to calling
|
|
25
|
+
* code (`{ chunk: { bytes } }` or `{ contentBlockDelta: { ... } }`). The
|
|
26
|
+
* member name is the message's event type, and its value is the JSON payload.
|
|
27
|
+
*
|
|
28
|
+
* The whole stream is read before the body is built. A simulated stream has
|
|
29
|
+
* every event available at once, so sending them together loses nothing.
|
|
30
|
+
*/
|
|
31
|
+
export async function simSdkWireEventStreamBody(events) {
|
|
32
|
+
const messages = [];
|
|
33
|
+
for await (const event of events) {
|
|
34
|
+
const members = Object.entries(event).filter(([, value]) => value !== undefined);
|
|
35
|
+
for (const [eventType, value] of members) {
|
|
36
|
+
messages.push(eventMessage(eventType, simSdkWireJsonBody(value)));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return Buffer.concat(messages);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Encode one event message.
|
|
43
|
+
*
|
|
44
|
+
* The layout is the prelude, the headers, the payload and a CRC-32 of
|
|
45
|
+
* everything before it. The prelude ends with a CRC-32 of its first eight
|
|
46
|
+
* bytes.
|
|
47
|
+
*/
|
|
48
|
+
function eventMessage(eventType, payload) {
|
|
49
|
+
const headers = Buffer.concat([
|
|
50
|
+
stringHeader(":event-type", eventType),
|
|
51
|
+
stringHeader(":content-type", "application/json"),
|
|
52
|
+
stringHeader(":message-type", "event"),
|
|
53
|
+
]);
|
|
54
|
+
const totalLength = preludeLength + headers.length + payload.length + messageChecksumLength;
|
|
55
|
+
const checksumOffset = totalLength - messageChecksumLength;
|
|
56
|
+
const message = Buffer.alloc(totalLength);
|
|
57
|
+
message.writeUInt32BE(totalLength, 0);
|
|
58
|
+
message.writeUInt32BE(headers.length, 4);
|
|
59
|
+
message.writeUInt32BE(crc32(message.subarray(0, 8)), 8);
|
|
60
|
+
headers.copy(message, preludeLength);
|
|
61
|
+
message.set(payload, preludeLength + headers.length);
|
|
62
|
+
message.writeUInt32BE(crc32(message.subarray(0, checksumOffset)), checksumOffset);
|
|
63
|
+
return message;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Encode one string-valued header: the name length and name, the type code,
|
|
67
|
+
* and the value length and value.
|
|
68
|
+
*/
|
|
69
|
+
function stringHeader(name, value) {
|
|
70
|
+
const nameBytes = Buffer.from(name);
|
|
71
|
+
const valueBytes = Buffer.from(value);
|
|
72
|
+
const header = Buffer.alloc(4 + nameBytes.length + valueBytes.length);
|
|
73
|
+
header.writeUInt8(nameBytes.length, 0);
|
|
74
|
+
nameBytes.copy(header, 1);
|
|
75
|
+
header.writeUInt8(stringHeaderType, 1 + nameBytes.length);
|
|
76
|
+
header.writeUInt16BE(valueBytes.length, 2 + nameBytes.length);
|
|
77
|
+
valueBytes.copy(header, 4 + nameBytes.length);
|
|
78
|
+
return header;
|
|
79
|
+
}
|
|
@@ -16,8 +16,8 @@ import { readSimSdkWireCredentialScope } from "./sim-sdk-wire-operation.js";
|
|
|
16
16
|
export function simSdkUnbridgedWireRequest(request) {
|
|
17
17
|
const service = readSimSdkWireCredentialScope(request)?.signingName ?? request.hostname;
|
|
18
18
|
return new SimSdkUnbridgedWireRequestError(`Cannot answer a request to ${service} from the simulation: a ` +
|
|
19
|
-
"serialized AWS API request can only be routed for
|
|
20
|
-
"the AWS JSON protocol. Where this is an AWS SDK bundled into " +
|
|
19
|
+
"serialized AWS API request can only be routed for S3, Bedrock " +
|
|
20
|
+
"Runtime and the services using the AWS JSON protocol. Where this is an AWS SDK bundled into " +
|
|
21
21
|
"function code, leaving the SDK out of the deployment package puts it " +
|
|
22
22
|
"back on the module interception path, which every simulated service " +
|
|
23
23
|
"is reachable through.");
|
|
@@ -24,9 +24,13 @@ export class SimBedrockAuthorizer {
|
|
|
24
24
|
caller: options.caller,
|
|
25
25
|
});
|
|
26
26
|
if (decision.isDenied) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
// A service control policy denial names the policy, as other services'
|
|
28
|
+
// denials do.
|
|
29
|
+
const reason = decision.denialReason ??
|
|
30
|
+
`because no identity-based policy allows the ${action} action`;
|
|
31
|
+
const caller = this.callerIdentifier.format(decision.caller.principal);
|
|
32
|
+
throw new SimBedrockAccessDeniedException(`User: ${caller} is not authorized to perform: ${action} on ` +
|
|
33
|
+
`resource: ${resource} ${reason}`);
|
|
30
34
|
}
|
|
31
35
|
return decision.caller;
|
|
32
36
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a declared Parameter `Type` holds a list.
|
|
3
|
+
*
|
|
4
|
+
* `CommaDelimitedList` and every `List<...>` type do, whatever the member
|
|
5
|
+
* type. A `Ref` to one resolves to a list of strings, `List<Number>` included.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isSimCfnParameterListType(type: string | undefined): boolean;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a declared Parameter `Type` holds a list.
|
|
3
|
+
*
|
|
4
|
+
* `CommaDelimitedList` and every `List<...>` type do, whatever the member
|
|
5
|
+
* type. A `Ref` to one resolves to a list of strings, `List<Number>` included.
|
|
6
|
+
*/
|
|
7
|
+
export function isSimCfnParameterListType(type) {
|
|
8
|
+
return type === "CommaDelimitedList" || (type?.startsWith("List<") ?? false);
|
|
9
|
+
}
|
|
@@ -13,6 +13,9 @@ interface SimCfnParameterValuesProperties {
|
|
|
13
13
|
* the command wins over a template `Default`, and a Parameter declared as a
|
|
14
14
|
* Parameter Store value type reads whichever of the two it ended up with as the
|
|
15
15
|
* name to read.
|
|
16
|
+
*
|
|
17
|
+
* A `CommaDelimitedList` or `List<...>` Parameter is given its value as one
|
|
18
|
+
* comma-separated string, and holds it as the list of members.
|
|
16
19
|
*/
|
|
17
20
|
export declare class SimCfnParameterValues {
|
|
18
21
|
private readonly values;
|
|
@@ -29,5 +32,12 @@ export declare class SimCfnParameterValues {
|
|
|
29
32
|
* `Default`.
|
|
30
33
|
*/
|
|
31
34
|
private recordDefaults;
|
|
35
|
+
/**
|
|
36
|
+
* Split the value of each list-typed Parameter on its commas.
|
|
37
|
+
*
|
|
38
|
+
* Each member is trimmed of the spaces around it, as CloudFormation trims
|
|
39
|
+
* them. A value with no commas is a list of one.
|
|
40
|
+
*/
|
|
41
|
+
private splitLists;
|
|
32
42
|
}
|
|
33
43
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isSimCfnParameterListType } from "./sim-cfn-parameter-list-type.js";
|
|
1
2
|
import { SimCfnParameterStoreValues } from "./store/sim-cfn-parameter-store-values.js";
|
|
2
3
|
/**
|
|
3
4
|
* The runtime value of every Parameter a Stack was created with.
|
|
@@ -6,6 +7,9 @@ import { SimCfnParameterStoreValues } from "./store/sim-cfn-parameter-store-valu
|
|
|
6
7
|
* the command wins over a template `Default`, and a Parameter declared as a
|
|
7
8
|
* Parameter Store value type reads whichever of the two it ended up with as the
|
|
8
9
|
* name to read.
|
|
10
|
+
*
|
|
11
|
+
* A `CommaDelimitedList` or `List<...>` Parameter is given its value as one
|
|
12
|
+
* comma-separated string, and holds it as the list of members.
|
|
9
13
|
*/
|
|
10
14
|
export class SimCfnParameterValues {
|
|
11
15
|
values;
|
|
@@ -15,6 +19,7 @@ export class SimCfnParameterValues {
|
|
|
15
19
|
this.storeValues = new SimCfnParameterStoreValues({ store });
|
|
16
20
|
this.values = new Map(Object.entries(supplied));
|
|
17
21
|
this.recordDefaults(definitions);
|
|
22
|
+
this.splitLists(definitions);
|
|
18
23
|
this.storeValues.applyTo(this.values, definitions);
|
|
19
24
|
}
|
|
20
25
|
/** Every Parameter that resolved to a stand-in value. */
|
|
@@ -39,4 +44,19 @@ export class SimCfnParameterValues {
|
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Split the value of each list-typed Parameter on its commas.
|
|
49
|
+
*
|
|
50
|
+
* Each member is trimmed of the spaces around it, as CloudFormation trims
|
|
51
|
+
* them. A value with no commas is a list of one.
|
|
52
|
+
*/
|
|
53
|
+
splitLists(definitions) {
|
|
54
|
+
for (const [parameterName, definition] of definitions) {
|
|
55
|
+
const value = this.values.get(parameterName);
|
|
56
|
+
if (typeof value === "string" &&
|
|
57
|
+
isSimCfnParameterListType(definition.Type)) {
|
|
58
|
+
this.values.set(parameterName, value.split(",").map((member) => member.trim()));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
42
62
|
}
|
|
@@ -5,9 +5,10 @@ import type { SimCfnParameterStoreReader } from "./store/sim-cfn-parameter-store
|
|
|
5
5
|
* defaults and Parameter Store reads have been applied.
|
|
6
6
|
*
|
|
7
7
|
* A Parameter is given its value as a string, because AWS CloudFormation
|
|
8
|
-
* command inputs provide ParameterValue as one. A
|
|
9
|
-
* `
|
|
10
|
-
*
|
|
8
|
+
* command inputs provide ParameterValue as one. A `CommaDelimitedList` or
|
|
9
|
+
* `List<...>` Parameter resolves to that string split into a list. So does an
|
|
10
|
+
* `AWS::SSM::Parameter::Value<List<String>>` Parameter, which is given a
|
|
11
|
+
* parameter name and splits the value stored under it. A resolved value can be
|
|
11
12
|
* either.
|
|
12
13
|
*/
|
|
13
14
|
export type SimCloudFormationParameterValue = string | string[];
|
|
@@ -61,8 +62,9 @@ export type SimCfnParametersContext = Pick<SimCfnParametersProperties, "definiti
|
|
|
61
62
|
*
|
|
62
63
|
* Most fields are recorded for structural typing/documentation. Runtime
|
|
63
64
|
* behavior applies string Default values when a command does not provide an
|
|
64
|
-
* explicit Parameter value,
|
|
65
|
-
* Type
|
|
65
|
+
* explicit Parameter value, splits the value of a `CommaDelimitedList` or
|
|
66
|
+
* `List<...>` Type, and reads an `AWS::SSM::Parameter::Value<...>` Type from
|
|
67
|
+
* simulated Parameter Store.
|
|
66
68
|
*/
|
|
67
69
|
export interface SimCfnParameterDefinition {
|
|
68
70
|
readonly Type?: string | undefined;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isSimCfnParameterListType } from "../sim-cfn-parameter-list-type.js";
|
|
1
2
|
/** The Parameter type that holds a Parameter Store name. */
|
|
2
3
|
const parameterStoreValuePrefix = "AWS::SSM::Parameter::Value<";
|
|
3
4
|
/**
|
|
@@ -14,6 +15,6 @@ export function simCfnParameterStoreValueType(declaredType) {
|
|
|
14
15
|
}
|
|
15
16
|
const innerType = declaredType.slice(parameterStoreValuePrefix.length, -1);
|
|
16
17
|
return {
|
|
17
|
-
list: innerType
|
|
18
|
+
list: isSimCfnParameterListType(innerType),
|
|
18
19
|
};
|
|
19
20
|
}
|
|
@@ -9,19 +9,25 @@ import type { SimCfnResolveContext } from "../../../resolve/sim-cfn-resolve-cont
|
|
|
9
9
|
* {
|
|
10
10
|
* "Fn::Join": ["-", ["a", "b", { "Ref": "Name" }]]
|
|
11
11
|
* }
|
|
12
|
+
*
|
|
13
|
+
* The values may also come from one function that returns the whole list:
|
|
14
|
+
*
|
|
15
|
+
* {
|
|
16
|
+
* "Fn::Join": [",", { "Fn::GetAtt": ["Zone", "NameServers"] }]
|
|
17
|
+
* }
|
|
12
18
|
*/
|
|
13
19
|
export declare class SimCfnFnJoin extends SimCfnNode {
|
|
14
20
|
private readonly delimiter;
|
|
15
21
|
private readonly values;
|
|
16
|
-
constructor(delimiter: string, values:
|
|
22
|
+
constructor(delimiter: string, values: SimCfnNode);
|
|
17
23
|
/**
|
|
18
|
-
* Resolve
|
|
24
|
+
* Resolve the values and join them with the delimiter.
|
|
19
25
|
*
|
|
20
|
-
* Joining happens only when
|
|
21
|
-
* value is still an unresolved expression (for
|
|
22
|
-
* during the up-front pass before Resources exist),
|
|
23
|
-
* itself in template form. A later resolution pass can
|
|
24
|
-
* referenced Resources are available.
|
|
26
|
+
* Joining happens only when the values have resolved to a list of strings.
|
|
27
|
+
* If the list, or any value in it, is still an unresolved expression (for
|
|
28
|
+
* example a Resource `Ref` during the up-front pass before Resources exist),
|
|
29
|
+
* this node re-emits itself in template form. A later resolution pass can
|
|
30
|
+
* finish it once the referenced Resources are available.
|
|
25
31
|
*
|
|
26
32
|
* A dynamic reference can be assembled out of the joined values, as CDK
|
|
27
33
|
* writes one whenever the secret it reads sits in the same Stack: the
|
|
@@ -32,16 +38,15 @@ export declare class SimCfnFnJoin extends SimCfnNode {
|
|
|
32
38
|
*/
|
|
33
39
|
resolve(context: SimCfnResolveContext): SimCfnTemplateValue;
|
|
34
40
|
/**
|
|
35
|
-
* Collect referenced names from
|
|
41
|
+
* Collect referenced names from the values.
|
|
36
42
|
*/
|
|
37
43
|
referencedNames(): string[];
|
|
38
|
-
private resolveValue;
|
|
39
44
|
/**
|
|
40
|
-
*
|
|
45
|
+
* Refuse a value that can never become a string.
|
|
41
46
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
47
|
+
* A string joins now, and an unresolved expression may join on a later
|
|
48
|
+
* pass. Anything else (a number, a nested list, a plain object) is a type
|
|
49
|
+
* error, as CloudFormation joins a list of strings only.
|
|
45
50
|
*/
|
|
46
|
-
private
|
|
51
|
+
private assertJoinable;
|
|
47
52
|
}
|