feat(phase1): rebrand to TTRPG Player and drop Git updates feed
Rename product to TTRPG Player (TTRPGPlayer / com.ttrpgplayer.app), use .ttrpg.zip for new saves while keeping .dnd.zip import, accept TTRPG- and DND- license keys on client, and remove sync-update-feed plus CI push to DndGamePlayerUpdates. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,10 +2,16 @@ import crypto from 'node:crypto';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
import {
|
||||
PROJECT_ZIP_EXTENSION,
|
||||
PROJECT_ZIP_EXTENSION_LEGACY,
|
||||
isProjectZipFileName,
|
||||
} from '../../shared/project/projectZipExtension';
|
||||
|
||||
import { readProjectJsonFromZip } from './yauzlProjectZip';
|
||||
|
||||
/**
|
||||
* Подменяет файл `finalPath` готовым `completedSrc` (обычно `*.dnd.zip.tmp`).
|
||||
* Подменяет файл `finalPath` готовым `completedSrc` (обычно `*.ttrpg.zip.tmp` / `*.dnd.zip.tmp`).
|
||||
* Нельзя сначала удалять `finalPath`: при сбое rename после rm проект теряется (Windows/антивирус).
|
||||
*/
|
||||
export async function replaceFileAtomic(completedSrc: string, finalPath: string): Promise<void> {
|
||||
@@ -50,8 +56,10 @@ export async function replaceFileAtomic(completedSrc: string, finalPath: string)
|
||||
await fs.unlink(backupPath).catch(() => undefined);
|
||||
}
|
||||
|
||||
/** Если сохранение оборвалось, остаётся только `*.dnd.zip.tmp` — восстанавливаем в `*.dnd.zip`. */
|
||||
export async function recoverOrphanDndZipTmpInRoot(root: string): Promise<void> {
|
||||
const ZIP_TMP_SUFFIXES = [`${PROJECT_ZIP_EXTENSION}.tmp`, `${PROJECT_ZIP_EXTENSION_LEGACY}.tmp`] as const;
|
||||
|
||||
/** Если сохранение оборвалось, остаётся `*.ttrpg.zip.tmp` / `*.dnd.zip.tmp` — восстанавливаем финальный архив. */
|
||||
export async function recoverOrphanProjectZipTmpInRoot(root: string): Promise<void> {
|
||||
let names: string[];
|
||||
try {
|
||||
names = await fs.readdir(root);
|
||||
@@ -59,10 +67,11 @@ export async function recoverOrphanDndZipTmpInRoot(root: string): Promise<void>
|
||||
return;
|
||||
}
|
||||
for (const name of names) {
|
||||
if (!name.endsWith('.dnd.zip.tmp')) continue;
|
||||
const matchedSuffix = ZIP_TMP_SUFFIXES.find((s) => name.endsWith(s));
|
||||
if (!matchedSuffix) continue;
|
||||
const tmpPath = path.join(root, name);
|
||||
const finalName = name.slice(0, -'.tmp'.length);
|
||||
if (!finalName.endsWith('.dnd.zip')) continue;
|
||||
if (!isProjectZipFileName(finalName)) continue;
|
||||
const finalPath = path.join(root, finalName);
|
||||
try {
|
||||
await fs.access(finalPath);
|
||||
@@ -80,3 +89,6 @@ export async function recoverOrphanDndZipTmpInRoot(root: string): Promise<void>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated Используйте {@link recoverOrphanProjectZipTmpInRoot}. */
|
||||
export const recoverOrphanDndZipTmpInRoot = recoverOrphanProjectZipTmpInRoot;
|
||||
|
||||
Reference in New Issue
Block a user