Skip to content

Commit 527d7a5

Browse files
committed
feat(core/schema): add docblocks
1 parent 3d59290 commit 527d7a5

File tree

13 files changed

+187
-29
lines changed

13 files changed

+187
-29
lines changed

packages/core/src/submodules/schema/TypeRegistry.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { describe, test as it, expect } from "vitest";
2-
import { TypeRegistry } from "./TypeRegistry";
1+
import { describe, expect, test as it } from "vitest";
2+
3+
import { error } from "./schemas/ErrorSchema";
34
import { list } from "./schemas/ListSchema";
45
import { map } from "./schemas/MapSchema";
56
import { struct } from "./schemas/StructureSchema";
6-
import { error } from "./schemas/ErrorSchema";
7+
import { TypeRegistry } from "./TypeRegistry";
78

89
describe(TypeRegistry.name, () => {
910
const [List, Map, Struct] = [list("ack", "List", { sparse: 1 }, 0), map("ack", "Map", 0, 0, 1), () => schema];

packages/core/src/submodules/schema/TypeRegistry.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ export class TypeRegistry {
2828
}
2929

3030
/**
31-
* The active type registry's namespace is used.
31+
* Adds the given schema to a type registry with the same namespace.
32+
*
3233
* @param shapeId - to be registered.
3334
* @param schema - to be registered.
3435
*/
@@ -50,6 +51,19 @@ export class TypeRegistry {
5051
return this.schemas.get(id)!;
5152
}
5253

54+
/**
55+
* The smithy-typescript code generator generates a synthetic (i.e. unmodeled) base exception,
56+
* because generated SDKs before the introduction of schemas have the notion of a ServiceBaseException, which
57+
* is unique per service/model.
58+
*
59+
* This is generated under a unique prefix that is combined with the service namespace, and this
60+
* method is used to retrieve it.
61+
*
62+
* The base exception synthetic schema is used when an error is returned by a service, but we cannot
63+
* determine what existing schema to use to deserialize it.
64+
*
65+
* @returns the synthetic base exception of the service namespace associated with this registry instance.
66+
*/
5367
public getBaseException(): ErrorSchema | undefined {
5468
for (const [id, schema] of this.schemas.entries()) {
5569
if (id.startsWith("smithyts.client.synthetic.") && id.endsWith("ServiceException")) {
@@ -59,10 +73,17 @@ export class TypeRegistry {
5973
return undefined;
6074
}
6175

62-
public find(seeker: (schema: ISchema) => boolean) {
63-
return [...this.schemas.values()].find(seeker);
76+
/**
77+
* @param predicate - criterion.
78+
* @returns a schema in this registry matching the predicate.
79+
*/
80+
public find(predicate: (schema: ISchema) => boolean) {
81+
return [...this.schemas.values()].find(predicate);
6482
}
6583

84+
/**
85+
* Unloads the current TypeRegistry.
86+
*/
6687
public destroy() {
6788
TypeRegistry.registries.delete(this.namespace);
6889
this.schemas.clear();

packages/core/src/submodules/schema/schemas/ErrorSchema.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ import type { SchemaRef, SchemaTraits } from "@smithy/types";
33
import { TypeRegistry } from "../TypeRegistry";
44
import { StructureSchema } from "./StructureSchema";
55

6+
/**
7+
* A schema for a structure shape having the error trait. These represent enumerated operation errors.
8+
* Because Smithy-TS SDKs use classes for exceptions, whereas plain objects are used for all other data,
9+
* and have an existing notion of a XYZServiceBaseException, the ErrorSchema differs from a StructureSchema
10+
* by additionally holding the class reference for the corresponding ServiceException class.
11+
*
12+
* @public
13+
*/
614
export class ErrorSchema extends StructureSchema {
715
public constructor(
816
public name: string,
@@ -18,6 +26,18 @@ export class ErrorSchema extends StructureSchema {
1826
}
1927
}
2028

29+
/**
30+
* Factory for ErrorSchema, to reduce codegen output and register the schema.
31+
*
32+
* @internal
33+
*
34+
* @param namespace - shapeId namespace.
35+
* @param name - shapeId name.
36+
* @param traits - shape level serde traits.
37+
* @param memberNames - list of member names.
38+
* @param memberList - list of schemaRef corresponding to each
39+
* @param ctor - class reference for the existing Error extending class.
40+
*/
2141
export function error(
2242
namespace: string,
2343
name: string,

packages/core/src/submodules/schema/schemas/ListSchema.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import type { ListSchema as IListSchema, SchemaRef, SchemaTraits } from "@smithy
33
import { TypeRegistry } from "../TypeRegistry";
44
import { Schema } from "./Schema";
55

6+
/**
7+
* A schema with a single member schema.
8+
* The deprecated Set type may be represented as a list.
9+
*
10+
* @public
11+
*/
612
export class ListSchema extends Schema implements IListSchema {
713
public constructor(
814
public name: string,
@@ -13,6 +19,11 @@ export class ListSchema extends Schema implements IListSchema {
1319
}
1420
}
1521

22+
/**
23+
* Factory for ListSchema.
24+
*
25+
* @internal
26+
*/
1627
export function list(namespace: string, name: string, traits: SchemaTraits = {}, valueSchema: SchemaRef): ListSchema {
1728
const schema = new ListSchema(
1829
namespace + "#" + name,

packages/core/src/submodules/schema/schemas/MapSchema.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import type { MapSchema as IMapSchema, SchemaRef, SchemaTraits } from "@smithy/t
33
import { TypeRegistry } from "../TypeRegistry";
44
import { Schema } from "./Schema";
55

6+
/**
7+
* A schema with a key schema and value schema.
8+
* @public
9+
*/
610
export class MapSchema extends Schema implements IMapSchema {
711
public constructor(
812
public name: string,
@@ -17,6 +21,10 @@ export class MapSchema extends Schema implements IMapSchema {
1721
}
1822
}
1923

24+
/**
25+
* Factory for MapSchema.
26+
* @internal
27+
*/
2028
export function map(
2129
namespace: string,
2230
name: string,

packages/core/src/submodules/schema/schemas/NormalizedSchema.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
import { MemberSchema } from "@smithy/types";
12
import { describe, expect, test as it } from "vitest";
23

34
import { list } from "./ListSchema";
45
import { map } from "./MapSchema";
56
import { NormalizedSchema } from "./NormalizedSchema";
6-
import { struct } from "./StructureSchema";
7-
import { sim } from "./SimpleSchema";
8-
import { MemberSchema } from "@smithy/types";
97
import { SCHEMA } from "./sentinels";
8+
import { sim } from "./SimpleSchema";
9+
import { struct } from "./StructureSchema";
1010

1111
describe(NormalizedSchema.name, () => {
1212
const [List, Map, Struct] = [list("ack", "List", { sparse: 1 }, 0), map("ack", "Map", 0, 0, 1), () => schema];

packages/core/src/submodules/schema/schemas/NormalizedSchema.ts

Lines changed: 80 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,26 @@ import { SimpleSchema } from "./SimpleSchema";
1515
import { StructureSchema } from "./StructureSchema";
1616

1717
/**
18-
* Wraps SchemaRef values for easier handling.
19-
* @internal
18+
* Wraps both class instances, numeric sentinel values, and member schema pairs.
19+
* Presents a consistent interface for interacting with polymorphic schema representations.
20+
*
21+
* @public
2022
*/
2123
export class NormalizedSchema implements INormalizedSchema {
22-
public readonly name: string;
23-
public readonly traits: SchemaTraits;
24+
private readonly name: string;
25+
private readonly traits: SchemaTraits;
2426

2527
private _isMemberSchema: boolean;
26-
private schema: Exclude<ISchema, MemberSchema>;
28+
private schema: Exclude<ISchema, MemberSchema | INormalizedSchema>;
2729
private memberTraits: SchemaTraits;
2830
private normalizedTraits?: SchemaTraitsObject;
2931

32+
/**
33+
* @param ref - a polymorphic SchemaRef to be dereferenced/normalized.
34+
* @param memberName - optional memberName if this NormalizedSchema should be considered a member schema.
35+
*/
3036
public constructor(
31-
public readonly ref: SchemaRef,
37+
private readonly ref: SchemaRef,
3238
private memberName?: string
3339
) {
3440
const traitStack = [] as SchemaTraits[];
@@ -65,7 +71,7 @@ export class NormalizedSchema implements INormalizedSchema {
6571
return;
6672
}
6773

68-
this.schema = deref(schema) as Exclude<ISchema, MemberSchema>;
74+
this.schema = deref(schema) as Exclude<ISchema, MemberSchema | INormalizedSchema>;
6975

7076
if (this.schema && typeof this.schema === "object") {
7177
this.traits = this.schema?.traits ?? {};
@@ -83,6 +89,9 @@ export class NormalizedSchema implements INormalizedSchema {
8389
}
8490
}
8591

92+
/**
93+
* Static constructor that attempts to avoid wrapping a NormalizedSchema within another.
94+
*/
8695
public static of(ref: SchemaRef, memberName?: string): NormalizedSchema {
8796
if (ref instanceof NormalizedSchema) {
8897
return ref;
@@ -124,7 +133,13 @@ export class NormalizedSchema implements INormalizedSchema {
124133
return traits;
125134
}
126135

127-
private static memberFrom(memberSchema: [SchemaRef, SchemaTraits], memberName: string): NormalizedSchema {
136+
/**
137+
* Creates a normalized member schema from the given schema and member name.
138+
*/
139+
private static memberFrom(
140+
memberSchema: NormalizedSchema | [SchemaRef, SchemaTraits],
141+
memberName: string
142+
): NormalizedSchema {
128143
if (memberSchema instanceof NormalizedSchema) {
129144
memberSchema.memberName = memberName;
130145
memberSchema._isMemberSchema = true;
@@ -133,16 +148,23 @@ export class NormalizedSchema implements INormalizedSchema {
133148
return new NormalizedSchema(memberSchema, memberName);
134149
}
135150

136-
public getSchema(): Exclude<ISchema, MemberSchema> {
151+
/**
152+
* @returns the underlying non-normalized schema.
153+
*/
154+
public getSchema(): Exclude<ISchema, MemberSchema | INormalizedSchema> {
137155
if (this.schema instanceof NormalizedSchema) {
138156
return (this.schema = this.schema.getSchema());
139157
}
140158
if (this.schema instanceof SimpleSchema) {
141-
return deref(this.schema.schemaRef) as Exclude<ISchema, MemberSchema>;
159+
return deref(this.schema.schemaRef) as Exclude<ISchema, MemberSchema | INormalizedSchema>;
142160
}
143-
return deref(this.schema) as Exclude<ISchema, MemberSchema>;
161+
return deref(this.schema) as Exclude<ISchema, MemberSchema | INormalizedSchema>;
144162
}
145163

164+
/**
165+
* @param withNamespace - qualifies the name.
166+
* @returns e.g. `MyShape` or `com.namespace#MyShape`.
167+
*/
146168
public getName(withNamespace = false): string | undefined {
147169
if (!withNamespace) {
148170
if (this.name && this.name.includes("#")) {
@@ -153,6 +175,10 @@ export class NormalizedSchema implements INormalizedSchema {
153175
return this.name || undefined;
154176
}
155177

178+
/**
179+
* @returns the member name if the schema is a member schema.
180+
* @throws Error when the schema isn't a member schema.
181+
*/
156182
public getMemberName(): string {
157183
if (!this.isMemberSchema()) {
158184
throw new Error(`@smithy/core/schema - cannot get member name on non-member schema: ${this.getName(true)}`);
@@ -168,6 +194,9 @@ export class NormalizedSchema implements INormalizedSchema {
168194
return this.getSchema() === ("unit" as const);
169195
}
170196

197+
/**
198+
* boolean methods on this class help control flow in shape serialization and deserialization.
199+
*/
171200
public isListSchema(): boolean {
172201
const inner = this.getSchema();
173202
if (typeof inner === "number") {
@@ -230,6 +259,10 @@ export class NormalizedSchema implements INormalizedSchema {
230259
return this.getSchema() === SCHEMA.STREAMING_BLOB;
231260
}
232261

262+
/**
263+
* @returns own traits merged with member traits, where member traits of the same trait key take priority.
264+
* This method is cached.
265+
*/
233266
public getMergedTraits(): SchemaTraitsObject {
234267
if (this.normalizedTraits) {
235268
return this.normalizedTraits;
@@ -241,14 +274,26 @@ export class NormalizedSchema implements INormalizedSchema {
241274
return this.normalizedTraits;
242275
}
243276

277+
/**
278+
* @returns only the member traits. If the schema is not a member, this returns empty.
279+
*/
244280
public getMemberTraits(): SchemaTraitsObject {
245281
return NormalizedSchema.translateTraits(this.memberTraits);
246282
}
247283

284+
/**
285+
* @returns only the traits inherent to the shape or member target shape if this schema is a member.
286+
* If there are any member traits they are excluded.
287+
*/
248288
public getOwnTraits(): SchemaTraitsObject {
249289
return NormalizedSchema.translateTraits(this.traits);
250290
}
251291

292+
/**
293+
* @returns the map's key's schema. Returns a dummy Document schema if this schema is a Document.
294+
*
295+
* @throws Error if the schema is not a Map or Document.
296+
*/
252297
public getKeySchema(): NormalizedSchema {
253298
if (this.isDocumentSchema()) {
254299
return NormalizedSchema.memberFrom([SCHEMA.DOCUMENT, 0], "key");
@@ -263,6 +308,12 @@ export class NormalizedSchema implements INormalizedSchema {
263308
return NormalizedSchema.memberFrom([(schema as MapSchema).keySchema, 0], "key");
264309
}
265310

311+
/**
312+
* @returns the schema of the map's value or list's member.
313+
* Returns a dummy Document schema if this schema is a Document.
314+
*
315+
* @throws Error if the schema is not a Map, List, nor Document.
316+
*/
266317
public getValueSchema(): NormalizedSchema {
267318
const schema = this.getSchema();
268319

@@ -295,12 +346,21 @@ export class NormalizedSchema implements INormalizedSchema {
295346
throw new Error(`@smithy/core/schema - the schema ${this.getName(true)} does not have a value member.`);
296347
}
297348

298-
public getMemberSchema(member: string): NormalizedSchema | undefined {
349+
/**
350+
* @returns the NormalizedSchema for the given member name. The returned instance will return true for `isMemberSchema()`
351+
* and will have the member name given.
352+
* @param member - which member to retrieve and wrap.
353+
*
354+
* @throws Error if member does not exist or the schema is neither a document nor structure.
355+
* Note that errors are assumed to be structures and unions are considered structures for these purposes.
356+
*/
357+
public getMemberSchema(member: string): NormalizedSchema {
299358
if (this.isStructSchema()) {
300359
const struct = this.getSchema() as StructureSchema;
301360
if (!(member in struct.members)) {
302-
// indicates the member is not recognized.
303-
return undefined;
361+
throw new Error(
362+
`@smithy/core/schema - the schema ${this.getName(true)} does not have a member with name=${member}.`
363+
);
304364
}
305365
return NormalizedSchema.memberFrom(struct.members[member], member);
306366
}
@@ -310,6 +370,9 @@ export class NormalizedSchema implements INormalizedSchema {
310370
throw new Error(`@smithy/core/schema - the schema ${this.getName(true)} does not have members.`);
311371
}
312372

373+
/**
374+
* @returns a map of member names to member schemas (normalized).
375+
*/
313376
public getMemberSchemas(): Record<string, NormalizedSchema> {
314377
const { schema } = this;
315378
const struct = schema as StructureSchema;
@@ -326,6 +389,9 @@ export class NormalizedSchema implements INormalizedSchema {
326389
return {};
327390
}
328391

392+
/**
393+
* @returns a last-resort human-readable name for the schema if it has no other identifiers.
394+
*/
329395
private getSchemaName(): string {
330396
const schema = this.getSchema();
331397
if (typeof schema === "number") {

packages/core/src/submodules/schema/schemas/OperationSchema.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import type { OperationSchema as IOperationSchema, SchemaRef, SchemaTraits } fro
33
import { TypeRegistry } from "../TypeRegistry";
44
import { Schema } from "./Schema";
55

6+
/**
7+
* This is used as a reference container for the input/output pair of schema, and for trait
8+
* detection on the operation that may affect client protocol logic.
9+
*
10+
* @public
11+
*/
612
export class OperationSchema extends Schema implements IOperationSchema {
713
public constructor(
814
public name: string,
@@ -14,6 +20,10 @@ export class OperationSchema extends Schema implements IOperationSchema {
1420
}
1521
}
1622

23+
/**
24+
* Factory for OperationSchema.
25+
* @internal
26+
*/
1727
export function op(
1828
namespace: string,
1929
name: string,

0 commit comments

Comments
 (0)