Files
formipay/node_modules/find-process/lib/find_pid.js
dwindown e8fbfb14c1 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>
2026-04-18 17:02:14 +07:00

212 lines
6.3 KiB
JavaScript

/*
* @Author: zoujie.wzj
* @Date: 2016-01-22 19:27:17
* @Last Modified by: Ayon Lee
* @Last Modified on: 2018-10-19
*/
'use strict'
// find pid by port
const os = require('os')
const fs = require('fs')
const utils = require('./utils')
const log = require('./logger')
const ensureDir = (path) => new Promise((resolve, reject) => {
if (fs.existsSync(path)) {
resolve()
} else {
fs.mkdir(path, err => {
err ? reject(err) : resolve()
})
}
})
const finders = {
darwin (port) {
return new Promise((resolve, reject) => {
utils.exec('netstat -anv -p TCP && netstat -anv -p UDP', function (err, stdout, stderr) {
if (err) {
reject(err)
} else {
err = stderr.toString().trim()
if (err) {
reject(err)
return
}
// Drop group header, e.g. "Active Internet connections"
const table = utils.stripLine(stdout.toString(), 1)
// Get the next line with the column headers
const headers = table.slice(0, table.indexOf('\n'))
// Drop the header line to get the table body
const body = utils.stripLine(table, 1)
// In macOS >=Sequoia, columns include `rxbytes` and `txbytes`, which
// shifts the PID column to index 10. Detect this with a search
// for rxbytes. (Parsing the headers more robustly isn't possible
// because some colmn names contain spaces, and others are only separated
// by a single space.)
const pidColumn = headers.indexOf('rxbytes') >= 0 ? 10 : 8
const found = utils.extractColumns(body, [0, 3, pidColumn], 10)
.filter(row => {
return !!String(row[0]).match(/^(udp|tcp)/)
})
.find(row => {
const matches = String(row[1]).match(/\.(\d+)$/)
if (matches && matches[1] === String(port)) {
return true
}
return false
})
if (found && found[2].length) {
resolve(parseInt(found[2], 10))
} else {
reject(new Error(`pid of port (${port}) not found`))
}
}
})
})
},
freebsd: 'darwin',
sunos: 'darwin',
linux (port) {
return new Promise((resolve, reject) => {
const cmd = 'netstat -tunlp'
utils.exec(cmd, function (err, stdout, stderr) {
if (err) {
reject(err)
} else {
const warn = stderr.toString().trim()
if (warn) {
// netstat -p ouputs warning if user is no-root
log.warn(warn)
}
// replace header
const data = utils.stripLine(stdout.toString(), 2)
const columns = utils.extractColumns(data, [3, 6], 7).find(column => {
const matches = String(column[0]).match(/:(\d+)$/)
if (matches && matches[1] === String(port)) {
return true
}
return false
})
if (columns && columns[1]) {
const pid = columns[1].split('/', 1)[0]
if (pid.length) {
resolve(parseInt(pid, 10))
} else {
reject(new Error(`pid of port (${port}) not found`))
}
} else {
reject(new Error(`pid of port (${port}) not found`))
}
}
})
})
},
win32 (port) {
return new Promise((resolve, reject) => {
utils.exec('netstat -ano', function (err, stdout, stderr) {
if (err) {
reject(err)
} else {
err = stderr.toString().trim()
if (err) {
reject(err)
return
}
// replace header
const data = utils.stripLine(stdout.toString(), 4)
const columns = utils.extractColumns(data, [1, 4], 5).find(column => {
const matches = String(column[0]).match(/:(\d+)$/)
if (matches && matches[1] === String(port)) {
return true
}
return false
})
if (columns && columns[1].length && parseInt(columns[1], 10) > 0) {
resolve(parseInt(columns[1], 10))
} else {
reject(new Error(`pid of port (${port}) not found`))
}
}
})
})
},
android (port) {
return new Promise((resolve, reject) => {
// on Android Termux, an warning will be emitted when executing `netstat`
// with option `-p` says 'showing only processes with your user ID', but
// it can still fetch the information we need. However, NodeJS treat this
// warning as an error, `util.exec()` will get nothing but the error. To
// get the true output of the command, we need to save it to a tmpfile and
// read that file instead.
const dir = os.tmpdir() + '/.find-process'
const file = dir + '/' + process.pid
const cmd = 'netstat -tunp >> "' + file + '"'
ensureDir(dir).then(() => {
utils.exec(cmd, () => {
fs.readFile(file, 'utf8', (err, data) => {
fs.unlink(file, () => { })
if (err) {
reject(err)
} else {
data = utils.stripLine(data, 2)
const columns = utils.extractColumns(data, [3, 6], 7).find(column => {
const matches = String(column[0]).match(/:(\d+)$/)
if (matches && matches[1] === String(port)) {
return true
}
return false
})
if (columns && columns[1]) {
const pid = columns[1].split('/', 1)[0]
if (pid.length) {
resolve(parseInt(pid, 10))
} else {
reject(new Error(`pid of port (${port}) not found`))
}
} else {
reject(new Error(`pid of port (${port}) not found`))
}
}
})
})
})
})
}
}
function findPidByPort (port) {
const platform = process.platform
return new Promise((resolve, reject) => {
if (!(platform in finders)) {
return reject(new Error(`platform ${platform} is unsupported`))
}
let findPid = finders[platform]
if (typeof findPid === 'string') {
findPid = finders[findPid]
}
findPid(port).then(resolve, reject)
})
}
module.exports = findPidByPort