Skip to content

Commit c855967

Browse files
committed
feat: schema
schema generator wip checkpoint: schema codegen compiles in typescript feat: scaffold schema types wip: codec/protocol/transport operation schema
1 parent f0562fe commit c855967

File tree

69 files changed

+3088
-162
lines changed

Some content is hidden

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

69 files changed

+3088
-162
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

+9
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@
4545
"import": "./dist-es/submodules/protocols/index.js",
4646
"require": "./dist-cjs/submodules/protocols/index.js",
4747
"types": "./dist-types/submodules/protocols/index.d.ts"
48+
},
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"
4855
}
4956
},
5057
"author": {
@@ -78,6 +85,8 @@
7885
"./cbor.js",
7986
"./protocols.d.ts",
8087
"./protocols.js",
88+
"./schema.d.ts",
89+
"./schema.js",
8190
"dist-*/**"
8291
],
8392
"homepage": "https://github.com/awslabs/smithy-typescript/tree/main/packages/core",

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,140 @@
1+
import { deref, ListSchema, MapSchema, StructureSchema } from "@smithy/core/schema";
2+
import { copyDocumentWithTransform, parseEpochTimestamp } from "@smithy/smithy-client";
3+
import {
4+
Codec,
5+
MemberSchema,
6+
Schema,
7+
SchemaRef,
8+
ShapeDeserializer,
9+
ShapeSerializer,
10+
TraitsSchema,
11+
} from "@smithy/types";
12+
13+
import { cbor } from "./cbor";
14+
import { dateToTag } from "./parseCborBody";
15+
16+
export class CborCodec implements Codec {
17+
public createSerializer(): CborShapeSerializer {
18+
return new CborShapeSerializer();
19+
}
20+
public createDeserializer(): CborShapeDeserializer {
21+
return new CborShapeDeserializer();
22+
}
23+
}
24+
25+
export class CborShapeSerializer implements ShapeSerializer {
26+
private value: unknown;
27+
28+
public write(schema: Schema, value: unknown): void {
29+
this.value = copyDocumentWithTransform(value, schema, (_: any, schemaRef: SchemaRef) => {
30+
if (_ instanceof Date) {
31+
return dateToTag(_);
32+
}
33+
const schema = deref((schemaRef as MemberSchema)?.[0] ?? schemaRef);
34+
if (_ instanceof Uint8Array) {
35+
return _;
36+
}
37+
const sparse = (schema as TraitsSchema)?.traits?.sparse;
38+
if (Array.isArray(_)) {
39+
if (!sparse) {
40+
return _.filter((item) => item != null);
41+
}
42+
} else if (_ && typeof _ === "object") {
43+
if (!sparse) {
44+
for (const [k, v] of Object.entries(_)) {
45+
if (v == null) {
46+
delete _[k];
47+
}
48+
}
49+
return _;
50+
}
51+
}
52+
return _;
53+
});
54+
}
55+
56+
public async flush(): Promise<Uint8Array> {
57+
const buffer = cbor.serialize(this.value);
58+
this.value = undefined;
59+
return buffer as Uint8Array;
60+
}
61+
}
62+
63+
export class CborShapeDeserializer implements ShapeDeserializer {
64+
public read(schema: Schema, bytes: Uint8Array): any {
65+
const data: any = cbor.deserialize(bytes);
66+
return this.readValue(schema, data);
67+
}
68+
69+
private readValue(schema: Schema, value: any): any {
70+
if (typeof schema === "string") {
71+
if (schema === "time" || schema === "epoch-seconds" || schema === "date-time") {
72+
return parseEpochTimestamp(value);
73+
}
74+
if (schema === "blob") {
75+
return value;
76+
}
77+
}
78+
switch (typeof value) {
79+
case "undefined":
80+
case "boolean":
81+
case "number":
82+
case "string":
83+
case "bigint":
84+
case "symbol":
85+
return value;
86+
case "function":
87+
case "object":
88+
if (value === null) {
89+
return null;
90+
}
91+
if ("byteLength" in (value as Uint8Array)) {
92+
return value;
93+
}
94+
if (value instanceof Date) {
95+
return value;
96+
}
97+
const traits =
98+
Array.isArray(schema) && schema.length >= 2
99+
? {
100+
...(deref((schema as MemberSchema)[0]) as TraitsSchema)?.traits,
101+
...(schema as MemberSchema)[1],
102+
}
103+
: (deref(schema) as TraitsSchema)?.traits;
104+
105+
if (Array.isArray(value)) {
106+
const newArray = [];
107+
for (const item of value) {
108+
newArray.push(this.readValue(schema instanceof ListSchema ? deref(schema.valueSchema) : void 0, item));
109+
if (!traits?.sparse) {
110+
if (newArray[newArray.length - 1] == null) {
111+
newArray.pop();
112+
}
113+
}
114+
}
115+
return newArray;
116+
}
117+
118+
const newObject = {} as any;
119+
for (const key of Object.keys(value)) {
120+
const targetSchema =
121+
schema instanceof StructureSchema
122+
? deref(schema.members[key]?.[0])
123+
: schema instanceof MapSchema
124+
? deref(schema.valueSchema)
125+
: void 0;
126+
newObject[key] = this.readValue(targetSchema, value[key]);
127+
if (!traits?.sparse && newObject[key] == null) {
128+
delete newObject[key];
129+
}
130+
}
131+
return newObject;
132+
default:
133+
return value;
134+
}
135+
}
136+
137+
public getContainerSize(): number {
138+
throw new Error("Method not implemented.");
139+
}
140+
}

0 commit comments

Comments
 (0)