@lightward/mechanic-cli 0.1.1 → 0.1.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/README.md +75 -37
- package/dist/base-command.d.ts +1 -0
- package/dist/base-command.d.ts.map +1 -1
- package/dist/base-command.js +16 -1
- package/dist/client.d.ts +3 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -1
- package/dist/commands/auth/login.d.ts.map +1 -1
- package/dist/commands/auth/login.js +6 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +9 -7
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +12 -6
- package/dist/commands/tasks/bundle.d.ts.map +1 -1
- package/dist/commands/tasks/bundle.js +37 -5
- package/dist/commands/tasks/diff.d.ts.map +1 -1
- package/dist/commands/tasks/diff.js +2 -2
- package/dist/commands/tasks/new.d.ts +16 -0
- package/dist/commands/tasks/new.d.ts.map +1 -0
- package/dist/commands/tasks/new.js +104 -0
- package/dist/commands/tasks/open.d.ts.map +1 -1
- package/dist/commands/tasks/open.js +2 -2
- package/dist/commands/tasks/preview.d.ts +4 -0
- package/dist/commands/tasks/preview.d.ts.map +1 -1
- package/dist/commands/tasks/preview.js +43 -3
- package/dist/commands/tasks/publish.js +1 -1
- package/dist/commands/tasks/pull.d.ts.map +1 -1
- package/dist/commands/tasks/pull.js +8 -5
- package/dist/commands/tasks/push.d.ts +2 -0
- package/dist/commands/tasks/push.d.ts.map +1 -1
- package/dist/commands/tasks/push.js +22 -7
- package/dist/commands/tasks/status.d.ts +1 -1
- package/dist/commands/tasks/status.d.ts.map +1 -1
- package/dist/commands/tasks/status.js +26 -14
- package/dist/commands/tasks/unbundle.d.ts.map +1 -1
- package/dist/commands/tasks/unbundle.js +5 -5
- package/dist/commands/tasks/validate.d.ts +1 -0
- package/dist/commands/tasks/validate.d.ts.map +1 -1
- package/dist/commands/tasks/validate.js +40 -18
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -11
- package/dist/tasks.js +2 -2
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/update-check.d.ts +14 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +136 -0
- package/package.json +1 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { BaseCommand } from "../../base-command.js";
|
|
4
|
+
import { CliError } from "../../errors.js";
|
|
5
|
+
import { pathExists } from "../../fs.js";
|
|
6
|
+
import { displayTaskPath, taskPath, taskSlug, unbundleTask, writeTaskFilePath } from "../../tasks.js";
|
|
7
|
+
function taskNameFromInput(input) {
|
|
8
|
+
const cleaned = input.trim().replace(/\s+/g, " ");
|
|
9
|
+
if (cleaned.includes(" ")) {
|
|
10
|
+
return cleaned;
|
|
11
|
+
}
|
|
12
|
+
return taskSlug(cleaned)
|
|
13
|
+
.split("-")
|
|
14
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
15
|
+
.join(" ");
|
|
16
|
+
}
|
|
17
|
+
function starterTask(name) {
|
|
18
|
+
return {
|
|
19
|
+
halt_action_run_sequence_on_error: false,
|
|
20
|
+
name,
|
|
21
|
+
docs: "",
|
|
22
|
+
options: {},
|
|
23
|
+
perform_action_runs_in_sequence: false,
|
|
24
|
+
preview_event_definitions: [],
|
|
25
|
+
script: [
|
|
26
|
+
"{% comment %}",
|
|
27
|
+
" Start writing your Mechanic task here.",
|
|
28
|
+
"{% endcomment %}",
|
|
29
|
+
"",
|
|
30
|
+
'{% log message: "Hello from Mechanic" %}',
|
|
31
|
+
"",
|
|
32
|
+
].join("\n"),
|
|
33
|
+
subscriptions_template: "mechanic/user/text\n",
|
|
34
|
+
tags: [],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export default class TasksNew extends BaseCommand {
|
|
38
|
+
static summary = "Create a new blank local task.";
|
|
39
|
+
static description = "Create one blank local starter task JSON file and its matching editable helper directory. Nothing is created in Mechanic until you publish.";
|
|
40
|
+
static examples = [
|
|
41
|
+
"$ mechanic tasks new order-tagger",
|
|
42
|
+
"$ mechanic tasks new \"Order tagger\"",
|
|
43
|
+
];
|
|
44
|
+
static args = {
|
|
45
|
+
name: Args.string({ required: true, description: "Task name or slug for the new local task." }),
|
|
46
|
+
};
|
|
47
|
+
static flags = {
|
|
48
|
+
force: Flags.boolean({ description: "Overwrite the local starter task JSON file and helper directory files." }),
|
|
49
|
+
json: Flags.boolean({ description: "Print created paths as JSON for agents, scripts, or editor integrations." }),
|
|
50
|
+
};
|
|
51
|
+
async run() {
|
|
52
|
+
const { args, flags } = await this.parse(TasksNew);
|
|
53
|
+
const project = await this.loadProject();
|
|
54
|
+
const requestedName = args.name.trim();
|
|
55
|
+
if (!requestedName) {
|
|
56
|
+
throw new CliError("Task name cannot be blank.", 2);
|
|
57
|
+
}
|
|
58
|
+
const slug = taskSlug(requestedName);
|
|
59
|
+
const name = taskNameFromInput(requestedName);
|
|
60
|
+
const filePath = taskPath(project, slug);
|
|
61
|
+
const helperDir = filePath.replace(/\.json$/i, "");
|
|
62
|
+
await this.checkExistingPaths(project, filePath, helperDir, Boolean(flags.force));
|
|
63
|
+
await writeTaskFilePath(filePath, starterTask(name));
|
|
64
|
+
await unbundleTask(filePath, helperDir);
|
|
65
|
+
const fileDisplay = displayTaskPath(project, filePath);
|
|
66
|
+
const helperDisplay = displayTaskPath(project, helperDir);
|
|
67
|
+
if (flags.json) {
|
|
68
|
+
this.outputJson({
|
|
69
|
+
ok: true,
|
|
70
|
+
name,
|
|
71
|
+
slug,
|
|
72
|
+
file: fileDisplay,
|
|
73
|
+
helper_dir: helperDisplay,
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.log(`Created ${this.taskName(fileDisplay)}`);
|
|
78
|
+
this.log(`Created ${this.taskName(helperDisplay)}`);
|
|
79
|
+
this.log("");
|
|
80
|
+
this.log("Next steps:");
|
|
81
|
+
this.log(` edit ${this.taskName(displayTaskPath(project, path.join(helperDir, "script.liquid")))}`);
|
|
82
|
+
this.log(` mechanic tasks preview ${this.taskName(slug)}`);
|
|
83
|
+
this.log(` mechanic tasks bundle ${this.taskName(slug)}`);
|
|
84
|
+
this.log(` mechanic tasks publish ${this.taskName(slug)}`);
|
|
85
|
+
}
|
|
86
|
+
async checkExistingPaths(project, filePath, helperDir, force) {
|
|
87
|
+
if (force) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const existing = [];
|
|
91
|
+
if (await pathExists(filePath)) {
|
|
92
|
+
existing.push(displayTaskPath(project, filePath));
|
|
93
|
+
}
|
|
94
|
+
if (await pathExists(helperDir)) {
|
|
95
|
+
existing.push(displayTaskPath(project, helperDir));
|
|
96
|
+
}
|
|
97
|
+
if (existing.length > 0) {
|
|
98
|
+
throw new CliError([
|
|
99
|
+
`${existing.join(" and ")} already exists.`,
|
|
100
|
+
"Choose another task name, or re-run with --force to overwrite the local starter files.",
|
|
101
|
+
].join("\n"), 2);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/open.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAc9C,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,OAAgB,OAAO,SAAqC;IAC5D,OAAgB,WAAW,
|
|
1
|
+
{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/open.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAc9C,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,OAAgB,OAAO,SAAqC;IAC5D,OAAgB,WAAW,SAAgH;IAE3I,OAAgB,IAAI;;MAElB;IAEI,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiBlE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBnC,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB3B"}
|
|
@@ -15,9 +15,9 @@ function openerCommand(url) {
|
|
|
15
15
|
}
|
|
16
16
|
export default class TasksOpen extends BaseCommand {
|
|
17
17
|
static summary = "Open a remote task in Mechanic.";
|
|
18
|
-
static description = "Open a remote Mechanic task by task ID, linked local task JSON file, helper directory
|
|
18
|
+
static description = "Open a remote Mechanic task by local task slug, task ID, linked local task JSON file, or helper directory.";
|
|
19
19
|
static args = {
|
|
20
|
-
target: Args.string({ required: true, description: "
|
|
20
|
+
target: Args.string({ required: true, description: "Local task slug, remote task ID, linked local task JSON file, or helper directory." }),
|
|
21
21
|
};
|
|
22
22
|
async taskIdForTarget(project, target) {
|
|
23
23
|
const selector = await resolveTaskSelector(project, target, {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseCommand } from "../../base-command.js";
|
|
2
2
|
import type { MechanicClient } from "../../client.js";
|
|
3
3
|
import type { JsonObject, Project, TaskPreviewResponse } from "../../types.js";
|
|
4
|
+
type PreviewDiagnostic = NonNullable<TaskPreviewResponse["diagnostics"]>[number];
|
|
4
5
|
type PreparedPreview = {
|
|
5
6
|
label: string;
|
|
6
7
|
slug?: string;
|
|
@@ -28,6 +29,9 @@ export default class TasksPreview extends BaseCommand {
|
|
|
28
29
|
renderPreview(project: Project, prepared: PreparedPreview, response: TaskPreviewResponse, options: PreviewRenderOptions): void;
|
|
29
30
|
renderVerboseDetails(response: TaskPreviewResponse): void;
|
|
30
31
|
renderRunDetails(response: TaskPreviewResponse): void;
|
|
32
|
+
renderDiagnostics(response: TaskPreviewResponse, options: PreviewRenderOptions): void;
|
|
33
|
+
diagnosticSeverityLabel(severity: PreviewDiagnostic["severity"]): string;
|
|
34
|
+
diagnosticDetails(diagnostic: PreviewDiagnostic): string[];
|
|
31
35
|
renderPreviewValue(label: string, value: unknown, indent: number): void;
|
|
32
36
|
formatPreviewValue(value: unknown): string | null;
|
|
33
37
|
runStatusLabel(ok: boolean | null): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/preview.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/preview.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { Args, Flags } from "@oclif/core";
|
|
|
2
2
|
import { BaseCommand } from "../../base-command.js";
|
|
3
3
|
import { HttpError, CliError } from "../../errors.js";
|
|
4
4
|
import { pathExists } from "../../fs.js";
|
|
5
|
-
import { displayTaskPath, readRawTaskFile, resolveTaskSelector, rawTaskFromHelperDir, taskForPush, unbundledHelperDirForTaskFile, validateTaskForPush, } from "../../tasks.js";
|
|
5
|
+
import { displayTaskPath, readRawTaskFile, resolveTaskSelector, rawTaskFromHelperDir, taskForPush, slugFromTaskFile, unbundledHelperDirForTaskFile, validateTaskForPush, } from "../../tasks.js";
|
|
6
6
|
function errorBodyAsPreview(body) {
|
|
7
7
|
if (!body || typeof body !== "object") {
|
|
8
8
|
return null;
|
|
@@ -18,7 +18,7 @@ export default class TasksPreview extends BaseCommand {
|
|
|
18
18
|
"Use --remote to preview the current task already in Mechanic, or --json for agents, scripts, and CI.",
|
|
19
19
|
].join("\n");
|
|
20
20
|
static args = {
|
|
21
|
-
target: Args.string({ required: true, description: "
|
|
21
|
+
target: Args.string({ required: true, description: "Local task slug, task file, helper directory, or linked task ID." }),
|
|
22
22
|
};
|
|
23
23
|
static flags = {
|
|
24
24
|
json: Flags.boolean({ description: "Print the raw preview response as JSON for agents or CI." }),
|
|
@@ -134,6 +134,7 @@ export default class TasksPreview extends BaseCommand {
|
|
|
134
134
|
if (options.verbose) {
|
|
135
135
|
this.renderVerboseDetails(response);
|
|
136
136
|
}
|
|
137
|
+
this.renderDiagnostics(response, options);
|
|
137
138
|
this.renderPermissions(response);
|
|
138
139
|
if (response.status === "invalid") {
|
|
139
140
|
this.renderValidationErrors(response);
|
|
@@ -217,6 +218,45 @@ export default class TasksPreview extends BaseCommand {
|
|
|
217
218
|
this.table(rows);
|
|
218
219
|
}
|
|
219
220
|
}
|
|
221
|
+
renderDiagnostics(response, options) {
|
|
222
|
+
const diagnostics = response.diagnostics || [];
|
|
223
|
+
const visibleDiagnostics = options.verbose
|
|
224
|
+
? diagnostics
|
|
225
|
+
: diagnostics.filter((diagnostic) => diagnostic.severity === "warning" || diagnostic.severity === "error");
|
|
226
|
+
if (visibleDiagnostics.length === 0) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
this.log("");
|
|
230
|
+
this.log(this.accent("Notes"));
|
|
231
|
+
for (const diagnostic of visibleDiagnostics) {
|
|
232
|
+
const details = options.verbose ? this.diagnosticDetails(diagnostic) : [];
|
|
233
|
+
const suffix = details.length ? ` ${this.muted(`(${details.join(", ")})`)}` : "";
|
|
234
|
+
const code = options.verbose ? ` ${this.muted(`[${diagnostic.code}]`)}` : "";
|
|
235
|
+
this.log(` ${this.diagnosticSeverityLabel(diagnostic.severity)}${code} ${diagnostic.message}${suffix}`);
|
|
236
|
+
if (options.verbose && diagnostic.docs_url) {
|
|
237
|
+
this.log(` ${this.muted(`Docs: ${diagnostic.docs_url}`)}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
diagnosticSeverityLabel(severity) {
|
|
242
|
+
switch (severity) {
|
|
243
|
+
case "error":
|
|
244
|
+
return this.color("red", "error");
|
|
245
|
+
case "warning":
|
|
246
|
+
return this.color("yellow", "warning");
|
|
247
|
+
case "info":
|
|
248
|
+
return this.muted("info");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
diagnosticDetails(diagnostic) {
|
|
252
|
+
return [
|
|
253
|
+
diagnostic.event_topic ? `event ${diagnostic.event_topic}` : null,
|
|
254
|
+
typeof diagnostic.event_index === "number" ? `event #${diagnostic.event_index + 1}` : null,
|
|
255
|
+
typeof diagnostic.task_run_index === "number" ? `task run #${diagnostic.task_run_index + 1}` : null,
|
|
256
|
+
typeof diagnostic.action_run_index === "number" ? `action run #${diagnostic.action_run_index + 1}` : null,
|
|
257
|
+
diagnostic.action_type ? `action ${diagnostic.action_type}` : null,
|
|
258
|
+
].filter((detail) => Boolean(detail));
|
|
259
|
+
}
|
|
220
260
|
renderPreviewValue(label, value, indent) {
|
|
221
261
|
const formatted = this.formatPreviewValue(value);
|
|
222
262
|
if (!formatted) {
|
|
@@ -345,7 +385,7 @@ export default class TasksPreview extends BaseCommand {
|
|
|
345
385
|
`${relativeFile} is out of date with ${relativeHelperDir}.`,
|
|
346
386
|
"",
|
|
347
387
|
"Bundle the helper directory before previewing this JSON file:",
|
|
348
|
-
` mechanic tasks bundle ${
|
|
388
|
+
` mechanic tasks bundle ${slugFromTaskFile(filePath)}`,
|
|
349
389
|
].join("\n"), 2);
|
|
350
390
|
}
|
|
351
391
|
approvalHint(action) {
|
|
@@ -5,7 +5,7 @@ export default class TasksPublish extends TasksPush {
|
|
|
5
5
|
static summary = "Publish one local task to Mechanic.";
|
|
6
6
|
static description = "Publish one local task to Mechanic, or use --all to publish every local task JSON file.";
|
|
7
7
|
static args = {
|
|
8
|
-
file: Args.string({ required: false, description: "
|
|
8
|
+
file: Args.string({ required: false, description: "Local task slug, task file, helper directory, or linked task ID." }),
|
|
9
9
|
};
|
|
10
10
|
static flags = {
|
|
11
11
|
all: Flags.boolean({ description: "Publish every task JSON file in this project." }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/pull.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/pull.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAoBpD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,OAAgB,OAAO,SAAmD;IAC1E,OAAgB,WAAW,SAAmI;IAE9J,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;;MAGnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAsG3B"}
|
|
@@ -6,12 +6,12 @@ import { pathExists } from "../../fs.js";
|
|
|
6
6
|
import { contentHash } from "../../hash.js";
|
|
7
7
|
import { stableStringify } from "../../json.js";
|
|
8
8
|
import { CliError } from "../../errors.js";
|
|
9
|
-
import { displayTaskPath, nextAvailableSlug, readRawTaskFile, resolveTaskSelector, taskForPush, taskPath, taskSlug, unbundledHelperDirForTaskFile, writeTaskFilePathAndRefreshHelper, } from "../../tasks.js";
|
|
9
|
+
import { displayTaskPath, nextAvailableSlug, readRawTaskFile, resolveTaskSelector, slugFromTaskFile, taskForPush, taskPath, taskSlug, unbundledHelperDirForTaskFile, writeTaskFilePathAndRefreshHelper, } from "../../tasks.js";
|
|
10
10
|
export default class TasksPull extends BaseCommand {
|
|
11
11
|
static summary = "Pull remote tasks into local task JSON files.";
|
|
12
12
|
static description = "Pull every remote task into local canonical task JSON files, or pass a task ID, linked file, or linked slug to pull one task.";
|
|
13
13
|
static args = {
|
|
14
|
-
task: Args.string({ required: false, description: "
|
|
14
|
+
task: Args.string({ required: false, description: "Local task slug, remote task ID, or linked local task JSON file." }),
|
|
15
15
|
};
|
|
16
16
|
static flags = {
|
|
17
17
|
all: Flags.boolean({ description: "Pull every remote task for this shop. This is the default when no task ID is passed." }),
|
|
@@ -45,13 +45,14 @@ export default class TasksPull extends BaseCommand {
|
|
|
45
45
|
if (helperDir) {
|
|
46
46
|
const relativeFile = displayTaskPath(project, filePath);
|
|
47
47
|
const relativeHelperDir = displayTaskPath(project, helperDir);
|
|
48
|
+
const slug = slugFromTaskFile(filePath);
|
|
48
49
|
throw new CliError([
|
|
49
50
|
`${relativeFile} is out of date with ${relativeHelperDir}.`,
|
|
50
51
|
"",
|
|
51
52
|
"The helper directory has changes that are not bundled into the JSON file.",
|
|
52
53
|
"",
|
|
53
54
|
"Bundle first:",
|
|
54
|
-
` mechanic tasks bundle ${
|
|
55
|
+
` mechanic tasks bundle ${slug}`,
|
|
55
56
|
"",
|
|
56
57
|
"Then pull:",
|
|
57
58
|
` mechanic tasks pull ${envelope.id}`,
|
|
@@ -61,7 +62,9 @@ export default class TasksPull extends BaseCommand {
|
|
|
61
62
|
const remoteTaskForPull = taskForPush(envelope.task);
|
|
62
63
|
const localMatchesCurrentRemote = stableStringify(localTaskForPull) === stableStringify(remoteTaskForPull);
|
|
63
64
|
const localHash = contentHash(localTaskForPull);
|
|
64
|
-
|
|
65
|
+
const localMatchesLastWritten = (localHash === link?.last_remote_content_hash
|
|
66
|
+
|| localHash === link?.last_local_content_hash);
|
|
67
|
+
if (!localMatchesCurrentRemote && !localMatchesLastWritten) {
|
|
65
68
|
throw new CliError([
|
|
66
69
|
`${displayTaskPath(project, filePath)} has local changes that would be overwritten.`,
|
|
67
70
|
`Run "mechanic tasks diff ${displayTaskPath(project, filePath)}" to review them.`,
|
|
@@ -71,7 +74,7 @@ export default class TasksPull extends BaseCommand {
|
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
await writeTaskFilePathAndRefreshHelper(filePath, envelope.task);
|
|
74
|
-
links = updateLink({ ...project, links }, slug, envelope.id, envelope.content_hash);
|
|
77
|
+
links = updateLink({ ...project, links }, slug, envelope.id, envelope.content_hash, contentHash(taskForPush(envelope.task)));
|
|
75
78
|
await saveLinks(project, links);
|
|
76
79
|
rows.push([
|
|
77
80
|
this.taskId(project, envelope.id),
|
|
@@ -18,6 +18,7 @@ type PushRow = {
|
|
|
18
18
|
task_id: string | null;
|
|
19
19
|
content_hash: string | null;
|
|
20
20
|
details: string;
|
|
21
|
+
url?: string;
|
|
21
22
|
};
|
|
22
23
|
type CreateCollision = {
|
|
23
24
|
remoteId: string;
|
|
@@ -54,6 +55,7 @@ export default class TasksPush extends BaseCommand {
|
|
|
54
55
|
rows: PushRow[];
|
|
55
56
|
}>;
|
|
56
57
|
pushRowsToTable(project: Project, statusHeader: string, rows: PushRow[], label: (status: string) => string): string[][];
|
|
58
|
+
printCreatedTaskLinks(rows: PushRow[]): void;
|
|
57
59
|
planLabel(plan: string): string;
|
|
58
60
|
}
|
|
59
61
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/push.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/push.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { Args, Flags } from "@oclif/core";
|
|
3
3
|
import { BaseCommand } from "../../base-command.js";
|
|
4
|
-
import { linkForSlug, saveLinks, updateLink } from "../../config.js";
|
|
4
|
+
import { linkForSlug, saveLinks, taskAdminUrl, updateLink } from "../../config.js";
|
|
5
5
|
import { CliError } from "../../errors.js";
|
|
6
|
+
import { contentHash } from "../../hash.js";
|
|
6
7
|
import { stableStringify } from "../../json.js";
|
|
7
8
|
import { displayTaskPath, remoteChangedSinceLastPull, remoteChangedSinceLastPullDetails, remoteChangedSinceLastPullMessage, selectedTaskFiles, readRawTaskFile, slugFromTaskFile, taskForPush, taskSlug, unbundledHelperDirForTaskFile, validateTaskForPush, writeTaskFilePathAndRefreshHelper, } from "../../tasks.js";
|
|
8
9
|
function createTaskIdempotencyKey(shopDomain, slug) {
|
|
@@ -22,7 +23,7 @@ export default class TasksPush extends BaseCommand {
|
|
|
22
23
|
static summary = "Publish one local task, or use --all to publish every local task.";
|
|
23
24
|
static description = "Publish one local task to Mechanic, or use --all to publish every local task JSON file in this project.";
|
|
24
25
|
static args = {
|
|
25
|
-
file: Args.string({ required: false, description: "
|
|
26
|
+
file: Args.string({ required: false, description: "Local task slug, task file, helper directory, or linked task ID." }),
|
|
26
27
|
};
|
|
27
28
|
static flags = {
|
|
28
29
|
all: Flags.boolean({ description: "Publish every task JSON file in this project." }),
|
|
@@ -67,6 +68,7 @@ export default class TasksPush extends BaseCommand {
|
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
69
70
|
this.table(this.pushRowsToTable(project, "Action", rows, (status) => this.actionLabel(status)));
|
|
71
|
+
this.printCreatedTaskLinks(rows);
|
|
70
72
|
}
|
|
71
73
|
async publishTasks(project, preparation, force) {
|
|
72
74
|
const client = await this.verifiedClientForProject(project);
|
|
@@ -80,7 +82,7 @@ export default class TasksPush extends BaseCommand {
|
|
|
80
82
|
const link = linkForSlug({ ...project, links }, slug);
|
|
81
83
|
if (!link) {
|
|
82
84
|
const created = await client.createTask(task, createTaskIdempotencyKey(project.shopDomain, slug));
|
|
83
|
-
links = updateLink({ ...project, links }, slug, created.id, created.content_hash);
|
|
85
|
+
links = updateLink({ ...project, links }, slug, created.id, created.content_hash, contentHash(taskForPush(created.task)));
|
|
84
86
|
await saveLinks(project, links);
|
|
85
87
|
await writeTaskFilePathAndRefreshHelper(file, created.task);
|
|
86
88
|
rows.push({
|
|
@@ -89,6 +91,7 @@ export default class TasksPush extends BaseCommand {
|
|
|
89
91
|
task_id: created.id,
|
|
90
92
|
content_hash: created.content_hash,
|
|
91
93
|
details: "created disabled; enable in Mechanic",
|
|
94
|
+
url: taskAdminUrl(project, created.id),
|
|
92
95
|
});
|
|
93
96
|
continue;
|
|
94
97
|
}
|
|
@@ -109,7 +112,7 @@ export default class TasksPush extends BaseCommand {
|
|
|
109
112
|
task,
|
|
110
113
|
...(force ? { force: true } : { previous_content_hash: link.last_remote_content_hash }),
|
|
111
114
|
});
|
|
112
|
-
links = updateLink({ ...project, links }, slug, updated.id, updated.content_hash);
|
|
115
|
+
links = updateLink({ ...project, links }, slug, updated.id, updated.content_hash, contentHash(taskForPush(updated.task)));
|
|
113
116
|
await saveLinks(project, links);
|
|
114
117
|
await writeTaskFilePathAndRefreshHelper(file, updated.task);
|
|
115
118
|
rows.push({
|
|
@@ -118,6 +121,7 @@ export default class TasksPush extends BaseCommand {
|
|
|
118
121
|
task_id: updated.id,
|
|
119
122
|
content_hash: updated.content_hash,
|
|
120
123
|
details: "",
|
|
124
|
+
url: taskAdminUrl(project, updated.id),
|
|
121
125
|
});
|
|
122
126
|
}
|
|
123
127
|
return rows;
|
|
@@ -249,10 +253,10 @@ export default class TasksPush extends BaseCommand {
|
|
|
249
253
|
"The helper directory has changes that are not bundled into the JSON file.",
|
|
250
254
|
"",
|
|
251
255
|
"Bundle first:",
|
|
252
|
-
` mechanic tasks bundle ${
|
|
256
|
+
` mechanic tasks bundle ${slug}`,
|
|
253
257
|
"",
|
|
254
258
|
"Then publish:",
|
|
255
|
-
` mechanic tasks publish ${
|
|
259
|
+
` mechanic tasks publish ${slug}`,
|
|
256
260
|
].join("\n");
|
|
257
261
|
if (!collectBlockedRows) {
|
|
258
262
|
throw new CliError(message, 2);
|
|
@@ -263,7 +267,7 @@ export default class TasksPush extends BaseCommand {
|
|
|
263
267
|
status: "blocked",
|
|
264
268
|
task_id: null,
|
|
265
269
|
content_hash: null,
|
|
266
|
-
details: `bundle ${
|
|
270
|
+
details: `bundle ${slug} first`,
|
|
267
271
|
});
|
|
268
272
|
continue;
|
|
269
273
|
}
|
|
@@ -352,6 +356,17 @@ export default class TasksPush extends BaseCommand {
|
|
|
352
356
|
]),
|
|
353
357
|
];
|
|
354
358
|
}
|
|
359
|
+
printCreatedTaskLinks(rows) {
|
|
360
|
+
const createdRows = rows.filter((row) => row.status === "created" && row.url);
|
|
361
|
+
if (createdRows.length === 0) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
this.log("");
|
|
365
|
+
this.log(this.accent(createdRows.length === 1 ? "Open created task:" : "Open created tasks:"));
|
|
366
|
+
for (const row of createdRows) {
|
|
367
|
+
this.log(` ${this.taskName(row.file)} ${this.taskName(row.url || "")}`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
355
370
|
planLabel(plan) {
|
|
356
371
|
switch (plan) {
|
|
357
372
|
case "would create":
|
|
@@ -15,7 +15,7 @@ export default class TasksStatus extends BaseCommand {
|
|
|
15
15
|
};
|
|
16
16
|
static flags: {
|
|
17
17
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
-
|
|
18
|
+
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
19
|
};
|
|
20
20
|
run(): Promise<void>;
|
|
21
21
|
helperStatus(project: Project, file: string, task: JsonObject): Promise<HelperStatus>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/status.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAe9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE1D,KAAK,YAAY,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/status.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAe9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE1D,KAAK,YAAY,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAuBF,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,WAAW;IAClD,OAAgB,OAAO,SAAwE;IAC/F,OAAgB,WAAW,SAA+Q;IAE1S,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;;MAOnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAsHpB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IA4BrF,YAAY,CAChB,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,GACnC,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAsB/C,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAejC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAgBnC"}
|
|
@@ -5,22 +5,22 @@ import { linkForSlug } from "../../config.js";
|
|
|
5
5
|
import { pathExists } from "../../fs.js";
|
|
6
6
|
import { stableStringify } from "../../json.js";
|
|
7
7
|
import { displayTaskPath, helperDirForTaskFile, readRawTaskFile, remoteChangedSinceLastPull, remoteChangedSinceLastPullDetails, selectedTaskFiles, slugFromTaskFile, taskForPush, unbundledHelperDirForTaskFile, validateTaskForPush, } from "../../tasks.js";
|
|
8
|
+
const IMPLICIT_REMOTE_CHECK_LIMIT = 25;
|
|
8
9
|
function errorMessage(error) {
|
|
9
10
|
return error instanceof Error ? error.message : String(error);
|
|
10
11
|
}
|
|
11
12
|
export default class TasksStatus extends BaseCommand {
|
|
12
|
-
static summary = "Show local task
|
|
13
|
-
static description =
|
|
13
|
+
static summary = "Show whether local task files are ready and in sync with Mechanic.";
|
|
14
|
+
static description = `Show whether local task files are linked, ready to publish, and in sync with their remote Mechanic tasks. Repo-wide status checks remote state for up to ${IMPLICIT_REMOTE_CHECK_LIMIT} tasks; larger projects show local status only. Use --local to skip remote checks.`;
|
|
14
15
|
static args = {
|
|
15
|
-
file: Args.string({ required: false, description: "
|
|
16
|
+
file: Args.string({ required: false, description: "Local task slug, task file, helper directory, or linked task ID. Defaults to every task JSON file." }),
|
|
16
17
|
};
|
|
17
18
|
static flags = {
|
|
18
19
|
json: Flags.boolean({
|
|
19
20
|
description: "Print task status as JSON for agents, scripts, or editor integrations.",
|
|
20
21
|
}),
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
description: "Check linked remote tasks and report no-change, local-change, or conflict state.",
|
|
22
|
+
local: Flags.boolean({
|
|
23
|
+
description: "Only check local files and links; do not call Mechanic.",
|
|
24
24
|
}),
|
|
25
25
|
};
|
|
26
26
|
async run() {
|
|
@@ -29,6 +29,8 @@ export default class TasksStatus extends BaseCommand {
|
|
|
29
29
|
const files = await selectedTaskFiles(project, args.file, !args.file);
|
|
30
30
|
const statuses = [];
|
|
31
31
|
let client = null;
|
|
32
|
+
const remoteSkippedForLimit = !flags.local && !args.file && files.length > IMPLICIT_REMOTE_CHECK_LIMIT;
|
|
33
|
+
const checkRemote = !flags.local && !remoteSkippedForLimit;
|
|
32
34
|
const getClient = async () => {
|
|
33
35
|
client ||= await this.verifiedClientForProject(project);
|
|
34
36
|
return client;
|
|
@@ -64,9 +66,9 @@ export default class TasksStatus extends BaseCommand {
|
|
|
64
66
|
if (helperStatus.details) {
|
|
65
67
|
details.push(helperStatus.details);
|
|
66
68
|
}
|
|
67
|
-
const remote =
|
|
69
|
+
const remote = checkRemote && task && !helperStatus.blocked
|
|
68
70
|
? await this.remoteStatus(link ? await getClient() : null, task, link)
|
|
69
|
-
:
|
|
71
|
+
: checkRemote ? { label: "skipped", details: undefined } : null;
|
|
70
72
|
if (remote?.details) {
|
|
71
73
|
details.push(remote.details);
|
|
72
74
|
}
|
|
@@ -86,14 +88,19 @@ export default class TasksStatus extends BaseCommand {
|
|
|
86
88
|
});
|
|
87
89
|
}
|
|
88
90
|
if (flags.json) {
|
|
89
|
-
|
|
91
|
+
const output = {
|
|
90
92
|
shop_domain: project.shopDomain,
|
|
91
|
-
remote_checked:
|
|
93
|
+
remote_checked: checkRemote,
|
|
92
94
|
tasks: statuses,
|
|
93
|
-
}
|
|
95
|
+
};
|
|
96
|
+
if (remoteSkippedForLimit) {
|
|
97
|
+
output.remote_skipped_reason = "too_many_tasks";
|
|
98
|
+
output.remote_check_limit = IMPLICIT_REMOTE_CHECK_LIMIT;
|
|
99
|
+
}
|
|
100
|
+
this.outputJson(output);
|
|
94
101
|
return;
|
|
95
102
|
}
|
|
96
|
-
const rows =
|
|
103
|
+
const rows = checkRemote
|
|
97
104
|
? [["File", "Link", "Local", "Remote", "Task ID", "Details"]]
|
|
98
105
|
: [["File", "Link", "Local", "Task ID", "Details"]];
|
|
99
106
|
for (const status of statuses) {
|
|
@@ -102,12 +109,17 @@ export default class TasksStatus extends BaseCommand {
|
|
|
102
109
|
status.link.linked ? this.success("linked") : this.color("yellow", "unlinked"),
|
|
103
110
|
this.localLabel(status.local.label),
|
|
104
111
|
];
|
|
105
|
-
if (
|
|
112
|
+
if (checkRemote) {
|
|
106
113
|
row.push(this.remoteLabel(status.remote?.label || "not checked"));
|
|
107
114
|
}
|
|
108
115
|
row.push(status.link.remote_id ? this.taskId(project, status.link.remote_id) : "--", status.details.join("; "));
|
|
109
116
|
rows.push(row);
|
|
110
117
|
}
|
|
118
|
+
if (remoteSkippedForLimit) {
|
|
119
|
+
this.log(this.color("yellow", `Skipped remote checks for ${files.length} tasks (limit ${IMPLICIT_REMOTE_CHECK_LIMIT}).`));
|
|
120
|
+
this.log(`Run "${this.taskName("mechanic tasks status <task>")}" to check one task's remote state.`);
|
|
121
|
+
this.log("");
|
|
122
|
+
}
|
|
111
123
|
this.table(rows);
|
|
112
124
|
}
|
|
113
125
|
async helperStatus(project, file, task) {
|
|
@@ -121,7 +133,7 @@ export default class TasksStatus extends BaseCommand {
|
|
|
121
133
|
return {
|
|
122
134
|
label: "needs bundle",
|
|
123
135
|
blocked: true,
|
|
124
|
-
details: `run mechanic tasks bundle ${
|
|
136
|
+
details: `run mechanic tasks bundle ${slugFromTaskFile(file)}`,
|
|
125
137
|
};
|
|
126
138
|
}
|
|
127
139
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unbundle.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/unbundle.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKpD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;IACpD,OAAgB,OAAO,SAAkD;IACzE,OAAgB,WAAW,
|
|
1
|
+
{"version":3,"file":"unbundle.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/unbundle.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKpD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;IACpD,OAAgB,OAAO,SAAkD;IACzE,OAAgB,WAAW,SAA0I;IACrK,OAAgB,QAAQ,WAKtB;IAEF,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;;MAOnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;YA+BZ,oBAAoB;CA2CnC"}
|
|
@@ -6,15 +6,15 @@ import { pathExists } from "../../fs.js";
|
|
|
6
6
|
import { displayTaskPath, resolveTaskSelector, unbundleTask } from "../../tasks.js";
|
|
7
7
|
export default class TasksUnbundle extends BaseCommand {
|
|
8
8
|
static summary = "Unbundle one task into one helper directory.";
|
|
9
|
-
static description = "Unbundle one canonical task JSON file, linked task ID, helper directory
|
|
9
|
+
static description = "Unbundle one local task slug, canonical task JSON file, linked task ID, or helper directory into one editable helper task directory.";
|
|
10
10
|
static examples = [
|
|
11
|
-
"$ mechanic tasks unbundle tasks/order-tagger.json",
|
|
12
11
|
"$ mechanic tasks unbundle order-tagger",
|
|
12
|
+
"$ mechanic tasks unbundle tasks/order-tagger.json",
|
|
13
13
|
"$ mechanic tasks unbundle 171578bf-79e2-46af-857a-dbd71c6b7b2b",
|
|
14
|
-
"$ mechanic tasks unbundle
|
|
14
|
+
"$ mechanic tasks unbundle order-tagger --out helpers/order-tagger",
|
|
15
15
|
];
|
|
16
16
|
static args = {
|
|
17
|
-
file: Args.string({ required: false, description: "
|
|
17
|
+
file: Args.string({ required: false, description: "Local task slug, task file, helper directory, or linked task ID." }),
|
|
18
18
|
};
|
|
19
19
|
static flags = {
|
|
20
20
|
json: Flags.boolean({
|
|
@@ -31,7 +31,7 @@ export default class TasksUnbundle extends BaseCommand {
|
|
|
31
31
|
"Choose one task to unbundle.",
|
|
32
32
|
"",
|
|
33
33
|
"Example:",
|
|
34
|
-
" mechanic tasks unbundle
|
|
34
|
+
" mechanic tasks unbundle order-tagger",
|
|
35
35
|
"",
|
|
36
36
|
"By default this writes to tasks/order-tagger/. Use --out <dir> to choose another helper directory.",
|
|
37
37
|
].join("\n"), 2);
|
|
@@ -11,5 +11,6 @@ export default class TasksValidate extends BaseCommand {
|
|
|
11
11
|
};
|
|
12
12
|
run(): Promise<void>;
|
|
13
13
|
validateTaskFile(file: string): Promise<ValidationResult>;
|
|
14
|
+
validateTaskDirectory(target: string): Promise<ValidationResult[]>;
|
|
14
15
|
}
|
|
15
16
|
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/validate.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/validate.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;AAUxB,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;IACpD,OAAgB,OAAO,SAA8D;IACrF,OAAgB,WAAW,SAAqH;IAEhJ,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;MAInB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAoDpB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAezD,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAgBzE"}
|