chore: baseline import
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { getPayload } from 'payload'
|
||||
import config from '../payload.config'
|
||||
|
||||
async function main() {
|
||||
const payload = await getPayload({ config })
|
||||
|
||||
const email = 'admin@eversolo.local'
|
||||
const password = 'EversoloAdmin!2026'
|
||||
|
||||
const existing = await payload.find({
|
||||
collection: 'users',
|
||||
where: { email: { equals: email } },
|
||||
limit: 1,
|
||||
})
|
||||
|
||||
if (existing.docs[0]) {
|
||||
console.log(`exists:${email}`)
|
||||
return
|
||||
}
|
||||
|
||||
const user = await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
email,
|
||||
password,
|
||||
role: 'admin',
|
||||
name: 'Admin',
|
||||
},
|
||||
})
|
||||
|
||||
console.log(`created:${user.email}`)
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
import { copyFile, readdir } from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
|
||||
const chunksDir = path.resolve(process.cwd(), '.next/static/chunks')
|
||||
const entries = await readdir(chunksDir)
|
||||
const hashedMainApp = entries.find((entry) => /^main-app-[^.]+\.(js)$/.test(entry))
|
||||
|
||||
if (!hashedMainApp) {
|
||||
console.warn('[fix-next-main-app] No hashed main-app chunk found, skipping.')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const source = path.join(chunksDir, hashedMainApp)
|
||||
const target = path.join(chunksDir, 'main-app.js')
|
||||
|
||||
await copyFile(source, target)
|
||||
console.log(`[fix-next-main-app] Copied ${hashedMainApp} -> main-app.js`)
|
||||
@@ -0,0 +1,132 @@
|
||||
import 'dotenv/config'
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { getProductCardImageDefault } from '../lib/product-card-image-defaults.ts'
|
||||
|
||||
const ROOT = process.cwd()
|
||||
const ASSET_CACHE = path.join(ROOT, 'src', 'seed', 'downloaded')
|
||||
|
||||
async function loadPayload() {
|
||||
const { getPayload } = await import('payload')
|
||||
const configUrl = pathToFileURL(path.join(ROOT, 'src', 'payload.config.ts')).href
|
||||
const { default: config } = await import(configUrl)
|
||||
return getPayload({ config })
|
||||
}
|
||||
|
||||
function safeFilenameFromUrl(url, fallbackPrefix) {
|
||||
try {
|
||||
const parsed = new URL(url)
|
||||
return path.basename(parsed.pathname) || `${fallbackPrefix}-${Date.now()}`
|
||||
} catch {
|
||||
return `${fallbackPrefix}-${Date.now()}`
|
||||
}
|
||||
}
|
||||
|
||||
async function ensureDir(dir) {
|
||||
await fs.mkdir(dir, { recursive: true })
|
||||
}
|
||||
|
||||
async function fileExists(filePath) {
|
||||
try {
|
||||
await fs.access(filePath)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadAsset(url, kind, slug) {
|
||||
const dir = path.join(ASSET_CACHE, kind)
|
||||
await ensureDir(dir)
|
||||
|
||||
const filename = safeFilenameFromUrl(url, slug)
|
||||
const filePath = path.join(dir, filename)
|
||||
|
||||
if (await fileExists(filePath)) {
|
||||
return { filePath, filename }
|
||||
}
|
||||
|
||||
const res = await fetch(url)
|
||||
if (!res.ok) throw new Error(`Failed to download ${url}: ${res.status}`)
|
||||
|
||||
const buffer = Buffer.from(await res.arrayBuffer())
|
||||
await fs.writeFile(filePath, buffer)
|
||||
return { filePath, filename }
|
||||
}
|
||||
|
||||
async function findUploadByFilename(payload, filename) {
|
||||
const existing = await payload.find({
|
||||
collection: 'media',
|
||||
where: { filename: { equals: filename } },
|
||||
limit: 1,
|
||||
})
|
||||
|
||||
return existing.docs[0] ?? null
|
||||
}
|
||||
|
||||
async function ensureMediaAsset(payload, { alt, slug, url }) {
|
||||
if (!url) return null
|
||||
|
||||
const { filePath, filename } = await downloadAsset(url, 'media', slug)
|
||||
const existing = await findUploadByFilename(payload, filename)
|
||||
if (existing) return existing.id
|
||||
|
||||
const created = await payload.create({
|
||||
collection: 'media',
|
||||
data: {
|
||||
alt: alt || slug,
|
||||
credit: 'legacy-site',
|
||||
tags: [{ value: 'source: legacy-site' }],
|
||||
},
|
||||
filePath,
|
||||
})
|
||||
|
||||
return created.id
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const payload = await loadPayload()
|
||||
|
||||
for (const locale of ['en', 'zh']) {
|
||||
const products = await payload.find({
|
||||
collection: 'products',
|
||||
locale,
|
||||
limit: 100,
|
||||
depth: 1,
|
||||
where: { docLocale: { equals: locale } },
|
||||
})
|
||||
|
||||
for (const product of products.docs) {
|
||||
const cardUrl = getProductCardImageDefault(product.slug, locale)
|
||||
const heroImageId =
|
||||
typeof product.heroImage === 'number'
|
||||
? product.heroImage
|
||||
: product.heroImage?.id ?? null
|
||||
|
||||
const cardImageId = await ensureMediaAsset(payload, {
|
||||
alt: typeof product.name === 'string' ? product.name : product.model,
|
||||
slug: `${product.slug}-card-${locale}`,
|
||||
url: cardUrl,
|
||||
})
|
||||
|
||||
await payload.update({
|
||||
collection: 'products',
|
||||
id: product.id,
|
||||
locale,
|
||||
data: {
|
||||
cardImage: cardImageId || heroImageId || undefined,
|
||||
lifestyleImage: heroImageId || undefined,
|
||||
},
|
||||
})
|
||||
|
||||
console.log(`[sync-product-display-images] ${locale} ${product.slug} -> card=${cardImageId ?? 'null'} lifestyle=${heroImageId ?? 'null'}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in New Issue
Block a user