From 1b20a858b2abb40afb9191254b8ea56cd03efdfe Mon Sep 17 00:00:00 2001 From: David Traum Date: Fri, 10 Apr 2026 16:07:16 +0200 Subject: [PATCH 1/7] docs: update code examples --- docs/admin-sdk/api-reference/base-options.md | 2 +- docs/admin-sdk/api-reference/context.md | 16 ++++++++-------- docs/admin-sdk/api-reference/ui/actionButton.md | 10 +++++----- docs/admin-sdk/develop/translations.md | 5 ++++- docs/admin-sdk/getting-started/index.md | 1 - .../getting-started/installation-apps.md | 4 +++- 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/docs/admin-sdk/api-reference/base-options.md b/docs/admin-sdk/api-reference/base-options.md index ee8936c76..ad4e681e8 100644 --- a/docs/admin-sdk/api-reference/base-options.md +++ b/docs/admin-sdk/api-reference/base-options.md @@ -69,7 +69,7 @@ notification.dispatch({ }); ui.actionButton.add({ - action: 'generate-report', + name: 'generate-report', entity: 'product', view: 'detail', label: 'Generate Report', diff --git a/docs/admin-sdk/api-reference/context.md b/docs/admin-sdk/api-reference/context.md index b365cfb71..77dda0d86 100644 --- a/docs/admin-sdk/api-reference/context.md +++ b/docs/admin-sdk/api-reference/context.md @@ -233,14 +233,14 @@ string; "6.4.0.0"; ``` -## compareShopwareVersion() +## compareIsShopwareVersion() -Compares the current Shopware version against a target version. The current Shopware version is always the left-hand side of the comparison — so `context.compareShopwareVersion('>=', '7.0.0')` reads as "is the current Shopware version equal to or greater than 7.0.0?" +Compares the current Shopware version against a target version. The current Shopware version is always the left-hand side of the comparison — so `context.compareIsShopwareVersion('>=', '7.0.0')` reads as "is the current Shopware version equal to or greater than 7.0.0?" #### Usage ```ts -const isRightVersion = await context.compareShopwareVersion(">=", "7.0.0"); +const isRightVersion = await context.compareIsShopwareVersion(">=", "7.0.0"); ``` #### Parameters @@ -253,9 +253,9 @@ const isRightVersion = await context.compareShopwareVersion(">=", "7.0.0"); The function supports both Shopware's four-digit version number and semver versions. The following calls are equivalent: ```ts -await context.compareShopwareVersion(">=", "6.6.4.0"); +await context.compareIsShopwareVersion(">=", "6.6.4.0"); -await context.compareShopwareVersion(">=", "6.4.0"); +await context.compareIsShopwareVersion(">=", "6.4.0"); ``` #### Return value @@ -303,10 +303,10 @@ Promise<{ { name: 'my-extension', version: '1.2.3', - type: 'app' + type: 'app', privileges: { read: [ 'product', 'customer' ], - write: [ 'product' ], + update: [ 'product' ], additional: [ 'system.cache_clear' ] } } @@ -465,7 +465,7 @@ No parameters needed. #### Return value ```ts -Promise; +Promise; ``` ## can() diff --git a/docs/admin-sdk/api-reference/ui/actionButton.md b/docs/admin-sdk/api-reference/ui/actionButton.md index 94ded8d01..5e9700664 100644 --- a/docs/admin-sdk/api-reference/ui/actionButton.md +++ b/docs/admin-sdk/api-reference/ui/actionButton.md @@ -19,7 +19,7 @@ import { location, ui } from "@shopware-ag/meteor-admin-sdk"; if (location.is(location.MAIN_HIDDEN)) { ui.actionButton.add({ - action: "your-app_customer-detail-action", + name: "your-app_customer-detail-action", entity: "customer", view: "detail", label: "Test action", @@ -34,7 +34,7 @@ if (location.is(location.MAIN_HIDDEN)) { | Name | Required | Description | | :----------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `action` | true | A unique name of your action | +| `name` | true | A unique identifier for your action | | `entity` | true | The entity this action is for possible values: `product`, `order`, `category`, `promotion`, `customer` or `media`. Value `media` is available in Shopware version 6.7.1 | | `view` | true | Determines if the action button appears on the listing or detail page, possible values: `detail`,`list` or item. View `item` is only used for entity `media` and in version 6.7.1 | | `label` | true | The label of your action button | @@ -58,7 +58,7 @@ import { location, ui } from "@shopware-ag/meteor-admin-sdk"; if (location.is(location.MAIN_HIDDEN)) { ui.actionButton.add({ - action: "your-app_customer-detail-action", + name: "your-app_customer-detail-action", entity: "customer", view: "detail", label: "Test action", @@ -81,7 +81,7 @@ if (location.is(location.MAIN_HIDDEN)) { import { ui } from "@shopware-ag/meteor-admin-sdk"; ui.actionButton.add({ - action: "your-app_customer-detail-action", + name: "your-app_customer-detail-action", entity: "customer", view: "detail", meteorIcon: "regular-analytics", @@ -104,7 +104,7 @@ ui.actionButton.add({ import { ui } from "@shopware-ag/meteor-admin-sdk"; ui.actionButton.add({ - action: "test-media-button", + name: "test-media-button", entity: "media", view: "item", meteorIcon: "regular-tools-alt", diff --git a/docs/admin-sdk/develop/translations.md b/docs/admin-sdk/develop/translations.md index dc45b4260..0431a0269 100644 --- a/docs/admin-sdk/develop/translations.md +++ b/docs/admin-sdk/develop/translations.md @@ -37,8 +37,11 @@ Snippet files follow the same structure used by the Shopware Administration. Ove Reference snippet keys directly in the UI configuration. Example: ```js -sw.ui.componentSection('sw-manufacturer-card-custom-fields__before').add({ +import { ui } from '@shopware-ag/meteor-admin-sdk'; + +ui.componentSection.add({ component: 'card', + positionId: 'sw-manufacturer-card-custom-fields__before', props: { title: 'my-app-name.example-card.title', subtitle: 'my-app-name.example-card.subtitle', diff --git a/docs/admin-sdk/getting-started/index.md b/docs/admin-sdk/getting-started/index.md index 6e6c4be4c..b9eaa8c51 100644 --- a/docs/admin-sdk/getting-started/index.md +++ b/docs/admin-sdk/getting-started/index.md @@ -19,7 +19,6 @@ Shopware supports two extension types: **apps** and **plugins**. Both can use th Apps run on an external server and communicate with Shopware through a defined API. They are the recommended approach because: - They work with **Shopware Cloud** and self-hosted instances -- They can be distributed through the Shopware Store - The frontend and backend are fully decoupled from the Shopware codebase Set up an app: [App Installation Flow](./installation-apps.md) diff --git a/docs/admin-sdk/getting-started/installation-apps.md b/docs/admin-sdk/getting-started/installation-apps.md index 3a1c792a5..50a212ae5 100644 --- a/docs/admin-sdk/getting-started/installation-apps.md +++ b/docs/admin-sdk/getting-started/installation-apps.md @@ -16,7 +16,9 @@ This guide discusses two SDKs: Each Shopware app must be hosted on its own domain. -It is NOT possible to host multiple apps under the same domain using different subfolders. Instead, use subdomains for each app. +It is NOT possible to host multiple apps under the same domain using different subfolders such as `your-company.com/app-one` and `your-company.com/app-two`. + +This is because the browser security model uses the app's **origin** (`scheme + host + port`) to isolate apps, and the path is not part of that origin. Apps hosted under different subfolders would still share the same origin, so they are not treated as separate apps. For more details, see the [FAQ entry](https://developer.shopware.com/resources/admin-extension-sdk/faq/#can-i-use-the-same-domain-with-subfolders-for-multiple-apps). Instead, use a dedicated subdomain for each app. Example: From 9bc7c9b395c97ba435a6d37f19da3beca20392c5 Mon Sep 17 00:00:00 2001 From: David Traum Date: Tue, 14 Apr 2026 15:35:14 +0200 Subject: [PATCH 2/7] chore: doc updates --- docs/admin-sdk/api-reference/data/repository.md | 8 ++++++-- docs/admin-sdk/api-reference/ui/mediaModal.md | 8 ++++---- docs/admin-sdk/api-reference/window.md | 10 +++++----- docs/admin-sdk/introduction.md | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/admin-sdk/api-reference/data/repository.md b/docs/admin-sdk/api-reference/data/repository.md index acb2a87c0..20e2c2137 100644 --- a/docs/admin-sdk/api-reference/data/repository.md +++ b/docs/admin-sdk/api-reference/data/repository.md @@ -150,14 +150,18 @@ Clones an existing entity ```ts const exampleRepository = data.repository('your_entity'); -const clonedEntityId = await exampleRepository.clone('theEntityIdToClone'); +const clonedEntityId = await exampleRepository.clone( + 'theEntityIdToClone', + yourApiContext +); ``` #### Parameters | Name | Required | Default | Description | | :--------- | :------- | :------ | :--------------------------------------------- | | `entityId` | true | | The entity id which should be cloned | -| `context` | false | {} | Change the [request context](#request-context) | +| `context` | true | | Change the [request context](#request-context) | +| `behavior` | false | | Optional clone behavior passed as the third argument | #### Return value This method returns the id of the cloned entity. diff --git a/docs/admin-sdk/api-reference/ui/mediaModal.md b/docs/admin-sdk/api-reference/ui/mediaModal.md index 6c5a89304..333d09654 100644 --- a/docs/admin-sdk/api-reference/ui/mediaModal.md +++ b/docs/admin-sdk/api-reference/ui/mediaModal.md @@ -27,7 +27,7 @@ ui.mediaModal.open({ allowMultiSelect: false, fileAccept: "image/png", selectors: ["fileName", "id", "url"], - callback: ({ fileName, id, url }) => {}, + callback: (mediaSelections) => {}, }); ``` @@ -42,8 +42,8 @@ All parameters are similar to the `sw-media-modal-v2` component's props. | `allowMultiSelect` | false | true | Define single or multiple selection | | `defaultTab` | false | library | Defines which tab should be opened by default | | `fileAccept` | false | image/\* | Define the file types which are allowed to be uploaded in Upload tab | -| `selectors` | false | ['fileName', 'id', 'url'] | Selected properties which should be returned in callback function | -| `callback` | true | | Callback function which will be called once the media item is selected. | +| `selectors` | false | ['fileName', 'id', 'url'] | Selected properties which should be returned for each item in the callback array | +| `callback` | true | | Callback function which receives an array of selected media items once a selection is made. | #### Example @@ -54,7 +54,7 @@ ui.mediaModal.open({ initialFolderId: "productMediaFolderId", allowMultiSelect: false, selectors: ["fileName", "id", "url"], - callback: ({ fileName, id, url }) => {}, + callback: (mediaSelections) => {}, }); ``` diff --git a/docs/admin-sdk/api-reference/window.md b/docs/admin-sdk/api-reference/window.md index 1edd09631..7b175c843 100644 --- a/docs/admin-sdk/api-reference/window.md +++ b/docs/admin-sdk/api-reference/window.md @@ -104,7 +104,7 @@ Returns a unique identifier for the current browser window. This is useful when #### Usage ```ts -adminWindow.getId(); +await adminWindow.getId(); ``` #### Parameters @@ -113,14 +113,14 @@ No parameters required. #### Return value -A `string` representing a unique identifier for the current window. +A `Promise` that resolves to a unique identifier for the current window. #### Example This example clears `sessionStorage` when a duplicated browser tab is detected. This can happen if a user uses the _Duplicate Tab_ feature of some browsers. ```ts -const windowId = adminWindow.getId(); +const windowId = await adminWindow.getId(); const storedWindowId = globalThis.sessionStorage.getItem("window-id"); if (windowId !== storedWindowId) { @@ -138,7 +138,7 @@ Retrieve the current Administration router path. #### Usage ```ts -adminWindow.getPath(); +await adminWindow.getPath(); ``` #### Parameters @@ -147,4 +147,4 @@ No parameters required. #### Return value -Returns a `string` containing the full path, or an empty string if the router is not available. +Returns a `Promise` containing the full path, or an empty string if the router is not available. diff --git a/docs/admin-sdk/introduction.md b/docs/admin-sdk/introduction.md index 4a3212136..925dc8474 100644 --- a/docs/admin-sdk/introduction.md +++ b/docs/admin-sdk/introduction.md @@ -21,7 +21,7 @@ What you can do with the SDK: - Provides a stable, backwards-compatible API for extending the Administration and reducing complexity during Shopware updates - Abstracts internal complexity, so deep knowledge of the Admin internals is not required - Written in [TypeScript](https://www.typescriptlang.org/) with full type safety and auto-completion support -- Lightweight and tree-shakable with no external dependencies, allowing granular imports and small bundle sizes +- Lightweight and tree-shakable, allowing granular imports and small bundle sizes ## Prerequisites From fd09877d7e86593789818a918b7324e63573ef12 Mon Sep 17 00:00:00 2001 From: David Traum Date: Tue, 14 Apr 2026 15:44:17 +0200 Subject: [PATCH 3/7] chore: remove instruction --- docs/admin-sdk/getting-started/installation-apps.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/admin-sdk/getting-started/installation-apps.md b/docs/admin-sdk/getting-started/installation-apps.md index 50a212ae5..f2833229a 100644 --- a/docs/admin-sdk/getting-started/installation-apps.md +++ b/docs/admin-sdk/getting-started/installation-apps.md @@ -18,8 +18,6 @@ Each Shopware app must be hosted on its own domain. It is NOT possible to host multiple apps under the same domain using different subfolders such as `your-company.com/app-one` and `your-company.com/app-two`. -This is because the browser security model uses the app's **origin** (`scheme + host + port`) to isolate apps, and the path is not part of that origin. Apps hosted under different subfolders would still share the same origin, so they are not treated as separate apps. For more details, see the [FAQ entry](https://developer.shopware.com/resources/admin-extension-sdk/faq/#can-i-use-the-same-domain-with-subfolders-for-multiple-apps). Instead, use a dedicated subdomain for each app. - Example: - `app-one.your-company.com` From b2b0587f85fe5f7d1857923cdffd4fd81eb62173 Mon Sep 17 00:00:00 2001 From: David Traum Date: Tue, 14 Apr 2026 15:45:41 +0200 Subject: [PATCH 4/7] chore: update installation-apps --- docs/admin-sdk/getting-started/installation-apps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin-sdk/getting-started/installation-apps.md b/docs/admin-sdk/getting-started/installation-apps.md index f2833229a..3a1c792a5 100644 --- a/docs/admin-sdk/getting-started/installation-apps.md +++ b/docs/admin-sdk/getting-started/installation-apps.md @@ -16,7 +16,7 @@ This guide discusses two SDKs: Each Shopware app must be hosted on its own domain. -It is NOT possible to host multiple apps under the same domain using different subfolders such as `your-company.com/app-one` and `your-company.com/app-two`. +It is NOT possible to host multiple apps under the same domain using different subfolders. Instead, use subdomains for each app. Example: From 31fd66b65f8724e33dea4f34c26dbfa13af6a88f Mon Sep 17 00:00:00 2001 From: David Traum Date: Wed, 15 Apr 2026 09:51:30 +0200 Subject: [PATCH 5/7] chore: add description for clone behavior, remove semicolons, change broken links --- docs/admin-sdk/api-reference/context.md | 24 +++++++++---------- .../api-reference/data/repository.md | 21 +++++++++++++++- docs/admin-sdk/api-reference/ui/mediaModal.md | 4 ++-- docs/admin-sdk/docs.yml | 4 ++-- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/docs/admin-sdk/api-reference/context.md b/docs/admin-sdk/api-reference/context.md index 77dda0d86..f0f673e1d 100644 --- a/docs/admin-sdk/api-reference/context.md +++ b/docs/admin-sdk/api-reference/context.md @@ -33,7 +33,7 @@ No parameters needed. Promise<{ languageId: string; systemLanguageId: string; -}>; +}> ``` #### Example value @@ -98,7 +98,7 @@ No parameters needed. #### Return value ```ts -Promise<"development" | "production" | "testing">; +Promise<"development" | "production" | "testing"> ``` #### Example value @@ -127,7 +127,7 @@ No parameters needed. Promise<{ locale: string; fallbackLocale: string; -}>; +}> ``` #### Example value @@ -195,7 +195,7 @@ No parameters needed. Promise<{ systemCurrencyId: string; systemCurrencyISOCode: string; -}>; +}> ``` #### Example value @@ -224,7 +224,7 @@ No parameters needed. #### Return value ```ts -string; +string ``` #### Example value @@ -261,7 +261,7 @@ await context.compareIsShopwareVersion(">=", "6.4.0"); #### Return value ```ts -boolean; +boolean ``` #### Example value @@ -294,7 +294,7 @@ Promise<{ version: string; type: "app" | "plugin"; privileges: privileges; -}>; +}> ``` #### Example value @@ -349,7 +349,7 @@ Promise<{ title: string; type: string; username: string; -}>; +}> ``` #### Example value @@ -390,7 +390,7 @@ No parameters needed. #### Return value ```ts -Promise; +Promise ``` This function returns a Promise that resolves to a string representing the user's timezone. @@ -428,7 +428,7 @@ Promise<{ id: string; locationId: string; }>; -}>; +}> ``` #### Example value @@ -465,7 +465,7 @@ No parameters needed. #### Return value ```ts -Promise; +Promise ``` ## can() @@ -489,5 +489,5 @@ const isAllowed: boolean = await context.can("product:read"); #### Return value ```ts -boolean; +boolean ``` diff --git a/docs/admin-sdk/api-reference/data/repository.md b/docs/admin-sdk/api-reference/data/repository.md index 20e2c2137..9e5a2693e 100644 --- a/docs/admin-sdk/api-reference/data/repository.md +++ b/docs/admin-sdk/api-reference/data/repository.md @@ -161,7 +161,7 @@ const clonedEntityId = await exampleRepository.clone( | :--------- | :------- | :------ | :--------------------------------------------- | | `entityId` | true | | The entity id which should be cloned | | `context` | true | | Change the [request context](#request-context) | -| `behavior` | false | | Optional clone behavior passed as the third argument | +| `behavior` | false | | Configure the [clone behavior](#clone-behavior) | #### Return value This method returns the id of the cloned entity. @@ -254,3 +254,22 @@ const exampleContext = { liveVersionId: 'yourLiveVersionId' } ``` + +### Clone Behavior +You can optionally change the clone behavior of the request. The clone behavior controls how the entity is duplicated on the server. + +Use `overwrites` to replace values in the cloned entity before it is written, for example to set a different name or other field values on the copy. + +Use `cloneChildren` to control whether child entities are cloned as well. This value defaults to `true`. + +```ts +const exampleCloneBehavior = { + // Replace values in the cloned entity before it is saved + overwrites: { + name: 'Copy of the original entity', + active: false + }, + // Set to false if child entities should not be cloned + cloneChildren: true +} +``` diff --git a/docs/admin-sdk/api-reference/ui/mediaModal.md b/docs/admin-sdk/api-reference/ui/mediaModal.md index 333d09654..96c22f8f8 100644 --- a/docs/admin-sdk/api-reference/ui/mediaModal.md +++ b/docs/admin-sdk/api-reference/ui/mediaModal.md @@ -27,7 +27,7 @@ ui.mediaModal.open({ allowMultiSelect: false, fileAccept: "image/png", selectors: ["fileName", "id", "url"], - callback: (mediaSelections) => {}, + callback: ([{ fileName, id, url }]) => {}, }); ``` @@ -54,7 +54,7 @@ ui.mediaModal.open({ initialFolderId: "productMediaFolderId", allowMultiSelect: false, selectors: ["fileName", "id", "url"], - callback: (mediaSelections) => {}, + callback: ([{ fileName, id, url }]) => {}, }); ``` diff --git a/docs/admin-sdk/docs.yml b/docs/admin-sdk/docs.yml index 2d491b288..280d0a016 100644 --- a/docs/admin-sdk/docs.yml +++ b/docs/admin-sdk/docs.yml @@ -1,9 +1,9 @@ redirects: api-reference/ui/component-section.html: api-reference/ui/component-sections.html - api-reference/ui/module/paymentOverviewCard.html: api-reference/ui/paymentOverviewCard.html + api-reference/ui/module/paymentOverviewCard.html: api-reference/ui/purchases-and-payments/paymentOverviewCard.html internals/how-it-works.html: concepts/architecture.html internals/datahandling.html: concepts/datahandling.html - api-reference/in-app-purchases/in-app-purchases.html: api-reference/data/in-app-purchases.html + api-reference/in-app-purchases/in-app-purchases.html: api-reference/ui/purchases-and-payments/in-app-purchases.html api-reference/in-app-purchases/index.html: api-reference/data/index.html api-reference/ui/module/index.html: api-reference/ui/index.html faq/index.html: develop/translations.html From b31316f6a989904a65bd58aa945d57bc778f2ccd Mon Sep 17 00:00:00 2001 From: David Traum Date: Wed, 15 Apr 2026 10:05:29 +0200 Subject: [PATCH 6/7] chore: add SaaS mention to app advantages --- docs/admin-sdk/getting-started/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin-sdk/getting-started/index.md b/docs/admin-sdk/getting-started/index.md index b9eaa8c51..74544ff1a 100644 --- a/docs/admin-sdk/getting-started/index.md +++ b/docs/admin-sdk/getting-started/index.md @@ -18,7 +18,7 @@ Shopware supports two extension types: **apps** and **plugins**. Both can use th Apps run on an external server and communicate with Shopware through a defined API. They are the recommended approach because: -- They work with **Shopware Cloud** and self-hosted instances +- They work with **Shopware Cloud** and self-hosted instances, and they are the only extension type available for **Shopware SaaS** - The frontend and backend are fully decoupled from the Shopware codebase Set up an app: [App Installation Flow](./installation-apps.md) From 928651d96e2c01d0430a23572d849ba88201f4da Mon Sep 17 00:00:00 2001 From: David Traum Date: Thu, 16 Apr 2026 15:21:58 +0200 Subject: [PATCH 7/7] chore: Add title prop to notification --- docs/admin-sdk/api-reference/base-options.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/admin-sdk/api-reference/base-options.md b/docs/admin-sdk/api-reference/base-options.md index ad4e681e8..f463b3a15 100644 --- a/docs/admin-sdk/api-reference/base-options.md +++ b/docs/admin-sdk/api-reference/base-options.md @@ -20,6 +20,7 @@ In this example, the base options are passed on the same object as the method-sp import { notification } from '@shopware-ag/meteor-admin-sdk'; notification.dispatch({ + title: 'Product report ready', message: 'Your product report is ready', /* ... base options ... */ }); @@ -62,6 +63,7 @@ Pass the `privileges` array to any SDK method that supports base options: import { notification, ui } from '@shopware-ag/meteor-admin-sdk'; notification.dispatch({ + title: 'Product report ready', message: 'Your product report is ready', privileges: [ 'product:read',