added dist to docker
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
import { execSync } from 'node:child_process'
|
||||
import { existsSync } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||
process.chdir(root)
|
||||
|
||||
execSync('node scripts/write-docker-vite-env.mjs', { stdio: 'inherit' })
|
||||
execSync('npm run build-only', { stdio: 'inherit' })
|
||||
|
||||
if (!existsSync(path.join(root, 'dist', 'index.html'))) {
|
||||
throw new Error('dist/index.html ساخته نشد')
|
||||
}
|
||||
|
||||
console.log('dist آماده است. commit و push کنید تا Dokploy بدون npm سرو کند.')
|
||||
@@ -0,0 +1,84 @@
|
||||
import http from 'node:http'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const port = Number(process.env.PORT || 7676)
|
||||
const distDir = path.resolve(process.env.DIST_DIR || path.join(__dirname, '..', 'dist'))
|
||||
const rawBase = String(process.env.VITE_BASE_PATH ?? '/admin/').trim() || '/admin/'
|
||||
const publicBase = rawBase === '/' ? '' : rawBase.replace(/\/+$/, '')
|
||||
|
||||
const MIME = {
|
||||
'.html': 'text/html; charset=utf-8',
|
||||
'.js': 'text/javascript; charset=utf-8',
|
||||
'.mjs': 'text/javascript; charset=utf-8',
|
||||
'.css': 'text/css; charset=utf-8',
|
||||
'.json': 'application/json; charset=utf-8',
|
||||
'.map': 'application/json; charset=utf-8',
|
||||
'.svg': 'image/svg+xml',
|
||||
'.png': 'image/png',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.gif': 'image/gif',
|
||||
'.webp': 'image/webp',
|
||||
'.ico': 'image/x-icon',
|
||||
'.woff': 'font/woff',
|
||||
'.woff2': 'font/woff2',
|
||||
'.ttf': 'font/ttf',
|
||||
'.txt': 'text/plain; charset=utf-8',
|
||||
'.webmanifest': 'application/manifest+json',
|
||||
}
|
||||
|
||||
function sendFile(res, filePath) {
|
||||
const type = MIME[path.extname(filePath).toLowerCase()] || 'application/octet-stream'
|
||||
res.writeHead(200, { 'Content-Type': type, 'Cache-Control': 'public, max-age=0' })
|
||||
fs.createReadStream(filePath).pipe(res)
|
||||
}
|
||||
|
||||
function sendIndex(res) {
|
||||
sendFile(res, path.join(distDir, 'index.html'))
|
||||
}
|
||||
|
||||
function resolveSafe(urlPath) {
|
||||
const decoded = decodeURIComponent(urlPath.split('?')[0] || '/')
|
||||
const relative = publicBase && decoded.startsWith(`${publicBase}/`)
|
||||
? decoded.slice(publicBase.length)
|
||||
: publicBase && decoded === publicBase
|
||||
? '/'
|
||||
: decoded
|
||||
const target = path.resolve(distDir, `.${relative}`)
|
||||
if (!target.startsWith(distDir)) return null
|
||||
return target
|
||||
}
|
||||
|
||||
const server = http.createServer((req, res) => {
|
||||
const url = req.url || '/'
|
||||
const pathname = decodeURIComponent(url.split('?')[0] || '/')
|
||||
|
||||
if (pathname === '/health' || (publicBase && pathname === `${publicBase}/health`)) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' })
|
||||
return res.end('ok')
|
||||
}
|
||||
|
||||
if (publicBase && pathname === publicBase) {
|
||||
res.writeHead(302, { Location: `${publicBase}/` })
|
||||
return res.end()
|
||||
}
|
||||
|
||||
if (publicBase && pathname === '/') {
|
||||
res.writeHead(302, { Location: `${publicBase}/` })
|
||||
return res.end()
|
||||
}
|
||||
|
||||
const target = resolveSafe(url)
|
||||
if (target && fs.existsSync(target) && fs.statSync(target).isFile()) {
|
||||
return sendFile(res, target)
|
||||
}
|
||||
|
||||
return sendIndex(res)
|
||||
})
|
||||
|
||||
server.listen(port, '0.0.0.0', () => {
|
||||
console.log(`fabric-trade admin listening on ${port} → ${publicBase || ''}/`)
|
||||
})
|
||||
@@ -0,0 +1,56 @@
|
||||
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
||||
|
||||
const keys = ['VITE_API_BASE_URL', 'VITE_USE_MOCK_AUTH', 'VITE_BASE_PATH']
|
||||
|
||||
function parseEnv(text) {
|
||||
const out = {}
|
||||
for (const line of text.split(/\r?\n/)) {
|
||||
const trimmed = line.trim()
|
||||
if (!trimmed || trimmed.startsWith('#')) continue
|
||||
const index = trimmed.indexOf('=')
|
||||
if (index <= 0) continue
|
||||
const key = trimmed.slice(0, index).trim()
|
||||
let value = trimmed.slice(index + 1)
|
||||
if (
|
||||
(value.startsWith('"') && value.endsWith('"')) ||
|
||||
(value.startsWith("'") && value.endsWith("'"))
|
||||
) {
|
||||
value = value.slice(1, -1)
|
||||
}
|
||||
out[key] = value
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
const merged = {}
|
||||
|
||||
if (existsSync('.env')) {
|
||||
Object.assign(merged, parseEnv(readFileSync('.env', 'utf8')))
|
||||
}
|
||||
|
||||
for (const key of keys) {
|
||||
const value = process.env[key]
|
||||
if (value) merged[key] = value
|
||||
}
|
||||
|
||||
if (!merged.VITE_API_BASE_URL) {
|
||||
merged.VITE_API_BASE_URL = 'https://nademitex.montest.ir/server/api'
|
||||
}
|
||||
|
||||
if (!merged.VITE_USE_MOCK_AUTH) {
|
||||
merged.VITE_USE_MOCK_AUTH = 'false'
|
||||
}
|
||||
|
||||
if (!merged.VITE_BASE_PATH || merged.VITE_BASE_PATH === '/') {
|
||||
merged.VITE_BASE_PATH = '/admin/'
|
||||
} else if (!merged.VITE_BASE_PATH.endsWith('/')) {
|
||||
merged.VITE_BASE_PATH = `${merged.VITE_BASE_PATH}/`
|
||||
}
|
||||
|
||||
const lines = Object.entries(merged)
|
||||
.filter(([key]) => key.startsWith('VITE_'))
|
||||
.map(([key, value]) => `${key}=${value}`)
|
||||
|
||||
writeFileSync('.env.production', `${lines.join('\n')}\n`)
|
||||
console.log('Vite build env:')
|
||||
for (const line of lines) console.log(` ${line}`)
|
||||
Reference in New Issue
Block a user