@lightward/mechanic-cli 0.1.6 → 0.1.9

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 CHANGED
@@ -56,7 +56,17 @@ prompted:
56
56
  mechanic init --shop example.myshopify.com
57
57
  ```
58
58
 
59
- Pull existing Mechanic tasks into local JSON files:
59
+ Choose how to start.
60
+
61
+ To bring one existing task into local files, find its remote task ID, then pull
62
+ that task:
63
+
64
+ ```bash
65
+ mechanic tasks list --verbose
66
+ mechanic tasks pull <remote-task-id>
67
+ ```
68
+
69
+ To intentionally bootstrap a repo with every task in the shop:
60
70
 
61
71
  ```bash
62
72
  mechanic tasks pull
@@ -70,15 +80,14 @@ initialized CLI project; it does not require a fresh repository:
70
80
  mechanic tasks new order-tagger
71
81
  ```
72
82
 
73
- For most Liquid or documentation edits, unbundle one task into helper files,
74
- edit those files, then bundle the helper directory back into its canonical JSON
75
- file. The JSON file remains the deployable source of truth; the helper directory
76
- is the comfortable editing view beside it. Tasks created with `tasks new`
77
- already have both files, so you can start editing the helper directory
78
- immediately.
83
+ For most Liquid or documentation edits, use the helper directory beside the JSON
84
+ file. Existing pulled tasks can be unbundled first; tasks created with
85
+ `tasks new` already have the helper directory.
79
86
 
80
87
  ```bash
88
+ # for an existing pulled task only
81
89
  mechanic tasks unbundle order-tagger
90
+
82
91
  # edit tasks/order-tagger/script.liquid, docs.md, or task.json
83
92
  mechanic tasks bundle order-tagger
84
93
  mechanic tasks status
@@ -88,6 +97,10 @@ mechanic tasks publish order-tagger --dry-run
88
97
  mechanic tasks publish order-tagger
89
98
  ```
90
99
 
100
+ For example, edit `tasks/order-tagger/docs.md` or
101
+ `tasks/order-tagger/script.liquid`, bundle it, preview it, then publish only
102
+ when the diff and dry-run plan look right.
103
+
91
104
  For normal setup, paste the token into the masked prompt or run
92
105
  `mechanic auth login` after `mechanic init`. In CI, store the token as
93
106
  `MECHANIC_API_TOKEN`. The `--token` flag exists for controlled automation, but
@@ -184,10 +197,11 @@ the fast offline check for JSON validity, link state, and helper-folder drift.
184
197
  Add `--json` when an editor integration needs task readiness, link state, and
185
198
  remote sync state without parsing table output.
186
199
 
187
- `tasks diff` compares the current remote task to your local file, groups output
188
- by changed field, and only shows nearby changed lines. Differences are
189
- informational by default; add `--exit-code` when a script or CI job should treat
190
- differences as a nonzero result.
200
+ `tasks diff` compares current Mechanic with your local file, groups output by
201
+ changed field, and only shows nearby changed lines. In diff output, `-` means
202
+ current Mechanic and `+` means local file. Differences are informational by
203
+ default; add `--exit-code` when a script or CI job should treat differences as a
204
+ nonzero result.
191
205
 
192
206
  `tasks preview` is the confidence check before publishing. It sends one local
193
207
  task to Mechanic's preview engine without saving it, then reports whether the
@@ -412,12 +426,15 @@ Mechanic app or by another local checkout.
412
426
 
413
427
  - `tasks pull` records the latest remote content hash in `.mechanic/links.json`.
414
428
  - `tasks pull <task>` can refresh a linked local file without `--force` when the
415
- local file still matches the last pulled hash. If local edits would be lost,
429
+ local file still matches the last synced hash. If local edits would be lost,
416
430
  it stops and asks for an explicit `--force`.
417
431
  - `tasks publish` sends that hash as `previous_content_hash`.
418
432
  - The API rejects stale publishes with a conflict.
419
- - `tasks diff` warns when the remote task changed since your last pull, then
420
- compares the current Mechanic task with your local file.
433
+ - `tasks diff` warns when Mechanic changed since the file was last synced, then
434
+ compares current Mechanic with your local file. If only Mechanic changed, pull
435
+ normally to update your local file. If both Mechanic and your local file
436
+ changed, choose explicitly: pull with `--force` to replace local with
437
+ Mechanic, or publish with `--force` to overwrite Mechanic with local.
421
438
  - `tasks publish --all` checks every linked remote task before writing anything,
422
439
  so one stale task blocks the whole publish instead of partially publishing
423
440
  earlier files first.
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/github/init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKpD,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IACjD,OAAgB,OAAO,SAA4E;IACnG,OAAgB,WAAW,SAAiH;IAE5I,OAAgB,KAAK;;MAEnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA2C3B"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/github/init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKpD,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IACjD,OAAgB,OAAO,SAAqF;IAC5G,OAAgB,WAAW,SAA0H;IAErJ,OAAgB,KAAK;;MAEnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA2C3B"}
@@ -5,8 +5,8 @@ import { CliError } from "../../errors.js";
5
5
  import { ensureDir, pathExists, writeText } from "../../fs.js";
6
6
  import { githubWorkflowFiles } from "../../github-workflows.js";
7
7
  export default class GithubInit extends BaseCommand {
8
- static summary = "Create GitHub Actions workflows for single-shop Mechanic task updates.";
9
- static description = "Create validation, manual deploy, and pull-from-app GitHub Actions workflows for this Mechanic CLI project.";
8
+ static summary = "Create optional GitHub Actions workflows for single-shop Mechanic task updates.";
9
+ static description = "Create optional validation, manual deploy, and pull-from-app GitHub Actions workflows for this Mechanic CLI project.";
10
10
  static flags = {
11
11
  force: Flags.boolean({ description: "Overwrite existing Mechanic GitHub workflow files." }),
12
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AASjD,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,WAAW;IAC3C,OAAgB,WAAW,SAAkD;IAE7E,OAAgB,KAAK;;;;;;MAQnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAgE3B"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AASjD,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,WAAW;IAC3C,OAAgB,WAAW,SAAkD;IAE7E,OAAgB,KAAK;;;;;;MAQnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAiE3B"}
@@ -59,6 +59,7 @@ export default class Init extends BaseCommand {
59
59
  this.log("");
60
60
  this.log("Next steps:");
61
61
  if (!storedToken) {
62
+ this.log(" create an API token in Mechanic: Settings -> API tokens");
62
63
  this.log(` ${this.taskName("mechanic auth login")}`);
63
64
  }
64
65
  this.log(` ${this.taskName("mechanic tasks pull")}`);
@@ -1 +1 @@
1
- {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/diff.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAYpD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,OAAgB,OAAO,SAA2D;IAClF,OAAgB,WAAW,SAA6G;IAExI,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;;;MAMnB;IAEF,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IA2BzB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA4H3B"}
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/diff.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAapD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,OAAgB,OAAO,SAA2D;IAClF,OAAgB,WAAW,SAA6G;IAExI,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;;;MAMnB;IAEF,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IA2BzB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAwI3B"}
@@ -1,7 +1,7 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
2
  import { BaseCommand } from "../../base-command.js";
3
3
  import { linkForSlug } from "../../config.js";
4
- import { diffTasks, displayTaskPath, readTaskFile, remoteChangedSinceLastPull, selectedTaskFiles, slugFromTaskFile, taskForPush, } from "../../tasks.js";
4
+ import { diffTasks, displayTaskPath, localChangedSinceLastSync, readTaskFile, remoteChangedSinceLastPull, selectedTaskFiles, slugFromTaskFile, taskForPush, } from "../../tasks.js";
5
5
  export default class TasksDiff extends BaseCommand {
6
6
  static summary = "Diff one task, or use --all to diff every local task.";
7
7
  static description = "Compare one local task with its linked remote task, or use --all to compare every local task JSON file.";
@@ -51,6 +51,7 @@ export default class TasksDiff extends BaseCommand {
51
51
  const relativeFile = displayTaskPath(project, file);
52
52
  if (!link) {
53
53
  hasUnlinkedTasks = true;
54
+ const message = `No remote task is linked yet. Run "mechanic tasks publish ${slug} --dry-run" to review the disabled create plan.`;
54
55
  results.push({
55
56
  file: relativeFile,
56
57
  slug,
@@ -59,9 +60,9 @@ export default class TasksDiff extends BaseCommand {
59
60
  remote_changed: false,
60
61
  field_differences: false,
61
62
  diff: null,
62
- message: "Task is not linked to a remote task.",
63
+ message,
63
64
  });
64
- differences.push(`# ${relativeFile}\nTask is not linked to a remote task.`);
65
+ differences.push(`# ${relativeFile}\n${message}`);
65
66
  continue;
66
67
  }
67
68
  const localTask = taskForPush(await readTaskFile(file));
@@ -69,6 +70,7 @@ export default class TasksDiff extends BaseCommand {
69
70
  const remoteTask = taskForPush(remote.task);
70
71
  const diff = diffTasks(localTask, remoteTask);
71
72
  const remoteChanged = remoteChangedSinceLastPull(link, remote);
73
+ const localChanged = localChangedSinceLastSync(link, localTask);
72
74
  const hasDiff = Boolean(diff);
73
75
  if (remoteChanged) {
74
76
  hasRemoteChanges = true;
@@ -88,13 +90,23 @@ export default class TasksDiff extends BaseCommand {
88
90
  if (remoteChanged || diff) {
89
91
  const section = [`# ${relativeFile}`];
90
92
  if (remoteChanged) {
91
- section.push(this.color("yellow", "Remote changed since your last pull."), this.muted("Showing what would change if your local file replaced the current Mechanic task."), this.muted("Diff legend: - current Mechanic, + local file."), this.muted(`Run "mechanic tasks pull ${link.remote_id}" to keep the Mechanic version, or use --force only if the local file should win.`), "");
93
+ section.push(this.color("yellow", localChanged
94
+ ? "Mechanic and your local file both changed since this file was last synced."
95
+ : "Mechanic changed since this file was last synced."), this.muted("Showing current Mechanic compared with your local file."), this.muted("Diff legend: - current Mechanic, + local file."), ...(localChanged ? [
96
+ this.muted("This compares the current versions; it does not show edit history."),
97
+ this.muted("A normal pull will stop because local changes would be overwritten."),
98
+ this.muted(`Run "mechanic tasks pull ${link.remote_id} --force" only if current Mechanic should replace your local file.`),
99
+ this.muted(`Run "mechanic tasks publish ${relativeFile} --force" only if your local file should overwrite Mechanic.`),
100
+ ] : [
101
+ this.muted("Your local file has no unsynced changes."),
102
+ this.muted(`Run "mechanic tasks pull ${link.remote_id}" to update your local file from current Mechanic.`),
103
+ ]), "");
92
104
  }
93
105
  if (diff) {
94
106
  section.push(diff);
95
107
  }
96
108
  else {
97
- section.push("No field differences between the current remote task and your local file.");
109
+ section.push("No field differences between current Mechanic and your local file.");
98
110
  }
99
111
  differences.push(this.colorDiff(section.join("\n")));
100
112
  }
@@ -123,7 +135,7 @@ export default class TasksDiff extends BaseCommand {
123
135
  summary = "Remote changes found.";
124
136
  }
125
137
  else if (!hasFieldDifferences && hasUnlinkedTasks) {
126
- summary = "Unlinked tasks found.";
138
+ summary = "No remote task linked yet.";
127
139
  }
128
140
  this.log(summary);
129
141
  if (flags["exit-code"]) {
@@ -1 +1 @@
1
- {"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/new.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAwCpD,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,WAAW;IAC/C,OAAgB,OAAO,SAAoC;IAC3D,OAAgB,WAAW,SAAiJ;IAC5K,OAAgB,QAAQ,WAGtB;IAEF,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;;MAGnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;YA0CZ,kBAAkB;CA2BjC"}
1
+ {"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/new.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAyCpD,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,WAAW;IAC/C,OAAgB,OAAO,SAAoC;IAC3D,OAAgB,WAAW,SAAiJ;IAC5K,OAAgB,QAAQ,WAGtB;IAEF,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;;MAGnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;YA0CZ,kBAAkB;CAoCjC"}
@@ -1,6 +1,7 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
2
  import path from "node:path";
3
3
  import { BaseCommand } from "../../base-command.js";
4
+ import { linkForSlug } from "../../config.js";
4
5
  import { CliError } from "../../errors.js";
5
6
  import { pathExists } from "../../fs.js";
6
7
  import { displayTaskPath, taskPath, taskSlug, unbundleTask, writeTaskFilePath } from "../../tasks.js";
@@ -59,7 +60,7 @@ export default class TasksNew extends BaseCommand {
59
60
  const name = taskNameFromInput(requestedName);
60
61
  const filePath = taskPath(project, slug);
61
62
  const helperDir = filePath.replace(/\.json$/i, "");
62
- await this.checkExistingPaths(project, filePath, helperDir, Boolean(flags.force));
63
+ await this.checkExistingPaths(project, slug, filePath, helperDir, Boolean(flags.force));
63
64
  await writeTaskFilePath(filePath, starterTask(name));
64
65
  await unbundleTask(filePath, helperDir);
65
66
  const fileDisplay = displayTaskPath(project, filePath);
@@ -83,7 +84,14 @@ export default class TasksNew extends BaseCommand {
83
84
  this.log(` mechanic tasks bundle ${this.taskName(slug)}`);
84
85
  this.log(` mechanic tasks publish ${this.taskName(slug)}`);
85
86
  }
86
- async checkExistingPaths(project, filePath, helperDir, force) {
87
+ async checkExistingPaths(project, slug, filePath, helperDir, force) {
88
+ const link = linkForSlug(project, slug);
89
+ if (link) {
90
+ throw new CliError([
91
+ `${slug} is already linked to a Mechanic task.`,
92
+ `Run "mechanic tasks pull ${link.remote_id}" to refresh it, or choose another name for a new task.`,
93
+ ].join("\n"), 2);
94
+ }
87
95
  if (force) {
88
96
  return;
89
97
  }
@@ -68,7 +68,7 @@ export default class TasksPull extends BaseCommand {
68
68
  throw new CliError([
69
69
  `${displayTaskPath(project, filePath)} has local changes that would be overwritten.`,
70
70
  `Run "mechanic tasks diff ${displayTaskPath(project, filePath)}" to review them.`,
71
- `Re-run "mechanic tasks pull ${envelope.id} --force" only if the remote version should replace the local file.`,
71
+ `Re-run "mechanic tasks pull ${envelope.id} --force" only if current Mechanic should replace your local file.`,
72
72
  ].join("\n"), 2);
73
73
  }
74
74
  }
@@ -18,6 +18,7 @@ type PushRow = {
18
18
  task_id: string | null;
19
19
  content_hash: string | null;
20
20
  details: string;
21
+ enabled?: boolean | null;
21
22
  url?: string;
22
23
  };
23
24
  type CreateCollision = {
@@ -55,7 +56,7 @@ export default class TasksPush extends BaseCommand {
55
56
  rows: PushRow[];
56
57
  }>;
57
58
  pushRowsToTable(project: Project, statusHeader: string, rows: PushRow[], label: (status: string) => string): string[][];
58
- printCreatedTaskLinks(rows: PushRow[]): void;
59
+ printPublishedTaskLinks(rows: PushRow[]): void;
59
60
  planLabel(plan: string): string;
60
61
  }
61
62
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/push.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/push.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ import { linkForSlug, saveLinks, taskAdminUrl, updateLink } from "../../config.j
5
5
  import { CliError } from "../../errors.js";
6
6
  import { contentHash } from "../../hash.js";
7
7
  import { stableStringify } from "../../json.js";
8
- import { displayTaskPath, remoteChangedSinceLastPull, remoteChangedSinceLastPullDetails, remoteChangedSinceLastPullMessage, selectedTaskFiles, readRawTaskFile, slugFromTaskFile, taskForPush, taskSlug, unbundledHelperDirForTaskFile, validateTaskForPush, writeTaskFilePathAndRefreshHelper, } from "../../tasks.js";
8
+ import { displayTaskPath, localChangedSinceLastSync, remoteChangedSinceLastPull, remoteChangedSinceLastPullDetails, remoteChangedSinceLastPullMessage, selectedTaskFiles, readRawTaskFile, slugFromTaskFile, taskForPush, taskSlug, unbundledHelperDirForTaskFile, validateTaskForPush, writeTaskFilePathAndRefreshHelper, } from "../../tasks.js";
9
9
  function createTaskIdempotencyKey(shopDomain, slug) {
10
10
  const hex = createHash("sha256")
11
11
  .update(`mechanic-cli-task-create\0${shopDomain}\0${slug}`)
@@ -18,6 +18,25 @@ function createTaskIdempotencyKey(shopDomain, slug) {
18
18
  hex.slice(20, 32),
19
19
  ].join("-");
20
20
  }
21
+ function remoteTaskEnabled(envelope) {
22
+ if (typeof envelope.enabled === "boolean") {
23
+ return envelope.enabled;
24
+ }
25
+ if (typeof envelope.task.enabled === "boolean") {
26
+ return envelope.task.enabled;
27
+ }
28
+ return null;
29
+ }
30
+ function remoteTaskStateDetail(envelope) {
31
+ const enabled = remoteTaskEnabled(envelope);
32
+ if (enabled === true) {
33
+ return "currently enabled";
34
+ }
35
+ if (enabled === false) {
36
+ return "currently disabled";
37
+ }
38
+ return "";
39
+ }
21
40
  export default class TasksPush extends BaseCommand {
22
41
  static hidden = true;
23
42
  static summary = "Publish one local task, or use --all to publish every local task.";
@@ -68,7 +87,7 @@ export default class TasksPush extends BaseCommand {
68
87
  return;
69
88
  }
70
89
  this.table(this.pushRowsToTable(project, "Action", rows, (status) => this.actionLabel(status)));
71
- this.printCreatedTaskLinks(rows);
90
+ this.printPublishedTaskLinks(rows);
72
91
  }
73
92
  async publishTasks(project, preparation, force) {
74
93
  const client = await this.verifiedClientForProject(project);
@@ -91,22 +110,25 @@ export default class TasksPush extends BaseCommand {
91
110
  task_id: created.id,
92
111
  content_hash: created.content_hash,
93
112
  details: "created disabled; enable in Mechanic",
113
+ enabled: remoteTaskEnabled(created),
94
114
  url: taskAdminUrl(project, created.id),
95
115
  });
96
116
  continue;
97
117
  }
98
- if (!force) {
99
- const remote = remoteBySlug.get(slug) || await client.getTask(link.remote_id);
100
- if (stableStringify(task) === stableStringify(taskForPush(remote.task))) {
101
- rows.push({
102
- file: relativeFile,
103
- status: "skipped",
104
- task_id: remote.id,
105
- content_hash: remote.content_hash,
106
- details: "",
107
- });
108
- continue;
109
- }
118
+ const remote = force
119
+ ? await client.getTask(link.remote_id)
120
+ : remoteBySlug.get(slug) || await client.getTask(link.remote_id);
121
+ if (stableStringify(task) === stableStringify(taskForPush(remote.task))) {
122
+ rows.push({
123
+ file: relativeFile,
124
+ status: "skipped",
125
+ task_id: remote.id,
126
+ content_hash: remote.content_hash,
127
+ details: remoteTaskStateDetail(remote),
128
+ enabled: remoteTaskEnabled(remote),
129
+ url: taskAdminUrl(project, remote.id),
130
+ });
131
+ continue;
110
132
  }
111
133
  const updated = await client.updateTask(link.remote_id, {
112
134
  task,
@@ -120,7 +142,8 @@ export default class TasksPush extends BaseCommand {
120
142
  status: force ? "forced" : "updated",
121
143
  task_id: updated.id,
122
144
  content_hash: updated.content_hash,
123
- details: "",
145
+ details: remoteTaskStateDetail(updated),
146
+ enabled: remoteTaskEnabled(updated),
124
147
  url: taskAdminUrl(project, updated.id),
125
148
  });
126
149
  }
@@ -129,7 +152,7 @@ export default class TasksPush extends BaseCommand {
129
152
  async preflightRemoteChanges(client, project, links, preparedTasks) {
130
153
  const remoteBySlug = new Map();
131
154
  const conflicts = [];
132
- for (const { slug, relativeFile } of preparedTasks) {
155
+ for (const { slug, relativeFile, task } of preparedTasks) {
133
156
  const link = linkForSlug({ ...project, links }, slug);
134
157
  if (!link) {
135
158
  continue;
@@ -137,12 +160,12 @@ export default class TasksPush extends BaseCommand {
137
160
  const remote = await client.getTask(link.remote_id);
138
161
  remoteBySlug.set(slug, remote);
139
162
  if (remoteChangedSinceLastPull(link, remote)) {
140
- conflicts.push(remoteChangedSinceLastPullMessage(relativeFile, link.remote_id));
163
+ conflicts.push(remoteChangedSinceLastPullMessage(relativeFile, link.remote_id, localChangedSinceLastSync(link, task)));
141
164
  }
142
165
  }
143
166
  if (conflicts.length > 0) {
144
167
  throw new CliError([
145
- "Remote changes found before publishing. Nothing was published.",
168
+ "Mechanic changes found before publishing. Nothing was published.",
146
169
  "",
147
170
  ...conflicts.map((conflict) => `- ${conflict}`),
148
171
  ].join("\n"), 2);
@@ -326,7 +349,7 @@ export default class TasksPush extends BaseCommand {
326
349
  status: "conflict",
327
350
  task_id: remote.id,
328
351
  content_hash: remote.content_hash,
329
- details: remoteChangedSinceLastPullDetails(),
352
+ details: remoteChangedSinceLastPullMessage(relativeFile, remote.id, localChangedSinceLastSync(link, task)),
330
353
  });
331
354
  continue;
332
355
  }
@@ -356,14 +379,14 @@ export default class TasksPush extends BaseCommand {
356
379
  ]),
357
380
  ];
358
381
  }
359
- printCreatedTaskLinks(rows) {
360
- const createdRows = rows.filter((row) => row.status === "created" && row.url);
361
- if (createdRows.length === 0) {
382
+ printPublishedTaskLinks(rows) {
383
+ const publishedRows = rows.filter((row) => ["created", "updated", "forced"].includes(row.status) && row.url);
384
+ if (publishedRows.length === 0) {
362
385
  return;
363
386
  }
364
387
  this.log("");
365
- this.log(this.accent(createdRows.length === 1 ? "Open created task:" : "Open created tasks:"));
366
- for (const row of createdRows) {
388
+ this.log(this.accent(publishedRows.length === 1 ? "Open task:" : "Open published tasks:"));
389
+ for (const row of publishedRows) {
367
390
  this.log(` ${this.taskName(row.file)} ${this.taskName(row.url || "")}`);
368
391
  }
369
392
  }
@@ -7,6 +7,25 @@ type HelperStatus = {
7
7
  blocked: boolean;
8
8
  details?: string;
9
9
  };
10
+ type TaskStatusResult = {
11
+ file: string;
12
+ slug: string;
13
+ link: {
14
+ linked: boolean;
15
+ remote_id: string | null;
16
+ };
17
+ local: HelperStatus;
18
+ remote: {
19
+ label: string;
20
+ details?: string;
21
+ task_id?: string;
22
+ task_name?: string;
23
+ updated_at?: string | null;
24
+ enabled?: boolean | null;
25
+ url?: string;
26
+ } | null;
27
+ details: string[];
28
+ };
10
29
  export default class TasksStatus extends BaseCommand {
11
30
  static summary: string;
12
31
  static description: string;
@@ -19,12 +38,11 @@ export default class TasksStatus extends BaseCommand {
19
38
  };
20
39
  run(): Promise<void>;
21
40
  helperStatus(project: Project, file: string, task: JsonObject): Promise<HelperStatus>;
22
- remoteStatus(client: MechanicClient | null, task: JsonObject, link: ReturnType<typeof linkForSlug>): Promise<{
23
- label: string;
24
- details?: string;
25
- }>;
41
+ remoteStatus(project: Project, client: MechanicClient | null, task: JsonObject, link: ReturnType<typeof linkForSlug>, relativeFile: string): Promise<TaskStatusResult["remote"]>;
42
+ printSingleTaskInfo(project: Project, statuses: TaskStatusResult[], checkRemote: boolean): void;
26
43
  localLabel(label: string): string;
27
44
  remoteLabel(label: string): string;
45
+ enabledLabel(enabled: boolean | null | undefined): string;
28
46
  }
29
47
  export {};
30
48
  //# sourceMappingURL=status.d.ts.map
@@ -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;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"}
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,EAAgB,MAAM,iBAAiB,CAAC;AAgB5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAgB,MAAM,gBAAgB,CAAC;AAExE,KAAK,YAAY,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE;QACJ,MAAM,EAAE,OAAO,CAAC;QAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC;IACF,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QACzB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,IAAI,CAAC;IACT,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AA0BF,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;IAuHpB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IA4BrF,YAAY,CAChB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,EACpC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAiCtC,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE,WAAW,EAAE,OAAO,GAAG,IAAI;IAwB/F,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAejC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAmBlC,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM;CAW1D"}
@@ -1,14 +1,28 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
2
  import path from "node:path";
3
3
  import { BaseCommand } from "../../base-command.js";
4
- import { linkForSlug } from "../../config.js";
4
+ import { linkForSlug, taskAdminUrl } from "../../config.js";
5
5
  import { pathExists } from "../../fs.js";
6
6
  import { stableStringify } from "../../json.js";
7
- import { displayTaskPath, helperDirForTaskFile, readRawTaskFile, remoteChangedSinceLastPull, remoteChangedSinceLastPullDetails, selectedTaskFiles, slugFromTaskFile, taskForPush, unbundledHelperDirForTaskFile, validateTaskForPush, } from "../../tasks.js";
7
+ import { displayTaskPath, helperDirForTaskFile, localChangedSinceLastSync, readRawTaskFile, remoteChangedSinceLastPull, remoteChangedSinceLastPullMessage, selectedTaskFiles, slugFromTaskFile, taskForPush, unbundledHelperDirForTaskFile, validateTaskForPush, } from "../../tasks.js";
8
8
  const IMPLICIT_REMOTE_CHECK_LIMIT = 25;
9
9
  function errorMessage(error) {
10
10
  return error instanceof Error ? error.message : String(error);
11
11
  }
12
+ function remoteTaskEnabled(envelope) {
13
+ if (typeof envelope.enabled === "boolean") {
14
+ return envelope.enabled;
15
+ }
16
+ if (typeof envelope.task.enabled === "boolean") {
17
+ return envelope.task.enabled;
18
+ }
19
+ return null;
20
+ }
21
+ function remoteTaskName(envelope) {
22
+ return typeof envelope.task.name === "string" && envelope.task.name.trim()
23
+ ? envelope.task.name
24
+ : envelope.id;
25
+ }
12
26
  export default class TasksStatus extends BaseCommand {
13
27
  static summary = "Show whether local task files are ready and in sync with Mechanic.";
14
28
  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.`;
@@ -67,13 +81,13 @@ export default class TasksStatus extends BaseCommand {
67
81
  details.push(helperStatus.details);
68
82
  }
69
83
  const remote = checkRemote && task && !helperStatus.blocked
70
- ? await this.remoteStatus(link ? await getClient() : null, task, link)
84
+ ? await this.remoteStatus(project, link ? await getClient() : null, task, link, relativeFile)
71
85
  : checkRemote ? { label: "skipped", details: undefined } : null;
72
86
  if (remote?.details) {
73
87
  details.push(remote.details);
74
88
  }
75
89
  else if (!link && task && !helperStatus.blocked) {
76
- details.push("publish will create disabled task");
90
+ details.push("run publish --dry-run to check create plan");
77
91
  }
78
92
  statuses.push({
79
93
  file: relativeFile,
@@ -121,6 +135,7 @@ export default class TasksStatus extends BaseCommand {
121
135
  this.log("");
122
136
  }
123
137
  this.table(rows);
138
+ this.printSingleTaskInfo(project, statuses, checkRemote);
124
139
  }
125
140
  async helperStatus(project, file, task) {
126
141
  const helperDir = helperDirForTaskFile(file);
@@ -146,21 +161,52 @@ export default class TasksStatus extends BaseCommand {
146
161
  }
147
162
  return { label: "ready", blocked: false };
148
163
  }
149
- async remoteStatus(client, task, link) {
164
+ async remoteStatus(project, client, task, link, relativeFile) {
150
165
  if (!link) {
151
- return { label: "will create", details: "publish will create disabled task" };
166
+ return { label: "unlinked", details: "run publish --dry-run to check create plan" };
152
167
  }
153
168
  if (!client) {
154
169
  return { label: "not checked" };
155
170
  }
156
171
  const remote = await client.getTask(link.remote_id);
172
+ const taskDetails = {
173
+ task_id: remote.id,
174
+ task_name: remoteTaskName(remote),
175
+ updated_at: remote.updated_at || null,
176
+ enabled: remoteTaskEnabled(remote),
177
+ url: taskAdminUrl(project, remote.id),
178
+ };
157
179
  if (remoteChangedSinceLastPull(link, remote)) {
158
- return { label: "conflict", details: remoteChangedSinceLastPullDetails() };
180
+ return {
181
+ label: "conflict",
182
+ details: remoteChangedSinceLastPullMessage(relativeFile, link.remote_id, localChangedSinceLastSync(link, task)),
183
+ ...taskDetails,
184
+ };
159
185
  }
160
186
  if (stableStringify(taskForPush(task)) !== stableStringify(taskForPush(remote.task))) {
161
- return { label: "local changes", details: "publish would update" };
187
+ return { label: "local changes", details: "publish would update", ...taskDetails };
188
+ }
189
+ return { label: "no change", ...taskDetails };
190
+ }
191
+ printSingleTaskInfo(project, statuses, checkRemote) {
192
+ if (!checkRemote || statuses.length !== 1) {
193
+ return;
194
+ }
195
+ const status = statuses[0];
196
+ const remote = status.remote;
197
+ if (!remote?.task_id) {
198
+ return;
162
199
  }
163
- return { label: "no change" };
200
+ this.log("");
201
+ this.log(this.accent("Task details"));
202
+ this.table([
203
+ ["Field", "Value"],
204
+ ["Name", this.taskName(remote.task_name || remote.task_id)],
205
+ ["State", this.enabledLabel(remote.enabled)],
206
+ ["Updated", this.muted(remote.updated_at || "--")],
207
+ ["Task ID", this.taskId(project, remote.task_id)],
208
+ ["URL", this.taskName(remote.url || taskAdminUrl(project, remote.task_id))],
209
+ ]);
164
210
  }
165
211
  localLabel(label) {
166
212
  switch (label) {
@@ -185,6 +231,8 @@ export default class TasksStatus extends BaseCommand {
185
231
  return this.color("cyan", label);
186
232
  case "conflict":
187
233
  return this.color("red", label);
234
+ case "unlinked":
235
+ return this.color("yellow", label);
188
236
  case "skipped":
189
237
  case "not checked":
190
238
  return this.muted(label);
@@ -192,4 +240,13 @@ export default class TasksStatus extends BaseCommand {
192
240
  return label;
193
241
  }
194
242
  }
243
+ enabledLabel(enabled) {
244
+ if (enabled === true) {
245
+ return this.success("enabled");
246
+ }
247
+ if (enabled === false) {
248
+ return this.color("yellow", "disabled");
249
+ }
250
+ return this.muted("unknown");
251
+ }
195
252
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEhF,eAAO,MAAM,oBAAoB,QAAkE,CAAC;AA0BpG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAyBzD;AA+BD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,SAA4B,GAAG,MAAM,CAG9F;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,UAAU,SAAuB,EACjC,MAAM,SAA4D,GACjE,cAAc,CAOhB;AAED,wBAAgB,UAAU,IAAI,SAAS,CAEtC;AA6ED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,UAAQ,GACZ,OAAO,CAAC,OAAO,CAAC,CA2BlB;AAED,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA0BhF;AAED,wBAAsB,WAAW,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAkCvE;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjF;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE5E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEjF;AAyBD,wBAAgB,UAAU,CACxB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,gBAAgB,CAAC,EAAE,MAAM,EACzB,QAAQ,CAAC,EAAE,MAAM,GAChB,SAAS,CAmBX"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEhF,eAAO,MAAM,oBAAoB,QAAkE,CAAC;AAwEpG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAyBzD;AA+BD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,SAA4B,GAAG,MAAM,CAG9F;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,UAAU,SAAuB,EACjC,MAAM,SAA4D,GACjE,cAAc,CAOhB;AAED,wBAAgB,UAAU,IAAI,SAAS,CAEtC;AA6ED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,UAAQ,GACZ,OAAO,CAAC,OAAO,CAAC,CA2BlB;AAED,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA0BhF;AAED,wBAAsB,WAAW,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAkCvE;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjF;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE5E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEjF;AAyBD,wBAAgB,UAAU,CACxB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,gBAAgB,CAAC,EAAE,MAAM,EACzB,QAAQ,CAAC,EAAE,MAAM,GAChB,SAAS,CAmBX"}
package/dist/config.js CHANGED
@@ -26,6 +26,37 @@ function parseConfigUrl(value, label) {
26
26
  throw new CliError(`${label} must be a valid URL.`);
27
27
  }
28
28
  }
29
+ function normalizeRelativeProjectPath(value, label) {
30
+ const normalizedInput = value.trim().replace(/\\/g, "/");
31
+ if (!normalizedInput
32
+ || path.posix.isAbsolute(normalizedInput)
33
+ || path.win32.isAbsolute(value)) {
34
+ throw new CliError(`${label} must be a relative path inside this Mechanic CLI project.`);
35
+ }
36
+ const normalized = path.posix.normalize(normalizedInput).replace(/\/+$/, "");
37
+ if (normalized === "."
38
+ || normalized === ".."
39
+ || normalized.startsWith("../")
40
+ || path.posix.isAbsolute(normalized)) {
41
+ throw new CliError(`${label} must be a relative path inside this Mechanic CLI project.`);
42
+ }
43
+ return normalized;
44
+ }
45
+ function normalizeTasksDirName(value) {
46
+ return normalizeRelativeProjectPath(value || DEFAULT_TASKS_DIR, "tasks_dir");
47
+ }
48
+ function normalizeLinkFile(slug, file, tasksDirName) {
49
+ const normalizedTasksDir = normalizeTasksDirName(tasksDirName);
50
+ const normalizedFile = normalizeRelativeProjectPath(file || `${normalizedTasksDir}/${slug}.json`, `.mechanic/links.json file for ${slug}`);
51
+ const relativeToTasksDir = path.posix.relative(normalizedTasksDir, normalizedFile);
52
+ if (relativeToTasksDir === ""
53
+ || relativeToTasksDir === ".."
54
+ || relativeToTasksDir.startsWith("../")
55
+ || path.posix.isAbsolute(relativeToTasksDir)) {
56
+ throw new CliError(`.mechanic/links.json file for ${slug} must be inside ${normalizedTasksDir}.`);
57
+ }
58
+ return normalizedFile;
59
+ }
29
60
  export function normalizeApiBaseUrl(value) {
30
61
  const url = parseConfigUrl(value, "api_base_url");
31
62
  const hostname = url.hostname.toLowerCase();
@@ -93,7 +124,7 @@ function normalizeLinkEntry(slug, entry, tasksDirName) {
93
124
  return null;
94
125
  }
95
126
  const normalized = {
96
- file: entry.file || `${tasksDirName}/${slug}.json`,
127
+ file: normalizeLinkFile(slug, entry.file, tasksDirName),
97
128
  remote_id: entry.remote_id,
98
129
  last_remote_content_hash: entry.last_remote_content_hash,
99
130
  };
@@ -107,7 +138,7 @@ function normalizeLegacyLinkEntry(slug, entry, tasksDirName) {
107
138
  return null;
108
139
  }
109
140
  return [slug, {
110
- file: `${tasksDirName}/${slug}.json`,
141
+ file: normalizeLinkFile(slug, undefined, tasksDirName),
111
142
  remote_id: entry.task_id,
112
143
  last_remote_content_hash: entry.last_remote_hash,
113
144
  }];
@@ -193,7 +224,7 @@ export async function loadProject(cwd = process.cwd()) {
193
224
  if (!config.api_base_url) {
194
225
  throw new CliError("mechanic.json must include api_base_url");
195
226
  }
196
- const tasksDirName = config.tasks_dir || DEFAULT_TASKS_DIR;
227
+ const tasksDirName = normalizeTasksDirName(config.tasks_dir);
197
228
  const linksPath = path.join(cwd, ".mechanic", "links.json");
198
229
  const links = normalizeLinks(await readJson(linksPath, emptyLinks()), config.shop_domain, tasksDirName);
199
230
  const apiBaseUrl = normalizeApiBaseUrl(process.env.MECHANIC_API_BASE_URL || config.api_base_url);
package/dist/tasks.d.ts CHANGED
@@ -26,8 +26,9 @@ export declare function writeTaskFile(project: Project, slug: string, task: Json
26
26
  export declare function resolveTaskSelector(project: Project, input: string, options?: ResolveTaskSelectorOptions): Promise<ResolvedTaskSelector>;
27
27
  export declare function selectedTaskFiles(project: Project, input: string | undefined, all: boolean): Promise<string[]>;
28
28
  export declare function remoteChangedSinceLastPull(link: LinkEntry, remote: Pick<TaskEnvelope, "content_hash">): boolean;
29
+ export declare function localChangedSinceLastSync(link: LinkEntry, task: JsonObject): boolean;
29
30
  export declare function remoteChangedSinceLastPullDetails(force?: boolean): string;
30
- export declare function remoteChangedSinceLastPullMessage(relativeFile: string, remoteId: string): string;
31
+ export declare function remoteChangedSinceLastPullMessage(relativeFile: string, remoteId: string, localChanged?: boolean): string;
31
32
  export declare function taskForPush(task: JsonObject): JsonObject;
32
33
  export declare function nextAvailableSlug(project: Project, baseSlug: string): Promise<string>;
33
34
  export declare function taskFromHelperDir(dirPath: string): Promise<JsonObject>;
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"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"}
package/dist/tasks.js CHANGED
@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { CliError } from "./errors.js";
4
4
  import { ensureDir, pathExists, readJson, readText, removeFile, writeJson, writeText } from "./fs.js";
5
+ import { contentHash } from "./hash.js";
5
6
  import { stableStringify } from "./json.js";
6
7
  const SPLIT_FILES = [
7
8
  ["script", "script.liquid"],
@@ -318,11 +319,19 @@ export async function selectedTaskFiles(project, input, all) {
318
319
  export function remoteChangedSinceLastPull(link, remote) {
319
320
  return remote.content_hash !== link.last_remote_content_hash;
320
321
  }
322
+ export function localChangedSinceLastSync(link, task) {
323
+ const localHash = contentHash(taskForPush(task));
324
+ return (localHash !== link.last_remote_content_hash
325
+ && localHash !== link.last_local_content_hash);
326
+ }
321
327
  export function remoteChangedSinceLastPullDetails(force = false) {
322
- return force ? "remote changed since last pull; --force set" : "remote changed since last pull";
328
+ return force ? "Mechanic changed since last sync; --force set" : "Mechanic changed since last sync";
323
329
  }
324
- export function remoteChangedSinceLastPullMessage(relativeFile, remoteId) {
325
- return `${relativeFile} has changes in Mechanic since the last pull. Run "mechanic tasks diff ${relativeFile}" to review, then "mechanic tasks pull ${remoteId}" to keep the Mechanic version, or re-run with --force only if the local file should win.`;
330
+ export function remoteChangedSinceLastPullMessage(relativeFile, remoteId, localChanged = false) {
331
+ if (localChanged) {
332
+ return `${relativeFile} has changes in Mechanic and local changes since this file was last synced. Run "mechanic tasks diff ${relativeFile}" to review. Then run "mechanic tasks pull ${remoteId} --force" only if current Mechanic should replace your local file, or run "mechanic tasks publish ${relativeFile} --force" only if your local file should overwrite Mechanic.`;
333
+ }
334
+ return `${relativeFile} has changes in Mechanic since this file was last synced. Run "mechanic tasks diff ${relativeFile}" to review, then "mechanic tasks pull ${remoteId}" to update your local file from current Mechanic before publishing.`;
326
335
  }
327
336
  export function taskForPush(task) {
328
337
  const { enabled: _enabled, id: _id, remote_id: _remoteId, ...payload } = task;
@@ -549,7 +558,7 @@ export function diffTasks(local, remote) {
549
558
  }
550
559
  const sections = [`Changed fields: ${changedFields.join(", ")}`];
551
560
  for (const field of changedFields) {
552
- sections.push("", `## ${field}`, "--- remote", "+++ local", ...formattedValueDiff(comparableRemote[field], comparableLocal[field]));
561
+ sections.push("", `## ${field}`, "--- current Mechanic", "+++ local file", ...formattedValueDiff(comparableRemote[field], comparableLocal[field]));
553
562
  }
554
563
  return sections.join("\n");
555
564
  }
package/dist/types.d.ts CHANGED
@@ -29,6 +29,7 @@ export type TaskEnvelope = {
29
29
  id: string;
30
30
  updated_at?: string;
31
31
  content_hash: string;
32
+ enabled?: boolean | null;
32
33
  task: JsonObject;
33
34
  };
34
35
  export type TaskListResponse = {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightward/mechanic-cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.9",
4
4
  "description": "Develop, preview, diff, and publish Mechanic Shopify automation tasks from local files",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -18,6 +18,13 @@
18
18
  ],
19
19
  "author": "Lightward",
20
20
  "homepage": "https://learn.mechanic.dev/platform/mechanic-cli",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/lightward/mechanic-cli.git"
24
+ },
25
+ "bugs": {
26
+ "url": "https://github.com/lightward/mechanic-cli/issues"
27
+ },
21
28
  "bin": {
22
29
  "mechanic": "./bin/mechanic.js"
23
30
  },
@@ -40,7 +47,7 @@
40
47
  "description": "Manage the stored API token for this project."
41
48
  },
42
49
  "github": {
43
- "description": "Generate GitHub Actions workflows for Mechanic task updates."
50
+ "description": "Generate optional GitHub Actions workflows for Mechanic task updates."
44
51
  },
45
52
  "shop": {
46
53
  "description": "Inspect this shop's Mechanic queue and backlog."