x
This commit is contained in:
62
frontend/scripts/ensure-native-bindings.mjs
Normal file
62
frontend/scripts/ensure-native-bindings.mjs
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* When optional native deps (e.g. @tailwindcss/oxide-*) fail to install (permissions, npm bugs),
|
||||
* fetch the correct platform package via npm pack and copy the .node file into vendor/.
|
||||
*/
|
||||
import { execSync } from 'node:child_process'
|
||||
import { copyFileSync, existsSync, mkdirSync, readdirSync, rmSync } from 'node:fs'
|
||||
import { join, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
const root = join(__dirname, '..')
|
||||
const vendorDir = join(root, 'vendor')
|
||||
|
||||
function isMusl() {
|
||||
try {
|
||||
return execSync('ldd --version', { encoding: 'utf8' }).includes('musl')
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function detectLinuxX64Oxide() {
|
||||
if (process.platform !== 'linux' || process.arch !== 'x64') return null
|
||||
return isMusl()
|
||||
? { pkg: '@tailwindcss/oxide-linux-x64-musl', version: '4.2.2', nodeName: 'tailwindcss-oxide.linux-x64-musl.node' }
|
||||
: { pkg: '@tailwindcss/oxide-linux-x64-gnu', version: '4.2.2', nodeName: 'tailwindcss-oxide.linux-x64-gnu.node' }
|
||||
}
|
||||
|
||||
function tryResolveOxidePackage(spec) {
|
||||
const sub = spec.pkg.replace('@tailwindcss/', '')
|
||||
const direct = join(root, 'node_modules', '@tailwindcss', sub, 'package.json')
|
||||
if (existsSync(direct)) return true
|
||||
return false
|
||||
}
|
||||
|
||||
function ensure() {
|
||||
const spec = detectLinuxX64Oxide()
|
||||
if (!spec) return
|
||||
|
||||
if (tryResolveOxidePackage(spec)) return
|
||||
|
||||
const outPath = join(vendorDir, spec.nodeName)
|
||||
if (existsSync(outPath)) return
|
||||
|
||||
mkdirSync(vendorDir, { recursive: true })
|
||||
const tmp = join(__dirname, '.native-tmp')
|
||||
rmSync(tmp, { recursive: true, force: true })
|
||||
mkdirSync(tmp, { recursive: true })
|
||||
|
||||
execSync(`npm pack ${spec.pkg}@${spec.version}`, { cwd: tmp, stdio: 'inherit' })
|
||||
const tgz = readdirSync(tmp).find((f) => f.endsWith('.tgz'))
|
||||
if (!tgz) throw new Error('ensure-native-bindings: npm pack produced no .tgz')
|
||||
execSync(`tar -xzf "${tgz}"`, { cwd: tmp, stdio: 'inherit' })
|
||||
const nodeSrc = join(tmp, 'package', spec.nodeName)
|
||||
if (!existsSync(nodeSrc)) {
|
||||
throw new Error(`ensure-native-bindings: missing ${nodeSrc}`)
|
||||
}
|
||||
copyFileSync(nodeSrc, outPath)
|
||||
rmSync(tmp, { recursive: true, force: true })
|
||||
}
|
||||
|
||||
ensure()
|
||||
14
frontend/scripts/run-build-inner.mjs
Normal file
14
frontend/scripts/run-build-inner.mjs
Normal file
@@ -0,0 +1,14 @@
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
|
||||
function run(scriptArgs) {
|
||||
const r = spawnSync(process.execPath, scriptArgs, { stdio: 'inherit', cwd: root })
|
||||
if (r.status !== 0) process.exit(r.status ?? 1)
|
||||
}
|
||||
|
||||
run([join(root, 'scripts', 'ensure-native-bindings.mjs')])
|
||||
run([join(root, 'node_modules/typescript/bin/tsc'), '-b'])
|
||||
run([join(root, 'node_modules/vite/bin/vite.js'), 'build'])
|
||||
21
frontend/scripts/run-build.mjs
Normal file
21
frontend/scripts/run-build.mjs
Normal file
@@ -0,0 +1,21 @@
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const major = parseInt(process.versions.node.split('.')[0], 10)
|
||||
|
||||
if (major >= 20) {
|
||||
const r = spawnSync(process.execPath, [join(root, 'scripts', 'run-build-inner.mjs')], {
|
||||
stdio: 'inherit',
|
||||
cwd: root,
|
||||
})
|
||||
process.exit(r.status ?? 1)
|
||||
}
|
||||
|
||||
const r = spawnSync(
|
||||
'npx',
|
||||
['-y', '-p', 'node@20', 'node', join(root, 'scripts', 'run-build-inner.mjs')],
|
||||
{ stdio: 'inherit', cwd: root, shell: false },
|
||||
)
|
||||
process.exit(r.status ?? 1)
|
||||
17
frontend/scripts/run-dev-inner.mjs
Normal file
17
frontend/scripts/run-dev-inner.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
|
||||
const ensure = spawnSync(process.execPath, [join(root, 'scripts', 'ensure-native-bindings.mjs')], {
|
||||
stdio: 'inherit',
|
||||
cwd: root,
|
||||
})
|
||||
if (ensure.status !== 0) process.exit(ensure.status ?? 1)
|
||||
|
||||
const vite = spawnSync(process.execPath, [join(root, 'node_modules/vite/bin/vite.js')], {
|
||||
stdio: 'inherit',
|
||||
cwd: root,
|
||||
})
|
||||
process.exit(vite.status ?? 1)
|
||||
13
frontend/scripts/run-dev.mjs
Normal file
13
frontend/scripts/run-dev.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const inner = join(root, 'scripts', 'run-dev-inner.mjs')
|
||||
const major = parseInt(process.versions.node.split('.')[0], 10)
|
||||
|
||||
const cmd = major >= 20 ? process.execPath : 'npx'
|
||||
const args = major >= 20 ? [inner] : ['-y', '-p', 'node@20', 'node', inner]
|
||||
|
||||
const r = spawnSync(cmd, args, { stdio: 'inherit', cwd: root, shell: false })
|
||||
process.exit(r.status ?? 1)
|
||||
Reference in New Issue
Block a user