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>
138 lines
5.5 KiB
Text
138 lines
5.5 KiB
Text
import { determineTimestampFormat } from "@smithy/core/protocols";
|
|
import { NormalizedSchema } from "@smithy/core/schema";
|
|
import { LazyJsonString, NumericValue, parseEpochTimestamp, parseRfc3339DateTimeWithOffset, parseRfc7231DateTime, } from "@smithy/core/serde";
|
|
import { fromBase64 } from "@smithy/util-base64";
|
|
import { SerdeContextConfig } from "../ConfigurableSerdeContext";
|
|
import { deserializingStructIterator } from "../structIterator";
|
|
import { UnionSerde } from "../UnionSerde";
|
|
import { jsonReviver } from "./jsonReviver";
|
|
import { parseJsonBody } from "./parseJsonBody";
|
|
export class JsonShapeDeserializer extends SerdeContextConfig {
|
|
settings;
|
|
constructor(settings) {
|
|
super();
|
|
this.settings = settings;
|
|
}
|
|
async read(schema, data) {
|
|
return this._read(schema, typeof data === "string" ? JSON.parse(data, jsonReviver) : await parseJsonBody(data, this.serdeContext));
|
|
}
|
|
readObject(schema, data) {
|
|
return this._read(schema, data);
|
|
}
|
|
_read(schema, value) {
|
|
const isObject = value !== null && typeof value === "object";
|
|
const ns = NormalizedSchema.of(schema);
|
|
if (isObject) {
|
|
if (ns.isStructSchema()) {
|
|
const union = ns.isUnionSchema();
|
|
const out = {};
|
|
let unionSerde;
|
|
if (union) {
|
|
unionSerde = new UnionSerde(value, out);
|
|
}
|
|
for (const [memberName, memberSchema] of deserializingStructIterator(ns, value, this.settings.jsonName ? "jsonName" : false)) {
|
|
const fromKey = this.settings.jsonName ? memberSchema.getMergedTraits().jsonName ?? memberName : memberName;
|
|
if (union) {
|
|
unionSerde.mark(fromKey);
|
|
}
|
|
if (value[fromKey] != null) {
|
|
out[memberName] = this._read(memberSchema, value[fromKey]);
|
|
}
|
|
}
|
|
if (union) {
|
|
unionSerde.writeUnknown();
|
|
}
|
|
return out;
|
|
}
|
|
if (Array.isArray(value) && ns.isListSchema()) {
|
|
const listMember = ns.getValueSchema();
|
|
const out = [];
|
|
const sparse = !!ns.getMergedTraits().sparse;
|
|
for (const item of value) {
|
|
if (sparse || item != null) {
|
|
out.push(this._read(listMember, item));
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
if (ns.isMapSchema()) {
|
|
const mapMember = ns.getValueSchema();
|
|
const out = {};
|
|
const sparse = !!ns.getMergedTraits().sparse;
|
|
for (const [_k, _v] of Object.entries(value)) {
|
|
if (sparse || _v != null) {
|
|
out[_k] = this._read(mapMember, _v);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
}
|
|
if (ns.isBlobSchema() && typeof value === "string") {
|
|
return fromBase64(value);
|
|
}
|
|
const mediaType = ns.getMergedTraits().mediaType;
|
|
if (ns.isStringSchema() && typeof value === "string" && mediaType) {
|
|
const isJson = mediaType === "application/json" || mediaType.endsWith("+json");
|
|
if (isJson) {
|
|
return LazyJsonString.from(value);
|
|
}
|
|
return value;
|
|
}
|
|
if (ns.isTimestampSchema() && value != null) {
|
|
const format = determineTimestampFormat(ns, this.settings);
|
|
switch (format) {
|
|
case 5:
|
|
return parseRfc3339DateTimeWithOffset(value);
|
|
case 6:
|
|
return parseRfc7231DateTime(value);
|
|
case 7:
|
|
return parseEpochTimestamp(value);
|
|
default:
|
|
console.warn("Missing timestamp format, parsing value with Date constructor:", value);
|
|
return new Date(value);
|
|
}
|
|
}
|
|
if (ns.isBigIntegerSchema() && (typeof value === "number" || typeof value === "string")) {
|
|
return BigInt(value);
|
|
}
|
|
if (ns.isBigDecimalSchema() && value != undefined) {
|
|
if (value instanceof NumericValue) {
|
|
return value;
|
|
}
|
|
const untyped = value;
|
|
if (untyped.type === "bigDecimal" && "string" in untyped) {
|
|
return new NumericValue(untyped.string, untyped.type);
|
|
}
|
|
return new NumericValue(String(value), "bigDecimal");
|
|
}
|
|
if (ns.isNumericSchema() && typeof value === "string") {
|
|
switch (value) {
|
|
case "Infinity":
|
|
return Infinity;
|
|
case "-Infinity":
|
|
return -Infinity;
|
|
case "NaN":
|
|
return NaN;
|
|
}
|
|
return value;
|
|
}
|
|
if (ns.isDocumentSchema()) {
|
|
if (isObject) {
|
|
const out = Array.isArray(value) ? [] : {};
|
|
for (const [k, v] of Object.entries(value)) {
|
|
if (v instanceof NumericValue) {
|
|
out[k] = v;
|
|
}
|
|
else {
|
|
out[k] = this._read(ns, v);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
else {
|
|
return structuredClone(value);
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
}
|