Repository: effector/effector (ts)

Issue:
[babel-plugin] Add an option to disable transforming `Domain` methods
<!--
Please fill out this entire template so that we can evaluate your proposal as quickly as possible.
-->

## Proposal

Add a new option `transformLegacyDomainMethods` to `effector/babel-plugin` that allows users to disable transforming [unit creator methods](https://effector.dev/en/api/effector/domain/#unit-creators) on `Domain`.

- Defaults to `true`, keeping the current behavior intact (backward-compatible change).
- When _disabled_, this option should take priority over the current `domainMethods` option, ensuring no domain methods are transformed.

This should simplify the configuration for users who already need `domainMethods` option as a hack, and assist in migrating to the new `Domain` API https://github.com/effector/effector/pull/763.

## Use case

This change can help resolve broken AST transforms, where other libraries/code use the same function names as `Domain`.

Issues:
- https://github.com/effector/effector/issues/580
- https://github.com/kireevmp/effector-swc-plugin/issues/12

### Related work

SWC Plugin implementation: https://github.com/kireevmp/effector-swc-plugin/pull/14
Domain unit creators deprecation issue: https://github.com/effector/effector/issues/1051


Pull request description:
[babel-plugin] Add an option to disable transforming `Domain` methods
As proposed in #1052, this PR adds an option to disable transforming unit creator methods on `Domain`

- [x] Add an option to the plugin
- [x] Unit tests
- [x] Write docs with motivation and usage

Closes #1052 


Patch:
diff --git a/documentation/src/content/docs/en/api/effector/babel-plugin.md b/documentation/src/content/docs/en/api/effector/babel-plugin.md
index 68f56e90..2a5c8483 100644
--- a/documentation/src/content/docs/en/api/effector/babel-plugin.md
+++ b/documentation/src/content/docs/en/api/effector/babel-plugin.md
@@ -322,6 +322,30 @@ Adds a file path and variable name of a unit definition to a sid. Useful for deb
 - Type: `boolean`
 - Default: `false`
 
+## `transformLegacyDomainMethods` (#configuration-transformLegacyDomainMethods)
+
+Allows disabling transforming Unit creators on [Domain](/en/api/effector/Domain). This option is useful when these transforms interfere with other libraries or your code.
+
+The `effector/babel-plugin` may misidentify calls to unit creators because it is hard to know which variables are indeed Domains. If your project can't run due to this, you can turn these transforms off with this flag and pass `Domain` as an argument to regular unit creators, which is a better and more stable alternative.
+
+:::warning
+Disabling this option will prevent units created with `Domain` methods from having a `sid` and other information. If your code relies on these methods, this will cause issues with your existing code.
+:::
+
+### Formulae (#configuration-transformLegacyDomainMethods-formulae)
+
+```json
+[
+  "effector/babel-plugin",
+  {
+    "transformLegacyDomainMethods": false
+  }
+]
+```
+
+- Type: `boolean`
+- Default: `true`
+
 ## `noDefaults` (#configuration-noDefaults)
 
 Option for `effector/babel-plugin` for making custom unit factories with clean configuration.
diff --git a/src/babel/babel-plugin.js b/src/babel/babel-plugin.js
index 320b4f84..aa8d54f9 100644
--- a/src/babel/babel-plugin.js
+++ b/src/babel/babel-plugin.js
@@ -13,6 +13,7 @@ module.exports = function (babel, options = {}) {
     addNames,
     addLoc,
     debugSids,
+    transformLegacyDomainMethods,
     hmr,
     filename: enableFileName,
     stores,
@@ -559,7 +560,7 @@ module.exports = function (babel, options = {}) {
           }
         }
 
-        if (t.isMemberExpression(path.node.callee)) {
+        if (transformLegacyDomainMethods && t.isMemberExpression(path.node.callee)) {
           applyMethodParsers(
             domainMethodParsers,
             path,
@@ -650,6 +651,7 @@ const normalizeOptions = options => {
     options,
     properties: {
       reactSsr: false,
+      transformLegacyDomainMethods: true,
       forceScope: false,
       filename: true,
       stores: true,


Test patch:
diff --git a/src/babel/__tests__/__snapshots__/babel-plugin.test.js.snap b/src/babel/__tests__/__snapshots__/babel-plugin.test.js.snap
index 51ccf591..f99da452 100644
--- a/src/babel/__tests__/__snapshots__/babel-plugin.test.js.snap
+++ b/src/babel/__tests__/__snapshots__/babel-plugin.test.js.snap
@@ -725,6 +725,43 @@ domain.createEvent('foo', {
 "
 `;
 
+exports[`babel-plugin should create domain no legacy methods with options 1`] = `
+"import {createDomain} from 'effector'
+import {importedDomain} from './local-file'
+const created = createDomain('created', {
+  name: 'created',
+  sid: '-g42wg',
+})
+const event = created.createEvent()
+const eventShort = created.event()
+const eventImported = importedDomain.event('name')
+const effect = created.createEffect(() => 0)
+const effectShort = created.effect({
+  handler: () => 0,
+})
+const effectImported = importedDomain.effect(() => 0, {
+  name: 'name',
+})
+const store = created.createStore(0)
+const storeShort = created.store(0, {
+  name: 'short',
+})
+const storeImported = importedDomain.store('value')
+const domain = created.createDomain()
+const domainShort = created.domain('name')
+const domainImported = importedDomain.domain()
+createDomain(
+  {
+    name: 'second',
+    domain: created,
+  },
+  {
+    sid: '8ugyqx',
+  },
+)
+"
+`;
+
 exports[`babel-plugin should create domain store 1`] = `
 "var _effectorFileName = '/src/babel/__tests__/fixtures/create-domain-store.js'
 import {createDomain} from 'effector'
diff --git a/src/babel/__tests__/fixtures/create-domain-no-legacy-methods.js b/src/babel/__tests__/fixtures/create-domain-no-legacy-methods.js
new file mode 100644
index 00000000..39fda8e9
--- /dev/null
+++ b/src/babel/__tests__/fixtures/create-domain-no-legacy-methods.js
@@ -0,0 +1,22 @@
+import {createDomain} from 'effector'
+import {importedDomain} from './local-file'
+
+const created = createDomain('created')
+
+const event = created.createEvent()
+const eventShort = created.event()
+const eventImported = importedDomain.event('name')
+
+const effect = created.createEffect(() => 0)
+const effectShort = created.effect({handler: () => 0})
+const effectImported = importedDomain.effect(() => 0, {name: 'name'})
+
+const store = created.createStore(0)
+const storeShort = created.store(0, {name: 'short'})
+const storeImported = importedDomain.store('value')
+
+const domain = created.createDomain()
+const domainShort = created.domain('name')
+const domainImported = importedDomain.domain()
+
+createDomain({name: 'second', domain: created})
diff --git a/src/babel/__tests__/fixtures/create-domain-no-legacy-methods.options.json b/src/babel/__tests__/fixtures/create-domain-no-legacy-methods.options.json
new file mode 100644
index 00000000..65a7b991
--- /dev/null
+++ b/src/babel/__tests__/fixtures/create-domain-no-legacy-methods.options.json
@@ -0,0 +1,3 @@
+{
+  "transformLegacyDomainMethods": false
+}
\ No newline at end of file