@kensio/yulin 1.21.28 → 1.21.30

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 (68) hide show
  1. package/dist/sdk/wire/sim-sdk-wire-bedrock-action.d.ts +18 -0
  2. package/dist/sdk/wire/sim-sdk-wire-bedrock-action.js +71 -0
  3. package/dist/sdk/wire/sim-sdk-wire-bedrock-input.d.ts +11 -0
  4. package/dist/sdk/wire/sim-sdk-wire-bedrock-input.js +45 -0
  5. package/dist/sdk/wire/sim-sdk-wire-bedrock.d.ts +10 -0
  6. package/dist/sdk/wire/sim-sdk-wire-bedrock.js +47 -0
  7. package/dist/sdk/wire/sim-sdk-wire-call.d.ts +30 -0
  8. package/dist/sdk/wire/sim-sdk-wire-call.js +32 -0
  9. package/dist/sdk/wire/sim-sdk-wire-dispatcher.js +7 -9
  10. package/dist/sdk/wire/sim-sdk-wire-event-stream.d.ts +16 -0
  11. package/dist/sdk/wire/sim-sdk-wire-event-stream.js +79 -0
  12. package/dist/sdk/wire/sim-sdk-wire-unbridged.js +2 -2
  13. package/dist/service/athena/engine/sim-athena-array-shims.js +1 -1
  14. package/dist/service/athena/engine/sim-athena-binary-text.d.ts +2 -2
  15. package/dist/service/athena/engine/sim-athena-binary-text.js +2 -2
  16. package/dist/service/athena/engine/sim-athena-cast-rewrite.d.ts +30 -0
  17. package/dist/service/athena/engine/sim-athena-cast-rewrite.js +107 -0
  18. package/dist/service/athena/engine/sim-athena-cast-shims.d.ts +12 -0
  19. package/dist/service/athena/engine/sim-athena-cast-shims.js +29 -0
  20. package/dist/service/athena/engine/sim-athena-cast-text.d.ts +13 -0
  21. package/dist/service/athena/engine/sim-athena-cast-text.js +66 -0
  22. package/dist/service/athena/engine/sim-athena-comparison-shims.js +1 -2
  23. package/dist/service/athena/engine/sim-athena-date-arithmetic-shims.d.ts +4 -5
  24. package/dist/service/athena/engine/sim-athena-date-arithmetic-shims.js +6 -14
  25. package/dist/service/athena/engine/sim-athena-date-units.d.ts +1 -1
  26. package/dist/service/athena/engine/sim-athena-date-units.js +1 -1
  27. package/dist/service/athena/engine/sim-athena-engine-answer.d.ts +10 -5
  28. package/dist/service/athena/engine/sim-athena-engine-answer.js +4 -4
  29. package/dist/service/athena/engine/sim-athena-engine-run.d.ts +4 -0
  30. package/dist/service/athena/engine/sim-athena-engine-run.js +10 -2
  31. package/dist/service/athena/engine/sim-athena-regexp-shims.js +2 -2
  32. package/dist/service/athena/engine/sim-athena-shim-refusal.d.ts +17 -0
  33. package/dist/service/athena/engine/sim-athena-shim-refusal.js +22 -0
  34. package/dist/service/athena/engine/sim-athena-shim-registry.d.ts +5 -1
  35. package/dist/service/athena/engine/sim-athena-shim-registry.js +14 -2
  36. package/dist/service/athena/engine/sim-athena-shims.js +2 -0
  37. package/dist/service/athena/engine/sim-athena-sql-translation.d.ts +1 -23
  38. package/dist/service/athena/engine/sim-athena-sql-translation.js +8 -23
  39. package/dist/service/athena/engine/sim-athena-translated-sql.d.ts +29 -0
  40. package/dist/service/athena/engine/sim-athena-translated-sql.js +12 -0
  41. package/dist/service/athena/engine/sim-athena-turn-down.d.ts +7 -0
  42. package/dist/service/athena/engine/sim-athena-turn-down.js +11 -0
  43. package/dist/service/athena/result/sim-athena-query-answer.d.ts +2 -1
  44. package/dist/service/athena/result/sim-athena-query-answer.js +2 -1
  45. package/dist/service/athena/sim-athena-snapshot-table.fixture.d.ts +10 -0
  46. package/dist/service/athena/sim-athena-snapshot-table.fixture.js +39 -0
  47. package/dist/service/bedrock/command/authorize/sim-bedrock-authorizer.js +7 -3
  48. package/dist/service/lambda/function/code/vm/sdk/sim-sdk-lambda-vm-module-provider.d.ts +2 -2
  49. package/dist/service/lambda/function/code/vm/sdk/sim-sdk-lambda-vm-module-provider.js +5 -9
  50. package/dist/service/lambda/function/code/vm/sim-lambda-vm-context.d.ts +1 -1
  51. package/dist/service/lambda/function/code/vm/sim-lambda-vm-context.js +11 -22
  52. package/dist/service/lambda/function/code/vm/sim-lambda-vm-host-globals.d.ts +4 -0
  53. package/dist/service/lambda/function/code/vm/sim-lambda-vm-host-globals.js +87 -0
  54. package/dist/service/lambda/function/invoke/sim-lambda-outbound-clients.d.ts +3 -0
  55. package/dist/service/lambda/function/invoke/sim-lambda-outbound-clients.js +10 -0
  56. package/dist/service/lambda/function/outbound/sim-lambda-http2-exchanges.d.ts +32 -0
  57. package/dist/service/lambda/function/outbound/sim-lambda-http2-exchanges.js +39 -0
  58. package/dist/service/lambda/function/outbound/sim-lambda-http2-messages.d.ts +33 -0
  59. package/dist/service/lambda/function/outbound/sim-lambda-http2-messages.js +87 -0
  60. package/dist/service/lambda/function/outbound/sim-lambda-http2-module.d.ts +27 -0
  61. package/dist/service/lambda/function/outbound/sim-lambda-http2-module.js +53 -0
  62. package/dist/service/lambda/function/outbound/sim-lambda-http2-session.d.ts +31 -0
  63. package/dist/service/lambda/function/outbound/sim-lambda-http2-session.js +57 -0
  64. package/dist/service/lambda/function/outbound/sim-lambda-transport-module.d.ts +11 -0
  65. package/dist/service/lambda/function/outbound/sim-lambda-transport-module.js +24 -0
  66. package/docs/services/athena/README.md +29 -8
  67. package/docs/services/lambda/README.md +18 -8
  68. package/package.json +1 -1
@@ -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 { readSimSdkWireInput } from "./sim-sdk-wire-json.js";
4
- import { readSimSdkWireCredentialScope, readSimSdkWireOperation, } from "./sim-sdk-wire-operation.js";
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 operation = readSimSdkWireOperation(request);
48
- if (operation === undefined) {
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(operation.commandName, readSimSdkWireInput(request.body)), makeSimSdkWireClient(operation.serviceId, scope?.regionName ?? this.regionName), undefined, caller);
57
- return simSdkWireOutputResponse(output, contentType);
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 simSdkWireErrorResponse(error, contentType);
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 a service using " +
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.");
@@ -57,7 +57,7 @@ function joined(array, delimiter, absent) {
57
57
  * One element written out.
58
58
  *
59
59
  * Trino refuses to join an array whose elements are not text, and raising here
60
- * turns the query down to its declared result instead.
60
+ * fails the query the same way.
61
61
  */
62
62
  function scalarText(value) {
63
63
  if (typeof value === "string") {
@@ -3,8 +3,8 @@ import type { SQLOutputValue } from "node:sqlite";
3
3
  * One encoded string read back to bytes, or null where it is null.
4
4
  *
5
5
  * Trino fails the query over text the encoding cannot carry, and `Buffer` reads
6
- * as much of it as it can and drops the rest. Raising here turns the query down
7
- * instead, which is nearer to Trino's answer than bytes nobody wrote.
6
+ * as much of it as it can and drops the rest. Raising here fails the query the
7
+ * way Trino does.
8
8
  */
9
9
  export declare function simAthenaDecodedText(text: string | undefined, encoding: "base64" | "hex"): Uint8Array | null;
10
10
  /**
@@ -20,8 +20,8 @@ const encodedReplacement = Buffer.from([0xef, 0xbf, 0xbd]);
20
20
  * One encoded string read back to bytes, or null where it is null.
21
21
  *
22
22
  * Trino fails the query over text the encoding cannot carry, and `Buffer` reads
23
- * as much of it as it can and drops the rest. Raising here turns the query down
24
- * instead, which is nearer to Trino's answer than bytes nobody wrote.
23
+ * as much of it as it can and drops the rest. Raising here fails the query the
24
+ * way Trino does.
25
25
  */
26
26
  export function simAthenaDecodedText(text, encoding) {
27
27
  if (text === undefined) {
@@ -0,0 +1,30 @@
1
+ import type { SimAthenaCatalogTable } from "../table/sim-athena-catalog-table.js";
2
+ /**
3
+ * The shims a cast to `DATE` and to `TIMESTAMP` are handed to.
4
+ *
5
+ * The names have the simulator's prefix so that neither can collide with a
6
+ * Trino function a statement calls itself.
7
+ */
8
+ export declare const simAthenaDateCast = "sim_athena_cast_date";
9
+ export declare const simAthenaTimestampCast = "sim_athena_cast_timestamp";
10
+ /** The second argument a shim is handed where the value it casts is text. */
11
+ export declare const simAthenaCastSource = "varchar";
12
+ /**
13
+ * Hand every cast to `DATE` or `TIMESTAMP` in the tree to the engine's shims.
14
+ *
15
+ * SQLite gives a column declared `DATE` or `TIMESTAMP` numeric affinity, so a
16
+ * plain `CAST('2026-08-15' AS DATE)` keeps the leading number and answers
17
+ * `2026`. Every date function downstream of that cast then reads a year where
18
+ * it expected a date.
19
+ *
20
+ * Trino's one-argument `date(x)` is the cast to `DATE` under another name,
21
+ * and it goes to the same shim. SQLite's own `date()` answers null over text
22
+ * that is no date, where Trino fails the cast.
23
+ *
24
+ * Trino reads text more strictly than a value already typed as a timestamp,
25
+ * and the shim is told which it has. A string literal and a column the catalog
26
+ * declares as text are text. Anything else is taken to be a date or a
27
+ * timestamp already, since the engine cannot tell the type a function answers
28
+ * with.
29
+ */
30
+ export declare function simAthenaRewriteCasts(ast: unknown, tables: readonly SimAthenaCatalogTable[]): void;
@@ -0,0 +1,107 @@
1
+ import { asAstNode, isColumnRef, replaceNode, simAthenaAstNodes, simAthenaCalledName, } from "./sim-athena-ast-nodes.js";
2
+ /**
3
+ * The shims a cast to `DATE` and to `TIMESTAMP` are handed to.
4
+ *
5
+ * The names have the simulator's prefix so that neither can collide with a
6
+ * Trino function a statement calls itself.
7
+ */
8
+ export const simAthenaDateCast = "sim_athena_cast_date";
9
+ export const simAthenaTimestampCast = "sim_athena_cast_timestamp";
10
+ /** The second argument a shim is handed where the value it casts is text. */
11
+ export const simAthenaCastSource = "varchar";
12
+ /** The shim each cast target goes to. */
13
+ const castShims = new Map([
14
+ ["DATE", simAthenaDateCast],
15
+ ["TIMESTAMP", simAthenaTimestampCast],
16
+ ]);
17
+ /** The Glue types a column of text is declared with. */
18
+ const textTypes = /^(?:string|varchar|char)\b/iu;
19
+ /**
20
+ * Hand every cast to `DATE` or `TIMESTAMP` in the tree to the engine's shims.
21
+ *
22
+ * SQLite gives a column declared `DATE` or `TIMESTAMP` numeric affinity, so a
23
+ * plain `CAST('2026-08-15' AS DATE)` keeps the leading number and answers
24
+ * `2026`. Every date function downstream of that cast then reads a year where
25
+ * it expected a date.
26
+ *
27
+ * Trino's one-argument `date(x)` is the cast to `DATE` under another name,
28
+ * and it goes to the same shim. SQLite's own `date()` answers null over text
29
+ * that is no date, where Trino fails the cast.
30
+ *
31
+ * Trino reads text more strictly than a value already typed as a timestamp,
32
+ * and the shim is told which it has. A string literal and a column the catalog
33
+ * declares as text are text. Anything else is taken to be a date or a
34
+ * timestamp already, since the engine cannot tell the type a function answers
35
+ * with.
36
+ */
37
+ export function simAthenaRewriteCasts(ast, tables) {
38
+ const textColumns = textColumnsOf(tables);
39
+ for (const node of simAthenaAstNodes(ast)) {
40
+ const cast = castOf(node);
41
+ if (cast !== undefined) {
42
+ replaceNode(node, {
43
+ type: "function",
44
+ name: { name: [{ type: "default", value: cast.shim }] },
45
+ args: {
46
+ type: "expr_list",
47
+ value: [cast.value, sourceOf(cast.value, textColumns)],
48
+ },
49
+ over: null,
50
+ });
51
+ }
52
+ }
53
+ }
54
+ function castOf(node) {
55
+ if (node["type"] === "cast") {
56
+ const shim = castShims.get(targetOf(node["target"]));
57
+ return shim === undefined ? undefined : { shim, value: node["expr"] };
58
+ }
59
+ const values = asAstNode(node["args"])?.["value"];
60
+ if (node["type"] !== "function" ||
61
+ simAthenaCalledName(node)?.toLowerCase() !== "date" ||
62
+ !Array.isArray(values) ||
63
+ values.length !== 1) {
64
+ return undefined;
65
+ }
66
+ return { shim: simAthenaDateCast, value: values[0] };
67
+ }
68
+ /** The one type a cast names, upper cased, or nothing for anything else. */
69
+ function targetOf(target) {
70
+ const only = Array.isArray(target) && target.length === 1 ? target[0] : null;
71
+ const dataType = asAstNode(only)?.["dataType"];
72
+ return typeof dataType === "string" ? dataType.toUpperCase() : "";
73
+ }
74
+ /** The second argument that tells the shim whether its value is text. */
75
+ function sourceOf(value, textColumns) {
76
+ const node = asAstNode(value);
77
+ const isText = node?.["type"] === "single_quote_string" ||
78
+ (node !== undefined &&
79
+ isColumnRef(node) &&
80
+ textColumns.has(node.column.toLowerCase()));
81
+ return {
82
+ type: "single_quote_string",
83
+ value: isText ? simAthenaCastSource : "",
84
+ };
85
+ }
86
+ /**
87
+ * Every column name the tables declare as text and as nothing else.
88
+ *
89
+ * A name two tables declare with different types is left out, since the
90
+ * statement could mean either and only text is held to the stricter read.
91
+ */
92
+ function textColumnsOf(tables) {
93
+ const text = new Set();
94
+ const other = new Set();
95
+ for (const table of tables) {
96
+ for (const column of [...table.columns, ...table.partitionKeys]) {
97
+ const name = column.Name.toLowerCase();
98
+ if (textTypes.test(column.Type ?? "")) {
99
+ text.add(name);
100
+ }
101
+ else {
102
+ other.add(name);
103
+ }
104
+ }
105
+ }
106
+ return text.difference(other);
107
+ }
@@ -0,0 +1,12 @@
1
+ import type { DatabaseSync } from "node:sqlite";
2
+ /**
3
+ * Trino's casts to `DATE` and `TIMESTAMP`, which SQLite cannot do itself.
4
+ *
5
+ * SQLite gives both types numeric affinity, so its own cast of
6
+ * `'2026-08-15'` answers `2026`. The statement's casts are rewritten onto
7
+ * these shims before it runs, and the rewrite says whether the value is text.
8
+ *
9
+ * A value the cast cannot read fails the query with Trino's own message, the
10
+ * way Athena fails it.
11
+ */
12
+ export declare function simAthenaInstallCastShims(database: DatabaseSync): void;
@@ -0,0 +1,29 @@
1
+ import { SimAthenaSetUpError } from "../error/sim-athena.error.js";
2
+ import { simAthenaCastSource, simAthenaDateCast, simAthenaTimestampCast, } from "./sim-athena-cast-rewrite.js";
3
+ import { simAthenaCastInstant, simAthenaCastRendered, } from "./sim-athena-cast-text.js";
4
+ import { shimText, simAthenaScalarShim } from "./sim-athena-shim-registry.js";
5
+ /**
6
+ * Trino's casts to `DATE` and `TIMESTAMP`, which SQLite cannot do itself.
7
+ *
8
+ * SQLite gives both types numeric affinity, so its own cast of
9
+ * `'2026-08-15'` answers `2026`. The statement's casts are rewritten onto
10
+ * these shims before it runs, and the rewrite says whether the value is text.
11
+ *
12
+ * A value the cast cannot read fails the query with Trino's own message, the
13
+ * way Athena fails it.
14
+ */
15
+ export function simAthenaInstallCastShims(database) {
16
+ simAthenaScalarShim(database, simAthenaDateCast, (value, source) => cast(value, source, "date"), "CAST(... AS DATE)");
17
+ simAthenaScalarShim(database, simAthenaTimestampCast, (value, source) => cast(value, source, "timestamp"), "CAST(... AS TIMESTAMP)");
18
+ }
19
+ function cast(value, source, type) {
20
+ const text = shimText(value);
21
+ if (text === undefined) {
22
+ return null;
23
+ }
24
+ const instant = simAthenaCastInstant(text, type, source === simAthenaCastSource);
25
+ if (instant === undefined) {
26
+ throw new SimAthenaSetUpError(`Value cannot be cast to ${type}: ${text}`);
27
+ }
28
+ return simAthenaCastRendered(instant, type);
29
+ }
@@ -0,0 +1,13 @@
1
+ /** The two types a cast in the engine reads a value as. */
2
+ export type SimAthenaCastType = "date" | "timestamp";
3
+ /**
4
+ * The instant one value names as the cast reads it, or nothing where the cast
5
+ * fails.
6
+ *
7
+ * Text is held to the formats Trino's cast from `varchar` takes. Any other
8
+ * source is a value some column or function already typed as a date or a
9
+ * timestamp, written as the ISO-8601 text the engine holds one as.
10
+ */
11
+ export declare function simAthenaCastInstant(text: string, type: SimAthenaCastType, fromText: boolean): number | undefined;
12
+ /** One instant rendered as Athena renders a value of the type. */
13
+ export declare function simAthenaCastRendered(instant: number, type: SimAthenaCastType): string;