Command Palette

Search for a command to run...

История изменений@gorgo/medusa-integration

2.0.0

Highlights

The Integration Module moves from 0.3 to 2.0 and takes the same major version as Medusa v2 and the Gorgo payment and fulfillment integrations built on it. Every Gorgo integration built on the module and released today requires @gorgo/medusa-integration@^2.0.0, so the version numbers say what works together. The upgrade needs Medusa v2.21.0 or later and a database migration, and nothing else in a project without its own code on top of the module. See Upgrade Guide and Breaking Changes below for the steps.

Settings Change History

The module records every change to an integration's settings. A record names the author, the time, and each field that changed, with its value before and after. For an option marked secret: true, it keeps only what happened to the value, which is set, replaced, or removed, so secrets never reach the history. The record also keeps the IP address, the client, and the ID of the request.

In Medusa Admin, the Change History section of an integration's page shows its five latest changes, and the Change History page under Settings → Integrations lists the changes of every integration. Search the table by the author's email, the integration's name, or a changed field. Filter it by integration, event, author, and date, and sort it by time, integration, event, or author. A change opens in a side panel with every changed field as "before → after" and a Copy as JSON button. The page address holds the search, the filters, and the sorting, so you can share a link to a filtered history.

The history is kept indefinitely and outlives the integration it describes, so a deleted integration still shows how it was configured. The module writes the record in the same workflow run that makes the change. A change made in the Admin is attributed to the admin user, a change made with an API key to that key, and a change your own code makes without an actor to System. To attribute it to the signed-in admin user, pass the actor to the workflow:

await upsertIntegrationWorkflow(req.scope).run({
  input: {
    provider_id: "int_my_default",
    values: { sandbox: false },
    actor: { type: req.auth_context.actor_type, id: req.auth_context.actor_id },
  },
})

Read the history through the new /admin/integrations/changes routes of the Admin API or through the module's service. The integration.updated event now carries the actor and the ids of the changed fields. Refer to Settings Change History for what the module records and to View the Change History in Medusa Admin for the Admin.

Every Registration Names Its Instance

A provider registered without an id is now the instance default, keyed int_<identifier>_default, so every stored provider_id names its instance, the same as a registration with an id. getInstanceId() returns "default" instead of null, instance_id in the Admin API is always a string, and the package root exports DEFAULT_INSTANCE_ID. The settings and the change history saved under the old key, int_<identifier>, move to the new one when medusa db:migrate runs. Nothing moves into a default instance that already has settings, into a named instance, or out of a key that a registration still uses.

The module now refuses to start when a key is registered twice, which is two entries of options.providers with the same provider and the same id, or an entry with id: "default" next to one without an id. Before, the second registration replaced the first one silently.

Metadata and the JSON Section

An integration and each record of its change history carry metadata, free-form data of your own code, as on any Medusa entity. POST /admin/integrations/:provider_id and upsertIntegrationWorkflow merge it into the stored metadata key by key, and values became optional, so a request can change the metadata alone. The module never reads it, and the change history doesn't list it. The integration's page in Medusa Admin gains a JSON section with the stored record as the Admin API returns it, last on the page like on Medusa's own detail pages.

Four More Categories

A descriptor can declare the categories tax, subscriptions, reviews, and admin, and the Admin groups and filters integrations by them. The release also drops a leftover check constraint that the first migration had declared under the column's old name. It still rejected search, content, analytics, authentication, and file_providers, so an integration of those categories couldn't be saved.

A Format Version for Stored Secrets

The module now stores every encrypted secret as v1: followed by the same base64 of the IV, the auth tag, and the ciphertext as before. A value without the prefix is one that 0.3.x wrote, and the module reads it as before, so the upgrade re-encrypts nothing. Base64 has no :, so the two formats can't be confused. The version leaves room for an external secret store and key rotation in a later 2.x release, with no further major version. When a value is stored in a format the installed module doesn't know, the error names that format and asks for an upgrade.

Reading Across a Secret Flag Change

Changing an option's secret flag after a store admin has saved it no longer breaks the integration. A newly secret option keeps its plain-text value until the next save encrypts it, and an option that is no longer secret has its stored value decrypted when the module reads it. When a secret can't be decrypted, because encryptionKey is missing or changed or the value is in a format version the installed module doesn't know, the module throws a MedusaError of type unexpected_state that names the option and the integration. An Admin API route answers with that message instead of the generic An unknown error occurred., and the Admin shows it in the notification. The connection test reports such an error as failed with the message, and deleting the settings works without the right key, so a lost key no longer blocks the way out.

Search Integrations by Name

The search on the Integrations page matches an integration's name and description in the interface language, as well as its identifier and instance. The search of the change history matches the integration's name the same way.

Warnings for Provider Authors

At startup, the module now warns about every option whose name looks like a credential but isn't declared secret: true, because its value is shown in the Admin and kept in the change history in clear text. It also warns when two providers declare the same identifier. Such a configuration started silently before, with both providers sharing the package details, the license check and, without an id, one settings record. The warning names both providers. 2.x warns, and 3.0 will refuse to start.

Translations in the gorgo Namespace

The Admin resolves an i18n key of a descriptor in the gorgo namespace first, then in Medusa's default translation namespace, so a provider ships its translations from src/admin/i18n/index.ts under either one. A key in another namespace takes the namespace:key form. The module and every Gorgo integration now keep their translations under gorgo.

AbstractIntegrationProviderService

The base class of a provider is now AbstractIntegrationProviderService, in step with Medusa's AbstractFulfillmentProviderService and AbstractNotificationProviderService. AbstractIntegrationProvider stays as a deprecated alias through every 2.x release, so a provider written for 0.x keeps working without a change. The alias goes away in 3.0.

Value Lists Across Versions

The descriptor reference now says what a release may do to the descriptor's fixed value lists, which are category, an option's type and control, a section's column, preferredLayoutId, and the status that testConnection returns. A new value arrives in a minor release. A value is removed or renamed only in a major release. Code that branches on one of these values should handle a value it doesn't know. The JSDoc of each list says the same, so an editor shows the rule on hover.

More Exports From the Package Root

The package root now exports every workflow of the module, which adds deleteIntegrationWorkflow, setIntegrationEnabledWorkflow, and testIntegrationConnectionWorkflow next to upsertIntegrationWorkflow, with their input types. It also exports the types the service returns, which are Integration, IntegrationChange, UiDescriptor, UiSection, UiField, IntegrationOverviewItem, IntegrationOverviewQuery, IntegrationOverviewResult, CatalogItem, LicenseStateEntry, IntegrationChangeUser, and IntegrationChangeField. The service gains readPlainOptions(record), which returns the stored options with the secrets left as stored and never throws, so the Admin can show a record whose secrets no longer decrypt.

New Documentation

The documentation of the module was rewritten. It gains references of the Admin API routes, the workflows, the service, the data models, the events, the validation rules, and the localization, guides to custom sections and the admin widget zones, user guides for the Admin, and diagrams of the roles, the read path, and the startup on the concepts page.

Upgrade Guide

A project that uses the module and the Gorgo integrations needs the first two steps. The third one is for a project with its own code on top of the module.

1. Update Medusa and the Packages

The module requires Medusa v2.21.0 or later. Update the module and every Gorgo integration in one step, so the peer dependencies stay satisfied. Replace the YooKassa package with the integrations your project uses:

yarn add @gorgo/medusa-integration@^2.0.0 @gorgo/medusa-payment-yookassa@^2.1.0

These versions work with 2.0:

PackageVersion
@gorgo/medusa-payment-yookassa2.1.0
@gorgo/medusa-payment-tkassa2.1.0
@gorgo/medusa-payment-robokassa2.1.0
@gorgo/medusa-payment-stripe2.1.0
@gorgo/medusa-payment-paypal2.1.0
@gorgo/medusa-payment-authorizenet2.1.0
@gorgo/medusa-payment-mollie2.1.0
@gorgo/medusa-fulfillment-apiship2.2.0
@gorgo/medusa-1c0.4.0
@gorgo-store/medusa-erp-1c0.4.0

2. Run the Migrations

The change history lives in the new integration_change table, metadata is a new column of integration and integration_change, and the category check gains the new values. The migrations also move the settings and the history of every registration without an id from int_<identifier> to int_<identifier>_default. Run them and restart the server:

npx medusa db:migrate

Until the migrations run, every change goes ahead without a record, the module logs a warning, and an integration registered without an id reads no settings, because the module looks for them under the new key. The settings and the secrets saved on 0.3.x are read as before, and the module re-encrypts nothing.

3. Check Your Own Code

  • A subscriber of integration.updated that branches on change handles the new "disabled" value.
  • Code that builds or compares the provider_id of a registration without an id uses int_<identifier>_default instead of int_<identifier>. integrationProviderKey(identifier) returns the new key, and parseIntegrationProviderKey returns instanceId: "default" for it and null for the old key.
  • Code that reads supports_multiple_instances from GET /admin/integrations drops it.
  • Code that catches the module's encryptionKey errors as a plain Error handles a MedusaError of type unexpected_state.
  • Code that deep-imports a compiled file of the module imports it from the root, ./workflows, ./modules/*, or ./admin instead. The root now exports every type a provider's declarations need.
  • A provider of your own keeps working as it is. Rename its base class from AbstractIntegrationProvider to AbstractIntegrationProviderService at your own pace, before 3.0. Remove supportsMultipleInstances from its descriptor if it declares it. getInstanceId() now returns "default" for a registration without an id, so a check for null is never true. If the provider is published with its declarations, rebuild it against 2.0, so its .d.ts files stop deep-importing the module.

To go back to 0.3.x after the upgrade, enter the secrets saved on 2.0 again, because 0.3.x doesn't read the new format, and expect 0.3.x to look for the settings of a registration without an id under the old key.

Breaking Changes

  • Medusa v2.21.0 or later. The module's peer dependencies on the @medusajs/* packages moved from ^2.17.2 to ^2.21.0.
  • The upgrade needs migrations. The module keeps the history in the new integration_change table, adds metadata to integration and integration_change, extends the category check, and moves the settings of every registration without an id to its new key. Until the migrations run, every change goes ahead without a record, the module logs a warning, and an integration registered without an id reads no settings.
  • A registration without an id is the instance default. Its key is int_<identifier>_default instead of int_<identifier>, getInstanceId() returns "default" instead of null, instance_id in the Admin API is always a string, and parseIntegrationProviderKey returns null for the old key.
  • A duplicate registration refuses to start. Two entries of options.providers with the same provider and the same id, or an entry with id: "default" next to one without an id, throw at startup. Before, the second registration replaced the first one silently.
  • supportsMultipleInstances is gone. The descriptor field and the supports_multiple_instances flag of GET /admin/integrations are removed. The module registers every entry of options.providers either way.
  • Gorgo integrations require 2.x. The versions listed above declare @gorgo/medusa-integration@^2.0.0 as a peer dependency, and their earlier versions declare >=0.1.5 <1.0.0, so update the module and the integrations together.
  • Narrowed package exports. @gorgo/medusa-integration no longer exports ./* and ./providers/*. The entries that stay are the root, ./workflows, ./modules/*, ./admin, and ./package.json. A deep import of any other compiled file fails with ERR_PACKAGE_PATH_NOT_EXPORTED. The root now also exports the IntegrationSection, IntegrationValidateContext, IntegrationValidateIssue, and IntegrationLayouts types, so the declarations of a provider written by the guide build without a deep import.
  • integration.updated says "disabled". When an integration is turned off, the event's change is now "disabled". Before, both enabling and disabling arrived as "enabled". A subscriber that branches on change needs the new value.
  • Encryption errors are MedusaErrors. When encryptionKey is missing, isn't the key a secret was saved with, or a secret is stored in a format version the module doesn't know, the module throws a MedusaError of type unexpected_state with a message that names the option and the integration. Before, it threw a plain Error or Node.js's own decryption error, and an Admin API route answered 500 with a generic message.
  • No downgrade after a secret is saved. A secret saved on 2.0 is stored with the format version above, and 0.3.x can't read it. A downgrade needs the secrets entered again.
  • Deprecated. AbstractIntegrationProvider is an alias of AbstractIntegrationProviderService and goes away in 3.0.

Features

  • record a change history of integration settings by @KaneFlak in 1816e1b

  • add read routes for the integration settings change history by @KaneFlak in e8b24be

  • show the change history on the integration page by @KaneFlak in f05acb2

  • add the change history page with search and the change card by @KaneFlak in 781667a

  • filter the change history by author and search it by the options changed by @KaneFlak in f8b923a

  • search integrations by their translated names and descriptions by @KaneFlak in 3e0c6aa

  • warn at startup when two providers declare the same identifier by @gorgohead in 54dea0a

  • store secrets with a format version and keep reading the unversioned ones by @gorgohead in 70824d0

  • register a provider without an id as the instance default, move its saved settings there on db:migrate and refuse a duplicate registration by @KaneFlak in 5559627

  • drop supportsMultipleInstances from the descriptor and the admin api by @KaneFlak in 0638d44

  • show the integration json on its page and add metadata to integrations and their changes by @KaneFlak in e0b3e5b

  • move the admin translations to the gorgo namespace by @KaneFlak in 8098d63

  • add the tax, subscriptions, reviews and admin categories by @gorgohead in e384a02

Bug Fixes

  • translate the pagination of the integrations and change history tables by @KaneFlak in 0bb06ad

  • fit the field badges of the change history table to its width by @KaneFlak in dfe38d7

  • send disabled in the integration.updated event when an integration is turned off by @gorgohead in 2128829

  • drop the leftover category check, read secrets across a secret flag change, report encryption key errors as MedusaError and export the service types and workflows from the root by @KaneFlak in b245203

Refactoring

  • rename AbstractIntegrationProvider to AbstractIntegrationProviderService with a deprecated alias by @KaneFlak in 1c91b2a

  • rename the integration state step to the integration snapshot step by @gorgohead in #533 (b31492b)

  • narrow the package exports and export the descriptor types from the root by @gorgohead in 3caa0f7

Documentation

0.3.3

Bug Fixes

  • regenerate the offline catalog with authorizenet and mollie by @gorgohead in d61f97d

0.3.2

Documentation

0.3.1

Documentation

0.3.0

Highlights

  • Gorgo License for paid integrations. A paid integration declares "gorgo": { "license": "required" } in its package.json, and the module checks its license against the project key in GORGO_LICENSE. Open-source integrations are not checked at all. Without a paid integration installed, the module never contacts the license service, and a free integration shows no license in the Admin.
  • The verdict is in the Admin. A paid integration gets a license line in the integrations table and a license block on its page, with the subscription end date, what to fix when the check fails and a link to the Gorgo account. Check now reruns the check right away, for example after you add a domain or renew the subscription.
  • Never blocks the server. The check runs in the background after startup and then once a day, all paid integrations in one request. If the license service is unreachable, it tries again in 15 minutes.

Bug Fixes

0.2.9

Bug Fixes

Dependencies

  • Updated dependencies:
    • @gorgo/telemetry@1.4.1

0.2.8

Bug Fixes

0.2.7

Bug Fixes

0.2.6

Documentation

0.2.5

Bug Fixes

  • point the missing encryption key error at the plugin options by @gorgohead in 5df6552

0.2.4

Documentation

0.2.3

Documentation

0.2.2

Bug Fixes

0.2.1

Chores

  • update dependencies and peerDependencies across multiple packages by @gorgohead in 10ecafc

0.2.0

Features

Documentation

0.1.5

  • Add number value support for enum
  • Improve docs

0.1.4

  • Improve docs snippet and UI
  • Update docs

0.1.3

  • Update docs

0.1.2

  • Export upsert workflow and provider_id helpers
  • Update docs

0.1.1

  • Bug fixes and improvements
  • Update docs

0.1.0

Highlights

  • First release of the Integration Module for Medusa. Plugins declare their settings with a single defineIntegration descriptor, and store admins configure them right in the Admin under Settings → Integrations – no medusa-config edits, no redeploys.

Features

  • No-code configuration in the Admin. Manage plugin credentials and settings under Settings → Integrations.
  • Encrypted secrets at rest. Fields marked secret are encrypted (AES-256-GCM) and never reach the browser.
  • Declarative descriptor (defineIntegration) for plugin authors: options, sections, validation, and a connection test in one place.
  • Rich option types & validation: string / url / email / uuid / number / boolean / enum / json, per-option and cross-section rules, conditional visibility, read-only fields, i18n labels, and an icon.
  • Multiple instances of the same provider (e.g. several accounts).
  • Connection test from the Admin.
  • Typed runtime resolve: consumers read a validated, decrypted config; incomplete or disabled configs never resolve, so drafts don't leak into runtime.
  • Custom admin widgets per provider.
  • Anonymous telemetry.
Изменено 12 ноября 2026 г.·Редактировать страницу