opencode-account-manager 0.4.1

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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +266 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +183 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/core/accounts.d.ts +19 -0
  8. package/dist/core/accounts.d.ts.map +1 -0
  9. package/dist/core/accounts.js +181 -0
  10. package/dist/core/accounts.js.map +1 -0
  11. package/dist/core/config-store.d.ts +48 -0
  12. package/dist/core/config-store.d.ts.map +1 -0
  13. package/dist/core/config-store.js +206 -0
  14. package/dist/core/config-store.js.map +1 -0
  15. package/dist/core/crypto.d.ts +40 -0
  16. package/dist/core/crypto.d.ts.map +1 -0
  17. package/dist/core/crypto.js +172 -0
  18. package/dist/core/crypto.js.map +1 -0
  19. package/dist/core/importers/amJson.d.ts +17 -0
  20. package/dist/core/importers/amJson.d.ts.map +1 -0
  21. package/dist/core/importers/amJson.js +131 -0
  22. package/dist/core/importers/amJson.js.map +1 -0
  23. package/dist/core/opencode-config.d.ts +92 -0
  24. package/dist/core/opencode-config.d.ts.map +1 -0
  25. package/dist/core/opencode-config.js +148 -0
  26. package/dist/core/opencode-config.js.map +1 -0
  27. package/dist/core/paths.d.ts +5 -0
  28. package/dist/core/paths.d.ts.map +1 -0
  29. package/dist/core/paths.js +38 -0
  30. package/dist/core/paths.js.map +1 -0
  31. package/dist/core/types.d.ts +74 -0
  32. package/dist/core/types.d.ts.map +1 -0
  33. package/dist/core/types.js +30 -0
  34. package/dist/core/types.js.map +1 -0
  35. package/dist/core/utils.d.ts +5 -0
  36. package/dist/core/utils.d.ts.map +1 -0
  37. package/dist/core/utils.js +35 -0
  38. package/dist/core/utils.js.map +1 -0
  39. package/dist/tui/Dashboard.d.ts +7 -0
  40. package/dist/tui/Dashboard.d.ts.map +1 -0
  41. package/dist/tui/Dashboard.js +331 -0
  42. package/dist/tui/Dashboard.js.map +1 -0
  43. package/dist/tui/components/AccountList.d.ts +18 -0
  44. package/dist/tui/components/AccountList.d.ts.map +1 -0
  45. package/dist/tui/components/AccountList.js +92 -0
  46. package/dist/tui/components/AccountList.js.map +1 -0
  47. package/dist/tui/components/Box.d.ts +11 -0
  48. package/dist/tui/components/Box.d.ts.map +1 -0
  49. package/dist/tui/components/Box.js +15 -0
  50. package/dist/tui/components/Box.js.map +1 -0
  51. package/dist/tui/components/ExportModal.d.ts +10 -0
  52. package/dist/tui/components/ExportModal.d.ts.map +1 -0
  53. package/dist/tui/components/ExportModal.js +192 -0
  54. package/dist/tui/components/ExportModal.js.map +1 -0
  55. package/dist/tui/components/FileBrowser.d.ts +12 -0
  56. package/dist/tui/components/FileBrowser.d.ts.map +1 -0
  57. package/dist/tui/components/FileBrowser.js +349 -0
  58. package/dist/tui/components/FileBrowser.js.map +1 -0
  59. package/dist/tui/components/Header.d.ts +8 -0
  60. package/dist/tui/components/Header.d.ts.map +1 -0
  61. package/dist/tui/components/Header.js +20 -0
  62. package/dist/tui/components/Header.js.map +1 -0
  63. package/dist/tui/components/ImportModal.d.ts +10 -0
  64. package/dist/tui/components/ImportModal.d.ts.map +1 -0
  65. package/dist/tui/components/ImportModal.js +215 -0
  66. package/dist/tui/components/ImportModal.js.map +1 -0
  67. package/dist/tui/components/McpServerList.d.ts +8 -0
  68. package/dist/tui/components/McpServerList.d.ts.map +1 -0
  69. package/dist/tui/components/McpServerList.js +35 -0
  70. package/dist/tui/components/McpServerList.js.map +1 -0
  71. package/dist/tui/components/Menu.d.ts +10 -0
  72. package/dist/tui/components/Menu.d.ts.map +1 -0
  73. package/dist/tui/components/Menu.js +83 -0
  74. package/dist/tui/components/Menu.js.map +1 -0
  75. package/dist/tui/components/PasswordInput.d.ts +12 -0
  76. package/dist/tui/components/PasswordInput.d.ts.map +1 -0
  77. package/dist/tui/components/PasswordInput.js +130 -0
  78. package/dist/tui/components/PasswordInput.js.map +1 -0
  79. package/dist/tui/components/ProviderList.d.ts +8 -0
  80. package/dist/tui/components/ProviderList.d.ts.map +1 -0
  81. package/dist/tui/components/ProviderList.js +37 -0
  82. package/dist/tui/components/ProviderList.js.map +1 -0
  83. package/dist/tui/components/SectionBox.d.ts +10 -0
  84. package/dist/tui/components/SectionBox.d.ts.map +1 -0
  85. package/dist/tui/components/SectionBox.js +16 -0
  86. package/dist/tui/components/SectionBox.js.map +1 -0
  87. package/dist/tui/components/StatsRow.d.ts +13 -0
  88. package/dist/tui/components/StatsRow.d.ts.map +1 -0
  89. package/dist/tui/components/StatsRow.js +18 -0
  90. package/dist/tui/components/StatsRow.js.map +1 -0
  91. package/dist/tui/components/StatusBadge.d.ts +8 -0
  92. package/dist/tui/components/StatusBadge.d.ts.map +1 -0
  93. package/dist/tui/components/StatusBadge.js +30 -0
  94. package/dist/tui/components/StatusBadge.js.map +1 -0
  95. package/dist/tui/components/index.d.ts +14 -0
  96. package/dist/tui/components/index.d.ts.map +1 -0
  97. package/dist/tui/components/index.js +32 -0
  98. package/dist/tui/components/index.js.map +1 -0
  99. package/dist/tui/index.d.ts +5 -0
  100. package/dist/tui/index.d.ts.map +1 -0
  101. package/dist/tui/index.js +13 -0
  102. package/dist/tui/index.js.map +1 -0
  103. package/docs/BLUEPRINT.md +476 -0
  104. package/docs/ROADMAP.md +74 -0
  105. package/package.json +38 -0
  106. package/src/cli.ts +207 -0
  107. package/src/core/accounts.ts +215 -0
  108. package/src/core/config-store.ts +212 -0
  109. package/src/core/crypto.ts +162 -0
  110. package/src/core/importers/amJson.ts +185 -0
  111. package/src/core/opencode-config.ts +217 -0
  112. package/src/core/paths.ts +32 -0
  113. package/src/core/types.ts +118 -0
  114. package/src/core/utils.ts +28 -0
  115. package/src/tui/Dashboard.tsx +431 -0
  116. package/src/tui/components/AccountList.tsx +155 -0
  117. package/src/tui/components/Box.tsx +37 -0
  118. package/src/tui/components/ExportModal.tsx +255 -0
  119. package/src/tui/components/FileBrowser.tsx +393 -0
  120. package/src/tui/components/Header.tsx +26 -0
  121. package/src/tui/components/ImportModal.tsx +288 -0
  122. package/src/tui/components/McpServerList.tsx +67 -0
  123. package/src/tui/components/Menu.tsx +103 -0
  124. package/src/tui/components/PasswordInput.tsx +159 -0
  125. package/src/tui/components/ProviderList.tsx +61 -0
  126. package/src/tui/components/SectionBox.tsx +35 -0
  127. package/src/tui/components/StatsRow.tsx +33 -0
  128. package/src/tui/components/StatusBadge.tsx +33 -0
  129. package/src/tui/components/index.ts +13 -0
  130. package/src/tui/index.tsx +11 -0
  131. package/tsconfig.json +20 -0
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.normalizePluginAccounts = normalizePluginAccounts;
7
+ exports.createEmptyPluginAccountsFile = createEmptyPluginAccountsFile;
8
+ exports.readPluginAccountsFile = readPluginAccountsFile;
9
+ exports.writePluginAccountsFile = writePluginAccountsFile;
10
+ exports.mergeAccount = mergeAccount;
11
+ exports.mergeAccounts = mergeAccounts;
12
+ exports.buildPortableExport = buildPortableExport;
13
+ exports.detectImportFormat = detectImportFormat;
14
+ exports.extractAccountsFromImport = extractAccountsFromImport;
15
+ exports.sanitizeAccountForPublic = sanitizeAccountForPublic;
16
+ exports.summarizeAccounts = summarizeAccounts;
17
+ const fs_1 = __importDefault(require("fs"));
18
+ const path_1 = __importDefault(require("path"));
19
+ const paths_1 = require("./paths");
20
+ const utils_1 = require("./utils");
21
+ function isRecord(value) {
22
+ return typeof value === "object" && value !== null;
23
+ }
24
+ function isAccountCandidate(value) {
25
+ if (!isRecord(value))
26
+ return false;
27
+ if (typeof value.email !== "string")
28
+ return false;
29
+ return value.email.includes("@");
30
+ }
31
+ function normalizeAccount(account) {
32
+ return {
33
+ ...account,
34
+ email: account.email.trim(),
35
+ };
36
+ }
37
+ function normalizePluginAccounts(data) {
38
+ const accounts = Array.isArray(data.accounts)
39
+ ? data.accounts.filter(isAccountCandidate).map(normalizeAccount)
40
+ : [];
41
+ return {
42
+ version: typeof data.version === "number" ? data.version : 3,
43
+ accounts,
44
+ activeIndex: typeof data.activeIndex === "number" ? data.activeIndex : undefined,
45
+ activeIndexByFamily: data.activeIndexByFamily && isRecord(data.activeIndexByFamily)
46
+ ? data.activeIndexByFamily
47
+ : undefined,
48
+ };
49
+ }
50
+ function createEmptyPluginAccountsFile() {
51
+ return {
52
+ version: 3,
53
+ accounts: [],
54
+ activeIndex: 0,
55
+ activeIndexByFamily: {},
56
+ };
57
+ }
58
+ function readPluginAccountsFile(filePath) {
59
+ const resolvedPath = (0, paths_1.getPluginAccountsPath)(filePath);
60
+ if (!fs_1.default.existsSync(resolvedPath)) {
61
+ throw new Error(`Plugin accounts file not found at ${resolvedPath}. ` +
62
+ "Login at least one account first or provide --plugin-path.");
63
+ }
64
+ const data = (0, utils_1.readJsonFile)(resolvedPath);
65
+ return normalizePluginAccounts(data);
66
+ }
67
+ function writePluginAccountsFile(filePath, data) {
68
+ const resolvedPath = (0, paths_1.getPluginAccountsPath)(filePath);
69
+ const normalized = normalizePluginAccounts(data);
70
+ const dir = path_1.default.dirname(resolvedPath);
71
+ if (!fs_1.default.existsSync(dir)) {
72
+ fs_1.default.mkdirSync(dir, { recursive: true });
73
+ }
74
+ (0, utils_1.writeJsonFile)(resolvedPath, normalized);
75
+ }
76
+ function mergeRateLimits(existing, incoming) {
77
+ if (!existing && !incoming)
78
+ return undefined;
79
+ return { ...(existing || {}), ...(incoming || {}) };
80
+ }
81
+ function mergeFingerprintHistory(existing, incoming) {
82
+ if (!existing && !incoming)
83
+ return undefined;
84
+ const list = [...(existing || []), ...(incoming || [])];
85
+ return list.length > 0 ? list : undefined;
86
+ }
87
+ function mergeAccount(existing, incoming) {
88
+ return {
89
+ ...existing,
90
+ ...incoming,
91
+ email: incoming.email || existing.email,
92
+ refreshToken: incoming.refreshToken || existing.refreshToken,
93
+ fingerprint: incoming.fingerprint || existing.fingerprint,
94
+ rateLimitResetTimes: mergeRateLimits(existing.rateLimitResetTimes, incoming.rateLimitResetTimes),
95
+ fingerprintHistory: mergeFingerprintHistory(existing.fingerprintHistory, incoming.fingerprintHistory),
96
+ };
97
+ }
98
+ function mergeAccounts(existingFile, incomingAccounts, mode) {
99
+ const base = normalizePluginAccounts(existingFile);
100
+ const incoming = incomingAccounts
101
+ .filter(isAccountCandidate)
102
+ .map(normalizeAccount);
103
+ if (mode === "replace") {
104
+ return {
105
+ version: base.version || 3,
106
+ accounts: incoming,
107
+ activeIndex: 0,
108
+ activeIndexByFamily: {},
109
+ };
110
+ }
111
+ const byEmail = new Map();
112
+ for (const account of base.accounts) {
113
+ byEmail.set((0, utils_1.toLowerTrim)(account.email), account);
114
+ }
115
+ for (const account of incoming) {
116
+ const key = (0, utils_1.toLowerTrim)(account.email);
117
+ const existing = byEmail.get(key);
118
+ if (existing) {
119
+ byEmail.set(key, mergeAccount(existing, account));
120
+ }
121
+ else {
122
+ byEmail.set(key, account);
123
+ }
124
+ }
125
+ return {
126
+ ...base,
127
+ accounts: Array.from(byEmail.values()),
128
+ };
129
+ }
130
+ function buildPortableExport(accounts) {
131
+ return {
132
+ version: 1,
133
+ exportedAt: Date.now(),
134
+ exportedFrom: "antigravity-sync",
135
+ accounts: accounts.map(normalizeAccount),
136
+ };
137
+ }
138
+ function detectImportFormat(data) {
139
+ if (!isRecord(data))
140
+ return "unknown";
141
+ if (data.exportedFrom === "antigravity-sync")
142
+ return "portable";
143
+ if (typeof data.version === "number" && Array.isArray(data.accounts)) {
144
+ return "plugin";
145
+ }
146
+ return "unknown";
147
+ }
148
+ function extractAccountsFromImport(data, format) {
149
+ if (Array.isArray(data)) {
150
+ return data.filter(isAccountCandidate).map(normalizeAccount);
151
+ }
152
+ if (!isRecord(data)) {
153
+ throw new Error("Import data must be an object or an array of accounts.");
154
+ }
155
+ const detected = format || detectImportFormat(data);
156
+ if (detected === "unknown") {
157
+ throw new Error("Unsupported import format. Provide a portable export or plugin file.");
158
+ }
159
+ const accounts = Array.isArray(data.accounts) ? data.accounts : [];
160
+ return accounts.filter(isAccountCandidate).map(normalizeAccount);
161
+ }
162
+ function sanitizeAccountForPublic(account) {
163
+ const { refreshToken, ...rest } = account;
164
+ return rest;
165
+ }
166
+ function summarizeAccounts(accounts) {
167
+ const now = Date.now();
168
+ let limited = 0;
169
+ for (const account of accounts) {
170
+ const resets = account.rateLimitResetTimes || {};
171
+ const isLimited = Object.values(resets).some((value) => value > now);
172
+ if (isLimited)
173
+ limited += 1;
174
+ }
175
+ return {
176
+ total: accounts.length,
177
+ limited,
178
+ available: accounts.length - limited,
179
+ };
180
+ }
181
+ //# sourceMappingURL=accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../src/core/accounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ export interface AppConfig {
2
+ lastExportFolder?: string;
3
+ lastImportFolder?: string;
4
+ defaultExportFormat?: "encrypted" | "plain";
5
+ recentFolders?: string[];
6
+ }
7
+ /**
8
+ * Get the full path to config file
9
+ */
10
+ export declare function getConfigPath(): string;
11
+ /**
12
+ * Read config file, return empty config if not exists
13
+ */
14
+ export declare function readConfig(): AppConfig;
15
+ /**
16
+ * Write config file
17
+ */
18
+ export declare function writeConfig(config: AppConfig): void;
19
+ /**
20
+ * Update last export folder and add to recent folders
21
+ */
22
+ export declare function updateLastExportFolder(folder: string): void;
23
+ /**
24
+ * Update last import folder and add to recent folders
25
+ */
26
+ export declare function updateLastImportFolder(folder: string): void;
27
+ /**
28
+ * Get recent folders list
29
+ */
30
+ export declare function getRecentFolders(): string[];
31
+ /**
32
+ * Get last export folder or default
33
+ */
34
+ export declare function getLastExportFolder(): string;
35
+ /**
36
+ * Get last import folder or default
37
+ */
38
+ export declare function getLastImportFolder(): string;
39
+ export interface QuickLocation {
40
+ label: string;
41
+ path: string;
42
+ exists: boolean;
43
+ }
44
+ /**
45
+ * Get list of quick locations for file browser
46
+ */
47
+ export declare function getQuickLocations(): QuickLocation[];
48
+ //# sourceMappingURL=config-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../../src/core/config-store.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,SAAS;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAwBD;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAMD;;GAEG;AACH,wBAAgB,UAAU,IAAI,SAAS,CAatC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAWnD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAK3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAK3D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAG3C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAG5C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAG5C;AA2BD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,EAAE,CAmDnD"}
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getConfigPath = getConfigPath;
37
+ exports.readConfig = readConfig;
38
+ exports.writeConfig = writeConfig;
39
+ exports.updateLastExportFolder = updateLastExportFolder;
40
+ exports.updateLastImportFolder = updateLastImportFolder;
41
+ exports.getRecentFolders = getRecentFolders;
42
+ exports.getLastExportFolder = getLastExportFolder;
43
+ exports.getLastImportFolder = getLastImportFolder;
44
+ exports.getQuickLocations = getQuickLocations;
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const os = __importStar(require("os"));
48
+ // ============================================================================
49
+ // Constants
50
+ // ============================================================================
51
+ const CONFIG_FILENAME = "ocam-config.json";
52
+ const MAX_RECENT_FOLDERS = 5;
53
+ // ============================================================================
54
+ // Path Functions
55
+ // ============================================================================
56
+ /**
57
+ * Get the config directory path
58
+ */
59
+ function getConfigDir() {
60
+ if (process.platform === "win32") {
61
+ const appData = process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
62
+ return path.join(appData, "opencode");
63
+ }
64
+ return path.join(os.homedir(), ".config", "opencode");
65
+ }
66
+ /**
67
+ * Get the full path to config file
68
+ */
69
+ function getConfigPath() {
70
+ return path.join(getConfigDir(), CONFIG_FILENAME);
71
+ }
72
+ // ============================================================================
73
+ // Config Functions
74
+ // ============================================================================
75
+ /**
76
+ * Read config file, return empty config if not exists
77
+ */
78
+ function readConfig() {
79
+ const configPath = getConfigPath();
80
+ if (!fs.existsSync(configPath)) {
81
+ return {};
82
+ }
83
+ try {
84
+ const content = fs.readFileSync(configPath, "utf-8");
85
+ return JSON.parse(content);
86
+ }
87
+ catch {
88
+ return {};
89
+ }
90
+ }
91
+ /**
92
+ * Write config file
93
+ */
94
+ function writeConfig(config) {
95
+ const configPath = getConfigPath();
96
+ const configDir = path.dirname(configPath);
97
+ // Ensure directory exists
98
+ if (!fs.existsSync(configDir)) {
99
+ fs.mkdirSync(configDir, { recursive: true });
100
+ }
101
+ const content = JSON.stringify(config, null, 2);
102
+ fs.writeFileSync(configPath, content, "utf-8");
103
+ }
104
+ /**
105
+ * Update last export folder and add to recent folders
106
+ */
107
+ function updateLastExportFolder(folder) {
108
+ const config = readConfig();
109
+ config.lastExportFolder = folder;
110
+ config.recentFolders = addToRecentFolders(config.recentFolders || [], folder);
111
+ writeConfig(config);
112
+ }
113
+ /**
114
+ * Update last import folder and add to recent folders
115
+ */
116
+ function updateLastImportFolder(folder) {
117
+ const config = readConfig();
118
+ config.lastImportFolder = folder;
119
+ config.recentFolders = addToRecentFolders(config.recentFolders || [], folder);
120
+ writeConfig(config);
121
+ }
122
+ /**
123
+ * Get recent folders list
124
+ */
125
+ function getRecentFolders() {
126
+ const config = readConfig();
127
+ return config.recentFolders || [];
128
+ }
129
+ /**
130
+ * Get last export folder or default
131
+ */
132
+ function getLastExportFolder() {
133
+ const config = readConfig();
134
+ return config.lastExportFolder || process.cwd();
135
+ }
136
+ /**
137
+ * Get last import folder or default
138
+ */
139
+ function getLastImportFolder() {
140
+ const config = readConfig();
141
+ return config.lastImportFolder || process.cwd();
142
+ }
143
+ // ============================================================================
144
+ // Helper Functions
145
+ // ============================================================================
146
+ /**
147
+ * Add folder to recent list, keeping max items and removing duplicates
148
+ */
149
+ function addToRecentFolders(recent, folder) {
150
+ // Normalize path
151
+ const normalized = path.normalize(folder);
152
+ // Remove if already exists
153
+ const filtered = recent.filter(f => path.normalize(f) !== normalized);
154
+ // Add to front
155
+ filtered.unshift(normalized);
156
+ // Keep only max items
157
+ return filtered.slice(0, MAX_RECENT_FOLDERS);
158
+ }
159
+ /**
160
+ * Get list of quick locations for file browser
161
+ */
162
+ function getQuickLocations() {
163
+ const home = os.homedir();
164
+ const locations = [];
165
+ // Current directory
166
+ locations.push({
167
+ label: "Current Directory",
168
+ path: process.cwd(),
169
+ exists: true,
170
+ });
171
+ // Desktop
172
+ const desktop = path.join(home, "Desktop");
173
+ locations.push({
174
+ label: "Desktop",
175
+ path: desktop,
176
+ exists: fs.existsSync(desktop),
177
+ });
178
+ // Documents
179
+ const documents = path.join(home, "Documents");
180
+ locations.push({
181
+ label: "Documents",
182
+ path: documents,
183
+ exists: fs.existsSync(documents),
184
+ });
185
+ // Downloads
186
+ const downloads = path.join(home, "Downloads");
187
+ locations.push({
188
+ label: "Downloads",
189
+ path: downloads,
190
+ exists: fs.existsSync(downloads),
191
+ });
192
+ // Last export folder (if different from above)
193
+ const config = readConfig();
194
+ if (config.lastExportFolder && fs.existsSync(config.lastExportFolder)) {
195
+ const isAlreadyListed = locations.some(loc => path.normalize(loc.path) === path.normalize(config.lastExportFolder));
196
+ if (!isAlreadyListed) {
197
+ locations.push({
198
+ label: "Recent Export",
199
+ path: config.lastExportFolder,
200
+ exists: true,
201
+ });
202
+ }
203
+ }
204
+ return locations.filter(loc => loc.exists);
205
+ }
206
+ //# sourceMappingURL=config-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../../src/core/config-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export interface EncryptedData {
2
+ salt: string;
3
+ iv: string;
4
+ authTag: string;
5
+ data: string;
6
+ }
7
+ /**
8
+ * Generate a random salt for encryption
9
+ */
10
+ export declare function generateSalt(): string;
11
+ /**
12
+ * Generate a random IV for encryption
13
+ */
14
+ export declare function generateIV(): string;
15
+ /**
16
+ * Encrypt data object with password using AES-256-GCM
17
+ *
18
+ * @param data - Object to encrypt (will be JSON stringified)
19
+ * @param password - Password for encryption
20
+ * @returns Encrypted data with salt, iv, authTag, and encrypted content
21
+ */
22
+ export declare function encrypt(data: object, password: string): EncryptedData;
23
+ /**
24
+ * Decrypt data with password using AES-256-GCM
25
+ *
26
+ * @param encrypted - Encrypted data object
27
+ * @param password - Password for decryption
28
+ * @returns Decrypted object
29
+ * @throws Error if password is wrong or data is corrupted
30
+ */
31
+ export declare function decrypt<T = unknown>(encrypted: EncryptedData, password: string): T;
32
+ /**
33
+ * Verify if a password can decrypt the data
34
+ *
35
+ * @param encrypted - Encrypted data object
36
+ * @param password - Password to verify
37
+ * @returns true if password is correct
38
+ */
39
+ export declare function verifyPassword(encrypted: EncryptedData, password: string): boolean;
40
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/core/crypto.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AA4BD;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CA6BrE;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,CA+BlF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOlF"}
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.generateSalt = generateSalt;
37
+ exports.generateIV = generateIV;
38
+ exports.encrypt = encrypt;
39
+ exports.decrypt = decrypt;
40
+ exports.verifyPassword = verifyPassword;
41
+ const crypto = __importStar(require("crypto"));
42
+ // ============================================================================
43
+ // Constants
44
+ // ============================================================================
45
+ const ALGORITHM = "aes-256-gcm";
46
+ const KEY_LENGTH = 32; // 256 bits
47
+ const SALT_LENGTH = 32; // 256 bits
48
+ const IV_LENGTH = 12; // 96 bits (recommended for GCM)
49
+ const AUTH_TAG_LENGTH = 16; // 128 bits
50
+ // scrypt parameters (N=16384, r=8, p=1)
51
+ const SCRYPT_N = 16384;
52
+ const SCRYPT_R = 8;
53
+ const SCRYPT_P = 1;
54
+ // ============================================================================
55
+ // Helper Functions
56
+ // ============================================================================
57
+ /**
58
+ * Generate random bytes and return as hex string
59
+ */
60
+ function randomHex(length) {
61
+ return crypto.randomBytes(length).toString("hex");
62
+ }
63
+ /**
64
+ * Derive encryption key from password using scrypt
65
+ */
66
+ function deriveKey(password, salt) {
67
+ return crypto.scryptSync(password, salt, KEY_LENGTH, {
68
+ N: SCRYPT_N,
69
+ r: SCRYPT_R,
70
+ p: SCRYPT_P,
71
+ });
72
+ }
73
+ // ============================================================================
74
+ // Public Functions
75
+ // ============================================================================
76
+ /**
77
+ * Generate a random salt for encryption
78
+ */
79
+ function generateSalt() {
80
+ return randomHex(SALT_LENGTH);
81
+ }
82
+ /**
83
+ * Generate a random IV for encryption
84
+ */
85
+ function generateIV() {
86
+ return randomHex(IV_LENGTH);
87
+ }
88
+ /**
89
+ * Encrypt data object with password using AES-256-GCM
90
+ *
91
+ * @param data - Object to encrypt (will be JSON stringified)
92
+ * @param password - Password for encryption
93
+ * @returns Encrypted data with salt, iv, authTag, and encrypted content
94
+ */
95
+ function encrypt(data, password) {
96
+ // Generate random salt and IV
97
+ const salt = Buffer.from(generateSalt(), "hex");
98
+ const iv = Buffer.from(generateIV(), "hex");
99
+ // Derive key from password
100
+ const key = deriveKey(password, salt);
101
+ // Create cipher
102
+ const cipher = crypto.createCipheriv(ALGORITHM, key, iv, {
103
+ authTagLength: AUTH_TAG_LENGTH,
104
+ });
105
+ // Encrypt data
106
+ const plaintext = JSON.stringify(data);
107
+ const encrypted = Buffer.concat([
108
+ cipher.update(plaintext, "utf8"),
109
+ cipher.final(),
110
+ ]);
111
+ // Get auth tag
112
+ const authTag = cipher.getAuthTag();
113
+ return {
114
+ salt: salt.toString("hex"),
115
+ iv: iv.toString("hex"),
116
+ authTag: authTag.toString("hex"),
117
+ data: encrypted.toString("hex"),
118
+ };
119
+ }
120
+ /**
121
+ * Decrypt data with password using AES-256-GCM
122
+ *
123
+ * @param encrypted - Encrypted data object
124
+ * @param password - Password for decryption
125
+ * @returns Decrypted object
126
+ * @throws Error if password is wrong or data is corrupted
127
+ */
128
+ function decrypt(encrypted, password) {
129
+ // Convert hex strings to buffers
130
+ const salt = Buffer.from(encrypted.salt, "hex");
131
+ const iv = Buffer.from(encrypted.iv, "hex");
132
+ const authTag = Buffer.from(encrypted.authTag, "hex");
133
+ const data = Buffer.from(encrypted.data, "hex");
134
+ // Derive key from password
135
+ const key = deriveKey(password, salt);
136
+ // Create decipher
137
+ const decipher = crypto.createDecipheriv(ALGORITHM, key, iv, {
138
+ authTagLength: AUTH_TAG_LENGTH,
139
+ });
140
+ // Set auth tag for verification
141
+ decipher.setAuthTag(authTag);
142
+ try {
143
+ // Decrypt data
144
+ const decrypted = Buffer.concat([
145
+ decipher.update(data),
146
+ decipher.final(),
147
+ ]);
148
+ // Parse JSON
149
+ return JSON.parse(decrypted.toString("utf8"));
150
+ }
151
+ catch (error) {
152
+ // Auth tag verification failed or JSON parse failed
153
+ throw new Error("Invalid password or corrupted file");
154
+ }
155
+ }
156
+ /**
157
+ * Verify if a password can decrypt the data
158
+ *
159
+ * @param encrypted - Encrypted data object
160
+ * @param password - Password to verify
161
+ * @returns true if password is correct
162
+ */
163
+ function verifyPassword(encrypted, password) {
164
+ try {
165
+ decrypt(encrypted, password);
166
+ return true;
167
+ }
168
+ catch {
169
+ return false;
170
+ }
171
+ }
172
+ //# sourceMappingURL=crypto.js.map