diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache index ac0e989c6141..1914de69254d 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache @@ -51,7 +51,7 @@ class {{classname}} { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'{{{path}}}'{{#pathParams}}.replaceAll('{' r'{{{baseName}}}' '}', {{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString()){{/pathParams}}; + final _path = r'{{{path}}}'{{#pathParams}}.replaceAll('{' r'{{{baseName}}}' '}', {{#includeLibraryTemplate}}api/path_param{{/includeLibraryTemplate}},){{/pathParams}}; final _options = Options( method: r'{{#lambda.uppercase}}{{httpMethod}}{{/lambda.uppercase}}', {{#isResponseFile}} diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache index 1d7352f8cc26..40a3771c4fec 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache @@ -54,5 +54,12 @@ dev_dependencies: build_runner: any freezed: '^3.0.0' json_serializable: '^6.9.3' + # unlike the json_serializable variant, this one has no copy_with_extension_gen + # whose source_gen constraint would hold source_helper back; source_helper 1.4.0 + # added extension members that clash with json_serializable 6.x's internal + # copies and break the build_runner build script, so hold it below 1.4.0. + # 1.3.9+ requires Dart 3.9 while this variant advertises >=3.8.0, so keep the + # 1.3.8 lower bound resolvable for 3.8 users + source_helper: '>=1.3.8 <1.4.0' {{/useFreezed}} test: '^1.16.0' diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache new file mode 100644 index 000000000000..1d633242d7cd --- /dev/null +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache @@ -0,0 +1 @@ +Uri.encodeComponent({{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString()) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache new file mode 100644 index 000000000000..1d633242d7cd --- /dev/null +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache @@ -0,0 +1 @@ +Uri.encodeComponent({{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString()) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache new file mode 100644 index 000000000000..1d633242d7cd --- /dev/null +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache @@ -0,0 +1 @@ +Uri.encodeComponent({{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString()) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/ruby-nextgen/gem.mustache b/modules/openapi-generator/src/main/resources/ruby-nextgen/gem.mustache index e411a4277681..68ee988370d9 100644 --- a/modules/openapi-generator/src/main/resources/ruby-nextgen/gem.mustache +++ b/modules/openapi-generator/src/main/resources/ruby-nextgen/gem.mustache @@ -21,10 +21,9 @@ module {{moduleName}} attr_reader :loader end -{{#moduleNameNested}} - # Nested moduleName: for_gem can't target a nested namespace, so drive Zeitwerk - # explicitly. The parent module(s) above are pre-defined so `module {{moduleName}}` - # (here and in every generated file) reopens rather than raising NameError. + # for_gem derives the namespace from gemName, which need not match moduleName (and + # can't target a nested one), so drive Zeitwerk explicitly. Any parent module(s) above + # are pre-defined so `module {{moduleName}}` reopens rather than raising NameError. @loader = Zeitwerk::Loader.new @loader.push_dir("#{__dir__}/{{gemName}}", namespace: self) # version.rb defines VERSION (not a `Version` class). for_gem's GemInflector special-cases @@ -32,10 +31,6 @@ module {{moduleName}} # {{moduleName}}::VERSION available. @loader.ignore("#{__dir__}/{{gemName}}/version.rb") require_relative "{{gemName}}/version" -{{/moduleNameNested}} -{{^moduleNameNested}} - @loader = Zeitwerk::Loader.for_gem -{{/moduleNameNested}} {{#zeitwerkInflections.0}} # Model names keep their acronym casing (e.g. HTTPConfig), but Zeitwerk's default # inflector would expect HttpConfig from the file name. Register the exceptions so diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java index acdf8de1cffc..e501bb1d5c0d 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java @@ -471,6 +471,47 @@ public void testFreezedIgnoresUseOptional() throws IOException { TestUtils.assertFileNotContains(output.toPath().resolve("lib/src/model/pet.dart"), "Optional<"); } + /** + * Path parameters must be URI-encoded as path components: the query_param helpers pass + * strings through unchanged, so a value containing '/' or spaces would otherwise break + * the request path. Every path substitution must therefore go through + * Uri.encodeComponent. + */ + @Test + public void testPathParamsAreUriEncoded() throws IOException { + for (Object[] libraryOption : serializationLibraries()) { + String serializationLibrary = (String) libraryOption[0]; + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("dart-dio") + .setInputSpec("src/test/resources/3_0/petstore.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")) + .addAdditionalProperty(CodegenConstants.SERIALIZATION_LIBRARY, serializationLibrary); + + ClientOptInput opts = configurator.toClientOptInput(); + Generator generator = new DefaultGenerator().opts(opts); + List files = generator.generate(); + files.forEach(File::deleteOnExit); + + // check every generated api class, not just one + Path apiDir = output.toPath().resolve("lib/src/api"); + try (var apiFiles = Files.list(apiDir)) { + for (Path apiFile : apiFiles.filter(p -> p.getFileName().toString().endsWith("_api.dart")) + .collect(java.util.stream.Collectors.toList())) { + String content = Files.readString(apiFile, StandardCharsets.UTF_8); + int substitutions = content.split("\\.replaceAll\\(", -1).length - 1; + Assert.assertTrue(substitutions > 0, + "expected path substitutions in " + apiFile + ": " + content); + int encodings = content.split("Uri\\.encodeComponent\\(", -1).length - 1; + Assert.assertEquals(encodings, substitutions, + "every path substitution in " + apiFile + " must be URI-encoded: " + content); + } + } + } + } + private Path generateFormParamsClient(String serializationLibrary) throws IOException { File output = Files.createTempDirectory("test").toFile(); output.deleteOnExit(); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/rubynextgen/RubyNextgenClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/rubynextgen/RubyNextgenClientCodegenTest.java index 4158d40b4961..d914f9527319 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/rubynextgen/RubyNextgenClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/rubynextgen/RubyNextgenClientCodegenTest.java @@ -443,6 +443,31 @@ public void testAcronymModelsGetZeitwerkInflections() throws Exception { "@two_fa_whitelist ||= DedicatedCloud::TwoFAWhitelist.new(@connection)"); } + @Test + public void testZeitwerkLoaderWhenModuleNameDiffersFromGemName() throws Exception { + java.nio.file.Path target = java.nio.file.Files.createTempDirectory("test"); + target.toFile().deleteOnExit(); + org.openapitools.codegen.ClientOptInput input = + new org.openapitools.codegen.config.CodegenConfigurator() + .setGeneratorName("ruby-nextgen") + .setInputSpec("src/test/resources/3_0/ruby-nextgen/acronym.yaml") + .setOutputDir(target.toString()) + // camelized gemName would be ThingsApi, but the namespace is Things: + // Zeitwerk::Loader.for_gem would target ThingsApi and autoload nothing + .addAdditionalProperty("gemName", "things_api") + .addAdditionalProperty("moduleName", "Things") + .toClientOptInput(); + new org.openapitools.codegen.DefaultGenerator(false).opts(input).generate(); + + // the explicit loader targets the moduleName namespace regardless of gemName + org.openapitools.codegen.TestUtils.assertFileContains( + target.resolve("lib/things_api.rb"), + "Zeitwerk::Loader.new", + "@loader.push_dir(\"#{__dir__}/things_api\", namespace: self)"); + org.openapitools.codegen.TestUtils.assertFileNotContains( + target.resolve("lib/things_api.rb"), "Zeitwerk::Loader.for_gem"); + } + @Test public void testNestedResourcesAreReachableFromClient() throws Exception { java.nio.file.Path target = java.nio.file.Files.createTempDirectory("test"); diff --git a/samples/client/others/ruby-nextgen-qdrant/lib/qdrant.rb b/samples/client/others/ruby-nextgen-qdrant/lib/qdrant.rb index 5be13f72f31e..612cc605f078 100644 --- a/samples/client/others/ruby-nextgen-qdrant/lib/qdrant.rb +++ b/samples/client/others/ruby-nextgen-qdrant/lib/qdrant.rb @@ -20,7 +20,16 @@ class << self attr_reader :loader end - @loader = Zeitwerk::Loader.for_gem + # for_gem derives the namespace from gemName, which need not match moduleName (and + # can't target a nested one), so drive Zeitwerk explicitly. Any parent module(s) above + # are pre-defined so `module Qdrant` reopens rather than raising NameError. + @loader = Zeitwerk::Loader.new + @loader.push_dir("#{__dir__}/qdrant", namespace: self) + # version.rb defines VERSION (not a `Version` class). for_gem's GemInflector special-cases + # this; a plain Loader doesn't, so ignore it for autoloading and require it directly to keep + # Qdrant::VERSION available. + @loader.ignore("#{__dir__}/qdrant/version.rb") + require_relative "qdrant/version" # The `api/` directory on disk is fixed regardless of the `apiNamespace` CliOption, # but api.mustache only nests classes under an `Api` module when the wrapper is # enabled (true). When it's disabled, tell Zeitwerk to collapse diff --git a/samples/client/petstore/ruby-nextgen/lib/petstore.rb b/samples/client/petstore/ruby-nextgen/lib/petstore.rb index 19e492b7a84c..8ee009b7e8c1 100644 --- a/samples/client/petstore/ruby-nextgen/lib/petstore.rb +++ b/samples/client/petstore/ruby-nextgen/lib/petstore.rb @@ -19,7 +19,16 @@ class << self attr_reader :loader end - @loader = Zeitwerk::Loader.for_gem + # for_gem derives the namespace from gemName, which need not match moduleName (and + # can't target a nested one), so drive Zeitwerk explicitly. Any parent module(s) above + # are pre-defined so `module Petstore` reopens rather than raising NameError. + @loader = Zeitwerk::Loader.new + @loader.push_dir("#{__dir__}/petstore", namespace: self) + # version.rb defines VERSION (not a `Version` class). for_gem's GemInflector special-cases + # this; a plain Loader doesn't, so ignore it for autoloading and require it directly to keep + # Petstore::VERSION available. + @loader.ignore("#{__dir__}/petstore/version.rb") + require_relative "petstore/version" # The `api/` directory on disk is fixed regardless of the `apiNamespace` CliOption, # but api.mustache only nests classes under an `Api` module when the wrapper is # enabled (true). When it's disabled, tell Zeitwerk to collapse diff --git a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart index 8aaf646e3051..6161c2f7eb2d 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart @@ -146,7 +146,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -370,7 +370,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'GET', headers: { @@ -558,7 +558,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { @@ -636,7 +636,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart index 5ad35b28d39a..ebd11aef63e3 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart @@ -43,7 +43,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', encodeQueryParameter(_serializers, orderId, const FullType(String)).toString()); + final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, orderId, const FullType(String)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -170,7 +170,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', encodeQueryParameter(_serializers, orderId, const FullType(int)).toString()); + final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, orderId, const FullType(int)).toString()),); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart index c052b91ccf63..7555893e7eb5 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart @@ -266,7 +266,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -320,7 +320,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'GET', headers: { @@ -529,7 +529,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'PUT', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart index ada4f50fa6bb..8c6df90231db 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart @@ -118,7 +118,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -336,7 +336,7 @@ _responseData = rawData == null ? null : deserialize, Pet>(rawData, 'Se ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'GET', headers: { @@ -494,7 +494,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { @@ -572,7 +572,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { @@ -675,7 +675,7 @@ _responseData = rawData == null ? null : deserialize(r ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart index f3d48dc3d1f1..0b9117eeb2f8 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart @@ -40,7 +40,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', orderId.toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(orderId.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -164,7 +164,7 @@ _responseData = rawData == null ? null : deserialize, int>(rawD ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', orderId.toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(orderId.toString()),); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart index ad5d89369ea4..0076a6f55775 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart @@ -250,7 +250,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -297,7 +297,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'GET', headers: { @@ -496,7 +496,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'S ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'PUT', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml index 5bde8eacee67..4d08924131e1 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml @@ -16,4 +16,11 @@ dev_dependencies: build_runner: any freezed: '^3.0.0' json_serializable: '^6.9.3' + # unlike the json_serializable variant, this one has no copy_with_extension_gen + # whose source_gen constraint would hold source_helper back; source_helper 1.4.0 + # added extension members that clash with json_serializable 6.x's internal + # copies and break the build_runner build script, so hold it below 1.4.0. + # 1.3.9+ requires Dart 3.9 while this variant advertises >=3.8.0, so keep the + # 1.3.8 lower bound resolvable for 3.8 users + source_helper: '>=1.3.8 <1.4.0' test: '^1.16.0' diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart index 60aaece86905..56b029ed8ca0 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart @@ -114,7 +114,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -332,7 +332,7 @@ _responseData = rawData == null ? null : deserialize, Pet>(rawData, 'Se ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'GET', headers: { @@ -486,7 +486,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { @@ -564,7 +564,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { @@ -667,7 +667,7 @@ _responseData = rawData == null ? null : deserialize(r ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart index 272e45a0ef6c..4ffc14056b5a 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart @@ -40,7 +40,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', orderId.toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(orderId.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -164,7 +164,7 @@ _responseData = rawData == null ? null : deserialize, int>(rawD ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', orderId.toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(orderId.toString()),); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart index 87ceeccc6b4a..166786eed585 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart @@ -238,7 +238,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -285,7 +285,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'GET', headers: { @@ -484,7 +484,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'S ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'PUT', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart index a4da1c5ff6db..379f664abef8 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart @@ -118,7 +118,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -342,7 +342,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'GET', headers: { @@ -500,7 +500,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { @@ -578,7 +578,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { @@ -684,7 +684,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart index 6f519ff8ee51..3c3e6ccb8f8d 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart @@ -43,7 +43,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', encodeQueryParameter(_serializers, orderId, const FullType(String)).toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, orderId, const FullType(String)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -170,7 +170,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', encodeQueryParameter(_serializers, orderId, const FullType(int)).toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, orderId, const FullType(int)).toString()),); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart index 2a7e5132a60a..f7b22e1a2bf2 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart @@ -244,7 +244,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -291,7 +291,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'GET', headers: { @@ -493,7 +493,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'PUT', headers: {