fix: prevent asset conflicts between React and Grid.js versions

Add coexistence checks to all enqueue methods to prevent loading
both React and Grid.js assets simultaneously.

Changes:
- ReactAdmin.php: Only enqueue React assets when ?react=1
- Init.php: Skip Grid.js when React active on admin pages
- Form.php, Coupon.php, Access.php: Restore classic assets when ?react=0
- Customer.php, Product.php, License.php: Add coexistence checks

Now the toggle between Classic and React versions works correctly.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
dwindown
2026-04-18 17:02:14 +07:00
parent bd9cdac02e
commit e8fbfb14c1
74973 changed files with 6658406 additions and 71 deletions

21
node_modules/resolve-bin/.github/workflows/test.yml generated vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Tests
on:
push:
branches:
- master
pull_request:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- '0.10.x'
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test

11
node_modules/resolve-bin/.jshintrc generated vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"laxcomma" : true
, "laxbreak" : true
, "sub" : true
, "onecase" : true
, "node" : true
, "expr" : true
, "strict" : false
, "validthis" : true
, "asi" : true
}

23
node_modules/resolve-bin/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,23 @@
Copyright 2013 Thorsten Lorenz.
All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

198
node_modules/resolve-bin/README.md generated vendored Normal file
View File

@@ -0,0 +1,198 @@
# resolve-bin [![build status](https://secure.travis-ci.org/thlorenz/resolve-bin.png)](http://travis-ci.org/thlorenz/resolve-bin)
Resolves the full path to the bin file of a given package by inspecting the `"bin"` field in its package.json.
```js
var resolveBin = require('resolve-bin');
// package.json: "bin": "bin/tap.js"
resolveBin('tap', function (err, bin) {
if (err) return console.error(err);
console.log(bin);
});
// => [..]/resolve-bin/node_modules/tap/bin/tap.js
```
## Installation
npm install resolve-bin
## API
<!-- START docme generated API please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN docme TO UPDATE -->
<div>
<div class="jsdoc-githubify">
<section>
<article>
<div class="container-overview">
<dl class="details">
</dl>
</div>
<dl>
<dt>
<h4 class="name" id="resolveBin"><span class="type-signature"></span>resolveBin<span class="signature">(name, <span class="optional">opts</span>, cb)</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
<p>Resolves the full path to the bin file of a given package by inspecting the &quot;bin&quot; field in its package.json.</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Argument</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>name</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="attributes">
</td>
<td class="description last"><p>module name, i.e. 'tap'</p></td>
</tr>
<tr>
<td class="name"><code>opts</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="attributes">
&lt;optional><br>
</td>
<td class="description last"><p>options</p>
<h6>Properties</h6>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>executable</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="description last"><p>(default: @name) executable name (e.g. 'buster-test')</p></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td class="name"><code>cb</code></td>
<td class="type">
<span class="param-type">function</span>
</td>
<td class="attributes">
</td>
<td class="description last"><p>called back with the full path to the bin file of the module or an error if it couldn't be resolved</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy">
<li>
<a href="https://github.com/thlorenz/resolve-bin/blob/master/index.js">index.js</a>
<span>, </span>
<a href="https://github.com/thlorenz/resolve-bin/blob/master/index.js#L6">lineno 6</a>
</li>
</ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="resolveBin::sync"><span class="type-signature"></span>resolveBin::sync<span class="signature">(name, <span class="optional">opts</span>)</span><span class="type-signature"> &rarr; {string}</span></h4>
</dt>
<dd>
<div class="description">
<p>Synchronous version of resolveBin</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Argument</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>name</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="attributes">
</td>
<td class="description last"><p>module name, i.e. 'tap'</p></td>
</tr>
<tr>
<td class="name"><code>opts</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="attributes">
&lt;optional><br>
</td>
<td class="description last"><p>options</p>
<h6>Properties</h6>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>executable</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="description last"><p>(default: @name) executable name (e.g. 'buster-test')</p></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy">
<li>
<a href="https://github.com/thlorenz/resolve-bin/blob/master/index.js">index.js</a>
<span>, </span>
<a href="https://github.com/thlorenz/resolve-bin/blob/master/index.js#L55">lineno 55</a>
</li>
</ul></dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
*generated with [docme](https://github.com/thlorenz/docme)*
</div>
<!-- END docme generated API please keep comment here to allow auto update -->
## License
MIT

View File

@@ -0,0 +1,31 @@
'use strict';
var resolveBin = require('..');
// package.json:
// "bin": {
// "dependency-cruiser": "bin/dependency-cruise.js",
// "dependency-cruise": "bin/dependency-cruise.js",
// "depcruise": "bin/dependency-cruise.js",
// "depcruise-fmt": "bin/depcruise-fmt.js",
// "depcruise-wrap-stream-in-html": "bin/wrap-stream-in-html.js"
// },
resolveBin('dependency-cruiser', function (err, bin) {
if (err) return console.error(err);
console.log(bin);
});
// => [..]/resolve-bin/node_modules/dependency-cruiser/bin/dependency-cruise.js
resolveBin('dependency-cruiser', {executable:"depcruise"}, function (err, bin) {
if (err) return console.error(err);
console.log(bin);
});
// => [..]/resolve-bin/node_modules/dependency-cruiser/bin/dependency-cruise.js
var path = resolveBin.sync('dependency-cruiser', { executable: 'depcruise' });
console.log(path);
// => [..]/resolve-bin/node_modules/dependency-cruiser/bin/dependency-cruise.js

23
node_modules/resolve-bin/examples/mocha.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
'use strict';
var resolveBin = require('../');
// package.json:
// "bin": {
// "mocha": "./bin/mocha",
// "_mocha": "./bin/_mocha"
// },
resolveBin('mocha', function (err, bin) {
if (err) return console.error(err);
console.log(bin);
});
// => [..]/resolve-bin/node_modules/mocha/bin/mocha
resolveBin('mocha', { executable: '_mocha' }, function (err, bin) {
if (err) return console.error(err);
console.log(bin);
});
// => [..]/resolve-bin/node_modules/mocha/bin/_mocha

27
node_modules/resolve-bin/examples/open-cli.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
'use strict';
var resolveBin = require('../');
// package.json:
// "bin": {
// "open-cli": "cli.js"
// },
resolveBin('open-cli', function (err, bin) {
if (err) return console.error(err);
console.log(bin);
});
// => [..]/resolve-bin/node_modules/open-cli/cli.js
resolveBin('open-cli', { executable: 'open-cli' }, function (err, bin) {
if (err) return console.error(err);
console.log(bin);
});
// => [..]/resolve-bin/node_modules/open-cli/cli.js
console.log(resolveBin.sync('open-cli'));
// => [..]/resolve-bin/node_modules/open-cli/cli.js

11
node_modules/resolve-bin/examples/tap.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
'use strict';
var resolveBin = require('../');
// package.json: "bin": "bin/tap.js"
resolveBin('tap', function (err, bin) {
if (err) return console.error(err);
console.log(bin);
});
// => [..]/resolve-bin/node_modules/tap/bin/tap.js

80
node_modules/resolve-bin/index.js generated vendored Normal file
View File

@@ -0,0 +1,80 @@
'use strict';
var findParentDir = require('find-parent-dir');
var path = require('path');
function requireResolve(name) {
try {
return require.resolve(name);
} catch (err) {
var modJson = require.resolve(name+"/package.json");
return path.dirname(modJson)
}
}
/**
* Resolves the full path to the bin file of a given package by inspecting the "bin" field in its package.json.
*
* @name resolveBin
* @function
* @param {string} name module name, i.e. 'tap'
* @param {Object=} opts options
* @param {string} opts.executable (default: @name) executable name (e.g. 'buster-test')
* @param {function} cb called back with the full path to the bin file of the module or an error if it couldn't be resolved
*/
module.exports = function (name, opts, cb) {
if (typeof opts === "function") {
cb = opts;
opts = {};
}
var executable = opts.executable || name;
var mod;
try {
mod = requireResolve(name);
} catch (err) {
return cb(err);
}
findParentDir(mod, 'package.json', function (err, dir) {
if (err) return cb(err);
var pack = require(path.join(dir, 'package.json'));
var binfield = pack.bin;
var binpath = typeof binfield === 'object' ? binfield[executable] : binfield;
if (!binpath) return cb(new Error("No bin `" + executable + "` in module `" + name + "`"));
var bin = path.join(dir, binpath);
cb(null, bin);
});
}
/**
* Resolves the full path to the bin file of a given package by inspecting the "bin" field in its package.json.
*
* @name resolveBin.sync
* @function
* @param {string} name module name, i.e. 'tap'
* @param {Object=} opts options
* @param {string} opts.executable (default: @name) executable name (e.g. 'buster-test')
* @returns {string}
*/
module.exports.sync = function sync (name, opts) {
opts = opts || {};
var executable = opts.executable || name;
var mod = requireResolve(name);
var dir = findParentDir.sync(mod, 'package.json')
var pack = require(path.join(dir, 'package.json'));
var binfield = pack.bin;
var binpath = typeof binfield === 'object' ? binfield[executable] : binfield;
if (!binpath) throw new Error("No bin `" + executable + "` in module `" + name + "`");
return path.join(dir, binpath);
}

40
node_modules/resolve-bin/package.json generated vendored Normal file
View File

@@ -0,0 +1,40 @@
{
"name": "resolve-bin",
"version": "0.4.3",
"description": "Resolves the full path to the bin file of a given package by inspecting the \"bin\" field in its package.json.",
"main": "index.js",
"scripts": {
"test": "tap test/*.js"
},
"repository": {
"type": "git",
"url": "git://github.com/thlorenz/resolve-bin.git"
},
"homepage": "https://github.com/thlorenz/resolve-bin",
"dependencies": {
"find-parent-dir": "~0.3.0"
},
"devDependencies": {
"dependency-cruiser": "^10.0.1",
"mocha": "~1.14.0",
"open-cli": "^6.0.1",
"tap": "~0.4.3"
},
"keywords": [
"resolve",
"bin",
"module"
],
"author": {
"name": "Thorsten Lorenz",
"email": "thlorenz@gmx.de",
"url": "http://thlorenz.com"
},
"license": {
"type": "MIT",
"url": "https://github.com/thlorenz/resolve-bin/blob/master/LICENSE"
},
"engine": {
"node": ">=0.6"
}
}

108
node_modules/resolve-bin/test/index.js generated vendored Normal file
View File

@@ -0,0 +1,108 @@
'use strict';
/*jshint asi: true */
var test = require('tap').test
var path = require('path')
var resolveBin = require('../');
function relative(dir) {
return path.relative(path.join(__dirname, '..'), dir)
}
test('\ntap', function (t) {
resolveBin('tap', function (err, bin) {
if (err) return t.fail(err);
t.equal(relative(bin), 'node_modules/tap/bin/tap.js')
t.end()
});
})
test('\ntap sync', function (t) {
var bin = resolveBin.sync('tap');
t.equal(relative(bin), 'node_modules/tap/bin/tap.js');
t.end();
})
test('\nmocha', function (t) {
resolveBin('mocha', function (err, bin) {
if (err) return t.fail(err);
t.equal(relative(bin), 'node_modules/mocha/bin/mocha')
t.end()
});
})
test('\n_mocha', function (t) {
resolveBin('mocha', { executable: "_mocha" }, function (err, bin) {
if (err) throw err;
t.equal(relative(bin), 'node_modules/mocha/bin/_mocha')
t.end()
});
})
test('\nno `executable` in options', function (t) {
resolveBin('mocha', {}, function (err, bin) {
if (err) throw err;
t.equal(relative(bin), 'node_modules/mocha/bin/mocha')
t.end()
});
})
test('\nnon-existent module', function (t) {
resolveBin('non-existent', function (err, bin) {
t.ok(err, 'returns error')
t.equal(err.code, 'MODULE_NOT_FOUND', 'saying module not found')
t.similar(err.message, /non-existent/, 'stating module name')
t.end()
});
})
test('\nnon-existent module sync', function (t) {
t.throws(function () {
resolveBin.sync('non-existent')
})
t.end()
})
test('\nnon-existent executable inside module', function (t) {
resolveBin('mocha', { executable: "no-such-bin" }, function (err, bin) {
t.ok(err, 'returns error')
t.similar(err.message, /no bin/i, 'stating module name')
t.end()
});
})
test('\nopen-cli (without "main" field in package.json)', function (t) {
resolveBin('open-cli', function (err, bin) {
if (err) return t.fail(err);
t.equal(relative(bin), 'node_modules/open-cli/cli.js')
t.end()
});
})
test('\nopen-cli (without "main" field in package.json), sync', function (t) {
var bin = resolveBin.sync('open-cli');
t.equal(relative(bin), 'node_modules/open-cli/cli.js')
t.end()
})
test('\ndependency-cruise (cannot import package.json)', function (t) {
resolveBin('dependency-cruiser', function (err, bin) {
if (err) return t.fail(err);
t.equal(relative(bin), 'node_modules/dependency-cruiser/bin/dependency-cruise.js')
t.end()
});
})
test('\ndependency-cruise (cannot import package.json)', function (t) {
resolveBin('dependency-cruiser', {executable:"depcruise"}, function (err, bin) {
if (err) return t.fail(err);
t.equal(relative(bin), 'node_modules/dependency-cruiser/bin/dependency-cruise.js')
t.end()
});
})
test('\ndependency-cruise (cannot import package.json)', function (t) {
var bin = resolveBin.sync('dependency-cruiser');
t.equal(relative(bin), 'node_modules/dependency-cruiser/bin/dependency-cruise.js')
t.end()
})