@qodalis/cli-server-jobs 2.4.2 → 2.5.1

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": "@qodalis/cli-server-jobs",
3
- "version": "2.4.2",
3
+ "version": "2.5.1",
4
4
  "description": "Background job management",
5
5
  "author": "Qodalis Solutions",
6
6
  "license": "MIT",
@@ -18,7 +18,7 @@
18
18
  "umd": "./umd/index.global.js",
19
19
  "unpkg": "./umd/index.global.js",
20
20
  "dependencies": {
21
- "@qodalis/cli-core": "2.4.2"
21
+ "@qodalis/cli-core": "2.5.1"
22
22
  },
23
23
  "sideEffects": false,
24
24
  "main": "./public-api.js",
package/public-api.d.mts CHANGED
@@ -5,6 +5,8 @@ interface JobDto {
5
5
  name: string;
6
6
  description: string;
7
7
  group?: string;
8
+ /** Free-form labels to filter jobs by (servers with job tags; missing on older servers). */
9
+ tags?: string[];
8
10
  status: 'active' | 'paused' | 'stopped';
9
11
  schedule?: string;
10
12
  /** Milliseconds (.NET, Node) or a span such as `30s` (Python). */
@@ -53,6 +55,8 @@ interface JobHistoryResponse {
53
55
  interface UpdateJobRequest {
54
56
  description?: string;
55
57
  group?: string;
58
+ /** Replaces the job's tags; `null` clears them. */
59
+ tags?: string[] | null;
56
60
  schedule?: string;
57
61
  interval?: string;
58
62
  maxRetries?: number;
@@ -115,12 +119,24 @@ declare class CliJobNameCompletionProvider implements ICliCompletionProvider {
115
119
  getCompletions(context: ICliCompletionContext): Promise<string[]>;
116
120
  }
117
121
 
122
+ /** Whether the job has every tag in `tags`, ignoring case. */
123
+ declare function jobHasTags(job: JobDto, tags: string[]): boolean;
124
+ /**
125
+ * The tags of a `--tag` option: repeated (`--tag a --tag b`) or comma-separated (`--tag a,b`),
126
+ * trimmed, empty ones dropped.
127
+ */
128
+ declare function parseTagArgs(value: unknown): string[];
118
129
  declare class CliJobsService {
119
130
  private baseUrl;
120
131
  private headers;
121
132
  constructor(baseUrl: string, headers?: Record<string, string>);
122
133
  private request;
123
- listJobs(): Promise<JobDto[]>;
134
+ /**
135
+ * The jobs; with `tags`, only those that have every tag (ignoring case). The server filters
136
+ * (`?tag=`), and the list is filtered here too, so a server without job tags lists nothing
137
+ * for a tag filter instead of every job.
138
+ */
139
+ listJobs(tags?: string[]): Promise<JobDto[]>;
124
140
  getJob(id: string): Promise<JobDto>;
125
141
  triggerJob(id: string): Promise<void>;
126
142
  pauseJob(id: string): Promise<void>;
@@ -136,10 +152,10 @@ declare class CliJobsService {
136
152
  getExecution(jobId: string, execId: string): Promise<JobExecutionDto>;
137
153
  }
138
154
 
139
- declare const LIBRARY_VERSION = "2.4.2";
155
+ declare const LIBRARY_VERSION = "2.5.1";
140
156
  declare const API_VERSION = 2;
141
157
 
142
158
  declare const jobsModule: ICliModule;
143
159
 
144
- export { API_VERSION, CliJobNameCompletionProvider, CliJobsCommandProcessor, CliJobsService, LIBRARY_VERSION, formatRunning, formatSpan, jobsModule };
160
+ export { API_VERSION, CliJobNameCompletionProvider, CliJobsCommandProcessor, CliJobsService, LIBRARY_VERSION, formatRunning, formatSpan, jobHasTags, jobsModule, parseTagArgs };
145
161
  export type { JobDto, JobExecutionDto, JobHistoryResponse, JobLogEntryDto, UpdateJobRequest };
package/public-api.d.ts CHANGED
@@ -5,6 +5,8 @@ interface JobDto {
5
5
  name: string;
6
6
  description: string;
7
7
  group?: string;
8
+ /** Free-form labels to filter jobs by (servers with job tags; missing on older servers). */
9
+ tags?: string[];
8
10
  status: 'active' | 'paused' | 'stopped';
9
11
  schedule?: string;
10
12
  /** Milliseconds (.NET, Node) or a span such as `30s` (Python). */
@@ -53,6 +55,8 @@ interface JobHistoryResponse {
53
55
  interface UpdateJobRequest {
54
56
  description?: string;
55
57
  group?: string;
58
+ /** Replaces the job's tags; `null` clears them. */
59
+ tags?: string[] | null;
56
60
  schedule?: string;
57
61
  interval?: string;
58
62
  maxRetries?: number;
@@ -115,12 +119,24 @@ declare class CliJobNameCompletionProvider implements ICliCompletionProvider {
115
119
  getCompletions(context: ICliCompletionContext): Promise<string[]>;
116
120
  }
117
121
 
122
+ /** Whether the job has every tag in `tags`, ignoring case. */
123
+ declare function jobHasTags(job: JobDto, tags: string[]): boolean;
124
+ /**
125
+ * The tags of a `--tag` option: repeated (`--tag a --tag b`) or comma-separated (`--tag a,b`),
126
+ * trimmed, empty ones dropped.
127
+ */
128
+ declare function parseTagArgs(value: unknown): string[];
118
129
  declare class CliJobsService {
119
130
  private baseUrl;
120
131
  private headers;
121
132
  constructor(baseUrl: string, headers?: Record<string, string>);
122
133
  private request;
123
- listJobs(): Promise<JobDto[]>;
134
+ /**
135
+ * The jobs; with `tags`, only those that have every tag (ignoring case). The server filters
136
+ * (`?tag=`), and the list is filtered here too, so a server without job tags lists nothing
137
+ * for a tag filter instead of every job.
138
+ */
139
+ listJobs(tags?: string[]): Promise<JobDto[]>;
124
140
  getJob(id: string): Promise<JobDto>;
125
141
  triggerJob(id: string): Promise<void>;
126
142
  pauseJob(id: string): Promise<void>;
@@ -136,10 +152,10 @@ declare class CliJobsService {
136
152
  getExecution(jobId: string, execId: string): Promise<JobExecutionDto>;
137
153
  }
138
154
 
139
- declare const LIBRARY_VERSION = "2.4.2";
155
+ declare const LIBRARY_VERSION = "2.5.1";
140
156
  declare const API_VERSION = 2;
141
157
 
142
158
  declare const jobsModule: ICliModule;
143
159
 
144
- export { API_VERSION, CliJobNameCompletionProvider, CliJobsCommandProcessor, CliJobsService, LIBRARY_VERSION, formatRunning, formatSpan, jobsModule };
160
+ export { API_VERSION, CliJobNameCompletionProvider, CliJobsCommandProcessor, CliJobsService, LIBRARY_VERSION, formatRunning, formatSpan, jobHasTags, jobsModule, parseTagArgs };
145
161
  export type { JobDto, JobExecutionDto, JobHistoryResponse, JobLogEntryDto, UpdateJobRequest };
package/public-api.js CHANGED
@@ -5,6 +5,14 @@ var cliCore = require('@qodalis/cli-core');
5
5
  // src/lib/processors/cli-jobs-command-processor.ts
6
6
 
7
7
  // src/lib/services/cli-jobs-service.ts
8
+ function jobHasTags(job, tags) {
9
+ const own = new Set((job.tags ?? []).map((t) => t.toLowerCase()));
10
+ return tags.every((t) => own.has(t.toLowerCase()));
11
+ }
12
+ function parseTagArgs(value) {
13
+ const values = Array.isArray(value) ? value : value === void 0 || value === null || value === true ? [] : [value];
14
+ return values.flatMap((v) => String(v).split(",")).map((t) => t.trim()).filter(Boolean);
15
+ }
8
16
  var CliJobsService = class {
9
17
  constructor(baseUrl, headers = {}) {
10
18
  this.baseUrl = baseUrl;
@@ -37,8 +45,15 @@ var CliJobsService = class {
37
45
  }
38
46
  return JSON.parse(text);
39
47
  }
40
- async listJobs() {
41
- return this.request("");
48
+ /**
49
+ * The jobs; with `tags`, only those that have every tag (ignoring case). The server filters
50
+ * (`?tag=`), and the list is filtered here too, so a server without job tags lists nothing
51
+ * for a tag filter instead of every job.
52
+ */
53
+ async listJobs(tags = []) {
54
+ const query = tags.map((t) => `tag=${encodeURIComponent(t)}`).join("&");
55
+ const jobs = await this.request(query ? `?${query}` : "");
56
+ return tags.length ? jobs.filter((j) => jobHasTags(j, tags)) : jobs;
42
57
  }
43
58
  async getJob(id) {
44
59
  return this.request(`/${encodeURIComponent(id)}`);
@@ -186,6 +201,9 @@ function formatRunning(job) {
186
201
  if (job.queued) parts.push("1 queued");
187
202
  return parts.join(", ");
188
203
  }
204
+ function formatTags(tags) {
205
+ return tags && tags.length > 0 ? tags.join(", ") : "-";
206
+ }
189
207
  function formatDuration(ms) {
190
208
  if (ms == null) return "-";
191
209
  if (ms < 1e3) return `${ms}ms`;
@@ -283,12 +301,14 @@ var CliJobsCommandProcessor = class {
283
301
  context.writer.writeln();
284
302
  cliCore.writeUsage(context, [
285
303
  ["server jobs list", t.t("cli.server.jobs.list.help.jobs_all_connected_servers", "Jobs on all connected servers")],
286
- ["server jobs ls --group <name>", t.t("cli.server.jobs.list.help.only_one_group", "Only one group")]
304
+ ["server jobs ls --group <name>", t.t("cli.server.jobs.list.help.only_one_group", "Only one group")],
305
+ ["server jobs ls --tag <tag> [--tag <tag>]", t.t("cli.server.jobs.list.help.only_tagged", "Only the jobs that have every tag given")]
287
306
  ]);
288
307
  context.writer.writeln();
289
308
  cliCore.writeExamples(context, [
290
309
  ["server jobs ls --server node", t.t("cli.server.jobs.list.help.jobs_node_server", "Jobs on the node server")],
291
- ["server jobs list --group reports", t.t("cli.server.jobs.list.help.jobs_reports_group", "Jobs in the reports group")]
310
+ ["server jobs list --group reports", t.t("cli.server.jobs.list.help.jobs_reports_group", "Jobs in the reports group")],
311
+ ["server jobs list --tag country:ro --tag bank", t.t("cli.server.jobs.list.help.jobs_tagged", "Jobs tagged both country:ro and bank")]
292
312
  ]);
293
313
  },
294
314
  aliases: ["ls"],
@@ -299,6 +319,12 @@ var CliJobsCommandProcessor = class {
299
319
  description: "Filter jobs by group",
300
320
  required: false,
301
321
  type: "string"
322
+ },
323
+ {
324
+ name: "tag",
325
+ description: "Only jobs that have this tag (repeatable or comma-separated; every tag must match)",
326
+ required: false,
327
+ type: "array"
302
328
  }
303
329
  ],
304
330
  processCommand: async (cmd, context) => {
@@ -613,10 +639,11 @@ var CliJobsCommandProcessor = class {
613
639
  return;
614
640
  }
615
641
  const groupFilter = cmd.args["group"];
642
+ const tagFilter = parseTagArgs(cmd.args["tag"]);
616
643
  const multiServer = services.length > 1;
617
644
  for (const { name, service } of services) {
618
645
  try {
619
- let jobs = await service.listJobs();
646
+ let jobs = await service.listJobs(tagFilter);
620
647
  if (groupFilter) {
621
648
  jobs = jobs.filter(
622
649
  (j) => j.group?.toLowerCase() === groupFilter.toLowerCase()
@@ -634,9 +661,11 @@ var CliJobsCommandProcessor = class {
634
661
  context.writer.writeInfo(" No jobs found.");
635
662
  continue;
636
663
  }
664
+ const showTags = jobs.some((j) => (j.tags?.length ?? 0) > 0);
637
665
  const headers = [
638
666
  "Name",
639
667
  "Group",
668
+ ...showTags ? ["Tags"] : [],
640
669
  "Status",
641
670
  "Schedule",
642
671
  "Last Run",
@@ -646,6 +675,7 @@ var CliJobsCommandProcessor = class {
646
675
  const rows = jobs.map((j) => [
647
676
  j.name,
648
677
  j.group ?? "-",
678
+ ...showTags ? [formatTags(j.tags)] : [],
649
679
  statusColor(j.status, context.writer),
650
680
  j.schedule ?? (formatSpan(j.interval) ? `every ${formatSpan(j.interval)}` : "-"),
651
681
  formatRelativeTime(j.lastRunAt),
@@ -682,6 +712,7 @@ var CliJobsCommandProcessor = class {
682
712
  ["Name", job.name],
683
713
  ["Description", job.description],
684
714
  ["Group", job.group ?? "-"],
715
+ ["Tags", formatTags(job.tags)],
685
716
  ["Status", statusColor(job.status, context.writer)],
686
717
  [
687
718
  "Schedule",
@@ -938,6 +969,10 @@ var CliJobsCommandProcessor = class {
938
969
  const newGroup = await ask(`Group [${job.group ?? "none"}]: `);
939
970
  if (newGroup == null) return cancelled();
940
971
  if (newGroup) update.group = newGroup;
972
+ const newTags = await ask(`Tags, comma-separated, - for none [${formatTags(job.tags)}]: `);
973
+ if (newTags == null) return cancelled();
974
+ if (newTags.trim() === "-") update.tags = null;
975
+ else if (newTags.trim()) update.tags = parseTagArgs(newTags);
941
976
  const currentSchedule = job.schedule ?? (formatSpan(job.interval) ? `interval: ${formatSpan(job.interval)}` : "none");
942
977
  const newSchedule = await ask(
943
978
  `Cron schedule [${currentSchedule}]: `
@@ -1218,7 +1253,7 @@ var CliJobNameCompletionProvider = class {
1218
1253
  };
1219
1254
 
1220
1255
  // src/lib/version.ts
1221
- var LIBRARY_VERSION = "2.4.2";
1256
+ var LIBRARY_VERSION = "2.5.1";
1222
1257
  var API_VERSION = 2;
1223
1258
  var completionProvider = new CliJobNameCompletionProvider();
1224
1259
  var jobsModule = {
@@ -1244,6 +1279,8 @@ exports.CliJobsService = CliJobsService;
1244
1279
  exports.LIBRARY_VERSION = LIBRARY_VERSION;
1245
1280
  exports.formatRunning = formatRunning;
1246
1281
  exports.formatSpan = formatSpan;
1282
+ exports.jobHasTags = jobHasTags;
1247
1283
  exports.jobsModule = jobsModule;
1284
+ exports.parseTagArgs = parseTagArgs;
1248
1285
  //# sourceMappingURL=public-api.js.map
1249
1286
  //# sourceMappingURL=public-api.js.map