@qodalis/cli-server-jobs 2.4.1 → 2.5.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.
- package/package.json +2 -2
- package/public-api.d.mts +19 -3
- package/public-api.d.ts +19 -3
- package/public-api.js +43 -6
- package/public-api.js.map +1 -1
- package/public-api.mjs +42 -7
- package/public-api.mjs.map +1 -1
- package/umd/index.global.js +43 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qodalis/cli-server-jobs",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
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.
|
|
21
|
+
"@qodalis/cli-core": "2.5.0"
|
|
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
|
-
|
|
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.
|
|
155
|
+
declare const LIBRARY_VERSION = "2.5.0";
|
|
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
|
-
|
|
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.
|
|
155
|
+
declare const LIBRARY_VERSION = "2.5.0";
|
|
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
|
-
|
|
41
|
-
|
|
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.
|
|
1256
|
+
var LIBRARY_VERSION = "2.5.0";
|
|
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
|