-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat(payments-plugin): Add multi currency support for braintree plugin #3239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: minor
Are you sure you want to change the base?
feat(payments-plugin): Add multi currency support for braintree plugin #3239
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
Hi! Thanks for this contribution. I'll need to find some time to properly review & test this - unfortunately it's unlikely in the next week due to workload. |
…in-multi-currency
|
Thanks for the nudge :) This is an amazing PR - great work on all the supporting parts for testing 👏 OK so it's now May 2025 and we have the You could add a flag to the init options, like configuration: config => {
if (BraintreePlugin.options.multipleMerchantAccountSupport === true) {
config.customfields.PaymentMethod.push(...)
}
return config;
} |
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. 💤 Files selected but had no reviewable changes (1)
You can disable this status message by setting the WalkthroughThe changes introduce a local development and testing setup for the Braintree payment plugin, including documentation, dev server scripts, and a test checkout UI. The Braintree plugin is enhanced to support multi-currency merchant account IDs, allowing merchant account selection based on order currency. Supporting types and utility functions are added, and related test infrastructure is updated. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant BraintreeTestCheckoutController
participant BraintreeDevServer
participant ShopGraphQLClient
participant BraintreePlugin
User->>BraintreeTestCheckoutController: GET /checkout
BraintreeTestCheckoutController->>BraintreeDevServer: Get clientToken
BraintreeDevServer->>ShopGraphQLClient: Query generateBraintreeClientToken
ShopGraphQLClient->>BraintreePlugin: generateBraintreeClientToken (currency)
BraintreePlugin->>BraintreePlugin: lookupMerchantAccountIdByCurrency
BraintreePlugin-->>ShopGraphQLClient: Return clientToken
ShopGraphQLClient-->>BraintreeDevServer: Return clientToken
BraintreeDevServer-->>BraintreeTestCheckoutController: Return clientToken
BraintreeTestCheckoutController-->>User: Serve checkout HTML with clientToken
User->>BraintreeTestCheckoutController: POST /checkout (payment payload)
BraintreeTestCheckoutController->>ShopGraphQLClient: Mutate addPaymentToOrder
ShopGraphQLClient->>BraintreePlugin: processPayment (currency, merchantAccountIds)
BraintreePlugin->>BraintreePlugin: lookupMerchantAccountIdByCurrency
BraintreePlugin-->>ShopGraphQLClient: Return payment result
ShopGraphQLClient-->>BraintreeTestCheckoutController: Return payment result
BraintreeTestCheckoutController-->>User: Return payment result
sequenceDiagram
participant Admin
participant BraintreeDevServer
participant AdminGraphQLClient
participant BraintreePlugin
Admin->>BraintreeDevServer: Start dev server
BraintreeDevServer->>AdminGraphQLClient: Mutate createPaymentMethod (with merchantAccountIds)
AdminGraphQLClient->>BraintreePlugin: Register payment method
BraintreePlugin-->>AdminGraphQLClient: Acknowledge registration
AdminGraphQLClient-->>BraintreeDevServer: Payment method created
BraintreeDevServer-->>Admin: Dev server ready, checkout URL logged
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
…intree-plugin-multi-currency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (7)
packages/payments-plugin/e2e/fixtures/stripe-checkout-test.plugin.ts (1)
22-22: HTML structure is still malformedPlacing
<html>after the<head>tag violates the DOM hierarchy. For a minimal fix:-<head> +<html> +<head> … -</head> - -<html> +</head> +<body> … +</body> </html>A correct structure avoids unpredictable rendering in some browsers.
packages/payments-plugin/README.md (1)
46-46: Format the URL as a proper markdown link.For consistency with other documentation, wrap the bare URL in markdown link syntax.
-1. Get the test keys from your Braintree dashboard, under menu settings, API section: https://sandbox.braintreegateway.com +1. Get the test keys from your [Braintree dashboard](https://sandbox.braintreegateway.com), under menu settings, API section.packages/payments-plugin/src/braintree/braintree-common.ts (1)
81-81: Fix the typo in the JSDoc comment.There's a duplicated 'm' in "mmerchantAccountId" in the description.
- * Looks up a single mmerchantAccountId from `merchantAccountIds` passed through the plugin options. + * Looks up a single merchantAccountId from `merchantAccountIds` passed through the plugin options.packages/payments-plugin/e2e/braintree-dev-server.ts (1)
70-73: Consider adding environment variable validation.The merchant account IDs are configured from environment variables without validation. If these variables are undefined, they could cause issues during testing.
merchantAccountIds: { - USD: process.env.BRAINTREE_MERCHANT_ACCOUNT_ID_USD, - EUR: process.env.BRAINTREE_MERCHANT_ACCOUNT_ID_EUR, + ...(process.env.BRAINTREE_MERCHANT_ACCOUNT_ID_USD && { USD: process.env.BRAINTREE_MERCHANT_ACCOUNT_ID_USD }), + ...(process.env.BRAINTREE_MERCHANT_ACCOUNT_ID_EUR && { EUR: process.env.BRAINTREE_MERCHANT_ACCOUNT_ID_EUR }), },packages/payments-plugin/e2e/fixtures/braintree-checkout-test.plugin.ts (3)
38-42: Consider making PayPal configuration dynamic.The PayPal flow configuration uses hard-coded values for amount and currency. Consider making these configurable or dynamic based on the actual order.
paypal: { flow: 'checkout', - amount: 100, - currency: 'GBP', + amount: 10.00, // Consider making this dynamic based on order total + currency: 'USD', // Consider making this match the order currency },
110-110: Fix the incorrect comment.The comment mentions "Stripe intent checkout page" but this is a Braintree plugin.
/** - * Test plugin for serving the Stripe intent checkout page + * Test plugin for serving the Braintree drop-in checkout page */
69-85: Add error handling to the payment submission function.The
sendPayloadToServerfunction could benefit from more robust error handling.async function sendPayloadToServer(payload) { + try { const response = await fetch('checkout', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Credentials': 'include', }, body: JSON.stringify(payload) }) - .then(res => res.json()) - .catch(err => console.error(err)) + .then(res => { + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + return res.json(); + }); document.querySelector('#result').innerHTML = JSON.stringify(response) console.log(response) + } catch (err) { + console.error('Payment submission failed:', err); + document.querySelector('#result').innerHTML = `Error: ${err.message}`; + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
packages/payments-plugin/README.md(1 hunks)packages/payments-plugin/e2e/braintree-dev-server.ts(1 hunks)packages/payments-plugin/e2e/fixtures/braintree-checkout-test.plugin.ts(1 hunks)packages/payments-plugin/e2e/fixtures/stripe-checkout-test.plugin.ts(2 hunks)packages/payments-plugin/e2e/payment-helpers.ts(1 hunks)packages/payments-plugin/e2e/stripe-dev-server.ts(1 hunks)packages/payments-plugin/package.json(2 hunks)packages/payments-plugin/src/braintree/braintree-common.ts(2 hunks)packages/payments-plugin/src/braintree/braintree.handler.ts(2 hunks)packages/payments-plugin/src/braintree/braintree.plugin.ts(1 hunks)packages/payments-plugin/src/braintree/braintree.resolver.ts(3 hunks)packages/payments-plugin/src/braintree/types.ts(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
packages/payments-plugin/e2e/stripe-dev-server.ts (1)
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: In packages/dashboard, when performing mutations with useMutation, do not pass variables at the point of declaration; instead, pass them when calling the mutate function. Type information should flow from the graphql function, so explicit typings or generics are not needed.
🧬 Code Graph Analysis (4)
packages/payments-plugin/src/braintree/braintree.handler.ts (1)
packages/payments-plugin/src/braintree/braintree-common.ts (1)
lookupMerchantAccountIdByCurrency(86-95)
packages/payments-plugin/src/braintree/types.ts (2)
packages/payments-plugin/src/braintree/braintree.handler.ts (1)
braintreePaymentMethodHandler(25-87)packages/core/src/index.ts (1)
CurrencyCode(23-23)
packages/payments-plugin/src/braintree/braintree-common.ts (2)
packages/payments-plugin/src/braintree/types.ts (1)
BraintreeMerchantAccountIds(9-9)packages/core/src/index.ts (1)
CurrencyCode(23-23)
packages/payments-plugin/src/braintree/braintree.resolver.ts (1)
packages/payments-plugin/src/braintree/braintree-common.ts (2)
getGateway(6-13)lookupMerchantAccountIdByCurrency(86-95)
🪛 LanguageTool
packages/payments-plugin/README.md
[uncategorized] ~61-~61: Possible missing comma found.
Context: ...er:braintree3. Watch the logs for the link or go tohttp://localhost:3050/checkou...
(AI_HYDRA_LEO_MISSING_COMMA)
🪛 markdownlint-cli2 (0.17.2)
packages/payments-plugin/README.md
46-46: Bare URL used
null
(MD034, no-bare-urls)
⏰ Context from checks skipped due to timeout of 90000ms (19)
- GitHub Check: e2e tests (22.x, sqljs)
- GitHub Check: e2e tests (22.x, mariadb)
- GitHub Check: e2e tests (22.x, postgres)
- GitHub Check: e2e tests (20.x, mysql)
- GitHub Check: e2e tests (20.x, postgres)
- GitHub Check: e2e tests (22.x, mysql)
- GitHub Check: e2e tests (20.x, mariadb)
- GitHub Check: e2e tests (20.x, sqljs)
- GitHub Check: codegen / codegen
- GitHub Check: build (22.x)
- GitHub Check: build (20.x)
- GitHub Check: unit tests (22.x)
- GitHub Check: unit tests (20.x)
- GitHub Check: publish_install (macos-latest, 20.x)
- GitHub Check: publish_install (macos-latest, 22.x)
- GitHub Check: publish_install (ubuntu-latest, 20.x)
- GitHub Check: publish_install (windows-latest, 20.x)
- GitHub Check: publish_install (ubuntu-latest, 22.x)
- GitHub Check: publish_install (windows-latest, 22.x)
🔇 Additional comments (18)
packages/payments-plugin/e2e/stripe-dev-server.ts (1)
29-29: Import-path adjustment looks correctThe new relative path resolves to
e2e/fixtures/stripe-checkout-test.plugin.ts, matching the revised folder structure. No further action required.packages/payments-plugin/e2e/payment-helpers.ts (1)
232-237: LGTM! GraphQL query follows established patterns.The new
GENERATE_BRAINTREE_CLIENT_TOKENquery is well-structured and consistent with the existing GraphQL queries in the file. It correctly supports the new Braintree development server infrastructure.packages/payments-plugin/package.json (1)
20-20: LGTM! Development script follows established patterns.The new
dev-server:braintreescript is consistent with the existing development server scripts for other payment providers (Mollie and Stripe), enabling streamlined local development and testing.packages/payments-plugin/src/braintree/types.ts (2)
1-1: LGTM! Import addition is appropriate.The
CurrencyCodeimport from@vendure/coreis correctly added to support the new multi-currency merchant account functionality.
9-9: LGTM! Type definition is well-structured.The
BraintreeMerchantAccountIdstype correctly usesPartial<Record<CurrencyCode, string>>to allow optional mapping of currency codes to merchant account IDs, providing flexibility for multi-currency configurations.packages/payments-plugin/src/braintree/braintree.plugin.ts (1)
241-241: LGTM! Minor formatting improvement.The added blank line before the
@VendurePlugindecorator improves code readability without affecting functionality.packages/payments-plugin/src/braintree/braintree.handler.ts (3)
14-14: LGTM! Import addition supports multi-currency functionality.The
lookupMerchantAccountIdByCurrencyimport is correctly added to support the new multi-currency merchant account functionality.
98-102: LGTM! Merchant account ID lookup logic is well-implemented.The merchant account ID lookup correctly uses the order's currency code to determine the appropriate merchant account. The implementation gracefully handles cases where no merchant account IDs are configured by returning
undefined.
108-108: LGTM! Transaction integration is correct.The
merchantAccountIdis properly passed to the Braintreetransaction.sale()method, enabling multi-currency merchant account support. The Braintree SDK will handleundefinedvalues gracefully by using the default merchant account.packages/payments-plugin/README.md (1)
41-62: Excellent documentation for local development setup.The Braintree local development section is well-structured and provides clear, step-by-step instructions. The inclusion of optional multi-currency configuration is particularly helpful.
packages/payments-plugin/src/braintree/braintree.resolver.ts (4)
16-16: Good addition of the utility function import.The import correctly includes the new
lookupMerchantAccountIdByCurrencyfunction needed for multi-currency support.
48-48: Excellent defensive programming with optional chaining.The addition of optional chaining (
?.) for accessingcustomFieldsprevents potential runtime errors ifcustomFieldsis undefined.
54-57: Proper integration of merchant account ID lookup.The merchant account ID is correctly determined using the utility function with the plugin options and order currency. This enables currency-specific merchant accounts for Braintree transactions.
75-78: Consistent implementation in fallback scenario.The merchant account ID lookup is correctly applied in the fallback case as well, ensuring consistency when the customer ID is invalid and needs to be reset.
packages/payments-plugin/src/braintree/braintree-common.ts (2)
86-95: Well-implemented utility function with proper error handling.The function correctly handles edge cases by returning
undefinedwhen inputs are missing, and provides a clean lookup mechanism for merchant account IDs by currency code. The implementation is simple and effective.
79-85: Excellent documentation with helpful context.The JSDoc provides clear usage examples and references the relevant Braintree documentation for setting up merchant account IDs. This will be very helpful for developers implementing multi-currency support.
packages/payments-plugin/e2e/braintree-dev-server.ts (1)
50-132: Excellent development server setup with comprehensive test environment.The dev server provides a complete testing environment with proper initialization, order preparation, and client token generation. The integration with the test plugin and exposure of necessary variables for external use is well thought out.
packages/payments-plugin/e2e/fixtures/braintree-checkout-test.plugin.ts (1)
17-107: Well-implemented test controller with functional Braintree integration.The controller provides a comprehensive testing interface with proper Braintree drop-in UI integration, event handling, and payment processing. The HTML template includes all necessary JavaScript for a functional checkout experience.
| @@ -3,7 +3,7 @@ import { Controller, Res, Get } from '@nestjs/common'; | |||
| import { PluginCommonModule, VendurePlugin } from '@vendure/core'; | |||
| import { Response } from 'express'; | |||
|
|
|||
| import { clientSecret } from './stripe-dev-server'; | |||
| import { clientSecret } from '../stripe-dev-server'; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Circular-dependency causes clientSecret to stay undefined
Because the plugin is imported by stripe-dev-server, this destructuring import happens while clientSecret is still undefined.
With CommonJS transpilation, the value is copied, not live-bound, so the HTML will embed “undefined” instead of the real secret.
-import { clientSecret } from '../stripe-dev-server';
+// Keep a live reference to the export to avoid stale value
+import * as StripeDevServer from '../stripe-dev-server';Then replace the template interpolation later in the file:
- clientSecret: '${clientSecret}',
+ clientSecret: '${StripeDevServer.clientSecret}',This keeps a single object reference and avoids the stale-value bug.
🤖 Prompt for AI Agents
In packages/payments-plugin/e2e/fixtures/stripe-checkout-test.plugin.ts at line
6, the import of clientSecret causes a circular dependency resulting in
clientSecret being undefined due to CommonJS copying the value instead of
live-binding. To fix this, import the entire module as an object instead of
destructuring clientSecret directly. Then, update the code to access
clientSecret as a property of that imported object, ensuring a live reference
and preventing the stale-value issue.
| merchantAccountIds?: BraintreeMerchantAccountIds; | ||
| extractMetadata?: (transaction: Transaction) => PaymentMetadata; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix documentation comment placement.
The documentation comment starting at line 100 appears to be documenting the extractMetadata property, but it's positioned above the merchantAccountIds property. This creates confusion about which property is being documented.
Apply this diff to fix the documentation:
+ /**
+ * @description
+ * Optional mapping of currency codes to Braintree merchant account IDs.
+ * This allows transactions to be processed using the appropriate merchant account
+ * based on the order's currency.
+ *
+ * @example
+ * ```ts
+ * merchantAccountIds: {
+ * USD: 'my_usd_merchant_account',
+ * EUR: 'my_eur_merchant_account',
+ * GBP: 'my_gbp_merchant_account'
+ * }
+ * ```
+ */
merchantAccountIds?: BraintreeMerchantAccountIds;
+ /**
+ * @description
+ * Allows you to configure exactly what information from the Braintree
+ * [Transaction object](https://developer.paypal.com/braintree/docs/reference/response/transaction#result-object) (which is returned by the
+ * `transaction.sale()` method of the SDK) should be persisted to the resulting Payment entity metadata.
+ *
+ * By default, the built-in extraction function will return a metadata object that looks like this:
+ *
+ * @example
+ * ```ts
+ * const metadata = {
+ * "status": "settling",
+ * "currencyIsoCode": "GBP",
+ * "merchantAccountId": "my_account_id",
+ * "cvvCheck": "Not Applicable",
+ * "avsPostCodeCheck": "Not Applicable",
+ * "avsStreetAddressCheck": "Not Applicable",
+ * "processorAuthorizationCode": null,
+ * "processorResponseText": "Approved",
+ * // for Paypal payments
+ * "paymentMethod": "paypal_account",
+ * "paypalData": {
+ * "payerEmail": "[email protected]",
+ * "paymentId": "PAYID-MLCXYNI74301746XK8807043",
+ * "authorizationId": "3BU93594D85624939",
+ * "payerStatus": "VERIFIED",
+ * "sellerProtectionStatus": "ELIGIBLE",
+ * "transactionFeeAmount": "0.54"
+ * },
+ * // for credit card payments
+ * "paymentMethod": "credit_card",
+ * "cardData": {
+ * "cardType": "MasterCard",
+ * "last4": "5454",
+ * "expirationDate": "02/2023"
+ * }
+ * // publicly-available metadata that will be
+ * // readable from the Shop API
+ * "public": {
+ * "cardData": {
+ * "cardType": "MasterCard",
+ * "last4": "5454",
+ * "expirationDate": "02/2023"
+ * },
+ * "paypalData": {
+ * "authorizationId": "3BU93594D85624939",
+ * }
+ * }
+ * }
+ * ```
+ *
+ * @since 1.7.0
+ */
- merchantAccountIds?: BraintreeMerchantAccountIds;
extractMetadata?: (transaction: Transaction) => PaymentMetadata;🤖 Prompt for AI Agents
In packages/payments-plugin/src/braintree/types.ts around lines 100 to 102, the
documentation comment is incorrectly placed above the merchantAccountIds
property but describes the extractMetadata property. Move the existing comment
block so that it directly precedes the extractMetadata property, and add a
proper documentation comment for merchantAccountIds above it as shown in the
suggested diff. This will clarify which property each comment documents and
improve code readability.
| { name: 'privateKey', value: process.env.BRAINTREE_PRIVATE_KEY! }, | ||
| { name: 'publicKey', value: process.env.BRAINTREE_PUBLIC_KEY! }, | ||
| { name: 'merchantId', value: process.env.BRAINTREE_MERCHANT_ID! }, | ||
| ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add validation for required environment variables.
The required Braintree credentials are used without validation. Consider adding checks to ensure they're properly configured.
arguments: [
- { name: 'privateKey', value: process.env.BRAINTREE_PRIVATE_KEY! },
- { name: 'publicKey', value: process.env.BRAINTREE_PUBLIC_KEY! },
- { name: 'merchantId', value: process.env.BRAINTREE_MERCHANT_ID! },
+ { name: 'privateKey', value: process.env.BRAINTREE_PRIVATE_KEY || (() => { throw new Error('BRAINTREE_PRIVATE_KEY is required'); })() },
+ { name: 'publicKey', value: process.env.BRAINTREE_PUBLIC_KEY || (() => { throw new Error('BRAINTREE_PUBLIC_KEY is required'); })() },
+ { name: 'merchantId', value: process.env.BRAINTREE_MERCHANT_ID || (() => { throw new Error('BRAINTREE_MERCHANT_ID is required'); })() },
],🤖 Prompt for AI Agents
In packages/payments-plugin/e2e/braintree-dev-server.ts around lines 104 to 107,
the Braintree environment variables are used without validation. Add checks
before this code to verify that process.env.BRAINTREE_PRIVATE_KEY,
process.env.BRAINTREE_PUBLIC_KEY, and process.env.BRAINTREE_MERCHANT_ID are
defined and not empty. If any are missing, throw an error or log a clear message
to prevent proceeding with invalid configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (23)
docs/docs/reference/typescript-api/services/product-option-group-service.md (1)
22-23: Document the semantics of the newly-addedincludeSoftDeletedflagThe generated signature now exposes a
findOneOptions?: { includeSoftDeleted: boolean }parameter, but the surrounding documentation does not describe what happens when the flag is set (e.g. whether it defaults tofalse, how it behaves with hard-deleted entities, performance impact, etc.).
Please add a short JSDoc comment on thefindOnemethod in the source (product-option-group.service.ts). The docs generator will then surface that explanation here.docs/docs/reference/dashboard/components/detail-page.md (2)
41-49:entityNamedescription may under-specify edge-casesThe docs state that the name “will be inferred from the query document” when omitted.
In practice, inference fails when the query:
- includes an alias (
order: orderByCode(...))- selects multiple root fields (
order,customer, …)- uses fragments with renamed types
A terse hint such as “Only omit when the query root field unambiguously matches the entity name” prevents surprises.
-If not provided, it will be inferred from the query document. +If omitted, the name is inferred from the root field of the query **only when that field uniquely and unambiguously matches the entity type**.
54-59: Mark optional prop consistentlyThe property table lists
entityNamewithout the trailing “?” that denotes optionality, whereas the signature above correctly showsentityName?: string. Add the “?” for consistency.-### entityName +### entityName?docs/docs/reference/core-plugins/graphiql-plugin/index.md (3)
24-25: Confirm the exported symbol’s casingThe example now imports
GraphiqlPlugin(lower-case “q”) whereas earlier docs usedGraphiQLPlugin.
If the public export in@vendure/graphiql-pluginis stillGraphiQLPlugin, this sample will not compile on case-sensitive filesystems.-import { GraphiqlPlugin } from '@vendure/graphiql-plugin'; +import { GraphiQLPlugin } from '@vendure/graphiql-plugin';Please verify the actual export name and keep the docs consistent.
36-46: Example contradicts the heading “Custom API paths”The section promises instructions on overriding the Admin/Shop API paths, yet the snippet only sets a custom
route.
Consider extending the snippet to demonstrate the expected options (e.g.adminApiPath,shopApiPath) or clarify that the plugin now autodetects these and that overriding is no longer needed.GraphiQLPlugin.init({ route: 'my-custom-route', // defaults to `graphiql` + // adminApiPath: 'my-admin-api', + // shopApiPath: 'my-shop-api', });
52-55: Minor punctuation tweak for readabilityA comma after “applications” improves flow.
-`?embeddedMode=true` - This renders the editor in embedded mode, which hides the header and - the API switcher. This is useful for embedding GraphiQL in other applications such as documentation. +`?embeddedMode=true` - This renders the editor in embedded mode, which hides the header and + the API switcher. This is useful for embedding GraphiQL in other applications, such as documentation.docs/docs/guides/getting-started/installation/index.md (4)
10-10: Tighten wording around Node.js version supportThe sentence is grammatically correct but slightly verbose. Replacing the second clause with a shorter parenthetical improves readability.
-* [Node.js](https://nodejs.org/en/) **v20** or above, with support for **even-numbered Node.js versions**. (Odd-numbered versions should still work but are not officially supported.) +* [Node.js](https://nodejs.org/en/) **v20** or above, preferably an **even-numbered version**. (Odd-numbered releases usually work, but they are not officially supported.)
15-16: Reduce repetition in the Docker Desktop note“Docker Desktop installed” appears twice in one sentence. Removing the duplication and tightening the wording keeps the bullet concise.
-* [Docker Desktop](https://www.docker.com/products/docker-desktop/): If you want to use the quick start with Postgres, you must have Docker Desktop installed. If you do not have Docker Desktop installed, then SQLite will be used for your database. +* [Docker Desktop](https://www.docker.com/products/docker-desktop/): Required only when using the quick-start option with Postgres. If Docker Desktop is unavailable, the installer falls back to SQLite.
42-42: Drop the unnecessary hyphen in “fully functional”“Fully” is an adverb ending in “-ly”, so the compound modifier doesn’t need a hyphen.
-And that's it! After a minute or two, you'll have a **fully-functional Vendure server** installed locally. +And that's it! After a minute or two, you'll have a **fully functional Vendure server** installed locally.
65-73: Use “who” for the database user and standardise list punctuationMinor grammar tweak plus terminal punctuation to make each sub-bullet consistent.
-3. **Have database credentials**: You need the username and password for a database user that has full permissions (CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT) on the database you created. +3. **Have database credentials**: You need the username and password for a database user who has full permissions (CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT) on the database you created.docs/docs/reference/core-plugins/job-queue-plugin/pub-sub-job-queue-strategy.md (1)
44-64: Remove trailing blanks insidespansmarkdownlint (MD038) flags the four
<MemberInfo … type={\… `}` lines because there’s a space inside the back-ticked string.
Trimming those spaces avoids the lint warning without altering the generated output:-<MemberInfo kind="method" type={`(injector: Injector) => `} /> +<MemberInfo kind="method" type={`(injector: Injector) =>`} />Apply the same change to the other 3 occurrences (lines 49, 54, 59/64).
docs/docs/guides/getting-started/try-the-api/index.mdx (2)
59-71: Consider giving each example a unique operation name.All three snippets use
query GetProducts, which is fine in isolation, but when a reader pastes multiple snippets into the same GraphiQL tab it will trigger “duplicate operation name” errors. Using something likeGetProductsBasic,GetProductsDetails,GetProductsFilteredwould avoid that friction.Also applies to: 88-96
208-226://is not a valid GraphQL comment delimiter – switch to#If a reader copies the snippet directly into GraphiQL, the lines starting with
// highlight-…will break parsing because GraphQL only recognises#for single-line comments.- // highlight-next-line + # highlight-next-line ... - // highlight-start + # highlight-start ... - // highlight-end + # highlight-endThe MDX highlighting plugin should still work with
#, and the snippet becomes copy-paste-safe.CHANGELOG.md (1)
3-3: Fix heading level increments to follow markdown conventions.The changelog violates markdown heading conventions by jumping from h2 (
##) directly to h4 (####). Heading levels should only increment by one level at a time.Change the
#### Fixesand#### Featuresheadings to### Fixesand### Featuresthroughout the changelog:-#### Fixes +### Fixes -#### Features +### FeaturesAlso applies to: 35-35, 59-59, 84-84
.github/workflows/build_and_test_pr.yml (1)
66-66: Same version-pin caveat applies hereSee the comment on the
masterworkflow – the rationale and risk profile are identical.README.md (1)
150-150: Consider improving the preposition usage.The static analysis tool suggests using "independent of" instead of "independent from" for better grammar.
-If you are making changes to the Admin UI, you need to start the Admin UI independent from the dev-server: +If you are making changes to the Admin UI, you need to start the Admin UI independent of the dev-server:docs/docs/guides/extending-the-dashboard/action-bar-items/index.md (2)
37-42: Minor punctuation glitch in bullet list.
LanguageTool flags “Loose punctuation mark”.
Trim the space before the dash to avoid rendering an extra paragraph.-The `context` prop provides access to: - -- **`entity`**: … +- The `context` prop provides access to: + - **`entity`**: …
58-70: Clean up temporary anchor element in export example.The snippet creates an
<a>element but never removes it, which can leak DOM
nodes in copy-pasted code.- const a = document.createElement('a'); - a.href = url; - a.download = `product-${product.id}.json`; - a.click(); - URL.revokeObjectURL(url); + const a = document.createElement('a'); + a.href = url; + a.download = `product-${product.id}.json`; + a.click(); + a.remove(); + URL.revokeObjectURL(url);docs/docs/guides/extending-the-dashboard/page-blocks/index.md (1)
36-40: Add null-safety to example to avoid runtime errors in copies.
context.entitycan beundefineduntil data loads.
A guarded render avoids “Cannot read property ‘name’ of undefined”.- return <div className="text-sm">Articles related to {context.entity.name}</div>; + return ( + <div className="text-sm"> + {context.entity ? `Articles related to ${context.entity.name}` : 'Loading…'} + </div> + );docs/docs/guides/extending-the-dashboard/navigation/index.md (1)
128-146: Add missing icon imports in the code sample
BarChartIconandPlugIconare referenced but never imported in this snippet, which will throw an undefined identifier error if copied verbatim.+import { defineDashboardExtension } from '@vendure/dashboard'; +import { BarChartIcon, PlugIcon } from 'lucide-react'; export default defineDashboardExtension({ navSections: [docs/docs/guides/extending-the-dashboard/cms-tutorial/index.md (2)
28-32: Typo: replace “you” with “your”-You now have you `CmsPlugin` created with a new `Article` entity. +You now have your `CmsPlugin` created with a new `Article` entity.
8-12: Minor wording – drop “in order to”The phrase “in order to” is verbose. Prefer a direct “to” for tighter prose.
-order to demonstrate how to extend the dashboard. +to demonstrate how to extend the dashboard.docs/docs/guides/extending-the-dashboard/custom-form-components/index.md (1)
24-65: Consider wrapping field controls withFormFieldWrapperInternally,
FormFieldWrapperstandardises labels, error display, and disabled states. Using it inside custom components aligns with established dashboard patterns and reduces boilerplate.Example refactor for
ColorPickerComponent(simplified):-<div className="space-y-2"> - … - {fieldState.error && <p className="text-sm text-destructive">{fieldState.error.message}</p>} -</div> +<FormFieldWrapper control={field.control} name={field.name} render={() => ( + <> + … /* existing picker controls */ + </> +)} />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between 8c68d8f6dde511f5e3f3eb8feaabe3b3c0bc05ce and f3b1fe63598796221ea54b8a88a161eb0ff321e3.
⛔ Files ignored due to path filters (1)
package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (63)
.cursor/rules/dashboard.mdc (1 hunks)
.github/workflows/build_and_test_branches.yml (1 hunks)
.github/workflows/build_and_test_master.yml (2 hunks)
.github/workflows/build_and_test_pr.yml (2 hunks)
.github/workflows/publish_master_to_npm.yml (1 hunks)
.github/workflows/stale_bot.yml (1 hunks)
.gitignore (0 hunks)
CHANGELOG.md (5 hunks)
CONTRIBUTING.md (3 hunks)
README.md (5 hunks)
docker-compose.yml (0 hunks)
docs/docs/guides/developer-guide/custom-strategies-in-plugins/index.mdx (1 hunks)
docs/docs/guides/developer-guide/scheduled-tasks/index.md (1 hunks)
docs/docs/guides/extending-the-admin-ui/getting-started/index.md (17 hunks)
docs/docs/guides/extending-the-dashboard/action-bar-items/index.md (1 hunks)
docs/docs/guides/extending-the-dashboard/cms-tutorial/index.md (1 hunks)
docs/docs/guides/extending-the-dashboard/custom-form-components/index.md (1 hunks)
docs/docs/guides/extending-the-dashboard/getting-started/index.md (5 hunks)
docs/docs/guides/extending-the-dashboard/navigation/index.md (1 hunks)
docs/docs/guides/extending-the-dashboard/page-blocks/index.md (1 hunks)
docs/docs/guides/extending-the-dashboard/tech-stack/index.md (1 hunks)
docs/docs/guides/getting-started/graphql-intro/index.mdx (2 hunks)
docs/docs/guides/getting-started/installation/index.md (2 hunks)
docs/docs/guides/getting-started/try-the-api/index.mdx (7 hunks)
docs/docs/reference/core-plugins/graphiql-plugin/index.md (2 hunks)
docs/docs/reference/core-plugins/job-queue-plugin/bull-mqjob-queue-plugin.md (2 hunks)
docs/docs/reference/core-plugins/job-queue-plugin/bull-mqjob-queue-strategy.md (1 hunks)
docs/docs/reference/core-plugins/job-queue-plugin/pub-sub-job-queue-strategy.md (1 hunks)
docs/docs/reference/core-plugins/job-queue-plugin/pub-sub-plugin.md (1 hunks)
docs/docs/reference/dashboard/components/detail-page.md (3 hunks)
docs/docs/reference/dashboard/components/list-page.md (5 hunks)
docs/docs/reference/dashboard/components/page-action-bar.md (3 hunks)
docs/docs/reference/dashboard/components/page-block.md (4 hunks)
docs/docs/reference/dashboard/components/page-layout.md (2 hunks)
docs/docs/reference/dashboard/components/page-title.md (1 hunks)
docs/docs/reference/dashboard/extensions/dashboard-action-bar-item.md (1 hunks)
docs/docs/reference/dashboard/extensions/dashboard-custom-form-component.md (1 hunks)
docs/docs/reference/dashboard/extensions/dashboard-extension.md (4 hunks)
docs/docs/reference/dashboard/extensions/dashboard-page-block-definition.md (1 hunks)
docs/docs/reference/dashboard/extensions/define-dashboard-extension.md (1 hunks)
docs/docs/reference/dashboard/extensions/page-block-location.md (1 hunks)
docs/docs/reference/dashboard/hooks/use-auth.md (1 hunks)
docs/docs/reference/dashboard/hooks/use-detail-page.md (5 hunks)
docs/docs/reference/dashboard/hooks/use-permissions.md (1 hunks)
docs/docs/reference/typescript-api/cache/redis-cache-plugin.md (1 hunks)
docs/docs/reference/typescript-api/cache/redis-cache-strategy.md (1 hunks)
docs/docs/reference/typescript-api/common/middleware.md (1 hunks)
docs/docs/reference/typescript-api/scheduled-tasks/clean-sessions-task.md (1 hunks)
docs/docs/reference/typescript-api/services/order-service.md (1 hunks)
docs/docs/reference/typescript-api/services/product-option-group-service.md (2 hunks)
docs/docs/reference/typescript-api/services/product-option-service.md (1 hunks)
docs/docs/reference/typescript-api/tax/address-based-tax-zone-strategy.md (1 hunks)
docs/docs/reference/typescript-api/telemetry/instrument.md (1 hunks)
docs/sidebars.js (3 hunks)
docs/src/components/Playground/index.tsx (1 hunks)
docs/src/pages/index.tsx (1 hunks)
lerna.json (1 hunks)
license/signatures/version1/cla.json (1 hunks)
packages/admin-ui-plugin/package.json (2 hunks)
packages/admin-ui/i18n-coverage.json (1 hunks)
packages/admin-ui/package.json (2 hunks)
packages/admin-ui/src/lib/catalog/src/components/bulk-add-facet-values-dialog/bulk-add-facet-values-dialog.component.ts (2 hunks)
packages/admin-ui/src/lib/core/src/common/version.ts (1 hunks)
💤 Files with no reviewable changes (2)
- docker-compose.yml
- .gitignore
✅ Files skipped from review due to trivial changes (35)
- docs/docs/reference/dashboard/extensions/page-block-location.md
- docs/docs/reference/core-plugins/job-queue-plugin/bull-mqjob-queue-strategy.md
- docs/docs/reference/typescript-api/tax/address-based-tax-zone-strategy.md
- docs/docs/reference/dashboard/components/page-layout.md
- license/signatures/version1/cla.json
- docs/docs/reference/typescript-api/cache/redis-cache-plugin.md
- packages/admin-ui-plugin/package.json
- packages/admin-ui/package.json
- docs/docs/reference/dashboard/extensions/define-dashboard-extension.md
- lerna.json
- docs/docs/reference/typescript-api/telemetry/instrument.md
- docs/docs/reference/dashboard/components/page-title.md
- docs/docs/reference/dashboard/extensions/dashboard-action-bar-item.md
- docs/docs/reference/dashboard/hooks/use-auth.md
- docs/docs/reference/typescript-api/services/product-option-service.md
- docs/docs/reference/dashboard/extensions/dashboard-page-block-definition.md
- docs/docs/reference/dashboard/hooks/use-permissions.md
- docs/src/pages/index.tsx
- docs/docs/reference/typescript-api/scheduled-tasks/clean-sessions-task.md
- .github/workflows/build_and_test_branches.yml
- packages/admin-ui/src/lib/core/src/common/version.ts
- docs/docs/reference/dashboard/components/page-block.md
- docs/docs/reference/typescript-api/cache/redis-cache-strategy.md
- docs/docs/reference/dashboard/components/page-action-bar.md
- docs/docs/guides/developer-guide/scheduled-tasks/index.md
- docs/docs/reference/dashboard/extensions/dashboard-custom-form-component.md
- docs/docs/reference/typescript-api/services/order-service.md
- docs/docs/guides/getting-started/graphql-intro/index.mdx
- packages/admin-ui/i18n-coverage.json
- docs/src/components/Playground/index.tsx
- docs/docs/reference/core-plugins/job-queue-plugin/pub-sub-plugin.md
- docs/docs/reference/dashboard/hooks/use-detail-page.md
- .cursor/rules/dashboard.mdc
- .github/workflows/stale_bot.yml
- docs/docs/reference/dashboard/components/list-page.md
🧰 Additional context used
🧠 Learnings (6)
docs/docs/guides/getting-started/try-the-api/index.mdx (3)
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: In packages/dashboard, when performing mutations with useMutation, do not pass variables at the point of declaration; instead, pass them when calling the mutate function. Type information should flow from the graphql function, so explicit typings or generics are not needed.
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: When using TanStack Query in packages/dashboard, always use the useQuery or useMutation hooks with the graphql and api utilities, following the provided pattern to ensure type safety and consistent API interaction.
Learnt from: dlhck
PR: vendure-ecommerce/vendure#3615
File: packages/dashboard/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx:161-214
Timestamp: 2025-06-25T11:20:48.133Z
Learning: Using `useMutation` with multiple concurrent `mutate` calls (e.g., in a `map` operation) causes race conditions and unpredictable behavior. This pattern has caused issues in the Vendure dashboard codebase. Instead, use `mutateAsync` with sequential processing (for loop with await) or proper chaining to ensure only one mutation runs at a time.
docs/docs/reference/dashboard/extensions/dashboard-extension.md (1)
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: For forms in packages/dashboard, prefer using the FormFieldWrapper component (a wrapper around Shadcn react-hook-form components) to make form controls more concise, instead of using raw Shadcn components directly.
docs/docs/reference/core-plugins/graphiql-plugin/index.md (1)
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: In packages/dashboard, when performing mutations with useMutation, do not pass variables at the point of declaration; instead, pass them when calling the mutate function. Type information should flow from the graphql function, so explicit typings or generics are not needed.
docs/docs/guides/extending-the-dashboard/getting-started/index.md (3)
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: All user-facing labels and messages in packages/dashboard should use localization via the Trans component or the useLingui hook, as shown in the provided example, to ensure proper internationalization.
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: For forms in packages/dashboard, prefer using the FormFieldWrapper component (a wrapper around Shadcn react-hook-form components) to make form controls more concise, instead of using raw Shadcn components directly.
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: When using TanStack Query in packages/dashboard, always use the useQuery or useMutation hooks with the graphql and api utilities, following the provided pattern to ensure type safety and consistent API interaction.
docs/docs/guides/extending-the-dashboard/custom-form-components/index.md (2)
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: For forms in packages/dashboard, prefer using the FormFieldWrapper component (a wrapper around Shadcn react-hook-form components) to make form controls more concise, instead of using raw Shadcn components directly.
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: All user-facing labels and messages in packages/dashboard should use localization via the Trans component or the useLingui hook, as shown in the provided example, to ensure proper internationalization.
docs/docs/guides/extending-the-dashboard/tech-stack/index.md (1)
Learnt from: CR
PR: vendure-ecommerce/vendure#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:16:30.177Z
Learning: When using TanStack Query in packages/dashboard, always use the useQuery or useMutation hooks with the graphql and api utilities, following the provided pattern to ensure type safety and consistent API interaction.
🧬 Code Graph Analysis (1)
docs/sidebars.js (2)
docs/src/theme/DocSidebarItem/Link/index.js (1)
icon (6-6)
docs/src/theme/DocSidebarItem/Category/index.js (1)
icon (6-6)
🪛 LanguageTool
CONTRIBUTING.md
[uncategorized] ~139-~139: Do not mix variants of the same word (‘synchronize’ and ‘synchronise’) within a single text.
Context: ...e three main ways to keep your fork synchronized: #### Option 1: Using GitHub's Web Int...
(EN_WORD_COHERENCY)
[uncategorized] ~272-~272: Possible missing comma found.
Context: ...merged. This is done via an automation bot which will prompt you to sign the CLA w...
(AI_HYDRA_LEO_MISSING_COMMA)
docs/docs/reference/core-plugins/graphiql-plugin/index.md
[uncategorized] ~54-~54: Possible missing comma found.
Context: ... useful for embedding GraphiQL in other applications such as documentation. In this mode,...
(AI_HYDRA_LEO_MISSING_COMMA)
docs/docs/guides/extending-the-dashboard/cms-tutorial/index.md
[style] ~10-~10: Consider a more concise word here.
Context: ...ent management system (CMS) for Vendure in order to demonstrate how to extend the dashboard...
(IN_ORDER_TO_PREMIUM)
[uncategorized] ~30-~30: “you” seems less likely than “your” (belonging to you).
Context: ...*[Finish] No, I'm done!** You now have you CmsPlugin created with a new `Article...
(AI_HYDRA_LEO_CP_YOU_YOUR)
[uncategorized] ~62-~62: Possible missing comma found.
Context: ...stomFields: ArticleCustomFields; } ``` Now let's create a new ArticleService to ...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~92-~92: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...t step is to create a migration for our newly-created entity: ```bash npx vendure migrate ``...
(HYPHENATED_LY_ADVERB_ADJECTIVE)
[uncategorized] ~153-~153: Possible missing comma found.
Context: ... a list page for our Article entity. First we'll create a new article-list.tsx f...
(AI_HYDRA_LEO_MISSING_COMMA)
[style] ~532-~532: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ts to structure the page into blocks. - Used custom form components (such as the `Ri...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
docs/docs/guides/extending-the-admin-ui/getting-started/index.md
[style] ~476-~476: ‘Prior to’ might be wordy. Consider a shorter alternative.
Context: ...ing correctly. ## Legacy API < v2.1.0 Prior to Vendure v2.1.0, the API for extending t...
(EN_WORDINESS_PREMIUM_PRIOR_TO)
docs/docs/guides/developer-guide/custom-strategies-in-plugins/index.mdx
[uncategorized] ~401-~401: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ... Always provide a default implementation so users can use your plugin out-of-the-bo...
(COMMA_COMPOUND_SENTENCE_2)
CHANGELOG.md
[uncategorized] ~203-~203: Possible missing comma found.
Context: ...At` column. This will only affect cache records so no prod data will be affected by i...
(AI_HYDRA_LEO_MISSING_COMMA)
README.md
[style] ~54-~54: The wording of this phrase can be improved.
Context: ...welcome%22). Thank you for considering making Vendure better! ## Development > [!IMPORTANT] > The ...
(MAKE_STYLE_BETTER)
[style] ~150-~150: Consider shortening or rephrasing this to strengthen your wording.
Context: ...ng Admin UI changes locally If you are making changes to the Admin UI, you need to start the Adm...
(MAKE_CHANGES)
[grammar] ~150-~150: The usual collocation for “independent” is “of”, not “from”. Did you mean “independent of”?
Context: ...dmin UI, you need to start the Admin UI independent from the dev-server: > [!NOTE] > You don't...
(INDEPENDENTLY_FROM_OF)
[misspelling] ~162-~162: Did you mean the verb “log in” instead of the noun ‘login’?
Context: ...-ui on "http://localhost:4200", you can login with the default credentials: Username...
(LOG_IN)
[uncategorized] ~167-~167: It appears that a hyphen is missing (if ‘auto’ is not used in the context of ‘cars’).
Context: ...dminPassword:superadmin` This will auto restart when you make changes to the Admin UI. ...
(AUTO_HYPHEN)
[style] ~167-~167: Consider shortening or rephrasing this to strengthen your wording.
Context: ...admin` This will auto restart when you make changes to the Admin UI. ### Testing your change...
(MAKE_CHANGES)
[uncategorized] ~211-~211: Possible missing comma found.
Context: ...ugging To debug the dev server with VS Code use the included [launch.json](/.vscode...
(AI_HYDRA_LEO_MISSING_COMMA)
[grammar] ~259-~259: Did you mean the noun “publishing”?
Context: ...it then invalidates the npm OTP and the publish will fail. So the solution is to publis...
(PREPOSITION_VERB)
docs/docs/guides/extending-the-dashboard/action-bar-items/index.md
[uncategorized] ~39-~39: Loose punctuation mark.
Context: ...prop provides access to: - entity: The current entity being viewed/edited ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~40-~40: Loose punctuation mark.
Context: ...., Product, Customer, etc.) - form: The React Hook Form instance for the cu...
(UNLIKELY_OPENING_PUNCTUATION)
docs/docs/guides/extending-the-dashboard/navigation/index.md
[uncategorized] ~97-~97: Loose punctuation mark.
Context: ...ies ### Required Properties - id: Unique identifier for the section - **`...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~102-~102: Loose punctuation mark.
Context: ...n ### Optional Properties - icon: Lucide React icon component to display ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~110-~110: Loose punctuation mark.
Context: ...# Required Properties - sectionId: ID of the section where this item shoul...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~116-~116: Loose punctuation mark.
Context: ...em ### Optional Properties - url: Custom URL if different from the route ...
(UNLIKELY_OPENING_PUNCTUATION)
[style] ~174-~174: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...rea, you might use order: 250. If you want to add a section before Settings in the bo...
(REP_WANT_TO_VB)
docs/docs/guides/extending-the-dashboard/page-blocks/index.md
[uncategorized] ~91-~91: Loose punctuation mark.
Context: ... be placed in two columns: - main: The main content area (wider column on ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~98-~98: Loose punctuation mark.
Context: ...prop provides access to: - entity: The current entity being viewed/edited ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~99-~99: Loose punctuation mark.
Context: ...., Product, Customer, etc.) - form: The React Hook Form instance for the cu...
(UNLIKELY_OPENING_PUNCTUATION)
docs/docs/guides/extending-the-dashboard/tech-stack/index.md
[style] ~11-~11: Try using a synonym here to strengthen your writing.
Context: ... The dashboard is built with React 19, giving you access to all the latest React features...
(GIVE_PROVIDE)
[uncategorized] ~11-~11: Possible missing comma found.
Context: ...ving you access to all the latest React features including: - React Compiler optimizati...
(AI_HYDRA_LEO_MISSING_COMMA)
[misspelling] ~66-~66: This word is normally spelled as one.
Context: ... ecosystem - Environment API for better multi-environment support ## UI Framework ### Tailwind ...
(EN_COMPOUNDS_MULTI_ENVIRONMENT)
docs/docs/guides/getting-started/installation/index.md
[uncategorized] ~11-~11: Possible missing comma found.
Context: ...(Odd-numbered versions should still work but are not officially supported.) ### Opt...
(AI_HYDRA_LEO_MISSING_COMMA)
[style] ~16-~16: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...ill be used for your database. * If you want to use an existing MySQL, MariaDB, or Post...
(REP_WANT_TO_VB)
[uncategorized] ~42-~42: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ... After a minute or two, you'll have a fully-functional Vendure server installed locally. On...
(HYPHENATED_LY_ADVERB_ADJECTIVE)
[style] ~71-~71: Consider using “who” when you are referring to a person instead of an object.
Context: ...ername and password for a database user that has full permissions (CREATE, ALTER, DR...
(THAT_WHO)
🪛 markdownlint-cli2 (0.17.2)
CONTRIBUTING.md
113-113: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
117-117: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
185-185: Fenced code blocks should have a language specified
null
(MD040, fenced-code-language)
216-216: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
224-224: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
246-246: Fenced code blocks should have a language specified
null
(MD040, fenced-code-language)
docs/docs/reference/dashboard/components/detail-page.md
37-37: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
CHANGELOG.md
3-3: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4
(MD001, heading-increment)
35-35: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4
(MD001, heading-increment)
59-59: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4
(MD001, heading-increment)
84-84: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4
(MD001, heading-increment)
README.md
157-157: Fenced code blocks should have a language specified
null
(MD040, fenced-code-language)
162-162: Bare URL used
null
(MD034, no-bare-urls)
193-193: Blank line inside blockquote
null
(MD028, no-blanks-blockquote)
docs/docs/reference/core-plugins/job-queue-plugin/pub-sub-job-queue-strategy.md
44-44: Spaces inside code span elements
null
(MD038, no-space-in-code)
49-49: Spaces inside code span elements
null
(MD038, no-space-in-code)
59-59: Spaces inside code span elements
null
(MD038, no-space-in-code)
64-64: Spaces inside code span elements
null
(MD038, no-space-in-code)
⏰ Context from checks skipped due to timeout of 90000ms (18)
- GitHub Check: e2e tests (20.x, mariadb)
- GitHub Check: e2e tests (22.x, postgres)
- GitHub Check: e2e tests (22.x, mysql)
- GitHub Check: e2e tests (22.x, sqljs)
- GitHub Check: e2e tests (22.x, mariadb)
- GitHub Check: e2e tests (20.x, postgres)
- GitHub Check: e2e tests (20.x, mysql)
- GitHub Check: e2e tests (20.x, sqljs)
- GitHub Check: unit tests (20.x)
- GitHub Check: unit tests (22.x)
- GitHub Check: build (20.x)
- GitHub Check: build (22.x)
- GitHub Check: publish_install (windows-latest, 22.x)
- GitHub Check: publish_install (ubuntu-latest, 22.x)
- GitHub Check: publish_install (windows-latest, 20.x)
- GitHub Check: publish_install (macos-latest, 22.x)
- GitHub Check: publish_install (ubuntu-latest, 20.x)
- GitHub Check: publish_install (macos-latest, 20.x)
🔇 Additional comments (20)
docs/docs/reference/dashboard/components/detail-page.md (1)
14-15: Verify sourceLine reference is still accurate
The GenerationInfo tag now points to line 124 in detail-page.tsx. Given the surrounding source code churn, please re-run the docs build after merging or double-check that line numbers still match the latest commit; otherwise the “view source” links in the docs will break.
docs/docs/guides/getting-started/try-the-api/index.mdx (1)
39-46: Good improvement – operation name added.
Adding the GetProducts operation name is a best-practice for readability & tooling support.
packages/admin-ui/src/lib/catalog/src/components/bulk-add-facet-values-dialog/bulk-add-facet-values-dialog.component.ts (3)
5-5: LGTM! Type correction improves semantic accuracy.
The change from FacetWithValuesFragment to FacetValueFragment is semantically correct since this component handles individual facet values rather than complete facets with their value collections.
Also applies to: 47-48, 54-54
45-45: Good formatting improvement.
Adding the trailing comma follows best practices and makes future diffs cleaner.
58-61: Constructor formatting improvement enhances readability.
The multi-line parameter formatting follows TypeScript conventions and improves maintainability.
.github/workflows/build_and_test_master.yml (1)
64-66: Pinning to 11.5 avoids the snapshot-isolation issue but may leave us on an old major release
Good call-out about 11.6.2+, but freezing the image at 11.5 places the CI on an EOL (or soon-to-be-EOL) minor.
Consider instead:
- Start the container with
11.6 (or later) and set
MARIADB_EXTRA_FLAGS: --innodb-snapshot-isolation=0
to retain the old behaviour; or
- At least add a follow-up ticket reminding us to bump once the test-suite is fixed.
This keeps security patches flowing while still unblocking the pipeline.
README.md (3)
46-55: Excellent addition to encourage community contributions.
The new Contributing section provides clear guidance and appropriately links to detailed contribution guidelines. This will help onboard new contributors effectively.
105-128: Great improvement to PostgreSQL setup instructions.
The addition of multiple configuration methods (.env file and CLI) with clear examples makes the database setup much more accessible for developers.
174-208: Excellent reorganization of the development workflow.
The clearer terminal setup instructions and step-by-step workflow summary will significantly improve the developer experience when testing changes locally.
CONTRIBUTING.md (4)
7-20: Excellent addition of Table of Contents.
The comprehensive Table of Contents makes this long document much more navigable and user-friendly for contributors.
111-231: Outstanding detailed contribution workflow guidance.
The step-by-step workflow with multiple options (GitHub CLI, web interface, git commands) significantly lowers the barrier to entry for new contributors. The inclusion of different synchronization methods accommodates various developer preferences and skill levels.
232-268: Valuable addition of documentation and help guidance.
The documentation section provides clear instructions for working with Docusaurus, and the help section appropriately directs contributors to community resources. The note about auto-generated reference docs is particularly helpful.
274-300: Excellent addition of issue triage guidelines for maintainers.
The structured approach with checklists and clear actions will help maintainers handle issues consistently and efficiently. This is valuable for project management.
docs/docs/guides/developer-guide/custom-strategies-in-plugins/index.mdx (1)
1-468: Outstanding comprehensive guide on custom strategies in plugins.
This is an exceptional addition to the developer documentation that:
- Provides a complete learning path from basic concepts to advanced usage
- Includes practical, working code examples throughout
- Covers essential aspects like dependency injection and lifecycle management
- Addresses both plugin author and user perspectives
- Follows Vendure's established patterns and conventions
- Includes valuable best practices and documentation guidelines
The guide will significantly help developers create extensible and maintainable plugins. The progression from simple examples to complex scenarios with multiple strategies is particularly well done.
docs/sidebars.js (2)
103-103: Appropriate placement of custom strategies guide.
Adding the custom strategies guide to the Advanced Topics section is well-placed, as it covers advanced plugin development concepts.
136-186: Excellent reorganization of Admin UI documentation.
The clear separation between "React Admin Dashboard" and "Angular Admin UI" categories with appropriate icons will help users navigate to the correct documentation for their use case. This reorganization aligns well with the project's strategic direction toward the React-based dashboard.
docs/docs/reference/dashboard/extensions/dashboard-extension.md (1)
23-23: Appropriate extensions to DashboardExtension interface.
The addition of navSections and customFormComponents properties enhances the dashboard extension API by enabling:
- Custom navigation section definitions for sidebar customization
- Custom form component registration for enhanced form handling
These additions align well with the broader dashboard extension capabilities being introduced and provide valuable customization options for developers.
Also applies to: 28-28, 39-43, 65-69
docs/docs/guides/extending-the-dashboard/getting-started/index.md (2)
9-10: Clear & helpful beta warning – thumbs-up.
No issues spotted; the timeline information is useful to readers.
127-135: Double-check new “What’s Next” links render correctly in Docusaurus.
Using absolute /guides/... URLs bypasses the site base-url; if the docs site is
served from a sub-path (e.g. /docs), links will 404.
Consider:
- - [CMS Tutorial](/guides/extending-the-dashboard/cms-tutorial/)
+ - [CMS Tutorial](../cms-tutorial/)
Same for the other items.
docs/docs/guides/extending-the-admin-ui/getting-started/index.md (1)
8-14: Deprecation notice looks good, but validate the cross-link.
Ensure /guides/extending-the-dashboard/getting-started/ exists in the built
site, otherwise readers will hit a 404.
| middleware: [{ | ||
| handler: json({ limit: '10mb' }), | ||
| route: '*', | ||
| route: '*splat', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'*splat' does not behave as a catch-all route – likely a typo
In Express, the pattern '*splat' matches any path that ends with the literal text splat, not every route.
If the intention is to apply the JSON body-parser to all routes (as the original example with '*' did), revert the change:
- route: '*splat',
+ route: '*',Otherwise, clarify in the docs why only routes terminating with “splat” should be affected to avoid misleading users.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| route: '*splat', | |
| route: '*', |
🤖 Prompt for AI Agents
In docs/docs/reference/typescript-api/common/middleware.md at line 36, the route
pattern '*splat' is incorrectly used as a catch-all route but it only matches
paths ending with the literal 'splat'. To fix this, replace '*splat' with '*' to
correctly apply the middleware to all routes, or update the documentation to
clearly explain why only routes ending with 'splat' are targeted if that is the
intended behavior.
| Note: To use this plugin, you need to manually install the `bullmq` package: | ||
|
|
||
| or | ||
|
|
||
| `npm install @vendure/job-queue-plugin bullmq` | ||
| ```shell | ||
| npm install bullmq@^5.4.2 | ||
| ``` | ||
|
|
||
| **Note:** The v1.x version of this plugin is designed to work with bullmq v1.x, etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Confusing version guidance – v5 in install command but v1 in note
The install snippet pins bullmq at ^5.4.2, yet the follow-up note still references “v1.x version of this plugin is designed to work with bullmq v1.x”.
Readers may not know which combo is correct. Either update the note to reflect the current (v3.x) plugin using BullMQ v5, or change the install snippet if v1 is still expected.
Suggested wording:
-Note: To use this plugin, you need to manually install the `bullmq` package:
+Note: To use this plugin, you need to manually install the `bullmq` package.
+Vendure ≥ v3 is tested with **bullmq v5**, so install a compatible v5 release.
+For older Vendure v1 installations, stick to **bullmq v1** instead.This removes ambiguity and helps users avoid an immediate “invalid peer-dependency” headache.
🤖 Prompt for AI Agents
In docs/docs/reference/core-plugins/job-queue-plugin/bull-mqjob-queue-plugin.md
around lines 35 to 41, the install command specifies bullmq version 5.4.2, but
the note below references compatibility with bullmq v1.x, causing confusion.
Update the note to correctly reflect that the current plugin version (v3.x) is
designed to work with bullmq v5.x, ensuring consistency between the install
command and the compatibility note to avoid user confusion and dependency
issues.
| Note: To use this strategy, you need to manually install the `@google-cloud/pubsub` package: | ||
|
|
||
| ```shell | ||
| npm install | ||
|
|
||
| ```ts title="Signature" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix broken code-fence and show the correct install command
The opening ```shell fence is never closed, so everything that follows is rendered as part of the shell block, breaking the whole page.
At the same time the snippet omits the actual package name that the preceding paragraph tells the reader to install.
```shell
-npm install
-
-```ts title="Signature"
+npm install @google-cloud/pubsub
+```
+
+```ts title="Signature"This closes the first fence and includes the required package, restoring proper Markdown rendering.
🤖 Prompt for AI Agents
In
docs/docs/reference/core-plugins/job-queue-plugin/pub-sub-job-queue-strategy.md
around lines 19 to 24, the shell code fence for the npm install command is not
closed and the install command is incomplete. Fix this by closing the shell code
fence properly and updating the command to "npm install @google-cloud/pubsub" to
match the described package installation. Then reopen the next code fence for
the TypeScript signature as intended.
| - name: Publish to NPM | ||
| if: ${{ steps.commit_check.outputs.should_publish == 'true' }} | ||
| run: npx lerna publish from-package --yes --dist-tag master --no-git-reset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Packages are published without an explicit build – rely on incidental scripts
lerna publish from-package assumes artefacts are already built.
If any package lacks a "prepare"/"prepublishOnly" script the publish will push unbuilt sources.
Add an explicit build before publishing:
- name: Build workspace
if: ${{ steps.commit_check.outputs.should_publish == 'true' }}
run: npm run build🤖 Prompt for AI Agents
In .github/workflows/publish_master_to_npm.yml around lines 78 to 80, the
publish step uses 'lerna publish from-package' without an explicit build step,
risking publishing unbuilt source code if packages lack prepare or
prepublishOnly scripts. To fix this, add a separate build step before the
publish step that runs 'npm run build' conditioned on the same publish trigger,
ensuring all packages are properly built before publishing.
| - name: Version and build packages | ||
| if: ${{ steps.commit_check.outputs.should_publish == 'true' }} | ||
| run: | | ||
| # Get current version from lerna.json | ||
| CURRENT_VERSION=$(node -p "require('./lerna.json').version") | ||
| IFS='.' read -r -a VERSION_PARTS <<< "$CURRENT_VERSION" | ||
| # Increment patch version for pre-release | ||
| PATCH=$((VERSION_PARTS[2] + 1)) | ||
| # Compose new pre-release version incl. timestamp | ||
| NEW_VERSION="${VERSION_PARTS[0]}.${VERSION_PARTS[1]}.${PATCH}-master-${{ steps.date.outputs.date }}" | ||
| npx lerna version $NEW_VERSION --no-git-tag-version --yes --no-push --force-publish |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NEW_VERSION is lost after this step – commit message will be blank
NEW_VERSION is a shell variable local to this step; subsequent steps run in a fresh shell, so it is not available when we build the commit message.
This results in:
chore: Bump version for pre-release to (note the empty version).
- npx lerna version $NEW_VERSION --no-git-tag-version --yes --no-push --force-publish
+ npx lerna version $NEW_VERSION --no-git-tag-version --yes --no-push --force-publish
+ # Expose for later steps
+ echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENVand later:
- git commit -m "chore: Bump version for pre-release to $NEW_VERSION"
+ git commit -m "chore: Bump version for pre-release to ${NEW_VERSION:-UNKNOWN}"(or use ${{ env.NEW_VERSION }} in a composite run-step).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Version and build packages | |
| if: ${{ steps.commit_check.outputs.should_publish == 'true' }} | |
| run: | | |
| # Get current version from lerna.json | |
| CURRENT_VERSION=$(node -p "require('./lerna.json').version") | |
| IFS='.' read -r -a VERSION_PARTS <<< "$CURRENT_VERSION" | |
| # Increment patch version for pre-release | |
| PATCH=$((VERSION_PARTS[2] + 1)) | |
| # Compose new pre-release version incl. timestamp | |
| NEW_VERSION="${VERSION_PARTS[0]}.${VERSION_PARTS[1]}.${PATCH}-master-${{ steps.date.outputs.date }}" | |
| npx lerna version $NEW_VERSION --no-git-tag-version --yes --no-push --force-publish | |
| - name: Version and build packages | |
| if: ${{ steps.commit_check.outputs.should_publish == 'true' }} | |
| run: | | |
| # Get current version from lerna.json | |
| CURRENT_VERSION=$(node -p "require('./lerna.json').version") | |
| IFS='.' read -r -a VERSION_PARTS <<< "$CURRENT_VERSION" | |
| # Increment patch version for pre-release | |
| PATCH=$((VERSION_PARTS[2] + 1)) | |
| # Compose new pre-release version incl. timestamp | |
| NEW_VERSION="${VERSION_PARTS[0]}.${VERSION_PARTS[1]}.${PATCH}-master-${{ steps.date.outputs.date }}" | |
| npx lerna version $NEW_VERSION --no-git-tag-version --yes --no-push --force-publish | |
| + # Expose for later steps | |
| + echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV |
| - name: Version and build packages | |
| if: ${{ steps.commit_check.outputs.should_publish == 'true' }} | |
| run: | | |
| # Get current version from lerna.json | |
| CURRENT_VERSION=$(node -p "require('./lerna.json').version") | |
| IFS='.' read -r -a VERSION_PARTS <<< "$CURRENT_VERSION" | |
| # Increment patch version for pre-release | |
| PATCH=$((VERSION_PARTS[2] + 1)) | |
| # Compose new pre-release version incl. timestamp | |
| NEW_VERSION="${VERSION_PARTS[0]}.${VERSION_PARTS[1]}.${PATCH}-master-${{ steps.date.outputs.date }}" | |
| npx lerna version $NEW_VERSION --no-git-tag-version --yes --no-push --force-publish | |
| - git commit -m "chore: Bump version for pre-release to $NEW_VERSION" | |
| + git commit -m "chore: Bump version for pre-release to ${NEW_VERSION:-UNKNOWN}" |
🤖 Prompt for AI Agents
In .github/workflows/publish_master_to_npm.yml around lines 60 to 70, the
NEW_VERSION variable is defined in a shell step but not persisted for later
steps, causing the commit message to miss the version. To fix this, export
NEW_VERSION as a GitHub Actions environment variable by adding 'echo
"NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV' at the end of the run block, so
subsequent steps can access it via '${{ env.NEW_VERSION }}'.
| // to introspect the GraphQL schema based on any API extensions | ||
| // and custom fields that are configured. | ||
| vendureConfigPath: pathToFileURL('./src/vendure-config.ts'), | ||
| // Points to the location of your Vendure server. | ||
| // Points to the location of your Vendure server. | ||
| adminUiConfig: { apiHost: 'http://localhost', apiPort: 3000 }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Make vendureConfigPath robust across working-directories.
pathToFileURL('./src/vendure-config.ts') is resolved relative to the process cwd.
If users invoke Vite from another directory (CI, Nx, pnpm workspace etc.) the
path can be wrong. Convert to an absolute path first.
- vendureConfigPath: pathToFileURL('./src/vendure-config.ts'),
+ vendureConfigPath: pathToFileURL(resolve(__dirname, 'src/vendure-config.ts')),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // to introspect the GraphQL schema based on any API extensions | |
| // and custom fields that are configured. | |
| vendureConfigPath: pathToFileURL('./src/vendure-config.ts'), | |
| // Points to the location of your Vendure server. | |
| // Points to the location of your Vendure server. | |
| adminUiConfig: { apiHost: 'http://localhost', apiPort: 3000 }, | |
| // to introspect the GraphQL schema based on any API extensions | |
| // and custom fields that are configured. | |
| vendureConfigPath: pathToFileURL(resolve(__dirname, 'src/vendure-config.ts')), | |
| // Points to the location of your Vendure server. | |
| adminUiConfig: { apiHost: 'http://localhost', apiPort: 3000 }, |
🤖 Prompt for AI Agents
In docs/docs/guides/extending-the-dashboard/getting-started/index.md around
lines 53 to 57, the vendureConfigPath is set using a relative path which can
break if the process is run from a different working directory. Fix this by
converting the relative path './src/vendure-config.ts' to an absolute path
before passing it to pathToFileURL, ensuring it resolves correctly regardless of
the current working directory.
| function OptimisticUpdateExample() { | ||
| const [optimisticState, addOptimistic] = useOptimistic(state, (currentState, optimisticValue) => { | ||
| // Return new state with optimistic update | ||
| return [...currentState, optimisticValue]; | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
useOptimistic example references undeclared state.
Readers copying this will hit a TS error. Provide an initial state variable:
-function OptimisticUpdateExample() {
- const [optimisticState, addOptimistic] = useOptimistic(state, (currentState, optimisticValue) => {
+function OptimisticUpdateExample() {
+ const [state, setState] = useState<ItemType[]>([]);
+ const [optimisticState, addOptimistic] = useOptimistic(state, (currentState, optimisticValue) => {
// ...
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function OptimisticUpdateExample() { | |
| const [optimisticState, addOptimistic] = useOptimistic(state, (currentState, optimisticValue) => { | |
| // Return new state with optimistic update | |
| return [...currentState, optimisticValue]; | |
| }); | |
| function OptimisticUpdateExample() { | |
| const [state, setState] = useState<ItemType[]>([]); | |
| const [optimisticState, addOptimistic] = useOptimistic(state, (currentState, optimisticValue) => { | |
| // Return new state with optimistic update | |
| return [...currentState, optimisticValue]; | |
| }); |
🤖 Prompt for AI Agents
In docs/docs/guides/extending-the-dashboard/tech-stack/index.md around lines 23
to 27, the example using useOptimistic references an undeclared variable state,
causing a TypeScript error. Declare and initialize a state variable before using
it in useOptimistic, such as const state = [] or an appropriate initial value,
to fix the error and make the example complete.
|
|
@michaelbromley I have played around with |
|
@michaelbromley started to patch package this feature set, do you need anything from me to get this into core payments plugins? I get that you were working 24/7 on the dashboard - which came together fabolously -, still would love to see this merged. |
|
@dlhck is attempting to deploy a commit to the Vendure Team on Vercel. A member of the Team first needs to authorize it. |
packages/payments-plugin/e2e/fixtures/braintree-checkout-test.plugin.ts
Outdated
Show resolved
Hide resolved
The plugin in this PR does not add any new customFields to vendure. I opted to define the |
|


Note: this PR has been remade, as it was originally branched off from master and made against master.
Description
As briefly described in #3218, this PR adds new feature to the core BraintreePlugin, extending the plugin options with an optional object named
merchantAccountIds.merchantAccountId, thegateway.clientToken.generate()andgateway.transaction.sale(). Both of these methods accept themerchantAccountIdwith typestring | undefined. To look up the correctmerchantAccountIdto use, we are using the activeorder.currencyCodeand the plugin options. I did not implement heavy input error checks as the plugin option validity is evaluated runtime thanks to typescript.clientTokengeneration and relying on the braintree-drop-in UI client side. Thebraintree-dev-serversets up an Order, logs info for the developer and exposes theshopClientand generatedclientTokenfor a test plugin found under/fixtures/braintree-checkout-test.plugin.ts.<div id="result"/>.noncegenerated by the client drop-in UI doesn't have fake-currency-mismatch-nonce test value. The drop-in UI in the browser has to be manually completed and the value sent to the vendure server. I think the development server introduced here helps a lot in this, but I'm open for suggestions to make complete e2e here.Possible improvement
I think it's not optimal to add the
merchantAccountIdvalues during plugin initialisation, this would be better off as args for the payment handler itself. But I would rather wait for the newstructtype to create the currency-merchantAccountId pairs as handler arguments to make it bullet-proof.Breaking changes
As far as I'm concerned, there are none.
Checklist
📌 Always:
👍 Most of the time:
Summary by CodeRabbit
New Features
Documentation
Style