hale-commenting-system 2.0.3 → 2.0.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 (58) hide show
  1. package/README.md +16 -207
  2. package/bin/detect.d.ts +1 -0
  3. package/bin/detect.js +62 -0
  4. package/bin/generators.d.ts +18 -0
  5. package/bin/generators.js +193 -0
  6. package/bin/hale-commenting.js +4 -0
  7. package/bin/index.d.ts +2 -0
  8. package/bin/index.js +61 -0
  9. package/bin/onboarding.d.ts +1 -0
  10. package/bin/onboarding.js +170 -0
  11. package/bin/postinstall.d.ts +2 -0
  12. package/bin/postinstall.js +65 -0
  13. package/bin/validators.d.ts +2 -0
  14. package/bin/validators.js +66 -0
  15. package/dist/cli/detect.d.ts +1 -0
  16. package/dist/cli/detect.js +62 -0
  17. package/dist/cli/generators.d.ts +18 -0
  18. package/dist/cli/generators.js +193 -0
  19. package/dist/cli/index.d.ts +2 -0
  20. package/dist/cli/index.js +61 -0
  21. package/dist/cli/onboarding.d.ts +1 -0
  22. package/dist/cli/onboarding.js +170 -0
  23. package/dist/cli/postinstall.d.ts +2 -0
  24. package/dist/cli/postinstall.js +65 -0
  25. package/dist/cli/validators.d.ts +2 -0
  26. package/dist/cli/validators.js +66 -0
  27. package/dist/components/CommentOverlay.d.ts +2 -0
  28. package/dist/components/CommentOverlay.js +101 -0
  29. package/dist/components/CommentPanel.d.ts +6 -0
  30. package/dist/components/CommentPanel.js +334 -0
  31. package/dist/components/CommentPin.d.ts +11 -0
  32. package/dist/components/CommentPin.js +64 -0
  33. package/dist/components/DetailsTab.d.ts +2 -0
  34. package/dist/components/DetailsTab.js +380 -0
  35. package/dist/components/FloatingWidget.d.ts +8 -0
  36. package/dist/components/FloatingWidget.js +128 -0
  37. package/dist/components/JiraTab.d.ts +2 -0
  38. package/dist/components/JiraTab.js +507 -0
  39. package/dist/contexts/CommentContext.d.ts +30 -0
  40. package/dist/contexts/CommentContext.js +891 -0
  41. package/dist/contexts/GitHubAuthContext.d.ts +13 -0
  42. package/dist/contexts/GitHubAuthContext.js +96 -0
  43. package/dist/index.d.ts +10 -97
  44. package/dist/index.js +26 -786
  45. package/dist/services/githubAdapter.d.ts +56 -0
  46. package/dist/services/githubAdapter.js +321 -0
  47. package/dist/types/index.d.ts +25 -0
  48. package/dist/types/index.js +2 -0
  49. package/dist/utils/version.d.ts +1 -0
  50. package/dist/utils/version.js +23 -0
  51. package/package.json +39 -38
  52. package/templates/webpack-middleware.js +226 -0
  53. package/cli/dist/index.js +0 -370
  54. package/cli/dist/index.js.map +0 -1
  55. package/dist/index.d.mts +0 -97
  56. package/dist/index.js.map +0 -1
  57. package/dist/index.mjs +0 -759
  58. package/dist/index.mjs.map +0 -1
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.runOnboarding = runOnboarding;
40
+ const inquirer_1 = __importDefault(require("inquirer"));
41
+ const validators = __importStar(require("./validators"));
42
+ const generators = __importStar(require("./generators"));
43
+ 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');
50
+ const githubAnswers = await inquirer_1.default.prompt([
51
+ {
52
+ type: 'input',
53
+ name: 'clientId',
54
+ message: 'GitHub OAuth Client ID:',
55
+ validate: (input) => {
56
+ if (!input.trim())
57
+ return 'Client ID is required';
58
+ return true;
59
+ }
60
+ },
61
+ {
62
+ type: 'password',
63
+ name: 'clientSecret',
64
+ message: 'GitHub OAuth Client Secret:',
65
+ validate: (input) => {
66
+ if (!input.trim())
67
+ return 'Client Secret is required';
68
+ return true;
69
+ }
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
+ }
91
+ ]);
92
+ // Validate GitHub credentials
93
+ console.log('\n🔍 Validating GitHub credentials...');
94
+ const githubValid = await validators.validateGitHubCredentials(githubAnswers.clientId, githubAnswers.clientSecret, githubAnswers.owner, githubAnswers.repo);
95
+ if (!githubValid) {
96
+ console.error('❌ GitHub validation failed. Please check your credentials and try again.');
97
+ process.exit(1);
98
+ }
99
+ console.log('✅ GitHub credentials validated!\n');
100
+ // Step 2: Jira Setup
101
+ console.log('🎫 Step 2: Jira Setup\n');
102
+ console.log('For Red Hat Jira, generate a Personal Access Token from:');
103
+ console.log('https://issues.redhat.com/secure/ViewProfile.jspa\n');
104
+ const jiraAnswers = await inquirer_1.default.prompt([
105
+ {
106
+ type: 'input',
107
+ name: 'baseUrl',
108
+ message: 'Jira Base URL:',
109
+ default: 'https://issues.redhat.com',
110
+ validate: (input) => {
111
+ if (!input.trim())
112
+ return 'Base URL is required';
113
+ try {
114
+ new URL(input);
115
+ return true;
116
+ }
117
+ catch {
118
+ return 'Please enter a valid URL';
119
+ }
120
+ }
121
+ },
122
+ {
123
+ type: 'input',
124
+ name: 'email',
125
+ message: 'Jira Email (optional, leave blank if using Bearer token):',
126
+ default: ''
127
+ },
128
+ {
129
+ type: 'password',
130
+ name: 'apiToken',
131
+ message: 'Jira API Token:',
132
+ validate: (input) => {
133
+ if (!input.trim())
134
+ return 'API Token is required';
135
+ return true;
136
+ }
137
+ }
138
+ ]);
139
+ // Validate Jira credentials
140
+ console.log('\n🔍 Validating Jira credentials...');
141
+ const jiraValid = await validators.validateJiraCredentials(jiraAnswers.baseUrl, jiraAnswers.apiToken, jiraAnswers.email || undefined);
142
+ if (!jiraValid) {
143
+ console.error('❌ Jira validation failed. Please check your credentials and try again.');
144
+ process.exit(1);
145
+ }
146
+ console.log('✅ Jira credentials validated!\n');
147
+ // Step 3: Generate files
148
+ console.log('📝 Step 3: Generating configuration files...\n');
149
+ await generators.generateFiles({
150
+ github: {
151
+ clientId: githubAnswers.clientId,
152
+ clientSecret: githubAnswers.clientSecret,
153
+ owner: githubAnswers.owner,
154
+ repo: githubAnswers.repo
155
+ },
156
+ jira: {
157
+ baseUrl: jiraAnswers.baseUrl,
158
+ apiToken: jiraAnswers.apiToken,
159
+ email: jiraAnswers.email || undefined
160
+ }
161
+ });
162
+ // Step 4: Integrate into project
163
+ console.log('🔧 Step 4: Integrating into PatternFly Seed project...\n');
164
+ await generators.integrateIntoProject();
165
+ console.log('\n✅ Setup complete!');
166
+ console.log('\nNext steps:');
167
+ console.log('1. Review the generated .env and .env.server files');
168
+ console.log('2. Restart your dev server: npm run start:dev');
169
+ console.log('3. The commenting system will be available in your app!\n');
170
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const detect = __importStar(require("./detect"));
40
+ const onboarding = __importStar(require("./onboarding"));
41
+ async function main() {
42
+ const cwd = process.cwd();
43
+ const envPath = path.join(cwd, '.env');
44
+ // Check if already configured (has GitHub client ID in .env)
45
+ if (fs.existsSync(envPath)) {
46
+ const envContent = fs.readFileSync(envPath, 'utf-8');
47
+ if (envContent.includes('VITE_GITHUB_CLIENT_ID')) {
48
+ // Already configured, skip onboarding
49
+ return;
50
+ }
51
+ }
52
+ // Check if we're in a PatternFly Seed project
53
+ const isPFSeed = detect.detectPatternFlySeed();
54
+ if (!isPFSeed) {
55
+ // Not a PF Seed project, skip silently (might be installing in a different context)
56
+ return;
57
+ }
58
+ // Run onboarding
59
+ console.log('🚀 Hale Commenting System - First-time setup\n');
60
+ await onboarding.runOnboarding();
61
+ }
62
+ main().catch((error) => {
63
+ // Don't fail the install if onboarding has issues
64
+ console.error('⚠️ Onboarding error (non-fatal):', error.message);
65
+ });
@@ -0,0 +1,2 @@
1
+ export declare function validateGitHubCredentials(clientId: string, clientSecret: string, owner: string, repo: string): Promise<boolean>;
2
+ export declare function validateJiraCredentials(baseUrl: string, apiToken: string, email?: string): Promise<boolean>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.validateGitHubCredentials = validateGitHubCredentials;
7
+ exports.validateJiraCredentials = validateJiraCredentials;
8
+ const node_fetch_1 = __importDefault(require("node-fetch"));
9
+ async function validateGitHubCredentials(clientId, clientSecret, owner, repo) {
10
+ try {
11
+ // Test OAuth app credentials by attempting token exchange (we'll use a dummy code)
12
+ // Actually, we can't test OAuth without a real callback, so we'll just check repo access
13
+ // For a real validation, we'd need the user to complete OAuth flow, but for onboarding
14
+ // we'll just verify the repo exists and is accessible
15
+ const repoUrl = `https://api.github.com/repos/${owner}/${repo}`;
16
+ const response = await (0, node_fetch_1.default)(repoUrl, {
17
+ headers: {
18
+ 'Accept': 'application/vnd.github+json',
19
+ 'User-Agent': 'hale-commenting-system'
20
+ }
21
+ });
22
+ if (response.ok) {
23
+ return true;
24
+ }
25
+ if (response.status === 404) {
26
+ console.error(` Repository ${owner}/${repo} not found or not accessible`);
27
+ return false;
28
+ }
29
+ console.error(` GitHub API error: ${response.status}`);
30
+ return false;
31
+ }
32
+ catch (error) {
33
+ console.error(` Error validating GitHub: ${error.message}`);
34
+ return false;
35
+ }
36
+ }
37
+ async function validateJiraCredentials(baseUrl, apiToken, email) {
38
+ try {
39
+ const url = `${baseUrl.replace(/\/+$/, '')}/rest/api/2/myself`;
40
+ const authHeader = email
41
+ ? `Basic ${Buffer.from(`${email}:${apiToken}`).toString('base64')}`
42
+ : `Bearer ${apiToken}`;
43
+ const response = await (0, node_fetch_1.default)(url, {
44
+ headers: {
45
+ 'Accept': 'application/json',
46
+ 'Authorization': authHeader,
47
+ 'User-Agent': 'hale-commenting-system'
48
+ }
49
+ });
50
+ if (response.ok) {
51
+ const data = await response.json();
52
+ console.log(` ✅ Authenticated as: ${data.displayName || data.name || 'User'}`);
53
+ return true;
54
+ }
55
+ if (response.status === 401 || response.status === 403) {
56
+ console.error(` Authentication failed. Check your token and email (if required).`);
57
+ return false;
58
+ }
59
+ console.error(` Jira API error: ${response.status}`);
60
+ return false;
61
+ }
62
+ catch (error) {
63
+ console.error(` Error validating Jira: ${error.message}`);
64
+ return false;
65
+ }
66
+ }
@@ -0,0 +1 @@
1
+ export declare function detectPatternFlySeed(): boolean;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.detectPatternFlySeed = detectPatternFlySeed;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ function detectPatternFlySeed() {
40
+ const cwd = process.cwd();
41
+ // Check for webpack config files
42
+ const hasWebpack = fs.existsSync(path.join(cwd, 'webpack.config.js')) ||
43
+ fs.existsSync(path.join(cwd, 'webpack.dev.js')) ||
44
+ fs.existsSync(path.join(cwd, 'webpack.common.js'));
45
+ // Check for src/app directory
46
+ const hasAppDir = fs.existsSync(path.join(cwd, 'src', 'app'));
47
+ // Check for PatternFly dependencies in package.json
48
+ let hasPatternFly = false;
49
+ try {
50
+ const packageJsonPath = path.join(cwd, 'package.json');
51
+ if (fs.existsSync(packageJsonPath)) {
52
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
53
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
54
+ hasPatternFly = !!(deps['@patternfly/react-core'] ||
55
+ deps['@patternfly/react-icons']);
56
+ }
57
+ }
58
+ catch {
59
+ // Ignore errors
60
+ }
61
+ return hasWebpack && hasAppDir && hasPatternFly;
62
+ }
@@ -0,0 +1,18 @@
1
+ interface GitHubConfig {
2
+ clientId: string;
3
+ clientSecret: string;
4
+ owner: string;
5
+ repo: string;
6
+ }
7
+ interface JiraConfig {
8
+ baseUrl: string;
9
+ apiToken: string;
10
+ email?: string;
11
+ }
12
+ interface Config {
13
+ github: GitHubConfig;
14
+ jira: JiraConfig;
15
+ }
16
+ export declare function generateFiles(config: Config): Promise<void>;
17
+ export declare function integrateIntoProject(): Promise<void>;
18
+ export {};
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.generateFiles = generateFiles;
37
+ exports.integrateIntoProject = integrateIntoProject;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ async function generateFiles(config) {
41
+ const cwd = process.cwd();
42
+ // Generate .env file (client-safe)
43
+ const envPath = path.join(cwd, '.env');
44
+ const envContent = `# GitHub OAuth (client-side; safe to expose)
45
+ VITE_GITHUB_CLIENT_ID=${config.github.clientId}
46
+
47
+ # Target repo for Issues/Comments
48
+ VITE_GITHUB_OWNER=${config.github.owner}
49
+ VITE_GITHUB_REPO=${config.github.repo}
50
+
51
+ # Jira Base URL
52
+ VITE_JIRA_BASE_URL=${config.jira.baseUrl}
53
+ `;
54
+ // Check if .env exists and append or create
55
+ if (fs.existsSync(envPath)) {
56
+ const existing = fs.readFileSync(envPath, 'utf-8');
57
+ // Only add if not already present
58
+ if (!existing.includes('VITE_GITHUB_CLIENT_ID')) {
59
+ fs.appendFileSync(envPath, '\n' + envContent);
60
+ console.log(' ✅ Updated .env file');
61
+ }
62
+ else {
63
+ console.log(' ⚠️ .env already contains commenting system config');
64
+ }
65
+ }
66
+ else {
67
+ fs.writeFileSync(envPath, envContent);
68
+ console.log(' ✅ Created .env file');
69
+ }
70
+ // Generate .env.server file (secrets)
71
+ const envServerPath = path.join(cwd, '.env.server');
72
+ let envServerContent = `# GitHub OAuth Client Secret (server-only)
73
+ GITHUB_CLIENT_SECRET=${config.github.clientSecret}
74
+
75
+ # Jira API Token (server-only)
76
+ JIRA_API_TOKEN=${config.jira.apiToken}
77
+ `;
78
+ if (config.jira.email) {
79
+ envServerContent += `JIRA_EMAIL=${config.jira.email}\n`;
80
+ }
81
+ if (fs.existsSync(envServerPath)) {
82
+ const existing = fs.readFileSync(envServerPath, 'utf-8');
83
+ if (!existing.includes('GITHUB_CLIENT_SECRET')) {
84
+ fs.appendFileSync(envServerPath, '\n' + envServerContent);
85
+ console.log(' ✅ Updated .env.server file');
86
+ }
87
+ else {
88
+ console.log(' ⚠️ .env.server already contains commenting system config');
89
+ }
90
+ }
91
+ else {
92
+ fs.writeFileSync(envServerPath, envServerContent);
93
+ console.log(' ✅ Created .env.server file');
94
+ }
95
+ // Ensure .env.server is in .gitignore
96
+ const gitignorePath = path.join(cwd, '.gitignore');
97
+ if (fs.existsSync(gitignorePath)) {
98
+ const gitignore = fs.readFileSync(gitignorePath, 'utf-8');
99
+ if (!gitignore.includes('.env.server')) {
100
+ fs.appendFileSync(gitignorePath, '\n.env.server\n');
101
+ console.log(' ✅ Added .env.server to .gitignore');
102
+ }
103
+ }
104
+ else {
105
+ fs.writeFileSync(gitignorePath, '.env.server\n');
106
+ console.log(' ✅ Created .gitignore with .env.server');
107
+ }
108
+ }
109
+ async function integrateIntoProject() {
110
+ const cwd = process.cwd();
111
+ const webpackDevPath = path.join(cwd, 'webpack.dev.js');
112
+ if (!fs.existsSync(webpackDevPath)) {
113
+ console.error(' ❌ webpack.dev.js not found. Cannot auto-integrate.');
114
+ return;
115
+ }
116
+ // Read webpack.dev.js
117
+ let webpackContent = fs.readFileSync(webpackDevPath, 'utf-8');
118
+ // Check if already integrated
119
+ if (webpackContent.includes('/api/github-oauth-callback') || webpackContent.includes('/api/jira-issue')) {
120
+ console.log(' ⚠️ webpack.dev.js already appears to have commenting system integration');
121
+ return;
122
+ }
123
+ // Read the template
124
+ // In compiled output, templates will be in the package root
125
+ const packageRoot = path.resolve(__dirname, '../../..');
126
+ const templatePath = path.join(packageRoot, 'templates', 'webpack-middleware.js');
127
+ if (!fs.existsSync(templatePath)) {
128
+ console.log(' ⚠️ Template file not found. Manual integration required.');
129
+ console.log(' See README for webpack.dev.js integration instructions.\n');
130
+ return;
131
+ }
132
+ const templateContent = fs.readFileSync(templatePath, 'utf-8');
133
+ // Find the setupMiddlewares function and inject our code
134
+ // Look for: setupMiddlewares: (middlewares, devServer) => {
135
+ const setupMiddlewaresRegex = /(setupMiddlewares\s*:\s*\([^)]+\)\s*=>\s*\{)/;
136
+ const match = webpackContent.match(setupMiddlewaresRegex);
137
+ if (!match) {
138
+ console.log(' ⚠️ Could not find setupMiddlewares in webpack.dev.js');
139
+ console.log(' 📋 Manual integration required. See templates/webpack-middleware.js\n');
140
+ return;
141
+ }
142
+ // Find where to inject (after express.json() setup, before return middlewares)
143
+ const expressJsonMatch = webpackContent.match(/devServer\.app\.use\(express\.json\(\)\);/);
144
+ if (expressJsonMatch) {
145
+ // Inject after express.json()
146
+ const insertIndex = expressJsonMatch.index + expressJsonMatch[0].length;
147
+ const before = webpackContent.substring(0, insertIndex);
148
+ const after = webpackContent.substring(insertIndex);
149
+ // Extract just the middleware code from template (skip comments)
150
+ const middlewareCode = templateContent
151
+ .replace(/^\/\/.*$/gm, '') // Remove comment lines
152
+ .trim()
153
+ .split('\n')
154
+ .filter(line => line.trim() && !line.trim().startsWith('//'))
155
+ .join('\n');
156
+ webpackContent = before + '\n\n' + middlewareCode + '\n' + after;
157
+ fs.writeFileSync(webpackDevPath, webpackContent);
158
+ console.log(' ✅ Updated webpack.dev.js with server middleware');
159
+ }
160
+ else {
161
+ // Try to inject at the beginning of setupMiddlewares
162
+ const insertIndex = match.index + match[0].length;
163
+ const before = webpackContent.substring(0, insertIndex);
164
+ const after = webpackContent.substring(insertIndex);
165
+ // Add dotenv loading and express setup if not present
166
+ let middlewareCode = templateContent.trim();
167
+ // Check if dotenv is already loaded
168
+ if (!webpackContent.includes('dotenv.config')) {
169
+ middlewareCode = `// Load env vars for local OAuth/token exchange
170
+ try {
171
+ const dotenv = require('dotenv');
172
+ dotenv.config({ path: path.resolve(__dirname, '.env') });
173
+ dotenv.config({ path: path.resolve(__dirname, '.env.server'), override: true });
174
+ } catch (e) {
175
+ // no-op
176
+ }
177
+
178
+ const express = require('express');
179
+ devServer.app.use(express.json());
180
+
181
+ ` + middlewareCode;
182
+ }
183
+ else if (!webpackContent.includes('express.json()')) {
184
+ middlewareCode = `const express = require('express');
185
+ devServer.app.use(express.json());
186
+
187
+ ` + middlewareCode;
188
+ }
189
+ webpackContent = before + '\n\n' + middlewareCode + '\n' + after;
190
+ fs.writeFileSync(webpackDevPath, webpackContent);
191
+ console.log(' ✅ Updated webpack.dev.js with server middleware');
192
+ }
193
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const detect = __importStar(require("./detect"));
38
+ const onboarding = __importStar(require("./onboarding"));
39
+ const args = process.argv.slice(2);
40
+ const command = args[0] || 'init';
41
+ async function main() {
42
+ if (command === 'init') {
43
+ // Check if we're in a PatternFly Seed project
44
+ const isPFSeed = detect.detectPatternFlySeed();
45
+ if (!isPFSeed) {
46
+ console.error('❌ Error: This package is designed for PatternFly Seed projects.');
47
+ console.error('Please run this command from a PatternFly Seed project directory.');
48
+ process.exit(1);
49
+ }
50
+ console.log('🚀 Hale Commenting System - Onboarding\n');
51
+ await onboarding.runOnboarding();
52
+ }
53
+ else {
54
+ console.log('Usage: hale-commenting-system [init]');
55
+ process.exit(1);
56
+ }
57
+ }
58
+ main().catch((error) => {
59
+ console.error('❌ Error:', error.message);
60
+ process.exit(1);
61
+ });
@@ -0,0 +1 @@
1
+ export declare function runOnboarding(): Promise<void>;