@lightward/mechanic-cli 0.1.6 → 0.1.8

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
@@ -184,10 +184,11 @@ the fast offline check for JSON validity, link state, and helper-folder drift.
184
184
  Add `--json` when an editor integration needs task readiness, link state, and
185
185
  remote sync state without parsing table output.
186
186
 
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.
187
+ `tasks diff` compares current Mechanic with your local file, groups output by
188
+ changed field, and only shows nearby changed lines. In diff output, `-` means
189
+ current Mechanic and `+` means local file. Differences are informational by
190
+ default; add `--exit-code` when a script or CI job should treat differences as a
191
+ nonzero result.
191
192
 
192
193
  `tasks preview` is the confidence check before publishing. It sends one local
193
194
  task to Mechanic's preview engine without saving it, then reports whether the
@@ -412,12 +413,15 @@ Mechanic app or by another local checkout.
412
413
 
413
414
  - `tasks pull` records the latest remote content hash in `.mechanic/links.json`.
414
415
  - `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,
416
+ local file still matches the last synced hash. If local edits would be lost,
416
417
  it stops and asks for an explicit `--force`.
417
418
  - `tasks publish` sends that hash as `previous_content_hash`.
418
419
  - 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.
420
+ - `tasks diff` warns when Mechanic changed since the file was last synced, then
421
+ compares current Mechanic with your local file. If only Mechanic changed, pull
422
+ normally to update your local file. If both Mechanic and your local file
423
+ changed, choose explicitly: pull with `--force` to replace local with
424
+ Mechanic, or publish with `--force` to overwrite Mechanic with local.
421
425
  - `tasks publish --all` checks every linked remote task before writing anything,
422
426
  so one stale task blocks the whole publish instead of partially publishing
423
427
  earlier files first.
@@ -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;CAuI3B"}
@@ -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.";
@@ -69,6 +69,7 @@ export default class TasksDiff extends BaseCommand {
69
69
  const remoteTask = taskForPush(remote.task);
70
70
  const diff = diffTasks(localTask, remoteTask);
71
71
  const remoteChanged = remoteChangedSinceLastPull(link, remote);
72
+ const localChanged = localChangedSinceLastSync(link, localTask);
72
73
  const hasDiff = Boolean(diff);
73
74
  if (remoteChanged) {
74
75
  hasRemoteChanges = true;
@@ -88,13 +89,23 @@ export default class TasksDiff extends BaseCommand {
88
89
  if (remoteChanged || diff) {
89
90
  const section = [`# ${relativeFile}`];
90
91
  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.`), "");
92
+ section.push(this.color("yellow", localChanged
93
+ ? "Mechanic and your local file both changed since this file was last synced."
94
+ : "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 ? [
95
+ this.muted("This compares the current versions; it does not show edit history."),
96
+ this.muted("A normal pull will stop because local changes would be overwritten."),
97
+ this.muted(`Run "mechanic tasks pull ${link.remote_id} --force" only if current Mechanic should replace your local file.`),
98
+ this.muted(`Run "mechanic tasks publish ${relativeFile} --force" only if your local file should overwrite Mechanic.`),
99
+ ] : [
100
+ this.muted("Your local file has no unsynced changes."),
101
+ this.muted(`Run "mechanic tasks pull ${link.remote_id}" to update your local file from current Mechanic.`),
102
+ ]), "");
92
103
  }
93
104
  if (diff) {
94
105
  section.push(diff);
95
106
  }
96
107
  else {
97
- section.push("No field differences between the current remote task and your local file.");
108
+ section.push("No field differences between current Mechanic and your local file.");
98
109
  }
99
110
  differences.push(this.colorDiff(section.join("\n")));
100
111
  }
@@ -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
  }
@@ -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}`)
@@ -129,7 +129,7 @@ export default class TasksPush extends BaseCommand {
129
129
  async preflightRemoteChanges(client, project, links, preparedTasks) {
130
130
  const remoteBySlug = new Map();
131
131
  const conflicts = [];
132
- for (const { slug, relativeFile } of preparedTasks) {
132
+ for (const { slug, relativeFile, task } of preparedTasks) {
133
133
  const link = linkForSlug({ ...project, links }, slug);
134
134
  if (!link) {
135
135
  continue;
@@ -137,12 +137,12 @@ export default class TasksPush extends BaseCommand {
137
137
  const remote = await client.getTask(link.remote_id);
138
138
  remoteBySlug.set(slug, remote);
139
139
  if (remoteChangedSinceLastPull(link, remote)) {
140
- conflicts.push(remoteChangedSinceLastPullMessage(relativeFile, link.remote_id));
140
+ conflicts.push(remoteChangedSinceLastPullMessage(relativeFile, link.remote_id, localChangedSinceLastSync(link, task)));
141
141
  }
142
142
  }
143
143
  if (conflicts.length > 0) {
144
144
  throw new CliError([
145
- "Remote changes found before publishing. Nothing was published.",
145
+ "Mechanic changes found before publishing. Nothing was published.",
146
146
  "",
147
147
  ...conflicts.map((conflict) => `- ${conflict}`),
148
148
  ].join("\n"), 2);
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightward/mechanic-cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Develop, preview, diff, and publish Mechanic Shopify automation tasks from local files",
5
5
  "type": "module",
6
6
  "keywords": [