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>
160 lines
6.3 KiB
Text
160 lines
6.3 KiB
Text
import { determineTimestampFormat } from "@smithy/core/protocols";
|
|
import { NormalizedSchema } from "@smithy/core/schema";
|
|
import { dateToUtcString, generateIdempotencyToken, LazyJsonString, NumericValue } from "@smithy/core/serde";
|
|
import { toBase64 } from "@smithy/util-base64";
|
|
import { SerdeContextConfig } from "../ConfigurableSerdeContext";
|
|
import { serializingStructIterator } from "../structIterator";
|
|
import { JsonReplacer } from "./jsonReplacer";
|
|
export class JsonShapeSerializer extends SerdeContextConfig {
|
|
settings;
|
|
buffer;
|
|
useReplacer = false;
|
|
rootSchema;
|
|
constructor(settings) {
|
|
super();
|
|
this.settings = settings;
|
|
}
|
|
write(schema, value) {
|
|
this.rootSchema = NormalizedSchema.of(schema);
|
|
this.buffer = this._write(this.rootSchema, value);
|
|
}
|
|
writeDiscriminatedDocument(schema, value) {
|
|
this.write(schema, value);
|
|
if (typeof this.buffer === "object") {
|
|
this.buffer.__type = NormalizedSchema.of(schema).getName(true);
|
|
}
|
|
}
|
|
flush() {
|
|
const { rootSchema, useReplacer } = this;
|
|
this.rootSchema = undefined;
|
|
this.useReplacer = false;
|
|
if (rootSchema?.isStructSchema() || rootSchema?.isDocumentSchema()) {
|
|
if (!useReplacer) {
|
|
return JSON.stringify(this.buffer);
|
|
}
|
|
const replacer = new JsonReplacer();
|
|
return replacer.replaceInJson(JSON.stringify(this.buffer, replacer.createReplacer(), 0));
|
|
}
|
|
return this.buffer;
|
|
}
|
|
_write(schema, value, container) {
|
|
const isObject = value !== null && typeof value === "object";
|
|
const ns = NormalizedSchema.of(schema);
|
|
if (isObject) {
|
|
if (ns.isStructSchema()) {
|
|
const out = {};
|
|
for (const [memberName, memberSchema] of serializingStructIterator(ns, value)) {
|
|
const serializableValue = this._write(memberSchema, value[memberName], ns);
|
|
if (serializableValue !== undefined) {
|
|
const jsonName = memberSchema.getMergedTraits().jsonName;
|
|
const targetKey = this.settings.jsonName ? jsonName ?? memberName : memberName;
|
|
out[targetKey] = serializableValue;
|
|
}
|
|
}
|
|
if (ns.isUnionSchema() && Object.keys(out).length === 0) {
|
|
const { $unknown } = value;
|
|
if (Array.isArray($unknown)) {
|
|
const [k, v] = $unknown;
|
|
out[k] = this._write(15, v);
|
|
}
|
|
}
|
|
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._write(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._write(mapMember, _v);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
if (value instanceof Uint8Array && (ns.isBlobSchema() || ns.isDocumentSchema())) {
|
|
if (ns === this.rootSchema) {
|
|
return value;
|
|
}
|
|
return (this.serdeContext?.base64Encoder ?? toBase64)(value);
|
|
}
|
|
if (value instanceof Date && (ns.isTimestampSchema() || ns.isDocumentSchema())) {
|
|
const format = determineTimestampFormat(ns, this.settings);
|
|
switch (format) {
|
|
case 5:
|
|
return value.toISOString().replace(".000Z", "Z");
|
|
case 6:
|
|
return dateToUtcString(value);
|
|
case 7:
|
|
return value.getTime() / 1000;
|
|
default:
|
|
console.warn("Missing timestamp format, using epoch seconds", value);
|
|
return value.getTime() / 1000;
|
|
}
|
|
}
|
|
if (value instanceof NumericValue) {
|
|
this.useReplacer = true;
|
|
}
|
|
}
|
|
if (value === null && container?.isStructSchema()) {
|
|
return void 0;
|
|
}
|
|
if (ns.isStringSchema()) {
|
|
if (typeof value === "undefined" && ns.isIdempotencyToken()) {
|
|
return generateIdempotencyToken();
|
|
}
|
|
const mediaType = ns.getMergedTraits().mediaType;
|
|
if (value != null && mediaType) {
|
|
const isJson = mediaType === "application/json" || mediaType.endsWith("+json");
|
|
if (isJson) {
|
|
return LazyJsonString.from(value);
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
if (typeof value === "number" && ns.isNumericSchema()) {
|
|
if (Math.abs(value) === Infinity || isNaN(value)) {
|
|
return String(value);
|
|
}
|
|
return value;
|
|
}
|
|
if (typeof value === "string" && ns.isBlobSchema()) {
|
|
if (ns === this.rootSchema) {
|
|
return value;
|
|
}
|
|
return (this.serdeContext?.base64Encoder ?? toBase64)(value);
|
|
}
|
|
if (typeof value === "bigint") {
|
|
this.useReplacer = true;
|
|
}
|
|
if (ns.isDocumentSchema()) {
|
|
if (isObject) {
|
|
const out = Array.isArray(value) ? [] : {};
|
|
for (const [k, v] of Object.entries(value)) {
|
|
if (v instanceof NumericValue) {
|
|
this.useReplacer = true;
|
|
out[k] = v;
|
|
}
|
|
else {
|
|
out[k] = this._write(ns, v);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
else {
|
|
return structuredClone(value);
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
}
|