@nahisaho/musubix-codegraph 2.3.2 → 2.3.4

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 (41) hide show
  1. package/dist/cli.d.ts +13 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +318 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +8 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/pr/errors.d.ts +63 -0
  10. package/dist/pr/errors.d.ts.map +1 -0
  11. package/dist/pr/errors.js +116 -0
  12. package/dist/pr/errors.js.map +1 -0
  13. package/dist/pr/git-operations.d.ts +186 -0
  14. package/dist/pr/git-operations.d.ts.map +1 -0
  15. package/dist/pr/git-operations.js +441 -0
  16. package/dist/pr/git-operations.js.map +1 -0
  17. package/dist/pr/github-adapter.d.ts +163 -0
  18. package/dist/pr/github-adapter.d.ts.map +1 -0
  19. package/dist/pr/github-adapter.js +467 -0
  20. package/dist/pr/github-adapter.js.map +1 -0
  21. package/dist/pr/index.d.ts +20 -0
  22. package/dist/pr/index.d.ts.map +1 -0
  23. package/dist/pr/index.js +26 -0
  24. package/dist/pr/index.js.map +1 -0
  25. package/dist/pr/pr-creator.d.ts +173 -0
  26. package/dist/pr/pr-creator.d.ts.map +1 -0
  27. package/dist/pr/pr-creator.js +468 -0
  28. package/dist/pr/pr-creator.js.map +1 -0
  29. package/dist/pr/pr-template.d.ts +105 -0
  30. package/dist/pr/pr-template.d.ts.map +1 -0
  31. package/dist/pr/pr-template.js +273 -0
  32. package/dist/pr/pr-template.js.map +1 -0
  33. package/dist/pr/refactoring-applier.d.ts +143 -0
  34. package/dist/pr/refactoring-applier.d.ts.map +1 -0
  35. package/dist/pr/refactoring-applier.js +412 -0
  36. package/dist/pr/refactoring-applier.js.map +1 -0
  37. package/dist/pr/types.d.ts +362 -0
  38. package/dist/pr/types.d.ts.map +1 -0
  39. package/dist/pr/types.js +63 -0
  40. package/dist/pr/types.js.map +1 -0
  41. package/package.json +11 -2
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @nahisaho/musubix-codegraph/pr - PR Creation Module
3
+ *
4
+ * Automatic PR generation from refactoring suggestions
5
+ *
6
+ * @packageDocumentation
7
+ * @module @nahisaho/musubix-codegraph/pr
8
+ *
9
+ * @see REQ-CG-PR-001 - REQ-CG-PR-009
10
+ * @see DES-CG-PR-001 - DES-CG-PR-006
11
+ */
12
+ // Main PR Creator
13
+ export { PRCreator, createPRCreator, createRefactoringPR, } from './pr-creator.js';
14
+ // Error Handling (v2.3.4 NEW)
15
+ export { PRCreatorError, PRErrorMessages, } from './errors.js';
16
+ // Git Operations
17
+ export { GitOperations, createGitOperations, } from './git-operations.js';
18
+ // GitHub Adapter
19
+ export { GitHubAdapter, createGitHubAdapter, } from './github-adapter.js';
20
+ // Refactoring Applier
21
+ export { RefactoringApplier, createRefactoringApplier, } from './refactoring-applier.js';
22
+ // PR Template Generator
23
+ export { PRTemplateGenerator, createPRTemplateGenerator, generateSimplePRBody, generatePRTitle, } from './pr-template.js';
24
+ // Utility Functions
25
+ export { REFACTORING_TO_COMMIT_TYPE, generateBranchName, generateCommitMessage, } from './types.js';
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pr/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,kBAAkB;AAClB,OAAO,EACL,SAAS,EACT,eAAe,EACf,mBAAmB,GAGpB,MAAM,iBAAiB,CAAC;AAEzB,8BAA8B;AAC9B,OAAO,EACL,cAAc,EACd,eAAe,GAEhB,MAAM,aAAa,CAAC;AAErB,iBAAiB;AACjB,OAAO,EACL,aAAa,EACb,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,iBAAiB;AACjB,OAAO,EACL,aAAa,EACb,mBAAmB,GAIpB,MAAM,qBAAqB,CAAC;AAE7B,sBAAsB;AACtB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GAIzB,MAAM,0BAA0B,CAAC;AAElC,wBAAwB;AACxB,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,GAEhB,MAAM,kBAAkB,CAAC;AAsC1B,oBAAoB;AACpB,OAAO,EACL,0BAA0B,EAC1B,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * @nahisaho/musubix-codegraph - PR Creator
3
+ *
4
+ * Main orchestrator for creating PRs from refactoring suggestions
5
+ *
6
+ * @packageDocumentation
7
+ * @module @nahisaho/musubix-codegraph/pr
8
+ *
9
+ * @see REQ-CG-PR-001 - GitHub Authentication
10
+ * @see REQ-CG-PR-002 - Auto Apply Refactoring
11
+ * @see REQ-CG-PR-003 - Git Branch Creation
12
+ * @see REQ-CG-PR-004 - Auto Commit
13
+ * @see REQ-CG-PR-005 - GitHub PR Creation
14
+ * @see DES-CG-PR-001 - Component Design
15
+ * @see DES-CG-PR-005 - Sequence Diagram
16
+ */
17
+ import { EventEmitter } from 'node:events';
18
+ import type { RefactoringSuggestion, PRCreateOptions, PRCreateResult, PRPreview, PRCreatorEvents } from './types.js';
19
+ /**
20
+ * PRCreator state
21
+ * @see DES-CG-v234-003
22
+ */
23
+ export type PRCreatorState = 'uninitialized' | 'offline' | 'full';
24
+ /**
25
+ * PR Creator configuration
26
+ */
27
+ export interface PRCreatorConfig {
28
+ /** Repository root path */
29
+ repoPath: string;
30
+ /** GitHub token (optional, will try env or gh CLI) */
31
+ githubToken?: string;
32
+ /** Remote name (default: origin) */
33
+ remote?: string;
34
+ /** Create backups before modifications */
35
+ createBackups?: boolean;
36
+ }
37
+ /**
38
+ * PR Creator
39
+ *
40
+ * Orchestrates the entire PR creation workflow:
41
+ * 1. Authenticate with GitHub
42
+ * 2. Create a new branch
43
+ * 3. Apply refactoring changes
44
+ * 4. Commit changes
45
+ * 5. Push to remote
46
+ * 6. Create PR on GitHub
47
+ *
48
+ * @see DES-CG-PR-001
49
+ * @see DES-CG-PR-005
50
+ * @example
51
+ * ```typescript
52
+ * const creator = new PRCreator({ repoPath: '/path/to/repo' });
53
+ * await creator.initialize();
54
+ *
55
+ * const result = await creator.create({
56
+ * suggestion: refactoringSuggestion,
57
+ * baseBranch: 'main',
58
+ * labels: ['refactoring', 'auto-generated'],
59
+ * });
60
+ *
61
+ * console.log(`PR created: ${result.pr?.url}`);
62
+ * ```
63
+ */
64
+ export declare class PRCreator extends EventEmitter {
65
+ private readonly config;
66
+ private git;
67
+ private github;
68
+ private applier;
69
+ private templateGenerator;
70
+ private initialized;
71
+ private originalBranch;
72
+ private state;
73
+ /**
74
+ * Create a new PRCreator
75
+ * @param config - Configuration options
76
+ */
77
+ constructor(config: PRCreatorConfig);
78
+ /**
79
+ * Initialize for offline operations (preview only)
80
+ * Does not require GitHub authentication
81
+ *
82
+ * @see REQ-CG-v234-001
83
+ * @see DES-CG-v234-001
84
+ */
85
+ initializeOffline(): Promise<{
86
+ success: boolean;
87
+ error?: string;
88
+ }>;
89
+ /**
90
+ * Initialize the PR creator with full GitHub authentication
91
+ * Sets up Git operations and authenticates with GitHub
92
+ */
93
+ initialize(): Promise<{
94
+ success: boolean;
95
+ error?: string;
96
+ }>;
97
+ /**
98
+ * Check if initialized
99
+ */
100
+ isInitialized(): boolean;
101
+ /**
102
+ * Get current state
103
+ * @see DES-CG-v234-003
104
+ */
105
+ getState(): PRCreatorState;
106
+ /**
107
+ * Generate PR preview without creating
108
+ * Works in both offline and full modes
109
+ *
110
+ * @see REQ-CG-v234-001
111
+ * @see DES-CG-v234-001
112
+ */
113
+ previewSuggestion(suggestion: RefactoringSuggestion): PRPreview;
114
+ /**
115
+ * Create a PR from a refactoring suggestion
116
+ * Requires full initialization (GitHub authentication)
117
+ *
118
+ * @see REQ-CG-PR-002, REQ-CG-PR-003, REQ-CG-PR-004, REQ-CG-PR-005
119
+ */
120
+ create(options: PRCreateOptions): Promise<PRCreateResult>;
121
+ /**
122
+ * Preview PR creation without actually creating
123
+ * @see REQ-CG-PR-007
124
+ */
125
+ preview(options: PRCreateOptions): Promise<PRPreview>;
126
+ /**
127
+ * Validate a suggestion can be applied
128
+ */
129
+ validate(suggestion: RefactoringSuggestion): {
130
+ valid: boolean;
131
+ reason?: string;
132
+ };
133
+ /**
134
+ * Dry run implementation
135
+ */
136
+ private dryRun;
137
+ /**
138
+ * Ensure initialized before operations (legacy)
139
+ * @deprecated Use ensureState() instead
140
+ */
141
+ private ensureInitialized;
142
+ /**
143
+ * Ensure PRCreator is in one of the allowed states
144
+ * @see DES-CG-v234-003
145
+ */
146
+ private ensureState;
147
+ /**
148
+ * Typed event emitter methods
149
+ */
150
+ emit<K extends keyof PRCreatorEvents>(event: K, data: PRCreatorEvents[K]): boolean;
151
+ on<K extends keyof PRCreatorEvents>(event: K, listener: (data: PRCreatorEvents[K]) => void): this;
152
+ once<K extends keyof PRCreatorEvents>(event: K, listener: (data: PRCreatorEvents[K]) => void): this;
153
+ }
154
+ /**
155
+ * Create a PRCreator instance
156
+ */
157
+ export declare function createPRCreator(repoPath: string, options?: Partial<PRCreatorConfig>): PRCreator;
158
+ /**
159
+ * Quick PR creation helper
160
+ *
161
+ * One-shot function to create a PR from a suggestion.
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * const result = await createRefactoringPR(
166
+ * '/path/to/repo',
167
+ * suggestion,
168
+ * { labels: ['refactoring'] }
169
+ * );
170
+ * ```
171
+ */
172
+ export declare function createRefactoringPR(repoPath: string, suggestion: RefactoringSuggestion, options?: Partial<PRCreateOptions>): Promise<PRCreateResult>;
173
+ //# sourceMappingURL=pr-creator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr-creator.d.ts","sourceRoot":"","sources":["../../src/pr/pr-creator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,468 @@
1
+ /**
2
+ * @nahisaho/musubix-codegraph - PR Creator
3
+ *
4
+ * Main orchestrator for creating PRs from refactoring suggestions
5
+ *
6
+ * @packageDocumentation
7
+ * @module @nahisaho/musubix-codegraph/pr
8
+ *
9
+ * @see REQ-CG-PR-001 - GitHub Authentication
10
+ * @see REQ-CG-PR-002 - Auto Apply Refactoring
11
+ * @see REQ-CG-PR-003 - Git Branch Creation
12
+ * @see REQ-CG-PR-004 - Auto Commit
13
+ * @see REQ-CG-PR-005 - GitHub PR Creation
14
+ * @see DES-CG-PR-001 - Component Design
15
+ * @see DES-CG-PR-005 - Sequence Diagram
16
+ */
17
+ import { EventEmitter } from 'node:events';
18
+ import { GitOperations } from './git-operations.js';
19
+ import { GitHubAdapter } from './github-adapter.js';
20
+ import { RefactoringApplier } from './refactoring-applier.js';
21
+ import { PRTemplateGenerator } from './pr-template.js';
22
+ import { PRCreatorError, PRErrorMessages } from './errors.js';
23
+ import { generateBranchName, generateCommitMessage, } from './types.js';
24
+ /**
25
+ * PR Creator
26
+ *
27
+ * Orchestrates the entire PR creation workflow:
28
+ * 1. Authenticate with GitHub
29
+ * 2. Create a new branch
30
+ * 3. Apply refactoring changes
31
+ * 4. Commit changes
32
+ * 5. Push to remote
33
+ * 6. Create PR on GitHub
34
+ *
35
+ * @see DES-CG-PR-001
36
+ * @see DES-CG-PR-005
37
+ * @example
38
+ * ```typescript
39
+ * const creator = new PRCreator({ repoPath: '/path/to/repo' });
40
+ * await creator.initialize();
41
+ *
42
+ * const result = await creator.create({
43
+ * suggestion: refactoringSuggestion,
44
+ * baseBranch: 'main',
45
+ * labels: ['refactoring', 'auto-generated'],
46
+ * });
47
+ *
48
+ * console.log(`PR created: ${result.pr?.url}`);
49
+ * ```
50
+ */
51
+ export class PRCreator extends EventEmitter {
52
+ config;
53
+ git = null;
54
+ github = null;
55
+ applier = null;
56
+ templateGenerator;
57
+ initialized = false;
58
+ originalBranch = null;
59
+ state = 'uninitialized';
60
+ /**
61
+ * Create a new PRCreator
62
+ * @param config - Configuration options
63
+ */
64
+ constructor(config) {
65
+ super();
66
+ this.config = {
67
+ remote: 'origin',
68
+ createBackups: true,
69
+ ...config,
70
+ };
71
+ this.templateGenerator = new PRTemplateGenerator();
72
+ }
73
+ // ============================================================================
74
+ // Initialization
75
+ // ============================================================================
76
+ /**
77
+ * Initialize for offline operations (preview only)
78
+ * Does not require GitHub authentication
79
+ *
80
+ * @see REQ-CG-v234-001
81
+ * @see DES-CG-v234-001
82
+ */
83
+ async initializeOffline() {
84
+ try {
85
+ // Initialize Git operations (local only)
86
+ this.git = new GitOperations({
87
+ repoPath: this.config.repoPath,
88
+ remote: this.config.remote,
89
+ });
90
+ // Initialize refactoring applier
91
+ this.applier = new RefactoringApplier({
92
+ repoPath: this.config.repoPath,
93
+ createBackups: this.config.createBackups,
94
+ });
95
+ // Store current branch for potential rollback
96
+ this.originalBranch = this.git.getCurrentBranch();
97
+ this.state = 'offline';
98
+ this.initialized = true;
99
+ return { success: true };
100
+ }
101
+ catch (error) {
102
+ return {
103
+ success: false,
104
+ error: error instanceof Error ? error.message : String(error),
105
+ };
106
+ }
107
+ }
108
+ /**
109
+ * Initialize the PR creator with full GitHub authentication
110
+ * Sets up Git operations and authenticates with GitHub
111
+ */
112
+ async initialize() {
113
+ try {
114
+ // First do offline initialization if not already done
115
+ if (this.state === 'uninitialized') {
116
+ const offlineResult = await this.initializeOffline();
117
+ if (!offlineResult.success) {
118
+ return offlineResult;
119
+ }
120
+ }
121
+ // Parse GitHub owner/repo from remote
122
+ const remoteInfo = this.git.parseRemoteUrl();
123
+ if (!remoteInfo) {
124
+ const err = PRErrorMessages.REMOTE_PARSE_FAILED;
125
+ return {
126
+ success: false,
127
+ error: `${err.message}. ${err.suggestion}`,
128
+ };
129
+ }
130
+ // Initialize GitHub adapter
131
+ this.github = new GitHubAdapter({
132
+ owner: remoteInfo.owner,
133
+ repo: remoteInfo.repo,
134
+ token: this.config.githubToken,
135
+ });
136
+ // Authenticate with GitHub
137
+ const authResult = await this.github.authenticate();
138
+ if (!authResult.authenticated) {
139
+ const err = PRErrorMessages.AUTH_FAILED;
140
+ return {
141
+ success: false,
142
+ error: `${err.message}: ${authResult.error}. ${err.suggestion}`,
143
+ };
144
+ }
145
+ this.state = 'full';
146
+ this.initialized = true;
147
+ return { success: true };
148
+ }
149
+ catch (error) {
150
+ return {
151
+ success: false,
152
+ error: error instanceof Error ? error.message : String(error),
153
+ };
154
+ }
155
+ }
156
+ /**
157
+ * Check if initialized
158
+ */
159
+ isInitialized() {
160
+ return this.initialized;
161
+ }
162
+ /**
163
+ * Get current state
164
+ * @see DES-CG-v234-003
165
+ */
166
+ getState() {
167
+ return this.state;
168
+ }
169
+ // ============================================================================
170
+ // Main Operations
171
+ // ============================================================================
172
+ /**
173
+ * Generate PR preview without creating
174
+ * Works in both offline and full modes
175
+ *
176
+ * @see REQ-CG-v234-001
177
+ * @see DES-CG-v234-001
178
+ */
179
+ previewSuggestion(suggestion) {
180
+ this.ensureState('offline', 'full');
181
+ const branchName = generateBranchName(suggestion);
182
+ const commitMessage = generateCommitMessage(suggestion);
183
+ const title = this.templateGenerator.generateTitle(suggestion);
184
+ const diffs = this.applier.preview(suggestion);
185
+ const body = this.templateGenerator.generate(suggestion, diffs);
186
+ const baseBranch = this.git.getDefaultBranch();
187
+ return {
188
+ branchName,
189
+ baseBranch,
190
+ title,
191
+ body,
192
+ diffs,
193
+ commitMessage,
194
+ };
195
+ }
196
+ /**
197
+ * Create a PR from a refactoring suggestion
198
+ * Requires full initialization (GitHub authentication)
199
+ *
200
+ * @see REQ-CG-PR-002, REQ-CG-PR-003, REQ-CG-PR-004, REQ-CG-PR-005
201
+ */
202
+ async create(options) {
203
+ this.ensureState('full');
204
+ const { suggestion, dryRun } = options;
205
+ const warnings = [];
206
+ try {
207
+ this.emit('pr:start', { suggestion });
208
+ // Generate branch name
209
+ const branchName = options.branchName ?? generateBranchName(suggestion);
210
+ // Check for uncommitted changes
211
+ if (this.git.hasUncommittedChanges()) {
212
+ warnings.push('Repository has uncommitted changes. They will be stashed.');
213
+ this.git.stash('musubix-pr-creator-auto-stash');
214
+ }
215
+ // Dry run mode - just preview
216
+ if (dryRun) {
217
+ return this.dryRun(options, branchName);
218
+ }
219
+ // Determine base branch
220
+ const baseBranch = options.baseBranch ?? this.git.getDefaultBranch();
221
+ // Create and checkout new branch
222
+ this.emit('pr:branch', { name: branchName });
223
+ this.git.createBranch(branchName, baseBranch);
224
+ // Apply refactoring changes
225
+ const diffs = this.applier.preview(suggestion);
226
+ for (const diff of diffs) {
227
+ this.emit('pr:applying', { file: diff.filePath, changes: 1 });
228
+ }
229
+ const applyResult = this.applier.apply(suggestion);
230
+ if (!applyResult.success) {
231
+ // Rollback branch
232
+ this.git.checkout(this.originalBranch);
233
+ this.git.deleteBranch(branchName, true);
234
+ return {
235
+ success: false,
236
+ branchName,
237
+ filesChanged: [],
238
+ linesAdded: 0,
239
+ linesDeleted: 0,
240
+ error: `Failed to apply changes: ${applyResult.error}`,
241
+ warnings,
242
+ };
243
+ }
244
+ // Stage all changes
245
+ this.git.stageAll();
246
+ // Generate commit message
247
+ const commitMessage = generateCommitMessage(suggestion);
248
+ // Commit
249
+ const commitInfo = this.git.commit(commitMessage);
250
+ this.emit('pr:commit', { hash: commitInfo.hash, message: commitMessage });
251
+ // Push to remote
252
+ this.emit('pr:push', { branch: branchName, remote: this.config.remote });
253
+ this.git.push({ setUpstream: true });
254
+ // Generate PR body
255
+ const prTitle = options.title ?? this.templateGenerator.generateTitle(suggestion);
256
+ const prBody = options.body ?? this.templateGenerator.generate(suggestion, diffs);
257
+ // Create PR
258
+ const pr = await this.github.createPullRequest({
259
+ title: prTitle,
260
+ body: prBody,
261
+ head: branchName,
262
+ base: baseBranch,
263
+ draft: options.draft,
264
+ });
265
+ this.emit('pr:created', { pr });
266
+ // Add labels, assignees, reviewers
267
+ if (options.labels && options.labels.length > 0) {
268
+ await this.github.addLabels(pr.number, options.labels);
269
+ }
270
+ if (options.assignees && options.assignees.length > 0) {
271
+ await this.github.addAssignees(pr.number, options.assignees);
272
+ }
273
+ if (options.reviewers && options.reviewers.length > 0) {
274
+ await this.github.addReviewers(pr.number, options.reviewers);
275
+ }
276
+ // Calculate stats
277
+ const stats = this.git.getDiffStats(baseBranch);
278
+ const result = {
279
+ success: true,
280
+ pr,
281
+ branchName,
282
+ commitHash: commitInfo.hash,
283
+ filesChanged: applyResult.filesModified,
284
+ linesAdded: stats.additions,
285
+ linesDeleted: stats.deletions,
286
+ warnings: warnings.length > 0 ? warnings : undefined,
287
+ };
288
+ this.emit('pr:complete', { result });
289
+ // Switch back to original branch
290
+ this.git.checkout(this.originalBranch);
291
+ return result;
292
+ }
293
+ catch (error) {
294
+ const errorMessage = error instanceof Error ? error.message : String(error);
295
+ this.emit('pr:error', { error: error, stage: 'create' });
296
+ // Attempt cleanup
297
+ try {
298
+ if (this.git && this.originalBranch) {
299
+ const currentBranch = this.git.getCurrentBranch();
300
+ if (currentBranch !== this.originalBranch) {
301
+ this.git.checkout(this.originalBranch);
302
+ }
303
+ }
304
+ }
305
+ catch {
306
+ // Ignore cleanup errors
307
+ }
308
+ return {
309
+ success: false,
310
+ branchName: options.branchName ?? generateBranchName(suggestion),
311
+ filesChanged: [],
312
+ linesAdded: 0,
313
+ linesDeleted: 0,
314
+ error: errorMessage,
315
+ warnings: warnings.length > 0 ? warnings : undefined,
316
+ };
317
+ }
318
+ }
319
+ /**
320
+ * Preview PR creation without actually creating
321
+ * @see REQ-CG-PR-007
322
+ */
323
+ async preview(options) {
324
+ this.ensureInitialized();
325
+ const { suggestion } = options;
326
+ const branchName = options.branchName ?? generateBranchName(suggestion);
327
+ const baseBranch = options.baseBranch ?? this.git.getDefaultBranch();
328
+ // Generate preview
329
+ const diffs = this.applier.preview(suggestion);
330
+ const title = options.title ?? this.templateGenerator.generateTitle(suggestion);
331
+ const body = options.body ?? this.templateGenerator.generate(suggestion, diffs);
332
+ const commitMessage = generateCommitMessage(suggestion);
333
+ return {
334
+ branchName,
335
+ baseBranch,
336
+ title,
337
+ body,
338
+ diffs,
339
+ commitMessage,
340
+ };
341
+ }
342
+ /**
343
+ * Validate a suggestion can be applied
344
+ */
345
+ validate(suggestion) {
346
+ this.ensureInitialized();
347
+ const result = this.applier.canApply(suggestion);
348
+ return { valid: result.canApply, reason: result.reason };
349
+ }
350
+ // ============================================================================
351
+ // Private Helpers
352
+ // ============================================================================
353
+ /**
354
+ * Dry run implementation
355
+ */
356
+ dryRun(options, branchName) {
357
+ const { suggestion } = options;
358
+ const baseBranch = options.baseBranch ?? this.git.getDefaultBranch();
359
+ // Generate preview
360
+ const diffs = this.applier.preview(suggestion);
361
+ const title = options.title ?? this.templateGenerator.generateTitle(suggestion);
362
+ const body = options.body ?? this.templateGenerator.generate(suggestion, diffs);
363
+ const commitMessage = generateCommitMessage(suggestion);
364
+ // Calculate stats from diffs
365
+ let linesAdded = 0;
366
+ let linesDeleted = 0;
367
+ for (const diff of diffs) {
368
+ linesAdded += diff.additions;
369
+ linesDeleted += diff.deletions;
370
+ }
371
+ return {
372
+ success: true,
373
+ branchName,
374
+ filesChanged: diffs.map(d => d.filePath),
375
+ linesAdded,
376
+ linesDeleted,
377
+ preview: {
378
+ branchName,
379
+ baseBranch,
380
+ title,
381
+ body,
382
+ diffs,
383
+ commitMessage,
384
+ },
385
+ };
386
+ }
387
+ /**
388
+ * Ensure initialized before operations (legacy)
389
+ * @deprecated Use ensureState() instead
390
+ */
391
+ ensureInitialized() {
392
+ if (!this.initialized) {
393
+ throw PRCreatorError.fromCode('NOT_INITIALIZED');
394
+ }
395
+ }
396
+ /**
397
+ * Ensure PRCreator is in one of the allowed states
398
+ * @see DES-CG-v234-003
399
+ */
400
+ ensureState(...allowed) {
401
+ if (!allowed.includes(this.state)) {
402
+ if (this.state === 'uninitialized') {
403
+ throw PRCreatorError.fromCode('NOT_INITIALIZED');
404
+ }
405
+ else if (this.state === 'offline' && allowed.includes('full')) {
406
+ throw PRCreatorError.fromCode('OFFLINE_MODE');
407
+ }
408
+ throw PRCreatorError.fromCode('NOT_INITIALIZED');
409
+ }
410
+ }
411
+ // ============================================================================
412
+ // Event Typing
413
+ // ============================================================================
414
+ /**
415
+ * Typed event emitter methods
416
+ */
417
+ emit(event, data) {
418
+ return super.emit(event, data);
419
+ }
420
+ on(event, listener) {
421
+ return super.on(event, listener);
422
+ }
423
+ once(event, listener) {
424
+ return super.once(event, listener);
425
+ }
426
+ }
427
+ /**
428
+ * Create a PRCreator instance
429
+ */
430
+ export function createPRCreator(repoPath, options) {
431
+ return new PRCreator({
432
+ repoPath,
433
+ ...options,
434
+ });
435
+ }
436
+ /**
437
+ * Quick PR creation helper
438
+ *
439
+ * One-shot function to create a PR from a suggestion.
440
+ *
441
+ * @example
442
+ * ```typescript
443
+ * const result = await createRefactoringPR(
444
+ * '/path/to/repo',
445
+ * suggestion,
446
+ * { labels: ['refactoring'] }
447
+ * );
448
+ * ```
449
+ */
450
+ export async function createRefactoringPR(repoPath, suggestion, options) {
451
+ const creator = createPRCreator(repoPath);
452
+ const initResult = await creator.initialize();
453
+ if (!initResult.success) {
454
+ return {
455
+ success: false,
456
+ branchName: generateBranchName(suggestion),
457
+ filesChanged: [],
458
+ linesAdded: 0,
459
+ linesDeleted: 0,
460
+ error: initResult.error,
461
+ };
462
+ }
463
+ return creator.create({
464
+ suggestion,
465
+ ...options,
466
+ });
467
+ }
468
+ //# sourceMappingURL=pr-creator.js.map