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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-drive.js","sourceRoot":"","sources":["../../src/sdk/google-drive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { SprintArtifact } from './sprint-artifact.js';
2
+ export { GoogleDriveClient } from './google-drive.js';
3
+ export type { SprintArtifactConfig, AuthConfig, BacklogItem, Sprint, Task, Manifest, ManifestFile, } from '../types/index.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EACV,oBAAoB,EACpB,UAAU,EACV,WAAW,EACX,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,YAAY,GACb,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { SprintArtifact } from './sprint-artifact.js';
2
+ export { GoogleDriveClient } from './google-drive.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { SprintArtifactConfig, AuthConfig, BacklogItem } from '../types/index.js';
2
+ export declare class SprintArtifact {
3
+ private projectRoot;
4
+ private config;
5
+ private auth;
6
+ private driveClient;
7
+ constructor(projectRoot: string);
8
+ init(folderId: string, auth?: AuthConfig): Promise<void>;
9
+ private ensureInitialized;
10
+ createBacklog(title: string, description: string, priority?: BacklogItem['priority']): Promise<BacklogItem>;
11
+ sync(): Promise<{
12
+ added: number;
13
+ updated: number;
14
+ deleted: number;
15
+ }>;
16
+ moveToSprint(backlogItemId: string, sprintId: string): Promise<void>;
17
+ selectTask(taskId: string): Promise<void>;
18
+ status(): Promise<{
19
+ initialized: boolean;
20
+ folderId: string;
21
+ selectedTask?: string;
22
+ lastSync?: string;
23
+ fileCount: number;
24
+ }>;
25
+ getConfig(): Promise<SprintArtifactConfig | null>;
26
+ private syncManifest;
27
+ private formatBacklogItem;
28
+ }
29
+ //# sourceMappingURL=sprint-artifact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sprint-artifact.d.ts","sourceRoot":"","sources":["../../src/sdk/sprint-artifact.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,UAAU,EACV,WAAW,EAIZ,MAAM,mBAAmB,CAAC;AAU3B,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,WAAW,CAAkC;gBAEzC,WAAW,EAAE,MAAM;IAIzB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;YAehD,iBAAiB;IAoBzB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,GAAE,WAAW,CAAC,UAAU,CAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAwBrH,IAAI,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAuCpE,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBpE,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzC,MAAM,IAAI,OAAO,CAAC;QACtB,WAAW,EAAE,OAAO,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IAaI,SAAS,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAIzC,YAAY;IAS1B,OAAO,CAAC,iBAAiB;CAe1B"}
@@ -0,0 +1,142 @@
1
+ import { loadConfig, saveConfig, loadAuth, saveAuth, getDefaultConfig, } from '../utils/config.js';
2
+ import { GoogleDriveClient } from './google-drive.js';
3
+ export class SprintArtifact {
4
+ projectRoot;
5
+ config = null;
6
+ auth = null;
7
+ driveClient = null;
8
+ constructor(projectRoot) {
9
+ this.projectRoot = projectRoot;
10
+ }
11
+ async init(folderId, auth) {
12
+ this.config = {
13
+ ...getDefaultConfig(),
14
+ googleDrive: { folderId },
15
+ };
16
+ await saveConfig(this.projectRoot, this.config);
17
+ if (auth) {
18
+ await saveAuth(this.projectRoot, auth);
19
+ this.auth = auth;
20
+ }
21
+ this.driveClient = null;
22
+ }
23
+ async ensureInitialized() {
24
+ if (!this.config) {
25
+ this.config = await loadConfig(this.projectRoot);
26
+ if (!this.config) {
27
+ throw new Error('Project not initialized. Run `sprint-artifact init` first.');
28
+ }
29
+ }
30
+ if (!this.auth) {
31
+ this.auth = await loadAuth(this.projectRoot);
32
+ if (!this.auth) {
33
+ throw new Error('Authentication not configured. Add auth.json to .sprint-artifact/');
34
+ }
35
+ }
36
+ if (!this.driveClient) {
37
+ this.driveClient = new GoogleDriveClient(this.auth);
38
+ }
39
+ }
40
+ async createBacklog(title, description, priority = 'medium') {
41
+ await this.ensureInitialized();
42
+ const item = {
43
+ id: crypto.randomUUID(),
44
+ title,
45
+ description,
46
+ priority,
47
+ status: 'todo',
48
+ createdAt: new Date().toISOString(),
49
+ updatedAt: new Date().toISOString(),
50
+ };
51
+ const content = this.formatBacklogItem(item);
52
+ const fileId = await this.driveClient.createFile(`${item.id}.md`, content, this.config.googleDrive.folderId);
53
+ await this.syncManifest();
54
+ return item;
55
+ }
56
+ async sync() {
57
+ await this.ensureInitialized();
58
+ const remoteFiles = await this.driveClient.listFiles(this.config.googleDrive.folderId);
59
+ const localManifest = this.config.manifest || { lastSync: '', files: [] };
60
+ const remoteMap = new Map(remoteFiles.map((f) => [f.id, f]));
61
+ const localMap = new Map(localManifest.files.map((f) => [f.id, f]));
62
+ let added = 0;
63
+ let updated = 0;
64
+ let deleted = 0;
65
+ for (const [id, remote] of remoteMap) {
66
+ const local = localMap.get(id);
67
+ if (!local) {
68
+ added++;
69
+ }
70
+ else if (local.modifiedTime !== remote.modifiedTime || local.md5Checksum !== remote.md5Checksum) {
71
+ updated++;
72
+ }
73
+ }
74
+ for (const [id] of localMap) {
75
+ if (!remoteMap.has(id)) {
76
+ deleted++;
77
+ }
78
+ }
79
+ const manifest = {
80
+ lastSync: new Date().toISOString(),
81
+ files: remoteFiles,
82
+ };
83
+ this.config.manifest = manifest;
84
+ await saveConfig(this.projectRoot, this.config);
85
+ return { added, updated, deleted };
86
+ }
87
+ async moveToSprint(backlogItemId, sprintId) {
88
+ await this.ensureInitialized();
89
+ const files = await this.driveClient.listFiles(this.config.googleDrive.folderId);
90
+ const file = files.find((f) => f.name === `${backlogItemId}.md`);
91
+ if (!file) {
92
+ throw new Error(`Backlog item ${backlogItemId} not found`);
93
+ }
94
+ const content = await this.driveClient.getFile(file.id);
95
+ const updatedContent = content.replace(/^sprint:.*$/m, `sprint: ${sprintId}`);
96
+ await this.driveClient.updateFile(file.id, updatedContent);
97
+ await this.syncManifest();
98
+ }
99
+ async selectTask(taskId) {
100
+ await this.ensureInitialized();
101
+ this.config.selectedTask = taskId;
102
+ await saveConfig(this.projectRoot, this.config);
103
+ }
104
+ async status() {
105
+ const config = await loadConfig(this.projectRoot);
106
+ const initialized = !!config;
107
+ return {
108
+ initialized,
109
+ folderId: config?.googleDrive.folderId || '',
110
+ selectedTask: config?.selectedTask,
111
+ lastSync: config?.manifest?.lastSync,
112
+ fileCount: config?.manifest?.files.length || 0,
113
+ };
114
+ }
115
+ async getConfig() {
116
+ return loadConfig(this.projectRoot);
117
+ }
118
+ async syncManifest() {
119
+ const remoteFiles = await this.driveClient.listFiles(this.config.googleDrive.folderId);
120
+ this.config.manifest = {
121
+ lastSync: new Date().toISOString(),
122
+ files: remoteFiles,
123
+ };
124
+ await saveConfig(this.projectRoot, this.config);
125
+ }
126
+ formatBacklogItem(item) {
127
+ return `---
128
+ id: ${item.id}
129
+ title: ${item.title}
130
+ priority: ${item.priority}
131
+ status: ${item.status}
132
+ created: ${item.createdAt}
133
+ updated: ${item.updatedAt}
134
+ ---
135
+
136
+ # ${item.title}
137
+
138
+ ${item.description}
139
+ `;
140
+ }
141
+ }
142
+ //# sourceMappingURL=sprint-artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sprint-artifact.js","sourceRoot":"","sources":["../../src/sdk/sprint-artifact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ export interface SprintArtifactConfig {
2
+ version: number;
3
+ googleDrive: {
4
+ folderId: string;
5
+ brdId?: string;
6
+ prdId?: string;
7
+ planningId?: string;
8
+ };
9
+ selectedTask?: string;
10
+ manifest?: Manifest;
11
+ }
12
+ export interface Manifest {
13
+ lastSync: string;
14
+ files: ManifestFile[];
15
+ }
16
+ export interface ManifestFile {
17
+ id: string;
18
+ name: string;
19
+ mimeType: string;
20
+ modifiedTime: string;
21
+ md5Checksum?: string;
22
+ }
23
+ export interface AuthConfig {
24
+ type: 'service_account' | 'oauth2';
25
+ credentials: ServiceAccountCredentials | OAuth2Credentials;
26
+ }
27
+ export interface ServiceAccountCredentials {
28
+ type: 'service_account';
29
+ project_id: string;
30
+ private_key_id: string;
31
+ private_key: string;
32
+ client_email: string;
33
+ client_id: string;
34
+ auth_uri: string;
35
+ token_uri: string;
36
+ auth_provider_x509_cert_url: string;
37
+ client_x509_cert_url: string;
38
+ }
39
+ export interface OAuth2Credentials {
40
+ client_id: string;
41
+ client_secret: string;
42
+ redirect_uris: string[];
43
+ refresh_token?: string;
44
+ access_token?: string;
45
+ token_expiry?: string;
46
+ }
47
+ export interface BacklogItem {
48
+ id: string;
49
+ title: string;
50
+ description: string;
51
+ priority: 'high' | 'medium' | 'low';
52
+ status: 'todo' | 'in-progress' | 'done';
53
+ sprint?: string;
54
+ assignee?: string;
55
+ createdAt: string;
56
+ updatedAt: string;
57
+ }
58
+ export interface Sprint {
59
+ id: string;
60
+ name: string;
61
+ startDate: string;
62
+ endDate: string;
63
+ goals: string[];
64
+ backlogItems: string[];
65
+ }
66
+ export interface Task {
67
+ id: string;
68
+ title: string;
69
+ description: string;
70
+ status: 'todo' | 'in-progress' | 'done';
71
+ backlogItemId: string;
72
+ sprintId?: string;
73
+ assignee?: string;
74
+ createdAt: string;
75
+ updatedAt: string;
76
+ }
77
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,iBAAiB,GAAG,QAAQ,CAAC;IACnC,WAAW,EAAE,yBAAyB,GAAG,iBAAiB,CAAC;CAC5D;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,iBAAiB,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B,EAAE,MAAM,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACpC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,MAAM,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,MAAM,CAAC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import type { SprintArtifactConfig, AuthConfig } from '../types/index.js';
2
+ export declare function getConfigPath(projectRoot: string): Promise<string>;
3
+ export declare function ensureConfigDir(projectRoot: string): Promise<void>;
4
+ export declare function loadConfig(projectRoot: string): Promise<SprintArtifactConfig | null>;
5
+ export declare function saveConfig(projectRoot: string, config: SprintArtifactConfig): Promise<void>;
6
+ export declare function loadAuth(projectRoot: string): Promise<AuthConfig | null>;
7
+ export declare function saveAuth(projectRoot: string, auth: AuthConfig): Promise<void>;
8
+ export declare function getDefaultConfig(): SprintArtifactConfig;
9
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAM1E,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAExE;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKxE;AAED,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAO1F;AAED,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjG;AAED,wBAAsB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAO9E;AAED,wBAAsB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAInF;AAED,wBAAgB,gBAAgB,IAAI,oBAAoB,CAOvD"}
@@ -0,0 +1,50 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { existsSync } from 'node:fs';
4
+ const CONFIG_DIR = '.sprint-artifact';
5
+ const CONFIG_FILE = 'config.json';
6
+ const AUTH_FILE = 'auth.json';
7
+ export async function getConfigPath(projectRoot) {
8
+ return join(projectRoot, CONFIG_DIR);
9
+ }
10
+ export async function ensureConfigDir(projectRoot) {
11
+ const configPath = await getConfigPath(projectRoot);
12
+ if (!existsSync(configPath)) {
13
+ await mkdir(configPath, { recursive: true });
14
+ }
15
+ }
16
+ export async function loadConfig(projectRoot) {
17
+ const configPath = join(projectRoot, CONFIG_DIR, CONFIG_FILE);
18
+ if (!existsSync(configPath)) {
19
+ return null;
20
+ }
21
+ const content = await readFile(configPath, 'utf-8');
22
+ return JSON.parse(content);
23
+ }
24
+ export async function saveConfig(projectRoot, config) {
25
+ await ensureConfigDir(projectRoot);
26
+ const configPath = join(projectRoot, CONFIG_DIR, CONFIG_FILE);
27
+ await writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
28
+ }
29
+ export async function loadAuth(projectRoot) {
30
+ const authPath = join(projectRoot, CONFIG_DIR, AUTH_FILE);
31
+ if (!existsSync(authPath)) {
32
+ return null;
33
+ }
34
+ const content = await readFile(authPath, 'utf-8');
35
+ return JSON.parse(content);
36
+ }
37
+ export async function saveAuth(projectRoot, auth) {
38
+ await ensureConfigDir(projectRoot);
39
+ const authPath = join(projectRoot, CONFIG_DIR, AUTH_FILE);
40
+ await writeFile(authPath, JSON.stringify(auth, null, 2), 'utf-8');
41
+ }
42
+ export function getDefaultConfig() {
43
+ return {
44
+ version: 1,
45
+ googleDrive: {
46
+ folderId: '',
47
+ },
48
+ };
49
+ }
50
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGrC,MAAM,UAAU,GAAG,kBAAkB,CAAC;AACtC,MAAM,WAAW,GAAG,aAAa,CAAC;AAClC,MAAM,SAAS,GAAG,WAAW,CAAC;AAE9B,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB;IACrD,OAAO,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAmB;IACvD,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,WAAmB;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAC9D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,WAAmB,EAAE,MAA4B;IAChF,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAC9D,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,WAAmB;IAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,WAAmB,EAAE,IAAgB;IAClE,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC1D,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,OAAO,EAAE,CAAC;QACV,WAAW,EAAE;YACX,QAAQ,EAAE,EAAE;SACb;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './config.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './config.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { OAuth2Credentials } from '../types/index.js';
2
+ export declare function findCredentials(): Promise<{
3
+ clientId: string;
4
+ clientSecret: string;
5
+ } | null>;
6
+ export declare function saveCredentialsGlobal(credentialsPath: string): Promise<void>;
7
+ export declare function login(options?: {
8
+ clientId?: string;
9
+ clientSecret?: string;
10
+ credentialsPath?: string;
11
+ }): Promise<OAuth2Credentials>;
12
+ //# sourceMappingURL=oauth2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth2.d.ts","sourceRoot":"","sources":["../../src/utils/oauth2.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAgB3D,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA0BlG;AAED,wBAAsB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlF;AAED,wBAAsB,KAAK,CAAC,OAAO,CAAC,EAAE;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+G7B"}
@@ -0,0 +1,148 @@
1
+ import { google } from 'googleapis';
2
+ import { createServer } from 'node:http';
3
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
4
+ import { join } from 'node:path';
5
+ import { homedir } from 'node:os';
6
+ import { existsSync } from 'node:fs';
7
+ import open from 'open';
8
+ const SCOPES = ['https://www.googleapis.com/auth/drive'];
9
+ const REDIRECT_PORT = 3000;
10
+ const REDIRECT_URI = `http://localhost:${REDIRECT_PORT}/callback`;
11
+ const GLOBAL_CONFIG_DIR = join(homedir(), '.sprint-artifact');
12
+ const GLOBAL_CREDENTIALS_FILE = join(GLOBAL_CONFIG_DIR, 'credentials.json');
13
+ const COMMON_CREDENTIALS_PATHS = [
14
+ 'credentials.json',
15
+ 'client_secret.json',
16
+ 'oauth2.json',
17
+ '.credentials.json',
18
+ ];
19
+ export async function findCredentials() {
20
+ // Check global config first
21
+ if (existsSync(GLOBAL_CREDENTIALS_FILE)) {
22
+ try {
23
+ const content = JSON.parse(await readFile(GLOBAL_CREDENTIALS_FILE, 'utf-8'));
24
+ const creds = content.installed || content.web;
25
+ if (creds?.client_id && creds?.client_secret) {
26
+ return { clientId: creds.client_id, clientSecret: creds.client_secret };
27
+ }
28
+ }
29
+ catch { }
30
+ }
31
+ // Check common paths in current directory
32
+ for (const path of COMMON_CREDENTIALS_PATHS) {
33
+ if (existsSync(path)) {
34
+ try {
35
+ const content = JSON.parse(await readFile(path, 'utf-8'));
36
+ const creds = content.installed || content.web;
37
+ if (creds?.client_id && creds?.client_secret) {
38
+ return { clientId: creds.client_id, clientSecret: creds.client_secret };
39
+ }
40
+ }
41
+ catch { }
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+ export async function saveCredentialsGlobal(credentialsPath) {
47
+ if (!existsSync(GLOBAL_CONFIG_DIR)) {
48
+ await mkdir(GLOBAL_CONFIG_DIR, { recursive: true });
49
+ }
50
+ const content = await readFile(credentialsPath, 'utf-8');
51
+ await writeFile(GLOBAL_CREDENTIALS_FILE, content, 'utf-8');
52
+ }
53
+ export async function login(options) {
54
+ let clientId = options?.clientId;
55
+ let clientSecret = options?.clientSecret;
56
+ // If credentials path provided, read and save globally
57
+ if (options?.credentialsPath) {
58
+ const content = JSON.parse(await readFile(options.credentialsPath, 'utf-8'));
59
+ const creds = content.installed || content.web;
60
+ clientId = creds.client_id;
61
+ clientSecret = creds.client_secret;
62
+ await saveCredentialsGlobal(options.credentialsPath);
63
+ console.log('✓ Credentials saved globally');
64
+ }
65
+ // Auto-detect if not provided
66
+ if (!clientId || !clientSecret) {
67
+ const detected = await findCredentials();
68
+ if (detected) {
69
+ clientId = detected.clientId;
70
+ clientSecret = detected.clientSecret;
71
+ console.log('✓ Credentials auto-detected');
72
+ }
73
+ else {
74
+ throw new Error('No credentials found. Provide --credentials path or save credentials to ~/.sprint-artifact/credentials.json');
75
+ }
76
+ }
77
+ const oauth2Client = new google.auth.OAuth2(clientId, clientSecret, REDIRECT_URI);
78
+ const authUrl = oauth2Client.generateAuthUrl({
79
+ access_type: 'offline',
80
+ scope: SCOPES,
81
+ prompt: 'consent',
82
+ });
83
+ return new Promise((resolve, reject) => {
84
+ const server = createServer(async (req, res) => {
85
+ const url = new URL(req.url, `http://localhost:${REDIRECT_PORT}`);
86
+ if (url.pathname === '/callback') {
87
+ const code = url.searchParams.get('code');
88
+ const error = url.searchParams.get('error');
89
+ if (error) {
90
+ res.writeHead(400, { 'Content-Type': 'text/html' });
91
+ res.end(`<h1>Error</h1><p>${error}</p>`);
92
+ server.close();
93
+ reject(new Error(`OAuth error: ${error}`));
94
+ return;
95
+ }
96
+ if (!code) {
97
+ res.writeHead(400, { 'Content-Type': 'text/html' });
98
+ res.end('<h1>Error</h1><p>No code received</p>');
99
+ server.close();
100
+ reject(new Error('No authorization code received'));
101
+ return;
102
+ }
103
+ try {
104
+ const { tokens } = await oauth2Client.getToken(code);
105
+ const credentials = {
106
+ client_id: clientId,
107
+ client_secret: clientSecret,
108
+ redirect_uris: [REDIRECT_URI],
109
+ refresh_token: tokens.refresh_token || undefined,
110
+ access_token: tokens.access_token || undefined,
111
+ token_expiry: tokens.expiry_date ? new Date(tokens.expiry_date).toISOString() : undefined,
112
+ };
113
+ res.writeHead(200, { 'Content-Type': 'text/html' });
114
+ res.end(`
115
+ <html>
116
+ <body style="font-family: sans-serif; text-align: center; padding: 50px;">
117
+ <h1 style="color: #4CAF50;">✓ Login Successful</h1>
118
+ <p>You can close this window and return to the terminal.</p>
119
+ </body>
120
+ </html>
121
+ `);
122
+ server.close();
123
+ resolve(credentials);
124
+ }
125
+ catch (err) {
126
+ res.writeHead(500, { 'Content-Type': 'text/html' });
127
+ res.end('<h1>Error</h1><p>Failed to get tokens</p>');
128
+ server.close();
129
+ reject(err);
130
+ }
131
+ }
132
+ else {
133
+ res.writeHead(404);
134
+ res.end();
135
+ }
136
+ });
137
+ server.listen(REDIRECT_PORT, () => {
138
+ console.log('Opening browser for login...');
139
+ open(authUrl).catch(() => {
140
+ console.log(`\nOpen this URL manually:\n${authUrl}\n`);
141
+ });
142
+ });
143
+ server.on('error', (err) => {
144
+ reject(err);
145
+ });
146
+ });
147
+ }
148
+ //# sourceMappingURL=oauth2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth2.js","sourceRoot":"","sources":["../../src/utils/oauth2.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "sprint-artifact",
3
+ "version": "0.2.0",
4
+ "description": "Sprint Artifact management tool with Google Drive integration",
5
+ "type": "module",
6
+ "main": "./dist/sdk/index.js",
7
+ "types": "./dist/sdk/index.d.ts",
8
+ "bin": {
9
+ "sprint-artifact": "dist/cli/index.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/sdk/index.js",
14
+ "types": "./dist/sdk/index.d.ts"
15
+ },
16
+ "./cli": {
17
+ "import": "./dist/cli/index.js"
18
+ },
19
+ "./mcp": {
20
+ "import": "./dist/mcp/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "scripts": {
29
+ "build": "tsc",
30
+ "dev": "tsc --watch",
31
+ "lint": "eslint src --ext .ts",
32
+ "format": "prettier --write \"src/**/*.ts\"",
33
+ "test": "vitest",
34
+ "cli": "node dist/cli/index.js",
35
+ "mcp": "node dist/mcp/index.js",
36
+ "prepublishOnly": "npm run build"
37
+ },
38
+ "keywords": [
39
+ "sprint",
40
+ "artifact",
41
+ "google-drive",
42
+ "mcp",
43
+ "cli",
44
+ "project-management",
45
+ "backlog",
46
+ "agile"
47
+ ],
48
+ "author": "dstwn",
49
+ "license": "MIT",
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/dstwn/sprint-artifact.git"
53
+ },
54
+ "bugs": {
55
+ "url": "https://github.com/dstwn/sprint-artifact/issues"
56
+ },
57
+ "homepage": "https://github.com/dstwn/sprint-artifact#readme",
58
+ "dependencies": {
59
+ "@modelcontextprotocol/sdk": "^1.0.0",
60
+ "commander": "^12.0.0",
61
+ "googleapis": "^130.0.0",
62
+ "open": "^11.0.0",
63
+ "zod": "^3.22.0"
64
+ },
65
+ "devDependencies": {
66
+ "@types/node": "^20.0.0",
67
+ "eslint": "^8.50.0",
68
+ "prettier": "^3.0.0",
69
+ "typescript": "^5.3.0",
70
+ "vitest": "^1.0.0"
71
+ }
72
+ }