plaid / plaid-openapi

API version 2020-09-14
https://plaid.com/docs
91 stars 37 forks source link

OpenAPI2 (or non OpenAPI 3) support #116

Closed LewisCowlesMotive closed 1 year ago

LewisCowlesMotive commented 1 year ago

Cross-linking as accidentally opened in plaid postman repo

https://github.com/plaid/plaid-postman/issues/140

phoenixy1 commented 1 year ago

As I mentioned in the other repo this isn't on the roadmap and probably won't be added to the roadmap (it'll be a big enough lift to get us onto OpenAPI 3.1) -- if you could share a little bit about your use case for the OpenAPI file we might be able to see if there is a workaround or alternative solution for solving your problem?

LewisCowlesMotive commented 1 year ago

We're trying to generate a mock server, so that we can use the api definition, to ensure our contract between our software and Plaid is valid, without being dependent on internet resources being permanently available. One component of this is a response generator; two others are request and response validators.

We have this successfully and easily completed with other providers, including railsbank and yapily, who use OpenAPI3; but there are some things about the Plaid OpenAPI docs which make the conversion more difficult (examples in the details block below).

Despite reporting as spec-compliant after and before conversion, we see warnings and errors from any tooling we've tried. I Checked the spec, it doesn't seem to be non-compliant, just quite different to other vendor interpretations, perhaps using more OpenAPI features).

Internally we have tooling that takes an OpenAPI (2.0) definition and generates a mock server, which services multiple API's using a path-prefix. By modifying the paths to take into account a prefix, and suffixing all definitions and references, this lets us generate a big-ol ball of yaml, without conflicting entries, which the rest of the tooling uses to validate request, response conformance, as well as generating responses using examples and conventions. I Can't share that code unfortunately, which I understand is a problem.

But, moving sideways, to things I can share, even using external tools, we've found it rather impossible thus-far to generate an API server when using this OpenAPI spec, even unmodified.

Here are some errors from one of those tools. ``` plaid-adapter-proxy-1 | One or more warnings exist in the OpenApi definition plaid-adapter-proxy-1 | at: components > schemas plaid-adapter-proxy-1 | at: AuthGetResponse > properties > item > properties > error > properties > causes > items plaid-adapter-proxy-1 | Schemas with an indeterminable type cannot serialize, deserialize, or validate values. [WSCH005] plaid-adapter-proxy-1 | at: TransactionsGetResponse > properties > transactions > items > allOf > 1 plaid-adapter-proxy-1 | Required properties not specified as a property but allowed via additionalProperties: account_owner, pending_transaction_id, payment_meta, name, location, category_id, category [WSCH007] plaid-adapter-proxy-1 | at: PaymentInitiationConsentGetResponse plaid-adapter-proxy-1 | Required property not specified as a property but allowed via additionalProperties: request_id [WSCH007] plaid-adapter-proxy-1 | at: LinkTokenCreateRequest > properties > user > properties > name > allOf > 1 plaid-adapter-proxy-1 | Schemas with an indeterminable type cannot serialize, deserialize, or validate values. [WSCH005] plaid-adapter-proxy-1 | at: ScreeningStatusUpdatedWebhook > properties > screening_id plaid-adapter-proxy-1 | Schemas with an indeterminable type cannot serialize, deserialize, or validate values. [WSCH005] plaid-adapter-proxy-1 | at: EntityScreeningStatusUpdatedWebhook > properties > screening_id plaid-adapter-proxy-1 | Schemas with an indeterminable type cannot serialize, deserialize, or validate values. [WSCH005] plaid-adapter-proxy-1 | at: IdentityVerificationStepUpdatedWebhook > properties > identity_verification_id plaid-adapter-proxy-1 | Schemas with an indeterminable type cannot serialize, deserialize, or validate values. [WSCH005] plaid-adapter-proxy-1 | at: IdentityVerificationRetriedWebhook > properties > identity_verification_id plaid-adapter-proxy-1 | Schemas with an indeterminable type cannot serialize, deserialize, or validate values. [WSCH005] plaid-adapter-proxy-1 | at: IdentityVerificationStatusUpdatedWebhook > properties > identity_verification_id plaid-adapter-proxy-1 | Schemas with an indeterminable type cannot serialize, deserialize, or validate values. [WSCH005] plaid-adapter-proxy-1 | at: Cause plaid-adapter-proxy-1 | Required properties not specified as a property but allowed via additionalProperties: item_id, error_type, error_code, error_message, display_message [WSCH007] plaid-adapter-proxy-1 | at: TransferQuestionnaireCreateRequest plaid-adapter-proxy-1 | Required properties not specified as a property but allowed via additionalProperties: disbursement_limits, payment_limits, transaction_frequency [WSCH007] plaid-adapter-proxy-1 | at: WalletCreateResponse plaid-adapter-proxy-1 | Required properties not specified as a property but allowed via additionalProperties: wallet_id, balance, request_id [WSCH007] plaid-adapter-proxy-1 | at: WalletGetResponse plaid-adapter-proxy-1 | Required properties not specified as a property but allowed via additionalProperties: wallet_id, balance, request_id [WSCH007] plaid-adapter-proxy-1 | at: WalletTransactionGetResponse plaid-adapter-proxy-1 | Required properties not specified as a property but allowed via additionalProperties: transaction_id, reference, type, amount, counterparty, status, created_at, request_id [WSCH007] plaid-adapter-proxy-1 | at: DashboardUser > properties > email_address > format plaid-adapter-proxy-1 | Non standard format "email" used for type "string". [WSCH001] plaid-adapter-proxy-1 | at: EmailAddressNullable > format plaid-adapter-proxy-1 | Non standard format "email" used for type "string". [WSCH001] plaid-adapter-proxy-1 | at: EntityScreeningHitData > properties > urls > items > properties > data > properties > url > format plaid-adapter-proxy-1 | Non standard format "uri" used for type "string". [WSCH001] plaid-adapter-proxy-1 | at: EntityWatchlistScreening > properties > search_terms > properties > url > format plaid-adapter-proxy-1 | Non standard format "uri" used for type "string". [WSCH001] plaid-adapter-proxy-1 | at: FDXParty > properties plaid-adapter-proxy-1 | at: homeUri > format plaid-adapter-proxy-1 | Non standard format "uri" used for type "string". [WSCH001] plaid-adapter-proxy-1 | at: logoUri > format plaid-adapter-proxy-1 | Non standard format "uri" used for type "string". [WSCH001] plaid-adapter-proxy-1 | at: FDXHateoasLink > properties > href > format plaid-adapter-proxy-1 | Non standard format "uri-reference" used for type "string". [WSCH001] plaid-adapter-proxy-1 | at: paths plaid-adapter-proxy-1 | at: /transactions/recurring/deactivate plaid-adapter-proxy-1 | No methods defined. [WPAT001] plaid-adapter-proxy-1 | at: /transfer/originator/get > post > requestBody > content > examples plaid-adapter-proxy-1 | Media type appears invalid. [WMED001] plaid-adapter-proxy-1 | /usr/src/app/node_modules/openapi-enforcer/index.js:78 plaid-adapter-proxy-1 | if (exception && exception.hasException) throw Error(exception.toString()); plaid-adapter-proxy-1 | ^ plaid-adapter-proxy-1 | plaid-adapter-proxy-1 | Error: One or more errors exist in the OpenApi definition plaid-adapter-proxy-1 | at: components > schemas plaid-adapter-proxy-1 | at: PaymentInitiationRecipientGetResponse plaid-adapter-proxy-1 | Properties not allowed: additionalProperties, required [EDEV001] plaid-adapter-proxy-1 | at: PaymentInitiationPaymentCreateRequest > properties > schedule plaid-adapter-proxy-1 | Properties not allowed: additionalProperties, required [EDEV001] plaid-adapter-proxy-1 | at: PaymentInitiationPaymentGetResponse plaid-adapter-proxy-1 | at: allOf > 0 > properties > schedule plaid-adapter-proxy-1 | Property not allowed: required [EDEV001] plaid-adapter-proxy-1 | Properties not allowed: additionalProperties, required [EDEV001] plaid-adapter-proxy-1 | at: StandaloneCurrencyCodeList > properties > unofficial_currency_code plaid-adapter-proxy-1 | Properties not allowed: properties, required [EDEV001] plaid-adapter-proxy-1 | at: StandaloneAccountType > properties plaid-adapter-proxy-1 | at: depository plaid-adapter-proxy-1 | Properties not allowed: properties, required [EDEV001] plaid-adapter-proxy-1 | at: credit plaid-adapter-proxy-1 | Properties not allowed: properties, required [EDEV001] plaid-adapter-proxy-1 | at: loan plaid-adapter-proxy-1 | Properties not allowed: properties, required [EDEV001] plaid-adapter-proxy-1 | at: investment plaid-adapter-proxy-1 | Properties not allowed: properties, required [EDEV001] plaid-adapter-proxy-1 | at: StandaloneInvestmentTransactionType > properties plaid-adapter-proxy-1 | at: buy plaid-adapter-proxy-1 | Property not allowed: properties [EDEV001] plaid-adapter-proxy-1 | at: sell plaid-adapter-proxy-1 | Property not allowed: properties [EDEV001] plaid-adapter-proxy-1 | at: cash plaid-adapter-proxy-1 | Property not allowed: properties [EDEV001] plaid-adapter-proxy-1 | at: fee plaid-adapter-proxy-1 | Property not allowed: properties [EDEV001] plaid-adapter-proxy-1 | at: transfer plaid-adapter-proxy-1 | Property not allowed: properties [EDEV001] plaid-adapter-proxy-1 | at: IncomeSummary > properties > pay_frequency > properties > value > enum > 5 plaid-adapter-proxy-1 | Value must be a string. Received: null plaid-adapter-proxy-1 | at: AssetReportGetResponse > properties > report > properties > items > items > properties > accounts > items plaid-adapter-proxy-1 | at: allOf > 1 > properties plaid-adapter-proxy-1 | at: transactions > items plaid-adapter-proxy-1 | Property not allowed: required [EDEV001] plaid-adapter-proxy-1 | at: ownership_type > enum plaid-adapter-proxy-1 | at: 1 plaid-adapter-proxy-1 | Value must be a plain object or a null. Received: "individual" plaid-adapter-proxy-1 | at: 2 plaid-adapter-proxy-1 | Value must be a plain object or a null. Received: "joint" plaid-adapter-proxy-1 | at: 3 plaid-adapter-proxy-1 | Value must be a plain object or a null. Received: "association" plaid-adapter-proxy-1 | at: 4 plaid-adapter-proxy-1 | Value must be a plain object or a null. Received: "trust" plaid-adapter-proxy-1 | Property not allowed: required [EDEV001] plaid-adapter-proxy-1 | at Enforcer (/usr/src/app/node_modules/openapi-enforcer/index.js:78:52) ```
LewisCowlesMotive commented 1 year ago
Here are some warnings from API Matic ``` API version string does not have a valid format. ([APIMATICPRE_L001](https://docs.apimatic.io/rulesets/apimatic-preliminary-linting/valid-api-version)) Source: API > Version. API Version: 2020-09-14_1.210.4. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[19] > institutionsGet [POST, /institutions/get] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: institutions -> status -> investments -> liabilities Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[19] > institutionsGet [POST, /institutions/get] > Default Response > Examples[0] > Example Value. Undeclared Fields: institutions -> status -> investments -> liabilities Component Name/Identifier: response. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[20] > institutionsSearch [POST, /institutions/search] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: institutions -> status -> investments -> liabilities Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[20] > institutionsSearch [POST, /institutions/search] > Default Response > Examples[0] > Example Value. Undeclared Fields: institutions -> status -> investments -> liabilities Component Name/Identifier: response. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[21] > institutionsGetById [POST, /institutions/get_by_id] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: institution -> status -> investments -> liabilities Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[21] > institutionsGetById [POST, /institutions/get_by_id] > Default Response > Examples[0] > Example Value. Undeclared Fields: institution -> status -> investments -> liabilities Component Name/Identifier: response. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[81] > paymentInitiationPaymentGet [POST, /payment_initiation/payment/get] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: payment_token, payment_expiration_time, bacs -> account_id Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[81] > paymentInitiationPaymentGet [POST, /payment_initiation/payment/get] > Default Response > Examples[0] > Example Value. Undeclared Fields: payment_token, payment_expiration_time, bacs -> account_id Component Name/Identifier: response. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[82] > paymentInitiationPaymentList [POST, /payment_initiation/payment/list] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: payments -> bacs -> account_id Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[82] > paymentInitiationPaymentList [POST, /payment_initiation/payment/list] > Default Response > Examples[0] > Example Value. Undeclared Fields: payments -> bacs -> account_id Component Name/Identifier: response. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[105] > bankTransferList [POST, /bank_transfer/list] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: bank_transfers -> originator_client_id Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[105] > bankTransferList [POST, /bank_transfer/list] > Default Response > Examples[0] > Example Value. Undeclared Fields: bank_transfers -> originator_client_id Component Name/Identifier: response. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[115] > transferSweepList [POST, /transfer/sweep/list] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: sweeps -> originator_client_id Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[115] > transferSweepList [POST, /transfer/sweep/list] > Default Response > Examples[0] > Example Value. Undeclared Fields: sweeps -> originator_client_id Component Name/Identifier: response. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[122] > transferRepaymentList [POST, /transfer/repayment/list] > Parameters[1] > body > Examples[0] > Example Value. Undeclared Fields: start_time Component Name/Identifier: body. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[123] > transferRepaymentReturnList [POST, /transfer/repayment/return/list] > Parameters[1] > body > Examples[0] > Example Value. Undeclared Fields: start_time Component Name/Identifier: body. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[143] > incomeVerificationPaystubsGet [POST, /income/verification/paystubs/get] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: paystubs -> earnings -> breakdown -> canonical_desription Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[143] > incomeVerificationPaystubsGet [POST, /income/verification/paystubs/get] > Default Response > Examples[0] > Example Value. Undeclared Fields: paystubs -> earnings -> breakdown -> canonical_desription Component Name/Identifier: response. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[145] > incomeVerificationTaxformsGet [POST, /income/verification/taxforms/get] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: taxforms -> w2 -> employee_id_number, taxforms -> w2 -> state_and_local_wages -> local_wages_and_tips Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[145] > incomeVerificationTaxformsGet [POST, /income/verification/taxforms/get] > Default Response > Examples[0] > Example Value. Undeclared Fields: taxforms -> w2 -> employee_id_number, taxforms -> w2 -> state_and_local_wages -> local_wages_and_tips Component Name/Identifier: response. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[155] > creditPayrollIncomeGet [POST, /credit/payroll_income/get] > Responses > Status Code 200 > Body Content > Media Type: application/json > Examples[0] > Example Value. Undeclared Fields: items -> payroll_income -> w2s -> state_and_local_wages -> local_wages_and_tips, items -> payroll_income -> form1099s -> feburary_amount, items -> payroll_income -> form1099s -> payer_made_direct_sales_of_500_or_more_of_consumer_products_to_buyer Component Name/Identifier: response200. The example specified contains undeclared fields. ([APIMATICDOCS_L106](https://docs.apimatic.io/rulesets/apimatic-docs-linting/no-undeclared-fields-in-example-value)) Source: API > Endpoints > plaid[155] > creditPayrollIncomeGet [POST, /credit/payroll_income/get] > Default Response > Examples[0] > Example Value. Undeclared Fields: items -> payroll_income -> w2s -> state_and_local_wages -> local_wages_and_tips, items -> payroll_income -> form1099s -> feburary_amount, items -> payroll_income -> form1099s -> payer_made_direct_sales_of_500_or_more_of_consumer_products_to_buyer Component Name/Identifier: response. Input identified as OpenAPI v3.0 (YAML). A test case generated from example values for endpoint accountsGet in group plaid. A test case generated from example values for endpoint accountsBalanceGet in group plaid. A test case generated from example values for endpoint transferRepaymentList in group plaid. A test case generated from example values for endpoint transferRepaymentReturnList in group plaid. A test case generated from example values for endpoint transactionsRulesCreate in group plaid. A test case generated from example values for endpoint transactionsRulesList in group plaid. A test case generated from example values for endpoint transactionsRulesRemove in group plaid. A test case generated from example values for endpoint partnerCustomerCreate in group plaid. A test case generated from example values for endpoint partnerCustomerGet in group plaid. A test case generated from example values for endpoint partnerCustomerEnable in group plaid. A test case generated from example values for endpoint partnerCustomerRemove in group plaid. Imported: 191 Endpoints, 1046 Models. One or more elements in the API specification has a missing description. ([APIMATICDOCS_L001](https://docs.apimatic.io/rulesets/apimatic-docs-linting/required-description-all-entities)) Source: API. ```
LewisCowlesMotive commented 1 year ago

nodejs-server-server-generated.zip

this one sort-of works. I delete the security: and securityDefinitions: sections, which incorrectly tell me I need to include headers that are not included when communicating with development or sandbox

LewisCowlesMotive commented 1 year ago

I guess the core point here, goes beyond what the company I work at is after, as why would that matter to anyone but them, they'll eventually need to make way for OpenAPI 3 and 3.1 🤷 .

It would be nice if there was more tooling to avoid this kind of dev effort when working with resources. The plaid quickstart was pretty cool to answer questions, as is the postman and having any API documentation, and the static HTML included with the postman.

For now, I guess I can chuck this into docker or kubernetes (sharing in case anyone else needs)

nodejs-server-server-generated-working.zip