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>
136 lines
5.6 KiB
Text
136 lines
5.6 KiB
Text
import { collectBody, RpcProtocol } from "@smithy/core/protocols";
|
|
import { deref, NormalizedSchema, TypeRegistry } from "@smithy/core/schema";
|
|
import { ProtocolLib } from "../ProtocolLib";
|
|
import { XmlShapeDeserializer } from "../xml/XmlShapeDeserializer";
|
|
import { QueryShapeSerializer } from "./QueryShapeSerializer";
|
|
export class AwsQueryProtocol extends RpcProtocol {
|
|
options;
|
|
serializer;
|
|
deserializer;
|
|
mixin = new ProtocolLib();
|
|
constructor(options) {
|
|
super({
|
|
defaultNamespace: options.defaultNamespace,
|
|
});
|
|
this.options = options;
|
|
const settings = {
|
|
timestampFormat: {
|
|
useTrait: true,
|
|
default: 5,
|
|
},
|
|
httpBindings: false,
|
|
xmlNamespace: options.xmlNamespace,
|
|
serviceNamespace: options.defaultNamespace,
|
|
serializeEmptyLists: true,
|
|
};
|
|
this.serializer = new QueryShapeSerializer(settings);
|
|
this.deserializer = new XmlShapeDeserializer(settings);
|
|
}
|
|
getShapeId() {
|
|
return "aws.protocols#awsQuery";
|
|
}
|
|
setSerdeContext(serdeContext) {
|
|
this.serializer.setSerdeContext(serdeContext);
|
|
this.deserializer.setSerdeContext(serdeContext);
|
|
}
|
|
getPayloadCodec() {
|
|
throw new Error("AWSQuery protocol has no payload codec.");
|
|
}
|
|
async serializeRequest(operationSchema, input, context) {
|
|
const request = await super.serializeRequest(operationSchema, input, context);
|
|
if (!request.path.endsWith("/")) {
|
|
request.path += "/";
|
|
}
|
|
Object.assign(request.headers, {
|
|
"content-type": `application/x-www-form-urlencoded`,
|
|
});
|
|
if (deref(operationSchema.input) === "unit" || !request.body) {
|
|
request.body = "";
|
|
}
|
|
const action = operationSchema.name.split("#")[1] ?? operationSchema.name;
|
|
request.body = `Action=${action}&Version=${this.options.version}` + request.body;
|
|
if (request.body.endsWith("&")) {
|
|
request.body = request.body.slice(-1);
|
|
}
|
|
return request;
|
|
}
|
|
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));
|
|
}
|
|
for (const header in response.headers) {
|
|
const value = response.headers[header];
|
|
delete response.headers[header];
|
|
response.headers[header.toLowerCase()] = value;
|
|
}
|
|
const shortName = operationSchema.name.split("#")[1] ?? operationSchema.name;
|
|
const awsQueryResultKey = ns.isStructSchema() && this.useNestedResult() ? shortName + "Result" : undefined;
|
|
const bytes = await collectBody(response.body, context);
|
|
if (bytes.byteLength > 0) {
|
|
Object.assign(dataObject, await deserializer.read(ns, bytes, awsQueryResultKey));
|
|
}
|
|
const output = {
|
|
$metadata: this.deserializeMetadata(response),
|
|
...dataObject,
|
|
};
|
|
return output;
|
|
}
|
|
useNestedResult() {
|
|
return true;
|
|
}
|
|
async handleError(operationSchema, context, response, dataObject, metadata) {
|
|
const errorIdentifier = this.loadQueryErrorCode(response, dataObject) ?? "Unknown";
|
|
const errorData = this.loadQueryError(dataObject);
|
|
const message = this.loadQueryErrorMessage(dataObject);
|
|
errorData.message = message;
|
|
errorData.Error = {
|
|
Type: errorData.Type,
|
|
Code: errorData.Code,
|
|
Message: message,
|
|
};
|
|
const { errorSchema, errorMetadata } = await this.mixin.getErrorSchemaOrThrowBaseException(errorIdentifier, this.options.defaultNamespace, response, errorData, metadata, this.mixin.findQueryCompatibleError);
|
|
const ns = NormalizedSchema.of(errorSchema);
|
|
const ErrorCtor = TypeRegistry.for(errorSchema[1]).getErrorCtor(errorSchema) ?? Error;
|
|
const exception = new ErrorCtor(message);
|
|
const output = {
|
|
Type: errorData.Error.Type,
|
|
Code: errorData.Error.Code,
|
|
Error: errorData.Error,
|
|
};
|
|
for (const [name, member] of ns.structIterator()) {
|
|
const target = member.getMergedTraits().xmlName ?? name;
|
|
const value = errorData[target] ?? dataObject[target];
|
|
output[name] = this.deserializer.readSchema(member, value);
|
|
}
|
|
throw this.mixin.decorateServiceException(Object.assign(exception, errorMetadata, {
|
|
$fault: ns.getMergedTraits().error,
|
|
message,
|
|
}, output), dataObject);
|
|
}
|
|
loadQueryErrorCode(output, data) {
|
|
const code = (data.Errors?.[0]?.Error ?? data.Errors?.Error ?? data.Error)?.Code;
|
|
if (code !== undefined) {
|
|
return code;
|
|
}
|
|
if (output.statusCode == 404) {
|
|
return "NotFound";
|
|
}
|
|
}
|
|
loadQueryError(data) {
|
|
return data.Errors?.[0]?.Error ?? data.Errors?.Error ?? data.Error;
|
|
}
|
|
loadQueryErrorMessage(data) {
|
|
const errorData = this.loadQueryError(data);
|
|
return errorData?.message ?? errorData?.Message ?? data.message ?? data.Message ?? "Unknown";
|
|
}
|
|
getDefaultContentType() {
|
|
return "application/x-www-form-urlencoded";
|
|
}
|
|
}
|