Skip to content

Commit d105c97

Browse files
authored
add instanceof overrides for schema classes (#1637)
1 parent c2a6b1b commit d105c97

File tree

9 files changed

+107
-6
lines changed

9 files changed

+107
-6
lines changed

.changeset/famous-bulldogs-heal.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@smithy/core": minor
3+
---
4+
5+
add instanceof overrides for schema classes

packages/core/src/submodules/protocols/HttpBindingProtocol.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,7 @@ export abstract class HttpBindingProtocol extends HttpProtocol {
7070
...input,
7171
};
7272

73-
for (const memberName of Object.keys(_input)) {
74-
const memberNs = ns.getMemberSchema(memberName);
75-
if (memberNs === undefined) {
76-
continue;
77-
}
73+
for (const [memberName, memberNs] of ns.structIterator()) {
7874
const memberTraits = memberNs.getMergedTraits();
7975
const inputMember = (_input as any)[memberName] as any;
8076

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import { StructureSchema } from "./StructureSchema";
1212
* @alpha
1313
*/
1414
export class ErrorSchema extends StructureSchema {
15+
public static symbol = Symbol.for("@smithy/core/schema::ErrorSchema");
16+
protected symbol = ErrorSchema.symbol;
17+
1518
public constructor(
1619
public name: string,
1720
public traits: SchemaTraits,
@@ -24,6 +27,15 @@ export class ErrorSchema extends StructureSchema {
2427
) {
2528
super(name, traits, memberNames, memberList);
2629
}
30+
31+
public static [Symbol.hasInstance](lhs: unknown): lhs is ErrorSchema {
32+
const isPrototype = ErrorSchema.prototype.isPrototypeOf(lhs as any);
33+
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
34+
const err = lhs as ErrorSchema;
35+
return err.symbol === ErrorSchema.symbol;
36+
}
37+
return isPrototype;
38+
}
2739
}
2840

2941
/**

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,25 @@ import { Schema } from "./Schema";
1010
* @alpha
1111
*/
1212
export class ListSchema extends Schema implements IListSchema {
13+
public static symbol = Symbol.for("@smithy/core/schema::ListSchema");
14+
protected symbol = ListSchema.symbol;
15+
1316
public constructor(
1417
public name: string,
1518
public traits: SchemaTraits,
1619
public valueSchema: SchemaRef
1720
) {
1821
super(name, traits);
1922
}
23+
24+
public static [Symbol.hasInstance](lhs: unknown): lhs is ListSchema {
25+
const isPrototype = ListSchema.prototype.isPrototypeOf(lhs as any);
26+
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
27+
const list = lhs as ListSchema;
28+
return list.symbol === ListSchema.symbol;
29+
}
30+
return isPrototype;
31+
}
2032
}
2133

2234
/**

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import { Schema } from "./Schema";
88
* @alpha
99
*/
1010
export class MapSchema extends Schema implements IMapSchema {
11+
public static symbol = Symbol.for("@smithy/core/schema::MapSchema");
12+
protected symbol = MapSchema.symbol;
13+
1114
public constructor(
1215
public name: string,
1316
public traits: SchemaTraits,
@@ -19,6 +22,15 @@ export class MapSchema extends Schema implements IMapSchema {
1922
) {
2023
super(name, traits);
2124
}
25+
26+
public static [Symbol.hasInstance](lhs: unknown): lhs is MapSchema {
27+
const isPrototype = MapSchema.prototype.isPrototypeOf(lhs as any);
28+
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
29+
const map = lhs as MapSchema;
30+
return map.symbol === MapSchema.symbol;
31+
}
32+
return isPrototype;
33+
}
2234
}
2335

2436
/**

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import { StructureSchema } from "./StructureSchema";
2121
* @alpha
2222
*/
2323
export class NormalizedSchema implements INormalizedSchema {
24+
public static symbol = Symbol.for("@smithy/core/schema::NormalizedSchema");
25+
protected symbol = NormalizedSchema.symbol;
26+
2427
private readonly name: string;
2528
private readonly traits: SchemaTraits;
2629

@@ -84,11 +87,22 @@ export class NormalizedSchema implements INormalizedSchema {
8487

8588
if (this._isMemberSchema && !memberName) {
8689
throw new Error(
87-
`@smithy/core/schema - NormalizedSchema member schema ${this.getName(true)} must initialize with memberName argument.`
90+
`@smithy/core/schema - NormalizedSchema member schema ${this.getName(
91+
true
92+
)} must initialize with memberName argument.`
8893
);
8994
}
9095
}
9196

97+
public static [Symbol.hasInstance](lhs: unknown): lhs is NormalizedSchema {
98+
const isPrototype = NormalizedSchema.prototype.isPrototypeOf(lhs as any);
99+
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
100+
const ns = lhs as NormalizedSchema;
101+
return ns.symbol === NormalizedSchema.symbol;
102+
}
103+
return isPrototype;
104+
}
105+
92106
/**
93107
* Static constructor that attempts to avoid wrapping a NormalizedSchema within another.
94108
*/

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,25 @@ import { Schema } from "./Schema";
1010
* @alpha
1111
*/
1212
export class SimpleSchema extends Schema implements TraitsSchema {
13+
public static symbol = Symbol.for("@smithy/core/schema::SimpleSchema");
14+
protected symbol = SimpleSchema.symbol;
15+
1316
public constructor(
1417
public name: string,
1518
public schemaRef: SchemaRef,
1619
public traits: SchemaTraits
1720
) {
1821
super(name, traits);
1922
}
23+
24+
public static [Symbol.hasInstance](lhs: unknown): lhs is SimpleSchema {
25+
const isPrototype = SimpleSchema.prototype.isPrototypeOf(lhs as any);
26+
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
27+
const sim = lhs as SimpleSchema;
28+
return sim.symbol === SimpleSchema.symbol;
29+
}
30+
return isPrototype;
31+
}
2032
}
2133

2234
/**

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import { Schema } from "./Schema";
99
* @alpha
1010
*/
1111
export class StructureSchema extends Schema implements IStructureSchema {
12+
public static symbol = Symbol.for("@smithy/core/schema::StructureSchema");
13+
protected symbol = StructureSchema.symbol;
14+
1215
public members: Record<string, [SchemaRef, SchemaTraits]> = {};
1316

1417
public constructor(
@@ -24,6 +27,15 @@ export class StructureSchema extends Schema implements IStructureSchema {
2427
: [memberList[i], 0];
2528
}
2629
}
30+
31+
public static [Symbol.hasInstance](lhs: unknown): lhs is StructureSchema {
32+
const isPrototype = StructureSchema.prototype.isPrototypeOf(lhs as any);
33+
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
34+
const struct = lhs as StructureSchema;
35+
return struct.symbol === StructureSchema.symbol;
36+
}
37+
return isPrototype;
38+
}
2739
}
2840

2941
/**

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ describe("schemas", () => {
4949
expect(error("ack", "Error", 0, [], [], Error)).toEqual(schema);
5050
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
5151
});
52+
53+
it("has an instanceOf operator", () => {
54+
const object = { ...schema };
55+
expect(ErrorSchema.prototype.isPrototypeOf(object)).toBe(false);
56+
expect(object).toBeInstanceOf(ErrorSchema);
57+
});
5258
});
5359
describe(ListSchema.name, () => {
5460
const schema = new ListSchema("ack#List", 0, 0);
@@ -62,6 +68,11 @@ describe("schemas", () => {
6268
expect(list("ack", "List", 0, 0)).toEqual(schema);
6369
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
6470
});
71+
it("has an instanceOf operator", () => {
72+
const object = { ...schema };
73+
expect(ListSchema.prototype.isPrototypeOf(object)).toBe(false);
74+
expect(object).toBeInstanceOf(ListSchema);
75+
});
6576
});
6677
describe(MapSchema.name, () => {
6778
const schema = new MapSchema("ack#Map", 0, 0, 1);
@@ -76,6 +87,11 @@ describe("schemas", () => {
7687
expect(map("ack", "Map", 0, 0, 1)).toEqual(schema);
7788
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
7889
});
90+
it("has an instanceOf operator", () => {
91+
const object = { ...schema };
92+
expect(MapSchema.prototype.isPrototypeOf(object)).toBe(false);
93+
expect(object).toBeInstanceOf(MapSchema);
94+
});
7995
});
8096
describe(OperationSchema.name, () => {
8197
const schema = new OperationSchema("ack#Operation", 0, "unit", "unit");
@@ -119,6 +135,11 @@ describe("schemas", () => {
119135
expect(sim("ack", "Simple", 0, 0)).toEqual(schema);
120136
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
121137
});
138+
it("has an instanceOf operator", () => {
139+
const object = { ...schema };
140+
expect(SimpleSchema.prototype.isPrototypeOf(object)).toBe(false);
141+
expect(object).toBeInstanceOf(SimpleSchema);
142+
});
122143
});
123144
describe(StructureSchema.name, () => {
124145
const schema = new StructureSchema("ack#Structure", 0, ["a", "b", "c"], [0, 1, 2]);
@@ -136,5 +157,10 @@ describe("schemas", () => {
136157
expect(struct("ack", "Structure", 0, ["a", "b", "c"], [0, 1, 2])).toEqual(schema);
137158
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
138159
});
160+
it("has an instanceOf operator", () => {
161+
const object = { ...schema };
162+
expect(StructureSchema.prototype.isPrototypeOf(object)).toBe(false);
163+
expect(object).toBeInstanceOf(StructureSchema);
164+
});
139165
});
140166
});

0 commit comments

Comments
 (0)