mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-27 18:12:05 -07:00
Prepare Windows release and signing process (#16)
This commit is contained in:
@@ -10,19 +10,32 @@ function existsSyncFrom(paths: string[]): (candidate: string) => boolean {
|
||||
|
||||
test('resolveConfigBaseDirs trims xdg value and deduplicates fallback dir', () => {
|
||||
const homeDir = '/home/tester';
|
||||
const baseDirs = resolveConfigBaseDirs(' /home/tester/.config ', homeDir);
|
||||
assert.deepEqual(baseDirs, [path.join(homeDir, '.config')]);
|
||||
const trimmedXdgConfigHome = '/home/tester/.config';
|
||||
const fallbackDir = path.posix.join(homeDir, '.config');
|
||||
const baseDirs = resolveConfigBaseDirs(` ${trimmedXdgConfigHome} `, homeDir, 'linux');
|
||||
const expected = Array.from(new Set([trimmedXdgConfigHome, fallbackDir]));
|
||||
assert.deepEqual(baseDirs, expected);
|
||||
});
|
||||
|
||||
test('resolveConfigBaseDirs prefers APPDATA on windows and deduplicates fallback dir', () => {
|
||||
const homeDir = 'C:\\Users\\tester';
|
||||
const appDataDir = 'C:\\Users\\tester\\AppData\\Roaming';
|
||||
|
||||
const baseDirs = resolveConfigBaseDirs(undefined, homeDir, 'win32', ` ${appDataDir} `);
|
||||
|
||||
assert.deepEqual(baseDirs, [appDataDir]);
|
||||
});
|
||||
|
||||
test('resolveConfigDir prefers xdg SubMiner config when present', () => {
|
||||
const homeDir = '/home/tester';
|
||||
const xdgConfigHome = '/tmp/xdg-config';
|
||||
const configDir = path.join(xdgConfigHome, 'SubMiner');
|
||||
const existsSync = existsSyncFrom([path.join(configDir, 'config.jsonc')]);
|
||||
const configDir = path.posix.join(xdgConfigHome, 'SubMiner');
|
||||
const existsSync = existsSyncFrom([path.posix.join(configDir, 'config.jsonc')]);
|
||||
|
||||
const resolved = resolveConfigDir({
|
||||
xdgConfigHome,
|
||||
homeDir,
|
||||
platform: 'linux',
|
||||
existsSync,
|
||||
});
|
||||
|
||||
@@ -37,20 +50,22 @@ test('resolveConfigDir ignores lowercase subminer candidate', () => {
|
||||
const resolved = resolveConfigDir({
|
||||
xdgConfigHome: '/tmp/missing-xdg',
|
||||
homeDir,
|
||||
platform: 'linux',
|
||||
existsSync,
|
||||
});
|
||||
|
||||
assert.equal(resolved, '/tmp/missing-xdg/SubMiner');
|
||||
assert.equal(resolved, path.posix.join('/tmp/missing-xdg', 'SubMiner'));
|
||||
});
|
||||
|
||||
test('resolveConfigDir falls back to existing directory when file is missing', () => {
|
||||
const homeDir = '/home/tester';
|
||||
const configDir = path.join(homeDir, '.config', 'SubMiner');
|
||||
const configDir = path.posix.join(homeDir, '.config', 'SubMiner');
|
||||
const existsSync = existsSyncFrom([configDir]);
|
||||
|
||||
const resolved = resolveConfigDir({
|
||||
xdgConfigHome: '/tmp/missing-xdg',
|
||||
homeDir,
|
||||
platform: 'linux',
|
||||
existsSync,
|
||||
});
|
||||
|
||||
@@ -61,17 +76,18 @@ test('resolveConfigFilePath prefers jsonc before json', () => {
|
||||
const homeDir = '/home/tester';
|
||||
const xdgConfigHome = '/tmp/xdg-config';
|
||||
const existsSync = existsSyncFrom([
|
||||
path.join(xdgConfigHome, 'SubMiner', 'config.jsonc'),
|
||||
path.join(xdgConfigHome, 'SubMiner', 'config.json'),
|
||||
path.posix.join(xdgConfigHome, 'SubMiner', 'config.jsonc'),
|
||||
path.posix.join(xdgConfigHome, 'SubMiner', 'config.json'),
|
||||
]);
|
||||
|
||||
const resolved = resolveConfigFilePath({
|
||||
xdgConfigHome,
|
||||
homeDir,
|
||||
platform: 'linux',
|
||||
existsSync,
|
||||
});
|
||||
|
||||
assert.equal(resolved, path.join(xdgConfigHome, 'SubMiner', 'config.jsonc'));
|
||||
assert.equal(resolved, path.posix.join(xdgConfigHome, 'SubMiner', 'config.jsonc'));
|
||||
});
|
||||
|
||||
test('resolveConfigFilePath keeps legacy fallback output path', () => {
|
||||
@@ -82,8 +98,40 @@ test('resolveConfigFilePath keeps legacy fallback output path', () => {
|
||||
const resolved = resolveConfigFilePath({
|
||||
xdgConfigHome,
|
||||
homeDir,
|
||||
platform: 'linux',
|
||||
existsSync,
|
||||
});
|
||||
|
||||
assert.equal(resolved, path.join(xdgConfigHome, 'SubMiner', 'config.jsonc'));
|
||||
assert.equal(resolved, path.posix.join(xdgConfigHome, 'SubMiner', 'config.jsonc'));
|
||||
});
|
||||
|
||||
test('resolveConfigDir prefers APPDATA SubMiner config on windows when present', () => {
|
||||
const homeDir = 'C:\\Users\\tester';
|
||||
const appDataDir = 'C:\\Users\\tester\\AppData\\Roaming';
|
||||
const configDir = path.win32.join(appDataDir, 'SubMiner');
|
||||
const existsSync = existsSyncFrom([path.win32.join(configDir, 'config.jsonc')]);
|
||||
|
||||
const resolved = resolveConfigDir({
|
||||
platform: 'win32',
|
||||
appDataDir,
|
||||
homeDir,
|
||||
existsSync,
|
||||
});
|
||||
|
||||
assert.equal(resolved, configDir);
|
||||
});
|
||||
|
||||
test('resolveConfigFilePath uses APPDATA fallback output path on windows', () => {
|
||||
const homeDir = 'C:\\Users\\tester';
|
||||
const appDataDir = 'C:\\Users\\tester\\AppData\\Roaming';
|
||||
const existsSync = existsSyncFrom([]);
|
||||
|
||||
const resolved = resolveConfigFilePath({
|
||||
platform: 'win32',
|
||||
appDataDir,
|
||||
homeDir,
|
||||
existsSync,
|
||||
});
|
||||
|
||||
assert.equal(resolved, path.win32.join(appDataDir, 'SubMiner', 'config.jsonc'));
|
||||
});
|
||||
|
||||
@@ -3,6 +3,8 @@ import path from 'node:path';
|
||||
type ExistsSync = (candidate: string) => boolean;
|
||||
|
||||
type ConfigPathOptions = {
|
||||
platform?: NodeJS.Platform;
|
||||
appDataDir?: string;
|
||||
xdgConfigHome?: string;
|
||||
homeDir: string;
|
||||
existsSync: ExistsSync;
|
||||
@@ -13,11 +15,24 @@ type ConfigPathOptions = {
|
||||
const DEFAULT_APP_NAMES = ['SubMiner'] as const;
|
||||
const DEFAULT_FILE_NAMES = ['config.jsonc', 'config.json'] as const;
|
||||
|
||||
function getPlatformPath(platform: NodeJS.Platform): typeof path.posix | typeof path.win32 {
|
||||
return platform === 'win32' ? path.win32 : path.posix;
|
||||
}
|
||||
|
||||
export function resolveConfigBaseDirs(
|
||||
xdgConfigHome: string | undefined,
|
||||
homeDir: string,
|
||||
platform: NodeJS.Platform = process.platform,
|
||||
appDataDir?: string,
|
||||
): string[] {
|
||||
const fallbackBaseDir = path.join(homeDir, '.config');
|
||||
const platformPath = getPlatformPath(platform);
|
||||
if (platform === 'win32') {
|
||||
const roamingBaseDir = platformPath.join(homeDir, 'AppData', 'Roaming');
|
||||
const primaryBaseDir = appDataDir?.trim() || roamingBaseDir;
|
||||
return Array.from(new Set([primaryBaseDir, roamingBaseDir]));
|
||||
}
|
||||
|
||||
const fallbackBaseDir = platformPath.join(homeDir, '.config');
|
||||
const primaryBaseDir = xdgConfigHome?.trim() || fallbackBaseDir;
|
||||
return Array.from(new Set([primaryBaseDir, fallbackBaseDir]));
|
||||
}
|
||||
@@ -31,14 +46,21 @@ function getDefaultAppName(options: ConfigPathOptions): string {
|
||||
}
|
||||
|
||||
export function resolveConfigDir(options: ConfigPathOptions): string {
|
||||
const baseDirs = resolveConfigBaseDirs(options.xdgConfigHome, options.homeDir);
|
||||
const platform = options.platform ?? process.platform;
|
||||
const platformPath = getPlatformPath(platform);
|
||||
const baseDirs = resolveConfigBaseDirs(
|
||||
options.xdgConfigHome,
|
||||
options.homeDir,
|
||||
platform,
|
||||
options.appDataDir,
|
||||
);
|
||||
const appNames = getAppNames(options);
|
||||
|
||||
for (const baseDir of baseDirs) {
|
||||
for (const appName of appNames) {
|
||||
const dir = path.join(baseDir, appName);
|
||||
const dir = platformPath.join(baseDir, appName);
|
||||
for (const fileName of DEFAULT_FILE_NAMES) {
|
||||
if (options.existsSync(path.join(dir, fileName))) {
|
||||
if (options.existsSync(platformPath.join(dir, fileName))) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
@@ -47,24 +69,31 @@ export function resolveConfigDir(options: ConfigPathOptions): string {
|
||||
|
||||
for (const baseDir of baseDirs) {
|
||||
for (const appName of appNames) {
|
||||
const dir = path.join(baseDir, appName);
|
||||
const dir = platformPath.join(baseDir, appName);
|
||||
if (options.existsSync(dir)) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path.join(baseDirs[0]!, getDefaultAppName(options));
|
||||
return platformPath.join(baseDirs[0]!, getDefaultAppName(options));
|
||||
}
|
||||
|
||||
export function resolveConfigFilePath(options: ConfigPathOptions): string {
|
||||
const baseDirs = resolveConfigBaseDirs(options.xdgConfigHome, options.homeDir);
|
||||
const platform = options.platform ?? process.platform;
|
||||
const platformPath = getPlatformPath(platform);
|
||||
const baseDirs = resolveConfigBaseDirs(
|
||||
options.xdgConfigHome,
|
||||
options.homeDir,
|
||||
platform,
|
||||
options.appDataDir,
|
||||
);
|
||||
const appNames = getAppNames(options);
|
||||
|
||||
for (const baseDir of baseDirs) {
|
||||
for (const appName of appNames) {
|
||||
for (const fileName of DEFAULT_FILE_NAMES) {
|
||||
const candidate = path.join(baseDir, appName, fileName);
|
||||
const candidate = platformPath.join(baseDir, appName, fileName);
|
||||
if (options.existsSync(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
@@ -72,5 +101,5 @@ export function resolveConfigFilePath(options: ConfigPathOptions): string {
|
||||
}
|
||||
}
|
||||
|
||||
return path.join(baseDirs[0]!, getDefaultAppName(options), DEFAULT_FILE_NAMES[0]!);
|
||||
return platformPath.join(baseDirs[0]!, getDefaultAppName(options), DEFAULT_FILE_NAMES[0]!);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ export function generateConfigTemplate(
|
||||
lines.push(' *');
|
||||
lines.push(' * This file is auto-generated from src/config/definitions.ts.');
|
||||
lines.push(
|
||||
' * Copy to $XDG_CONFIG_HOME/SubMiner/config.jsonc (or ~/.config/SubMiner/config.jsonc) and edit as needed.',
|
||||
' * Copy to %APPDATA%/SubMiner/config.jsonc on Windows, or $XDG_CONFIG_HOME/SubMiner/config.jsonc (or ~/.config/SubMiner/config.jsonc) on Linux/macOS.',
|
||||
);
|
||||
lines.push(' */');
|
||||
lines.push('{');
|
||||
|
||||
Reference in New Issue
Block a user