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

View File

@@ -0,0 +1,5 @@
/**
* @hidden
*/
export declare function logAndExitProcess(error: Error): void;
//# sourceMappingURL=errorhandling.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"errorhandling.d.ts","sourceRoot":"","sources":["../../../../src/integrations/utils/errorhandling.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAuBpD"}

View File

@@ -0,0 +1,26 @@
import { getCurrentHub } from '@sentry/core';
import { forget, logger } from '@sentry/utils';
import { IS_DEBUG_BUILD } from '../../flags';
var DEFAULT_SHUTDOWN_TIMEOUT = 2000;
/**
* @hidden
*/
export function logAndExitProcess(error) {
// eslint-disable-next-line no-console
console.error(error && error.stack ? error.stack : error);
var client = getCurrentHub().getClient();
if (client === undefined) {
IS_DEBUG_BUILD && logger.warn('No NodeClient was defined, we are exiting the process now.');
global.process.exit(1);
}
var options = client.getOptions();
var timeout = (options && options.shutdownTimeout && options.shutdownTimeout > 0 && options.shutdownTimeout) ||
DEFAULT_SHUTDOWN_TIMEOUT;
forget(client.close(timeout).then(function (result) {
if (!result) {
IS_DEBUG_BUILD && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!');
}
global.process.exit(1);
}));
}
//# sourceMappingURL=errorhandling.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"errorhandling.js","sourceRoot":"","sources":["../../../../src/integrations/utils/errorhandling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,IAAM,wBAAwB,GAAG,IAAI,CAAC;AAEtC;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAY;IAC5C,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAE1D,IAAM,MAAM,GAAG,aAAa,EAAE,CAAC,SAAS,EAAc,CAAC;IAEvD,IAAI,MAAM,KAAK,SAAS,EAAE;QACxB,cAAc,IAAI,MAAM,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;QAC5F,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACxB;IAED,IAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACpC,IAAM,OAAO,GACX,CAAC,OAAO,IAAI,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,eAAe,GAAG,CAAC,IAAI,OAAO,CAAC,eAAe,CAAC;QAC9F,wBAAwB,CAAC;IAC3B,MAAM,CACJ,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAC,MAAe;QACzC,IAAI,CAAC,MAAM,EAAE;YACX,cAAc,IAAI,MAAM,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;SAC7G;QACD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["import { getCurrentHub } from '@sentry/core';\nimport { forget, logger } from '@sentry/utils';\n\nimport { NodeClient } from '../../client';\nimport { IS_DEBUG_BUILD } from '../../flags';\n\nconst DEFAULT_SHUTDOWN_TIMEOUT = 2000;\n\n/**\n * @hidden\n */\nexport function logAndExitProcess(error: Error): void {\n // eslint-disable-next-line no-console\n console.error(error && error.stack ? error.stack : error);\n\n const client = getCurrentHub().getClient<NodeClient>();\n\n if (client === undefined) {\n IS_DEBUG_BUILD && logger.warn('No NodeClient was defined, we are exiting the process now.');\n global.process.exit(1);\n }\n\n const options = client.getOptions();\n const timeout =\n (options && options.shutdownTimeout && options.shutdownTimeout > 0 && options.shutdownTimeout) ||\n DEFAULT_SHUTDOWN_TIMEOUT;\n forget(\n client.close(timeout).then((result: boolean) => {\n if (!result) {\n IS_DEBUG_BUILD && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!');\n }\n global.process.exit(1);\n }),\n );\n}\n"]}

View File

@@ -0,0 +1,64 @@
/// <reference types="node" />
import * as http from 'http';
import * as https from 'https';
import { URL } from 'url';
/**
* Checks whether given url points to Sentry server
* @param url url to verify
*/
export declare function isSentryRequest(url: string): boolean;
/**
* Assemble a URL to be used for breadcrumbs and spans.
*
* @param requestOptions RequestOptions object containing the component parts for a URL
* @returns Fully-formed URL
*/
export declare function extractUrl(requestOptions: RequestOptions): string;
/**
* Handle various edge cases in the span description (for spans representing http(s) requests).
*
* @param description current `description` property of the span representing the request
* @param requestOptions Configuration data for the request
* @param Request Request object
*
* @returns The cleaned description
*/
export declare function cleanSpanDescription(description: string | undefined, requestOptions: RequestOptions, request: http.ClientRequest): string | undefined;
export declare type RequestOptions = http.RequestOptions & {
hash?: string;
search?: string;
pathname?: string;
href?: string;
};
declare type RequestCallback = (response: http.IncomingMessage) => void;
export declare type RequestMethodArgs = [RequestOptions | string | URL, RequestCallback?] | [string | URL, RequestOptions, RequestCallback?];
export declare type RequestMethod = (...args: RequestMethodArgs) => http.ClientRequest;
/**
* Convert a URL object into a RequestOptions object.
*
* Copied from Node's internals (where it's used in http(s).request() and http(s).get()), modified only to use the
* RequestOptions type above.
*
* See https://github.com/nodejs/node/blob/master/lib/internal/url.js.
*/
export declare function urlToOptions(url: URL): RequestOptions;
/**
* Normalize inputs to `http(s).request()` and `http(s).get()`.
*
* Legal inputs to `http(s).request()` and `http(s).get()` can take one of ten forms:
* [ RequestOptions | string | URL ],
* [ RequestOptions | string | URL, RequestCallback ],
* [ string | URL, RequestOptions ], and
* [ string | URL, RequestOptions, RequestCallback ].
*
* This standardizes to one of two forms: [ RequestOptions ] and [ RequestOptions, RequestCallback ]. A similar thing is
* done as the first step of `http(s).request()` and `http(s).get()`; this just does it early so that we can interact
* with the args in a standard way.
*
* @param requestArgs The inputs to `http(s).request()` or `http(s).get()`, as an array.
*
* @returns Equivalent args of the form [ RequestOptions ] or [ RequestOptions, RequestCallback ].
*/
export declare function normalizeRequestArgs(httpModule: typeof http | typeof https, requestArgs: RequestMethodArgs): [RequestOptions] | [RequestOptions, RequestCallback];
export {};
//# sourceMappingURL=http.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../../src/integrations/utils/http.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAI1B;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,cAAc,EAAE,cAAc,GAAG,MAAM,CASjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,IAAI,CAAC,aAAa,GAC1B,MAAM,GAAG,SAAS,CAuBpB;AAGD,oBAAY,cAAc,GAAG,IAAI,CAAC,cAAc,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACxH,aAAK,eAAe,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,eAAe,KAAK,IAAI,CAAC;AAChE,oBAAY,iBAAiB,GACzB,CAAC,cAAc,GAAG,MAAM,GAAG,GAAG,EAAE,eAAe,CAAC,CAAC,GACjD,CAAC,MAAM,GAAG,GAAG,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC;AACrD,oBAAY,aAAa,GAAG,CAAC,GAAG,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC,aAAa,CAAC;AAE/E;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,cAAc,CAkBrD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,OAAO,IAAI,GAAG,OAAO,KAAK,EACtC,WAAW,EAAE,iBAAiB,GAC7B,CAAC,cAAc,CAAC,GAAG,CAAC,cAAc,EAAE,eAAe,CAAC,CAoDtD"}

View File

@@ -0,0 +1,150 @@
import { __assign, __read } from "tslib";
import { getCurrentHub } from '@sentry/core';
import { parseSemver } from '@sentry/utils';
import { URL } from 'url';
var NODE_VERSION = parseSemver(process.versions.node);
/**
* Checks whether given url points to Sentry server
* @param url url to verify
*/
export function isSentryRequest(url) {
var _a;
var dsn = (_a = getCurrentHub().getClient()) === null || _a === void 0 ? void 0 : _a.getDsn();
return dsn ? url.includes(dsn.host) : false;
}
/**
* Assemble a URL to be used for breadcrumbs and spans.
*
* @param requestOptions RequestOptions object containing the component parts for a URL
* @returns Fully-formed URL
*/
export function extractUrl(requestOptions) {
var protocol = requestOptions.protocol || '';
var hostname = requestOptions.hostname || requestOptions.host || '';
// Don't log standard :80 (http) and :443 (https) ports to reduce the noise
var port = !requestOptions.port || requestOptions.port === 80 || requestOptions.port === 443 ? '' : ":" + requestOptions.port;
var path = requestOptions.path ? requestOptions.path : '/';
return protocol + "//" + hostname + port + path;
}
/**
* Handle various edge cases in the span description (for spans representing http(s) requests).
*
* @param description current `description` property of the span representing the request
* @param requestOptions Configuration data for the request
* @param Request Request object
*
* @returns The cleaned description
*/
export function cleanSpanDescription(description, requestOptions, request) {
var _a, _b, _c;
// nothing to clean
if (!description) {
return description;
}
// eslint-disable-next-line prefer-const
var _d = __read(description.split(' '), 2), method = _d[0], requestUrl = _d[1];
// superagent sticks the protocol in a weird place (we check for host because if both host *and* protocol are missing,
// we're likely dealing with an internal route and this doesn't apply)
if (requestOptions.host && !requestOptions.protocol) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
requestOptions.protocol = (_b = (_a = request) === null || _a === void 0 ? void 0 : _a.agent) === null || _b === void 0 ? void 0 : _b.protocol; // worst comes to worst, this is undefined and nothing changes
requestUrl = extractUrl(requestOptions);
}
// internal routes can end up starting with a triple slash rather than a single one
if ((_c = requestUrl) === null || _c === void 0 ? void 0 : _c.startsWith('///')) {
requestUrl = requestUrl.slice(2);
}
return method + " " + requestUrl;
}
/**
* Convert a URL object into a RequestOptions object.
*
* Copied from Node's internals (where it's used in http(s).request() and http(s).get()), modified only to use the
* RequestOptions type above.
*
* See https://github.com/nodejs/node/blob/master/lib/internal/url.js.
*/
export function urlToOptions(url) {
var options = {
protocol: url.protocol,
hostname: typeof url.hostname === 'string' && url.hostname.startsWith('[') ? url.hostname.slice(1, -1) : url.hostname,
hash: url.hash,
search: url.search,
pathname: url.pathname,
path: "" + (url.pathname || '') + (url.search || ''),
href: url.href,
};
if (url.port !== '') {
options.port = Number(url.port);
}
if (url.username || url.password) {
options.auth = url.username + ":" + url.password;
}
return options;
}
/**
* Normalize inputs to `http(s).request()` and `http(s).get()`.
*
* Legal inputs to `http(s).request()` and `http(s).get()` can take one of ten forms:
* [ RequestOptions | string | URL ],
* [ RequestOptions | string | URL, RequestCallback ],
* [ string | URL, RequestOptions ], and
* [ string | URL, RequestOptions, RequestCallback ].
*
* This standardizes to one of two forms: [ RequestOptions ] and [ RequestOptions, RequestCallback ]. A similar thing is
* done as the first step of `http(s).request()` and `http(s).get()`; this just does it early so that we can interact
* with the args in a standard way.
*
* @param requestArgs The inputs to `http(s).request()` or `http(s).get()`, as an array.
*
* @returns Equivalent args of the form [ RequestOptions ] or [ RequestOptions, RequestCallback ].
*/
export function normalizeRequestArgs(httpModule, requestArgs) {
var _a, _b, _c, _d, _e, _f, _g, _h;
var callback, requestOptions;
// pop off the callback, if there is one
if (typeof requestArgs[requestArgs.length - 1] === 'function') {
callback = requestArgs.pop();
}
// create a RequestOptions object of whatever's at index 0
if (typeof requestArgs[0] === 'string') {
requestOptions = urlToOptions(new URL(requestArgs[0]));
}
else if (requestArgs[0] instanceof URL) {
requestOptions = urlToOptions(requestArgs[0]);
}
else {
requestOptions = requestArgs[0];
}
// if the options were given separately from the URL, fold them in
if (requestArgs.length === 2) {
requestOptions = __assign(__assign({}, requestOptions), requestArgs[1]);
}
// Figure out the protocol if it's currently missing
if (requestOptions.protocol === undefined) {
// Worst case we end up populating protocol with undefined, which it already is
/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */
// NOTE: Prior to Node 9, `https` used internals of `http` module, thus we don't patch it.
// Because of that, we cannot rely on `httpModule` to provide us with valid protocol,
// as it will always return `http`, even when using `https` module.
//
// See test/integrations/http.test.ts for more details on Node <=v8 protocol issue.
if (NODE_VERSION.major && NODE_VERSION.major > 8) {
requestOptions.protocol =
((_b = (_a = httpModule) === null || _a === void 0 ? void 0 : _a.globalAgent) === null || _b === void 0 ? void 0 : _b.protocol) || ((_c = requestOptions.agent) === null || _c === void 0 ? void 0 : _c.protocol) || ((_d = requestOptions._defaultAgent) === null || _d === void 0 ? void 0 : _d.protocol);
}
else {
requestOptions.protocol =
((_e = requestOptions.agent) === null || _e === void 0 ? void 0 : _e.protocol) || ((_f = requestOptions._defaultAgent) === null || _f === void 0 ? void 0 : _f.protocol) || ((_h = (_g = httpModule) === null || _g === void 0 ? void 0 : _g.globalAgent) === null || _h === void 0 ? void 0 : _h.protocol);
}
/* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any */
}
// return args in standardized form
if (callback) {
return [requestOptions, callback];
}
else {
return [requestOptions];
}
}
//# sourceMappingURL=http.js.map

File diff suppressed because one or more lines are too long