@danypops/tickets 0.4.2 → 0.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/tickets",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Unified CLI, daemon, and TypeScript library for issue tracking across GitHub, GitLab, and Jira.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -158,7 +158,9 @@ export class GitHubRepository {
158
158
  return toDomain(raw);
159
159
  }
160
160
 
161
- async search(query: string, limit = 50): Promise<Issue[]> {
161
+ // project is accepted for IssueRepository interface parity but ignored --
162
+ // GitHub's scope (owner/repo) is fixed at construction, not overridable per call.
163
+ async search(query: string, limit = 50, _project?: string): Promise<Issue[]> {
162
164
  const scope = this.repo ? `repo:${this.owner}/${this.repo}` : `org:${this.owner}`;
163
165
  const result = (await this.call((signal) =>
164
166
  this.client.rest.search.issuesAndPullRequests({ q: `${scope} ${query}`, per_page: limit, request: { signal } }),
@@ -141,7 +141,9 @@ export class GitLabRepository {
141
141
  return toDomain(raw);
142
142
  }
143
143
 
144
- async search(query: string, limit = 50): Promise<Issue[]> {
144
+ // project is accepted for IssueRepository interface parity but ignored --
145
+ // GitLab's scope (projectId) is fixed at construction, not overridable per call.
146
+ async search(query: string, limit = 50, _project?: string): Promise<Issue[]> {
145
147
  const raw = await this.call<GlIssue[]>(() =>
146
148
  this.client.Issues.all({ projectId: this.projectId, search: query, perPage: limit }),
147
149
  );
@@ -237,8 +237,9 @@ export class JiraRepository {
237
237
  return this.get(key);
238
238
  }
239
239
 
240
- async search(query: string, limit = 50): Promise<Issue[]> {
241
- const scope = this.project ? `project = ${jqlQuote(this.project)} AND ` : "";
240
+ async search(query: string, limit = 50, project?: string): Promise<Issue[]> {
241
+ const effectiveProject = project ?? this.project;
242
+ const scope = effectiveProject ? `project = ${jqlQuote(effectiveProject)} AND ` : "";
242
243
  const jql = `${scope}text ~ ${jqlQuote(query)} ORDER BY created DESC`;
243
244
  return this.searchJql(jql, limit);
244
245
  }
@@ -266,9 +267,12 @@ export class JiraRepository {
266
267
  private async searchJql(jql: string, limit: number): Promise<Issue[]> {
267
268
  // searchForIssuesUsingJqlPost hits the deprecated /rest/api/2/search, which
268
269
  // Atlassian has sunset on Jira Cloud (410 Gone). The enhanced variant posts
269
- // to the still-live /rest/api/2/search/jql with an identical request/response shape.
270
+ // to the still-live /rest/api/2/search/jql -- but unlike the old endpoint
271
+ // (which defaulted to *navigable fields), this one defaults to id-only, so
272
+ // toDomain() would crash on a missing summary/status/etc. without an explicit
273
+ // fields request. "*all" restores the old behavior (including custom fields).
270
274
  const result = await this.call<{ issues?: JiraIssue[] }>(() =>
271
- this.client.issueSearch.searchForIssuesUsingJqlEnhancedSearchPost({ jql, maxResults: limit }),
275
+ this.client.issueSearch.searchForIssuesUsingJqlEnhancedSearchPost({ jql, maxResults: limit, fields: ["*all"] }),
272
276
  );
273
277
  return (result?.issues ?? []).map((raw) => this.toDomain(raw));
274
278
  }
@@ -77,8 +77,8 @@ export class TicketService {
77
77
  return this.repo(backend).update(key, input);
78
78
  }
79
79
 
80
- async search(backend: string, query: string, limit?: number): Promise<Issue[]> {
81
- return this.repo(backend).search(query, limit);
80
+ async search(backend: string, query: string, limit?: number, project?: string): Promise<Issue[]> {
81
+ return this.repo(backend).search(query, limit, project);
82
82
  }
83
83
 
84
84
  async children(ref: string): Promise<Issue[]> {
package/src/daemon/ops.ts CHANGED
@@ -36,7 +36,7 @@ export interface TicketOpInputs extends Record<TicketOperation, unknown> {
36
36
  "issue.get": { ref: string };
37
37
  "issue.create": { backend: string; input: CreateInput };
38
38
  "issue.update": { ref: string; input: UpdateInput };
39
- "issue.search": { backend: string; query: string; limit?: number };
39
+ "issue.search": { backend: string; query: string; limit?: number; project?: string };
40
40
  "issue.children": { ref: string };
41
41
  "issue.comments": { ref: string };
42
42
  "issue.comment_add": { ref: string; body: string };
@@ -41,7 +41,7 @@ const handlers: { [Op in TicketOperation]: Handler<Op> } = {
41
41
  "issue.get": async (deps, input) => ({ issue: await deps.service.get(input.ref) }),
42
42
  "issue.create": async (deps, input) => ({ issue: await deps.service.create(input.backend, input.input) }),
43
43
  "issue.update": async (deps, input) => ({ issue: await deps.service.update(input.ref, input.input) }),
44
- "issue.search": async (deps, input) => ({ issues: await deps.service.search(input.backend, input.query, input.limit) }),
44
+ "issue.search": async (deps, input) => ({ issues: await deps.service.search(input.backend, input.query, input.limit, input.project) }),
45
45
  "issue.children": async (deps, input) => ({ issues: await deps.service.children(input.ref) }),
46
46
  "issue.comments": async (deps, input) => ({ comments: await deps.service.comments(input.ref) }),
47
47
  "issue.comment_add": async (deps, input) => ({ comment: await deps.service.addComment(input.ref, input.body) }),
@@ -13,7 +13,8 @@ export interface IssueRepository {
13
13
  get(key: string): Promise<Issue>;
14
14
  create(input: CreateInput): Promise<Issue>;
15
15
  update(key: string, input: UpdateInput): Promise<Issue>;
16
- search(query: string, limit?: number): Promise<Issue[]>;
16
+ /** project: per-call override of this repository's own default/configured project (Jira only; GitHub/GitLab ignore it -- their scope is fixed to the configured repo/project at construction). */
17
+ search(query: string, limit?: number, project?: string): Promise<Issue[]>;
17
18
  listChildren(key: string): Promise<Issue[]>;
18
19
  }
19
20