@invoicer/cli 1.2.5 ā 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/workspace.js +63 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/core/paths.js +25 -7
- package/dist/core/paths.js.map +1 -1
- package/dist/core/settings.js +99 -0
- package/dist/core/settings.js.map +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ import { registerClientsCommand } from "./commands/clients.js";
|
|
|
11
11
|
import { registerTimesheetCommand } from "./commands/timesheet.js";
|
|
12
12
|
import { registerSenderCommand } from "./commands/sender.js";
|
|
13
13
|
import { registerDraftsCommand } from "./commands/drafts.js";
|
|
14
|
+
import { registerWorkspaceCommand } from "./commands/workspace.js";
|
|
14
15
|
function getPackageVersion() {
|
|
15
16
|
try {
|
|
16
17
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -33,6 +34,7 @@ export function createProgram(paths = createProjectPaths()) {
|
|
|
33
34
|
registerTimesheetCommand(program, paths);
|
|
34
35
|
registerSenderCommand(program, paths);
|
|
35
36
|
registerDraftsCommand(program, paths);
|
|
37
|
+
registerWorkspaceCommand(program, paths);
|
|
36
38
|
return program;
|
|
37
39
|
}
|
|
38
40
|
export async function runCli(argv = process.argv, paths = createProjectPaths()) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAqB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { getCustomDataPath, setCustomDataPath, clearCustomDataPath, loadCliSettings, } from "../core/settings.js";
|
|
2
|
+
export function registerWorkspaceCommand(program, paths) {
|
|
3
|
+
program
|
|
4
|
+
.command("workspace")
|
|
5
|
+
.alias("path")
|
|
6
|
+
.description("Manage CLI data path location")
|
|
7
|
+
.option("--list", "Show current workspace path", false)
|
|
8
|
+
.option("--set <path>", "Set custom data path")
|
|
9
|
+
.option("--clear", "Clear custom data path and use default", false)
|
|
10
|
+
.action(async (options) => {
|
|
11
|
+
// If no option provided, show status
|
|
12
|
+
if (!options.list && !options.set && !options.clear) {
|
|
13
|
+
showWorkspaceStatus(paths);
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
if (options.list) {
|
|
17
|
+
showWorkspaceStatus(paths);
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
if (options.set) {
|
|
21
|
+
try {
|
|
22
|
+
setCustomDataPath(options.set);
|
|
23
|
+
console.log(`\nā
Data path set to: ${options.set}`);
|
|
24
|
+
console.log(`\nš Data files location:\n ${options.set}/config.json\n ${options.set}/data/timesheet.json\n ${options.set}/data/archive.json\n`);
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
29
|
+
console.error(`ā Failed to set data path: ${message}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (options.clear) {
|
|
34
|
+
clearCustomDataPath();
|
|
35
|
+
console.log("\nā
Custom data path cleared.");
|
|
36
|
+
console.log(" CLI will now use default location.");
|
|
37
|
+
showWorkspaceStatus(paths);
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function showWorkspaceStatus(paths) {
|
|
43
|
+
const customPath = getCustomDataPath();
|
|
44
|
+
const settings = loadCliSettings();
|
|
45
|
+
console.log("\nš Current Workspace Configuration:\n");
|
|
46
|
+
if (customPath) {
|
|
47
|
+
console.log(` Status: ā
Custom path set`);
|
|
48
|
+
console.log(` Path: ${customPath}`);
|
|
49
|
+
console.log(` Config: ${customPath}/config.json`);
|
|
50
|
+
console.log(` Data: ${customPath}/data/\n`);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
console.log(` Status: Using default location`);
|
|
54
|
+
console.log(` Path: ${paths.projectRoot}`);
|
|
55
|
+
console.log(` Config: ${paths.configPath}`);
|
|
56
|
+
console.log(` Data: ${paths.timesheetPath.replace("/timesheet.json", "")}/\n`);
|
|
57
|
+
}
|
|
58
|
+
console.log("š Usage:\n");
|
|
59
|
+
console.log(" Set custom path: invoicer workspace --set /path/to/workspace");
|
|
60
|
+
console.log(" Clear custom path: invoicer workspace --clear");
|
|
61
|
+
console.log(" Show status: invoicer workspace --list\n");
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/commands/workspace.ts"],"names":[],"mappings":"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"}
|
package/dist/core/paths.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { homedir } from "node:os";
|
|
4
|
+
import { homedir, platform } from "node:os";
|
|
5
|
+
import { getCustomDataPath } from "./settings.js";
|
|
5
6
|
export function findProjectRoot(startDir = process.cwd()) {
|
|
6
7
|
let currentDir = startDir;
|
|
7
8
|
const root = path.parse(currentDir).root;
|
|
@@ -18,12 +19,29 @@ export function createProjectPaths(startDir = process.cwd()) {
|
|
|
18
19
|
const moduleRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
19
20
|
const foundRoot = findProjectRoot(startDir);
|
|
20
21
|
const hasModuleConfig = fs.existsSync(path.join(moduleRoot, "config.json"));
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
// Get default app data directory (matching desktop app behavior)
|
|
23
|
+
const getDefaultDataDir = () => {
|
|
24
|
+
const osType = platform();
|
|
25
|
+
if (osType === "win32") {
|
|
26
|
+
// Windows: %APPDATA%\invoicer
|
|
27
|
+
const appdata = process.env.APPDATA;
|
|
28
|
+
if (appdata)
|
|
29
|
+
return path.join(appdata, "invoicer");
|
|
30
|
+
}
|
|
31
|
+
// macOS and Linux: ~/.local/share/invoicer (XDG Base Directory spec)
|
|
32
|
+
const xdgDataHome = process.env.XDG_DATA_HOME;
|
|
33
|
+
if (xdgDataHome)
|
|
34
|
+
return path.join(xdgDataHome, "invoicer");
|
|
35
|
+
return path.join(homedir(), ".local", "share", "invoicer");
|
|
36
|
+
};
|
|
37
|
+
// Priority: 1) Custom data path (if user set via `invoicer workspace --set`)
|
|
38
|
+
// 2) Project root (if config found in parents)
|
|
39
|
+
// 3) Module root (if it has config - development mode)
|
|
40
|
+
// 4) System app data directory (matches desktop app)
|
|
41
|
+
const customPath = getCustomDataPath();
|
|
42
|
+
const projectRoot = customPath ?? foundRoot ?? (hasModuleConfig ? moduleRoot : getDefaultDataDir());
|
|
43
|
+
// Ensure data subdirectory exists when using app data directory
|
|
44
|
+
if (!customPath && !foundRoot && !hasModuleConfig) {
|
|
27
45
|
const dataDir = path.join(projectRoot, "data");
|
|
28
46
|
if (!fs.existsSync(dataDir)) {
|
|
29
47
|
fs.mkdirSync(dataDir, { recursive: true });
|
package/dist/core/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
function getSettingsDir() {
|
|
5
|
+
// Use same config location as desktop app for consistency
|
|
6
|
+
const osType = process.platform;
|
|
7
|
+
if (osType === "win32") {
|
|
8
|
+
const appdata = process.env.APPDATA;
|
|
9
|
+
if (appdata)
|
|
10
|
+
return path.join(appdata, "invoicer");
|
|
11
|
+
}
|
|
12
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
13
|
+
if (xdgConfigHome)
|
|
14
|
+
return path.join(xdgConfigHome, "invoicer");
|
|
15
|
+
return path.join(homedir(), ".config", "invoicer");
|
|
16
|
+
}
|
|
17
|
+
function getSettingsPath() {
|
|
18
|
+
const settingsDir = getSettingsDir();
|
|
19
|
+
return path.join(settingsDir, "cli-settings.json");
|
|
20
|
+
}
|
|
21
|
+
export function loadCliSettings() {
|
|
22
|
+
const settingsPath = getSettingsPath();
|
|
23
|
+
if (!fs.existsSync(settingsPath)) {
|
|
24
|
+
return { version: 1 };
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const data = fs.readFileSync(settingsPath, "utf-8");
|
|
28
|
+
const parsed = JSON.parse(data);
|
|
29
|
+
// Validate required fields
|
|
30
|
+
if (typeof parsed.version !== "number") {
|
|
31
|
+
throw new Error("Invalid settings: missing or invalid version field");
|
|
32
|
+
}
|
|
33
|
+
return parsed;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
37
|
+
console.error(`ā ļø Could not read CLI settings (${message}), using defaults`);
|
|
38
|
+
return { version: 1 };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function saveCliSettings(settings) {
|
|
42
|
+
const settingsPath = getSettingsPath();
|
|
43
|
+
const settingsDir = path.dirname(settingsPath);
|
|
44
|
+
// Ensure directory exists
|
|
45
|
+
if (!fs.existsSync(settingsDir)) {
|
|
46
|
+
fs.mkdirSync(settingsDir, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
const json = JSON.stringify(settings, null, 2);
|
|
49
|
+
fs.writeFileSync(settingsPath, json, "utf-8");
|
|
50
|
+
}
|
|
51
|
+
export function getCustomDataPath() {
|
|
52
|
+
const settings = loadCliSettings();
|
|
53
|
+
if (!settings.customDataPath)
|
|
54
|
+
return null;
|
|
55
|
+
// Validate path still exists
|
|
56
|
+
if (fs.existsSync(settings.customDataPath)) {
|
|
57
|
+
return settings.customDataPath;
|
|
58
|
+
}
|
|
59
|
+
// Path no longer exists, clear it
|
|
60
|
+
settings.customDataPath = undefined;
|
|
61
|
+
saveCliSettings(settings);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
export function setCustomDataPath(customPath) {
|
|
65
|
+
const resolvedPath = path.resolve(customPath);
|
|
66
|
+
// Ensure path exists and is a directory
|
|
67
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
68
|
+
throw new Error(`Path does not exist: ${customPath}`);
|
|
69
|
+
}
|
|
70
|
+
const stat = fs.statSync(resolvedPath);
|
|
71
|
+
if (!stat.isDirectory()) {
|
|
72
|
+
throw new Error(`Path is not a directory: ${customPath}`);
|
|
73
|
+
}
|
|
74
|
+
// Check write permissions
|
|
75
|
+
try {
|
|
76
|
+
fs.accessSync(resolvedPath, fs.constants.W_OK);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
throw new Error(`Path is not writable: ${customPath}`);
|
|
80
|
+
}
|
|
81
|
+
// Resolve symlinks to get canonical path
|
|
82
|
+
let canonicalPath = resolvedPath;
|
|
83
|
+
try {
|
|
84
|
+
canonicalPath = fs.realpathSync(resolvedPath);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// If canonicalization fails, use the resolved path anyway
|
|
88
|
+
console.warn(`ā ļø Could not resolve symlinks for ${resolvedPath}, using as-is`);
|
|
89
|
+
}
|
|
90
|
+
const settings = loadCliSettings();
|
|
91
|
+
settings.customDataPath = canonicalPath;
|
|
92
|
+
saveCliSettings(settings);
|
|
93
|
+
}
|
|
94
|
+
export function clearCustomDataPath() {
|
|
95
|
+
const settings = loadCliSettings();
|
|
96
|
+
settings.customDataPath = undefined;
|
|
97
|
+
saveCliSettings(settings);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/core/settings.ts"],"names":[],"mappings":"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"}
|