kaimon-cli 0.1.41 → 0.1.44
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 +56 -0
- package/dist/__tests__/commands/pull.test.d.ts +2 -0
- package/dist/__tests__/commands/pull.test.d.ts.map +1 -0
- package/dist/__tests__/commands/pull.test.js +182 -0
- package/dist/__tests__/commands/pull.test.js.map +1 -0
- package/dist/__tests__/commands/push.test.d.ts +2 -0
- package/dist/__tests__/commands/push.test.d.ts.map +1 -0
- package/dist/__tests__/commands/push.test.js +255 -0
- package/dist/__tests__/commands/push.test.js.map +1 -0
- package/dist/__tests__/helpers.d.ts +49 -0
- package/dist/__tests__/helpers.d.ts.map +1 -0
- package/dist/__tests__/helpers.js +151 -0
- package/dist/__tests__/helpers.js.map +1 -0
- package/dist/__tests__/integration/full-workflow.test.d.ts +2 -0
- package/dist/__tests__/integration/full-workflow.test.d.ts.map +1 -0
- package/dist/__tests__/integration/full-workflow.test.js +213 -0
- package/dist/__tests__/integration/full-workflow.test.js.map +1 -0
- package/dist/__tests__/setup.d.ts +2 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +24 -0
- package/dist/__tests__/setup.js.map +1 -0
- package/dist/__tests__/unit/utils/config.test.d.ts +2 -0
- package/dist/__tests__/unit/utils/config.test.d.ts.map +1 -0
- package/dist/__tests__/unit/utils/config.test.js +171 -0
- package/dist/__tests__/unit/utils/config.test.js.map +1 -0
- package/dist/__tests__/unit/utils/frontmatter.test.d.ts +2 -0
- package/dist/__tests__/unit/utils/frontmatter.test.d.ts.map +1 -0
- package/dist/__tests__/unit/utils/frontmatter.test.js +231 -0
- package/dist/__tests__/unit/utils/frontmatter.test.js.map +1 -0
- package/dist/__tests__/unit/utils/markdown.test.d.ts +2 -0
- package/dist/__tests__/unit/utils/markdown.test.d.ts.map +1 -0
- package/dist/__tests__/unit/utils/markdown.test.js +296 -0
- package/dist/__tests__/unit/utils/markdown.test.js.map +1 -0
- package/dist/__tests__/unit/utils/projectConfig.test.d.ts +2 -0
- package/dist/__tests__/unit/utils/projectConfig.test.d.ts.map +1 -0
- package/dist/__tests__/unit/utils/projectConfig.test.js +160 -0
- package/dist/__tests__/unit/utils/projectConfig.test.js.map +1 -0
- package/dist/__tests__/unit/utils/requireAuth.test.d.ts +2 -0
- package/dist/__tests__/unit/utils/requireAuth.test.d.ts.map +1 -0
- package/dist/__tests__/unit/utils/requireAuth.test.js +96 -0
- package/dist/__tests__/unit/utils/requireAuth.test.js.map +1 -0
- package/dist/__tests__/unit/utils/tokenRefresh.test.d.ts +2 -0
- package/dist/__tests__/unit/utils/tokenRefresh.test.d.ts.map +1 -0
- package/dist/__tests__/unit/utils/tokenRefresh.test.js +170 -0
- package/dist/__tests__/unit/utils/tokenRefresh.test.js.map +1 -0
- package/dist/__tests__/unit/utils/versionCheck.test.d.ts +2 -0
- package/dist/__tests__/unit/utils/versionCheck.test.d.ts.map +1 -0
- package/dist/__tests__/unit/utils/versionCheck.test.js +105 -0
- package/dist/__tests__/unit/utils/versionCheck.test.js.map +1 -0
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +2 -1
- package/dist/commands/pull.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +28 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +79 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/projectConfig.d.ts.map +1 -1
- package/dist/utils/projectConfig.js +9 -1
- package/dist/utils/projectConfig.js.map +1 -1
- package/dist/utils/pushOperations.d.ts.map +1 -1
- package/dist/utils/pushOperations.js +242 -19
- package/dist/utils/pushOperations.js.map +1 -1
- package/dist/utils/syncOperations.d.ts +2 -1
- package/dist/utils/syncOperations.d.ts.map +1 -1
- package/dist/utils/syncOperations.js +153 -43
- package/dist/utils/syncOperations.js.map +1 -1
- package/dist/utils/versionCheck.d.ts +6 -0
- package/dist/utils/versionCheck.d.ts.map +1 -0
- package/dist/utils/versionCheck.js +61 -0
- package/dist/utils/versionCheck.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -68,6 +68,9 @@ kaimon pull
|
|
|
68
68
|
# Download documents to current folder (no KaimonDocs subfolder)
|
|
69
69
|
kaimon pull --flat
|
|
70
70
|
|
|
71
|
+
# Pull without confirmation
|
|
72
|
+
kaimon pull -y
|
|
73
|
+
|
|
71
74
|
# Upload local markdown files to Kaimon
|
|
72
75
|
kaimon push
|
|
73
76
|
|
|
@@ -82,13 +85,22 @@ kaimon sync
|
|
|
82
85
|
```
|
|
83
86
|
|
|
84
87
|
**Pull behavior:**
|
|
88
|
+
- **Smart sync**: Only pulls new or updated documents (compares timestamps)
|
|
89
|
+
- If local file is newer than remote → skips (no overwrite)
|
|
85
90
|
- Default: Creates `./KaimonDocs/` subfolder and downloads documents there
|
|
86
91
|
- `--flat`: Downloads documents directly to current folder (no subfolder)
|
|
92
|
+
- `-y, --yes`: Skip confirmation and pull all documents
|
|
93
|
+
- Shows preview with file counts and timestamps before pulling
|
|
87
94
|
|
|
88
95
|
**Push behavior:**
|
|
96
|
+
- **Smart sync**: Only pushes new or modified files (compares timestamps)
|
|
97
|
+
- If remote is newer than local → skips (no overwrite)
|
|
98
|
+
- Reads frontmatter `kaimon_id` to match existing documents
|
|
89
99
|
- Default: Finds all `.md` files in current folder + subfolders, lists them, asks for confirmation
|
|
90
100
|
- `[files...]`: Push only specific files (e.g., `kaimon push doc1.md readme.md`)
|
|
91
101
|
- `-y, --yes`: Skip confirmation and push all files found
|
|
102
|
+
- Shows preview with actions and timestamps before pushing
|
|
103
|
+
- Automatically updates frontmatter with `kaimon_id` for new documents
|
|
92
104
|
|
|
93
105
|
## Document Format
|
|
94
106
|
|
|
@@ -107,6 +119,50 @@ updated_at: "2024-02-21T15:00:00Z"
|
|
|
107
119
|
Content here...
|
|
108
120
|
```
|
|
109
121
|
|
|
122
|
+
**Important**: The `kaimon_id` field links local files to remote documents. Don't remove it!
|
|
123
|
+
- When pushing: Files with `kaimon_id` update existing documents
|
|
124
|
+
- When pushing: Files without `kaimon_id` create new documents
|
|
125
|
+
- The CLI automatically adds `kaimon_id` to new files after first push
|
|
126
|
+
|
|
127
|
+
## Smart Sync
|
|
128
|
+
|
|
129
|
+
Both `pull` and `push` use **timestamp-based smart sync** to avoid unnecessary transfers:
|
|
130
|
+
|
|
131
|
+
### Pull Logic
|
|
132
|
+
- **New documents**: Not in local folder → pull
|
|
133
|
+
- **Updated documents**: Remote newer than local → pull
|
|
134
|
+
- **Up-to-date**: Remote same age or older → skip
|
|
135
|
+
|
|
136
|
+
### Push Logic
|
|
137
|
+
- **New files**: No `kaimon_id` in frontmatter → create new document
|
|
138
|
+
- **Modified files**: Local newer than remote → push update
|
|
139
|
+
- **Up-to-date**: Remote same age or newer → skip
|
|
140
|
+
|
|
141
|
+
### Example Output
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
$ kaimon pull
|
|
145
|
+
|
|
146
|
+
Checking authentication... ✓
|
|
147
|
+
Analyzing documents...
|
|
148
|
+
|
|
149
|
+
📄 Found 3 document(s) to pull:
|
|
150
|
+
|
|
151
|
+
New documents:
|
|
152
|
+
1. Project Roadmap.md (created 2 hours ago)
|
|
153
|
+
|
|
154
|
+
Updated documents:
|
|
155
|
+
2. README.md (Local: 2 hours ago, Remote: 30 mins ago)
|
|
156
|
+
3. Architecture.md (Local: 5 days ago, Remote: 1 day ago)
|
|
157
|
+
|
|
158
|
+
⏭️ 12 document(s) already up to date
|
|
159
|
+
|
|
160
|
+
📁 Sync Location
|
|
161
|
+
Will sync to: ./KaimonDocs/
|
|
162
|
+
|
|
163
|
+
Continue? (y/N):
|
|
164
|
+
```
|
|
165
|
+
|
|
110
166
|
## Troubleshooting
|
|
111
167
|
|
|
112
168
|
### "Not authenticated"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/commands/pull.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { pullDocuments } from '../../utils/syncOperations.js';
|
|
6
|
+
import * as config from '../../utils/config.js';
|
|
7
|
+
import * as supabaseClient from '../../utils/supabaseClient.js';
|
|
8
|
+
import * as tokenRefresh from '../../utils/tokenRefresh.js';
|
|
9
|
+
import { createTempDir, cleanupTempDir, mockConfig, mockDocumentRecord, mockBlockNoteContent, createMockSupabaseClient } from '../helpers.js';
|
|
10
|
+
describe('pull command', () => {
|
|
11
|
+
let tempDir;
|
|
12
|
+
let docsDir;
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
tempDir = createTempDir();
|
|
15
|
+
docsDir = path.join(tempDir, 'KaimonDocs');
|
|
16
|
+
vi.spyOn(os, 'homedir').mockReturnValue(tempDir);
|
|
17
|
+
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
18
|
+
});
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
cleanupTempDir(tempDir);
|
|
21
|
+
vi.restoreAllMocks();
|
|
22
|
+
});
|
|
23
|
+
describe('pullDocuments', () => {
|
|
24
|
+
it('should pull new documents', async () => {
|
|
25
|
+
// Setup auth
|
|
26
|
+
config.saveConfig(mockConfig());
|
|
27
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
28
|
+
// Mock Supabase
|
|
29
|
+
const mockSupabase = createMockSupabaseClient();
|
|
30
|
+
const mockDocs = [mockDocumentRecord({ title: 'Test Document' })];
|
|
31
|
+
mockSupabase.from.mockReturnValue({
|
|
32
|
+
select: vi.fn().mockReturnThis(),
|
|
33
|
+
order: vi.fn().mockResolvedValue({ data: mockDocs, error: null })
|
|
34
|
+
});
|
|
35
|
+
const mockContent = mockBlockNoteContent('Test Document');
|
|
36
|
+
const blob = new Blob([JSON.stringify(mockContent)], { type: 'application/json' });
|
|
37
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
38
|
+
download: vi.fn().mockResolvedValue({ data: blob, error: null })
|
|
39
|
+
});
|
|
40
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
41
|
+
// Pull with -y flag to skip confirmation
|
|
42
|
+
await pullDocuments(false, true);
|
|
43
|
+
// Verify file was created
|
|
44
|
+
const files = fs.readdirSync(docsDir);
|
|
45
|
+
expect(files).toHaveLength(1);
|
|
46
|
+
expect(files[0]).toContain('.md');
|
|
47
|
+
// Verify content
|
|
48
|
+
const content = fs.readFileSync(path.join(docsDir, files[0]), 'utf-8');
|
|
49
|
+
expect(content).toContain('kaimon_id:');
|
|
50
|
+
expect(content).toContain('Test Document');
|
|
51
|
+
});
|
|
52
|
+
it('should skip up-to-date documents', async () => {
|
|
53
|
+
config.saveConfig(mockConfig());
|
|
54
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
55
|
+
// Create existing file with newer mtime
|
|
56
|
+
const mockDoc = mockDocumentRecord({
|
|
57
|
+
id: 'doc-123',
|
|
58
|
+
title: 'Existing Document',
|
|
59
|
+
updated_at: new Date(Date.now() - 86400000).toISOString() // 1 day ago
|
|
60
|
+
});
|
|
61
|
+
fs.mkdirSync(docsDir, { recursive: true });
|
|
62
|
+
const existingFile = path.join(docsDir, 'Existing-Document.md');
|
|
63
|
+
fs.writeFileSync(existingFile, `---
|
|
64
|
+
kaimon_id: "doc-123"
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
Content`, 'utf-8');
|
|
68
|
+
// Set file mtime to now (newer than remote)
|
|
69
|
+
fs.utimesSync(existingFile, new Date(), new Date());
|
|
70
|
+
const mockSupabase = createMockSupabaseClient();
|
|
71
|
+
mockSupabase.from.mockReturnValue({
|
|
72
|
+
select: vi.fn().mockReturnThis(),
|
|
73
|
+
order: vi.fn().mockResolvedValue({ data: [mockDoc], error: null })
|
|
74
|
+
});
|
|
75
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
76
|
+
await pullDocuments(false, true);
|
|
77
|
+
// File should not be modified
|
|
78
|
+
const content = fs.readFileSync(existingFile, 'utf-8');
|
|
79
|
+
expect(content).toBe(`---
|
|
80
|
+
kaimon_id: "doc-123"
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
Content`);
|
|
84
|
+
});
|
|
85
|
+
it('should use flat directory structure with --flat', async () => {
|
|
86
|
+
config.saveConfig(mockConfig());
|
|
87
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
88
|
+
const mockSupabase = createMockSupabaseClient();
|
|
89
|
+
const mockDocs = [mockDocumentRecord()];
|
|
90
|
+
mockSupabase.from.mockReturnValue({
|
|
91
|
+
select: vi.fn().mockReturnThis(),
|
|
92
|
+
order: vi.fn().mockResolvedValue({ data: mockDocs, error: null })
|
|
93
|
+
});
|
|
94
|
+
const mockContent = mockBlockNoteContent();
|
|
95
|
+
const blob = new Blob([JSON.stringify(mockContent)], { type: 'application/json' });
|
|
96
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
97
|
+
download: vi.fn().mockResolvedValue({ data: blob, error: null })
|
|
98
|
+
});
|
|
99
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
100
|
+
// Pull with --flat
|
|
101
|
+
await pullDocuments(true, true);
|
|
102
|
+
// Files should be in current directory, not KaimonDocs/
|
|
103
|
+
const files = fs.readdirSync(tempDir);
|
|
104
|
+
const mdFiles = files.filter(f => f.endsWith('.md'));
|
|
105
|
+
expect(mdFiles.length).toBeGreaterThan(0);
|
|
106
|
+
expect(fs.existsSync(docsDir)).toBe(false);
|
|
107
|
+
});
|
|
108
|
+
it('should handle no documents gracefully', async () => {
|
|
109
|
+
config.saveConfig(mockConfig());
|
|
110
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
111
|
+
const mockSupabase = createMockSupabaseClient();
|
|
112
|
+
mockSupabase.from.mockReturnValue({
|
|
113
|
+
select: vi.fn().mockReturnThis(),
|
|
114
|
+
order: vi.fn().mockResolvedValue({ data: [], error: null })
|
|
115
|
+
});
|
|
116
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
117
|
+
await pullDocuments(false, true);
|
|
118
|
+
// Should not create directory if no docs
|
|
119
|
+
expect(fs.existsSync(docsDir)).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
it('should handle authentication failure', async () => {
|
|
122
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(false);
|
|
123
|
+
await expect(pullDocuments(false, true)).rejects.toThrow('Not authenticated');
|
|
124
|
+
});
|
|
125
|
+
it('should handle database errors', async () => {
|
|
126
|
+
config.saveConfig(mockConfig());
|
|
127
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
128
|
+
const mockSupabase = createMockSupabaseClient();
|
|
129
|
+
mockSupabase.from.mockReturnValue({
|
|
130
|
+
select: vi.fn().mockReturnThis(),
|
|
131
|
+
order: vi.fn().mockResolvedValue({
|
|
132
|
+
data: null,
|
|
133
|
+
error: { message: 'Database error' }
|
|
134
|
+
})
|
|
135
|
+
});
|
|
136
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
137
|
+
await expect(pullDocuments(false, true)).rejects.toThrow();
|
|
138
|
+
});
|
|
139
|
+
it('should handle storage download errors gracefully', async () => {
|
|
140
|
+
config.saveConfig(mockConfig());
|
|
141
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
142
|
+
const mockSupabase = createMockSupabaseClient();
|
|
143
|
+
const mockDocs = [mockDocumentRecord()];
|
|
144
|
+
mockSupabase.from.mockReturnValue({
|
|
145
|
+
select: vi.fn().mockReturnThis(),
|
|
146
|
+
order: vi.fn().mockResolvedValue({ data: mockDocs, error: null })
|
|
147
|
+
});
|
|
148
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
149
|
+
download: vi.fn().mockResolvedValue({
|
|
150
|
+
data: null,
|
|
151
|
+
error: { message: 'File not found' }
|
|
152
|
+
})
|
|
153
|
+
});
|
|
154
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
155
|
+
// Should not throw, but handle error gracefully
|
|
156
|
+
await pullDocuments(false, true);
|
|
157
|
+
});
|
|
158
|
+
it('should update file mtime to match remote', async () => {
|
|
159
|
+
config.saveConfig(mockConfig());
|
|
160
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
161
|
+
const remoteTime = new Date('2024-01-15T10:00:00Z');
|
|
162
|
+
const mockDoc = mockDocumentRecord({ updated_at: remoteTime.toISOString() });
|
|
163
|
+
const mockSupabase = createMockSupabaseClient();
|
|
164
|
+
mockSupabase.from.mockReturnValue({
|
|
165
|
+
select: vi.fn().mockReturnThis(),
|
|
166
|
+
order: vi.fn().mockResolvedValue({ data: [mockDoc], error: null })
|
|
167
|
+
});
|
|
168
|
+
const mockContent = mockBlockNoteContent();
|
|
169
|
+
const blob = new Blob([JSON.stringify(mockContent)], { type: 'application/json' });
|
|
170
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
171
|
+
download: vi.fn().mockResolvedValue({ data: blob, error: null })
|
|
172
|
+
});
|
|
173
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
174
|
+
await pullDocuments(false, true);
|
|
175
|
+
const files = fs.readdirSync(docsDir);
|
|
176
|
+
const filePath = path.join(docsDir, files[0]);
|
|
177
|
+
const stats = fs.statSync(filePath);
|
|
178
|
+
expect(stats.mtime.toISOString()).toBe(remoteTime.toISOString());
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
//# sourceMappingURL=pull.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.test.js","sourceRoot":"","sources":["../../../src/__tests__/commands/pull.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/commands/push.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { pushDocuments } from '../../utils/pushOperations.js';
|
|
6
|
+
import * as config from '../../utils/config.js';
|
|
7
|
+
import * as supabaseClient from '../../utils/supabaseClient.js';
|
|
8
|
+
import * as tokenRefresh from '../../utils/tokenRefresh.js';
|
|
9
|
+
import { createTempDir, cleanupTempDir, mockConfig, mockDocumentRecord, createMockSupabaseClient, createMockMarkdownFile } from '../helpers.js';
|
|
10
|
+
describe('push command', () => {
|
|
11
|
+
let tempDir;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
tempDir = createTempDir();
|
|
14
|
+
vi.spyOn(os, 'homedir').mockReturnValue(tempDir);
|
|
15
|
+
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
16
|
+
});
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
cleanupTempDir(tempDir);
|
|
19
|
+
vi.restoreAllMocks();
|
|
20
|
+
});
|
|
21
|
+
describe('pushDocuments', () => {
|
|
22
|
+
it('should create new documents without kaimon_id', async () => {
|
|
23
|
+
config.saveConfig(mockConfig());
|
|
24
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
25
|
+
// Create a markdown file without kaimon_id
|
|
26
|
+
const filePath = createMockMarkdownFile(tempDir, 'new-doc.md', '# New Document\n\nContent here.');
|
|
27
|
+
const mockSupabase = createMockSupabaseClient();
|
|
28
|
+
// Mock user
|
|
29
|
+
mockSupabase.auth.getUser.mockResolvedValue({
|
|
30
|
+
data: { user: { id: 'user-123', email: 'test@example.com' } },
|
|
31
|
+
error: null
|
|
32
|
+
});
|
|
33
|
+
// Create a chainable mock query builder
|
|
34
|
+
const mockChain = {
|
|
35
|
+
select: vi.fn().mockReturnThis(),
|
|
36
|
+
in: vi.fn().mockResolvedValue({ data: [], error: null }),
|
|
37
|
+
insert: vi.fn().mockReturnThis(),
|
|
38
|
+
single: vi.fn().mockResolvedValue({
|
|
39
|
+
data: { id: 'new-doc-id', title: 'new-doc', created_at: new Date().toISOString(), updated_at: new Date().toISOString() },
|
|
40
|
+
error: null
|
|
41
|
+
})
|
|
42
|
+
};
|
|
43
|
+
// Make sure each method returns the same chain object
|
|
44
|
+
mockChain.select.mockReturnValue(mockChain);
|
|
45
|
+
mockChain.insert.mockReturnValue(mockChain);
|
|
46
|
+
mockSupabase.from.mockReturnValue(mockChain);
|
|
47
|
+
// Mock storage upload
|
|
48
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
49
|
+
upload: vi.fn().mockResolvedValue({ data: {}, error: null })
|
|
50
|
+
});
|
|
51
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
52
|
+
await pushDocuments({ skipConfirmation: true });
|
|
53
|
+
// Verify insert was called (document created)
|
|
54
|
+
expect(mockChain.insert).toHaveBeenCalled();
|
|
55
|
+
// Verify file was updated with kaimon_id
|
|
56
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
57
|
+
expect(content).toContain('kaimon_id: "new-doc-id"');
|
|
58
|
+
});
|
|
59
|
+
it('should update existing documents with kaimon_id', async () => {
|
|
60
|
+
config.saveConfig(mockConfig());
|
|
61
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
62
|
+
// Create a markdown file with kaimon_id (older than remote)
|
|
63
|
+
const oldTime = new Date(Date.now() - 86400000); // 1 day ago
|
|
64
|
+
const filePath = createMockMarkdownFile(tempDir, 'existing-doc.md', '# Updated Content', { kaimon_id: 'doc-123', updated_at: oldTime.toISOString() });
|
|
65
|
+
// Make file newer by touching it
|
|
66
|
+
const newTime = new Date();
|
|
67
|
+
fs.utimesSync(filePath, newTime, newTime);
|
|
68
|
+
const mockSupabase = createMockSupabaseClient();
|
|
69
|
+
mockSupabase.auth.getUser.mockResolvedValue({
|
|
70
|
+
data: { user: { id: 'user-123', email: 'test@example.com' } },
|
|
71
|
+
error: null
|
|
72
|
+
});
|
|
73
|
+
// Mock finding existing document
|
|
74
|
+
mockSupabase.from.mockReturnValue({
|
|
75
|
+
select: vi.fn().mockReturnThis(),
|
|
76
|
+
in: vi.fn().mockResolvedValue({
|
|
77
|
+
data: [mockDocumentRecord({ id: 'doc-123', updated_at: oldTime.toISOString() })],
|
|
78
|
+
error: null
|
|
79
|
+
}),
|
|
80
|
+
update: vi.fn().mockReturnThis(),
|
|
81
|
+
eq: vi.fn().mockResolvedValue({ error: null })
|
|
82
|
+
});
|
|
83
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
84
|
+
upload: vi.fn().mockResolvedValue({ data: {}, error: null })
|
|
85
|
+
});
|
|
86
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
87
|
+
await pushDocuments({ skipConfirmation: true });
|
|
88
|
+
// Verify upload was called
|
|
89
|
+
expect(mockSupabase.storage.from().upload).toHaveBeenCalled();
|
|
90
|
+
});
|
|
91
|
+
it('should skip up-to-date documents', async () => {
|
|
92
|
+
config.saveConfig(mockConfig());
|
|
93
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
94
|
+
// Create file with older local time
|
|
95
|
+
const oldTime = new Date(Date.now() - 86400000);
|
|
96
|
+
const filePath = createMockMarkdownFile(tempDir, 'old-doc.md', '# Content', { kaimon_id: 'doc-123' });
|
|
97
|
+
fs.utimesSync(filePath, oldTime, oldTime);
|
|
98
|
+
const mockSupabase = createMockSupabaseClient();
|
|
99
|
+
mockSupabase.auth.getUser.mockResolvedValue({
|
|
100
|
+
data: { user: { id: 'user-123' } },
|
|
101
|
+
error: null
|
|
102
|
+
});
|
|
103
|
+
// Remote is newer
|
|
104
|
+
mockSupabase.from.mockReturnValue({
|
|
105
|
+
select: vi.fn().mockReturnThis(),
|
|
106
|
+
in: vi.fn().mockResolvedValue({
|
|
107
|
+
data: [mockDocumentRecord({ id: 'doc-123', updated_at: new Date().toISOString() })],
|
|
108
|
+
error: null
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
const uploadSpy = vi.fn().mockResolvedValue({ data: {}, error: null });
|
|
112
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
113
|
+
upload: uploadSpy
|
|
114
|
+
});
|
|
115
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
116
|
+
await pushDocuments({ skipConfirmation: true });
|
|
117
|
+
// Upload should not be called for up-to-date docs
|
|
118
|
+
expect(uploadSpy).not.toHaveBeenCalled();
|
|
119
|
+
});
|
|
120
|
+
it('should push only specified files', async () => {
|
|
121
|
+
config.saveConfig(mockConfig());
|
|
122
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
123
|
+
createMockMarkdownFile(tempDir, 'doc1.md', '# Doc 1');
|
|
124
|
+
createMockMarkdownFile(tempDir, 'doc2.md', '# Doc 2');
|
|
125
|
+
createMockMarkdownFile(tempDir, 'doc3.md', '# Doc 3');
|
|
126
|
+
const mockSupabase = createMockSupabaseClient();
|
|
127
|
+
mockSupabase.auth.getUser.mockResolvedValue({
|
|
128
|
+
data: { user: { id: 'user-123' } },
|
|
129
|
+
error: null
|
|
130
|
+
});
|
|
131
|
+
mockSupabase.from.mockReturnValue({
|
|
132
|
+
select: vi.fn().mockReturnThis(),
|
|
133
|
+
in: vi.fn().mockResolvedValue({ data: [], error: null }),
|
|
134
|
+
insert: vi.fn().mockReturnThis(),
|
|
135
|
+
single: vi.fn().mockResolvedValue({
|
|
136
|
+
data: { id: 'new-id', created_at: new Date().toISOString(), updated_at: new Date().toISOString() },
|
|
137
|
+
error: null
|
|
138
|
+
})
|
|
139
|
+
});
|
|
140
|
+
const uploadSpy = vi.fn().mockResolvedValue({ data: {}, error: null });
|
|
141
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
142
|
+
upload: uploadSpy
|
|
143
|
+
});
|
|
144
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
145
|
+
// Push only doc1.md
|
|
146
|
+
await pushDocuments({ files: ['doc1.md'], skipConfirmation: true });
|
|
147
|
+
// Only one file should be uploaded
|
|
148
|
+
expect(uploadSpy).toHaveBeenCalledTimes(1);
|
|
149
|
+
});
|
|
150
|
+
it('should skip excluded directories', async () => {
|
|
151
|
+
config.saveConfig(mockConfig());
|
|
152
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
153
|
+
// Create files in excluded directories
|
|
154
|
+
fs.mkdirSync(path.join(tempDir, 'node_modules'), { recursive: true });
|
|
155
|
+
fs.mkdirSync(path.join(tempDir, '.git'), { recursive: true });
|
|
156
|
+
createMockMarkdownFile(path.join(tempDir, 'node_modules'), 'should-skip.md', '# Skip');
|
|
157
|
+
createMockMarkdownFile(path.join(tempDir, '.git'), 'also-skip.md', '# Skip');
|
|
158
|
+
createMockMarkdownFile(tempDir, 'should-include.md', '# Include');
|
|
159
|
+
const mockSupabase = createMockSupabaseClient();
|
|
160
|
+
mockSupabase.auth.getUser.mockResolvedValue({
|
|
161
|
+
data: { user: { id: 'user-123' } },
|
|
162
|
+
error: null
|
|
163
|
+
});
|
|
164
|
+
mockSupabase.from.mockReturnValue({
|
|
165
|
+
select: vi.fn().mockReturnThis(),
|
|
166
|
+
in: vi.fn().mockResolvedValue({ data: [], error: null }),
|
|
167
|
+
insert: vi.fn().mockReturnThis(),
|
|
168
|
+
single: vi.fn().mockResolvedValue({
|
|
169
|
+
data: { id: 'new-id', created_at: new Date().toISOString(), updated_at: new Date().toISOString() },
|
|
170
|
+
error: null
|
|
171
|
+
})
|
|
172
|
+
});
|
|
173
|
+
const uploadSpy = vi.fn().mockResolvedValue({ data: {}, error: null });
|
|
174
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
175
|
+
upload: uploadSpy
|
|
176
|
+
});
|
|
177
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
178
|
+
await pushDocuments({ skipConfirmation: true });
|
|
179
|
+
// Only one file should be found (excluded dirs skipped)
|
|
180
|
+
expect(uploadSpy).toHaveBeenCalledTimes(1);
|
|
181
|
+
});
|
|
182
|
+
it('should handle no markdown files gracefully', async () => {
|
|
183
|
+
config.saveConfig(mockConfig());
|
|
184
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
185
|
+
const mockSupabase = createMockSupabaseClient();
|
|
186
|
+
mockSupabase.auth.getUser.mockResolvedValue({
|
|
187
|
+
data: { user: { id: 'user-123' } },
|
|
188
|
+
error: null
|
|
189
|
+
});
|
|
190
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
191
|
+
await pushDocuments({ skipConfirmation: true });
|
|
192
|
+
// Should complete without error
|
|
193
|
+
});
|
|
194
|
+
it('should handle authentication failure', async () => {
|
|
195
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(false);
|
|
196
|
+
await expect(pushDocuments({ skipConfirmation: true })).rejects.toThrow('Not authenticated');
|
|
197
|
+
});
|
|
198
|
+
it('should handle upload errors gracefully', async () => {
|
|
199
|
+
config.saveConfig(mockConfig());
|
|
200
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
201
|
+
createMockMarkdownFile(tempDir, 'doc.md', '# Document');
|
|
202
|
+
const mockSupabase = createMockSupabaseClient();
|
|
203
|
+
mockSupabase.auth.getUser.mockResolvedValue({
|
|
204
|
+
data: { user: { id: 'user-123' } },
|
|
205
|
+
error: null
|
|
206
|
+
});
|
|
207
|
+
mockSupabase.from.mockReturnValue({
|
|
208
|
+
select: vi.fn().mockReturnThis(),
|
|
209
|
+
in: vi.fn().mockResolvedValue({ data: [], error: null }),
|
|
210
|
+
insert: vi.fn().mockReturnThis(),
|
|
211
|
+
single: vi.fn().mockResolvedValue({
|
|
212
|
+
data: { id: 'new-id', created_at: new Date().toISOString(), updated_at: new Date().toISOString() },
|
|
213
|
+
error: null
|
|
214
|
+
})
|
|
215
|
+
});
|
|
216
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
217
|
+
upload: vi.fn().mockResolvedValue({
|
|
218
|
+
data: null,
|
|
219
|
+
error: { message: 'Upload failed' }
|
|
220
|
+
})
|
|
221
|
+
});
|
|
222
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
223
|
+
// Should not throw, but handle error gracefully
|
|
224
|
+
await pushDocuments({ skipConfirmation: true });
|
|
225
|
+
});
|
|
226
|
+
it('should extract title from filename if not in frontmatter', async () => {
|
|
227
|
+
config.saveConfig(mockConfig());
|
|
228
|
+
vi.spyOn(tokenRefresh, 'ensureValidToken').mockResolvedValue(true);
|
|
229
|
+
createMockMarkdownFile(tempDir, 'My-Great-Document.md', '# Content');
|
|
230
|
+
const mockSupabase = createMockSupabaseClient();
|
|
231
|
+
mockSupabase.auth.getUser.mockResolvedValue({
|
|
232
|
+
data: { user: { id: 'user-123' } },
|
|
233
|
+
error: null
|
|
234
|
+
});
|
|
235
|
+
const insertSpy = vi.fn().mockReturnThis();
|
|
236
|
+
mockSupabase.from.mockReturnValue({
|
|
237
|
+
select: vi.fn().mockReturnThis(),
|
|
238
|
+
in: vi.fn().mockResolvedValue({ data: [], error: null }),
|
|
239
|
+
insert: insertSpy,
|
|
240
|
+
single: vi.fn().mockResolvedValue({
|
|
241
|
+
data: { id: 'new-id', title: 'My-Great-Document', created_at: new Date().toISOString(), updated_at: new Date().toISOString() },
|
|
242
|
+
error: null
|
|
243
|
+
})
|
|
244
|
+
});
|
|
245
|
+
mockSupabase.storage.from.mockReturnValue({
|
|
246
|
+
upload: vi.fn().mockResolvedValue({ data: {}, error: null })
|
|
247
|
+
});
|
|
248
|
+
vi.spyOn(supabaseClient, 'getSupabaseClient').mockReturnValue(mockSupabase);
|
|
249
|
+
await pushDocuments({ skipConfirmation: true });
|
|
250
|
+
// Verify title was extracted from filename
|
|
251
|
+
expect(insertSpy).toHaveBeenCalledWith(expect.objectContaining({ title: 'My-Great-Document' }));
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
//# sourceMappingURL=push.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.test.js","sourceRoot":"","sources":["../../../src/__tests__/commands/push.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers for mocking and utilities
|
|
3
|
+
*/
|
|
4
|
+
export declare function createMockSupabaseClient(): {
|
|
5
|
+
auth: {
|
|
6
|
+
getUser: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
7
|
+
refreshSession: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
8
|
+
};
|
|
9
|
+
from: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
10
|
+
storage: {
|
|
11
|
+
from: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export declare function mockBlockNoteContent(title?: string): {
|
|
15
|
+
type: string;
|
|
16
|
+
content: ({
|
|
17
|
+
type: string;
|
|
18
|
+
props: {
|
|
19
|
+
level: number;
|
|
20
|
+
};
|
|
21
|
+
content: {
|
|
22
|
+
type: string;
|
|
23
|
+
text: string;
|
|
24
|
+
}[];
|
|
25
|
+
} | {
|
|
26
|
+
type: string;
|
|
27
|
+
content: {
|
|
28
|
+
type: string;
|
|
29
|
+
text: string;
|
|
30
|
+
}[];
|
|
31
|
+
props?: undefined;
|
|
32
|
+
})[];
|
|
33
|
+
};
|
|
34
|
+
export declare function mockDocumentRecord(overrides?: any): any;
|
|
35
|
+
export declare function createTempDir(prefix?: string): string;
|
|
36
|
+
export declare function cleanupTempDir(dirPath: string): void;
|
|
37
|
+
export declare function mockConfig(overrides?: any): any;
|
|
38
|
+
export declare function mockProjectConfig(overrides?: any): any;
|
|
39
|
+
export declare function createMockMarkdownFile(dirPath: string, filename: string, content: string, frontmatter?: any): string;
|
|
40
|
+
export declare function mockReadline(answers: string[]): {
|
|
41
|
+
createInterface: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
42
|
+
};
|
|
43
|
+
export declare function mockStdin(input: string): {
|
|
44
|
+
on: import("vitest").Mock<(event: string, handler: (data: string) => void) => void>;
|
|
45
|
+
setRawMode: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
46
|
+
resume: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
47
|
+
pause: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/__tests__/helpers.ts"],"names":[],"mappings":"AAKA;;GAEG;AAGH,wBAAgB,wBAAwB;;;;;;;;;EAkCvC;AAGD,wBAAgB,oBAAoB,CAAC,KAAK,GAAE,MAAwB;;;;;;;;;;;;;;;;;;;EAuBnE;AAGD,wBAAgB,kBAAkB,CAAC,SAAS,GAAE,GAAQ,OASrD;AAGD,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAuB,GAAG,MAAM,CAErE;AAGD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAIpD;AAGD,wBAAgB,UAAU,CAAC,SAAS,GAAE,GAAQ,OAQ7C;AAGD,wBAAgB,iBAAiB,CAAC,SAAS,GAAE,GAAQ,OAUpD;AAGD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,GAAQ,GACpB,MAAM,CAaR;AAGD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE;;EAY7C;AAGD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM;sCAEjB,MAAM,WAAW,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;;;;EAW5D"}
|