confluence-cli 1.18.0 → 1.19.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.
@@ -31,8 +31,9 @@ jobs:
31
31
  runs-on: ubuntu-latest
32
32
  steps:
33
33
  - uses: actions/checkout@v3
34
- - name: Run npm audit
35
- run: npm audit --audit-level moderate
34
+ - run: npm ci
35
+ - name: Run npm audit (production only)
36
+ run: npm audit --audit-level moderate --omit=dev
36
37
 
37
38
  publish:
38
39
  needs: [test, security]
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [1.19.0](https://github.com/pchuri/confluence-cli/compare/v1.18.0...v1.19.0) (2026-02-20)
2
+
3
+
4
+ ### Features
5
+
6
+ * add --cql flag to search command for raw CQL queries ([#40](https://github.com/pchuri/confluence-cli/issues/40)) ([311f5a9](https://github.com/pchuri/confluence-cli/commit/311f5a98bfd175c6b7902c55b4dd0687b2a0d8c0)), closes [#39](https://github.com/pchuri/confluence-cli/issues/39)
7
+
1
8
  # [1.18.0](https://github.com/pchuri/confluence-cli/compare/v1.17.0...v1.18.0) (2026-02-15)
2
9
 
3
10
 
package/bin/confluence.js CHANGED
@@ -75,11 +75,12 @@ program
75
75
  .command('search <query>')
76
76
  .description('Search for Confluence pages')
77
77
  .option('-l, --limit <limit>', 'Limit number of results', '10')
78
+ .option('--cql', 'Pass query as raw CQL instead of text search')
78
79
  .action(async (query, options) => {
79
80
  const analytics = new Analytics();
80
81
  try {
81
82
  const client = new ConfluenceClient(getConfig());
82
- const results = await client.search(query, parseInt(options.limit));
83
+ const results = await client.search(query, parseInt(options.limit), options.cql);
83
84
 
84
85
  if (results.length === 0) {
85
86
  console.log(chalk.yellow('No results found.'));
@@ -221,10 +221,11 @@ class ConfluenceClient {
221
221
  /**
222
222
  * Search for pages
223
223
  */
224
- async search(query, limit = 10) {
224
+ async search(query, limit = 10, rawCql = false) {
225
+ const cql = rawCql ? query : `text ~ "${String(query).replace(/"/g, '\\"')}"`;
225
226
  const response = await this.client.get('/search', {
226
227
  params: {
227
- cql: `text ~ "${query}"`,
228
+ cql,
228
229
  limit: limit
229
230
  }
230
231
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "confluence-cli",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "A command-line interface for Atlassian Confluence with page creation and editing capabilities",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -303,6 +303,68 @@ describe('ConfluenceClient', () => {
303
303
  });
304
304
  });
305
305
 
306
+ describe('search', () => {
307
+ test('should wrap query in text search by default', async () => {
308
+ const mock = new MockAdapter(client.client);
309
+ mock.onGet('/search').reply((config) => {
310
+ expect(config.params.cql).toBe('text ~ "architecture decisions"');
311
+ expect(config.params.limit).toBe(10);
312
+ return [200, { results: [] }];
313
+ });
314
+
315
+ const results = await client.search('architecture decisions');
316
+ expect(results).toEqual([]);
317
+
318
+ mock.restore();
319
+ });
320
+
321
+ test('should pass raw CQL when rawCql is true', async () => {
322
+ const mock = new MockAdapter(client.client);
323
+ const rawQuery = 'contributor = currentUser() order by lastmodified desc';
324
+ mock.onGet('/search').reply((config) => {
325
+ expect(config.params.cql).toBe(rawQuery);
326
+ return [200, {
327
+ results: [{
328
+ content: { id: '123', title: 'Test Page', type: 'page' },
329
+ excerpt: 'test excerpt'
330
+ }]
331
+ }];
332
+ });
333
+
334
+ const results = await client.search(rawQuery, 10, true);
335
+ expect(results).toHaveLength(1);
336
+ expect(results[0].id).toBe('123');
337
+ expect(results[0].title).toBe('Test Page');
338
+
339
+ mock.restore();
340
+ });
341
+
342
+ test('should escape double quotes in text search query', async () => {
343
+ const mock = new MockAdapter(client.client);
344
+ mock.onGet('/search').reply((config) => {
345
+ expect(config.params.cql).toBe('text ~ "test \\"quoted\\" term"');
346
+ return [200, { results: [] }];
347
+ });
348
+
349
+ const results = await client.search('test "quoted" term');
350
+ expect(results).toEqual([]);
351
+
352
+ mock.restore();
353
+ });
354
+
355
+ test('should respect limit parameter', async () => {
356
+ const mock = new MockAdapter(client.client);
357
+ mock.onGet('/search').reply((config) => {
358
+ expect(config.params.limit).toBe(5);
359
+ return [200, { results: [] }];
360
+ });
361
+
362
+ await client.search('test', 5);
363
+
364
+ mock.restore();
365
+ });
366
+ });
367
+
306
368
  describe('page creation and updates', () => {
307
369
  test('should have required methods for page management', () => {
308
370
  expect(typeof client.createPage).toBe('function');