sprint-artifact 0.2.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/LICENSE ADDED
@@ -0,0 +1 @@
1
+ MIT License
package/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # Sprint Artifact
2
+
3
+ Sprint Artifact management tool with Google Drive integration.
4
+
5
+ Manage your sprint artifacts (BRD, PRD, tasks, backlogs) directly from CLI or AI assistants (Cursor, Claude, Codex, OpenCode).
6
+
7
+ ## Features
8
+
9
+ - **CLI** - Full command-line interface for sprint management
10
+ - **MCP Server** - Integration with AI coding assistants
11
+ - **SDK** - Programmatic access for custom workflows
12
+ - **Google Drive Sync** - Bi-directional sync with Google Drive
13
+ - **OAuth2 Login** - Simple Google account login for team members
14
+
15
+ ## Quick Start
16
+
17
+ ### Install
18
+
19
+ ```bash
20
+ npm install -g sprint-artifact
21
+ ```
22
+
23
+ ### Setup Google Cloud
24
+
25
+ 1. Buka [Google Cloud Console](https://console.cloud.google.com)
26
+ 2. Buat/select project
27
+ 3. Enable **Google Drive API** (APIs & Services > Library)
28
+ 4. Buat **OAuth consent screen** (APIs & Services > OAuth consent screen)
29
+ - User Type: **Internal** (Workspace) atau **External**
30
+ - App name: `sprint-artifact`
31
+ 5. Buat **OAuth 2.0 Client ID** (APIs & Services > Credentials)
32
+ - Application type: **Desktop app**
33
+ - Download JSON
34
+
35
+ ### Login
36
+
37
+ ```bash
38
+ # Taruh credentials.json di folder project atau ~/.sprint-artifact/
39
+ cp ~/Downloads/credentials.json ./credentials.json
40
+
41
+ # Login dengan Google account
42
+ sprint-artifact login
43
+ ```
44
+
45
+ Browser terbuka > pilih akun Google > selesai.
46
+
47
+ ### Initialize Project
48
+
49
+ ```bash
50
+ # Buat folder di Google Drive, copy folder ID dari URL
51
+ sprint-artifact init --folder-id <GOOGLE_DRIVE_FOLDER_ID>
52
+ ```
53
+
54
+ ## CLI Commands
55
+
56
+ ```bash
57
+ # Login dengan Google account
58
+ sprint-artifact login [--credentials <path>]
59
+
60
+ # Initialize project
61
+ sprint-artifact init --folder-id <FOLDER_ID>
62
+
63
+ # Buat backlog item
64
+ sprint-artifact backlog create --title "Feature" --desc "Description" --priority high
65
+
66
+ # Sync dengan Google Drive
67
+ sprint-artifact sync
68
+
69
+ # Lihat status
70
+ sprint-artifact status
71
+
72
+ # Pilih task yang sedang dikerjakan
73
+ sprint-artifact select <TASK_ID>
74
+
75
+ # Pindahkan backlog ke sprint
76
+ sprint-artifact sprint move --backlog-id <ID> --sprint-id <ID>
77
+ ```
78
+
79
+ ## MCP Server
80
+
81
+ Tambahkan ke konfigurasi MCP (Cursor, Claude, dll):
82
+
83
+ ```json
84
+ {
85
+ "mcpServers": {
86
+ "sprint-artifact": {
87
+ "command": "sprint-artifact",
88
+ "args": ["mcp"]
89
+ }
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### Available Tools
95
+
96
+ | Tool | Description |
97
+ |------|-------------|
98
+ | `backlog_create` | Buat backlog item baru |
99
+ | `sync_documents` | Sync dokumen dengan Google Drive |
100
+ | `move_to_sprint` | Pindahkan backlog ke sprint |
101
+ | `status` | Lihat status project |
102
+ | `select_task` | Pilih task yang sedang dikerjakan |
103
+
104
+ ## SDK Usage
105
+
106
+ ```typescript
107
+ import { SprintArtifact } from 'sprint-artifact';
108
+
109
+ const artifact = new SprintArtifact(process.cwd());
110
+
111
+ // Login (hanya perlu sekali)
112
+ await artifact.init('GOOGLE_DRIVE_FOLDER_ID');
113
+
114
+ // Buat backlog
115
+ await artifact.createBacklog('Feature A', 'Description', 'high');
116
+
117
+ // Sync dengan Google Drive
118
+ const result = await artifact.sync();
119
+ console.log(`Added: ${result.added}, Updated: ${result.updated}`);
120
+ ```
121
+
122
+ ## Configuration
123
+
124
+ ### `.sprint-artifact/config.json`
125
+
126
+ ```json
127
+ {
128
+ "version": 1,
129
+ "googleDrive": {
130
+ "folderId": "your-folder-id"
131
+ },
132
+ "selectedTask": "task-id",
133
+ "manifest": {
134
+ "lastSync": "2024-01-01T00:00:00Z",
135
+ "files": []
136
+ }
137
+ }
138
+ ```
139
+
140
+ ### `.sprint-artifact/auth.json`
141
+
142
+ Auto-generated saat login. Jangan commit ke repository.
143
+
144
+ ## Project Structure
145
+
146
+ ```
147
+ .sprint-artifact/
148
+ ├── config.json # Project config (folder ID, manifest)
149
+ └── auth.json # OAuth2 tokens (auto-generated)
150
+ ```
151
+
152
+ ## Security
153
+
154
+ - `auth.json` dan `credentials.json` di-**gitignore** secara default
155
+ - Setiap user login dengan akun Google masing-masing
156
+ - Token tersimpan lokal di tiap komputer
157
+ - Untuk team, share `credentials.json` via internal docs (bukan public repo)
158
+
159
+ ## License
160
+
161
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { SprintArtifact } from '../sdk/index.js';
4
+ import { resolve } from 'node:path';
5
+ import { login } from '../utils/oauth2.js';
6
+ import { saveAuth } from '../utils/config.js';
7
+ const program = new Command();
8
+ program
9
+ .name('sprint-artifact')
10
+ .description('Sprint Artifact management tool with Google Drive integration')
11
+ .version('0.1.0');
12
+ program
13
+ .command('login')
14
+ .description('Login with Google account (auto-detect credentials)')
15
+ .option('--credentials <path>', 'Path to OAuth2 credentials JSON file')
16
+ .action(async (options) => {
17
+ try {
18
+ const projectRoot = resolve(process.cwd());
19
+ const credentials = await login({
20
+ credentialsPath: options.credentials,
21
+ });
22
+ await saveAuth(projectRoot, {
23
+ type: 'oauth2',
24
+ credentials,
25
+ });
26
+ console.log('✓ Login successful');
27
+ console.log(' Auth saved to .sprint-artifact/auth.json');
28
+ }
29
+ catch (error) {
30
+ console.error('✗ Login failed:', error);
31
+ process.exit(1);
32
+ }
33
+ });
34
+ program
35
+ .command('init')
36
+ .description('Initialize a new Sprint Artifact project')
37
+ .requiredOption('--folder-id <id>', 'Google Drive folder ID')
38
+ .option('--auth <path>', 'Path to auth JSON file')
39
+ .action(async (options) => {
40
+ try {
41
+ const projectRoot = resolve(process.cwd());
42
+ const artifact = new SprintArtifact(projectRoot);
43
+ await artifact.init(options.folderId);
44
+ console.log('✓ Sprint Artifact project initialized');
45
+ console.log(` Folder ID: ${options.folderId}`);
46
+ console.log(' Config: .sprint-artifact/config.json');
47
+ if (options.auth) {
48
+ console.log(` Auth: ${options.auth}`);
49
+ }
50
+ }
51
+ catch (error) {
52
+ console.error('✗ Failed to initialize:', error);
53
+ process.exit(1);
54
+ }
55
+ });
56
+ const backlogCmd = program
57
+ .command('backlog')
58
+ .description('Manage backlog items');
59
+ backlogCmd
60
+ .command('create')
61
+ .description('Create a new backlog item')
62
+ .requiredOption('--title <title>', 'Backlog item title')
63
+ .option('--description <desc>', 'Backlog item description', '')
64
+ .option('--priority <priority>', 'Priority (high, medium, low)', 'medium')
65
+ .action(async (options) => {
66
+ try {
67
+ const projectRoot = resolve(process.cwd());
68
+ const artifact = new SprintArtifact(projectRoot);
69
+ const item = await artifact.createBacklog(options.title, options.description, options.priority);
70
+ console.log('✓ Backlog item created');
71
+ console.log(` ID: ${item.id}`);
72
+ console.log(` Title: ${item.title}`);
73
+ }
74
+ catch (error) {
75
+ console.error('✗ Failed to create backlog item:', error);
76
+ process.exit(1);
77
+ }
78
+ });
79
+ program
80
+ .command('sync')
81
+ .description('Sync documents with Google Drive')
82
+ .action(async () => {
83
+ try {
84
+ const projectRoot = resolve(process.cwd());
85
+ const artifact = new SprintArtifact(projectRoot);
86
+ const result = await artifact.sync();
87
+ console.log('✓ Sync completed');
88
+ console.log(` Added: ${result.added}`);
89
+ console.log(` Updated: ${result.updated}`);
90
+ console.log(` Deleted: ${result.deleted}`);
91
+ }
92
+ catch (error) {
93
+ console.error('✗ Sync failed:', error);
94
+ process.exit(1);
95
+ }
96
+ });
97
+ program
98
+ .command('status')
99
+ .description('Show project status')
100
+ .action(async () => {
101
+ try {
102
+ const projectRoot = resolve(process.cwd());
103
+ const artifact = new SprintArtifact(projectRoot);
104
+ const status = await artifact.status();
105
+ console.log('Sprint Artifact Status');
106
+ console.log('─'.repeat(40));
107
+ console.log(`Initialized: ${status.initialized ? 'Yes' : 'No'}`);
108
+ if (status.initialized) {
109
+ console.log(`Folder ID: ${status.folderId}`);
110
+ console.log(`Selected Task: ${status.selectedTask || 'None'}`);
111
+ console.log(`Last Sync: ${status.lastSync || 'Never'}`);
112
+ console.log(`Files: ${status.fileCount}`);
113
+ }
114
+ }
115
+ catch (error) {
116
+ console.error('✗ Failed to get status:', error);
117
+ process.exit(1);
118
+ }
119
+ });
120
+ program
121
+ .command('select')
122
+ .description('Select a task to work on')
123
+ .argument('<task-id>', 'Task ID to select')
124
+ .action(async (taskId) => {
125
+ try {
126
+ const projectRoot = resolve(process.cwd());
127
+ const artifact = new SprintArtifact(projectRoot);
128
+ await artifact.selectTask(taskId);
129
+ console.log(`✓ Selected task: ${taskId}`);
130
+ }
131
+ catch (error) {
132
+ console.error('✗ Failed to select task:', error);
133
+ process.exit(1);
134
+ }
135
+ });
136
+ const sprintCmd = program
137
+ .command('sprint')
138
+ .description('Manage sprints');
139
+ sprintCmd
140
+ .command('move')
141
+ .description('Move a backlog item to a sprint')
142
+ .requiredOption('--backlog-id <id>', 'Backlog item ID')
143
+ .requiredOption('--sprint-id <id>', 'Sprint ID')
144
+ .action(async (options) => {
145
+ try {
146
+ const projectRoot = resolve(process.cwd());
147
+ const artifact = new SprintArtifact(projectRoot);
148
+ await artifact.moveToSprint(options.backlogId, options.sprintId);
149
+ console.log(`✓ Moved backlog item ${options.backlogId} to sprint ${options.sprintId}`);
150
+ }
151
+ catch (error) {
152
+ console.error('✗ Failed to move item:', error);
153
+ process.exit(1);
154
+ }
155
+ });
156
+ program.parse();
157
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { SprintArtifact } from '../sdk/index.js';
6
+ import { resolve } from 'node:path';
7
+ import { z } from 'zod';
8
+ const server = new Server({
9
+ name: 'sprint-artifact',
10
+ version: '0.1.0',
11
+ }, {
12
+ capabilities: {
13
+ tools: {},
14
+ },
15
+ });
16
+ const projectRoot = resolve(process.cwd());
17
+ const artifact = new SprintArtifact(projectRoot);
18
+ const BacklogCreateSchema = z.object({
19
+ title: z.string(),
20
+ description: z.string().optional().default(''),
21
+ priority: z.enum(['high', 'medium', 'low']).optional().default('medium'),
22
+ });
23
+ const SyncSchema = z.object({});
24
+ const MoveToSprintSchema = z.object({
25
+ backlogId: z.string(),
26
+ sprintId: z.string(),
27
+ });
28
+ const StatusSchema = z.object({});
29
+ const SelectTaskSchema = z.object({
30
+ taskId: z.string(),
31
+ });
32
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
33
+ return {
34
+ tools: [
35
+ {
36
+ name: 'backlog_create',
37
+ description: 'Create a new backlog item in Google Drive',
38
+ inputSchema: {
39
+ type: 'object',
40
+ properties: {
41
+ title: { type: 'string', description: 'Backlog item title' },
42
+ description: { type: 'string', description: 'Backlog item description' },
43
+ priority: {
44
+ type: 'string',
45
+ enum: ['high', 'medium', 'low'],
46
+ description: 'Priority level',
47
+ },
48
+ },
49
+ required: ['title'],
50
+ },
51
+ },
52
+ {
53
+ name: 'sync_documents',
54
+ description: 'Sync documents between local and Google Drive',
55
+ inputSchema: {
56
+ type: 'object',
57
+ properties: {},
58
+ },
59
+ },
60
+ {
61
+ name: 'move_to_sprint',
62
+ description: 'Move a backlog item to a sprint',
63
+ inputSchema: {
64
+ type: 'object',
65
+ properties: {
66
+ backlogId: { type: 'string', description: 'Backlog item ID' },
67
+ sprintId: { type: 'string', description: 'Sprint ID' },
68
+ },
69
+ required: ['backlogId', 'sprintId'],
70
+ },
71
+ },
72
+ {
73
+ name: 'status',
74
+ description: 'Get current project status',
75
+ inputSchema: {
76
+ type: 'object',
77
+ properties: {},
78
+ },
79
+ },
80
+ {
81
+ name: 'select_task',
82
+ description: 'Select a task to work on',
83
+ inputSchema: {
84
+ type: 'object',
85
+ properties: {
86
+ taskId: { type: 'string', description: 'Task ID to select' },
87
+ },
88
+ required: ['taskId'],
89
+ },
90
+ },
91
+ ],
92
+ };
93
+ });
94
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
95
+ const { name, arguments: args } = request.params;
96
+ try {
97
+ switch (name) {
98
+ case 'backlog_create': {
99
+ const { title, description, priority } = BacklogCreateSchema.parse(args);
100
+ const item = await artifact.createBacklog(title, description, priority);
101
+ return {
102
+ content: [
103
+ {
104
+ type: 'text',
105
+ text: JSON.stringify(item, null, 2),
106
+ },
107
+ ],
108
+ };
109
+ }
110
+ case 'sync_documents': {
111
+ SyncSchema.parse(args);
112
+ const result = await artifact.sync();
113
+ return {
114
+ content: [
115
+ {
116
+ type: 'text',
117
+ text: JSON.stringify(result, null, 2),
118
+ },
119
+ ],
120
+ };
121
+ }
122
+ case 'move_to_sprint': {
123
+ const { backlogId, sprintId } = MoveToSprintSchema.parse(args);
124
+ await artifact.moveToSprint(backlogId, sprintId);
125
+ return {
126
+ content: [
127
+ {
128
+ type: 'text',
129
+ text: `Moved backlog item ${backlogId} to sprint ${sprintId}`,
130
+ },
131
+ ],
132
+ };
133
+ }
134
+ case 'status': {
135
+ StatusSchema.parse(args);
136
+ const status = await artifact.status();
137
+ return {
138
+ content: [
139
+ {
140
+ type: 'text',
141
+ text: JSON.stringify(status, null, 2),
142
+ },
143
+ ],
144
+ };
145
+ }
146
+ case 'select_task': {
147
+ const { taskId } = SelectTaskSchema.parse(args);
148
+ await artifact.selectTask(taskId);
149
+ return {
150
+ content: [
151
+ {
152
+ type: 'text',
153
+ text: `Selected task: ${taskId}`,
154
+ },
155
+ ],
156
+ };
157
+ }
158
+ default:
159
+ throw new Error(`Unknown tool: ${name}`);
160
+ }
161
+ }
162
+ catch (error) {
163
+ return {
164
+ content: [
165
+ {
166
+ type: 'text',
167
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
168
+ },
169
+ ],
170
+ isError: true,
171
+ };
172
+ }
173
+ });
174
+ async function main() {
175
+ const transport = new StdioServerTransport();
176
+ await server.connect(transport);
177
+ console.error('Sprint Artifact MCP server running on stdio');
178
+ }
179
+ main().catch(console.error);
180
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { AuthConfig, ManifestFile } from '../types/index.js';
2
+ export declare class GoogleDriveClient {
3
+ private drive;
4
+ constructor(auth: AuthConfig);
5
+ private createAuthClient;
6
+ createFolder(name: string, parentId?: string): Promise<string>;
7
+ createFile(name: string, content: string, parentId?: string, mimeType?: string): Promise<string>;
8
+ getFile(fileId: string): Promise<string>;
9
+ updateFile(fileId: string, content: string, mimeType?: string): Promise<void>;
10
+ listFiles(folderId: string): Promise<ManifestFile[]>;
11
+ getFileMetadata(fileId: string): Promise<ManifestFile>;
12
+ deleteFile(fileId: string): Promise<void>;
13
+ findFolder(name: string, parentId?: string): Promise<string | null>;
14
+ }
15
+ //# sourceMappingURL=google-drive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-drive.d.ts","sourceRoot":"","sources":["../../src/sdk/google-drive.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAqB,MAAM,mBAAmB,CAAC;AAErF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAiB;gBAElB,IAAI,EAAE,UAAU;IAK5B,OAAO,CAAC,gBAAgB;IAuBlB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAe9D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,SAAkB,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBzG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQxC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtF,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAgBpD,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAgBtD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAa1E"}
@@ -0,0 +1,114 @@
1
+ import { google } from 'googleapis';
2
+ export class GoogleDriveClient {
3
+ drive;
4
+ constructor(auth) {
5
+ const authClient = this.createAuthClient(auth);
6
+ this.drive = google.drive({ version: 'v3', auth: authClient });
7
+ }
8
+ createAuthClient(auth) {
9
+ if (auth.type === 'service_account') {
10
+ return new google.auth.GoogleAuth({
11
+ credentials: auth.credentials,
12
+ scopes: ['https://www.googleapis.com/auth/drive'],
13
+ });
14
+ }
15
+ else {
16
+ const creds = auth.credentials;
17
+ const oauth2Client = new google.auth.OAuth2(creds.client_id, creds.client_secret, creds.redirect_uris[0]);
18
+ if (creds.refresh_token) {
19
+ oauth2Client.setCredentials({
20
+ refresh_token: creds.refresh_token,
21
+ access_token: creds.access_token,
22
+ });
23
+ }
24
+ return oauth2Client;
25
+ }
26
+ }
27
+ async createFolder(name, parentId) {
28
+ const fileMetadata = {
29
+ name,
30
+ mimeType: 'application/vnd.google-apps.folder',
31
+ ...(parentId && { parents: [parentId] }),
32
+ };
33
+ const response = await this.drive.files.create({
34
+ requestBody: fileMetadata,
35
+ fields: 'id',
36
+ });
37
+ return response.data.id;
38
+ }
39
+ async createFile(name, content, parentId, mimeType = 'text/markdown') {
40
+ const fileMetadata = {
41
+ name,
42
+ ...(parentId && { parents: [parentId] }),
43
+ };
44
+ const media = {
45
+ mimeType,
46
+ body: content,
47
+ };
48
+ const response = await this.drive.files.create({
49
+ requestBody: fileMetadata,
50
+ media,
51
+ fields: 'id',
52
+ });
53
+ return response.data.id;
54
+ }
55
+ async getFile(fileId) {
56
+ const response = await this.drive.files.get({
57
+ fileId,
58
+ alt: 'media',
59
+ });
60
+ return response.data;
61
+ }
62
+ async updateFile(fileId, content, mimeType = 'text/markdown') {
63
+ await this.drive.files.update({
64
+ fileId,
65
+ media: {
66
+ mimeType,
67
+ body: content,
68
+ },
69
+ });
70
+ }
71
+ async listFiles(folderId) {
72
+ const response = await this.drive.files.list({
73
+ q: `'${folderId}' in parents and trashed = false`,
74
+ fields: 'files(id, name, mimeType, modifiedTime, md5Checksum)',
75
+ pageSize: 1000,
76
+ });
77
+ return (response.data.files || []).map((file) => ({
78
+ id: file.id,
79
+ name: file.name,
80
+ mimeType: file.mimeType,
81
+ modifiedTime: file.modifiedTime,
82
+ md5Checksum: file.md5Checksum || undefined,
83
+ }));
84
+ }
85
+ async getFileMetadata(fileId) {
86
+ const response = await this.drive.files.get({
87
+ fileId,
88
+ fields: 'id, name, mimeType, modifiedTime, md5Checksum',
89
+ });
90
+ const file = response.data;
91
+ return {
92
+ id: file.id,
93
+ name: file.name,
94
+ mimeType: file.mimeType,
95
+ modifiedTime: file.modifiedTime,
96
+ md5Checksum: file.md5Checksum || undefined,
97
+ };
98
+ }
99
+ async deleteFile(fileId) {
100
+ await this.drive.files.delete({ fileId });
101
+ }
102
+ async findFolder(name, parentId) {
103
+ const query = parentId
104
+ ? `name = '${name}' and '${parentId}' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false`
105
+ : `name = '${name}' and mimeType = 'application/vnd.google-apps.folder' and trashed = false`;
106
+ const response = await this.drive.files.list({
107
+ q: query,
108
+ fields: 'files(id)',
109
+ pageSize: 1,
110
+ });
111
+ return response.data.files?.[0]?.id || null;
112
+ }
113
+ }
114
+ //# sourceMappingURL=google-drive.js.map