Skip to content

Commit 829db8d

Browse files
committed
feat: implement migration to new config format
1 parent b454627 commit 829db8d

File tree

3 files changed

+217
-85
lines changed

3 files changed

+217
-85
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "Ziit",
44
"description": "The swiss army knive for coding time tracking.",
55
"publisher": "PandaDEV",
6-
"version": "1.1.1",
6+
"version": "1.2.0",
77
"keywords": [
88
"ziit",
99
"vscode",

src/config.ts

Lines changed: 115 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,23 @@ import * as fs from "fs/promises";
44
import * as os from "os";
55
import * as path from "path";
66

7-
const CONFIG_FILE_NAME = ".ziit.json";
8-
const CONFIG_FILE_PATH = path.join(os.homedir(), CONFIG_FILE_NAME);
7+
function getConfigDir(): string {
8+
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
9+
if (xdgConfigHome) {
10+
return path.join(xdgConfigHome, "ziit");
11+
}
12+
return path.join(os.homedir(), ".config", "ziit");
13+
}
14+
15+
const CONFIG_DIR = getConfigDir();
16+
const CONFIG_FILE_NAME = "config.json";
17+
const CONFIG_FILE_PATH = path.join(CONFIG_DIR, CONFIG_FILE_NAME);
18+
19+
const LEGACY_CONFIG_FILE_NAME = ".ziit.json";
20+
const LEGACY_CONFIG_FILE_PATH = path.join(
21+
os.homedir(),
22+
LEGACY_CONFIG_FILE_NAME,
23+
);
924
const OLD_CONFIG_FILE_NAME = ".ziit.cfg";
1025
const OLD_CONFIG_FILE_PATH = path.join(os.homedir(), OLD_CONFIG_FILE_NAME);
1126

@@ -14,33 +29,98 @@ interface ZiitConfig {
1429
baseUrl?: string;
1530
}
1631

17-
async function migrateOldConfigIfNeeded() {
32+
async function ensureConfigDir(): Promise<void> {
1833
try {
19-
await fs.access(OLD_CONFIG_FILE_PATH);
20-
const content = await fs.readFile(OLD_CONFIG_FILE_PATH, "utf-8");
21-
let apiKey: string | undefined;
22-
let baseUrl: string | undefined;
23-
const lines = content.split(/\r?\n/);
24-
for (const line of lines) {
25-
const trimmed = line.trim();
26-
if (trimmed.startsWith("api_key")) {
27-
apiKey = trimmed.split("=")[1]?.trim();
34+
await fs.mkdir(CONFIG_DIR, { recursive: true });
35+
} catch (error: any) {
36+
log(`Error creating config directory: ${error.message}`);
37+
}
38+
}
39+
40+
async function migrateLegacyConfigs(): Promise<void> {
41+
try {
42+
await fs.access(CONFIG_FILE_PATH);
43+
log("New config file already exists, skipping migration");
44+
return;
45+
} catch {
46+
log("New config file not found, checking for legacy configs to migrate");
47+
}
48+
49+
let migratedConfig: ZiitConfig = {};
50+
let migrationSource = "";
51+
52+
try {
53+
await fs.access(LEGACY_CONFIG_FILE_PATH);
54+
const content = await fs.readFile(LEGACY_CONFIG_FILE_PATH, "utf-8");
55+
migratedConfig = JSON.parse(content);
56+
migrationSource = LEGACY_CONFIG_FILE_PATH;
57+
log("Found legacy .ziit.json config file for migration");
58+
} catch {
59+
try {
60+
await fs.access(OLD_CONFIG_FILE_PATH);
61+
const content = await fs.readFile(OLD_CONFIG_FILE_PATH, "utf-8");
62+
let apiKey: string | undefined;
63+
let baseUrl: string | undefined;
64+
const lines = content.split(/\r?\n/);
65+
for (const line of lines) {
66+
const trimmed = line.trim();
67+
if (trimmed.startsWith("api_key")) {
68+
apiKey = trimmed.split("=")[1]?.trim();
69+
}
70+
if (trimmed.startsWith("base_url")) {
71+
baseUrl = trimmed.split("=")[1]?.trim().replace(/\\:/g, ":");
72+
}
2873
}
29-
if (trimmed.startsWith("base_url")) {
30-
baseUrl = trimmed.split("=")[1]?.trim().replace(/\\:/g, ":");
74+
if (apiKey) migratedConfig.apiKey = apiKey;
75+
if (baseUrl) migratedConfig.baseUrl = baseUrl;
76+
migrationSource = OLD_CONFIG_FILE_PATH;
77+
log("Found legacy .ziit.cfg config file for migration");
78+
} catch {
79+
return;
80+
}
81+
}
82+
83+
if (migrationSource) {
84+
try {
85+
await ensureConfigDir();
86+
await fs.writeFile(
87+
CONFIG_FILE_PATH,
88+
JSON.stringify(migratedConfig, null, 2),
89+
);
90+
91+
try {
92+
if (migrationSource === LEGACY_CONFIG_FILE_PATH) {
93+
await fs.unlink(LEGACY_CONFIG_FILE_PATH);
94+
log(
95+
`Migrated config from ${LEGACY_CONFIG_FILE_PATH} to ${CONFIG_FILE_PATH}`,
96+
);
97+
} else if (migrationSource === OLD_CONFIG_FILE_PATH) {
98+
await fs.unlink(OLD_CONFIG_FILE_PATH);
99+
log(
100+
`Migrated config from ${OLD_CONFIG_FILE_PATH} to ${CONFIG_FILE_PATH}`,
101+
);
102+
}
103+
} catch (cleanupError: any) {
104+
log(
105+
`Warning: Could not remove old config file: ${cleanupError.message}`,
106+
);
31107
}
108+
109+
vscode.window.showInformationMessage(
110+
"Ziit configuration has been migrated to the new location. " +
111+
`New location: ${CONFIG_FILE_PATH}`,
112+
);
113+
} catch (error: any) {
114+
log(`Error during migration: ${error.message}`);
115+
vscode.window.showErrorMessage(
116+
`Failed to migrate Ziit configuration: ${error.message}`,
117+
);
32118
}
33-
const jsonConfig: ZiitConfig = {};
34-
if (apiKey) jsonConfig.apiKey = apiKey;
35-
if (baseUrl) jsonConfig.baseUrl = baseUrl;
36-
await fs.writeFile(CONFIG_FILE_PATH, JSON.stringify(jsonConfig, null, 2));
37-
await fs.unlink(OLD_CONFIG_FILE_PATH);
38-
log("Migrated old .ziit.cfg to .ziit.json");
39-
} catch {}
119+
}
40120
}
41121

42122
async function readConfigFile(): Promise<ZiitConfig> {
43-
await migrateOldConfigIfNeeded();
123+
await migrateLegacyConfigs();
44124
try {
45125
const content = await fs.readFile(CONFIG_FILE_PATH, "utf-8");
46126
return JSON.parse(content);
@@ -50,7 +130,7 @@ async function readConfigFile(): Promise<ZiitConfig> {
50130
} else {
51131
log(`Error reading config file: ${error.message}`);
52132
vscode.window.showErrorMessage(
53-
`Error reading Ziit config file: ${error.message}`
133+
`Error reading Ziit config file: ${error.message}`,
54134
);
55135
return {};
56136
}
@@ -59,18 +139,19 @@ async function readConfigFile(): Promise<ZiitConfig> {
59139

60140
async function writeConfigFile(config: ZiitConfig): Promise<void> {
61141
try {
142+
await ensureConfigDir();
62143
await fs.writeFile(CONFIG_FILE_PATH, JSON.stringify(config, null, 2));
63-
log("Config file updated (.ziit.json)");
144+
log(`Config file updated (${CONFIG_FILE_PATH})`);
64145
} catch (error: any) {
65146
log(`Error writing config file: ${error.message}`);
66147
vscode.window.showErrorMessage(
67-
`Failed to write Ziit config file: ${error.message}`
148+
`Failed to write Ziit config file: ${error.message}`,
68149
);
69150
}
70151
}
71152

72153
async function getConfigValue<T>(
73-
key: keyof ZiitConfig
154+
key: keyof ZiitConfig,
74155
): Promise<T | undefined> {
75156
const vscodeConfig = vscode.workspace.getConfiguration("ziit");
76157

@@ -100,7 +181,7 @@ async function getConfigValue<T>(
100181

101182
async function updateConfigValue<T>(
102183
key: keyof ZiitConfig,
103-
value: T
184+
value: T,
104185
): Promise<void> {
105186
let currentConfig: ZiitConfig = {};
106187
try {
@@ -113,7 +194,9 @@ async function updateConfigValue<T>(
113194
const newConfig = { ...currentConfig, [key]: value };
114195
await writeConfigFile(newConfig);
115196
await vscode.workspace.getConfiguration("ziit").update(key, value, true);
116-
log(`${key} updated in config file (.ziit.json) and VS Code settings.`);
197+
log(
198+
`${key} updated in config file (${CONFIG_FILE_PATH}) and VS Code settings.`,
199+
);
117200
}
118201

119202
export async function setApiKey(): Promise<void> {
@@ -155,13 +238,13 @@ export async function getBaseUrl(): Promise<string> {
155238

156239
export async function initializeAndSyncConfig(): Promise<void> {
157240
log(
158-
"Initializing or syncing config file (.ziit.json) with VS Code settings..."
241+
`Initializing or syncing config file (${CONFIG_FILE_PATH}) with VS Code settings...`,
159242
);
160243
let fileConfig: ZiitConfig;
161244
let fileNeedsCreation = false;
162245
try {
163246
fileConfig = await readConfigFile();
164-
log("Config file found (.ziit.json)");
247+
log(`Config file found (${CONFIG_FILE_PATH})`);
165248
} catch (error: any) {
166249
if (error.code === "ENOENT") {
167250
log(`Config file not found at ${CONFIG_FILE_PATH}. Will create it.`);
@@ -183,7 +266,7 @@ export async function initializeAndSyncConfig(): Promise<void> {
183266
}
184267
await writeConfigFile(initialConfig);
185268
fileConfig = initialConfig;
186-
log("Config file created and populated (.ziit.json)");
269+
log(`Config file created and populated (${CONFIG_FILE_PATH})`);
187270
}
188271
let updated = false;
189272
for (const key of ["apiKey", "baseUrl"]) {
@@ -201,7 +284,7 @@ export async function initializeAndSyncConfig(): Promise<void> {
201284
if (vscodeValue !== undefined && vscodeValue !== defaultValue) {
202285
await vscodeConfig.update(key, undefined, true);
203286
log(
204-
`Reset VS Code setting '${key}' to default as it's not in config file.`
287+
`Reset VS Code setting '${key}' to default as it's not in config file.`,
205288
);
206289
updated = true;
207290
}

0 commit comments

Comments
 (0)