hale-commenting-system 2.0.4 → 2.1.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/bin/detect.d.ts CHANGED
@@ -1 +1,10 @@
1
1
  export declare function detectPatternFlySeed(): boolean;
2
+ export interface GitRemoteInfo {
3
+ owner?: string;
4
+ repo?: string;
5
+ url?: string;
6
+ isFork?: boolean;
7
+ }
8
+ export declare function detectGitRemote(): GitRemoteInfo | null;
9
+ export type ProjectSetupType = 'forked' | 'cloned' | 'unknown' | 'none';
10
+ export declare function detectProjectSetup(): ProjectSetupType;
package/bin/detect.js CHANGED
@@ -34,8 +34,11 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.detectPatternFlySeed = detectPatternFlySeed;
37
+ exports.detectGitRemote = detectGitRemote;
38
+ exports.detectProjectSetup = detectProjectSetup;
37
39
  const fs = __importStar(require("fs"));
38
40
  const path = __importStar(require("path"));
41
+ const child_process_1 = require("child_process");
39
42
  function detectPatternFlySeed() {
40
43
  const cwd = process.cwd();
41
44
  // Check for webpack config files
@@ -60,3 +63,72 @@ function detectPatternFlySeed() {
60
63
  }
61
64
  return hasWebpack && hasAppDir && hasPatternFly;
62
65
  }
66
+ function detectGitRemote() {
67
+ const cwd = process.cwd();
68
+ // Check if .git exists
69
+ if (!fs.existsSync(path.join(cwd, '.git'))) {
70
+ return null;
71
+ }
72
+ try {
73
+ // Get remote URL
74
+ const remoteUrl = (0, child_process_1.execSync)('git remote get-url origin', {
75
+ cwd,
76
+ encoding: 'utf-8',
77
+ stdio: ['ignore', 'pipe', 'ignore']
78
+ }).trim();
79
+ if (!remoteUrl) {
80
+ return null;
81
+ }
82
+ // Parse GitHub URL (supports https://, git@, and ssh formats)
83
+ // https://github.com/owner/repo.git
84
+ // git@github.com:owner/repo.git
85
+ // ssh://git@github.com/owner/repo.git
86
+ const githubMatch = remoteUrl.match(/github\.com[/:]([^/]+)\/([^/]+?)(?:\.git)?$/);
87
+ if (githubMatch) {
88
+ const owner = githubMatch[1];
89
+ const repo = githubMatch[2].replace(/\.git$/, '');
90
+ // Try to detect if it's a fork by checking if upstream exists
91
+ let isFork = false;
92
+ try {
93
+ (0, child_process_1.execSync)('git remote get-url upstream', {
94
+ cwd,
95
+ encoding: 'utf-8',
96
+ stdio: ['ignore', 'pipe', 'ignore']
97
+ });
98
+ isFork = true;
99
+ }
100
+ catch {
101
+ // No upstream remote, might still be a fork but we can't tell
102
+ // Check if repo name matches patternfly-react-seed (likely a fork)
103
+ isFork = repo.includes('patternfly-react-seed') || repo.includes('pfseed');
104
+ }
105
+ return {
106
+ owner,
107
+ repo,
108
+ url: remoteUrl,
109
+ isFork
110
+ };
111
+ }
112
+ }
113
+ catch (error) {
114
+ // Git command failed or not a git repo
115
+ return null;
116
+ }
117
+ return null;
118
+ }
119
+ function detectProjectSetup() {
120
+ const gitInfo = detectGitRemote();
121
+ if (!gitInfo) {
122
+ return 'none';
123
+ }
124
+ // Check if it looks like a fork (has patternfly-react-seed in name or has upstream)
125
+ if (gitInfo.isFork || gitInfo.repo?.includes('patternfly-react-seed')) {
126
+ return 'forked';
127
+ }
128
+ // Check if it's a clone of the original
129
+ if (gitInfo.owner === 'patternfly' && gitInfo.repo === 'patternfly-react-seed') {
130
+ return 'cloned';
131
+ }
132
+ // Has git remote but unclear
133
+ return 'unknown';
134
+ }
package/bin/onboarding.js CHANGED
@@ -40,13 +40,207 @@ exports.runOnboarding = runOnboarding;
40
40
  const inquirer_1 = __importDefault(require("inquirer"));
41
41
  const validators = __importStar(require("./validators"));
42
42
  const generators = __importStar(require("./generators"));
43
+ const detect_1 = require("./detect");
43
44
  async function runOnboarding() {
44
- console.log('Welcome to Hale Commenting System!');
45
- console.log('This setup will guide you through connecting GitHub and Jira.\n');
46
- // Step 1: GitHub OAuth Setup
47
- console.log('šŸ“¦ Step 1: GitHub OAuth Setup\n');
48
- console.log('You\'ll need to create a GitHub OAuth App if you haven\'t already.');
49
- console.log('Visit: https://github.com/settings/developers\n');
45
+ // Welcome & Explanation
46
+ console.log('šŸš€ Welcome to Hale Commenting System!\n');
47
+ console.log('This commenting system allows you to:');
48
+ console.log(' • Add comments directly on your design pages');
49
+ console.log(' • Sync comments with GitHub Issues');
50
+ console.log(' • Link Jira tickets to pages');
51
+ console.log(' • Store design goals and context\n');
52
+ console.log('Why GitHub?');
53
+ console.log(' We use GitHub Issues to store and sync all comments. When you add a comment');
54
+ console.log(' on a page, it creates a GitHub Issue. This allows comments to persist, sync');
55
+ console.log(' across devices, and be managed like any other GitHub Issue.\n');
56
+ console.log('Why Jira?');
57
+ console.log(' You can link Jira tickets to specific pages or sections. This helps connect');
58
+ console.log(' design work to development tracking and provides context for reviewers.\n');
59
+ // Step 1: Project Status Check
60
+ console.log('šŸ“‹ Step 1: Project Setup Check\n');
61
+ const hasProject = await inquirer_1.default.prompt([
62
+ {
63
+ type: 'list',
64
+ name: 'hasProject',
65
+ message: 'Do you have a PatternFly Seed project set up locally?',
66
+ choices: [
67
+ { name: 'Yes, I have it set up', value: 'yes' },
68
+ { name: 'No, I need help setting it up', value: 'no' }
69
+ ]
70
+ }
71
+ ]);
72
+ if (hasProject.hasProject === 'no') {
73
+ console.log('\nšŸ“š Setting up PatternFly Seed:\n');
74
+ console.log('1. Fork the PatternFly Seed repository:');
75
+ console.log(' Visit: https://github.com/patternfly/patternfly-react-seed');
76
+ console.log(' Click "Fork" in the top right\n');
77
+ console.log('2. Clone your fork locally:');
78
+ console.log(' git clone https://github.com/YOUR_USERNAME/patternfly-react-seed.git');
79
+ console.log(' cd patternfly-react-seed\n');
80
+ console.log('3. Install dependencies:');
81
+ console.log(' npm install\n');
82
+ console.log('4. Run this setup again:');
83
+ console.log(' npx hale-commenting-system init\n');
84
+ process.exit(0);
85
+ }
86
+ // Check if it's actually a PF Seed project
87
+ if (!(0, detect_1.detectPatternFlySeed)()) {
88
+ console.error('āŒ Error: This doesn\'t appear to be a PatternFly Seed project.');
89
+ console.error('Please run this command from a PatternFly Seed project directory.');
90
+ process.exit(1);
91
+ }
92
+ // Detect project setup type
93
+ const gitInfo = (0, detect_1.detectGitRemote)();
94
+ const setupType = (0, detect_1.detectProjectSetup)();
95
+ let projectSetup = 'unknown';
96
+ let owner = gitInfo?.owner;
97
+ let repo = gitInfo?.repo;
98
+ if (setupType === 'none' || !gitInfo) {
99
+ // No git remote - need to set up
100
+ const setupAnswer = await inquirer_1.default.prompt([
101
+ {
102
+ type: 'list',
103
+ name: 'setupType',
104
+ message: 'How did you set up your PatternFly Seed project?',
105
+ choices: [
106
+ { name: 'I forked the PatternFly Seed repo on GitHub', value: 'forked' },
107
+ { name: 'I cloned the PatternFly Seed repo locally', value: 'cloned' },
108
+ { name: 'I\'m not sure', value: 'unknown' }
109
+ ]
110
+ }
111
+ ]);
112
+ projectSetup = setupAnswer.setupType;
113
+ }
114
+ else {
115
+ projectSetup = setupType;
116
+ }
117
+ // Handle different setup types
118
+ if (projectSetup === 'forked') {
119
+ // Ask for owner/repo if not detected
120
+ if (!owner || !repo) {
121
+ const forkAnswers = await inquirer_1.default.prompt([
122
+ {
123
+ type: 'input',
124
+ name: 'owner',
125
+ message: 'What is your GitHub username or organization name?',
126
+ default: owner,
127
+ validate: (input) => {
128
+ if (!input.trim())
129
+ return 'Owner is required';
130
+ return true;
131
+ }
132
+ },
133
+ {
134
+ type: 'input',
135
+ name: 'repo',
136
+ message: 'What is the name of your forked repository?',
137
+ default: repo,
138
+ validate: (input) => {
139
+ if (!input.trim())
140
+ return 'Repository name is required';
141
+ return true;
142
+ }
143
+ }
144
+ ]);
145
+ owner = forkAnswers.owner;
146
+ repo = forkAnswers.repo;
147
+ }
148
+ else {
149
+ console.log(`\nāœ… Detected repository: ${owner}/${repo}\n`);
150
+ }
151
+ }
152
+ else if (projectSetup === 'cloned') {
153
+ console.log('\nšŸ“ Since you cloned the repo, you\'ll need to create your own GitHub repository.\n');
154
+ console.log('Steps:');
155
+ console.log('1. Create a new repository on GitHub');
156
+ console.log('2. Add it as a remote: git remote add origin <your-repo-url>');
157
+ console.log('3. Push your code: git push -u origin main\n');
158
+ const hasCreated = await inquirer_1.default.prompt([
159
+ {
160
+ type: 'confirm',
161
+ name: 'created',
162
+ message: 'Have you created and pushed to your GitHub repository?',
163
+ default: false
164
+ }
165
+ ]);
166
+ if (!hasCreated.created) {
167
+ console.log('\nPlease complete the steps above and run this setup again.');
168
+ process.exit(0);
169
+ }
170
+ // Ask for owner/repo
171
+ const repoAnswers = await inquirer_1.default.prompt([
172
+ {
173
+ type: 'input',
174
+ name: 'owner',
175
+ message: 'What is your GitHub username or organization name?',
176
+ validate: (input) => {
177
+ if (!input.trim())
178
+ return 'Owner is required';
179
+ return true;
180
+ }
181
+ },
182
+ {
183
+ type: 'input',
184
+ name: 'repo',
185
+ message: 'What is the name of your GitHub repository?',
186
+ validate: (input) => {
187
+ if (!input.trim())
188
+ return 'Repository name is required';
189
+ return true;
190
+ }
191
+ }
192
+ ]);
193
+ owner = repoAnswers.owner;
194
+ repo = repoAnswers.repo;
195
+ }
196
+ else if (projectSetup === 'unknown') {
197
+ // Try to detect from git
198
+ if (gitInfo && gitInfo.owner && gitInfo.repo) {
199
+ console.log(`\nāœ… Detected repository: ${gitInfo.owner}/${gitInfo.repo}\n`);
200
+ owner = gitInfo.owner;
201
+ repo = gitInfo.repo;
202
+ }
203
+ else {
204
+ // Ask for owner/repo
205
+ const repoAnswers = await inquirer_1.default.prompt([
206
+ {
207
+ type: 'input',
208
+ name: 'owner',
209
+ message: 'What is your GitHub username or organization name?',
210
+ validate: (input) => {
211
+ if (!input.trim())
212
+ return 'Owner is required';
213
+ return true;
214
+ }
215
+ },
216
+ {
217
+ type: 'input',
218
+ name: 'repo',
219
+ message: 'What is the name of your GitHub repository?',
220
+ validate: (input) => {
221
+ if (!input.trim())
222
+ return 'Repository name is required';
223
+ return true;
224
+ }
225
+ }
226
+ ]);
227
+ owner = repoAnswers.owner;
228
+ repo = repoAnswers.repo;
229
+ }
230
+ }
231
+ // Step 2: GitHub OAuth Setup
232
+ console.log('\nšŸ“¦ Step 2: GitHub OAuth Setup\n');
233
+ console.log('To sync comments with GitHub Issues, we need to authenticate with GitHub.');
234
+ console.log('This requires creating a GitHub OAuth App.\n');
235
+ console.log('Instructions:');
236
+ console.log('1. Visit: https://github.com/settings/developers');
237
+ console.log('2. Click "New OAuth App"');
238
+ console.log('3. Fill in the form:');
239
+ console.log(' - Application name: Your app name (e.g., "My Design Comments")');
240
+ console.log(' - Homepage URL: http://localhost:9000 (or your dev server URL)');
241
+ console.log(' - Authorization callback URL: http://localhost:9000/api/github-oauth-callback');
242
+ console.log('4. Click "Register application"');
243
+ console.log('5. Copy the Client ID and generate a Client Secret\n');
50
244
  const githubAnswers = await inquirer_1.default.prompt([
51
245
  {
52
246
  type: 'input',
@@ -62,45 +256,29 @@ async function runOnboarding() {
62
256
  type: 'password',
63
257
  name: 'clientSecret',
64
258
  message: 'GitHub OAuth Client Secret:',
259
+ mask: '*',
65
260
  validate: (input) => {
66
261
  if (!input.trim())
67
262
  return 'Client Secret is required';
68
263
  return true;
69
264
  }
70
- },
71
- {
72
- type: 'input',
73
- name: 'owner',
74
- message: 'GitHub Owner (username or org):',
75
- validate: (input) => {
76
- if (!input.trim())
77
- return 'Owner is required';
78
- return true;
79
- }
80
- },
81
- {
82
- type: 'input',
83
- name: 'repo',
84
- message: 'GitHub Repository name:',
85
- validate: (input) => {
86
- if (!input.trim())
87
- return 'Repository name is required';
88
- return true;
89
- }
90
265
  }
91
266
  ]);
92
267
  // Validate GitHub credentials
93
268
  console.log('\nšŸ” Validating GitHub credentials...');
94
- const githubValid = await validators.validateGitHubCredentials(githubAnswers.clientId, githubAnswers.clientSecret, githubAnswers.owner, githubAnswers.repo);
269
+ const githubValid = await validators.validateGitHubCredentials(githubAnswers.clientId, githubAnswers.clientSecret, owner, repo);
95
270
  if (!githubValid) {
96
271
  console.error('āŒ GitHub validation failed. Please check your credentials and try again.');
97
272
  process.exit(1);
98
273
  }
99
274
  console.log('āœ… GitHub credentials validated!\n');
100
- // Step 2: Jira Setup
101
- console.log('šŸŽ« Step 2: Jira Setup\n');
275
+ // Step 3: Jira Setup
276
+ console.log('šŸŽ« Step 3: Jira Setup\n');
277
+ console.log('You can link Jira tickets to pages in your design. This helps connect');
278
+ console.log('design work to development tracking.\n');
102
279
  console.log('For Red Hat Jira, generate a Personal Access Token from:');
103
280
  console.log('https://issues.redhat.com/secure/ViewProfile.jspa\n');
281
+ console.log('Note: We use Bearer token authentication (no email required for Red Hat Jira).\n');
104
282
  const jiraAnswers = await inquirer_1.default.prompt([
105
283
  {
106
284
  type: 'input',
@@ -119,16 +297,11 @@ async function runOnboarding() {
119
297
  }
120
298
  }
121
299
  },
122
- {
123
- type: 'input',
124
- name: 'email',
125
- message: 'Jira Email (optional, leave blank if using Bearer token):',
126
- default: ''
127
- },
128
300
  {
129
301
  type: 'password',
130
302
  name: 'apiToken',
131
303
  message: 'Jira API Token:',
304
+ mask: '*',
132
305
  validate: (input) => {
133
306
  if (!input.trim())
134
307
  return 'API Token is required';
@@ -138,29 +311,30 @@ async function runOnboarding() {
138
311
  ]);
139
312
  // Validate Jira credentials
140
313
  console.log('\nšŸ” Validating Jira credentials...');
141
- const jiraValid = await validators.validateJiraCredentials(jiraAnswers.baseUrl, jiraAnswers.apiToken, jiraAnswers.email || undefined);
314
+ const jiraValid = await validators.validateJiraCredentials(jiraAnswers.baseUrl, jiraAnswers.apiToken, undefined // No email for Bearer token
315
+ );
142
316
  if (!jiraValid) {
143
317
  console.error('āŒ Jira validation failed. Please check your credentials and try again.');
144
318
  process.exit(1);
145
319
  }
146
320
  console.log('āœ… Jira credentials validated!\n');
147
- // Step 3: Generate files
148
- console.log('šŸ“ Step 3: Generating configuration files...\n');
321
+ // Step 4: Generate files
322
+ console.log('šŸ“ Step 4: Generating configuration files...\n');
149
323
  await generators.generateFiles({
150
324
  github: {
151
325
  clientId: githubAnswers.clientId,
152
326
  clientSecret: githubAnswers.clientSecret,
153
- owner: githubAnswers.owner,
154
- repo: githubAnswers.repo
327
+ owner: owner,
328
+ repo: repo
155
329
  },
156
330
  jira: {
157
331
  baseUrl: jiraAnswers.baseUrl,
158
332
  apiToken: jiraAnswers.apiToken,
159
- email: jiraAnswers.email || undefined
333
+ email: undefined // Not used for Bearer token
160
334
  }
161
335
  });
162
- // Step 4: Integrate into project
163
- console.log('šŸ”§ Step 4: Integrating into PatternFly Seed project...\n');
336
+ // Step 5: Integrate into project
337
+ console.log('šŸ”§ Step 5: Integrating into PatternFly Seed project...\n');
164
338
  await generators.integrateIntoProject();
165
339
  console.log('\nāœ… Setup complete!');
166
340
  console.log('\nNext steps:');
@@ -1 +1,10 @@
1
1
  export declare function detectPatternFlySeed(): boolean;
2
+ export interface GitRemoteInfo {
3
+ owner?: string;
4
+ repo?: string;
5
+ url?: string;
6
+ isFork?: boolean;
7
+ }
8
+ export declare function detectGitRemote(): GitRemoteInfo | null;
9
+ export type ProjectSetupType = 'forked' | 'cloned' | 'unknown' | 'none';
10
+ export declare function detectProjectSetup(): ProjectSetupType;
@@ -34,8 +34,11 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.detectPatternFlySeed = detectPatternFlySeed;
37
+ exports.detectGitRemote = detectGitRemote;
38
+ exports.detectProjectSetup = detectProjectSetup;
37
39
  const fs = __importStar(require("fs"));
38
40
  const path = __importStar(require("path"));
41
+ const child_process_1 = require("child_process");
39
42
  function detectPatternFlySeed() {
40
43
  const cwd = process.cwd();
41
44
  // Check for webpack config files
@@ -60,3 +63,72 @@ function detectPatternFlySeed() {
60
63
  }
61
64
  return hasWebpack && hasAppDir && hasPatternFly;
62
65
  }
66
+ function detectGitRemote() {
67
+ const cwd = process.cwd();
68
+ // Check if .git exists
69
+ if (!fs.existsSync(path.join(cwd, '.git'))) {
70
+ return null;
71
+ }
72
+ try {
73
+ // Get remote URL
74
+ const remoteUrl = (0, child_process_1.execSync)('git remote get-url origin', {
75
+ cwd,
76
+ encoding: 'utf-8',
77
+ stdio: ['ignore', 'pipe', 'ignore']
78
+ }).trim();
79
+ if (!remoteUrl) {
80
+ return null;
81
+ }
82
+ // Parse GitHub URL (supports https://, git@, and ssh formats)
83
+ // https://github.com/owner/repo.git
84
+ // git@github.com:owner/repo.git
85
+ // ssh://git@github.com/owner/repo.git
86
+ const githubMatch = remoteUrl.match(/github\.com[/:]([^/]+)\/([^/]+?)(?:\.git)?$/);
87
+ if (githubMatch) {
88
+ const owner = githubMatch[1];
89
+ const repo = githubMatch[2].replace(/\.git$/, '');
90
+ // Try to detect if it's a fork by checking if upstream exists
91
+ let isFork = false;
92
+ try {
93
+ (0, child_process_1.execSync)('git remote get-url upstream', {
94
+ cwd,
95
+ encoding: 'utf-8',
96
+ stdio: ['ignore', 'pipe', 'ignore']
97
+ });
98
+ isFork = true;
99
+ }
100
+ catch {
101
+ // No upstream remote, might still be a fork but we can't tell
102
+ // Check if repo name matches patternfly-react-seed (likely a fork)
103
+ isFork = repo.includes('patternfly-react-seed') || repo.includes('pfseed');
104
+ }
105
+ return {
106
+ owner,
107
+ repo,
108
+ url: remoteUrl,
109
+ isFork
110
+ };
111
+ }
112
+ }
113
+ catch (error) {
114
+ // Git command failed or not a git repo
115
+ return null;
116
+ }
117
+ return null;
118
+ }
119
+ function detectProjectSetup() {
120
+ const gitInfo = detectGitRemote();
121
+ if (!gitInfo) {
122
+ return 'none';
123
+ }
124
+ // Check if it looks like a fork (has patternfly-react-seed in name or has upstream)
125
+ if (gitInfo.isFork || gitInfo.repo?.includes('patternfly-react-seed')) {
126
+ return 'forked';
127
+ }
128
+ // Check if it's a clone of the original
129
+ if (gitInfo.owner === 'patternfly' && gitInfo.repo === 'patternfly-react-seed') {
130
+ return 'cloned';
131
+ }
132
+ // Has git remote but unclear
133
+ return 'unknown';
134
+ }
@@ -40,13 +40,207 @@ exports.runOnboarding = runOnboarding;
40
40
  const inquirer_1 = __importDefault(require("inquirer"));
41
41
  const validators = __importStar(require("./validators"));
42
42
  const generators = __importStar(require("./generators"));
43
+ const detect_1 = require("./detect");
43
44
  async function runOnboarding() {
44
- console.log('Welcome to Hale Commenting System!');
45
- console.log('This setup will guide you through connecting GitHub and Jira.\n');
46
- // Step 1: GitHub OAuth Setup
47
- console.log('šŸ“¦ Step 1: GitHub OAuth Setup\n');
48
- console.log('You\'ll need to create a GitHub OAuth App if you haven\'t already.');
49
- console.log('Visit: https://github.com/settings/developers\n');
45
+ // Welcome & Explanation
46
+ console.log('šŸš€ Welcome to Hale Commenting System!\n');
47
+ console.log('This commenting system allows you to:');
48
+ console.log(' • Add comments directly on your design pages');
49
+ console.log(' • Sync comments with GitHub Issues');
50
+ console.log(' • Link Jira tickets to pages');
51
+ console.log(' • Store design goals and context\n');
52
+ console.log('Why GitHub?');
53
+ console.log(' We use GitHub Issues to store and sync all comments. When you add a comment');
54
+ console.log(' on a page, it creates a GitHub Issue. This allows comments to persist, sync');
55
+ console.log(' across devices, and be managed like any other GitHub Issue.\n');
56
+ console.log('Why Jira?');
57
+ console.log(' You can link Jira tickets to specific pages or sections. This helps connect');
58
+ console.log(' design work to development tracking and provides context for reviewers.\n');
59
+ // Step 1: Project Status Check
60
+ console.log('šŸ“‹ Step 1: Project Setup Check\n');
61
+ const hasProject = await inquirer_1.default.prompt([
62
+ {
63
+ type: 'list',
64
+ name: 'hasProject',
65
+ message: 'Do you have a PatternFly Seed project set up locally?',
66
+ choices: [
67
+ { name: 'Yes, I have it set up', value: 'yes' },
68
+ { name: 'No, I need help setting it up', value: 'no' }
69
+ ]
70
+ }
71
+ ]);
72
+ if (hasProject.hasProject === 'no') {
73
+ console.log('\nšŸ“š Setting up PatternFly Seed:\n');
74
+ console.log('1. Fork the PatternFly Seed repository:');
75
+ console.log(' Visit: https://github.com/patternfly/patternfly-react-seed');
76
+ console.log(' Click "Fork" in the top right\n');
77
+ console.log('2. Clone your fork locally:');
78
+ console.log(' git clone https://github.com/YOUR_USERNAME/patternfly-react-seed.git');
79
+ console.log(' cd patternfly-react-seed\n');
80
+ console.log('3. Install dependencies:');
81
+ console.log(' npm install\n');
82
+ console.log('4. Run this setup again:');
83
+ console.log(' npx hale-commenting-system init\n');
84
+ process.exit(0);
85
+ }
86
+ // Check if it's actually a PF Seed project
87
+ if (!(0, detect_1.detectPatternFlySeed)()) {
88
+ console.error('āŒ Error: This doesn\'t appear to be a PatternFly Seed project.');
89
+ console.error('Please run this command from a PatternFly Seed project directory.');
90
+ process.exit(1);
91
+ }
92
+ // Detect project setup type
93
+ const gitInfo = (0, detect_1.detectGitRemote)();
94
+ const setupType = (0, detect_1.detectProjectSetup)();
95
+ let projectSetup = 'unknown';
96
+ let owner = gitInfo?.owner;
97
+ let repo = gitInfo?.repo;
98
+ if (setupType === 'none' || !gitInfo) {
99
+ // No git remote - need to set up
100
+ const setupAnswer = await inquirer_1.default.prompt([
101
+ {
102
+ type: 'list',
103
+ name: 'setupType',
104
+ message: 'How did you set up your PatternFly Seed project?',
105
+ choices: [
106
+ { name: 'I forked the PatternFly Seed repo on GitHub', value: 'forked' },
107
+ { name: 'I cloned the PatternFly Seed repo locally', value: 'cloned' },
108
+ { name: 'I\'m not sure', value: 'unknown' }
109
+ ]
110
+ }
111
+ ]);
112
+ projectSetup = setupAnswer.setupType;
113
+ }
114
+ else {
115
+ projectSetup = setupType;
116
+ }
117
+ // Handle different setup types
118
+ if (projectSetup === 'forked') {
119
+ // Ask for owner/repo if not detected
120
+ if (!owner || !repo) {
121
+ const forkAnswers = await inquirer_1.default.prompt([
122
+ {
123
+ type: 'input',
124
+ name: 'owner',
125
+ message: 'What is your GitHub username or organization name?',
126
+ default: owner,
127
+ validate: (input) => {
128
+ if (!input.trim())
129
+ return 'Owner is required';
130
+ return true;
131
+ }
132
+ },
133
+ {
134
+ type: 'input',
135
+ name: 'repo',
136
+ message: 'What is the name of your forked repository?',
137
+ default: repo,
138
+ validate: (input) => {
139
+ if (!input.trim())
140
+ return 'Repository name is required';
141
+ return true;
142
+ }
143
+ }
144
+ ]);
145
+ owner = forkAnswers.owner;
146
+ repo = forkAnswers.repo;
147
+ }
148
+ else {
149
+ console.log(`\nāœ… Detected repository: ${owner}/${repo}\n`);
150
+ }
151
+ }
152
+ else if (projectSetup === 'cloned') {
153
+ console.log('\nšŸ“ Since you cloned the repo, you\'ll need to create your own GitHub repository.\n');
154
+ console.log('Steps:');
155
+ console.log('1. Create a new repository on GitHub');
156
+ console.log('2. Add it as a remote: git remote add origin <your-repo-url>');
157
+ console.log('3. Push your code: git push -u origin main\n');
158
+ const hasCreated = await inquirer_1.default.prompt([
159
+ {
160
+ type: 'confirm',
161
+ name: 'created',
162
+ message: 'Have you created and pushed to your GitHub repository?',
163
+ default: false
164
+ }
165
+ ]);
166
+ if (!hasCreated.created) {
167
+ console.log('\nPlease complete the steps above and run this setup again.');
168
+ process.exit(0);
169
+ }
170
+ // Ask for owner/repo
171
+ const repoAnswers = await inquirer_1.default.prompt([
172
+ {
173
+ type: 'input',
174
+ name: 'owner',
175
+ message: 'What is your GitHub username or organization name?',
176
+ validate: (input) => {
177
+ if (!input.trim())
178
+ return 'Owner is required';
179
+ return true;
180
+ }
181
+ },
182
+ {
183
+ type: 'input',
184
+ name: 'repo',
185
+ message: 'What is the name of your GitHub repository?',
186
+ validate: (input) => {
187
+ if (!input.trim())
188
+ return 'Repository name is required';
189
+ return true;
190
+ }
191
+ }
192
+ ]);
193
+ owner = repoAnswers.owner;
194
+ repo = repoAnswers.repo;
195
+ }
196
+ else if (projectSetup === 'unknown') {
197
+ // Try to detect from git
198
+ if (gitInfo && gitInfo.owner && gitInfo.repo) {
199
+ console.log(`\nāœ… Detected repository: ${gitInfo.owner}/${gitInfo.repo}\n`);
200
+ owner = gitInfo.owner;
201
+ repo = gitInfo.repo;
202
+ }
203
+ else {
204
+ // Ask for owner/repo
205
+ const repoAnswers = await inquirer_1.default.prompt([
206
+ {
207
+ type: 'input',
208
+ name: 'owner',
209
+ message: 'What is your GitHub username or organization name?',
210
+ validate: (input) => {
211
+ if (!input.trim())
212
+ return 'Owner is required';
213
+ return true;
214
+ }
215
+ },
216
+ {
217
+ type: 'input',
218
+ name: 'repo',
219
+ message: 'What is the name of your GitHub repository?',
220
+ validate: (input) => {
221
+ if (!input.trim())
222
+ return 'Repository name is required';
223
+ return true;
224
+ }
225
+ }
226
+ ]);
227
+ owner = repoAnswers.owner;
228
+ repo = repoAnswers.repo;
229
+ }
230
+ }
231
+ // Step 2: GitHub OAuth Setup
232
+ console.log('\nšŸ“¦ Step 2: GitHub OAuth Setup\n');
233
+ console.log('To sync comments with GitHub Issues, we need to authenticate with GitHub.');
234
+ console.log('This requires creating a GitHub OAuth App.\n');
235
+ console.log('Instructions:');
236
+ console.log('1. Visit: https://github.com/settings/developers');
237
+ console.log('2. Click "New OAuth App"');
238
+ console.log('3. Fill in the form:');
239
+ console.log(' - Application name: Your app name (e.g., "My Design Comments")');
240
+ console.log(' - Homepage URL: http://localhost:9000 (or your dev server URL)');
241
+ console.log(' - Authorization callback URL: http://localhost:9000/api/github-oauth-callback');
242
+ console.log('4. Click "Register application"');
243
+ console.log('5. Copy the Client ID and generate a Client Secret\n');
50
244
  const githubAnswers = await inquirer_1.default.prompt([
51
245
  {
52
246
  type: 'input',
@@ -62,45 +256,29 @@ async function runOnboarding() {
62
256
  type: 'password',
63
257
  name: 'clientSecret',
64
258
  message: 'GitHub OAuth Client Secret:',
259
+ mask: '*',
65
260
  validate: (input) => {
66
261
  if (!input.trim())
67
262
  return 'Client Secret is required';
68
263
  return true;
69
264
  }
70
- },
71
- {
72
- type: 'input',
73
- name: 'owner',
74
- message: 'GitHub Owner (username or org):',
75
- validate: (input) => {
76
- if (!input.trim())
77
- return 'Owner is required';
78
- return true;
79
- }
80
- },
81
- {
82
- type: 'input',
83
- name: 'repo',
84
- message: 'GitHub Repository name:',
85
- validate: (input) => {
86
- if (!input.trim())
87
- return 'Repository name is required';
88
- return true;
89
- }
90
265
  }
91
266
  ]);
92
267
  // Validate GitHub credentials
93
268
  console.log('\nšŸ” Validating GitHub credentials...');
94
- const githubValid = await validators.validateGitHubCredentials(githubAnswers.clientId, githubAnswers.clientSecret, githubAnswers.owner, githubAnswers.repo);
269
+ const githubValid = await validators.validateGitHubCredentials(githubAnswers.clientId, githubAnswers.clientSecret, owner, repo);
95
270
  if (!githubValid) {
96
271
  console.error('āŒ GitHub validation failed. Please check your credentials and try again.');
97
272
  process.exit(1);
98
273
  }
99
274
  console.log('āœ… GitHub credentials validated!\n');
100
- // Step 2: Jira Setup
101
- console.log('šŸŽ« Step 2: Jira Setup\n');
275
+ // Step 3: Jira Setup
276
+ console.log('šŸŽ« Step 3: Jira Setup\n');
277
+ console.log('You can link Jira tickets to pages in your design. This helps connect');
278
+ console.log('design work to development tracking.\n');
102
279
  console.log('For Red Hat Jira, generate a Personal Access Token from:');
103
280
  console.log('https://issues.redhat.com/secure/ViewProfile.jspa\n');
281
+ console.log('Note: We use Bearer token authentication (no email required for Red Hat Jira).\n');
104
282
  const jiraAnswers = await inquirer_1.default.prompt([
105
283
  {
106
284
  type: 'input',
@@ -119,16 +297,11 @@ async function runOnboarding() {
119
297
  }
120
298
  }
121
299
  },
122
- {
123
- type: 'input',
124
- name: 'email',
125
- message: 'Jira Email (optional, leave blank if using Bearer token):',
126
- default: ''
127
- },
128
300
  {
129
301
  type: 'password',
130
302
  name: 'apiToken',
131
303
  message: 'Jira API Token:',
304
+ mask: '*',
132
305
  validate: (input) => {
133
306
  if (!input.trim())
134
307
  return 'API Token is required';
@@ -138,29 +311,30 @@ async function runOnboarding() {
138
311
  ]);
139
312
  // Validate Jira credentials
140
313
  console.log('\nšŸ” Validating Jira credentials...');
141
- const jiraValid = await validators.validateJiraCredentials(jiraAnswers.baseUrl, jiraAnswers.apiToken, jiraAnswers.email || undefined);
314
+ const jiraValid = await validators.validateJiraCredentials(jiraAnswers.baseUrl, jiraAnswers.apiToken, undefined // No email for Bearer token
315
+ );
142
316
  if (!jiraValid) {
143
317
  console.error('āŒ Jira validation failed. Please check your credentials and try again.');
144
318
  process.exit(1);
145
319
  }
146
320
  console.log('āœ… Jira credentials validated!\n');
147
- // Step 3: Generate files
148
- console.log('šŸ“ Step 3: Generating configuration files...\n');
321
+ // Step 4: Generate files
322
+ console.log('šŸ“ Step 4: Generating configuration files...\n');
149
323
  await generators.generateFiles({
150
324
  github: {
151
325
  clientId: githubAnswers.clientId,
152
326
  clientSecret: githubAnswers.clientSecret,
153
- owner: githubAnswers.owner,
154
- repo: githubAnswers.repo
327
+ owner: owner,
328
+ repo: repo
155
329
  },
156
330
  jira: {
157
331
  baseUrl: jiraAnswers.baseUrl,
158
332
  apiToken: jiraAnswers.apiToken,
159
- email: jiraAnswers.email || undefined
333
+ email: undefined // Not used for Bearer token
160
334
  }
161
335
  });
162
- // Step 4: Integrate into project
163
- console.log('šŸ”§ Step 4: Integrating into PatternFly Seed project...\n');
336
+ // Step 5: Integrate into project
337
+ console.log('šŸ”§ Step 5: Integrating into PatternFly Seed project...\n');
164
338
  await generators.integrateIntoProject();
165
339
  console.log('\nāœ… Setup complete!');
166
340
  console.log('\nNext steps:');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hale-commenting-system",
3
- "version": "2.0.4",
3
+ "version": "2.1.0",
4
4
  "description": "Commenting system for PatternFly Seed projects with GitHub and Jira integration",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",