Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/hungry-mayflies-confess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@smithy/core": patch
"@smithy/types": patch
---

fix ordering of static simple schema type
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
ResponseMetadata,
RetryableTrait,
SchemaRef,
StaticErrorSchema,
StringSchema,
TimestampDefaultSchema,
} from "@smithy/types";
Expand Down Expand Up @@ -306,6 +307,14 @@ describe(SmithyRpcV2CborProtocol.name, () => {
}),
});

const errorResponseNoDiscriminator = new HttpResponse({
statusCode: 404,
headers: {},
body: cbor.serialize({
modeledProperty: "oh no",
}),
});

const serdeContext = {};

class ServiceBaseException extends Error {
Expand All @@ -326,18 +335,31 @@ describe(SmithyRpcV2CborProtocol.name, () => {

beforeEach(() => {
ns.clear();
synthetic.clear();
});

const modeledExceptionSchema = error("ns", "ModeledException", 0, ["modeledProperty"], [0], null);
const baseServiceExceptionSchema = error("smithy.ts.sdk.synthetic.ns", "BaseServiceException", 0, [], [], null);
const modeledExceptionSchema = [
-3,
"ns",
"ModeledException",
0,
["modeledProperty"],
[0],
] satisfies StaticErrorSchema;
const baseServiceExceptionSchema = [
-3,
"smithy.ts.sdk.synthetic.ns",
"BaseServiceException",
0,
[],
[],
] satisfies StaticErrorSchema;

it("should throw the schema error ctor if one exists", async () => {
// this is for modeled exceptions.

ns.register(modeledExceptionSchema.getName(), modeledExceptionSchema);
ns.registerError(modeledExceptionSchema, ModeledExceptionCtor);

synthetic.register(baseServiceExceptionSchema.getName(), baseServiceExceptionSchema);
synthetic.registerError(baseServiceExceptionSchema, ServiceBaseException);

try {
Expand All @@ -353,11 +375,10 @@ describe(SmithyRpcV2CborProtocol.name, () => {
it("should throw a base error if available in the namespace, when no error schema is modeled", async () => {
// this is the expected fallback case for all generated clients.

synthetic.register(baseServiceExceptionSchema.getName(), baseServiceExceptionSchema);
synthetic.registerError(baseServiceExceptionSchema, ServiceBaseException);

try {
await protocol.deserializeResponse(operation, serdeContext as any, errorResponse);
await protocol.deserializeResponse(operation, serdeContext as any, errorResponseNoDiscriminator);
} catch (e) {
expect(e).toBeInstanceOf(ServiceBaseException);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
OperationSchema,
ResponseMetadata,
SerdeFunctions,
StaticErrorSchema,
} from "@smithy/types";
import { getSmithyContext } from "@smithy/util-middleware";

Expand Down Expand Up @@ -104,9 +105,9 @@ export class SmithyRpcV2CborProtocol extends RpcProtocol {

const registry = TypeRegistry.for(namespace);

let errorSchema: ErrorSchema;
let errorSchema: StaticErrorSchema;
try {
errorSchema = registry.getSchema(errorName) as ErrorSchema;
errorSchema = registry.getSchema(errorName) as StaticErrorSchema;
} catch (e) {
if (dataObject.Message) {
dataObject.message = dataObject.Message;
Expand Down
17 changes: 14 additions & 3 deletions packages/core/src/submodules/schema/TypeRegistry.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { StaticErrorSchema } from "@smithy/types";
import { describe, expect, test as it } from "vitest";

import { error } from "./schemas/ErrorSchema";
import { list } from "./schemas/ListSchema";
import { map } from "./schemas/MapSchema";
import { struct } from "./schemas/StructureSchema";
Expand All @@ -16,15 +16,26 @@ describe(TypeRegistry.name, () => {

it("stores and retrieves schema objects", () => {
const tr = TypeRegistry.for("NAMESPACE");
tr.register(List.getName(), List);
expect(tr.getSchema("List")).toBe(List);
tr.register(Map.getName(), Map);
expect(tr.getSchema("Map")).toBe(Map);
tr.register(Struct().getName(), Struct());
expect(tr.getSchema("Structure")).toBe(schema);
});

it("has a helper method to retrieve a synthetic base exception", () => {
// the service namespace is appended to the synthetic prefix.
const err = error("smithy.ts.sdk.synthetic.NAMESPACE", "UhOhServiceException", 0, [], [], Error);
const tr = TypeRegistry.for("smithy.ts.sdk.synthetic.NAMESPACE");
const err = [
-3,
"smithy.ts.sdk.synthetic.NAMESPACE",
"UhOhServiceException",
0,
[],
[],
] satisfies StaticErrorSchema;
const tr = TypeRegistry.for(err[1]);
tr.registerError(err, Error);
expect(tr.getBaseException()).toBe(err);
});
});
28 changes: 17 additions & 11 deletions packages/core/src/submodules/schema/TypeRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export class TypeRegistry {
*/
public register(shapeId: string, schema: ISchema) {
const qualifiedName = this.normalizeShapeId(shapeId);
this.schemas.set(qualifiedName, schema);
const registry = TypeRegistry.for(qualifiedName.split("#")[0]);
registry.schemas.set(qualifiedName, schema);
}

/**
Expand All @@ -54,15 +55,20 @@ export class TypeRegistry {
* Associates an error schema with its constructor.
*/
public registerError(es: ErrorSchema | StaticErrorSchema, ctor: any) {
this.exceptions.set(es, ctor);
const $error = es as StaticErrorSchema;
const registry = TypeRegistry.for($error[1]);
registry.schemas.set($error[1] + "#" + $error[2], $error);
registry.exceptions.set($error, ctor);
}

/**
* @param es - query.
* @returns Error constructor that extends the service's base exception.
*/
public getErrorCtor(es: ErrorSchema | StaticErrorSchema): any {
return this.exceptions.get(es);
const $error = es as StaticErrorSchema;
const registry = TypeRegistry.for($error[1]);
return registry.exceptions.get(es);
}

/**
Expand All @@ -78,10 +84,14 @@ export class TypeRegistry {
*
* @returns the synthetic base exception of the service namespace associated with this registry instance.
*/
public getBaseException(): ErrorSchema | undefined {
for (const [id, schema] of this.schemas.entries()) {
if (id.startsWith("smithy.ts.sdk.synthetic.") && id.endsWith("ServiceException")) {
return schema as ErrorSchema;
public getBaseException(): StaticErrorSchema | undefined {
for (const exceptionKey of this.exceptions.keys()) {
if (Array.isArray(exceptionKey)) {
const [, ns, name] = exceptionKey;
const id = ns + "#" + name;
if (id.startsWith("smithy.ts.sdk.synthetic.") && id.endsWith("ServiceException")) {
return exceptionKey;
}
}
}
return undefined;
Expand Down Expand Up @@ -109,8 +119,4 @@ export class TypeRegistry {
}
return this.namespace + "#" + shapeId;
}

private getNamespace(shapeId: string) {
return this.normalizeShapeId(shapeId).split("#")[0];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import type { OperationSchema } from "./OperationSchema";
import { op } from "./OperationSchema";
import { Schema } from "./Schema";
import type { SimpleSchema } from "./SimpleSchema";
import { sim } from "./SimpleSchema";
import { simAdapter } from "./SimpleSchema";
import { struct, StructureSchema } from "./StructureSchema";
import { translateTraits } from "./translateTraits";

Expand Down Expand Up @@ -450,7 +450,7 @@ export function hydrate(
const [id, ...rest] = ss;
return (
{
[0 satisfies StaticSchemaIdSimple]: sim,
[0 satisfies StaticSchemaIdSimple]: simAdapter,
[1 satisfies StaticSchemaIdList]: list,
[2 satisfies StaticSchemaIdMap]: map,
[3 satisfies StaticSchemaIdStruct]: struct,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/submodules/schema/schemas/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export abstract class Schema implements TraitsSchema {

public static assign<T extends Schema>(instance: T, values: Omit<T, "getName" | "symbol">): T {
const schema = Object.assign(instance, values);
TypeRegistry.for(schema.namespace).register(schema.name, schema);
// TypeRegistry.for(schema.namespace).register(schema.name, schema);
return schema;
}

Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/submodules/schema/schemas/SimpleSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,15 @@ export const sim = (namespace: string, name: string, schemaRef: SchemaRef, trait
traits,
schemaRef,
});

/**
* @internal
* @deprecated
*/
export const simAdapter = (namespace: string, name: string, traits: SchemaTraits, schemaRef: SchemaRef) =>
Schema.assign(new SimpleSchema(), {
name,
namespace,
traits,
schemaRef,
});
18 changes: 6 additions & 12 deletions packages/core/src/submodules/schema/schemas/schemas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ describe("schemas", () => {
expect(schema.ctor).toBe(null);
});

it("has a factory and the factory registers the schema", () => {
it("has a factory", () => {
expect(error("ack", "Error", 0, [], [])).toEqual(schema);
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
});

it("has an instanceOf operator", () => {
Expand All @@ -44,9 +43,8 @@ describe("schemas", () => {
it("has a value schema", () => {
expect(schema.valueSchema).toBe(0 as SchemaRef);
});
it("has a factory and the factory registers the schema", () => {
it("has a factory", () => {
expect(list("ack", "List", 0, 0)).toEqual(schema);
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
});
it("has an instanceOf operator", () => {
const object = { ...schema };
Expand All @@ -65,9 +63,8 @@ describe("schemas", () => {
expect(schema.keySchema).toBe(0 as SchemaRef);
expect(schema.valueSchema).toBe(1 as SchemaRef);
});
it("has a factory and the factory registers the schema", () => {
it("has a factory", () => {
expect(map("ack", "Map", 0, 0, 1)).toEqual(schema);
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
});
it("has an instanceOf operator", () => {
const object = { ...schema };
Expand All @@ -86,9 +83,8 @@ describe("schemas", () => {
expect(schema.input).toEqual("unit");
expect(schema.output).toEqual("unit");
});
it("has a factory and the factory registers the schema", () => {
it("has a factory", () => {
expect(op("ack", "Operation", 0, "unit", "unit")).toEqual(schema);
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
});
});

Expand Down Expand Up @@ -121,9 +117,8 @@ describe("schemas", () => {
expect(schema).toBeInstanceOf(Schema);
expect(schema).toBeInstanceOf(SimpleSchema);
});
it("has a factory and the factory registers the schema", () => {
it("has a factory", () => {
expect(sim("ack", "Simple", 0, 0)).toEqual(schema);
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
});
it("has an instanceOf operator", () => {
const object = { ...schema };
Expand All @@ -143,9 +138,8 @@ describe("schemas", () => {
expect(schema.memberNames).toEqual(["a", "b", "c"]);
expect(schema.memberList).toEqual([0, 1, 2]);
});
it("has a factory and the factory registers the schema", () => {
it("has a factory", () => {
expect(struct("ack", "Structure", 0, ["a", "b", "c"], [0, 1, 2])).toEqual(schema);
expect(TypeRegistry.for("ack").getSchema(schema.name)).toEqual(schema);
});
it("has an instanceOf operator", () => {
const object = { ...schema };
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/schema/static-schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export type ShapeNamespace = string;
/**
* @alpha
*/
export type StaticSimpleSchema = [StaticSchemaIdSimple, ShapeNamespace, ShapeName, SchemaRef, SchemaTraits];
export type StaticSimpleSchema = [StaticSchemaIdSimple, ShapeNamespace, ShapeName, SchemaTraits, SchemaRef];

/**
* @alpha
Expand Down
19 changes: 4 additions & 15 deletions private/smithy-rpcv2-cbor-schema/src/schemas/schemas_0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ import {
InvalidGreeting as __InvalidGreeting,
ValidationException as __ValidationException,
} from "../models/index";
import { TypeRegistry, error } from "@smithy/core/schema";
import { TypeRegistry } from "@smithy/core/schema";
import {
StaticErrorSchema,
StaticListSchema,
Expand Down Expand Up @@ -295,26 +295,15 @@ export var RpcV2CborDenseMapsInputOutput: StaticStructureSchema = [
_RVCDMIO,
0,
[_dSM, _dNM, _dBM, _dSMe, _dSMen],
[() => DenseStructMap, 128 | 1, 128 | 2, 128 | 0, [2, n1, _DSM, 0, 64 | 0, 64 | 0] as StaticMapSchema],
[() => DenseStructMap, 128 | 1, 128 | 2, 128 | 0, [2, n1, _DSM, 0, 0, 64 | 0]],
];
export var RpcV2CborListInputOutput: StaticStructureSchema = [
3,
n1,
_RVCLIO,
0,
[_sL, _sS, _iL, _bL, _tL, _eL, _iEL, _nSL, _sLt, _bLl],
[
64 | 0,
64 | 0,
64 | 1,
64 | 2,
64 | 4,
64 | 0,
64 | 1,
[1, n2, _NSL, 0, 64 | 0] as StaticListSchema,
() => StructureList,
64 | 21,
],
[64 | 0, 64 | 0, 64 | 1, 64 | 2, 64 | 4, 64 | 0, 64 | 1, [1, n2, _NSL, 0, 64 | 0], () => StructureList, 64 | 21],
];
export var RpcV2CborSparseMapsInputOutput: StaticStructureSchema = [
3,
Expand Down Expand Up @@ -352,7 +341,7 @@ export var SparseNullsOperationInputOutput: StaticStructureSchema = [
];
export var StructureListMember: StaticStructureSchema = [3, n1, _SLM, 0, [_a, _b_], [0, 0]];
export var GreetingStruct: StaticStructureSchema = [3, n2, _GS, 0, [_h], [0]];
export var RpcV2ProtocolServiceException = error(_sC, "RpcV2ProtocolServiceException", 0, [], [], null);
export var RpcV2ProtocolServiceException: StaticErrorSchema = [-3, _sC, "RpcV2ProtocolServiceException", 0, [], []];
TypeRegistry.for(_sC).registerError(RpcV2ProtocolServiceException, __RpcV2ProtocolServiceException);

export var ValidationExceptionFieldList: StaticListSchema = [1, n0, _VEFL, 0, () => ValidationExceptionField];
Expand Down
Loading