mnotes-cli 1.6.0 → 1.7.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/commands/login.d.ts +2 -0
- package/dist/commands/login.js +5 -0
- package/dist/commands/workspace.js +146 -34
- package/dist/config.js +29 -1
- package/package.json +1 -1
package/dist/commands/login.d.ts
CHANGED
package/dist/commands/login.js
CHANGED
|
@@ -62,10 +62,15 @@ function readConfig() {
|
|
|
62
62
|
const raw = fs.readFileSync(configPath(), "utf-8");
|
|
63
63
|
const parsed = JSON.parse(raw);
|
|
64
64
|
if (typeof parsed.apiKey === "string" && typeof parsed.serverUrl === "string") {
|
|
65
|
+
let workspaces;
|
|
66
|
+
if (typeof parsed.workspaces === "object" && parsed.workspaces !== null && !Array.isArray(parsed.workspaces)) {
|
|
67
|
+
workspaces = parsed.workspaces;
|
|
68
|
+
}
|
|
65
69
|
return {
|
|
66
70
|
apiKey: parsed.apiKey,
|
|
67
71
|
serverUrl: parsed.serverUrl,
|
|
68
72
|
workspaceId: typeof parsed.workspaceId === "string" ? parsed.workspaceId : undefined,
|
|
73
|
+
workspaces,
|
|
69
74
|
};
|
|
70
75
|
}
|
|
71
76
|
return null;
|
|
@@ -45,6 +45,26 @@ function ask(rl, question) {
|
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
+
/** Save a directory → workspace mapping in config. */
|
|
49
|
+
function saveDirectoryMapping(dir, workspaceId) {
|
|
50
|
+
const stored = (0, login_1.readConfig)();
|
|
51
|
+
if (!stored) {
|
|
52
|
+
process.stderr.write("Error: not logged in. Run `mnotes login` first.\n");
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
const workspaces = stored.workspaces ?? {};
|
|
56
|
+
workspaces[dir] = workspaceId;
|
|
57
|
+
(0, login_1.writeConfig)({ ...stored, workspaces });
|
|
58
|
+
}
|
|
59
|
+
/** Remove a directory → workspace mapping from config. */
|
|
60
|
+
function removeDirectoryMapping(dir) {
|
|
61
|
+
const stored = (0, login_1.readConfig)();
|
|
62
|
+
if (!stored?.workspaces?.[dir])
|
|
63
|
+
return false;
|
|
64
|
+
delete stored.workspaces[dir];
|
|
65
|
+
(0, login_1.writeConfig)(stored);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
48
68
|
function registerWorkspaceCommand(program) {
|
|
49
69
|
const ws = program
|
|
50
70
|
.command("workspace")
|
|
@@ -62,20 +82,25 @@ function registerWorkspaceCommand(program) {
|
|
|
62
82
|
return;
|
|
63
83
|
}
|
|
64
84
|
const stored = (0, login_1.readConfig)();
|
|
65
|
-
const
|
|
85
|
+
const cwd = process.cwd();
|
|
86
|
+
const dirMapped = stored?.workspaces?.[cwd];
|
|
87
|
+
const globalDefault = stored?.workspaceId;
|
|
66
88
|
for (const w of workspaces) {
|
|
67
89
|
const markers = [];
|
|
68
90
|
if (w.isDefault)
|
|
69
91
|
markers.push("default");
|
|
70
|
-
if (w.id ===
|
|
71
|
-
markers.push("
|
|
92
|
+
if (w.id === dirMapped)
|
|
93
|
+
markers.push("linked");
|
|
94
|
+
else if (w.id === globalDefault)
|
|
95
|
+
markers.push("global");
|
|
72
96
|
const suffix = markers.length > 0 ? ` (${markers.join(", ")})` : "";
|
|
73
97
|
console.log(` ${w.name} [${w.slug}]${suffix}`);
|
|
74
98
|
}
|
|
75
99
|
});
|
|
76
100
|
ws.command("select")
|
|
77
|
-
.description("Select
|
|
78
|
-
.
|
|
101
|
+
.description("Select workspace for current directory (saved to config)")
|
|
102
|
+
.option("--global", "Set as global default instead of per-directory")
|
|
103
|
+
.action(async (opts) => {
|
|
79
104
|
const globalOpts = program.opts();
|
|
80
105
|
const config = (0, config_1.resolveConfig)(globalOpts);
|
|
81
106
|
const client = (0, client_1.createClient)(config.baseUrl, config.apiKey);
|
|
@@ -86,7 +111,8 @@ function registerWorkspaceCommand(program) {
|
|
|
86
111
|
return;
|
|
87
112
|
}
|
|
88
113
|
const stored = (0, login_1.readConfig)();
|
|
89
|
-
const
|
|
114
|
+
const cwd = process.cwd();
|
|
115
|
+
const currentId = stored?.workspaces?.[cwd] || stored?.workspaceId;
|
|
90
116
|
const rl = readline.createInterface({
|
|
91
117
|
input: process.stdin,
|
|
92
118
|
output: process.stderr,
|
|
@@ -95,7 +121,7 @@ function registerWorkspaceCommand(program) {
|
|
|
95
121
|
process.stderr.write("\nWorkspaces:\n");
|
|
96
122
|
for (let i = 0; i < workspaces.length; i++) {
|
|
97
123
|
const w = workspaces[i];
|
|
98
|
-
const marker = w.id ===
|
|
124
|
+
const marker = w.id === currentId ? " *" : "";
|
|
99
125
|
process.stderr.write(` ${i + 1}. ${w.name} [${w.slug}]${marker}\n`);
|
|
100
126
|
}
|
|
101
127
|
const answer = await ask(rl, `\nSelect workspace [1-${workspaces.length}]: `);
|
|
@@ -105,52 +131,138 @@ function registerWorkspaceCommand(program) {
|
|
|
105
131
|
process.exit(1);
|
|
106
132
|
}
|
|
107
133
|
const selected = workspaces[choice - 1];
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
134
|
+
if (opts.global) {
|
|
135
|
+
const existing = stored ?? { apiKey: config.apiKey, serverUrl: config.baseUrl };
|
|
136
|
+
(0, login_1.writeConfig)({ ...existing, workspaceId: selected.id });
|
|
137
|
+
console.log(`Global default workspace: ${selected.name} [${selected.slug}]`);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
saveDirectoryMapping(cwd, selected.id);
|
|
141
|
+
console.log(`Linked ${cwd} → ${selected.name} [${selected.slug}]`);
|
|
142
|
+
}
|
|
111
143
|
}
|
|
112
144
|
finally {
|
|
113
145
|
rl.close();
|
|
114
146
|
}
|
|
115
147
|
});
|
|
116
|
-
ws.command("
|
|
148
|
+
ws.command("link")
|
|
149
|
+
.description("Link current directory to a workspace")
|
|
150
|
+
.argument("[workspace-id]", "Workspace ID or slug (interactive if omitted)")
|
|
151
|
+
.action(async (workspaceIdOrSlug) => {
|
|
152
|
+
const globalOpts = program.opts();
|
|
153
|
+
const config = (0, config_1.resolveConfig)(globalOpts);
|
|
154
|
+
const client = (0, client_1.createClient)(config.baseUrl, config.apiKey);
|
|
155
|
+
const res = await client.listWorkspaces();
|
|
156
|
+
const workspaces = res.data;
|
|
157
|
+
if (workspaces.length === 0) {
|
|
158
|
+
console.log("No workspaces found. Create one with: mnotes workspace create <name>");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const cwd = process.cwd();
|
|
162
|
+
let selected;
|
|
163
|
+
if (workspaceIdOrSlug) {
|
|
164
|
+
selected = workspaces.find((w) => w.id === workspaceIdOrSlug || w.slug === workspaceIdOrSlug);
|
|
165
|
+
if (!selected) {
|
|
166
|
+
process.stderr.write(`Error: workspace "${workspaceIdOrSlug}" not found.\n`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const rl = readline.createInterface({
|
|
172
|
+
input: process.stdin,
|
|
173
|
+
output: process.stderr,
|
|
174
|
+
});
|
|
175
|
+
try {
|
|
176
|
+
process.stderr.write("\nWorkspaces:\n");
|
|
177
|
+
for (let i = 0; i < workspaces.length; i++) {
|
|
178
|
+
const w = workspaces[i];
|
|
179
|
+
process.stderr.write(` ${i + 1}. ${w.name} [${w.slug}]\n`);
|
|
180
|
+
}
|
|
181
|
+
const answer = await ask(rl, `\nLink to workspace [1-${workspaces.length}]: `);
|
|
182
|
+
const choice = parseInt(answer, 10);
|
|
183
|
+
if (choice < 1 || choice > workspaces.length || isNaN(choice)) {
|
|
184
|
+
process.stderr.write("Invalid selection.\n");
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
selected = workspaces[choice - 1];
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
rl.close();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
saveDirectoryMapping(cwd, selected.id);
|
|
194
|
+
console.log(`Linked ${cwd} → ${selected.name} [${selected.slug}]`);
|
|
195
|
+
});
|
|
196
|
+
ws.command("unlink")
|
|
197
|
+
.description("Remove workspace mapping for current directory")
|
|
198
|
+
.action(async () => {
|
|
199
|
+
const cwd = process.cwd();
|
|
200
|
+
const removed = removeDirectoryMapping(cwd);
|
|
201
|
+
if (removed) {
|
|
202
|
+
console.log(`Unlinked ${cwd}`);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
console.log(`No workspace linked to ${cwd}`);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
ws.command("create")
|
|
117
209
|
.description("Create a new workspace")
|
|
210
|
+
.argument("<name>", "Workspace name")
|
|
118
211
|
.action(async (name) => {
|
|
119
212
|
const globalOpts = program.opts();
|
|
120
213
|
const config = (0, config_1.resolveConfig)(globalOpts);
|
|
121
214
|
const client = (0, client_1.createClient)(config.baseUrl, config.apiKey);
|
|
122
215
|
const res = await client.createWorkspace(name);
|
|
123
216
|
console.log(`Created workspace: ${res.data.name} [${res.data.slug}]`);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
console.log("Auto-selected as default workspace.");
|
|
129
|
-
}
|
|
217
|
+
// Auto-link to current directory
|
|
218
|
+
const cwd = process.cwd();
|
|
219
|
+
saveDirectoryMapping(cwd, res.data.id);
|
|
220
|
+
console.log(`Linked ${cwd} → ${res.data.name}`);
|
|
130
221
|
});
|
|
131
222
|
ws.command("current")
|
|
132
|
-
.description("Show
|
|
223
|
+
.description("Show workspace for current directory")
|
|
133
224
|
.action(async () => {
|
|
134
225
|
const stored = (0, login_1.readConfig)();
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
226
|
+
const cwd = process.cwd();
|
|
227
|
+
// Check directory mapping first
|
|
228
|
+
const dirMapped = stored?.workspaces?.[cwd];
|
|
229
|
+
const effectiveId = dirMapped || stored?.workspaceId;
|
|
230
|
+
const source = dirMapped ? "linked" : stored?.workspaceId ? "global" : null;
|
|
231
|
+
if (!effectiveId) {
|
|
232
|
+
console.log(`No workspace for ${cwd}`);
|
|
233
|
+
console.log("Run: mnotes workspace select");
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const config = (0, config_1.resolveConfig)(program.opts());
|
|
237
|
+
const client = (0, client_1.createClient)(config.baseUrl, config.apiKey);
|
|
238
|
+
try {
|
|
239
|
+
const res = await client.listWorkspaces();
|
|
240
|
+
const current = res.data.find((w) => w.id === effectiveId);
|
|
241
|
+
if (current) {
|
|
242
|
+
console.log(`${current.name} [${current.slug}] (${source})`);
|
|
147
243
|
}
|
|
148
|
-
|
|
149
|
-
console.log(
|
|
244
|
+
else {
|
|
245
|
+
console.log(`${effectiveId} (${source}, not found on server)`);
|
|
150
246
|
}
|
|
151
247
|
}
|
|
152
|
-
|
|
153
|
-
console.log(
|
|
248
|
+
catch {
|
|
249
|
+
console.log(`${effectiveId} (${source})`);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
ws.command("mappings")
|
|
253
|
+
.description("Show all directory → workspace mappings")
|
|
254
|
+
.action(async () => {
|
|
255
|
+
const stored = (0, login_1.readConfig)();
|
|
256
|
+
const workspaces = stored?.workspaces;
|
|
257
|
+
if (!workspaces || Object.keys(workspaces).length === 0) {
|
|
258
|
+
console.log("No directory mappings. Use: mnotes workspace link");
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
for (const [dir, wsId] of Object.entries(workspaces)) {
|
|
262
|
+
console.log(` ${dir} → ${wsId}`);
|
|
263
|
+
}
|
|
264
|
+
if (stored?.workspaceId) {
|
|
265
|
+
console.log(`\n Global default: ${stored.workspaceId}`);
|
|
154
266
|
}
|
|
155
267
|
});
|
|
156
268
|
}
|
package/dist/config.js
CHANGED
|
@@ -2,6 +2,34 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveConfig = resolveConfig;
|
|
4
4
|
const login_1 = require("./commands/login");
|
|
5
|
+
/**
|
|
6
|
+
* Resolve workspace ID from (in priority order):
|
|
7
|
+
* 1. Explicit flag/option
|
|
8
|
+
* 2. MNOTES_WORKSPACE_ID env var
|
|
9
|
+
* 3. Per-directory mapping in config (cwd → workspaceId)
|
|
10
|
+
* 4. Global default workspaceId in config
|
|
11
|
+
*/
|
|
12
|
+
function resolveWorkspaceId(explicit, stored) {
|
|
13
|
+
if (explicit)
|
|
14
|
+
return explicit;
|
|
15
|
+
if (process.env.MNOTES_WORKSPACE_ID)
|
|
16
|
+
return process.env.MNOTES_WORKSPACE_ID;
|
|
17
|
+
// Check per-directory mapping
|
|
18
|
+
if (stored?.workspaces) {
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
// Exact match first, then walk up parent directories
|
|
21
|
+
let dir = cwd;
|
|
22
|
+
while (true) {
|
|
23
|
+
if (stored.workspaces[dir])
|
|
24
|
+
return stored.workspaces[dir];
|
|
25
|
+
const parent = require("path").dirname(dir);
|
|
26
|
+
if (parent === dir)
|
|
27
|
+
break; // reached root
|
|
28
|
+
dir = parent;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return stored?.workspaceId;
|
|
32
|
+
}
|
|
5
33
|
function resolveConfig(opts) {
|
|
6
34
|
const stored = (0, login_1.readConfig)();
|
|
7
35
|
const apiKey = opts.apiKey || process.env.MNOTES_API_KEY || stored?.apiKey;
|
|
@@ -10,6 +38,6 @@ function resolveConfig(opts) {
|
|
|
10
38
|
process.exit(1);
|
|
11
39
|
}
|
|
12
40
|
const baseUrl = opts.url || process.env.MNOTES_URL || stored?.serverUrl || "https://mnotes.framework.by";
|
|
13
|
-
const workspaceId = opts.workspaceId
|
|
41
|
+
const workspaceId = resolveWorkspaceId(opts.workspaceId, stored ?? undefined);
|
|
14
42
|
return { apiKey, baseUrl, workspaceId };
|
|
15
43
|
}
|