diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/EmptyInputOutputCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/EmptyInputOutputCommand.ts index 8bf4d3e4bc7..bebe9fc7968 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/EmptyInputOutputCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/EmptyInputOutputCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { EmptyStructure } from "../models/models_0"; -import { EmptyInputOutput } from "../schemas/schemas"; +import { EmptyInputOutput } from "../schemas/schemas_2_EmptyInputOutput"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/Float16Command.ts b/private/smithy-rpcv2-cbor-schema/src/commands/Float16Command.ts index 36519027a5c..e48b71f0800 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/Float16Command.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/Float16Command.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { Float16Output } from "../models/models_0"; -import { Float16 } from "../schemas/schemas"; +import { Float16 } from "../schemas/schemas_4_"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/FractionalSecondsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/FractionalSecondsCommand.ts index bdb8a27f3a7..8a9776cd18e 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/FractionalSecondsCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/FractionalSecondsCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { FractionalSecondsOutput } from "../models/models_0"; -import { FractionalSeconds } from "../schemas/schemas"; +import { FractionalSeconds } from "../schemas/schemas_3_FractionalSeconds"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/GreetingWithErrorsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/GreetingWithErrorsCommand.ts index 2bdd8ab5295..26ec75a22c3 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/GreetingWithErrorsCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/GreetingWithErrorsCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { GreetingWithErrorsOutput } from "../models/models_0"; -import { GreetingWithErrors } from "../schemas/schemas"; +import { GreetingWithErrors } from "../schemas/schemas_1_Rpc"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/NoInputOutputCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/NoInputOutputCommand.ts index 1f32c1beab1..d93f14eea19 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/NoInputOutputCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/NoInputOutputCommand.ts @@ -1,7 +1,7 @@ // smithy-typescript generated code import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; -import { NoInputOutput } from "../schemas/schemas"; +import { NoInputOutput } from "../schemas/schemas_5_NoInputOutput"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/OperationWithDefaultsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/OperationWithDefaultsCommand.ts index 5b20c18c592..cfdfaedf5d7 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/OperationWithDefaultsCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/OperationWithDefaultsCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { OperationWithDefaultsInput, OperationWithDefaultsOutput } from "../models/models_0"; -import { OperationWithDefaults } from "../schemas/schemas"; +import { OperationWithDefaults } from "../schemas/schemas_1_Rpc"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/OptionalInputOutputCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/OptionalInputOutputCommand.ts index 87a512bda9d..cb3a234ecb9 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/OptionalInputOutputCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/OptionalInputOutputCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { SimpleStructure } from "../models/models_0"; -import { OptionalInputOutput } from "../schemas/schemas"; +import { OptionalInputOutput } from "../schemas/schemas_1_Rpc"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/RecursiveShapesCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/RecursiveShapesCommand.ts index 8ee991482ff..8ac48b4c99f 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/RecursiveShapesCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/RecursiveShapesCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { RecursiveShapesInputOutput } from "../models/models_0"; -import { RecursiveShapes } from "../schemas/schemas"; +import { RecursiveShapes } from "../schemas/schemas_1_Rpc"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborDenseMapsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborDenseMapsCommand.ts index c7e6686b358..38f98a94ddd 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborDenseMapsCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborDenseMapsCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { RpcV2CborDenseMapsInputOutput } from "../models/models_0"; -import { RpcV2CborDenseMaps } from "../schemas/schemas"; +import { RpcV2CborDenseMaps } from "../schemas/schemas_1_Rpc"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborListsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborListsCommand.ts index 5b1ad6cf1ca..1111b00fa56 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborListsCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborListsCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { RpcV2CborListInputOutput } from "../models/models_0"; -import { RpcV2CborLists } from "../schemas/schemas"; +import { RpcV2CborLists } from "../schemas/schemas_1_Rpc"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborSparseMapsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborSparseMapsCommand.ts index 69ffd3ff2f8..5434e479a25 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborSparseMapsCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborSparseMapsCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { RpcV2CborSparseMapsInputOutput } from "../models/models_0"; -import { RpcV2CborSparseMaps } from "../schemas/schemas"; +import { RpcV2CborSparseMaps } from "../schemas/schemas_1_Rpc"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/SimpleScalarPropertiesCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/SimpleScalarPropertiesCommand.ts index 9a0244e3ff8..5945cc84fb3 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/SimpleScalarPropertiesCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/SimpleScalarPropertiesCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { SimpleScalarStructure } from "../models/models_0"; -import { SimpleScalarProperties } from "../schemas/schemas"; +import { SimpleScalarProperties } from "../schemas/schemas_1_Rpc"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/SparseNullsOperationCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/SparseNullsOperationCommand.ts index 56696a232bf..d7bc1c72188 100644 --- a/private/smithy-rpcv2-cbor-schema/src/commands/SparseNullsOperationCommand.ts +++ b/private/smithy-rpcv2-cbor-schema/src/commands/SparseNullsOperationCommand.ts @@ -2,7 +2,7 @@ import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; import { commonParams } from "../endpoint/EndpointParameters"; import { SparseNullsOperationInputOutput } from "../models/models_0"; -import { SparseNullsOperation } from "../schemas/schemas"; +import { SparseNullsOperation } from "../schemas/schemas_1_Rpc"; import { getEndpointPlugin } from "@smithy/middleware-endpoint"; import { Command as $Command } from "@smithy/smithy-client"; import { MetadataBearer as __MetadataBearer } from "@smithy/types"; diff --git a/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_0.ts b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_0.ts new file mode 100644 index 00000000000..0250a19e8fe --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_0.ts @@ -0,0 +1,145 @@ +export const _CE = "ComplexError"; +export const _CNED = "ComplexNestedErrorData"; +export const _COD = "ClientOptionalDefaults"; +export const _D = "Defaults"; +export const _DSM = "DenseSetMap"; +export const _DSMe = "DenseStructMap"; +export const _EIO = "EmptyInputOutput"; +export const _ES = "EmptyStructure"; +export const _F = "Foo"; +export const _FO = "Float16Output"; +export const _FS = "FractionalSeconds"; +export const _FSO = "FractionalSecondsOutput"; +export const _Fl = "Float16"; +export const _GS = "GreetingStruct"; +export const _GWE = "GreetingWithErrors"; +export const _GWEO = "GreetingWithErrorsOutput"; +export const _IG = "InvalidGreeting"; +export const _M = "Message"; +export const _N = "Nested"; +export const _NIO = "NoInputOutput"; +export const _NSL = "NestedStringList"; +export const _OIO = "OptionalInputOutput"; +export const _OWD = "OperationWithDefaults"; +export const _OWDI = "OperationWithDefaultsInput"; +export const _OWDO = "OperationWithDefaultsOutput"; +export const _RS = "RecursiveShapes"; +export const _RSIO = "RecursiveShapesInputOutput"; +export const _RSION = "RecursiveShapesInputOutputNested1"; +export const _RSIONe = "RecursiveShapesInputOutputNested2"; +export const _RVCDM = "RpcV2CborDenseMaps"; +export const _RVCDMIO = "RpcV2CborDenseMapsInputOutput"; +export const _RVCL = "RpcV2CborLists"; +export const _RVCLIO = "RpcV2CborListInputOutput"; +export const _RVCSM = "RpcV2CborSparseMaps"; +export const _RVCSMIO = "RpcV2CborSparseMapsInputOutput"; +export const _SBM = "SparseBooleanMap"; +export const _SL = "StructureList"; +export const _SLM = "StructureListMember"; +export const _SNM = "SparseNumberMap"; +export const _SNO = "SparseNullsOperation"; +export const _SNOIO = "SparseNullsOperationInputOutput"; +export const _SS = "SimpleStructure"; +export const _SSL = "SparseStringList"; +export const _SSM = "SparseSetMap"; +export const _SSMp = "SparseStructMap"; +export const _SSMpa = "SparseStringMap"; +export const _SSP = "SimpleScalarProperties"; +export const _SSS = "SimpleScalarStructure"; +export const _TL = "TopLevel"; +export const _VE = "ValidationException"; +export const _VEF = "ValidationExceptionField"; +export const _VEFL = "ValidationExceptionFieldList"; +export const _a = "a"; +export const _b = "bar"; +export const _bL = "booleanList"; +export const _bLl = "blobList"; +export const _bV = "byteValue"; +export const _bVl = "blobValue"; +export const _b_ = "b"; +export const _c = "client"; +export const _cOD = "clientOptionalDefaults"; +export const _d = "datetime"; +export const _dB = "defaultBoolean"; +export const _dBM = "denseBooleanMap"; +export const _dBe = "defaultBlob"; +export const _dBef = "defaultByte"; +export const _dD = "defaultDouble"; +export const _dE = "defaultEnum"; +export const _dF = "defaultFloat"; +export const _dI = "defaultInteger"; +export const _dIE = "defaultIntEnum"; +export const _dL = "defaultList"; +export const _dLe = "defaultLong"; +export const _dM = "defaultMap"; +export const _dNM = "denseNumberMap"; +export const _dS = "defaultString"; +export const _dSM = "denseStructMap"; +export const _dSMe = "denseStringMap"; +export const _dSMen = "denseSetMap"; +export const _dSe = "defaultShort"; +export const _dT = "defaultTimestamp"; +export const _dV = "doubleValue"; +export const _de = "defaults"; +export const _e = "error"; +export const _eB = "emptyBlob"; +export const _eL = "enumList"; +export const _eS = "emptyString"; +export const _f = "foo"; +export const _fB = "falseBoolean"; +export const _fBV = "falseBooleanValue"; +export const _fL = "fieldList"; +export const _fV = "floatValue"; +export const _g = "greeting"; +export const _h = "hi"; +export const _iEL = "intEnumList"; +export const _iL = "integerList"; +export const _iV = "integerValue"; +export const _lV = "longValue"; +export const _m = "message"; +export const _me = "member"; +export const _n = "nested"; +export const _nSL = "nestedStringList"; +export const _oTLD = "otherTopLevelDefault"; +export const _p = "path"; +export const _rM = "recursiveMember"; +export const _s = "sparse"; +export const _sBM = "sparseBooleanMap"; +export const _sL = "stringList"; +export const _sLt = "structureList"; +export const _sNM = "sparseNumberMap"; +export const _sS = "stringSet"; +export const _sSL = "sparseStringList"; +export const _sSM = "sparseStructMap"; +export const _sSMp = "sparseStringMap"; +export const _sSMpa = "sparseSetMap"; +export const _sV = "shortValue"; +export const _sVt = "stringValue"; +export const _tBV = "trueBooleanValue"; +export const _tL = "timestampList"; +export const _tLD = "topLevelDefault"; +export const _v = "value"; +export const _zB = "zeroByte"; +export const _zD = "zeroDouble"; +export const _zF = "zeroFloat"; +export const _zI = "zeroInteger"; +export const _zL = "zeroLong"; +export const _zS = "zeroShort"; +export const n0 = "smithy.framework"; +export const n1 = "smithy.protocoltests.rpcv2Cbor"; +export const n2 = "smithy.protocoltests.shared"; + +// smithy-typescript generated code +import { RpcV2ProtocolServiceException as __RpcV2ProtocolServiceException } from "../models/RpcV2ProtocolServiceException"; +import { error } from "@smithy/core/schema"; + +/* eslint no-var: 0 */ + +export var RpcV2ProtocolServiceException = error( + "smithy.ts.sdk.synthetic.smithy.protocoltests.rpcv2Cbor", + "RpcV2ProtocolServiceException", + 0, + [], + [], + __RpcV2ProtocolServiceException +); diff --git a/private/smithy-rpcv2-cbor-schema/src/schemas/schemas.ts b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_1_Rpc.ts similarity index 55% rename from private/smithy-rpcv2-cbor-schema/src/schemas/schemas.ts rename to private/smithy-rpcv2-cbor-schema/src/schemas/schemas_1_Rpc.ts index a35afb55e51..8f3205f17cd 100644 --- a/private/smithy-rpcv2-cbor-schema/src/schemas/schemas.ts +++ b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_1_Rpc.ts @@ -1,141 +1,133 @@ -const _CE = "ComplexError"; -const _CNED = "ComplexNestedErrorData"; -const _COD = "ClientOptionalDefaults"; -const _D = "Defaults"; -const _DSM = "DenseSetMap"; -const _DSMe = "DenseStructMap"; -const _EIO = "EmptyInputOutput"; -const _ES = "EmptyStructure"; -const _F = "Foo"; -const _FO = "Float16Output"; -const _FS = "FractionalSeconds"; -const _FSO = "FractionalSecondsOutput"; -const _Fl = "Float16"; -const _GS = "GreetingStruct"; -const _GWE = "GreetingWithErrors"; -const _GWEO = "GreetingWithErrorsOutput"; -const _IG = "InvalidGreeting"; -const _M = "Message"; -const _N = "Nested"; -const _NIO = "NoInputOutput"; -const _NSL = "NestedStringList"; -const _OIO = "OptionalInputOutput"; -const _OWD = "OperationWithDefaults"; -const _OWDI = "OperationWithDefaultsInput"; -const _OWDO = "OperationWithDefaultsOutput"; -const _RS = "RecursiveShapes"; -const _RSIO = "RecursiveShapesInputOutput"; -const _RSION = "RecursiveShapesInputOutputNested1"; -const _RSIONe = "RecursiveShapesInputOutputNested2"; -const _RVCDM = "RpcV2CborDenseMaps"; -const _RVCDMIO = "RpcV2CborDenseMapsInputOutput"; -const _RVCL = "RpcV2CborLists"; -const _RVCLIO = "RpcV2CborListInputOutput"; -const _RVCSM = "RpcV2CborSparseMaps"; -const _RVCSMIO = "RpcV2CborSparseMapsInputOutput"; -const _SBM = "SparseBooleanMap"; -const _SL = "StructureList"; -const _SLM = "StructureListMember"; -const _SNM = "SparseNumberMap"; -const _SNO = "SparseNullsOperation"; -const _SNOIO = "SparseNullsOperationInputOutput"; -const _SS = "SimpleStructure"; -const _SSL = "SparseStringList"; -const _SSM = "SparseSetMap"; -const _SSMp = "SparseStructMap"; -const _SSMpa = "SparseStringMap"; -const _SSP = "SimpleScalarProperties"; -const _SSS = "SimpleScalarStructure"; -const _TL = "TopLevel"; -const _VE = "ValidationException"; -const _VEF = "ValidationExceptionField"; -const _VEFL = "ValidationExceptionFieldList"; -const _a = "a"; -const _b = "bar"; -const _bL = "booleanList"; -const _bLl = "blobList"; -const _bV = "byteValue"; -const _bVl = "blobValue"; -const _b_ = "b"; -const _c = "client"; -const _cOD = "clientOptionalDefaults"; -const _d = "datetime"; -const _dB = "defaultBoolean"; -const _dBM = "denseBooleanMap"; -const _dBe = "defaultBlob"; -const _dBef = "defaultByte"; -const _dD = "defaultDouble"; -const _dE = "defaultEnum"; -const _dF = "defaultFloat"; -const _dI = "defaultInteger"; -const _dIE = "defaultIntEnum"; -const _dL = "defaultList"; -const _dLe = "defaultLong"; -const _dM = "defaultMap"; -const _dNM = "denseNumberMap"; -const _dS = "defaultString"; -const _dSM = "denseStructMap"; -const _dSMe = "denseStringMap"; -const _dSMen = "denseSetMap"; -const _dSe = "defaultShort"; -const _dT = "defaultTimestamp"; -const _dV = "doubleValue"; -const _de = "defaults"; -const _e = "error"; -const _eB = "emptyBlob"; -const _eL = "enumList"; -const _eS = "emptyString"; -const _f = "foo"; -const _fB = "falseBoolean"; -const _fBV = "falseBooleanValue"; -const _fL = "fieldList"; -const _fV = "floatValue"; -const _g = "greeting"; -const _h = "hi"; -const _iEL = "intEnumList"; -const _iL = "integerList"; -const _iV = "integerValue"; -const _lV = "longValue"; -const _m = "message"; -const _me = "member"; -const _n = "nested"; -const _nSL = "nestedStringList"; -const _oTLD = "otherTopLevelDefault"; -const _p = "path"; -const _rM = "recursiveMember"; -const _s = "sparse"; -const _sBM = "sparseBooleanMap"; -const _sL = "stringList"; -const _sLt = "structureList"; -const _sNM = "sparseNumberMap"; -const _sS = "stringSet"; -const _sSL = "sparseStringList"; -const _sSM = "sparseStructMap"; -const _sSMp = "sparseStringMap"; -const _sSMpa = "sparseSetMap"; -const _sV = "shortValue"; -const _sVt = "stringValue"; -const _tBV = "trueBooleanValue"; -const _tL = "timestampList"; -const _tLD = "topLevelDefault"; -const _v = "value"; -const _zB = "zeroByte"; -const _zD = "zeroDouble"; -const _zF = "zeroFloat"; -const _zI = "zeroInteger"; -const _zL = "zeroLong"; -const _zS = "zeroShort"; -const n0 = "smithy.framework"; -const n1 = "smithy.protocoltests.rpcv2Cbor"; -const n2 = "smithy.protocoltests.shared"; - // smithy-typescript generated code -import { RpcV2ProtocolServiceException as __RpcV2ProtocolServiceException } from "../models/RpcV2ProtocolServiceException"; import { ComplexError as __ComplexError, InvalidGreeting as __InvalidGreeting, ValidationException as __ValidationException, } from "../models/index"; +import { + _CE, + _CNED, + _COD, + _D, + _DSM, + _DSMe, + _F, + _GS, + _GWE, + _GWEO, + _IG, + _M, + _N, + _NSL, + _OIO, + _OWD, + _OWDI, + _OWDO, + _RS, + _RSIO, + _RSION, + _RSIONe, + _RVCDM, + _RVCDMIO, + _RVCL, + _RVCLIO, + _RVCSM, + _RVCSMIO, + _SBM, + _SL, + _SLM, + _SNM, + _SNO, + _SNOIO, + _SS, + _SSL, + _SSM, + _SSMp, + _SSMpa, + _SSP, + _SSS, + _TL, + _VE, + _VEF, + _VEFL, + _a, + _b, + _bL, + _bLl, + _bV, + _bVl, + _b_, + _c, + _cOD, + _dB, + _dBM, + _dBe, + _dBef, + _dD, + _dE, + _dF, + _dI, + _dIE, + _dL, + _dLe, + _dM, + _dNM, + _dS, + _dSM, + _dSMe, + _dSMen, + _dSe, + _dT, + _dV, + _de, + _e, + _eB, + _eL, + _eS, + _f, + _fB, + _fBV, + _fL, + _fV, + _g, + _h, + _iEL, + _iL, + _iV, + _lV, + _m, + _me, + _n, + _nSL, + _oTLD, + _p, + _rM, + _s, + _sBM, + _sL, + _sLt, + _sNM, + _sS, + _sSL, + _sSM, + _sSMp, + _sSMpa, + _sV, + _sVt, + _tBV, + _tL, + _tLD, + _v, + _zB, + _zD, + _zF, + _zI, + _zL, + _zS, + n0, + n1, + n2, +} from "./schemas_0"; import { error, list, map, op, struct } from "@smithy/core/schema"; /* eslint no-var: 0 */ @@ -198,9 +190,6 @@ export var Defaults = struct( ], [0, 2, 64 | 0, 4, 21, 1, 1, 1, 1, 1, 1, 128 | 0, 0, 1, 0, 2, 21, 1, 1, 1, 1, 1, 1] ); -export var EmptyStructure = struct(n1, _ES, 0, [], []); -export var Float16Output = struct(n1, _FO, 0, [_v], [1]); -export var FractionalSecondsOutput = struct(n1, _FSO, 0, [_d], [5]); export var GreetingWithErrorsOutput = struct(n1, _GWEO, 0, [_g], [0]); export var InvalidGreeting = error( n1, @@ -313,14 +302,6 @@ export var SparseNullsOperationInputOutput = struct( ); export var StructureListMember = struct(n1, _SLM, 0, [_a, _b_], [0, 0]); export var GreetingStruct = struct(n2, _GS, 0, [_h], [0]); -export var RpcV2ProtocolServiceException = error( - "smithy.ts.sdk.synthetic.smithy.protocoltests.rpcv2Cbor", - "RpcV2ProtocolServiceException", - 0, - [], - [], - __RpcV2ProtocolServiceException -); export var ValidationExceptionFieldList = list(n0, _VEFL, 0, () => ValidationExceptionField); export var StructureList = list(n1, _SL, 0, () => StructureListMember); export var TestStringList = 64 | 0; @@ -405,27 +386,6 @@ export var SparseStringMap = map( 0, 0 ); -export var EmptyInputOutput = op( - n1, - _EIO, - 0, - () => EmptyStructure, - () => EmptyStructure -); -export var Float16 = op( - n1, - _Fl, - 0, - () => Unit, - () => Float16Output -); -export var FractionalSeconds = op( - n1, - _FS, - 0, - () => Unit, - () => FractionalSecondsOutput -); export var GreetingWithErrors = op( n1, _GWE, @@ -433,13 +393,6 @@ export var GreetingWithErrors = op( () => Unit, () => GreetingWithErrorsOutput ); -export var NoInputOutput = op( - n1, - _NIO, - 0, - () => Unit, - () => Unit -); export var OperationWithDefaults = op( n1, _OWD, diff --git a/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_2_EmptyInputOutput.ts b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_2_EmptyInputOutput.ts new file mode 100644 index 00000000000..6f08d2ec392 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_2_EmptyInputOutput.ts @@ -0,0 +1,14 @@ +// smithy-typescript generated code +import { _EIO, _ES, n1 } from "./schemas_0"; +import { op, struct } from "@smithy/core/schema"; + +/* eslint no-var: 0 */ + +export var EmptyStructure = struct(n1, _ES, 0, [], []); +export var EmptyInputOutput = op( + n1, + _EIO, + 0, + () => EmptyStructure, + () => EmptyStructure +); diff --git a/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_3_FractionalSeconds.ts b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_3_FractionalSeconds.ts new file mode 100644 index 00000000000..7f9a11ccc86 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_3_FractionalSeconds.ts @@ -0,0 +1,15 @@ +// smithy-typescript generated code +import { _FS, _FSO, _d, n1 } from "./schemas_0"; +import { Unit } from "./schemas_1_Rpc"; +import { op, struct } from "@smithy/core/schema"; + +/* eslint no-var: 0 */ + +export var FractionalSecondsOutput = struct(n1, _FSO, 0, [_d], [5]); +export var FractionalSeconds = op( + n1, + _FS, + 0, + () => Unit, + () => FractionalSecondsOutput +); diff --git a/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_4_.ts b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_4_.ts new file mode 100644 index 00000000000..e44a5e80c78 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_4_.ts @@ -0,0 +1,15 @@ +// smithy-typescript generated code +import { _FO, _Fl, _v, n1 } from "./schemas_0"; +import { Unit } from "./schemas_1_Rpc"; +import { op, struct } from "@smithy/core/schema"; + +/* eslint no-var: 0 */ + +export var Float16Output = struct(n1, _FO, 0, [_v], [1]); +export var Float16 = op( + n1, + _Fl, + 0, + () => Unit, + () => Float16Output +); diff --git a/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_5_NoInputOutput.ts b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_5_NoInputOutput.ts new file mode 100644 index 00000000000..d31aec32b48 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas_5_NoInputOutput.ts @@ -0,0 +1,14 @@ +// smithy-typescript generated code +import { _NIO, n1 } from "./schemas_0"; +import { Unit } from "./schemas_1_Rpc"; +import { op } from "@smithy/core/schema"; + +/* eslint no-var: 0 */ + +export var NoInputOutput = op( + n1, + _NIO, + 0, + () => Unit, + () => Unit +); diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java index dc73f8c2029..503ea1b45c8 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java @@ -61,6 +61,7 @@ import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator; import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin; import software.amazon.smithy.typescript.codegen.schema.SchemaGenerationAllowlist; +import software.amazon.smithy.typescript.codegen.schema.ShapeGroupingIndex; import software.amazon.smithy.typescript.codegen.sections.CommandBodyExtraCodeSection; import software.amazon.smithy.typescript.codegen.sections.CommandConstructorCodeSection; import software.amazon.smithy.typescript.codegen.sections.CommandPropertiesCodeSection; @@ -668,9 +669,10 @@ private void addCommandSpecificPlugins() { } private void writeSchemaSerde() { + ShapeGroupingIndex shapeTree = ShapeGroupingIndex.of(model); String operationSchema = reservedWords.escape(operation.getId().getName()); writer.addRelativeImport(operationSchema, null, Paths.get( - ".", CodegenUtils.SOURCE_FOLDER, SCHEMAS_FOLDER, "schemas" + ".", CodegenUtils.SOURCE_FOLDER, SCHEMAS_FOLDER, shapeTree.getGroup(operation.getId()) )); writer.write(""" .sc($L)""", diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerator.java index 551c1bff1db..9d8b414d7dc 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerator.java @@ -5,8 +5,11 @@ package software.amazon.smithy.typescript.codegen.schema; +import java.nio.file.Path; import java.nio.file.Paths; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -24,6 +27,7 @@ import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.shapes.ShapeType; import software.amazon.smithy.model.shapes.StructureShape; import software.amazon.smithy.model.shapes.UnionShape; @@ -45,13 +49,20 @@ public class SchemaGenerator implements Runnable { public static final String SCHEMAS_FOLDER = "schemas"; private final SchemaReferenceIndex elision; + private final ShapeGroupingIndex treeOrganizer; private final TypeScriptSettings settings; private final SymbolProvider symbolProvider; private final Model model; private final FileManifest fileManifest; - private final StringStore stringStore = new StringStore(); - private final TypeScriptWriter writer = new TypeScriptWriter(""); + private final StringStore store = new StringStore(); + /** + * Keyed by the schema group determined by the ShapeGroupingIndex. + */ + private final Map writers = new HashMap<>(); + /** + * Avoids infinite recursion when navigating shape graph. + */ private final Set loadShapesVisited = new HashSet<>(); private final Set structureShapes = new TreeSet<>(); @@ -61,6 +72,9 @@ public class SchemaGenerator implements Runnable { private final Set operationShapes = new TreeSet<>(); private final Set simpleShapes = new TreeSet<>(); + /** + * Used to deconflict schema variable names. + */ private final Set existsAsSchema = new HashSet<>(); private final Set requiresNamingDeconfliction = new HashSet<>(); @@ -76,11 +90,7 @@ public SchemaGenerator(Model model, elision = SchemaReferenceIndex.of(model); this.settings = settings; this.symbolProvider = symbolProvider; - writer.write( - """ - /* eslint no-var: 0 */ - """ - ); + treeOrganizer = ShapeGroupingIndex.of(model); } /** @@ -116,11 +126,54 @@ public void run() { unionShapes.forEach(this::writeUnionSchema); operationShapes.forEach(this::writeOperationSchema); - String stringVariables = stringStore.flushVariableDeclarationCode(); - fileManifest.writeFile( - Paths.get(CodegenUtils.SOURCE_FOLDER, SCHEMAS_FOLDER, "schemas.ts").toString(), - stringVariables + "\n" + writer - ); + String stringConstants = store.flushVariableDeclarationCode() + .replaceAll("const ", "export const "); + + for (Map.Entry entry : writers.entrySet()) { + String group = entry.getKey(); + TypeScriptWriter writer = entry.getValue(); + + boolean hasContent = !writer.toString().endsWith("/* eslint no-var: 0 */\n"); + if (hasContent) { + if (group.equals("schemas_0")) { + fileManifest.writeFile( + Paths.get(CodegenUtils.SOURCE_FOLDER, SCHEMAS_FOLDER, group + ".ts").toString(), + stringConstants + "\n" + writer + ); + } else { + fileManifest.writeFile( + Paths.get(CodegenUtils.SOURCE_FOLDER, SCHEMAS_FOLDER, group + ".ts").toString(), + writer.toString() + ); + } + } + } + } + + /** + * @return writer corresponding to the file that will hold the shape's schema. + */ + private TypeScriptWriter getWriter(ShapeId shape) { + return writers.computeIfAbsent(treeOrganizer.getGroup(shape), k -> { + TypeScriptWriter typeScriptWriter = new TypeScriptWriter(""); + typeScriptWriter.write(""" + /* eslint no-var: 0 */ + """); + return typeScriptWriter; + }); + } + + /** + * @return writer corresponding to the base schemas file (schemas_0.ts). + */ + private TypeScriptWriter getBaseWriter() { + return writers.computeIfAbsent("schemas_0", k -> { + TypeScriptWriter typeScriptWriter = new TypeScriptWriter(""); + typeScriptWriter.write(""" + /* eslint no-var: 0 */ + """); + return typeScriptWriter; + }); } /** @@ -183,6 +236,11 @@ private void loadShapes(Shape shape) { } } + /** + * Since we use the short names for schema objects, in rare cases there may be a + * naming conflict due to shapes with the same short name in different namespaces. + * These shapes will have their variable names deconflicted with a suffix. + */ private void deconflictSchemaVarNames() { Set observedShapeNames = new HashSet<>(); for (Shape shape : existsAsSchema) { @@ -201,19 +259,24 @@ private void deconflictSchemaVarNames() { private String getShapeVariableName(Shape shape) { String symbolName = reservedWords.escape(shape.getId().getName()); if (requiresNamingDeconfliction.contains(shape)) { - symbolName += "_" + stringStore.var(shape.getId().getNamespace(), "n"); + symbolName += "_" + checkImportString(shape, shape.getId().getNamespace(), "n"); } return symbolName; } + /** + * Writes the schema declaration for a simple shape. + * If it has no runtime traits, e.g. a plain string, nothing will be written. + */ private void writeSimpleSchema(Shape shape) { + TypeScriptWriter writer = getWriter(shape.getId()); if (elision.traits.hasSchemaTraits(shape)) { writer.addImportSubmodule("sim", "sim", TypeScriptDependency.SMITHY_CORE, "/schema"); writer.write(""" export var $L = sim($L, $L, $L,""", getShapeVariableName(shape), - stringStore.var(shape.getId().getNamespace(), "n"), - stringStore.var(shape.getId().getName()), + checkImportString(shape, shape.getId().getNamespace(), "n"), + checkImportString(shape, shape.getId().getName()), resolveSimpleSchema(shape) ); writeTraits(shape); @@ -222,6 +285,7 @@ private void writeSimpleSchema(Shape shape) { } private void writeStructureSchema(StructureShape shape) { + TypeScriptWriter writer = getWriter(shape.getId()); checkedWriteSchema(shape, () -> { String symbolName = reservedWords.escape(shape.getId().getName()); if (shape.hasTrait(ErrorTrait.class)) { @@ -236,8 +300,8 @@ private void writeStructureSchema(StructureShape shape) { export var $L = error($L, $L,""", "", getShapeVariableName(shape), - stringStore.var(shape.getId().getNamespace(), "n"), - stringStore.var(shape.getId().getName()), + checkImportString(shape, shape.getId().getNamespace(), "n"), + checkImportString(shape, shape.getId().getName()), () -> doWithMembers(shape) ); writer.writeInline(",$L", exceptionCtorSymbolName); @@ -248,15 +312,20 @@ private void writeStructureSchema(StructureShape shape) { export var $L = struct($L, $L,""", ");", getShapeVariableName(shape), - stringStore.var(shape.getId().getNamespace(), "n"), - stringStore.var(shape.getId().getName()), + checkImportString(shape, shape.getId().getNamespace(), "n"), + checkImportString(shape, shape.getId().getName()), () -> doWithMembers(shape) ); } }); } + /** + * Writes the synthetic base exception schema. + */ private void writeBaseError() { + TypeScriptWriter writer = getBaseWriter(); + String serviceName = CodegenUtils.getServiceName(settings, model, symbolProvider); String serviceExceptionName = CodegenUtils.getServiceExceptionName(serviceName); String namespace = settings.getService(model).getId().getNamespace(); @@ -279,14 +348,15 @@ private void writeBaseError() { } private void writeUnionSchema(UnionShape shape) { + TypeScriptWriter writer = getWriter(shape.getId()); checkedWriteSchema(shape, () -> { writer.addImportSubmodule("struct", "uni", TypeScriptDependency.SMITHY_CORE, "/schema"); writer.openBlock(""" export var $L = uni($L, $L,""", ");", getShapeVariableName(shape), - stringStore.var(shape.getId().getNamespace(), "n"), - stringStore.var(shape.getId().getName()), + checkImportString(shape, shape.getId().getNamespace(), "n"), + checkImportString(shape, shape.getId().getName()), () -> doWithMembers(shape) ); }); @@ -296,22 +366,26 @@ private void writeUnionSchema(UnionShape shape) { * Handles the member entries for unions/structures. */ private void doWithMembers(Shape shape) { + TypeScriptWriter writer = getWriter(shape.getId()); writeTraits(shape); + // member names. writer.write(", [ "); shape.getAllMembers().forEach((memberName, member) -> { - writer.write("$L,", stringStore.var(memberName)); + writer.write("$L,", checkImportString(shape, memberName)); }); + + // member schemas. writer.write(" ], ["); shape.getAllMembers().forEach((memberName, member) -> { - String ref = resolveSchema(member); + String ref = resolveSchema(shape, member); if (elision.traits.hasSchemaTraits(member)) { writer.openBlock(""" [$L,\s""", "],", ref, () -> { - writeTraits(member); + writeTraitsInContext(shape, member); } ); } else { @@ -322,14 +396,15 @@ private void doWithMembers(Shape shape) { } private void writeListSchema(CollectionShape shape) { + TypeScriptWriter writer = getWriter(shape.getId()); checkedWriteSchema(shape, () -> { writer.addImportSubmodule("list", "list", TypeScriptDependency.SMITHY_CORE, "/schema"); writer.openBlock(""" export var $L = list($L, $L,""", ");", getShapeVariableName(shape), - stringStore.var(shape.getId().getNamespace(), "n"), - stringStore.var(shape.getId().getName()), + checkImportString(shape, shape.getId().getNamespace(), "n"), + checkImportString(shape, shape.getId().getName()), () -> this.doWithMember( shape, shape.getMember() @@ -339,14 +414,15 @@ private void writeListSchema(CollectionShape shape) { } private void writeMapSchema(MapShape shape) { + TypeScriptWriter writer = getWriter(shape.getId()); checkedWriteSchema(shape, () -> { writer.addImportSubmodule("map", "map", TypeScriptDependency.SMITHY_CORE, "/schema"); writer.openBlock(""" export var $L = map($L, $L,""", ");", getShapeVariableName(shape), - stringStore.var(shape.getId().getNamespace(), "n"), - stringStore.var(shape.getId().getName()), + checkImportString(shape, shape.getId().getNamespace(), "n"), + checkImportString(shape, shape.getId().getName()), () -> this.doWithMember( shape, shape.getKey(), @@ -360,15 +436,16 @@ private void writeMapSchema(MapShape shape) { * Write member schema insertion for lists. */ private void doWithMember(Shape shape, MemberShape memberShape) { + TypeScriptWriter writer = getWriter(shape.getId()); writeTraits(shape); - String ref = resolveSchema(memberShape); + String ref = resolveSchema(shape, memberShape); if (elision.traits.hasSchemaTraits(memberShape)) { writer.openBlock( ", [$L, ", "]", ref, () -> { - writeTraits(memberShape); + writeTraitsInContext(shape, memberShape); } ); } else { @@ -380,16 +457,17 @@ private void doWithMember(Shape shape, MemberShape memberShape) { * Write member schema insertion for maps. */ private void doWithMember(Shape shape, MemberShape keyShape, MemberShape memberShape) { + TypeScriptWriter writer = getWriter(shape.getId()); writeTraits(shape); - String keyRef = resolveSchema(keyShape); - String valueRef = resolveSchema(memberShape); + String keyRef = resolveSchema(shape, keyShape); + String valueRef = resolveSchema(shape, memberShape); if (elision.traits.hasSchemaTraits(memberShape) || elision.traits.hasSchemaTraits(keyShape)) { writer.openBlock( ", [$L, ", "]", keyRef, () -> { - writeTraits(keyShape); + writeTraitsInContext(shape, keyShape); } ); writer.openBlock( @@ -397,7 +475,7 @@ private void doWithMember(Shape shape, MemberShape keyShape, MemberShape memberS "]", valueRef, () -> { - writeTraits(memberShape); + writeTraitsInContext(shape, memberShape); } ); } else { @@ -406,15 +484,18 @@ private void doWithMember(Shape shape, MemberShape keyShape, MemberShape memberS } private void writeOperationSchema(OperationShape shape) { + TypeScriptWriter writer = getWriter(shape.getId()); writer.addImportSubmodule("op", "op", TypeScriptDependency.SMITHY_CORE, "/schema"); writer.openBlock(""" export var $L = op($L, $L,""", ");", getShapeVariableName(shape), - stringStore.var(shape.getId().getNamespace(), "n"), - stringStore.var(shape.getId().getName()), + checkImportString(shape, shape.getId().getNamespace(), "n"), + checkImportString(shape, shape.getId().getName()), () -> { writeTraits(shape); + checkImportSchema(shape, model.expectShape(shape.getInputShape())); + checkImportSchema(shape, model.expectShape(shape.getOutputShape())); writer.write(""" , () => $L, () => $L""", getShapeVariableName(model.expectShape(shape.getInputShape())), @@ -425,8 +506,22 @@ private void writeOperationSchema(OperationShape shape) { } private void writeTraits(Shape shape) { + writeTraitsInContext(shape, shape); + } + + /** + * When the context is not the base group, then any StringStore variables + * are imported from the base group. + */ + private void writeTraitsInContext(Shape context, Shape shape) { + TypeScriptWriter writer = getWriter(context.getId()); + boolean useImportedStrings = !treeOrganizer.isBaseGroup(context); + writer.write( - new SchemaTraitWriter(shape, elision, stringStore).toString() + new SchemaTraitWriter( + shape, elision, + useImportedStrings ? store.useSchemaWriter(writer) : store + ).toString() ); } @@ -434,6 +529,7 @@ private void writeTraits(Shape shape) { * Checks whether ok to write minimized schema. */ private void checkedWriteSchema(Shape shape, Runnable schemaWriteFn) { + TypeScriptWriter writer = getWriter(shape.getId()); if (shape.getId().getNamespace().equals("smithy.api") && shape.getId().getName().equals("Unit")) { // special signal value for operation input/output. @@ -441,7 +537,7 @@ private void checkedWriteSchema(Shape shape, Runnable schemaWriteFn) { export var Unit = "unit" as const; """); } else if (!elision.isReferenceSchema(shape) && !elision.traits.hasSchemaTraits(shape)) { - String sentinel = this.resolveSchema(shape); + String sentinel = this.resolveSchema(model.expectShape(ShapeId.from("smithy.api#Unit")), shape); writer.write( """ @@ -459,7 +555,7 @@ private void checkedWriteSchema(Shape shape, Runnable schemaWriteFn) { * @return generally the symbol name of the target shape, but sometimes a sentinel value for special types like * blob and timestamp. */ - private String resolveSchema(Shape shape) { + private String resolveSchema(Shape context, Shape shape) { MemberShape memberShape = null; if (shape instanceof MemberShape ms) { memberShape = ms; @@ -477,9 +573,17 @@ private String resolveSchema(Shape shape) { } } + if (isReference || hasTraits) { + checkImportSchema(context, shape); + } + return (isReference || hasTraits ? "() => " : "") + getShapeVariableName(shape); } + /** + * @return a sentinel value representing a preconfigured schema type. + * @throws IllegalArgumentException when no sentinel value exists, e.g. a non-simple schema was passed in. + */ private String resolveSimpleSchema(Shape shape) { MemberShape memberShape = null; if (shape instanceof MemberShape ms) { @@ -527,7 +631,8 @@ private String resolveSimpleSchema(Shape shape) { return "19"; } case LIST, SET, MAP -> { - return resolveSimpleSchemaNestedContainer(shape, writer, stringStore); + TypeScriptWriter writer = getWriter(shape.getId()); + return resolveSimpleSchemaNestedContainer(shape, writer); } default -> { // @@ -536,7 +641,15 @@ private String resolveSimpleSchema(Shape shape) { throw new IllegalArgumentException("shape is not simple"); } - private String resolveSimpleSchemaNestedContainer(Shape shape, TypeScriptWriter writer, StringStore stringStore) { + /** + * For example, the number 5 represents a timestamp (Date-Time) schema with no other traits. + * For lists, the bit modifier 64 is applied, giving 64 | 5 for a list of timestamps. + * For further nested containers, bit masks can no longer be used, necessitating the `sim` simple schema + * wrapper: `sim("namespace", "ListOfLists", 64 | 5, {});`. + * + * @return the container bit modifier attached to the schema numeric value. + */ + private String resolveSimpleSchemaNestedContainer(Shape shape, TypeScriptWriter writer) { Shape contained; String factory; String sentinel; @@ -566,18 +679,51 @@ private String resolveSimpleSchemaNestedContainer(Shape shape, TypeScriptWriter if (contained.isListShape()) { writer.addImportSubmodule(factory, factory, TypeScriptDependency.SMITHY_CORE, "/schema"); - String schemaVarName = stringStore.var(shape.getId().getName()); - return factory + "(" + stringStore.var(shape.getId().getNamespace(), "n") + ", " + schemaVarName + ", 0, " + String schemaVarName = checkImportString(shape, shape.getId().getName()); + return factory + "(" + + checkImportString(shape, shape.getId().getNamespace(), "n") + ", " + schemaVarName + ", 0, " + keyMemberSchema + this.resolveSimpleSchema(contained) + ")"; } else if (contained.isMapShape()) { writer.addImportSubmodule(factory, factory, TypeScriptDependency.SMITHY_CORE, "/schema"); - String schemaVarName = stringStore.var(shape.getId().getName()); - return factory + "(" + stringStore.var(shape.getId().getNamespace(), "n") + ", " + schemaVarName + ", 0, " + String schemaVarName = checkImportString(shape, shape.getId().getName()); + return factory + "(" + + checkImportString(shape, shape.getId().getNamespace(), "n") + ", " + schemaVarName + ", 0, " + keyMemberSchema + this.resolveSimpleSchema(contained) + ")"; } else { return sentinel + "|" + this.resolveSimpleSchema(contained); } } + + /** + * Imports the shape's schema from another file if the context group differs from the shape group. + */ + private void checkImportSchema(Shape context, Shape shape) { + String shapeGroup = treeOrganizer.getGroup(shape.getId()); + if (treeOrganizer.different(context, shape)) { + getWriter(context.getId()).addRelativeImport( + getShapeVariableName(shape), null, Path.of("./", shapeGroup) + ); + } + } + + private String checkImportString(Shape context, String fullString) { + return checkImportString(context, fullString, null); + } + + /** + * Imports a string variable from the base group if the context is not the base group. + */ + private String checkImportString(Shape context, String fullString, String prefix) { + String var = prefix != null ? store.var(fullString, prefix) : store.var(fullString); + if (!treeOrganizer.isBaseGroup(context)) { + getWriter(context.getId()).addRelativeImport( + var, + null, + Path.of("./schemas_0") + ); + } + return var; + } } diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/ShapeGroupingIndex.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/ShapeGroupingIndex.java new file mode 100644 index 00000000000..ba43550fcd0 --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/ShapeGroupingIndex.java @@ -0,0 +1,285 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.schema; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.knowledge.KnowledgeIndex; +import software.amazon.smithy.model.knowledge.TopDownIndex; +import software.amazon.smithy.model.shapes.MemberShape; +import software.amazon.smithy.model.shapes.OperationShape; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.utils.SmithyInternalApi; + +/** + * Creates schema groupings. + * E.g. used to create disjoint sets of schemas to assist with tree-shaking. + */ +@SmithyInternalApi +public class ShapeGroupingIndex implements KnowledgeIndex { + public static final String FILENAME_PREFIX = "schemas"; + + /** + * The maximum number of operations to place into one group (file). + */ + public static final int MAX_OPERATIONS_GROUP_SIZE = 12; + + /** + * Instances of this class for specific models. + */ + private static final Map INSTANCES = new ConcurrentHashMap<>(); + + /** + * Shapes mapped to operations that use them. + */ + private final Map> shapeToOperationDependents = new HashMap<>(); + + /** + * Shapes mapped to the largest logical grouping of operations making use of the shape. + */ + private final Map> shapeToOperationalGroup = new HashMap<>(); + + /** + * Hashed combined operation names to their numeric group id. + */ + private final Map opGroups = new HashMap<>(); + + /** + * Combined operation names mapped to a readable group name. + */ + private final Map groupNames = new HashMap<>(); + + /** + * Last group assigned by increasing number. + */ + private int lastGroup = 0; + + /** + * Contextual model. + */ + private Model model; + + public static ShapeGroupingIndex of(Model model) { + return INSTANCES.computeIfAbsent(model, k -> { + ShapeGroupingIndex shapeTreeOrganizer = new ShapeGroupingIndex(); + shapeTreeOrganizer.loadModel(model); + return shapeTreeOrganizer; + }); + } + + /** + * @return the group name (filename) of the schema group for the given shape. + */ + public String getGroup(ShapeId id) { + if (!shapeToOperationalGroup.containsKey(id)) { + return getBaseGroup(); + } + TreeSet operations = shapeToOperationalGroup.get(id); + return hashOperationSet(operations); + } + + /** + * @return whether shape is in the base group. + */ + public boolean isBaseGroup(Shape shape) { + return getGroup(shape.getId()).equals(getBaseGroup()); + } + + /** + * @return whether two shapes are in different groups. + */ + public boolean different(Shape a, Shape b) { + return !Objects.equals( + getGroup(a.getId()), + getGroup(b.getId()) + ); + } + + /** + * Initialize for given model. + */ + private void loadModel(Model model) { + if (this.model != null) { + throw new IllegalArgumentException("Model has already been loaded"); + } + this.model = model; + for (ServiceShape service : model.getServiceShapes()) { + for (OperationShape operation : TopDownIndex.of(model).getContainedOperations(service)) { + readOperationClosure(operation, new HashSet<>()); + } + } + + // restack operational groups. + for (Map.Entry> entry : shapeToOperationDependents.entrySet()) { + ShapeId shapeId = entry.getKey(); + TreeSet dependentOperations = entry.getValue(); + + shapeToOperationalGroup.put(shapeId, + shapeToOperationDependents.values() + .stream() + .filter(group -> group.size() < MAX_OPERATIONS_GROUP_SIZE) + .filter(group -> group.containsAll(dependentOperations)) + .max(Comparator.comparing(TreeSet::size)) + .orElse(dependentOperations) + ); + } + + // precompute group allocations. + shapeToOperationalGroup.keySet() + .forEach(this::getGroup); + } + + /** + * @return a string hash identifying the group that this set of operations is assigned to. + */ + private String hashOperationSet(TreeSet operations) { + if (operations.size() > MAX_OPERATIONS_GROUP_SIZE) { + return getBaseGroup(); + } + String key = joinOperationNames(operations); + if (opGroups.containsKey(key) && groupNames.containsKey(key)) { + return FILENAME_PREFIX + + "_" + opGroups.get(key) + + "_" + groupNames.get(key); + } else { + opGroups.put(key, ++lastGroup); + groupNames.put(key, nominateGroupName(operations)); + } + return FILENAME_PREFIX + + "_" + lastGroup + + "_" + groupNames.get(key); + } + + /** + * Determines a name for the group of operations + * based on the most commonly observed name or structure. + * Uses "longest common phrase" algorithm. + */ + private String nominateGroupName(TreeSet operations) { + if (operations.size() == 1) { + return operations.iterator().next().getName(); + } + + Set names = operations.stream().map(ShapeId::getName).collect(Collectors.toSet()); + int minLength = 3; + + Stream phrases = names.stream() + .flatMap(operationName -> names.stream() + .filter(otherOperationName -> !otherOperationName.equals(operationName)) + .flatMap(other -> { + Set wordPhrases = new HashSet<>(); + + // expensive, but cached. + for (int i = 0; i < operationName.length(); ++i) { + for (int j = i + 1; j <= operationName.length(); ++j) { + String candidate = operationName.substring(i, j); + + if (candidate.length() >= minLength && other.contains(candidate)) { + boolean validNounPhrase = isValidNounPhrase(operationName, i, j); + if (validNounPhrase) { + wordPhrases.add(candidate); + } + } + } + } + + return wordPhrases.stream(); + }) + ); + + return phrases + .collect(Collectors.groupingBy(s -> s, Collectors.counting())) + .entrySet() + .stream() + .max(Map.Entry.comparingByValue()) + .map(Map.Entry::getKey) + .orElse(""); + } + + /** + * The substring from i to j starts with a capital letter and ends + * with the string or at another capital letter or number. + */ + private static boolean isValidNounPhrase(String name, int i, int j) { + String candidate = name.substring(i, j); + + boolean capitalInitialChar = candidate.substring(0, 1).matches("[A-Z]"); + boolean endsWord = name.length() == j + || name.substring(j, j + 1).matches("[A-Z0-9]"); + + return capitalInitialChar && endsWord; + } + + private String getBaseGroup() { + return FILENAME_PREFIX + "_0"; + } + + /** + * Make known that a shape id is used within a certain operation. + */ + private void register(ShapeId operationId, ShapeId shapeId) { + shapeToOperationDependents.computeIfAbsent(shapeId, k -> new TreeSet<>()).add(operationId); + } + + /** + * Explore the set of shapes in the closure of an operation. + */ + private void readOperationClosure(OperationShape op, Set visited) { + registerShapes(op, op, visited); + op.getInput().ifPresent(inputShape -> { + registerShapes(op, model.expectShape(inputShape), visited); + }); + op.getOutput().ifPresent(outputShape -> { + registerShapes(op, model.expectShape(outputShape), visited); + }); + op.getErrors().forEach(error -> { + registerShapes(op, model.expectShape(error), visited); + }); + } + + /** + * Registers knowledge of the shape in the context of an operation. + * Recurses on referenced shapes in the input shape. + */ + private void registerShapes(OperationShape op, Shape shape, Set visited) { + if (shape.isMemberShape()) { + registerShapes(op, model.expectShape(shape.asMemberShape().get().getTarget()), visited); + return; + } + if (visited.contains(shape)) { + return; + } + visited.add(shape); + register(op.getId(), shape.getId()); + + Set memberTargetShapes = shape.getAllMembers().values().stream() + .map(MemberShape::getTarget) + .map(model::expectShape) + .collect(Collectors.toSet()); + + for (Shape memberTargetShape : memberTargetShapes) { + registerShapes(op, memberTargetShape, visited); + } + } + + /** + * Used to create a hash of a set of operations. + */ + private String joinOperationNames(TreeSet operations) { + return operations.stream().map(ShapeId::getName).collect(Collectors.joining(",")); + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/StringStore.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/StringStore.java index 37e97e090e5..3d3625d7153 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/StringStore.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/StringStore.java @@ -5,6 +5,7 @@ package software.amazon.smithy.typescript.codegen.util; +import java.nio.file.Path; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -16,6 +17,7 @@ import java.util.TreeMap; import java.util.function.Function; import java.util.regex.Pattern; +import software.amazon.smithy.typescript.codegen.TypeScriptWriter; import software.amazon.smithy.utils.SmithyInternalApi; /** @@ -25,7 +27,7 @@ * form of compression on long protocol serde files. */ @SmithyInternalApi -public final class StringStore { +public class StringStore { /** * Words are the component strings found within `camelCaseWords` or `header-dashed-words`. */ @@ -170,4 +172,40 @@ private boolean isNeutral(String variable) { } return true; } + + public WithSchemaWriter useSchemaWriter(TypeScriptWriter writer) { + return new WithSchemaWriter(writer, this); + } + + @SmithyInternalApi + public static final class WithSchemaWriter extends StringStore { + private final TypeScriptWriter writer; + private final StringStore store; + + private WithSchemaWriter( + TypeScriptWriter writer, + StringStore store + ) { + this.writer = writer; + this.store = store; + } + + @Override + public String var(String literal) { + String var = store.var(literal); + writer.addRelativeImport( + var, null, Path.of("./schemas_0") + ); + return var; + } + + @Override + public String var(String literal, String preferredPrefix) { + String var = store.var(literal, preferredPrefix); + writer.addRelativeImport( + var, null, Path.of("./schemas_0") + ); + return var; + } + } }