jira-pat 1.0.0 → 1.0.2

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,31 @@
1
+ name: Publish to NPM
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ # Optional: Also run on manual trigger
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ publish:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Setup Node.js
17
+ uses: actions/setup-node@v4
18
+ with:
19
+ node-version: '22'
20
+ registry-url: 'https://registry.npmjs.org'
21
+
22
+ - name: Install dependencies
23
+ run: npm install
24
+
25
+ - name: Run Tests
26
+ run: npm test
27
+
28
+ - name: Publish to NPM
29
+ run: npm publish
30
+ env:
31
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/AGENTS.md CHANGED
@@ -1,91 +1,124 @@
1
1
  # AGENTS.md - Jira Dashboard
2
2
 
3
+ ## Project Overview
4
+
5
+ A Jira Dashboard CLI tool with Express backend (port 5000) and React frontend (port 5173).
6
+
3
7
  ## Project Structure
4
8
 
5
9
  ```
6
10
  jira-dashboard/
7
- ├── package.json # Root - runs both servers with concurrently
8
- ├── backend/ # Express API (CommonJS), port 5000
9
- ├── index.js # Entry point
10
- ├── routes/ # API route handlers
11
- └── service/ # Jira API integration (axios + node-cache)
12
- └── frontend/ # React app (ES modules + Vite), port 5173
13
- ├── src/
14
- ├── App.jsx # Main component (~400 lines)
15
- │ ├── index.css # All styles (~1700 lines)
16
- │ ├── services/ # API client (axios)
17
- ├── components/ # React components
18
- │ │ ├── IssueDrawer.jsx
19
- │ │ ├── CreateIssueModal.jsx
20
- │ │ ├── IssueTable.jsx
21
- │ │ ├── StandaloneIssuePage.jsx
22
- │ │ └── ToastContainer.jsx
23
- │ └── hooks/ # Custom React hooks
24
- │ ├── useIssueDrawer.js
25
- │ ├── useToasts.js
26
- │ └── useIssuesList.js
27
- └── vite.config.js
11
+ ├── package.json # Root - runs both servers with concurrently
12
+ ├── bin/
13
+ └── jira.js # CLI entry point for `jira` command
14
+ ├── backend/ # Express API (CommonJS), port 5000
15
+ ├── index.js # Entry point
16
+ │ ├── routes/ # API route handlers (issues.js, projects.js)
17
+ ├── service/ # Jira API integration (jiraService.js)
18
+ └── __tests__/ # Jest tests
19
+ └── frontend/ # React app (ES modules + Vite)
20
+ └── src/
21
+ ├── App.jsx # Main component
22
+ ├── index.css # All styles (~2500 lines)
23
+ ├── services/ # API client (api.js)
24
+ ├── components/ # React components
25
+ ├── hooks/ # Custom React hooks
26
+ └── utils/ # Helper functions
28
27
  ```
29
28
 
30
29
  ## Commands
31
30
 
31
+ ### Development
32
32
  ```bash
33
- # Root - runs both servers
34
- npm start
35
-
36
- # Frontend
37
- cd frontend && npm run dev # Dev server (port 5173)
38
- cd frontend && npm run build # Production build
39
- cd frontend && npm run preview # Preview build
40
-
41
- # Backend
42
- cd backend && npm start # Start server (port 5000)
33
+ npm start # Run both backend and frontend concurrently
34
+ npm run build # Build frontend for production
35
+ cd frontend && npm run dev # Frontend dev server only (port 5173)
36
+ cd backend && npm start # Backend server only (port 5000)
43
37
  ```
44
38
 
45
- ## Environment Setup
39
+ ### Testing
46
40
 
47
- Create `/backend/.env`:
48
- ```
49
- JIRA_BASE_URL=https://your-domain.atlassian.net
50
- JIRA_EMAIL=your-email@example.com
51
- JIRA_PAT=your-api-token
52
- PORT=5000
53
- BACKEND_BASE_URL=http://localhost:5000
41
+ **Root (runs both):**
42
+ ```bash
43
+ npm test # Run all tests
54
44
  ```
55
45
 
56
- Create `/frontend/.env` (optional):
46
+ **Backend (Jest):**
47
+ ```bash
48
+ cd backend && npm test # Watch mode
49
+ cd backend && npm test -- --coverage # With coverage
50
+ cd backend && npm test -- --testPathPattern=routes/issues.test.js # Single file
51
+ cd backend && npm test -- --testNamePattern=create # Tests matching name
52
+ cd backend && npm test -- --watchAll=false # Single run, no watch
57
53
  ```
58
- VITE_API_BASE_URL=http://localhost:5000/api
54
+
55
+ **Frontend (Vitest):**
56
+ ```bash
57
+ cd frontend && npm test # Watch mode
58
+ cd frontend && npm run test:run # Single run (CI mode)
59
+ cd frontend && npm test -- src/services/api.test.js # Single file
60
+ cd frontend && npm test -- --grep "should render" # Pattern match
61
+ cd frontend && npm test -- --coverage # With coverage
59
62
  ```
60
63
 
61
- ## Code Style
64
+ ---
65
+
66
+ ## Code Style Guidelines
62
67
 
63
- ### General
68
+ ### General Principles
64
69
  - No comments unless explaining non-obvious logic
65
70
  - Small, focused functions (single responsibility)
66
71
  - Prefer early returns to reduce nesting
67
- - 4-space indentation (backend), standard formatting (frontend)
68
-
69
- ### Frontend (React + Vite - ES Modules)
70
- - `.jsx` for React components, `.js` for utilities
71
- - Named exports for utilities, default export for components
72
- - Functional components with hooks only (no class components)
73
- - Import order: React → external libs → internal modules → CSS
72
+ - Prefer composition over prop drilling
73
+ - Memoize expensive computations with `useMemo`/`React.memo`
74
74
 
75
+ ### Import Order (Frontend)
75
76
  ```jsx
76
77
  import React, { useState, useEffect } from 'react';
77
78
  import { Search, X } from 'lucide-react';
78
79
  import { getIssues } from './services/api';
80
+ import { formatDate } from './utils/helpers';
79
81
  import './index.css';
80
82
  ```
81
83
 
82
- ### Backend (Node.js - CommonJS)
83
- - Use `require()` and `module.exports`
84
+ ### React Components
85
+ - Use `.jsx` extension for components, `.js` for utilities
86
+ - Default export for components, named exports for utilities
87
+ - Functional components with hooks only (no class components)
88
+ - Destructure props in function signature
89
+
90
+ ```jsx
91
+ // Good
92
+ export default function IssueTable({ issues, onRowClick, loading }) {
93
+ return <table>...</table>;
94
+ }
95
+
96
+ // Good - hook pattern
97
+ const [data, setData] = useState(null);
98
+ const isLoading = useMemo(() => expensiveCalculation(data), [data]);
99
+ ```
100
+
101
+ ### Backend (Node.js)
102
+ - CommonJS: `require()` and `module.exports`
84
103
  - Keep routes thin, services thick
104
+ - Always validate input before processing
105
+ - Return appropriate HTTP status codes
85
106
 
86
107
  ```javascript
87
108
  const express = require('express');
88
109
  const router = express.Router();
110
+
111
+ router.get('/:id', async (req, res) => {
112
+ try {
113
+ const data = await service.getData(req.params.id);
114
+ if (!data) return res.status(404).json({ error: 'Not found' });
115
+ res.json(data);
116
+ } catch (error) {
117
+ console.error('Error:', error.message);
118
+ res.status(500).json({ error: 'Server error', details: error.message });
119
+ }
120
+ });
121
+
89
122
  module.exports = router;
90
123
  ```
91
124
 
@@ -94,23 +127,27 @@ module.exports = router;
94
127
  | Type | Convention | Example |
95
128
  |------|------------|---------|
96
129
  | Components | PascalCase | `IssueDrawer` |
130
+ | Hooks | camelCase `useXxx` | `useIssueDrawer` |
131
+ | State setters | `setXxx` | `setIssues` |
97
132
  | Functions | camelCase | `fetchIssues` |
98
133
  | Constants | UPPER_SNAKE | `STATUS_CHIPS` |
99
- | CSS Classes | kebab-case | `.issue-table` |
134
+ | CSS classes | kebab-case | `.issue-table` |
100
135
  | Files | kebab-case | `api-client.js` |
101
- | React state | `useXxx`, `setXxx` | `issues`, `setIssues` |
136
+ | Files (components) | PascalCase | `IssueDrawer.jsx` |
137
+
138
+ ---
102
139
 
103
140
  ## Common Patterns
104
141
 
105
142
  ### Debounce (search inputs)
106
143
  ```jsx
107
144
  useEffect(() => {
108
- const timer = setTimeout(() => fetchData(), 500);
145
+ const timer = setTimeout(() => fetchData(searchQuery), 500);
109
146
  return () => clearTimeout(timer);
110
147
  }, [searchQuery]);
111
148
  ```
112
149
 
113
- ### Async with Loading/Error
150
+ ### Async with Loading/Error State
114
151
  ```jsx
115
152
  const [loading, setLoading] = useState(false);
116
153
  const [error, setError] = useState(null);
@@ -143,8 +180,8 @@ const addToast = (message, type = 'info') => {
143
180
  ```jsx
144
181
  useEffect(() => {
145
182
  const handleKeyDown = (e) => {
146
- if (e.key === '/' && !['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)) {
147
- e.preventDefault();
183
+ if (e.key === 'Escape' && !['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)) {
184
+ onClose();
148
185
  }
149
186
  };
150
187
  window.addEventListener('keydown', handleKeyDown);
@@ -152,67 +189,121 @@ useEffect(() => {
152
189
  }, []);
153
190
  ```
154
191
 
155
- ## Error Handling
192
+ ---
156
193
 
157
- ### Backend API Routes
158
- ```javascript
159
- router.get('/:id', async (req, res) => {
160
- try {
161
- const data = await service.getData(req.params.id);
162
- if (!data) return res.status(404).json({ error: 'Not found' });
163
- res.json(data);
164
- } catch (error) {
165
- console.error('Error:', error.message);
166
- res.status(500).json({ error: 'Server error', details: error.message });
167
- }
168
- });
169
- ```
194
+ ## Accessibility (A11y)
170
195
 
171
- ### Frontend
172
- ```jsx
173
- {error && (
174
- <div className="error" role="alert">
175
- <AlertCircle size={16} />
176
- {error}
177
- </div>
178
- )}
179
- ```
180
-
181
- ## Accessibility
182
- - Always use `aria-label` on icon-only buttons
183
- - Use semantic HTML (`<button>`, `<nav>`, `<main>`)
196
+ - Always add `aria-label` to icon-only buttons
197
+ - Use semantic HTML: `<button>`, `<nav>`, `<main>`, `<article>`
198
+ - Add `role="alert"` for error messages
184
199
  - Support keyboard navigation (Tab, Enter, Escape, Arrow keys)
200
+ - Add `aria-sort="none/ascending/descending"` to sortable table headers
201
+ - Add `scope="col"` to table headers
202
+ - Wrap pagination in `<nav aria-label="Pagination">`
185
203
 
186
204
  ```jsx
187
205
  <button onClick={handleDelete} aria-label="Delete item">
188
206
  <TrashIcon size={16} />
189
207
  </button>
208
+
209
+ <nav aria-label="Pagination">
210
+ <button aria-label="Previous page">Prev</button>
211
+ </nav>
190
212
  ```
191
213
 
214
+ ---
215
+
192
216
  ## CSS Guidelines
193
- - Use CSS custom properties (variables) for colors, spacing
217
+
218
+ - Use CSS custom properties (variables) for all colors, spacing, shadows
194
219
  - BEM-inspired naming for component styles
195
220
  - Avoid inline styles except for dynamic values
221
+ - Group related styles together
222
+ - Use `rem` for sizing, `px` for borders
196
223
 
197
224
  ```css
198
225
  :root {
199
226
  --primary: #0052cc;
227
+ --primary-light: rgba(0, 82, 204, 0.1);
200
228
  --spacing-sm: 8px;
201
229
  --spacing-md: 16px;
230
+ --radius-md: 4px;
231
+ --transition-fast: 150ms ease;
202
232
  }
203
233
 
204
- .button { padding: var(--spacing-sm) var(--spacing-md); }
205
- .button--loading { opacity: 0.7; }
234
+ .issue-table { /* Block */ }
235
+ .issue-table__row { /* Element */ }
236
+ .issue-table__row--active { /* Modifier */ }
237
+ ```
238
+
239
+ ---
240
+
241
+ ## API Design (Backend)
242
+
243
+ ### Response Format
244
+ - Success: `res.json(data)` or `res.status(201).json(data)`
245
+ - Error: `res.status(code).json({ error: 'message', details: error.message })`
246
+
247
+ ### Validation
248
+ - Always validate input with regex or type checking
249
+ - Sanitize JQL queries to prevent injection
250
+ - Limit mutation operations with rate limiting
251
+
252
+ ---
253
+
254
+ ## Testing Guidelines
255
+
256
+ ### Backend (Jest + Supertest)
257
+ - Test file location: `__tests__/filename.test.js`
258
+ - Mock external services (axios calls)
259
+ - Use descriptive test names: `it('should return 404 when issue not found')`
260
+
261
+ ### Frontend (Vitest + Testing Library)
262
+ - Test file location: `src/__tests__/path/to/file.test.jsx`
263
+ - Test behavior, not implementation
264
+ - Use `screen.getByRole`, `screen.getByText` for queries
265
+ - Mock API calls with `vi.fn()` and `mockResolvedValue`
266
+
267
+ ```jsx
268
+ it('should call onRowClick when row is clicked', async () => {
269
+ render(<IssueTable issues={mockIssues} onRowClick={mockFn} />);
270
+ fireEvent.click(screen.getByText('TEST-1'));
271
+ expect(mockFn).toHaveBeenCalledWith('TEST-1');
272
+ });
206
273
  ```
207
274
 
275
+ ---
276
+
277
+ ## Environment Variables
278
+
279
+ ### Backend (`backend/.env`)
280
+ ```
281
+ JIRA_BASE_URL=https://your-domain.atlassian.net
282
+ JIRA_EMAIL=your-email@example.com
283
+ JIRA_PAT=your-api-token
284
+ PORT=5000
285
+ BACKEND_BASE_URL=http://localhost:5000
286
+ ```
287
+
288
+ ### Frontend (`frontend/.env`)
289
+ ```
290
+ VITE_API_BASE_URL=http://localhost:5000/api
291
+ ```
292
+
293
+ ---
294
+
208
295
  ## Jira API Integration
296
+
209
297
  - Uses axios with 10-second timeout
210
298
  - 60-second in-memory cache (node-cache)
211
299
  - Basic Auth with Jira PAT for authentication
212
- - Uses JQL for searching issues
300
+ - Jira Cloud API v3 endpoints
301
+ - ADF (Atlassian Document Format) for rich text
213
302
 
214
303
  ## Security
304
+
215
305
  - Never commit `.env` files (in `.gitignore`)
216
306
  - API credentials use Basic Auth with Jira PAT
217
- - File uploads limited to 10MB
218
- - Input validation on all API endpoints
307
+ - File uploads limited to 10MB (multer configuration)
308
+ - Rate limiting on mutation endpoints
309
+ - Input validation and sanitization on all API endpoints
package/README.md CHANGED
@@ -2,25 +2,115 @@
2
2
 
3
3
  A fast, lightweight, and modern Jira Dashboard built with React, Vite, and Node.js. It avoids CORS and proxy issues by connecting directly to the Jira Cloud API using Basic Authentication within a dedicated Express backend.
4
4
 
5
- ## Features Currently Supported
6
-
7
- 1. **Direct Jira Cloud Integration**: Uses your Atlassian Email and API Token securely to fetch real-time Jira data.
8
- 2. **"My Assigned Issues" View**: By default, the API automatically fetches tickets currently assigned to you (`currentUser()`).
9
- 3. **Dynamic Filtering**:
10
- - Filter by **Project Key** (e.g. `ABC`)
11
- - Search by **Summary / Text** content
12
- - Filter by **Ticket Status** (To Do, In Progress, Done, Closed)
13
- 4. **Interactive Side Drawer**: Click an issue row to load real-time deep-dive details.
14
- - **Rich Media & Comments**: Renders descriptions and comments with inline images seamlessly proxied securely from Jira.
15
- - **Subtasks & Linked Issues**: Visual hierarchy mapping of attached Jira issues, enabling clickable exploration.
16
- - **Issue Transitions**: Update ticket stages (e.g., "To Do" -> "In Progress") directly within the app.
17
- - **Ticket Assignment**: Searchable user dropdown directly mapped to your active Jira user directory.
18
- - **File Attachments**: One-click upload functionality for files mapped directly onto tickets.
19
- 5. **Create New Issues**: Global "+" action triggering dynamic Issue schemas directly synced from Jira projects.
20
- 6. **Fast, Modern UI**: Refactored with `lucide-react` icons, toast notifications, and animated skeleton loaders.
21
- 7. **Keyboard Navigation**: Press `/` to focus search, `Enter` to open an issue, and `Esc` to close modals.
22
- 8. **Backend Caching & Proxying**: 60-second in-memory caching via `node-cache` bypassing CORS/Auth blocks.
23
- 9. **Single Command Start**: Run both the React frontend and Node backend simultaneously using `npm start`.
5
+ ## Features
6
+
7
+ 1. **Direct Jira Cloud Integration**: Connects to the Jira REST API securely via an Express backend.
8
+ 2. **CLI Configuration**: Easy setup with the built-in `jira` CLI tool.
9
+ 3. **Dynamic Filtering**: Filter by project, status, or keyword.
10
+ 4. **Interactive Issue View**:
11
+ - Full issue details in a side drawer or standalone page.
12
+ - Rich text rendering (Markdown/ADF to HTML).
13
+ - Proxying of Jira-hosted images and attachments.
14
+ - Status transitions and user assignment.
15
+ - File uploads directly to Jira tickets.
16
+ 5. **Subtasks & Linked Issues**: Visualize and navigate between related tickets.
17
+ 6. **Backend Caching**: 60-second in-memory caching for performance and API rate-limiting compliance.
18
+ 7. **Fully Tested**: Comprehensive unit and integration tests for both frontend and backend.
19
+ 8. **Error Handling**: Robust error boundaries and toast notifications for a smooth experience.
20
+
21
+ ---
22
+
23
+ ## Getting Started
24
+
25
+ ### Prerequisites
26
+
27
+ - Node.js (v18 or higher recommended)
28
+ - An Atlassian account with a Jira Cloud instance
29
+ - A Jira API Token ([Get one here](https://id.atlassian.com/manage-profile/security/api-tokens))
30
+
31
+ ### Installation & Setup
32
+
33
+ 1. **Download & Install**:
34
+ ```bash
35
+ git clone https://github.com/yourusername/jira-dashboard.git
36
+ cd jira-dashboard
37
+ npm install
38
+ ```
39
+
40
+ 2. **Configure your Account**:
41
+ Run the setup tool to connect your Jira account:
42
+ ```bash
43
+ npm link # Optional: allows you to just type 'jira'
44
+ jira config
45
+ ```
46
+ Follow the prompts to enter your **Jira URL**, **Email**, and **API Token**.
47
+
48
+ 3. **Launch the App**:
49
+ ```bash
50
+ npm start
51
+ ```
52
+ Your browser should automatically open to `http://localhost:5000`.
53
+
54
+ ---
55
+
56
+ ## Using the Dashboard (User Guide)
57
+
58
+ Once the dashboard is open, here is how you can manage your work:
59
+
60
+ ### 1. Finding Your Work
61
+ * **Default View**: When you log in, you will see all issues currently assigned to you.
62
+ * **Search**: Use the search bar at the top to find specific tickets by typing their title or description. (Tip: Press `/` to jump to search).
63
+ * **Filters**: Use the **Project** and **Status** dropdowns to narrow down your list (e.g., only show "In Progress" tasks for project "ABC").
64
+
65
+ ### 2. Viewing and Updating Issues
66
+ * **Open Details**: Click on any row in the table. A side panel will slide out with the full description and comments.
67
+ * **Change Status**: Inside the panel, click the status button (like "To Do") to move the ticket to a new stage (like "Done").
68
+ * **Reassign**: Click the user's name or avatar to search for and assign the ticket to someone else.
69
+ * **Add Attachments**: Drag and drop files directly onto the "Upload" area in the side panel to add them to the Jira ticket.
70
+
71
+ ### 3. Creating New Issues
72
+ * Click the blue **+** button in the top right corner.
73
+ * Select the **Project** and **Issue Type** (e.g., Task, Bug).
74
+ * Enter a **Summary** and click **Create**. The ticket is instantly added to your Jira instance.
75
+
76
+ ---
77
+
78
+ ## Development (Technical)
79
+
80
+ ### Running the Backend (API)
81
+ ```bash
82
+ cd backend
83
+ npm start
84
+ ```
85
+ The API runs on `http://localhost:5000`.
86
+
87
+ ### Running the Frontend (Vite)
88
+ ```bash
89
+ cd frontend
90
+ npm run dev
91
+ ```
92
+ The frontend runs on `http://localhost:5173` (proxies `/api` to port 5000).
93
+
94
+ ---
95
+
96
+ ## Testing
97
+
98
+ ### Run All Tests
99
+ ```bash
100
+ npm test
101
+ ```
102
+
103
+ ### Backend Tests
104
+ ```bash
105
+ cd backend
106
+ npm test
107
+ ```
108
+
109
+ ### Frontend Tests
110
+ ```bash
111
+ cd frontend
112
+ npm test
113
+ ```
24
114
 
25
115
  ---
26
116
 
@@ -28,37 +118,21 @@ A fast, lightweight, and modern Jira Dashboard built with React, Vite, and Node.
28
118
 
29
119
  ```
30
120
  jira-dashboard/
31
- ├── package.json # Root configuration for concurrently running both servers
32
- ├── README.md # This file
33
-
121
+ ├── bin/ # CLI setup and start scripts
34
122
  ├── backend/ # Node.js + Express API Layer
35
- │ ├── .env # Secrets (JIRA_BASE_URL, JIRA_EMAIL, JIRA_PAT)
36
- │ ├── index.js # Main Express server and configuration
37
- ├── package.json # Backend dependencies (express, axios, cors)
38
- │ ├── routes/
39
- │ │ └── issues.js # Route logic for /api/issues
40
- │ └── service/
41
- │ └── jiraService.js# Jira REST API communication & JQL construction
123
+ │ ├── routes/ # API Endpoints (Issues, Projects)
124
+ │ ├── service/ # Jira API integration logic
125
+ └── __tests__/ # Backend test suite
42
126
 
43
127
  └── frontend/ # React + Vite UI
44
- ├── package.json # Frontend dependencies (react, lucide-react)
45
- ├── vite.config.js # Vite configuration
46
- ├── index.html # App entry HTML
47
- └── src/
48
- ├── main.jsx # React DOM entry point
49
- ├── App.jsx # Main Dashboard View and Filters
50
- ├── index.css # Clean, modern UI Styling
51
- └── services/
52
- └── api.js # Axios client connecting to backend /api/issues
128
+ ├── src/
129
+ ├── components/ # React components (Table, Drawer, Modals)
130
+ ├── hooks/ # Custom React hooks (Data fetching, UI state)
131
+ └── __tests__/ # Frontend test suite
53
132
  ```
54
133
 
55
134
  ---
56
135
 
57
- ## How To Run
136
+ ## License
58
137
 
59
- 1. Open `/backend/.env` and ensure your `JIRA_BASE_URL`, `JIRA_EMAIL`, and `JIRA_PAT` (Atlassian API Token) are filled in.
60
- 2. Run the application from the root directory:
61
- ```bash
62
- npm start
63
- ```
64
- 3. Open your browser to `http://localhost:5173`.
138
+ ISC