From caefa3319b623b7aa29491ace9da2d7c5c46ced1 Mon Sep 17 00:00:00 2001 From: Yehor Zhukovskyi <43119306+YegorZh@users.noreply.github.com> Date: Wed, 20 Nov 2024 17:06:06 +0200 Subject: [PATCH 1/4] Script to add version header to java sdk on generation (#100) * feat: script to add version header to java dsdk on generation, some test fixes that are already merged in java sdk * feat: generation now also injects headers for setInterceptor function of ApiClient * fix: java sdk version name --- README.md | 308 ++++++++++++++++++++++++++++++------------- changes_script.rb | 39 ------ generate.rb | 328 ---------------------------------------------- openapi.json | 2 +- 4 files changed, 221 insertions(+), 456 deletions(-) delete mode 100644 changes_script.rb delete mode 100644 generate.rb diff --git a/README.md b/README.md index 779f14f..3d62fdd 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ The project is wrapped with npm, we strongly advice to install Node LTS to acces ## Generating Unit Client Libraries Below you can find examples for generating client libraries using [OpenAPI generator](https://openapi-generator.tech/). -You may also use any other known generator, such as [Swagger Codegen](https://github.com/swagger-api/swagger-codegen#generating-a-client-from-local-files), download the jar from [here](https://mvnrepository.com/artifact/io.swagger.codegen.v3/swagger-codegen-cli) The following examples are with the use of [openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli). @@ -20,129 +19,239 @@ The following examples are with the use of [openapi-generator-cli](https://githu ### bundle ```commandline -Bundles the open api specification into one file inside of dist folder +Bundles the open api specification into one file inside the dist folder ``` ### generate-java ```commandline -Runs the bundle command and generates java sdk inside of dist folder +Runs the bundle command and generates java sdk inside the dist folder. ``` -### lint - -```commandline -Runs redocly lint for schemas to detect any potential issues -``` - -### format +### generate-node ```commandline -Applies prettier formatting to the schemas +Runs the bundle command and generates node sdk inside the dist folder. ``` -## Legacy - -All of the info listed below is related to the legacy functionality and will be deprecated or updated soon - -### unit-java +### generate-ruby ```commandline -openapi-generator-cli generate -g java -i openapi.json -o unit +Runs the bundle command and generates ruby sdk inside the dist folder. ``` -### unit-python - -We recommend using our script which can be found in this repository: +### generate-python ```commandline -python "./generate.py" +Runs the bundle command and generates python sdk inside the dist folder. ``` -Or generate by yourself with swagger-codegen-cli: - -``` -java -jar swagger-codegen-cli-3.0.47.jar generate -i openapi.json -l python -o unit -``` - -### unit-typescript-axios +### lint ```commandline -openapi-generator-cli generate -g typescript-axios -i openapi.json -o unit -p npmName=TypescriptUnitClient +Runs redocly lint for schemas to detect any potential issues ``` -### unit-ruby +### format ```commandline -openapi-generator-cli generate -g ruby -i openapi.json -o unit +Applies prettier formatting to the schemas ``` ## Generated Clients Usage Examples -#### Python - -``` - from datetime import date, timedelta - from swagger_client import configuration, api_client, Address, CreateIndividualApplicationAttributes, FullName, Phone, - CreateIndividualApplication, CreateBusinessApplication, CreateBusinessApplicationAttributes, BeneficialOwner, \ - Contact, Officer - - _configuration = configuration.Configuration() - _configuration.api_key['Authorization'] = "access_token" - _configuration.api_key_prefix['Authorization'] = 'Bearer' - - api_client = api_client.ApiClient(configuration=_configuration) - - address = Address(street="1600 Pennsylvania Avenue Northwest", city="Washington", state="CA", - postal_code="20500", - country="US") - attr = CreateIndividualApplicationAttributes(FullName("Peter", "Parker"), "jone.doe1@unit-finance.com", - Phone("1", "2025550108"), ssn, - address=address, date_of_birth="2001-08-10", dba="Piedpiper Inc", - ein="123456789", sole_proprietorship=False, - idempotency_key=str(uuid.uuid1()), - jwt_subject="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9fQ") - - application_request = {"data": CreateIndividualApplication(attributes=attr)} - - application = CreateApplicationApi(api_client).execute(application_request).data - customer_id = application.relationships.customer.data.id - - attributes = CreateDepositAccountAttributes("checking", {"purpose": "sdk-test"}) - relationships = CreateDepositAccountRelationships(customer={"data": {"type": "customer", "id": customer_id}}) - req = CreateDepositAccount("depositAccount", attributes, relationships) - - account = CreateAnAccountApi(api_client).execute({"data": req}) -``` - -you can find more examples in the unit/e2e_tests directory - #### Java String access_token = "access_token"; ApiClient cl = new ApiClient(); - cl.setBearerToken(access_token); - Configuration.setDefaultApiClient(cl); - - GetListRecurringPaymentsApi api = new GetListRecurringPaymentsApi(); - - UnitRecurringPaymentListResponse response = api.execute(); + ObjectMapper mapper = cl.getObjectMapper(); + mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // To allow certain requests with empty bodies + cl.setObjectMapper(mapper); + cl.setRequestInterceptor(r -> { + r.header("Authorization", "Bearer " + access_token); + }); + UnitApi unitApi = new UnitApi(cl); + + CreateBusinessApplication createBusinessApplication = new CreateBusinessApplication(); + CreateBusinessApplicationAttributes attr = new CreateBusinessApplicationAttributes(); + + attr.setName("Peter Parker"); + + Address address = new Address(); + address.setStreet("20 Ingram St"); + address.setCity("Forest Hills"); + address.setPostalCode("11375"); + address.setCountry("US"); + address.setState("NY"); + attr.setAddress(address); + + + Phone p = new Phone(); + p.setNumber("5555555555"); + p.setCountryCode("1"); + attr.setPhone(p); + + attr.setStateOfIncorporation("DE"); + attr.setEin("123456789"); + attr.setEntityType(EntityType.CORPORATION); + attr.setIp("127.0.0.1"); + attr.setAnnualRevenue(BusinessAnnualRevenue.BETWEEN250K_AND500K); + attr.setNumberOfEmployees(BusinessNumberOfEmployees.BETWEEN100_AND500); + attr.setCashFlow(CashFlow.PREDICTABLE); + attr.setYearOfIncorporation("1999"); + List countriesOfOperation = new ArrayList(); + countriesOfOperation.add("US"); + countriesOfOperation.add("CA"); + + attr.setCountriesOfOperation(countriesOfOperation); + + attr.setWebsite(null); + + String email = "richard@piedpiper.com"; + Contact contact = new Contact(); + contact.setEmail(email); + contact.setPhone(p); + FullName fn = new FullName(); + fn.setFirst("Peter"); + fn.setLast("Parker"); + contact.setFullName(fn); + attr.setContact(contact); + + + CreateOfficer officer = new CreateOfficer(); + officer.setAnnualIncome(AnnualIncome.BETWEEN50K_AND100K); + officer.setFullName(fn); + officer.setAddress(address); + officer.setEmail(email); + officer.setPhone(p); + LocalDate dateOfBirh = LocalDate.of(1997, 11, 1); + officer.setDateOfBirth(dateOfBirh); + officer.setTitle(CreateOfficer.TitleEnum.CEO); + officer.setOccupation(Occupation.ARCHITECT_OR_ENGINEER); + officer.setSourceOfIncome(SourceOfIncome.BUSINESS_OWNERSHIP_INTERESTS); + officer.setSsn("123456789"); + + attr.setOfficer(officer); + attr.setBusinessVertical(BusinessVertical.ARTS_ENTERTAINMENT_AND_RECREATION); + + List beneficialOwners = new ArrayList(); + CreateBeneficialOwner beneficialOwner = new CreateBeneficialOwner(); + beneficialOwner.setAddress(address); + beneficialOwner.setFullName(fn); + beneficialOwner.setDateOfBirth(dateOfBirh); + beneficialOwner.setSsn("721074426"); + beneficialOwner.setEmail(email); + beneficialOwner.setPhone(p); + beneficialOwner.setOccupation(Occupation.ARCHITECT_OR_ENGINEER); + beneficialOwner.setAnnualIncome(AnnualIncome.BETWEEN100K_AND250K); + beneficialOwner.setSourceOfIncome(SourceOfIncome.BUSINESS_OWNERSHIP_INTERESTS); + beneficialOwners.add(beneficialOwner); + attr.setBeneficialOwners(beneficialOwners); + + createBusinessApplication.setAttributes(attr); + + CreateApplicationRequest ca = new CreateApplicationRequest(); + ca.data(new CreateApplicationRequestData(createBusinessApplication)); + + UnitCreateApplicationResponse res = unitApi.createApplication(ca) + +you can find more examples in the unit/e2e_tests/java directory #### Typescript - import { GetAccountApi } from "./api"; + import { + Address, + AnnualIncome, + BusinessAnnualRevenue, + BusinessNumberOfEmployees, + BusinessVertical, + CashFlow, + CreateApplicationRequest, + EntityType, + FullName, + Occupation, + OfficerTitleEnum, + Phone, + SourceOfIncome, + UnitApi, + } from "./api"; import { Configuration } from "./configuration"; - const token = "your_token" - const con: Configuration = new Configuration({accessToken: token}) - const api: GetAccountApi = new GetAccountApi(con) - async function exec() { - return (await api.execute("12345")).data - } - - exec().then((res) => { - console.log(res) - }) + const config: Configuration = new Configuration({ + accessToken: "access_token" + }); + const unitApi: UnitApi = new UnitApi(config); + + const address: Address = { + street: "20 Ingram St", + city: "Forest Hills", + postalCode: "11375", + country: "US", + state: "NY", + }; + const phone: Phone = { + number: "5555555555", + countryCode: "1", + }; + const fullName: FullName = { + first: "Peter", + last: "Parker", + }; + const email = "richard@piedpiper.com"; + const dateOfBirth = "1997-11-01"; + const today = new Date(); + + const req: CreateApplicationRequest = { + data: { + type: "businessApplication", + attributes: { + name: "Peter Parker", + address, + phone, + stateOfIncorporation: "DE", + ein: "123456789", + entityType: EntityType.Corporation, + ip: "127.0.0.1", + annualRevenue: BusinessAnnualRevenue.Between1mAnd5m, + numberOfEmployees: BusinessNumberOfEmployees.Between100And500, + cashFlow: CashFlow.Predictable, + countriesOfOperation: ["US", "CA"], + businessVertical: BusinessVertical.AgricultureForestryFishingOrHunting, + yearOfIncorporation: (today.getFullYear() - 2).toString(), + contact: { + email, + fullName, + phone, + }, + officer: { + annualIncome: AnnualIncome.Between100kAnd250k, + fullName, + address, + email, + phone, + dateOfBirth, + title: OfficerTitleEnum.Ceo, + occupation: Occupation.ArchitectOrEngineer, + sourceOfIncome: SourceOfIncome.BusinessOwnershipInterests, + ssn: "123456789", + }, + beneficialOwners: [ + { + address, + fullName, + dateOfBirth, + ssn: "721074426", + email, + phone, + occupation: Occupation.ArchitectOrEngineer, + sourceOfIncome: SourceOfIncome.BusinessOwnershipInterests, + }, + ], + }, + }, + }; + + let res = await unitApi.createApplication(req); ## Known Generators Issues @@ -164,12 +273,35 @@ When generating a python-sdk, you should change the configurations to: "name": "Authorization" } +### Java responses + +We are using `Java native` as a library template during generation of the java sdk and there are issues with types in responses containing raw text or binary files. +In order to fix that we have a custom script in place. If you would generate a library yourself you should call the `fix-java-file-get-requests` script from package.json providing the `--path=./dist/java-sdk/src/main/java/unit/java/sdk/api/UnitApi.java` argument to fix the errors after the generation. + ### CLI version Use the follow command to check the openapi-generator-cli version: `openapi-generator-cli version` -We recommend using v7.0.1, you can change the version with the command: +We recommend using v7.9.0, you can change the version with the command: + +`openapi-generator-cli version-manager set 7.9.0` + +## Legacy -`openapi-generator-cli version-manager set 7.0.1` +All of the info listed below is related to the legacy functionality and will be deprecated or updated soon + +### unit-python + +We recommend using our script which can be found in this repository: + +```commandline +python "./generate.py" +``` + +Or generate by yourself with swagger-codegen-cli: + +``` +java -jar swagger-codegen-cli-3.0.47.jar generate -i openapi.json -l python -o unit +``` diff --git a/changes_script.rb b/changes_script.rb deleted file mode 100644 index 788f69b..0000000 --- a/changes_script.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'fileutils' - -source_dir = '../openapi-unit-sdk/schemas' -target_dir = '../openapi-unit-sdk/schemas_with_one_of' - -exclusions = [ - 'account.json', - 'application.json', - 'authorization_request.json', - 'card.json', - 'customer.json', - 'limits.json', - 'payment.json', - 'recurring_payment.json', - 'repayment.json', - 'transaction.json' -] - -def copy_files(source, target, exclusions) - FileUtils.mkdir_p(target) unless File.exist?(target) - - Dir.foreach(source) do |item| - next if item == '.' or item == '..' - next if exclusions.include?(item) - - source_path = File.join(source, item) - target_path = File.join(target, item) - - if File.directory?(source_path) - copy_files(source_path, target_path, exclusions) - else - FileUtils.cp(source_path, target_path) - end - end -end - -copy_files(source_dir, target_dir, exclusions) - -puts "Files copied successfully, excluding specified files." diff --git a/generate.rb b/generate.rb deleted file mode 100644 index b04a2f4..0000000 --- a/generate.rb +++ /dev/null @@ -1,328 +0,0 @@ -require 'json' -require 'open3' - -# Function to replace paths in the OpenAPI JSON file -def replace_paths_with_one_of(openapi_file, new_paths) - begin - openapi_data = JSON.parse(File.read(openapi_file)) - - # Replace the 'paths' section with new paths - openapi_data['paths'] = new_paths - - # Write the modified OpenAPI file back - File.open(openapi_file, 'w') do |file| - file.write(JSON.pretty_generate(openapi_data)) - end - - puts "OpenAPI file updated successfully." - rescue => e - puts "An error occurred: #{e.message}" - end -end - -# New paths referencing 'schemas_with_one_of' -new_paths = { - "/applications/{applicationId}": { - "$ref": "./schemas_with_one_of/application_paths.json#/application" - }, - "/applications/{applicationId}/cancel": { - "$ref": "./schemas_with_one_of/application_paths.json#/cancel_application" - }, - "/applications": { - "$ref": "./schemas_with_one_of/application_paths.json#/applications" - }, - "/application-forms": { - "$ref": "./schemas_with_one_of/application_paths.json#/application_forms" - }, - "/applications/{applicationId}/documents/{documentId}": { - "$ref": "./schemas_with_one_of/application_paths.json#/upload_pdf_file" - }, - "/applications/{applicationId}/documents/{documentId}/": { - "$ref": "./schemas_with_one_of/application_paths.json#/upload_png_file" - }, - "/applications/{applicationId}/documents/{documentId}/?": { - "$ref": "./schemas_with_one_of/application_paths.json#/upload_jpg_file" - }, - "/applications/{applicationId}/documents/{documentId}/back": { - "$ref": "./schemas_with_one_of/application_paths.json#/upload_pdf_file_back" - }, - "/applications/{applicationId}/documents/{documentId}/back/": { - "$ref": "./schemas_with_one_of/application_paths.json#/upload_png_file_back" - }, - "/applications/{applicationId}/documents/{documentId}/back/?": { - "$ref": "./schemas_with_one_of/application_paths.json#/upload_jpg_file_back" - }, - "/applications/{applicationId}/documents": { - "$ref": "./schemas_with_one_of/application_paths.json#/documents" - }, - "/applications/{applicationId}/documents/{documentId}/verify": { - "$ref": "./schemas_with_one_of/application_paths.json#/verify_document" - }, - "/applications/{applicationId}/documents/{documentId}/download": { - "$ref": "./schemas_with_one_of/application_paths.json#/download_document" - }, - "/applications/{applicationId}/documents/{documentId}/download/back": { - "$ref": "./schemas_with_one_of/application_paths.json#/download_back_side_document" - }, - "/application-forms/{applicationFormId}": { - "$ref": "./schemas_with_one_of/application_paths.json#/application_form" - }, - "/accounts": { - "$ref": "./schemas_with_one_of/account_paths.json#/accounts" - }, - "/accounts/{accountId}": { - "$ref": "./schemas_with_one_of/account_paths.json#/account" - }, - "/accounts/{accountId}/limits": { - "$ref": "./schemas_with_one_of/account_paths.json#/get_account_limits" - }, - "/accounts/{accountId}/unfreeze": { - "$ref": "./schemas_with_one_of/account_paths.json#/unfreeze_account" - }, - "/accounts/{accountId}/freeze": { - "$ref": "./schemas_with_one_of/account_paths.json#/freeze_account" - }, - "/accounts/{accountId}/close": { - "$ref": "./schemas_with_one_of/account_paths.json#/close_account" - }, - "/accounts/{accountId}/reopen": { - "$ref": "./schemas_with_one_of/account_paths.json#/reopen_account" - }, - "/accounts/{accountId}/enter-daca": { - "$ref": "./schemas_with_one_of/account_paths.json#/enter_daca" - }, - "/accounts/{accountId}/activate-daca": { - "$ref": "./schemas_with_one_of/account_paths.json#/activate_daca" - }, - "/accounts/{accountId}/deactivate-daca": { - "$ref": "./schemas_with_one_of/account_paths.json#/deactivate_daca" - }, - "/account-end-of-day": { - "$ref": "./schemas_with_one_of/account_paths.json#/get_account_end_of_day" - }, - "/customers/{customerId}": { - "$ref": "./schemas_with_one_of/customer_paths.json#/customer" - }, - "/customers": { - "$ref": "./schemas_with_one_of/customer_paths.json#/list_customers" - }, - "/customers/{customerId}/archive": { - "$ref": "./schemas_with_one_of/customer_paths.json#/archive_customer" - }, - "/payments": { - "$ref": "./schemas_with_one_of/payments_paths.json#/get_and_create_payments" - }, - "/payments/{paymentId}": { - "$ref": "./schemas_with_one_of/payments_paths.json#/get_and_patch_payment" - }, - "/payments/{paymentId}/cancel": { - "$ref": "./schemas_with_one_of/payments_paths.json#/cancel_payment" - }, - "/received-payments": { - "$ref": "./schemas_with_one_of/payments_paths.json#/list_received_payments" - }, - "/received-payments/{paymentId}": { - "$ref": "./schemas_with_one_of/payments_paths.json#/received_payments" - }, - "/received-payments/{paymentId}/advance": { - "$ref": "./schemas_with_one_of/payments_paths.json#/advance_received_payment" - }, - "/counterparties": { - "$ref": "./schemas_with_one_of/counterparty_paths.json#/counterparties" - }, - "/counterparties/{counterpartyId}": { - "$ref": "./schemas_with_one_of/counterparty_paths.json#/counterparty" - }, - "/counterparties/{counterpartyId}/balance": { - "$ref": "./schemas_with_one_of/counterparty_paths.json#/counterparty_balance" - }, - "/recurring-payments": { - "$ref": "./schemas_with_one_of/payments_paths.json#/recurring_payments" - }, - "/recurring-payments/{paymentId}": { - "$ref": "./schemas_with_one_of/payments_paths.json#/get_recurring_payment" - }, - "/recurring-payments/{paymentId}/disable": { - "$ref": "./schemas_with_one_of/payments_paths.json#/disable_recurring_payment" - }, - "/recurring-payments/{paymentId}/enable": { - "$ref": "./schemas_with_one_of/payments_paths.json#/enable_recurring_payment" - }, - "/cards": { - "$ref": "./schemas_with_one_of/card_paths.json#/cards" - }, - "/cards/{cardId}": { - "$ref": "./schemas_with_one_of/card_paths.json#/card" - }, - "/cards/{cardId}/secure-data/pin/status": { - "$ref": "./schemas_with_one_of/card_paths.json#/card_pin_status" - }, - "/cards/{cardId}/report-stolen": { - "$ref": "./schemas_with_one_of/card_paths.json#/report_stolen_card" - }, - "/cards/{cardId}/report-lost": { - "$ref": "./schemas_with_one_of/card_paths.json#/report_lost_card" - }, - "/cards/{cardId}/close": { - "$ref": "./schemas_with_one_of/card_paths.json#/close_card" - }, - "/cards/{cardId}/freeze": { - "$ref": "./schemas_with_one_of/card_paths.json#/freeze_card" - }, - "/cards/{cardId}/unfreeze": { - "$ref": "./schemas_with_one_of/card_paths.json#/unfreeze_card" - }, - "/cards/{cardId}/limits": { - "$ref": "./schemas_with_one_of/card_paths.json#/card_limits" - }, - "/authorizations": { - "$ref": "./schemas_with_one_of/authorization_paths.json#/authorizations" - }, - "/authorizations/{authorizationId}": { - "$ref": "./schemas_with_one_of/authorization_paths.json#/get_authorization" - }, - "/authorization-requests": { - "$ref": "./schemas_with_one_of/authorization_paths.json#/get_authorizations_requests" - }, - "/authorization-requests/{authorizationId}": { - "$ref": "./schemas_with_one_of/authorization_paths.json#/get_authorization_requests" - }, - "/authorization-requests/{authorizationId}/approve": { - "$ref": "./schemas_with_one_of/authorization_paths.json#/approve_authorization_requests" - }, - "/authorization-requests/{authorizationId}/decline": { - "$ref": "./schemas_with_one_of/authorization_paths.json#/decline_authorization_requests" - }, - "/statements": { - "$ref": "./schemas_with_one_of/statement_paths.json#/get_statements" - }, - "/statements/{statementId}/html": { - "$ref": "./schemas_with_one_of/statement_paths.json#/get_statement_html" - }, - "/statements/{statementId}/pdf": { - "$ref": "./schemas_with_one_of/statement_paths.json#/get_statement_pdf" - }, - "/statements/{accountId}/bank/pdf": { - "$ref": "./schemas_with_one_of/statement_paths.json#/get_statement_bank_pdf" - }, - "/rewards": { - "$ref": "./schemas_with_one_of/reward_paths.json#/rewards" - }, - "/rewards/{rewardId}": { - "$ref": "./schemas_with_one_of/reward_paths.json#/get_reward" - }, - "/events": { - "$ref": "./schemas_with_one_of/event_paths.json#/list_events" - }, - "/events/{eventId}": { - "$ref": "./schemas_with_one_of/event_paths.json#/event" - }, - "/institutions/{routingNumber}": { - "$ref": "./schemas_with_one_of/institution_paths.json#/get_institution" - }, - "/fees": { - "$ref": "./schemas_with_one_of/fee_paths.json#/create_fee" - }, - "/check-deposits": { - "$ref": "./schemas_with_one_of/check_deposit_paths.json#/check_deposits" - }, - "/check-deposits/{checkDepositId}": { - "$ref": "./schemas_with_one_of/check_deposit_paths.json#/check_deposit" - }, - "/check-deposits/{checkDepositId}/confirm": { - "$ref": "./schemas_with_one_of/check_deposit_paths.json#/confirm_check_deposit" - }, - "/check-deposits/{checkDepositId}/front": { - "$ref": "./schemas_with_one_of/check_deposit_paths.json#/get_front_check_deposit" - }, - "/check-deposits/{checkDepositId}/back": { - "$ref": "./schemas_with_one_of/check_deposit_paths.json#/get_back_check_deposit" - }, - "/users/{userId}/api-tokens": { - "$ref": "./schemas_with_one_of/token_paths.json#/api_tokens" - }, - "/users/{userId}/api-tokens/{tokenId}": { - "$ref": "./schemas_with_one_of/token_paths.json#/delete_token" - }, - "/customers/{customerId}/token": { - "$ref": "./schemas_with_one_of/token_paths.json#/create_customer_token" - }, - "/customers/{customerId}/token/verification": { - "$ref": "./schemas_with_one_of/token_paths.json#/create_customer_token_verification" - }, - "/webhooks": { - "$ref": "./schemas_with_one_of/webhook_paths.json#/webhooks" - }, - "/webhooks/{webhookId}": { - "$ref": "./schemas_with_one_of/webhook_paths.json#/webhook" - }, - "/webhooks/{webhookId}/enable": { - "$ref": "./schemas_with_one_of/webhook_paths.json#/enable_webhook" - }, - "/webhooks/{webhookId}/disable": { - "$ref": "./schemas_with_one_of/webhook_paths.json#/disable_webhook" - }, - "/atm-locations": { - "$ref": "./schemas_with_one_of/atm_location_paths.json#/list_atm_locations" - }, - "/accounts/{accountId}/transactions/{transactionId}": { - "$ref": "./schemas_with_one_of/transaction_paths.json#/transaction" - }, - "/transactions": { - "$ref": "./schemas_with_one_of/transaction_paths.json#/list_transactions" - }, - "/disputes": { - "$ref": "./schemas_with_one_of/dispute_paths.json#/list_disputes" - }, - "/disputes/{disputeId}": { - "$ref": "./schemas_with_one_of/dispute_paths.json#/get_dispute" - }, - "/repayments": { - "$ref": "./schemas_with_one_of/repayment_paths.json#/repayments" - }, - "/repayments/{repaymentId}": { - "$ref": "./schemas_with_one_of/repayment_paths.json#/repayment" - }, - "/check-payments": { - "$ref": "./schemas_with_one_of/check_payment_paths.json#/check_payments" - }, - "/check-payments/{checkPaymentId}": { - "$ref": "./schemas_with_one_of/check_payment_paths.json#/check_payment" - }, - "/check-payments/{checkPaymentId}/approve": { - "$ref": "./schemas_with_one_of/check_payment_paths.json#/check_payment_approve" - }, - "/check-payments/{checkPaymentId}/cancel": { - "$ref": "./schemas_with_one_of/check_payment_paths.json#/check_payment_cancel" - }, - "/check-payments/{checkPaymentId}/return": { - "$ref": "./schemas_with_one_of/check_payment_paths.json#/check_payment_return" - }, - "/check-payments/{checkPaymentId}/front": { - "$ref": "./schemas_with_one_of/check_payment_paths.json#/get_check_payment_front" - }, - "/check-payments/{checkPaymentId}/back": { - "$ref": "./schemas_with_one_of/check_payment_paths.json#/get_check_payment_back" - }, - "/stop-payments": { - "$ref": "./schemas_with_one_of/stop_payment_paths.json#/stop_payments" - }, - "/stop-payments/{stop_payment_id}": { - "$ref": "./schemas_with_one_of/stop_payment_paths.json#/stop_payment" - }, - "/stop-payments/{stop_payment_id}/disable": { - "$ref": "./schemas_with_one_of/stop_payment_paths.json#/disable_stop_payment" - } -} - -replace_paths_with_one_of("openapi.json", new_paths) - -# Generate the Ruby SDK using openapi-generator-cli -command = "openapi-generator-cli generate -g ruby -i openapi.json -o unit/e2e_tests/ruby" -stdout, stderr, status = Open3.capture3(command) - -if status.success? - puts "SDK generated successfully." -else - puts "Error generating SDK: #{stderr}" -end diff --git a/openapi.json b/openapi.json index 6f59efa..631369b 100644 --- a/openapi.json +++ b/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "Unit OpenAPI specifications", "description": "An OpenAPI specifications for unit-sdk clients", - "version": "0.1.0" + "version": "0.2.0" }, "servers": [ { From 1607490963ced159ac26014cfa04ab9f80ba50b6 Mon Sep 17 00:00:00 2001 From: YegorZh Date: Fri, 22 Nov 2024 19:07:18 +0000 Subject: [PATCH 2/4] feat: python improvements, removed unused bearer related components, usage example updates --- README.md | 354 +++++++++++++++++++++++++++------------------------ generate.py | 111 ---------------- openapi.json | 16 +-- package.json | 3 +- 4 files changed, 193 insertions(+), 291 deletions(-) delete mode 100644 generate.py diff --git a/README.md b/README.md index 3d62fdd..599fddd 100644 --- a/README.md +++ b/README.md @@ -62,104 +62,107 @@ Applies prettier formatting to the schemas #### Java - String access_token = "access_token"; - ApiClient cl = new ApiClient(); - ObjectMapper mapper = cl.getObjectMapper(); - mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // To allow certain requests with empty bodies - cl.setObjectMapper(mapper); - cl.setRequestInterceptor(r -> { - r.header("Authorization", "Bearer " + access_token); - }); - UnitApi unitApi = new UnitApi(cl); - - CreateBusinessApplication createBusinessApplication = new CreateBusinessApplication(); - CreateBusinessApplicationAttributes attr = new CreateBusinessApplicationAttributes(); - - attr.setName("Peter Parker"); - - Address address = new Address(); - address.setStreet("20 Ingram St"); - address.setCity("Forest Hills"); - address.setPostalCode("11375"); - address.setCountry("US"); - address.setState("NY"); - attr.setAddress(address); - - - Phone p = new Phone(); - p.setNumber("5555555555"); - p.setCountryCode("1"); - attr.setPhone(p); - - attr.setStateOfIncorporation("DE"); - attr.setEin("123456789"); - attr.setEntityType(EntityType.CORPORATION); - attr.setIp("127.0.0.1"); - attr.setAnnualRevenue(BusinessAnnualRevenue.BETWEEN250K_AND500K); - attr.setNumberOfEmployees(BusinessNumberOfEmployees.BETWEEN100_AND500); - attr.setCashFlow(CashFlow.PREDICTABLE); - attr.setYearOfIncorporation("1999"); - List countriesOfOperation = new ArrayList(); - countriesOfOperation.add("US"); - countriesOfOperation.add("CA"); - - attr.setCountriesOfOperation(countriesOfOperation); - - attr.setWebsite(null); - - String email = "richard@piedpiper.com"; - Contact contact = new Contact(); - contact.setEmail(email); - contact.setPhone(p); - FullName fn = new FullName(); - fn.setFirst("Peter"); - fn.setLast("Parker"); - contact.setFullName(fn); - attr.setContact(contact); - - - CreateOfficer officer = new CreateOfficer(); - officer.setAnnualIncome(AnnualIncome.BETWEEN50K_AND100K); - officer.setFullName(fn); - officer.setAddress(address); - officer.setEmail(email); - officer.setPhone(p); - LocalDate dateOfBirh = LocalDate.of(1997, 11, 1); - officer.setDateOfBirth(dateOfBirh); - officer.setTitle(CreateOfficer.TitleEnum.CEO); - officer.setOccupation(Occupation.ARCHITECT_OR_ENGINEER); - officer.setSourceOfIncome(SourceOfIncome.BUSINESS_OWNERSHIP_INTERESTS); - officer.setSsn("123456789"); - - attr.setOfficer(officer); - attr.setBusinessVertical(BusinessVertical.ARTS_ENTERTAINMENT_AND_RECREATION); - - List beneficialOwners = new ArrayList(); - CreateBeneficialOwner beneficialOwner = new CreateBeneficialOwner(); - beneficialOwner.setAddress(address); - beneficialOwner.setFullName(fn); - beneficialOwner.setDateOfBirth(dateOfBirh); - beneficialOwner.setSsn("721074426"); - beneficialOwner.setEmail(email); - beneficialOwner.setPhone(p); - beneficialOwner.setOccupation(Occupation.ARCHITECT_OR_ENGINEER); - beneficialOwner.setAnnualIncome(AnnualIncome.BETWEEN100K_AND250K); - beneficialOwner.setSourceOfIncome(SourceOfIncome.BUSINESS_OWNERSHIP_INTERESTS); - beneficialOwners.add(beneficialOwner); - attr.setBeneficialOwners(beneficialOwners); - - createBusinessApplication.setAttributes(attr); - - CreateApplicationRequest ca = new CreateApplicationRequest(); - ca.data(new CreateApplicationRequestData(createBusinessApplication)); - - UnitCreateApplicationResponse res = unitApi.createApplication(ca) +```java +String access_token = "access_token"; +ApiClient cl = new ApiClient(); +ObjectMapper mapper = cl.getObjectMapper(); +mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // To allow certain requests with empty bodies +cl.setObjectMapper(mapper); +cl.setRequestInterceptor(r -> { + r.header("Authorization", "Bearer " + access_token); +}); +UnitApi unitApi = new UnitApi(cl); + +CreateBusinessApplication createBusinessApplication = new CreateBusinessApplication(); +CreateBusinessApplicationAttributes attr = new CreateBusinessApplicationAttributes(); + +attr.setName("Peter Parker"); + +Address address = new Address(); +address.setStreet("20 Ingram St"); +address.setCity("Forest Hills"); +address.setPostalCode("11375"); +address.setCountry("US"); +address.setState("NY"); +attr.setAddress(address); + + +Phone p = new Phone(); +p.setNumber("5555555555"); +p.setCountryCode("1"); +attr.setPhone(p); + +attr.setStateOfIncorporation("DE"); +attr.setEin("123456789"); +attr.setEntityType(EntityType.CORPORATION); +attr.setIp("127.0.0.1"); +attr.setAnnualRevenue(BusinessAnnualRevenue.BETWEEN250K_AND500K); +attr.setNumberOfEmployees(BusinessNumberOfEmployees.BETWEEN100_AND500); +attr.setCashFlow(CashFlow.PREDICTABLE); +attr.setYearOfIncorporation("1999"); +List countriesOfOperation = new ArrayList(); +countriesOfOperation.add("US"); +countriesOfOperation.add("CA"); + +attr.setCountriesOfOperation(countriesOfOperation); + +attr.setWebsite(null); + +String email = "richard@piedpiper.com"; +Contact contact = new Contact(); +contact.setEmail(email); +contact.setPhone(p); +FullName fn = new FullName(); +fn.setFirst("Peter"); +fn.setLast("Parker"); +contact.setFullName(fn); +attr.setContact(contact); + + +CreateOfficer officer = new CreateOfficer(); +officer.setAnnualIncome(AnnualIncome.BETWEEN50K_AND100K); +officer.setFullName(fn); +officer.setAddress(address); +officer.setEmail(email); +officer.setPhone(p); +LocalDate dateOfBirh = LocalDate.of(1997, 11, 1); +officer.setDateOfBirth(dateOfBirh); +officer.setTitle(CreateOfficer.TitleEnum.CEO); +officer.setOccupation(Occupation.ARCHITECT_OR_ENGINEER); +officer.setSourceOfIncome(SourceOfIncome.BUSINESS_OWNERSHIP_INTERESTS); +officer.setSsn("123456789"); + +attr.setOfficer(officer); +attr.setBusinessVertical(BusinessVertical.ARTS_ENTERTAINMENT_AND_RECREATION); + +List beneficialOwners = new ArrayList(); +CreateBeneficialOwner beneficialOwner = new CreateBeneficialOwner(); +beneficialOwner.setAddress(address); +beneficialOwner.setFullName(fn); +beneficialOwner.setDateOfBirth(dateOfBirh); +beneficialOwner.setSsn("721074426"); +beneficialOwner.setEmail(email); +beneficialOwner.setPhone(p); +beneficialOwner.setOccupation(Occupation.ARCHITECT_OR_ENGINEER); +beneficialOwner.setAnnualIncome(AnnualIncome.BETWEEN100K_AND250K); +beneficialOwner.setSourceOfIncome(SourceOfIncome.BUSINESS_OWNERSHIP_INTERESTS); +beneficialOwners.add(beneficialOwner); +attr.setBeneficialOwners(beneficialOwners); + +createBusinessApplication.setAttributes(attr); + +CreateApplicationRequest ca = new CreateApplicationRequest(); +ca.data(new CreateApplicationRequestData(createBusinessApplication)); + +UnitCreateApplicationResponse res = unitApi.createApplication(ca) +``` you can find more examples in the unit/e2e_tests/java directory #### Typescript - import { +```typescript +import { Address, AnnualIncome, BusinessAnnualRevenue, @@ -174,104 +177,127 @@ you can find more examples in the unit/e2e_tests/java directory Phone, SourceOfIncome, UnitApi, - } from "./api"; - import { Configuration } from "./configuration"; +} from "./api"; +import { Configuration } from "./configuration"; - const config: Configuration = new Configuration({ - accessToken: "access_token" - }); - const unitApi: UnitApi = new UnitApi(config); +const config: Configuration = new Configuration({ + accessToken: "access_token", +}); +const unitApi: UnitApi = new UnitApi(config); - const address: Address = { +const address: Address = { street: "20 Ingram St", city: "Forest Hills", postalCode: "11375", country: "US", state: "NY", - }; - const phone: Phone = { +}; +const phone: Phone = { number: "5555555555", countryCode: "1", - }; - const fullName: FullName = { +}; +const fullName: FullName = { first: "Peter", last: "Parker", - }; - const email = "richard@piedpiper.com"; - const dateOfBirth = "1997-11-01"; - const today = new Date(); +}; +const email = "richard@piedpiper.com"; +const dateOfBirth = "1997-11-01"; +const today = new Date(); - const req: CreateApplicationRequest = { +const req: CreateApplicationRequest = { data: { type: "businessApplication", attributes: { - name: "Peter Parker", - address, - phone, - stateOfIncorporation: "DE", - ein: "123456789", - entityType: EntityType.Corporation, - ip: "127.0.0.1", - annualRevenue: BusinessAnnualRevenue.Between1mAnd5m, - numberOfEmployees: BusinessNumberOfEmployees.Between100And500, - cashFlow: CashFlow.Predictable, - countriesOfOperation: ["US", "CA"], - businessVertical: BusinessVertical.AgricultureForestryFishingOrHunting, - yearOfIncorporation: (today.getFullYear() - 2).toString(), - contact: { - email, - fullName, - phone, - }, - officer: { - annualIncome: AnnualIncome.Between100kAnd250k, - fullName, - address, - email, - phone, - dateOfBirth, - title: OfficerTitleEnum.Ceo, - occupation: Occupation.ArchitectOrEngineer, - sourceOfIncome: SourceOfIncome.BusinessOwnershipInterests, - ssn: "123456789", - }, - beneficialOwners: [ - { + name: "Peter Parker", address, - fullName, - dateOfBirth, - ssn: "721074426", - email, phone, - occupation: Occupation.ArchitectOrEngineer, - sourceOfIncome: SourceOfIncome.BusinessOwnershipInterests, + stateOfIncorporation: "DE", + ein: "123456789", + entityType: EntityType.Corporation, + ip: "127.0.0.1", + annualRevenue: BusinessAnnualRevenue.Between1mAnd5m, + numberOfEmployees: BusinessNumberOfEmployees.Between100And500, + cashFlow: CashFlow.Predictable, + countriesOfOperation: ["US", "CA"], + businessVertical: + BusinessVertical.AgricultureForestryFishingOrHunting, + yearOfIncorporation: (today.getFullYear() - 2).toString(), + contact: { + email, + fullName, + phone, }, - ], + officer: { + annualIncome: AnnualIncome.Between100kAnd250k, + fullName, + address, + email, + phone, + dateOfBirth, + title: OfficerTitleEnum.Ceo, + occupation: Occupation.ArchitectOrEngineer, + sourceOfIncome: SourceOfIncome.BusinessOwnershipInterests, + ssn: "123456789", + }, + beneficialOwners: [ + { + address, + fullName, + dateOfBirth, + ssn: "721074426", + email, + phone, + occupation: Occupation.ArchitectOrEngineer, + sourceOfIncome: SourceOfIncome.BusinessOwnershipInterests, + }, + ], }, }, - }; +}; - let res = await unitApi.createApplication(req); +let res = await unitApi.createApplication(req); +``` + +#### Python + +```python +import unit_python_sdk +from unit_python_sdk.rest import ApiException + +# Defining the host is optional and defaults to https://api.s.unit.sh +# See configuration.py for a list of all supported configuration parameters. +configuration = unit_python_sdk.Configuration( + host = "https://api.s.unit.sh" +) -## Known Generators Issues -### Authorization Tokens -The default authorization configuration is located in components/securitySchemes/bearerAuth section in the openapi.json file and looks as follows: +# Enter a context with an instance of the API client +with unit_python_sdk.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_client.set_default_header("Authorization", "Bearer access_token"); + api_instance = unit_python_sdk.UnitApi(api_client) - "bearerAuth": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "JWT" - } + try: + full_name = unit_python_sdk.FullName(first="Peter", last="Parker"); + address = unit_python_sdk.Address(street="20 Ingram St", street2=None, city="Forest Hills", state="NY", postalCode="11375", country="US"); + ssn = "721074426" + date_of_birth = "2001-08-10"; + email = "peter@oscorp.com"; + phone = unit_python_sdk.Phone(countryCode="1", number="5555555555"); + occupation = unit_python_sdk.Occupation.ARCHITECTORENGINEER; + attributes: unit_python_sdk.CreateIndividualApplicationAttributes = unit_python_sdk.CreateIndividualApplicationAttributes(fullName=full_name, email=email, phone=phone, ssn=ssn, dateOfBirth=date_of_birth, address=address, occupation=occupation); + createIndividualApplication: unit_python_sdk.CreateIndividualApplication = unit_python_sdk.CreateIndividualApplication(type="individualApplication", attributes=attributes); + data = unit_python_sdk.CreateApplicationRequestData(createIndividualApplication); + req = unit_python_sdk.CreateApplicationRequest(data=data); -When generating a python-sdk, you should change the configurations to: - "bearerAuth": { - "type": "apiKey", - "in": "header", - "name": "Authorization" - } + res = api_instance.create_application(req); + except ApiException as e: + print("Exception when calling UnitApi->create_application: %s\n" % e) +``` + +## Known Generators Issues ### Java responses diff --git a/generate.py b/generate.py deleted file mode 100644 index 92854b0..0000000 --- a/generate.py +++ /dev/null @@ -1,111 +0,0 @@ -import os -import json - -python_bearer_auth = { - "type": "apiKey", - "in": "header", - "name": "Authorization" -} - -default_bearer_auth = { - "type": "http", - "scheme": "bearer", - "bearerFormat": "JWT" -} - - -def change_bearer(bearer=python_bearer_auth): - with open('openapi.json', encoding='utf8') as file: - j = json.load(file) - - j["components"]["securitySchemes"]["bearerAuth"] = bearer - - with open('openapi.json', 'w', encoding='utf8') as file: - json.dump(j, file, indent=4, ensure_ascii=False) - - -# if flag is not python -change_bearer() - -path_of_the_directory = './schemas/' - -for filename in os.listdir(path_of_the_directory): - f_path = os.path.join(path_of_the_directory, filename) - if os.path.isfile(f_path): - f = open(f_path, 'r', encoding="utf8") - json_object = json.load(f) - f.close - - json_object_as_string = str(json_object) - json_object_as_string = json_object_as_string.replace('./schemas/', '') - json_object_as_string = json_object_as_string.replace('./', '') - json_object_as_string = json_object_as_string.replace('"$ref": "../', '"$ref": "') - - if json_object_as_string == str(json_object): - continue - - data = eval(json_object_as_string) - - # Re-open file here - f2 = open(f_path, 'w', encoding="utf8") - json.dump(data, f2, indent=4) - # for line in lineList: - # line = line.replace('./schemas/', '') - # f2.write(line) - f2.close() - -try: - path_of_the_directory = "./unit/swagger_client" - for root, dirs, files in os.walk(path_of_the_directory, topdown=False): - for name in files: - os.remove(os.path.join(root, name)) - for name in dirs: - os.rmdir(os.path.join(root, name)) -except FileNotFoundError: - print("ignore") - -file_name = "swagger-codegen-cli-3.0.47.jar" -if not os.path.exists(file_name): - print(f"Error: Unable to access jarfile {file_name}") - change_bearer(default_bearer_auth) - exit(1) - -os.system(f"java -jar {file_name} generate -i openapi.json -l python -o unit") - -path_of_the_directory = './unit/swagger_client/models/' - -if not os.path.exists(path_of_the_directory): - change_bearer(default_bearer_auth) - exit(1) - -for filename in os.listdir(path_of_the_directory): - f_path = os.path.join(path_of_the_directory, filename) - if os.path.isfile(f_path): - f = open(f_path, 'r') - lineList = f.readlines() - f.close - - # Re-open file here - f2 = open(f_path, 'w') - for line in lineList: - line = line.replace('#/components/schemas/', '') - f2.write(line) - f2.close() - -f_path = "unit/swagger_client/api/create_application_api.py" -f = open(f_path, 'r') -lineList = f.readlines() -f.close - -# Re-open file here -f2 = open(f_path, 'w') -for line in lineList: - line = line.replace('_create_application', 'create_application') - f2.write(line) -f2.close() - - -change_bearer(default_bearer_auth) - - - diff --git a/openapi.json b/openapi.json index 631369b..3584a8b 100644 --- a/openapi.json +++ b/openapi.json @@ -359,19 +359,5 @@ "/sandbox/received-ach-payment": { "$ref": "./schemas/simulation/simulationPaths.json#/createIncomingAchPayment" } - }, - "components": { - "securitySchemes": { - "bearerAuth": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "JWT" - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ] + } } diff --git a/package.json b/package.json index 34a0825..0381c81 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "add-version-header-to-java": "ts-node ./scripts/java/addVersionHeaderToApiClient.ts", "generate-java": "rm -rf ./dist/java-sdk && npm run bundle && npx mkdirp dist/java-sdk/src/test/java/unit/java/sdk && cp -a ./unit/e2e_tests/java/. ./dist/java-sdk/src/test/java/unit/java/sdk && openapi-generator-cli generate -g java -i ./dist/bundledSchema.json -o ./dist/java-sdk -p hideGenerationTimestamp=true -p packageName=unit.java.sdk -p modelPackage=unit.java.sdk.model -p apiPackage=unit.java.sdk.api --library native -p useJakartaEe=true --openapi-normalizer REFACTOR_ALLOF_WITH_PROPERTIES_ONLY=true && npm run fix-java-file-get-requests -- --path=./dist/java-sdk/src/main/java/unit/java/sdk/api/UnitApi.java && npm run add-version-header-to-java -- --path=./dist/java-sdk/src/main/java/unit/java/sdk/ApiClient.java", "generate-ruby": "rm -rf ./dist/ruby-sdk && npm run bundle && cp -r unit ./dist/ruby-sdk && openapi-generator-cli generate -g ruby -i ./dist/bundledSchema.json -o ./dist/ruby-sdk", - "generate-node": "rm -rf ./dist/node-sdk && npm run bundle && openapi-generator-cli generate -g typescript-axios -i ./dist/bundledSchema.json -o ./dist/node-sdk", + "generate-node": "rm -rf ./dist/node-sdk && npm run bundle && openapi-generator-cli generate -g typescript-axios -i ./dist/bundledSchema.json -o ./dist/node-sdk -p packageName=", + "generate-python": "rm -rf ./dist/python-sdk && npm run bundle && openapi-generator-cli generate -i ./dist/bundledSchema.json -g python -o ./dist/python-sdk -p packageName=unit_python_sdk", "lint": "redocly lint --config .redocly.yaml openapi.json", "format": "prettier ./schemas --write" }, From 4c828cc0209e00e2fcb79038e57064a3a0b033fe Mon Sep 17 00:00:00 2001 From: YegorZh Date: Mon, 25 Nov 2024 08:25:16 +0000 Subject: [PATCH 3/4] fix: added security back to fix linting issues --- openapi.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openapi.json b/openapi.json index 3584a8b..f7af7bb 100644 --- a/openapi.json +++ b/openapi.json @@ -359,5 +359,10 @@ "/sandbox/received-ach-payment": { "$ref": "./schemas/simulation/simulationPaths.json#/createIncomingAchPayment" } - } + }, + "security": [ + { + "bearerAuth": [] + } + ] } From e35b813d803fb7da149d85a7db90d57e2d9fbe02 Mon Sep 17 00:00:00 2001 From: YegorZh Date: Mon, 25 Nov 2024 08:51:05 +0000 Subject: [PATCH 4/4] fix: added securitySchemes component back --- openapi.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openapi.json b/openapi.json index f7af7bb..631369b 100644 --- a/openapi.json +++ b/openapi.json @@ -360,6 +360,15 @@ "$ref": "./schemas/simulation/simulationPaths.json#/createIncomingAchPayment" } }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" + } + } + }, "security": [ { "bearerAuth": []