obsyncd 1.0.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/README.md +920 -0
- package/dist/cli/commands/init.d.ts +8 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +104 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/status.d.ts +8 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +117 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +13 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +225 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/prompts/conflictPrompt.d.ts +10 -0
- package/dist/cli/prompts/conflictPrompt.d.ts.map +1 -0
- package/dist/cli/prompts/conflictPrompt.js +51 -0
- package/dist/cli/prompts/conflictPrompt.js.map +1 -0
- package/dist/cli/prompts/fileBrowser.d.ts +6 -0
- package/dist/cli/prompts/fileBrowser.d.ts.map +1 -0
- package/dist/cli/prompts/fileBrowser.js +91 -0
- package/dist/cli/prompts/fileBrowser.js.map +1 -0
- package/dist/cli/prompts/vaultSelector.d.ts +13 -0
- package/dist/cli/prompts/vaultSelector.d.ts.map +1 -0
- package/dist/cli/prompts/vaultSelector.js +63 -0
- package/dist/cli/prompts/vaultSelector.js.map +1 -0
- package/dist/cli/ui/colors.d.ts +50 -0
- package/dist/cli/ui/colors.d.ts.map +1 -0
- package/dist/cli/ui/colors.js +62 -0
- package/dist/cli/ui/colors.js.map +1 -0
- package/dist/cli/ui/output.d.ts +45 -0
- package/dist/cli/ui/output.d.ts.map +1 -0
- package/dist/cli/ui/output.js +116 -0
- package/dist/cli/ui/output.js.map +1 -0
- package/dist/cli/ui/spinner.d.ts +29 -0
- package/dist/cli/ui/spinner.d.ts.map +1 -0
- package/dist/cli/ui/spinner.js +80 -0
- package/dist/cli/ui/spinner.js.map +1 -0
- package/dist/cli/ui/table.d.ts +28 -0
- package/dist/cli/ui/table.d.ts.map +1 -0
- package/dist/cli/ui/table.js +123 -0
- package/dist/cli/ui/table.js.map +1 -0
- package/dist/cli/utils/terminal.d.ts +21 -0
- package/dist/cli/utils/terminal.d.ts.map +1 -0
- package/dist/cli/utils/terminal.js +59 -0
- package/dist/cli/utils/terminal.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +32 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +45 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +112 -0
- package/dist/config/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/storage/index.d.ts +35 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +97 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/sync/changeDetector.d.ts +29 -0
- package/dist/sync/changeDetector.d.ts.map +1 -0
- package/dist/sync/changeDetector.js +259 -0
- package/dist/sync/changeDetector.js.map +1 -0
- package/dist/sync/conflictResolver.d.ts +29 -0
- package/dist/sync/conflictResolver.d.ts.map +1 -0
- package/dist/sync/conflictResolver.js +116 -0
- package/dist/sync/conflictResolver.js.map +1 -0
- package/dist/sync/directoryLister.d.ts +18 -0
- package/dist/sync/directoryLister.d.ts.map +1 -0
- package/dist/sync/directoryLister.js +39 -0
- package/dist/sync/directoryLister.js.map +1 -0
- package/dist/sync/index.d.ts +29 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +212 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/manifest.d.ts +48 -0
- package/dist/sync/manifest.d.ts.map +1 -0
- package/dist/sync/manifest.js +137 -0
- package/dist/sync/manifest.js.map +1 -0
- package/dist/sync/types.d.ts +109 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +5 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/sync/watchMode.d.ts +84 -0
- package/dist/sync/watchMode.d.ts.map +1 -0
- package/dist/sync/watchMode.js +364 -0
- package/dist/sync/watchMode.js.map +1 -0
- package/dist/sync/watcher.d.ts +114 -0
- package/dist/sync/watcher.d.ts.map +1 -0
- package/dist/sync/watcher.js +293 -0
- package/dist/sync/watcher.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +25 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/vault/index.d.ts +38 -0
- package/dist/vault/index.d.ts.map +1 -0
- package/dist/vault/index.js +106 -0
- package/dist/vault/index.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { select } from '@inquirer/prompts';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { theme, symbols } from '../ui/colors.js';
|
|
5
|
+
/**
|
|
6
|
+
* Check if a directory is an Obsidian vault
|
|
7
|
+
*/
|
|
8
|
+
async function isObsidianVault(dirPath) {
|
|
9
|
+
try {
|
|
10
|
+
const obsidianPath = path.join(dirPath, '.obsidian');
|
|
11
|
+
const stat = await fs.stat(obsidianPath);
|
|
12
|
+
return stat.isDirectory();
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Format a directory name with indicators
|
|
20
|
+
*/
|
|
21
|
+
async function formatDirectoryName(name, fullPath) {
|
|
22
|
+
const isVault = await isObsidianVault(fullPath);
|
|
23
|
+
if (isVault) {
|
|
24
|
+
return `${symbols.vault} ${theme.highlight(name)} ${theme.muted('(Obsidian vault)')}`;
|
|
25
|
+
}
|
|
26
|
+
return `${symbols.folder} ${name}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Browse directories interactively
|
|
30
|
+
* Returns the selected directory path
|
|
31
|
+
*/
|
|
32
|
+
export async function browseForDirectory(startPath) {
|
|
33
|
+
let currentPath = path.resolve(startPath);
|
|
34
|
+
while (true) {
|
|
35
|
+
// Get directory contents
|
|
36
|
+
let entries;
|
|
37
|
+
try {
|
|
38
|
+
const dirents = await fs.readdir(currentPath, { withFileTypes: true });
|
|
39
|
+
entries = dirents
|
|
40
|
+
.filter((d) => d.isDirectory())
|
|
41
|
+
.filter((d) => !d.name.startsWith('.')) // Hide hidden directories
|
|
42
|
+
.map((d) => ({ name: d.name }))
|
|
43
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// If we can't read the directory, go up one level
|
|
47
|
+
currentPath = path.dirname(currentPath);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
// Build choices
|
|
51
|
+
const choices = [];
|
|
52
|
+
// Add navigation options
|
|
53
|
+
choices.push({
|
|
54
|
+
value: '__SELECT__',
|
|
55
|
+
name: `${theme.success('\u2713')} ${theme.bold('Select this folder')} ${theme.muted(`(${currentPath})`)}`,
|
|
56
|
+
});
|
|
57
|
+
choices.push({
|
|
58
|
+
value: '__PARENT__',
|
|
59
|
+
name: `${theme.muted('..')} ${theme.muted('(parent directory)')}`,
|
|
60
|
+
});
|
|
61
|
+
// Add subdirectories
|
|
62
|
+
for (const entry of entries) {
|
|
63
|
+
const fullPath = path.join(currentPath, entry.name);
|
|
64
|
+
const formattedName = await formatDirectoryName(entry.name, fullPath);
|
|
65
|
+
choices.push({
|
|
66
|
+
value: entry.name,
|
|
67
|
+
name: formattedName,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// Show the prompt
|
|
71
|
+
const selection = await select({
|
|
72
|
+
message: `${theme.dim('Current:')} ${theme.cyan(currentPath)}`,
|
|
73
|
+
choices,
|
|
74
|
+
pageSize: 15,
|
|
75
|
+
});
|
|
76
|
+
// Handle selection
|
|
77
|
+
if (selection === '__SELECT__') {
|
|
78
|
+
return currentPath;
|
|
79
|
+
}
|
|
80
|
+
if (selection === '__PARENT__') {
|
|
81
|
+
const parentPath = path.dirname(currentPath);
|
|
82
|
+
if (parentPath !== currentPath) {
|
|
83
|
+
currentPath = parentPath;
|
|
84
|
+
}
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
// Navigate into subdirectory
|
|
88
|
+
currentPath = path.join(currentPath, selection);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=fileBrowser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileBrowser.js","sourceRoot":"","sources":["../../../src/cli/prompts/fileBrowser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt the user to enter or browse for a vault path
|
|
3
|
+
*/
|
|
4
|
+
export declare function promptForVaultPath(message: string): Promise<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Prompt for source vault with context
|
|
7
|
+
*/
|
|
8
|
+
export declare function promptForSourceVault(): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Prompt for destination vault with context
|
|
11
|
+
*/
|
|
12
|
+
export declare function promptForDestinationVault(): Promise<string>;
|
|
13
|
+
//# sourceMappingURL=vaultSelector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vaultSelector.d.ts","sourceRoot":"","sources":["../../../src/cli/prompts/vaultSelector.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA2CzE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,CAK5D;AAED;;GAEG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,CAAC,CAKjE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { input, confirm } from '@inquirer/prompts';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { ObsidianVault } from '../../vault/index.js';
|
|
4
|
+
import { theme, formatPath } from '../ui/colors.js';
|
|
5
|
+
import { logWarning } from '../ui/output.js';
|
|
6
|
+
import { browseForDirectory } from './fileBrowser.js';
|
|
7
|
+
/**
|
|
8
|
+
* Prompt the user to enter or browse for a vault path
|
|
9
|
+
*/
|
|
10
|
+
export async function promptForVaultPath(message) {
|
|
11
|
+
const useBrowser = await confirm({
|
|
12
|
+
message: 'Would you like to browse for the folder?',
|
|
13
|
+
default: true,
|
|
14
|
+
});
|
|
15
|
+
let selectedPath;
|
|
16
|
+
if (useBrowser) {
|
|
17
|
+
selectedPath = await browseForDirectory(process.cwd());
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
selectedPath = await input({
|
|
21
|
+
message,
|
|
22
|
+
validate: async (value) => {
|
|
23
|
+
if (!value.trim()) {
|
|
24
|
+
return 'Path is required';
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const resolvedPath = path.resolve(selectedPath);
|
|
31
|
+
// Validate it's an Obsidian vault
|
|
32
|
+
const vault = new ObsidianVault({ vaultPath: resolvedPath });
|
|
33
|
+
const isVault = await vault.isObsidianVault(resolvedPath);
|
|
34
|
+
if (!isVault) {
|
|
35
|
+
logWarning(`${formatPath(resolvedPath)} is not an Obsidian vault (no .obsidian directory)`);
|
|
36
|
+
const continueAnyway = await confirm({
|
|
37
|
+
message: 'Continue anyway?',
|
|
38
|
+
default: false,
|
|
39
|
+
});
|
|
40
|
+
if (!continueAnyway) {
|
|
41
|
+
// Recursively prompt again
|
|
42
|
+
return promptForVaultPath(message);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return resolvedPath;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Prompt for source vault with context
|
|
49
|
+
*/
|
|
50
|
+
export async function promptForSourceVault() {
|
|
51
|
+
console.log(theme.bold('\nSelect source vault'));
|
|
52
|
+
console.log(theme.muted('This is the vault you want to sync FROM\n'));
|
|
53
|
+
return promptForVaultPath('Enter source vault path:');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Prompt for destination vault with context
|
|
57
|
+
*/
|
|
58
|
+
export async function promptForDestinationVault() {
|
|
59
|
+
console.log(theme.bold('\nSelect destination vault'));
|
|
60
|
+
console.log(theme.muted('This is the vault you want to sync TO\n'));
|
|
61
|
+
return promptForVaultPath('Enter destination vault path:');
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=vaultSelector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vaultSelector.js","sourceRoot":"","sources":["../../../src/cli/prompts/vaultSelector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAe;IACtD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC;QAC/B,OAAO,EAAE,0CAA0C;QACnD,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,IAAI,YAAoB,CAAC;IAEzB,IAAI,UAAU,EAAE,CAAC;QACf,YAAY,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,MAAM,KAAK,CAAC;YACzB,OAAO;YACP,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBACxB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;oBAClB,OAAO,kBAAkB,CAAC;gBAC5B,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAEhD,kCAAkC;IAClC,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAE1D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,UAAU,CAAC,GAAG,UAAU,CAAC,YAAY,CAAC,oDAAoD,CAAC,CAAC;QAE5F,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC;YACnC,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,2BAA2B;YAC3B,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC;IAEtE,OAAO,kBAAkB,CAAC,0BAA0B,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC,CAAC;IAEpE,OAAO,kBAAkB,CAAC,+BAA+B,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic color theme for consistent CLI output
|
|
3
|
+
*/
|
|
4
|
+
export declare const theme: {
|
|
5
|
+
success: import("picocolors/types").Formatter;
|
|
6
|
+
error: import("picocolors/types").Formatter;
|
|
7
|
+
warning: import("picocolors/types").Formatter;
|
|
8
|
+
info: import("picocolors/types").Formatter;
|
|
9
|
+
muted: import("picocolors/types").Formatter;
|
|
10
|
+
highlight: import("picocolors/types").Formatter;
|
|
11
|
+
cyan: import("picocolors/types").Formatter;
|
|
12
|
+
bold: import("picocolors/types").Formatter;
|
|
13
|
+
dim: import("picocolors/types").Formatter;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Unicode symbols for status indicators
|
|
17
|
+
*/
|
|
18
|
+
export declare const symbols: {
|
|
19
|
+
success: string;
|
|
20
|
+
error: string;
|
|
21
|
+
warning: string;
|
|
22
|
+
info: string;
|
|
23
|
+
arrow: string;
|
|
24
|
+
bullet: string;
|
|
25
|
+
folder: string;
|
|
26
|
+
vault: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Format a label with a value
|
|
30
|
+
*/
|
|
31
|
+
export declare function label(name: string, value: string | number): string;
|
|
32
|
+
/**
|
|
33
|
+
* Format a path for display
|
|
34
|
+
*/
|
|
35
|
+
export declare function formatPath(filePath: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Format a number with appropriate color based on value
|
|
38
|
+
*/
|
|
39
|
+
export declare function formatCount(count: number, options?: {
|
|
40
|
+
zeroMuted?: boolean;
|
|
41
|
+
}): string;
|
|
42
|
+
/**
|
|
43
|
+
* Create a header/title line
|
|
44
|
+
*/
|
|
45
|
+
export declare function header(text: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Create a section divider
|
|
48
|
+
*/
|
|
49
|
+
export declare function divider(width?: number): string;
|
|
50
|
+
//# sourceMappingURL=colors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../../src/cli/ui/colors.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,KAAK;;;;;;;;;;CAUjB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO;;;;;;;;;CASnB,CAAC;AAEF;;GAEG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAElE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAKpF;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,GAAE,MAAW,GAAG,MAAM,CAElD"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
/**
|
|
3
|
+
* Semantic color theme for consistent CLI output
|
|
4
|
+
*/
|
|
5
|
+
export const theme = {
|
|
6
|
+
success: pc.green,
|
|
7
|
+
error: pc.red,
|
|
8
|
+
warning: pc.yellow,
|
|
9
|
+
info: pc.blue,
|
|
10
|
+
muted: pc.gray,
|
|
11
|
+
highlight: pc.cyan,
|
|
12
|
+
cyan: pc.cyan,
|
|
13
|
+
bold: pc.bold,
|
|
14
|
+
dim: pc.dim,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Unicode symbols for status indicators
|
|
18
|
+
*/
|
|
19
|
+
export const symbols = {
|
|
20
|
+
success: pc.green('\u2713'), // ✓
|
|
21
|
+
error: pc.red('\u2717'), // ✗
|
|
22
|
+
warning: pc.yellow('\u26A0'), // ⚠
|
|
23
|
+
info: pc.blue('\u2139'), // ℹ
|
|
24
|
+
arrow: pc.cyan('\u2192'), // →
|
|
25
|
+
bullet: pc.dim('\u2022'), // •
|
|
26
|
+
folder: '\uD83D\uDCC1', // 📁
|
|
27
|
+
vault: '\uD83D\uDDC4\uFE0F', // 🗄️
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Format a label with a value
|
|
31
|
+
*/
|
|
32
|
+
export function label(name, value) {
|
|
33
|
+
return `${pc.dim(name + ':')} ${value}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Format a path for display
|
|
37
|
+
*/
|
|
38
|
+
export function formatPath(filePath) {
|
|
39
|
+
return pc.cyan(filePath);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Format a number with appropriate color based on value
|
|
43
|
+
*/
|
|
44
|
+
export function formatCount(count, options) {
|
|
45
|
+
if (count === 0 && options?.zeroMuted) {
|
|
46
|
+
return pc.dim('0');
|
|
47
|
+
}
|
|
48
|
+
return count > 0 ? pc.bold(String(count)) : String(count);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create a header/title line
|
|
52
|
+
*/
|
|
53
|
+
export function header(text) {
|
|
54
|
+
return pc.bold(pc.underline(text));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create a section divider
|
|
58
|
+
*/
|
|
59
|
+
export function divider(width = 40) {
|
|
60
|
+
return pc.dim('\u2500'.repeat(width));
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../../src/cli/ui/colors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,OAAO,EAAE,EAAE,CAAC,KAAK;IACjB,KAAK,EAAE,EAAE,CAAC,GAAG;IACb,OAAO,EAAE,EAAE,CAAC,MAAM;IAClB,IAAI,EAAE,EAAE,CAAC,IAAI;IACb,KAAK,EAAE,EAAE,CAAC,IAAI;IACd,SAAS,EAAE,EAAE,CAAC,IAAI;IAClB,IAAI,EAAE,EAAE,CAAC,IAAI;IACb,IAAI,EAAE,EAAE,CAAC,IAAI;IACb,GAAG,EAAE,EAAE,CAAC,GAAG;CACZ,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,IAAI;IACjC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI;IAC7B,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI;IAClC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI;IAC7B,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI;IAC9B,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI;IAC9B,MAAM,EAAE,cAAc,EAAE,KAAK;IAC7B,KAAK,EAAE,oBAAoB,EAAE,MAAM;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,KAAsB;IACxD,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,OAAO,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,OAAiC;IAC1E,IAAI,KAAK,KAAK,CAAC,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;QACtC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,QAAgB,EAAE;IACxC,OAAO,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log a success message with a green checkmark
|
|
3
|
+
*/
|
|
4
|
+
export declare function logSuccess(message: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Log an error message with a red X
|
|
7
|
+
*/
|
|
8
|
+
export declare function logError(message: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Log a warning message with a yellow warning sign
|
|
11
|
+
*/
|
|
12
|
+
export declare function logWarning(message: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Log an info message with a blue info symbol
|
|
15
|
+
*/
|
|
16
|
+
export declare function logInfo(message: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Log a muted/dimmed message
|
|
19
|
+
*/
|
|
20
|
+
export declare function logMuted(message: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Log a blank line
|
|
23
|
+
*/
|
|
24
|
+
export declare function logBlank(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Log a key-value pair with formatting
|
|
27
|
+
*/
|
|
28
|
+
export declare function logKeyValue(key: string, value: string | number, indent?: number): void;
|
|
29
|
+
/**
|
|
30
|
+
* Log a section header
|
|
31
|
+
*/
|
|
32
|
+
export declare function logHeader(title: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Log a list item with a bullet point
|
|
35
|
+
*/
|
|
36
|
+
export declare function logListItem(item: string, indent?: number): void;
|
|
37
|
+
/**
|
|
38
|
+
* Print an error and exit the process
|
|
39
|
+
*/
|
|
40
|
+
export declare function exitWithError(message: string, code?: number): never;
|
|
41
|
+
/**
|
|
42
|
+
* Check if running in interactive mode
|
|
43
|
+
*/
|
|
44
|
+
export declare function requireInteractive(featureName: string): void;
|
|
45
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/cli/ui/output.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMhD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAM9C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMhD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAM7C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAM9C;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,IAAI,CAE/B;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI,CAOzF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAQ7C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI,CAOlE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAU,GAAG,KAAK,CAGtE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAM5D"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { theme, symbols } from './colors.js';
|
|
2
|
+
import { isInteractive, supportsColor } from '../utils/terminal.js';
|
|
3
|
+
/**
|
|
4
|
+
* Log a success message with a green checkmark
|
|
5
|
+
*/
|
|
6
|
+
export function logSuccess(message) {
|
|
7
|
+
if (supportsColor()) {
|
|
8
|
+
console.log(`${symbols.success} ${theme.success(message)}`);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
console.log(`[OK] ${message}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Log an error message with a red X
|
|
16
|
+
*/
|
|
17
|
+
export function logError(message) {
|
|
18
|
+
if (supportsColor()) {
|
|
19
|
+
console.error(`${symbols.error} ${theme.error(message)}`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.error(`[ERROR] ${message}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Log a warning message with a yellow warning sign
|
|
27
|
+
*/
|
|
28
|
+
export function logWarning(message) {
|
|
29
|
+
if (supportsColor()) {
|
|
30
|
+
console.log(`${symbols.warning} ${theme.warning(message)}`);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.log(`[WARN] ${message}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Log an info message with a blue info symbol
|
|
38
|
+
*/
|
|
39
|
+
export function logInfo(message) {
|
|
40
|
+
if (supportsColor()) {
|
|
41
|
+
console.log(`${symbols.info} ${theme.info(message)}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.log(`[INFO] ${message}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Log a muted/dimmed message
|
|
49
|
+
*/
|
|
50
|
+
export function logMuted(message) {
|
|
51
|
+
if (supportsColor()) {
|
|
52
|
+
console.log(theme.muted(message));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.log(message);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Log a blank line
|
|
60
|
+
*/
|
|
61
|
+
export function logBlank() {
|
|
62
|
+
console.log();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Log a key-value pair with formatting
|
|
66
|
+
*/
|
|
67
|
+
export function logKeyValue(key, value, indent = 0) {
|
|
68
|
+
const padding = ' '.repeat(indent);
|
|
69
|
+
if (supportsColor()) {
|
|
70
|
+
console.log(`${padding}${theme.dim(key + ':')} ${value}`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.log(`${padding}${key}: ${value}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Log a section header
|
|
78
|
+
*/
|
|
79
|
+
export function logHeader(title) {
|
|
80
|
+
logBlank();
|
|
81
|
+
if (supportsColor()) {
|
|
82
|
+
console.log(theme.bold(title));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
console.log(title);
|
|
86
|
+
console.log('='.repeat(title.length));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Log a list item with a bullet point
|
|
91
|
+
*/
|
|
92
|
+
export function logListItem(item, indent = 2) {
|
|
93
|
+
const padding = ' '.repeat(indent);
|
|
94
|
+
if (supportsColor()) {
|
|
95
|
+
console.log(`${padding}${symbols.bullet} ${item}`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.log(`${padding}- ${item}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Print an error and exit the process
|
|
103
|
+
*/
|
|
104
|
+
export function exitWithError(message, code = 1) {
|
|
105
|
+
logError(message);
|
|
106
|
+
process.exit(code);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if running in interactive mode
|
|
110
|
+
*/
|
|
111
|
+
export function requireInteractive(featureName) {
|
|
112
|
+
if (!isInteractive()) {
|
|
113
|
+
exitWithError(`${featureName} requires an interactive terminal. Please provide all required options via command line flags.`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/cli/ui/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spinner instance interface for consistent API
|
|
3
|
+
*/
|
|
4
|
+
export interface SpinnerInstance {
|
|
5
|
+
start(): SpinnerInstance;
|
|
6
|
+
stop(): SpinnerInstance;
|
|
7
|
+
succeed(text?: string): SpinnerInstance;
|
|
8
|
+
fail(text?: string): SpinnerInstance;
|
|
9
|
+
warn(text?: string): SpinnerInstance;
|
|
10
|
+
info(text?: string): SpinnerInstance;
|
|
11
|
+
text: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a spinner with consistent styling
|
|
15
|
+
* Falls back to simple text output in non-interactive mode
|
|
16
|
+
*/
|
|
17
|
+
export declare function createSpinner(text: string): SpinnerInstance;
|
|
18
|
+
/**
|
|
19
|
+
* Create a spinner and immediately start it
|
|
20
|
+
*/
|
|
21
|
+
export declare function startSpinner(text: string): SpinnerInstance;
|
|
22
|
+
/**
|
|
23
|
+
* Run an async operation with a spinner
|
|
24
|
+
*/
|
|
25
|
+
export declare function withSpinner<T>(text: string, operation: () => Promise<T>, options?: {
|
|
26
|
+
successText?: string | ((result: T) => string);
|
|
27
|
+
failText?: string;
|
|
28
|
+
}): Promise<T>;
|
|
29
|
+
//# sourceMappingURL=spinner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../../src/cli/ui/spinner.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,IAAI,eAAe,CAAC;IACzB,IAAI,IAAI,eAAe,CAAC;IACxB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IACxC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IACrC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IACrC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAkDD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAU3D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAG1D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,CAAC,EAAE;IACR,WAAW,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,OAAO,CAAC,CAAC,CAAC,CAeZ"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import ora from 'ora';
|
|
2
|
+
import { isInteractive } from '../utils/terminal.js';
|
|
3
|
+
/**
|
|
4
|
+
* Non-interactive fallback spinner that just logs text
|
|
5
|
+
*/
|
|
6
|
+
class FallbackSpinner {
|
|
7
|
+
_text;
|
|
8
|
+
constructor(text) {
|
|
9
|
+
this._text = text;
|
|
10
|
+
}
|
|
11
|
+
get text() {
|
|
12
|
+
return this._text;
|
|
13
|
+
}
|
|
14
|
+
set text(value) {
|
|
15
|
+
this._text = value;
|
|
16
|
+
}
|
|
17
|
+
start() {
|
|
18
|
+
console.log(`[...] ${this._text}`);
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
stop() {
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
succeed(text) {
|
|
25
|
+
console.log(`[OK] ${text || this._text}`);
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
fail(text) {
|
|
29
|
+
console.error(`[FAIL] ${text || this._text}`);
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
warn(text) {
|
|
33
|
+
console.log(`[WARN] ${text || this._text}`);
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
info(text) {
|
|
37
|
+
console.log(`[INFO] ${text || this._text}`);
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a spinner with consistent styling
|
|
43
|
+
* Falls back to simple text output in non-interactive mode
|
|
44
|
+
*/
|
|
45
|
+
export function createSpinner(text) {
|
|
46
|
+
if (!isInteractive()) {
|
|
47
|
+
return new FallbackSpinner(text);
|
|
48
|
+
}
|
|
49
|
+
return ora({
|
|
50
|
+
text,
|
|
51
|
+
spinner: 'dots',
|
|
52
|
+
color: 'cyan',
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Create a spinner and immediately start it
|
|
57
|
+
*/
|
|
58
|
+
export function startSpinner(text) {
|
|
59
|
+
const spinner = createSpinner(text);
|
|
60
|
+
return spinner.start();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Run an async operation with a spinner
|
|
64
|
+
*/
|
|
65
|
+
export async function withSpinner(text, operation, options) {
|
|
66
|
+
const spinner = startSpinner(text);
|
|
67
|
+
try {
|
|
68
|
+
const result = await operation();
|
|
69
|
+
const successText = typeof options?.successText === 'function'
|
|
70
|
+
? options.successText(result)
|
|
71
|
+
: options?.successText;
|
|
72
|
+
spinner.succeed(successText);
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
spinner.fail(options?.failText);
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../../src/cli/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAerD;;GAEG;AACH,MAAM,eAAe;IACX,KAAK,CAAS;IAEtB,YAAY,IAAY;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,IAAI,CAAC,KAAa;QACpB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,KAAK;QACH,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,IAAa;QACnB,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,IAAa;QAChB,OAAO,CAAC,KAAK,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,IAAa;QAChB,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,IAAa;QAChB,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;QACrB,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,GAAG,CAAC;QACT,IAAI;QACJ,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,MAAM;KACd,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,SAA2B,EAC3B,OAGC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,WAAW,GACf,OAAO,OAAO,EAAE,WAAW,KAAK,UAAU;YACxC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC;YAC7B,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC;QAC3B,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAChC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SyncResult } from '../../sync/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Format sync results as formatted text
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatSyncResultTable(result: SyncResult): string;
|
|
6
|
+
/**
|
|
7
|
+
* Format vault status information
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatVaultInfoTable(info: {
|
|
10
|
+
name: string;
|
|
11
|
+
path: string;
|
|
12
|
+
fileCount: number;
|
|
13
|
+
totalSize: string;
|
|
14
|
+
lastModified: string;
|
|
15
|
+
}): string;
|
|
16
|
+
/**
|
|
17
|
+
* Format sync status
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatSyncStatusTable(status: {
|
|
20
|
+
syncId: string;
|
|
21
|
+
lastSync: string;
|
|
22
|
+
trackedFiles: number;
|
|
23
|
+
}): string;
|
|
24
|
+
/**
|
|
25
|
+
* Format a list of files with an optional header
|
|
26
|
+
*/
|
|
27
|
+
export declare function formatFileList(files: string[], header: string, maxItems?: number): string;
|
|
28
|
+
//# sourceMappingURL=table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/cli/ui/table.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAqDhE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAsBT;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAoBT;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAAW,GACpB,MAAM,CAmBR"}
|