Next.js website for Rocky Mountain Vending company featuring: - Product catalog with Stripe integration - Service areas and parts pages - Admin dashboard with Clerk authentication - SEO optimized pages with JSON-LD structured data Co-authored-by: Cursor <cursoragent@cursor.com>
266 lines
12 KiB
Text
266 lines
12 KiB
Text
import { NormalizedSchema, translateTraits } from "@smithy/core/schema";
|
|
import { splitEvery, splitHeader } from "@smithy/core/serde";
|
|
import { HttpRequest } from "@smithy/protocol-http";
|
|
import { sdkStreamMixin } from "@smithy/util-stream";
|
|
import { collectBody } from "./collect-stream-body";
|
|
import { extendedEncodeURIComponent } from "./extended-encode-uri-component";
|
|
import { HttpProtocol } from "./HttpProtocol";
|
|
export class HttpBindingProtocol extends HttpProtocol {
|
|
async serializeRequest(operationSchema, _input, context) {
|
|
const input = {
|
|
...(_input ?? {}),
|
|
};
|
|
const serializer = this.serializer;
|
|
const query = {};
|
|
const headers = {};
|
|
const endpoint = await context.endpoint();
|
|
const ns = NormalizedSchema.of(operationSchema?.input);
|
|
const schema = ns.getSchema();
|
|
let hasNonHttpBindingMember = false;
|
|
let payload;
|
|
const request = new HttpRequest({
|
|
protocol: "",
|
|
hostname: "",
|
|
port: undefined,
|
|
path: "",
|
|
fragment: undefined,
|
|
query: query,
|
|
headers: headers,
|
|
body: undefined,
|
|
});
|
|
if (endpoint) {
|
|
this.updateServiceEndpoint(request, endpoint);
|
|
this.setHostPrefix(request, operationSchema, input);
|
|
const opTraits = translateTraits(operationSchema.traits);
|
|
if (opTraits.http) {
|
|
request.method = opTraits.http[0];
|
|
const [path, search] = opTraits.http[1].split("?");
|
|
if (request.path == "/") {
|
|
request.path = path;
|
|
}
|
|
else {
|
|
request.path += path;
|
|
}
|
|
const traitSearchParams = new URLSearchParams(search ?? "");
|
|
Object.assign(query, Object.fromEntries(traitSearchParams));
|
|
}
|
|
}
|
|
for (const [memberName, memberNs] of ns.structIterator()) {
|
|
const memberTraits = memberNs.getMergedTraits() ?? {};
|
|
const inputMemberValue = input[memberName];
|
|
if (inputMemberValue == null && !memberNs.isIdempotencyToken()) {
|
|
continue;
|
|
}
|
|
if (memberTraits.httpPayload) {
|
|
const isStreaming = memberNs.isStreaming();
|
|
if (isStreaming) {
|
|
const isEventStream = memberNs.isStructSchema();
|
|
if (isEventStream) {
|
|
if (input[memberName]) {
|
|
payload = await this.serializeEventStream({
|
|
eventStream: input[memberName],
|
|
requestSchema: ns,
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
payload = inputMemberValue;
|
|
}
|
|
}
|
|
else {
|
|
serializer.write(memberNs, inputMemberValue);
|
|
payload = serializer.flush();
|
|
}
|
|
delete input[memberName];
|
|
}
|
|
else if (memberTraits.httpLabel) {
|
|
serializer.write(memberNs, inputMemberValue);
|
|
const replacement = serializer.flush();
|
|
if (request.path.includes(`{${memberName}+}`)) {
|
|
request.path = request.path.replace(`{${memberName}+}`, replacement.split("/").map(extendedEncodeURIComponent).join("/"));
|
|
}
|
|
else if (request.path.includes(`{${memberName}}`)) {
|
|
request.path = request.path.replace(`{${memberName}}`, extendedEncodeURIComponent(replacement));
|
|
}
|
|
delete input[memberName];
|
|
}
|
|
else if (memberTraits.httpHeader) {
|
|
serializer.write(memberNs, inputMemberValue);
|
|
headers[memberTraits.httpHeader.toLowerCase()] = String(serializer.flush());
|
|
delete input[memberName];
|
|
}
|
|
else if (typeof memberTraits.httpPrefixHeaders === "string") {
|
|
for (const [key, val] of Object.entries(inputMemberValue)) {
|
|
const amalgam = memberTraits.httpPrefixHeaders + key;
|
|
serializer.write([memberNs.getValueSchema(), { httpHeader: amalgam }], val);
|
|
headers[amalgam.toLowerCase()] = serializer.flush();
|
|
}
|
|
delete input[memberName];
|
|
}
|
|
else if (memberTraits.httpQuery || memberTraits.httpQueryParams) {
|
|
this.serializeQuery(memberNs, inputMemberValue, query);
|
|
delete input[memberName];
|
|
}
|
|
else {
|
|
hasNonHttpBindingMember = true;
|
|
}
|
|
}
|
|
if (hasNonHttpBindingMember && input) {
|
|
serializer.write(schema, input);
|
|
payload = serializer.flush();
|
|
}
|
|
request.headers = headers;
|
|
request.query = query;
|
|
request.body = payload;
|
|
return request;
|
|
}
|
|
serializeQuery(ns, data, query) {
|
|
const serializer = this.serializer;
|
|
const traits = ns.getMergedTraits();
|
|
if (traits.httpQueryParams) {
|
|
for (const [key, val] of Object.entries(data)) {
|
|
if (!(key in query)) {
|
|
const valueSchema = ns.getValueSchema();
|
|
Object.assign(valueSchema.getMergedTraits(), {
|
|
...traits,
|
|
httpQuery: key,
|
|
httpQueryParams: undefined,
|
|
});
|
|
this.serializeQuery(valueSchema, val, query);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
if (ns.isListSchema()) {
|
|
const sparse = !!ns.getMergedTraits().sparse;
|
|
const buffer = [];
|
|
for (const item of data) {
|
|
serializer.write([ns.getValueSchema(), traits], item);
|
|
const serializable = serializer.flush();
|
|
if (sparse || serializable !== undefined) {
|
|
buffer.push(serializable);
|
|
}
|
|
}
|
|
query[traits.httpQuery] = buffer;
|
|
}
|
|
else {
|
|
serializer.write([ns, traits], data);
|
|
query[traits.httpQuery] = serializer.flush();
|
|
}
|
|
}
|
|
async deserializeResponse(operationSchema, context, response) {
|
|
const deserializer = this.deserializer;
|
|
const ns = NormalizedSchema.of(operationSchema.output);
|
|
const dataObject = {};
|
|
if (response.statusCode >= 300) {
|
|
const bytes = await collectBody(response.body, context);
|
|
if (bytes.byteLength > 0) {
|
|
Object.assign(dataObject, await deserializer.read(15, bytes));
|
|
}
|
|
await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response));
|
|
throw new Error("@smithy/core/protocols - HTTP Protocol error handler failed to throw.");
|
|
}
|
|
for (const header in response.headers) {
|
|
const value = response.headers[header];
|
|
delete response.headers[header];
|
|
response.headers[header.toLowerCase()] = value;
|
|
}
|
|
const nonHttpBindingMembers = await this.deserializeHttpMessage(ns, context, response, dataObject);
|
|
if (nonHttpBindingMembers.length) {
|
|
const bytes = await collectBody(response.body, context);
|
|
if (bytes.byteLength > 0) {
|
|
const dataFromBody = await deserializer.read(ns, bytes);
|
|
for (const member of nonHttpBindingMembers) {
|
|
dataObject[member] = dataFromBody[member];
|
|
}
|
|
}
|
|
}
|
|
else if (nonHttpBindingMembers.discardResponseBody) {
|
|
await collectBody(response.body, context);
|
|
}
|
|
dataObject.$metadata = this.deserializeMetadata(response);
|
|
return dataObject;
|
|
}
|
|
async deserializeHttpMessage(schema, context, response, arg4, arg5) {
|
|
let dataObject;
|
|
if (arg4 instanceof Set) {
|
|
dataObject = arg5;
|
|
}
|
|
else {
|
|
dataObject = arg4;
|
|
}
|
|
let discardResponseBody = true;
|
|
const deserializer = this.deserializer;
|
|
const ns = NormalizedSchema.of(schema);
|
|
const nonHttpBindingMembers = [];
|
|
for (const [memberName, memberSchema] of ns.structIterator()) {
|
|
const memberTraits = memberSchema.getMemberTraits();
|
|
if (memberTraits.httpPayload) {
|
|
discardResponseBody = false;
|
|
const isStreaming = memberSchema.isStreaming();
|
|
if (isStreaming) {
|
|
const isEventStream = memberSchema.isStructSchema();
|
|
if (isEventStream) {
|
|
dataObject[memberName] = await this.deserializeEventStream({
|
|
response,
|
|
responseSchema: ns,
|
|
});
|
|
}
|
|
else {
|
|
dataObject[memberName] = sdkStreamMixin(response.body);
|
|
}
|
|
}
|
|
else if (response.body) {
|
|
const bytes = await collectBody(response.body, context);
|
|
if (bytes.byteLength > 0) {
|
|
dataObject[memberName] = await deserializer.read(memberSchema, bytes);
|
|
}
|
|
}
|
|
}
|
|
else if (memberTraits.httpHeader) {
|
|
const key = String(memberTraits.httpHeader).toLowerCase();
|
|
const value = response.headers[key];
|
|
if (null != value) {
|
|
if (memberSchema.isListSchema()) {
|
|
const headerListValueSchema = memberSchema.getValueSchema();
|
|
headerListValueSchema.getMergedTraits().httpHeader = key;
|
|
let sections;
|
|
if (headerListValueSchema.isTimestampSchema() &&
|
|
headerListValueSchema.getSchema() === 4) {
|
|
sections = splitEvery(value, ",", 2);
|
|
}
|
|
else {
|
|
sections = splitHeader(value);
|
|
}
|
|
const list = [];
|
|
for (const section of sections) {
|
|
list.push(await deserializer.read(headerListValueSchema, section.trim()));
|
|
}
|
|
dataObject[memberName] = list;
|
|
}
|
|
else {
|
|
dataObject[memberName] = await deserializer.read(memberSchema, value);
|
|
}
|
|
}
|
|
}
|
|
else if (memberTraits.httpPrefixHeaders !== undefined) {
|
|
dataObject[memberName] = {};
|
|
for (const [header, value] of Object.entries(response.headers)) {
|
|
if (header.startsWith(memberTraits.httpPrefixHeaders)) {
|
|
const valueSchema = memberSchema.getValueSchema();
|
|
valueSchema.getMergedTraits().httpHeader = header;
|
|
dataObject[memberName][header.slice(memberTraits.httpPrefixHeaders.length)] = await deserializer.read(valueSchema, value);
|
|
}
|
|
}
|
|
}
|
|
else if (memberTraits.httpResponseCode) {
|
|
dataObject[memberName] = response.statusCode;
|
|
}
|
|
else {
|
|
nonHttpBindingMembers.push(memberName);
|
|
}
|
|
}
|
|
nonHttpBindingMembers.discardResponseBody = discardResponseBody;
|
|
return nonHttpBindingMembers;
|
|
}
|
|
}
|