Skip to content

Commit 9abe45a

Browse files
committed
feat: schema
schema generator wip checkpoint: schema codegen compiles in typescript feat: scaffold schema types wip: codec/protocol/transport operation schema rework schemas
1 parent 3db70fa commit 9abe45a

File tree

94 files changed

+7622
-138
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+7622
-138
lines changed

.changeset/nice-deers-shake.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@smithy/smithy-client": minor
3+
"@smithy/types": minor
4+
"@smithy/core": minor
5+
---
6+
7+
implement schema framework

packages/core/package.json

+10
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
"require": "./dist-cjs/submodules/protocols/index.js",
4747
"types": "./dist-types/submodules/protocols/index.d.ts"
4848
},
49+
"./schema": {
50+
"module": "./dist-es/submodules/schema/index.js",
51+
"node": "./dist-cjs/submodules/schema/index.js",
52+
"import": "./dist-es/submodules/schema/index.js",
53+
"require": "./dist-cjs/submodules/schema/index.js",
54+
"types": "./dist-types/submodules/schema/index.d.ts"
55+
},
4956
"./serde": {
5057
"module": "./dist-es/submodules/serde/index.js",
5158
"node": "./dist-cjs/submodules/serde/index.js",
@@ -64,6 +71,7 @@
6471
"@smithy/middleware-serde": "workspace:^",
6572
"@smithy/protocol-http": "workspace:^",
6673
"@smithy/types": "workspace:^",
74+
"@smithy/util-base64": "workspace:^",
6775
"@smithy/util-body-length-browser": "workspace:^",
6876
"@smithy/util-middleware": "workspace:^",
6977
"@smithy/util-stream": "workspace:^",
@@ -85,6 +93,8 @@
8593
"./cbor.js",
8694
"./protocols.d.ts",
8795
"./protocols.js",
96+
"./schema.d.ts",
97+
"./schema.js",
8898
"./serde.d.ts",
8999
"./serde.js",
90100
"dist-*/**"

packages/core/schema.d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Do not edit:
3+
* This is a compatibility redirect for contexts that do not understand package.json exports field.
4+
*/
5+
declare module "@smithy/core/schema" {
6+
export * from "@smithy/core/dist-types/submodules/schema/index.d";
7+
}

packages/core/schema.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
/**
3+
* Do not edit:
4+
* This is a compatibility redirect for contexts that do not understand package.json exports field.
5+
*/
6+
module.exports = require("./dist-cjs/submodules/schema/index.js");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import { NormalizedSchema } from "@smithy/core/schema";
2+
import { copyDocumentWithTransform, parseEpochTimestamp } from "@smithy/core/serde";
3+
import { Codec, Schema, SchemaRef, SerdeContext, ShapeDeserializer, ShapeSerializer } from "@smithy/types";
4+
5+
import { cbor } from "./cbor";
6+
import { dateToTag } from "./parseCborBody";
7+
8+
export class CborCodec implements Codec<Uint8Array, Uint8Array> {
9+
private serdeContext?: SerdeContext;
10+
11+
public createSerializer(): CborShapeSerializer {
12+
const serializer = new CborShapeSerializer();
13+
serializer.setSerdeContext(this.serdeContext!);
14+
return serializer;
15+
}
16+
17+
public createDeserializer(): CborShapeDeserializer {
18+
const deserializer = new CborShapeDeserializer();
19+
deserializer.setSerdeContext(this.serdeContext!);
20+
return deserializer;
21+
}
22+
23+
public setSerdeContext(serdeContext: SerdeContext): void {
24+
this.serdeContext = serdeContext;
25+
}
26+
}
27+
28+
export class CborShapeSerializer implements ShapeSerializer<Uint8Array> {
29+
private serdeContext?: SerdeContext;
30+
private value: unknown;
31+
32+
public setSerdeContext(serdeContext: SerdeContext) {
33+
this.serdeContext = serdeContext;
34+
}
35+
36+
public write(schema: Schema, value: unknown): void {
37+
this.value = copyDocumentWithTransform(value, schema, (_: any, schemaRef: SchemaRef) => {
38+
if (_ instanceof Date) {
39+
return dateToTag(_);
40+
}
41+
if (_ instanceof Uint8Array) {
42+
return _;
43+
}
44+
45+
const ns = NormalizedSchema.of(schemaRef);
46+
const sparse = !!ns.getMergedTraits().sparse;
47+
48+
if (Array.isArray(_)) {
49+
if (!sparse) {
50+
return _.filter((item) => item != null);
51+
}
52+
} else if (_ && typeof _ === "object") {
53+
if (!sparse || ns.isStructSchema()) {
54+
for (const [k, v] of Object.entries(_)) {
55+
if (v == null) {
56+
delete _[k];
57+
}
58+
}
59+
return _;
60+
}
61+
}
62+
63+
return _;
64+
});
65+
}
66+
67+
public flush(): Uint8Array {
68+
const buffer = cbor.serialize(this.value);
69+
this.value = undefined;
70+
return buffer as Uint8Array;
71+
}
72+
}
73+
74+
export class CborShapeDeserializer implements ShapeDeserializer {
75+
private serdeContext?: SerdeContext;
76+
77+
public setSerdeContext(serdeContext: SerdeContext) {
78+
this.serdeContext = serdeContext;
79+
}
80+
81+
public read(schema: Schema, bytes: Uint8Array): any {
82+
const data: any = cbor.deserialize(bytes);
83+
return this.readValue(schema, data);
84+
}
85+
86+
private readValue(_schema: Schema, value: any): any {
87+
const ns = NormalizedSchema.of(_schema);
88+
const schema = ns.getSchema();
89+
90+
if (typeof schema === "number") {
91+
if (ns.isTimestampSchema()) {
92+
// format is ignored.
93+
return parseEpochTimestamp(value);
94+
}
95+
if (ns.isBlobSchema()) {
96+
return value;
97+
}
98+
}
99+
100+
switch (typeof value) {
101+
case "undefined":
102+
case "boolean":
103+
case "number":
104+
case "string":
105+
case "bigint":
106+
case "symbol":
107+
return value;
108+
case "function":
109+
case "object":
110+
if (value === null) {
111+
return null;
112+
}
113+
if ("byteLength" in (value as Uint8Array)) {
114+
return value;
115+
}
116+
if (value instanceof Date) {
117+
return value;
118+
}
119+
if (ns.isDocumentSchema()) {
120+
return value;
121+
}
122+
123+
if (ns.isListSchema()) {
124+
const newArray = [];
125+
const memberSchema = ns.getValueSchema();
126+
const sparse = ns.isListSchema() && !!ns.getMergedTraits().sparse;
127+
128+
for (const item of value) {
129+
newArray.push(this.readValue(memberSchema, item));
130+
if (!sparse && newArray[newArray.length - 1] == null) {
131+
newArray.pop();
132+
}
133+
}
134+
return newArray;
135+
}
136+
137+
const newObject = {} as any;
138+
139+
if (ns.isMapSchema()) {
140+
const sparse = ns.getMergedTraits().sparse;
141+
const targetSchema = ns.getValueSchema();
142+
143+
for (const key of Object.keys(value)) {
144+
newObject[key] = this.readValue(targetSchema, value[key]);
145+
146+
if (newObject[key] == null && !sparse) {
147+
delete newObject[key];
148+
}
149+
}
150+
} else if (ns.isStructSchema()) {
151+
for (const key of Object.keys(value)) {
152+
const targetSchema = ns.getMemberSchema(key);
153+
if (targetSchema === undefined) {
154+
continue;
155+
}
156+
newObject[key] = this.readValue(targetSchema, value[key]);
157+
}
158+
}
159+
return newObject;
160+
default:
161+
return value;
162+
}
163+
}
164+
}

0 commit comments

Comments
 (0)