@wafflebase/cli 0.4.9 → 0.5.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 (83) hide show
  1. package/dist/bin.js +99988 -11
  2. package/package.json +7 -6
  3. package/dist/bin.d.ts +0 -2
  4. package/dist/client/dry-run.d.ts +0 -5
  5. package/dist/client/dry-run.js +0 -16
  6. package/dist/client/http-client.d.ts +0 -59
  7. package/dist/client/http-client.js +0 -178
  8. package/dist/commands/api-keys.d.ts +0 -2
  9. package/dist/commands/api-keys.js +0 -54
  10. package/dist/commands/cells.d.ts +0 -2
  11. package/dist/commands/cells.js +0 -108
  12. package/dist/commands/ctx.d.ts +0 -5
  13. package/dist/commands/ctx.js +0 -56
  14. package/dist/commands/docs.d.ts +0 -3
  15. package/dist/commands/docs.js +0 -320
  16. package/dist/commands/login.d.ts +0 -2
  17. package/dist/commands/login.js +0 -220
  18. package/dist/commands/logout.d.ts +0 -2
  19. package/dist/commands/logout.js +0 -10
  20. package/dist/commands/root.d.ts +0 -18
  21. package/dist/commands/root.js +0 -37
  22. package/dist/commands/schema.d.ts +0 -2
  23. package/dist/commands/schema.js +0 -28
  24. package/dist/commands/sheets-export.d.ts +0 -2
  25. package/dist/commands/sheets-export.js +0 -52
  26. package/dist/commands/sheets-import.d.ts +0 -2
  27. package/dist/commands/sheets-import.js +0 -88
  28. package/dist/commands/sheets.d.ts +0 -2
  29. package/dist/commands/sheets.js +0 -17
  30. package/dist/commands/slides.d.ts +0 -3
  31. package/dist/commands/slides.js +0 -227
  32. package/dist/commands/status.d.ts +0 -2
  33. package/dist/commands/status.js +0 -22
  34. package/dist/commands/tabs.d.ts +0 -2
  35. package/dist/commands/tabs.js +0 -20
  36. package/dist/config/config.d.ts +0 -38
  37. package/dist/config/config.js +0 -135
  38. package/dist/config/session.d.ts +0 -49
  39. package/dist/config/session.js +0 -74
  40. package/dist/docs/content.d.ts +0 -37
  41. package/dist/docs/content.js +0 -90
  42. package/dist/docs/docx-export.d.ts +0 -23
  43. package/dist/docs/docx-export.js +0 -14
  44. package/dist/docs/docx-import.d.ts +0 -36
  45. package/dist/docs/docx-import.js +0 -70
  46. package/dist/docs/dom-polyfill.d.ts +0 -1
  47. package/dist/docs/dom-polyfill.js +0 -29
  48. package/dist/docs/fontkit-measurer.d.ts +0 -41
  49. package/dist/docs/fontkit-measurer.js +0 -64
  50. package/dist/docs/image-fetcher.d.ts +0 -37
  51. package/dist/docs/image-fetcher.js +0 -38
  52. package/dist/docs/import.d.ts +0 -72
  53. package/dist/docs/import.js +0 -146
  54. package/dist/docs/page-range.d.ts +0 -29
  55. package/dist/docs/page-range.js +0 -74
  56. package/dist/docs/page-slice.d.ts +0 -45
  57. package/dist/docs/page-slice.js +0 -61
  58. package/dist/docs/paginate.d.ts +0 -13
  59. package/dist/docs/paginate.js +0 -19
  60. package/dist/docs/pdf-export.d.ts +0 -47
  61. package/dist/docs/pdf-export.js +0 -95
  62. package/dist/output/binary.d.ts +0 -37
  63. package/dist/output/binary.js +0 -47
  64. package/dist/output/csv.d.ts +0 -4
  65. package/dist/output/csv.js +0 -25
  66. package/dist/output/formatter.d.ts +0 -4
  67. package/dist/output/formatter.js +0 -41
  68. package/dist/output/json.d.ts +0 -1
  69. package/dist/output/json.js +0 -3
  70. package/dist/output/table.d.ts +0 -4
  71. package/dist/output/table.js +0 -14
  72. package/dist/schema/registry.d.ts +0 -42
  73. package/dist/schema/registry.js +0 -375
  74. package/dist/slides/content.d.ts +0 -41
  75. package/dist/slides/content.js +0 -122
  76. package/dist/slides/import.d.ts +0 -82
  77. package/dist/slides/import.js +0 -170
  78. package/dist/slides/pptx-export.d.ts +0 -6
  79. package/dist/slides/pptx-export.js +0 -10
  80. package/dist/slides/pptx-import.d.ts +0 -35
  81. package/dist/slides/pptx-import.js +0 -49
  82. package/dist/util/csv-parse.d.ts +0 -21
  83. package/dist/util/csv-parse.js +0 -99
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wafflebase/cli",
3
- "version": "0.4.9",
3
+ "version": "0.5.1",
4
4
  "description": "CLI for Wafflebase spreadsheet API",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -19,9 +19,7 @@
19
19
  "fontkit": "^2.0.4",
20
20
  "open": "^11.0.0",
21
21
  "pdf-lib": "^1.17.1",
22
- "yaml": "^2.0.0",
23
- "@wafflebase/docs": "0.4.9",
24
- "@wafflebase/slides": "0.4.9"
22
+ "yaml": "^2.0.0"
25
23
  },
26
24
  "devDependencies": {
27
25
  "@types/fontkit": "^2.0.0",
@@ -29,12 +27,15 @@
29
27
  "@vitest/coverage-v8": "4.1.8",
30
28
  "eslint": "^9.18.0",
31
29
  "jszip": "^3.10.1",
30
+ "tsup": "^8.5.1",
32
31
  "tsx": "^4.19.0",
33
32
  "typescript": "^5.9.3",
34
- "vitest": "^4.1.8"
33
+ "vitest": "^4.1.8",
34
+ "@wafflebase/docs": "0.5.1",
35
+ "@wafflebase/slides": "0.5.1"
35
36
  },
36
37
  "scripts": {
37
- "build": "tsc",
38
+ "build": "tsup",
38
39
  "dev": "tsx src/bin.ts",
39
40
  "test": "vitest --run",
40
41
  "test:watch": "vitest",
package/dist/bin.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,5 +0,0 @@
1
- import type { CliConfig } from '../config/config.js';
2
- /**
3
- * Print the request that would be sent without executing it.
4
- */
5
- export declare function printDryRun(config: CliConfig, method: string, path: string, body?: unknown): void;
@@ -1,16 +0,0 @@
1
- /**
2
- * Print the request that would be sent without executing it.
3
- */
4
- export function printDryRun(config, method, path, body) {
5
- const server = config.server.replace(/\/$/, '');
6
- const url = `${server}/api/v1/workspaces/${config.workspace}${path}`;
7
- const output = {
8
- dry_run: true,
9
- method,
10
- url,
11
- };
12
- if (body !== undefined) {
13
- output.body = body;
14
- }
15
- console.log(JSON.stringify(output, null, 2));
16
- }
@@ -1,59 +0,0 @@
1
- import type { Document } from '@wafflebase/docs';
2
- import type { SlidesDocument } from '@wafflebase/slides/node';
3
- import type { CliConfig } from '../config/config.js';
4
- export interface ApiResponse<T = unknown> {
5
- ok: boolean;
6
- status: number;
7
- data: T;
8
- }
9
- export interface ApiError {
10
- error: {
11
- code: string;
12
- message: string;
13
- command?: string;
14
- };
15
- }
16
- export declare class HttpClient {
17
- private config;
18
- constructor(config: CliConfig);
19
- private get headers();
20
- private get base();
21
- /**
22
- * Attempt to refresh the JWT session. Returns true on success.
23
- */
24
- private refreshSession;
25
- request<T>(method: string, path: string, body?: unknown): Promise<ApiResponse<T>>;
26
- listDocuments(): Promise<ApiResponse<unknown[]>>;
27
- createDocument(title: string, type?: 'doc' | 'sheet' | 'slides'): Promise<ApiResponse<unknown>>;
28
- getDocument(id: string): Promise<ApiResponse<unknown>>;
29
- updateDocument(id: string, title: string): Promise<ApiResponse<unknown>>;
30
- deleteDocument(id: string): Promise<ApiResponse<unknown>>;
31
- getDocContent(docId: string): Promise<ApiResponse<Document>>;
32
- putDocContent(docId: string, doc: Document): Promise<ApiResponse<Document>>;
33
- getSlidesContent(docId: string): Promise<ApiResponse<SlidesDocument>>;
34
- putSlidesContent(docId: string, deck: SlidesDocument): Promise<ApiResponse<SlidesDocument>>;
35
- listTabs(docId: string): Promise<ApiResponse<unknown[]>>;
36
- getCells(docId: string, tabId: string, range?: string): Promise<ApiResponse<unknown>>;
37
- getCell(docId: string, tabId: string, sref: string): Promise<ApiResponse<unknown>>;
38
- setCell(docId: string, tabId: string, sref: string, value?: string, formula?: string): Promise<ApiResponse<unknown>>;
39
- deleteCell(docId: string, tabId: string, sref: string): Promise<ApiResponse<unknown>>;
40
- batchCells(docId: string, tabId: string, cells: Record<string, {
41
- value?: string;
42
- formula?: string;
43
- } | null>): Promise<ApiResponse<unknown>>;
44
- listApiKeys(): Promise<{
45
- ok: boolean;
46
- status: number;
47
- data: unknown;
48
- }>;
49
- createApiKey(name: string): Promise<{
50
- ok: boolean;
51
- status: number;
52
- data: unknown;
53
- }>;
54
- revokeApiKey(id: string): Promise<{
55
- ok: boolean;
56
- status: number;
57
- data: unknown;
58
- }>;
59
- }
@@ -1,178 +0,0 @@
1
- import { loadSession, saveSession, decodeJwtExpiry, } from '../config/session.js';
2
- export class HttpClient {
3
- config;
4
- constructor(config) {
5
- this.config = config;
6
- }
7
- get headers() {
8
- const h = {
9
- 'Content-Type': 'application/json',
10
- };
11
- if (this.config.authMode === 'api-key' && this.config.apiKey) {
12
- h['Authorization'] = `Bearer ${this.config.apiKey}`;
13
- }
14
- else if (this.config.authMode === 'jwt' && this.config.accessToken) {
15
- h['Authorization'] = `Bearer ${this.config.accessToken}`;
16
- }
17
- return h;
18
- }
19
- get base() {
20
- const server = this.config.server.replace(/\/$/, '');
21
- return `${server}/api/v1/workspaces/${this.config.workspace}`;
22
- }
23
- /**
24
- * Attempt to refresh the JWT session. Returns true on success.
25
- */
26
- async refreshSession() {
27
- if (!this.config.refreshToken)
28
- return false;
29
- const server = this.config.server.replace(/\/$/, '');
30
- const res = await fetch(`${server}/auth/refresh`, {
31
- method: 'POST',
32
- headers: { 'Content-Type': 'application/json' },
33
- body: JSON.stringify({ refreshToken: this.config.refreshToken }),
34
- });
35
- if (!res.ok)
36
- return false;
37
- const data = (await res.json().catch(() => null));
38
- if (!data?.accessToken || !data?.refreshToken)
39
- return false;
40
- // Update in-memory config
41
- this.config.accessToken = data.accessToken;
42
- this.config.refreshToken = data.refreshToken;
43
- // Persist refreshed tokens to session file (if it exists).
44
- // If the session file is missing the in-memory config is already
45
- // updated, so the current process will keep working; the user can
46
- // run `wafflebase login` to recreate the session file.
47
- const session = loadSession();
48
- if (session) {
49
- session.accessToken = data.accessToken;
50
- session.refreshToken = data.refreshToken;
51
- session.expiresAt = decodeJwtExpiry(data.accessToken);
52
- saveSession(session);
53
- }
54
- return true;
55
- }
56
- async request(method, path, body) {
57
- const url = `${this.base}${path}`;
58
- const res = await fetch(url, {
59
- method,
60
- headers: this.headers,
61
- body: body ? JSON.stringify(body) : undefined,
62
- });
63
- // Auto-refresh on 401 for JWT auth (one attempt only)
64
- if (res.status === 401 &&
65
- this.config.authMode === 'jwt' &&
66
- this.config.refreshToken) {
67
- const refreshed = await this.refreshSession();
68
- if (refreshed) {
69
- // Retry the original request with new token
70
- const retryRes = await fetch(url, {
71
- method,
72
- headers: this.headers,
73
- body: body ? JSON.stringify(body) : undefined,
74
- });
75
- const retryData = (await retryRes.json().catch(() => null));
76
- return { ok: retryRes.ok, status: retryRes.status, data: retryData };
77
- }
78
- // Refresh failed — return a clear error
79
- return {
80
- ok: false,
81
- status: 401,
82
- data: {
83
- error: {
84
- code: 'SESSION_EXPIRED',
85
- message: 'Session expired. Run `wafflebase login`.',
86
- },
87
- },
88
- };
89
- }
90
- const data = (await res.json().catch(() => null));
91
- return { ok: res.ok, status: res.status, data };
92
- }
93
- // Documents
94
- listDocuments() {
95
- return this.request('GET', '/documents');
96
- }
97
- createDocument(title, type) {
98
- const body = { title };
99
- if (type)
100
- body.type = type;
101
- return this.request('POST', '/documents', body);
102
- }
103
- getDocument(id) {
104
- return this.request('GET', `/documents/${id}`);
105
- }
106
- updateDocument(id, title) {
107
- return this.request('PATCH', `/documents/${id}`, { title });
108
- }
109
- deleteDocument(id) {
110
- return this.request('DELETE', `/documents/${id}`);
111
- }
112
- // Docs (word-processor) content
113
- getDocContent(docId) {
114
- return this.request('GET', `/documents/${docId}/content`);
115
- }
116
- putDocContent(docId, doc) {
117
- return this.request('PUT', `/documents/${docId}/content`, doc);
118
- }
119
- // Slides content — same endpoint as docs; the backend dispatches on
120
- // the persisted document type, picking the docs writer for `'doc'`
121
- // and the slides writer for `'slides'`.
122
- getSlidesContent(docId) {
123
- return this.request('GET', `/documents/${docId}/content`);
124
- }
125
- putSlidesContent(docId, deck) {
126
- return this.request('PUT', `/documents/${docId}/content`, deck);
127
- }
128
- // Tabs
129
- listTabs(docId) {
130
- return this.request('GET', `/documents/${docId}/tabs`);
131
- }
132
- // Cells
133
- getCells(docId, tabId, range) {
134
- const query = range ? `?range=${encodeURIComponent(range)}` : '';
135
- return this.request('GET', `/documents/${docId}/tabs/${tabId}/cells${query}`);
136
- }
137
- getCell(docId, tabId, sref) {
138
- return this.request('GET', `/documents/${docId}/tabs/${tabId}/cells/${sref}`);
139
- }
140
- setCell(docId, tabId, sref, value, formula) {
141
- return this.request('PUT', `/documents/${docId}/tabs/${tabId}/cells/${sref}`, {
142
- value,
143
- formula,
144
- });
145
- }
146
- deleteCell(docId, tabId, sref) {
147
- return this.request('DELETE', `/documents/${docId}/tabs/${tabId}/cells/${sref}`);
148
- }
149
- batchCells(docId, tabId, cells) {
150
- return this.request('PATCH', `/documents/${docId}/tabs/${tabId}/cells`, { cells });
151
- }
152
- // API Keys (management endpoints use different base)
153
- async listApiKeys() {
154
- const server = this.config.server.replace(/\/$/, '');
155
- const url = `${server}/workspaces/${this.config.workspace}/api-keys`;
156
- const res = await fetch(url, { headers: this.headers });
157
- const data = await res.json().catch(() => null);
158
- return { ok: res.ok, status: res.status, data };
159
- }
160
- async createApiKey(name) {
161
- const server = this.config.server.replace(/\/$/, '');
162
- const url = `${server}/workspaces/${this.config.workspace}/api-keys`;
163
- const res = await fetch(url, {
164
- method: 'POST',
165
- headers: this.headers,
166
- body: JSON.stringify({ name }),
167
- });
168
- const data = await res.json().catch(() => null);
169
- return { ok: res.ok, status: res.status, data };
170
- }
171
- async revokeApiKey(id) {
172
- const server = this.config.server.replace(/\/$/, '');
173
- const url = `${server}/workspaces/${this.config.workspace}/api-keys/${id}`;
174
- const res = await fetch(url, { method: 'DELETE', headers: this.headers });
175
- const data = await res.json().catch(() => null);
176
- return { ok: res.ok, status: res.status, data };
177
- }
178
- }
@@ -1,2 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function registerApiKeysCommand(program: Command): void;
@@ -1,54 +0,0 @@
1
- import { getGlobalOpts, getClient } from './root.js';
2
- import { output, outputError } from '../output/formatter.js';
3
- export function registerApiKeysCommand(program) {
4
- const apiKey = program
5
- .command('api-keys')
6
- .alias('api-key')
7
- .description('Manage API keys');
8
- apiKey
9
- .command('create <name>')
10
- .description('Create a new API key')
11
- .action(async function (name) {
12
- const opts = getGlobalOpts(this);
13
- try {
14
- const res = await getClient(opts).createApiKey(name);
15
- if (!res.ok)
16
- throw new Error(`HTTP ${res.status}`);
17
- // Never suppress output — the raw key is shown only once
18
- output(res.data, opts.format, false);
19
- }
20
- catch (e) {
21
- outputError(e, opts.quiet);
22
- }
23
- });
24
- apiKey
25
- .command('list')
26
- .description('List API keys in workspace')
27
- .action(async function () {
28
- const opts = getGlobalOpts(this);
29
- try {
30
- const res = await getClient(opts).listApiKeys();
31
- if (!res.ok)
32
- throw new Error(`HTTP ${res.status}`);
33
- output(res.data, opts.format, opts.quiet);
34
- }
35
- catch (e) {
36
- outputError(e, opts.quiet);
37
- }
38
- });
39
- apiKey
40
- .command('revoke <key-id>')
41
- .description('Revoke an API key')
42
- .action(async function (keyId) {
43
- const opts = getGlobalOpts(this);
44
- try {
45
- const res = await getClient(opts).revokeApiKey(keyId);
46
- if (!res.ok)
47
- throw new Error(`HTTP ${res.status}`);
48
- output(res.data, opts.format, opts.quiet);
49
- }
50
- catch (e) {
51
- outputError(e, opts.quiet);
52
- }
53
- });
54
- }
@@ -1,2 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function registerCellsCommand(parent: Command): void;
@@ -1,108 +0,0 @@
1
- import { getGlobalOpts, getClient, getConfig } from './root.js';
2
- import { output, outputError } from '../output/formatter.js';
3
- import { printDryRun } from '../client/dry-run.js';
4
- export function registerCellsCommand(parent) {
5
- const cell = parent
6
- .command('cells')
7
- .alias('cell')
8
- .description('Read and write cells');
9
- cell
10
- .command('get <doc-id> [range]')
11
- .description('Get cells (default: all, or A1, or A1:C10)')
12
- .option('--tab <tab-id>', 'Tab ID', 'tab-1')
13
- .action(async function (docId, range) {
14
- const opts = getGlobalOpts(this);
15
- const { tab } = this.opts();
16
- try {
17
- const res = range?.includes(':')
18
- ? await getClient(opts).getCells(docId, tab, range)
19
- : range
20
- ? await getClient(opts).getCell(docId, tab, range)
21
- : await getClient(opts).getCells(docId, tab);
22
- if (!res.ok)
23
- throw new Error(`HTTP ${res.status}`);
24
- output(res.data, opts.format, opts.quiet);
25
- }
26
- catch (e) {
27
- outputError(e, opts.quiet);
28
- }
29
- });
30
- cell
31
- .command('set <doc-id> <ref> <value>')
32
- .description('Set a single cell value')
33
- .option('--tab <tab-id>', 'Tab ID', 'tab-1')
34
- .option('--formula', 'Treat value as a formula')
35
- .action(async function (docId, ref, value) {
36
- const opts = getGlobalOpts(this);
37
- const { tab, formula } = this.opts();
38
- const body = formula ? { formula: value } : { value };
39
- if (opts.dryRun) {
40
- printDryRun(getConfig(opts), 'PUT', `/documents/${docId}/tabs/${tab}/cells/${ref}`, body);
41
- return;
42
- }
43
- try {
44
- const res = await getClient(opts).setCell(docId, tab, ref, formula ? undefined : value, formula ? value : undefined);
45
- if (!res.ok)
46
- throw new Error(`HTTP ${res.status}`);
47
- output(res.data, opts.format, opts.quiet);
48
- }
49
- catch (e) {
50
- outputError(e, opts.quiet);
51
- }
52
- });
53
- cell
54
- .command('delete <doc-id> <ref>')
55
- .description('Delete a single cell')
56
- .option('--tab <tab-id>', 'Tab ID', 'tab-1')
57
- .action(async function (docId, ref) {
58
- const opts = getGlobalOpts(this);
59
- const { tab } = this.opts();
60
- if (opts.dryRun) {
61
- printDryRun(getConfig(opts), 'DELETE', `/documents/${docId}/tabs/${tab}/cells/${ref}`);
62
- return;
63
- }
64
- try {
65
- const res = await getClient(opts).deleteCell(docId, tab, ref);
66
- if (!res.ok)
67
- throw new Error(`HTTP ${res.status}`);
68
- output(res.data, opts.format, opts.quiet);
69
- }
70
- catch (e) {
71
- outputError(e, opts.quiet);
72
- }
73
- });
74
- cell
75
- .command('batch <doc-id>')
76
- .description('Batch update cells (JSON from stdin or --data)')
77
- .option('--tab <tab-id>', 'Tab ID', 'tab-1')
78
- .option('--data <json>', 'Cell data as JSON string')
79
- .action(async function (docId) {
80
- const opts = getGlobalOpts(this);
81
- const { tab, data: dataStr } = this.opts();
82
- let cells;
83
- if (dataStr) {
84
- cells = JSON.parse(dataStr);
85
- }
86
- else {
87
- // Read from stdin
88
- const chunks = [];
89
- for await (const chunk of process.stdin) {
90
- chunks.push(chunk);
91
- }
92
- cells = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
93
- }
94
- if (opts.dryRun) {
95
- printDryRun(getConfig(opts), 'PATCH', `/documents/${docId}/tabs/${tab}/cells`, { cells });
96
- return;
97
- }
98
- try {
99
- const res = await getClient(opts).batchCells(docId, tab, cells);
100
- if (!res.ok)
101
- throw new Error(`HTTP ${res.status}`);
102
- output(res.data, opts.format, opts.quiet);
103
- }
104
- catch (e) {
105
- outputError(e, opts.quiet);
106
- }
107
- });
108
- }
@@ -1,5 +0,0 @@
1
- import { Command } from 'commander';
2
- import type { WorkspaceInfo } from '../config/session.js';
3
- export declare function formatWorkspaceList(workspaces: WorkspaceInfo[], activeId: string): string;
4
- export declare function findWorkspace(workspaces: WorkspaceInfo[], query: string): WorkspaceInfo | undefined;
5
- export declare function registerCtxCommand(program: Command): void;
@@ -1,56 +0,0 @@
1
- import { loadSession, saveSession } from '../config/session.js';
2
- export function formatWorkspaceList(workspaces, activeId) {
3
- return workspaces
4
- .map((ws) => {
5
- const marker = ws.id === activeId ? '*' : ' ';
6
- return `${marker} ${ws.id.slice(0, 8)} ${ws.name}`;
7
- })
8
- .join('\n');
9
- }
10
- export function findWorkspace(workspaces, query) {
11
- // Exact ID match
12
- const byId = workspaces.find((ws) => ws.id === query);
13
- if (byId)
14
- return byId;
15
- // Exact name match (case-insensitive)
16
- const byName = workspaces.find((ws) => ws.name.toLowerCase() === query.toLowerCase());
17
- if (byName)
18
- return byName;
19
- // Prefix match on ID
20
- const byPrefix = workspaces.filter((ws) => ws.id.startsWith(query));
21
- if (byPrefix.length === 1)
22
- return byPrefix[0];
23
- return undefined;
24
- }
25
- export function registerCtxCommand(program) {
26
- const ctx = program.command('ctx').description('Workspace context switching');
27
- ctx
28
- .command('list')
29
- .description('List workspaces')
30
- .action(() => {
31
- const session = loadSession();
32
- if (!session) {
33
- console.log('Not logged in. Run `wafflebase login`.');
34
- return;
35
- }
36
- console.log(formatWorkspaceList(session.workspaces, session.activeWorkspace));
37
- });
38
- ctx
39
- .command('switch <name-or-id>')
40
- .description('Switch active workspace')
41
- .action((query) => {
42
- const session = loadSession();
43
- if (!session) {
44
- console.error('Not logged in. Run `wafflebase login`.');
45
- process.exit(1);
46
- }
47
- const ws = findWorkspace(session.workspaces, query);
48
- if (!ws) {
49
- console.error(`Workspace not found: ${query}`);
50
- process.exit(1);
51
- }
52
- session.activeWorkspace = ws.id;
53
- saveSession(session);
54
- console.log(`Switched to ${ws.name}.`);
55
- });
56
- }
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function registerDocsCommand(program: Command): void;
3
- export declare function registerDocsImportCommand(doc: Command): void;