Reset repository to README title only

Approach is changing entirely; clearing prior implementation
to start over from a clean slate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-09 20:41:19 +09:00
parent 9d55819e30
commit cd79378f3c
33 changed files with 0 additions and 8451 deletions

View File

@@ -1,247 +0,0 @@
import fs from 'node:fs'
import fsp from 'node:fs/promises'
import path from 'node:path'
import { accountPath, fileDir, manifestDir, manifestRootPath } from './paths'
import { AccountEntry, DashboardPackEntry, PackDefinition, PackListEntry, RootManifest } from './types'
const defaultRootManifest: RootManifest = {
packs: [
{
name: 'Sample Pack',
file: 'sample-pack'
}
]
}
const defaultAccount: AccountEntry[] = [
{
id: 'admin',
password: 'change-me'
}
]
const defaultPackDefinition: PackDefinition = {
mcVersion: '1.20.1',
recommendedJdkVersion: 17,
loaderType: 'vanilla',
loaderVersion: '',
loaderInstallerPath: '',
serverMinRam: 2048,
serverMaxRam: 4096,
clientMinRam: 4096,
clientRecommendedRam: 8192,
packPath: 'sample-pack.zip',
description: '새 서버팩',
configEditableFiles: ['server.properties', 'bukkit.yml'],
resourcePackFiles: [],
shaderPackFiles: []
}
async function ensureDir(targetPath: string): Promise<void> {
await fsp.mkdir(targetPath, { recursive: true })
}
async function ensureJsonFile<T>(targetPath: string, defaultValue: T): Promise<void> {
if (!fs.existsSync(targetPath)) {
await fsp.writeFile(targetPath, `${JSON.stringify(defaultValue, null, 2)}\n`, 'utf8')
}
}
export async function ensureProjectFiles(): Promise<void> {
await ensureDir(manifestDir)
await ensureDir(fileDir)
await ensureJsonFile(manifestRootPath, defaultRootManifest)
await ensureJsonFile(accountPath, defaultAccount)
const samplePackPath = path.join(manifestDir, 'sample-pack.json')
await ensureJsonFile(samplePackPath, defaultPackDefinition)
}
async function readJsonFile<T>(targetPath: string, fallback: T): Promise<T> {
try {
const raw = await fsp.readFile(targetPath, 'utf8')
return JSON.parse(raw) as T
} catch {
return fallback
}
}
async function writeJsonFile(targetPath: string, payload: unknown): Promise<void> {
await fsp.writeFile(targetPath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8')
}
function sanitizePackKey(name: string): string {
const trimmed = name.trim().replace(/\.json$/i, '')
const normalized = trimmed.replace(/[^a-zA-Z0-9_-]/g, '-').replace(/-+/g, '-')
return normalized.length > 0 ? normalized : 'new'
}
export async function loadRootManifest(): Promise<RootManifest> {
await ensureProjectFiles()
return readJsonFile<RootManifest>(manifestRootPath, defaultRootManifest)
}
export async function saveRootManifest(manifest: RootManifest): Promise<void> {
await writeJsonFile(manifestRootPath, manifest)
}
export async function loadAccounts(): Promise<AccountEntry[]> {
await ensureProjectFiles()
return readJsonFile<AccountEntry[]>(accountPath, defaultAccount)
}
export async function listManifestFiles(): Promise<string[]> {
await ensureProjectFiles()
const entries = await fsp.readdir(manifestDir, { withFileTypes: true })
return entries
.filter((entry) => entry.isFile() && entry.name.endsWith('.json'))
.map((entry) => entry.name.replace(/\.json$/i, ''))
.sort((left, right) => left.localeCompare(right))
}
export async function listDashboardPacks(): Promise<DashboardPackEntry[]> {
const [manifestFiles, rootManifest] = await Promise.all([
listManifestFiles(),
loadRootManifest()
])
return manifestFiles.map((file) => {
const registeredPack = rootManifest.packs.find((entry) => entry.file === file)
return {
file,
name: registeredPack?.name ?? file,
registered: registeredPack != null
}
})
}
export async function loadPackDefinition(packKey: string): Promise<PackDefinition | null> {
await ensureProjectFiles()
const safeKey = sanitizePackKey(packKey)
const filePath = path.join(manifestDir, `${safeKey}.json`)
if (!fs.existsSync(filePath)) {
return null
}
return readJsonFile<PackDefinition>(filePath, defaultPackDefinition)
}
export async function savePackDefinition(packKey: string, payload: PackDefinition): Promise<void> {
const safeKey = sanitizePackKey(packKey)
await writeJsonFile(path.join(manifestDir, `${safeKey}.json`), payload)
}
function nextAvailableNewKey(existing: string[]): string {
if (!existing.includes('new')) {
return 'new'
}
let index = 2
while (existing.includes(`new${index}`)) {
index += 1
}
return `new${index}`
}
export async function createNewPack(): Promise<string> {
const existing = await listManifestFiles()
const packKey = nextAvailableNewKey(existing)
await savePackDefinition(packKey, {
...defaultPackDefinition,
description: `새 서버팩 (${packKey})`
})
const manifest = await loadRootManifest()
manifest.packs.push({
name: `새 서버팩 (${packKey})`,
file: packKey
})
await saveRootManifest(manifest)
return packKey
}
export async function deletePacks(packKeys: string[]): Promise<void> {
const targetKeys = new Set(packKeys.map((entry) => sanitizePackKey(entry)))
const manifest = await loadRootManifest()
manifest.packs = manifest.packs.filter((entry) => !targetKeys.has(entry.file))
await saveRootManifest(manifest)
await Promise.all(
[...targetKeys].map(async (packKey) => {
const filePath = path.join(manifestDir, `${packKey}.json`)
if (fs.existsSync(filePath)) {
await fsp.unlink(filePath)
}
})
)
}
export async function updatePack(
currentKey: string,
nextName: string,
nextKey: string,
definition: PackDefinition
): Promise<string> {
const safeCurrentKey = sanitizePackKey(currentKey)
const safeNextKey = sanitizePackKey(nextKey)
const currentPath = path.join(manifestDir, `${safeCurrentKey}.json`)
const nextPath = path.join(manifestDir, `${safeNextKey}.json`)
if (safeCurrentKey !== safeNextKey && fs.existsSync(nextPath)) {
throw new Error('같은 이름의 JSON 파일이 이미 존재합니다.')
}
await savePackDefinition(safeNextKey, definition)
if (safeCurrentKey !== safeNextKey && fs.existsSync(currentPath)) {
await fsp.unlink(currentPath)
}
const manifest = await loadRootManifest()
const targetIndex = manifest.packs.findIndex((entry) => entry.file === safeCurrentKey)
const nextEntry: PackListEntry = {
name: nextName.trim(),
file: safeNextKey
}
if (targetIndex >= 0) {
manifest.packs[targetIndex] = nextEntry
} else {
manifest.packs.push(nextEntry)
}
await saveRootManifest(manifest)
return safeNextKey
}
export function normalizePackDefinition(input: Partial<PackDefinition>): PackDefinition {
return {
mcVersion: String(input.mcVersion ?? '1.20.1').trim() || '1.20.1',
recommendedJdkVersion: Number.isFinite(Number(input.recommendedJdkVersion))
? Number(input.recommendedJdkVersion)
: 17,
loaderType: ['vanilla', 'forge', 'fabric', 'neoforge'].includes(String(input.loaderType ?? 'vanilla'))
? String(input.loaderType ?? 'vanilla') as PackDefinition['loaderType']
: 'vanilla',
loaderVersion: String(input.loaderVersion ?? '').trim(),
loaderInstallerPath: String(input.loaderInstallerPath ?? '').trim(),
serverMinRam: Number(input.serverMinRam ?? 2048),
serverMaxRam: Number(input.serverMaxRam ?? 4096),
clientMinRam: Number(input.clientMinRam ?? 4096),
clientRecommendedRam: Number(input.clientRecommendedRam ?? 8192),
packPath: String(input.packPath ?? '').trim(),
description: String(input.description ?? '').trim(),
files: Array.isArray(input.files)
? input.files.map((entry) => String(entry).trim()).filter((entry) => entry.length > 0)
: undefined,
configEditableFiles: Array.isArray(input.configEditableFiles)
? input.configEditableFiles.map((entry) => String(entry).trim()).filter((entry) => entry.length > 0)
: ['server.properties', 'bukkit.yml'],
resourcePackFiles: Array.isArray(input.resourcePackFiles)
? input.resourcePackFiles.map((entry) => String(entry).trim()).filter((entry) => entry.length > 0)
: [],
shaderPackFiles: Array.isArray(input.shaderPackFiles)
? input.shaderPackFiles.map((entry) => String(entry).trim()).filter((entry) => entry.length > 0)
: []
}
}