@lightward/mechanic-cli 0.1.3 → 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 +10 -6
- 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 +6 -2
- package/dist/commands/tasks/diff.d.ts.map +1 -1
- package/dist/commands/tasks/diff.js +1 -1
- package/dist/commands/tasks/new.d.ts.map +1 -1
- package/dist/commands/tasks/new.js +2 -1
- package/dist/commands/tasks/pull.d.ts.map +1 -1
- package/dist/commands/tasks/pull.js +4 -2
- 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 +18 -3
- package/dist/commands/tasks/status.d.ts +0 -1
- package/dist/commands/tasks/status.d.ts.map +1 -1
- package/dist/commands/tasks/status.js +16 -13
- 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 +1 -1
- package/dist/types.d.ts +1 -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
package/README.md
CHANGED
|
@@ -38,6 +38,8 @@ Install from npm:
|
|
|
38
38
|
npm install -g @lightward/mechanic-cli
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
In interactive terminals, Mechanic occasionally checks npm and prints the update command when a newer CLI is available.
|
|
42
|
+
|
|
41
43
|
## Quick Start
|
|
42
44
|
|
|
43
45
|
Create an API token in Mechanic:
|
|
@@ -61,7 +63,8 @@ mechanic tasks pull
|
|
|
61
63
|
```
|
|
62
64
|
|
|
63
65
|
To start from scratch instead, create a new blank local task. This writes a
|
|
64
|
-
starter JSON file and matching helper directory
|
|
66
|
+
starter JSON file and matching helper directory. You can use this in any
|
|
67
|
+
initialized CLI project; it does not require a fresh repository:
|
|
65
68
|
|
|
66
69
|
```bash
|
|
67
70
|
mechanic tasks new order-tagger
|
|
@@ -124,7 +127,7 @@ mechanic tasks publish <task> [--force] [--dry-run] [--json]
|
|
|
124
127
|
mechanic tasks publish --all [--force] [--dry-run] [--json]
|
|
125
128
|
mechanic tasks unbundle <task> [--out <dir>] [--json]
|
|
126
129
|
mechanic tasks bundle <task|dir|file> [--out <file>] [--json]
|
|
127
|
-
mechanic tasks validate <
|
|
130
|
+
mechanic tasks validate <task|dir> [--json]
|
|
128
131
|
```
|
|
129
132
|
|
|
130
133
|
Most task commands accept a `<task>` selector. In day-to-day use, prefer the
|
|
@@ -166,9 +169,10 @@ explicitly pass `--all`.
|
|
|
166
169
|
|
|
167
170
|
`tasks new` creates a new blank local starter task. It writes both
|
|
168
171
|
`tasks/<slug>.json` and `tasks/<slug>/`, so you can edit the helper files first
|
|
169
|
-
and bundle them into the JSON file before publishing. It
|
|
170
|
-
|
|
171
|
-
|
|
172
|
+
and bundle them into the JSON file before publishing. It can be used any time in
|
|
173
|
+
an initialized CLI project, and it refuses to overwrite existing local task files
|
|
174
|
+
unless you pass `--force`. It does not create anything in Mechanic until you run
|
|
175
|
+
`tasks publish`; new published tasks are created disabled.
|
|
172
176
|
|
|
173
177
|
`shop status` shows the current Mechanic run queue for the configured shop:
|
|
174
178
|
running runs, waiting runs, queue lag, and the largest backlog groups by task,
|
|
@@ -381,7 +385,7 @@ After editing, bundle the helper directory back to canonical JSON:
|
|
|
381
385
|
|
|
382
386
|
```bash
|
|
383
387
|
mechanic tasks bundle order-tagger
|
|
384
|
-
mechanic tasks validate
|
|
388
|
+
mechanic tasks validate order-tagger
|
|
385
389
|
```
|
|
386
390
|
|
|
387
391
|
`tasks bundle` accepts the local task slug or either side of the pair.
|
package/dist/base-command.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Command } from "@oclif/core";
|
|
|
2
2
|
import { MechanicClient } from "./client.js";
|
|
3
3
|
import type { Project } from "./types.js";
|
|
4
4
|
export declare abstract class BaseCommand extends Command {
|
|
5
|
+
protected finally(error: Error | undefined): Promise<void>;
|
|
5
6
|
loadProject(): Promise<Project>;
|
|
6
7
|
clientForProject(project: Project): Promise<MechanicClient>;
|
|
7
8
|
verifiedClientForProject(project: Project): Promise<MechanicClient>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-command.d.ts","sourceRoot":"","sources":["../src/base-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAM,MAAM,aAAa,CAAC;AAI1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"base-command.d.ts","sourceRoot":"","sources":["../src/base-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAM,MAAM,aAAa,CAAC;AAI1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAI7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,8BAAsB,WAAY,SAAQ,OAAO;cACtB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBnE,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAQ3D,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAMnE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI5B,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAenC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAI1C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI3B,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAIhC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI7B,eAAe,IAAI,MAAM;IAQzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI9B,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAIhD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI;CAgB9B"}
|
package/dist/base-command.js
CHANGED
|
@@ -5,13 +5,28 @@ import { requireToken } from "./auth.js";
|
|
|
5
5
|
import { MechanicClient } from "./client.js";
|
|
6
6
|
import { loadProject, taskAdminUrl } from "./config.js";
|
|
7
7
|
import { CliError } from "./errors.js";
|
|
8
|
+
import { getUpdateNotice, shouldCheckForUpdates } from "./update-check.js";
|
|
8
9
|
export class BaseCommand extends Command {
|
|
10
|
+
async finally(error) {
|
|
11
|
+
await super.finally(error);
|
|
12
|
+
if (error || !shouldCheckForUpdates(this.argv)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const notice = await getUpdateNotice();
|
|
16
|
+
if (!notice) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
this.log("");
|
|
20
|
+
this.log(`${this.color("yellow", "Update available")} Mechanic CLI ${this.muted(notice.currentVersion)} -> ${this.success(notice.latestVersion)}`);
|
|
21
|
+
this.log(`Update with: ${this.taskName("npm install -g @lightward/mechanic-cli")}`);
|
|
22
|
+
}
|
|
9
23
|
async loadProject() {
|
|
10
24
|
return loadProject(process.cwd());
|
|
11
25
|
}
|
|
12
26
|
async clientForProject(project) {
|
|
13
27
|
return new MechanicClient({
|
|
14
28
|
baseUrl: project.apiBaseUrl,
|
|
29
|
+
expectedShopDomain: project.shopDomain,
|
|
15
30
|
token: await requireToken(project.shopDomain),
|
|
16
31
|
});
|
|
17
32
|
}
|
|
@@ -24,7 +39,7 @@ export class BaseCommand extends Command {
|
|
|
24
39
|
const verification = await client.verifyAuth();
|
|
25
40
|
const verifiedShopDomain = verification.shop?.shopify_domain;
|
|
26
41
|
if (verifiedShopDomain !== project.shopDomain) {
|
|
27
|
-
throw new CliError(
|
|
42
|
+
throw new CliError("API token does not match this Mechanic CLI project. Use a token for the shop in mechanic.json, or re-run mechanic init for the intended shop.", 2);
|
|
28
43
|
}
|
|
29
44
|
}
|
|
30
45
|
accent(text) {
|
package/dist/client.d.ts
CHANGED
|
@@ -17,9 +17,11 @@ export type AuthVerification = {
|
|
|
17
17
|
};
|
|
18
18
|
export declare class MechanicClient {
|
|
19
19
|
readonly baseUrl: string;
|
|
20
|
+
readonly expectedShopDomain?: string;
|
|
20
21
|
readonly token: string;
|
|
21
|
-
constructor({ baseUrl, token }: {
|
|
22
|
+
constructor({ baseUrl, expectedShopDomain, token }: {
|
|
22
23
|
baseUrl: string;
|
|
24
|
+
expectedShopDomain?: string;
|
|
23
25
|
token: string;
|
|
24
26
|
});
|
|
25
27
|
request<T>(pathname: string, options?: RequestOptions): Promise<T>;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAKtH,eAAO,MAAM,UAAU,QAAkD,CAAC;AAE1E,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,SAAS,CAAC,EAAE;QACV,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;CACH,CAAC;AAwGF,qBAAa,cAAc;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAKtH,eAAO,MAAM,UAAU,QAAkD,CAAC;AAE1E,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,SAAS,CAAC,EAAE;QACV,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;CACH,CAAC;AAwGF,qBAAa,cAAc;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAM7G,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAgD5E,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAIvC,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAI5C,SAAS,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAItC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAI1C,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IASxE,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAM3D,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAQ5E,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CAM3H"}
|
package/dist/client.js
CHANGED
|
@@ -87,9 +87,11 @@ function apiErrorMessage(response, parsed) {
|
|
|
87
87
|
}
|
|
88
88
|
export class MechanicClient {
|
|
89
89
|
baseUrl;
|
|
90
|
+
expectedShopDomain;
|
|
90
91
|
token;
|
|
91
|
-
constructor({ baseUrl, token }) {
|
|
92
|
+
constructor({ baseUrl, expectedShopDomain, token }) {
|
|
92
93
|
this.baseUrl = baseUrl;
|
|
94
|
+
this.expectedShopDomain = expectedShopDomain;
|
|
93
95
|
this.token = token;
|
|
94
96
|
}
|
|
95
97
|
async request(pathname, options = {}) {
|
|
@@ -106,6 +108,7 @@ export class MechanicClient {
|
|
|
106
108
|
Accept: "application/json",
|
|
107
109
|
Authorization: `Bearer ${this.token}`,
|
|
108
110
|
"User-Agent": USER_AGENT,
|
|
111
|
+
...(this.expectedShopDomain ? { "X-Mechanic-Shop-Domain": this.expectedShopDomain } : {}),
|
|
109
112
|
...(options.body === undefined ? {} : { "Content-Type": "application/json" }),
|
|
110
113
|
...(options.headers || {}),
|
|
111
114
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,OAAgB,WAAW,SAA4C;IAEvE,OAAgB,KAAK;;MAInB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,OAAgB,WAAW,SAA4C;IAEvE,OAAgB,KAAK;;MAInB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BpB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;CASxC"}
|
|
@@ -14,14 +14,18 @@ export default class AuthLogin extends BaseCommand {
|
|
|
14
14
|
const { flags } = await this.parse(AuthLogin);
|
|
15
15
|
const token = flags.token || process.env.MECHANIC_API_TOKEN || (await this.promptForToken());
|
|
16
16
|
const project = await this.loadProject();
|
|
17
|
-
const client = new MechanicClient({
|
|
17
|
+
const client = new MechanicClient({
|
|
18
|
+
baseUrl: project.apiBaseUrl,
|
|
19
|
+
expectedShopDomain: project.shopDomain,
|
|
20
|
+
token,
|
|
21
|
+
});
|
|
18
22
|
const verification = await client.verifyAuth();
|
|
19
23
|
const verifiedDomain = verification.shop?.shopify_domain;
|
|
20
24
|
if (!verifiedDomain) {
|
|
21
25
|
throw new CliError("Token verification did not return a shop domain.");
|
|
22
26
|
}
|
|
23
27
|
if (verifiedDomain !== project.shopDomain) {
|
|
24
|
-
throw new CliError(
|
|
28
|
+
throw new CliError("API token does not match this Mechanic CLI project. Use a token for the shop in mechanic.json.", 2);
|
|
25
29
|
}
|
|
26
30
|
await saveToken(project.shopDomain, token);
|
|
27
31
|
this.log(`${this.success("Stored")} API token for ${this.accent(project.shopDomain)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAiBjD,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAAW;IAC7C,OAAgB,WAAW,SAA2E;IAEhG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAiBjD,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAAW;IAC7C,OAAgB,WAAW,SAA2E;IAEhG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAoH1B,WAAW,CAAC,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM;CAUpD"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -60,14 +60,16 @@ export default class Doctor extends BaseCommand {
|
|
|
60
60
|
const verifiedDomain = verification.shop?.shopify_domain;
|
|
61
61
|
verifiedShopMatches = verifiedDomain === project.shopDomain;
|
|
62
62
|
addRow("Token shop", verifiedShopMatches ? "ok" : "fail", verifiedDomain
|
|
63
|
-
?
|
|
63
|
+
? (verifiedShopMatches ? project.shopDomain : "API token does not match this project")
|
|
64
64
|
: "API did not return a shop domain");
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
if (verifiedShopMatches) {
|
|
66
|
+
const tokenDetails = [
|
|
67
|
+
verification.api_token?.name,
|
|
68
|
+
verification.api_token?.created_by ? `created by ${verification.api_token.created_by}` : null,
|
|
69
|
+
].filter(Boolean).join(", ");
|
|
70
|
+
if (tokenDetails) {
|
|
71
|
+
addRow("Token identity", "ok", tokenDetails);
|
|
72
|
+
}
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
catch (error) {
|
|
@@ -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;
|
|
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;CAoE3B"}
|
package/dist/commands/init.js
CHANGED
|
@@ -28,14 +28,18 @@ export default class Init extends BaseCommand {
|
|
|
28
28
|
: null);
|
|
29
29
|
let storedToken = false;
|
|
30
30
|
if (token) {
|
|
31
|
-
const client = new MechanicClient({
|
|
31
|
+
const client = new MechanicClient({
|
|
32
|
+
baseUrl: normalizeApiBaseUrl(flags["api-base-url"]),
|
|
33
|
+
expectedShopDomain: flags.shop,
|
|
34
|
+
token,
|
|
35
|
+
});
|
|
32
36
|
const verification = await client.verifyAuth();
|
|
33
37
|
const verifiedDomain = verification.shop?.shopify_domain;
|
|
34
38
|
if (!verifiedDomain) {
|
|
35
39
|
throw new CliError("Token verification did not return a shop domain.");
|
|
36
40
|
}
|
|
37
41
|
if (verifiedDomain !== flags.shop) {
|
|
38
|
-
throw new CliError(
|
|
42
|
+
throw new CliError("API token does not match the requested shop. Check --shop or use a token for that shop.", 2);
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
const project = await initProject(process.cwd(), flags.shop, flags["api-base-url"], flags["app-url"], Boolean(flags.force));
|
|
@@ -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;
|
|
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;CAoH3B"}
|
|
@@ -86,7 +86,7 @@ export default class TasksDiff extends BaseCommand {
|
|
|
86
86
|
if (remoteChanged || diff) {
|
|
87
87
|
const section = [`# ${relativeFile}`];
|
|
88
88
|
if (remoteChanged) {
|
|
89
|
-
section.push(this.color("yellow", "Remote changed since your last pull."), this.muted("Showing the current Mechanic task
|
|
89
|
+
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.`), "");
|
|
90
90
|
}
|
|
91
91
|
if (diff) {
|
|
92
92
|
section.push(diff);
|
|
@@ -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;
|
|
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"}
|
|
@@ -18,6 +18,7 @@ function starterTask(name) {
|
|
|
18
18
|
return {
|
|
19
19
|
halt_action_run_sequence_on_error: false,
|
|
20
20
|
name,
|
|
21
|
+
docs: "",
|
|
21
22
|
options: {},
|
|
22
23
|
perform_action_runs_in_sequence: false,
|
|
23
24
|
preview_event_definitions: [],
|
|
@@ -80,7 +81,7 @@ export default class TasksNew extends BaseCommand {
|
|
|
80
81
|
this.log(` edit ${this.taskName(displayTaskPath(project, path.join(helperDir, "script.liquid")))}`);
|
|
81
82
|
this.log(` mechanic tasks preview ${this.taskName(slug)}`);
|
|
82
83
|
this.log(` mechanic tasks bundle ${this.taskName(slug)}`);
|
|
83
|
-
this.log(` mechanic tasks publish ${this.taskName(slug)}
|
|
84
|
+
this.log(` mechanic tasks publish ${this.taskName(slug)}`);
|
|
84
85
|
}
|
|
85
86
|
async checkExistingPaths(project, filePath, helperDir, force) {
|
|
86
87
|
if (force) {
|
|
@@ -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;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;
|
|
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"}
|
|
@@ -62,7 +62,9 @@ export default class TasksPull extends BaseCommand {
|
|
|
62
62
|
const remoteTaskForPull = taskForPush(envelope.task);
|
|
63
63
|
const localMatchesCurrentRemote = stableStringify(localTaskForPull) === stableStringify(remoteTaskForPull);
|
|
64
64
|
const localHash = contentHash(localTaskForPull);
|
|
65
|
-
|
|
65
|
+
const localMatchesLastWritten = (localHash === link?.last_remote_content_hash
|
|
66
|
+
|| localHash === link?.last_local_content_hash);
|
|
67
|
+
if (!localMatchesCurrentRemote && !localMatchesLastWritten) {
|
|
66
68
|
throw new CliError([
|
|
67
69
|
`${displayTaskPath(project, filePath)} has local changes that would be overwritten.`,
|
|
68
70
|
`Run "mechanic tasks diff ${displayTaskPath(project, filePath)}" to review them.`,
|
|
@@ -72,7 +74,7 @@ export default class TasksPull extends BaseCommand {
|
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
await writeTaskFilePathAndRefreshHelper(filePath, envelope.task);
|
|
75
|
-
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)));
|
|
76
78
|
await saveLinks(project, links);
|
|
77
79
|
rows.push([
|
|
78
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":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAmBpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnF,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;CAClB,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAgBF,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,OAAgB,MAAM,UAAQ;IAC9B,OAAgB,OAAO,SAAuE;IAC9F,OAAgB,WAAW,SAA6G;IAExI,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;;;;MAKnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAMpB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCvE,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IA8E9F,sBAAsB,CAC1B,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,SAAS,EAChB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IA8B/B,wBAAwB,CAC5B,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,SAAS,EAChB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAwClC,6BAA6B,CACjC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,SAAS,EAChB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,IAAI,CAAC;IAwBV,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,kBAAkB,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IA6FpG,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;QACtF,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,EAAE,OAAO,EAAE,CAAC;KACjB,CAAC;IA6EF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,EAAE,EAAE;IAavH,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAe5C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAehC"}
|
|
@@ -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) {
|
|
@@ -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;
|
|
@@ -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":
|
|
@@ -16,7 +16,6 @@ export default class TasksStatus extends BaseCommand {
|
|
|
16
16
|
static flags: {
|
|
17
17
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
18
|
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
|
-
remote: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
20
19
|
};
|
|
21
20
|
run(): Promise<void>;
|
|
22
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;
|
|
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"}
|
|
@@ -2,16 +2,16 @@ import { Args, Flags } from "@oclif/core";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { BaseCommand } from "../../base-command.js";
|
|
4
4
|
import { linkForSlug } from "../../config.js";
|
|
5
|
-
import { CliError } from "../../errors.js";
|
|
6
5
|
import { pathExists } from "../../fs.js";
|
|
7
6
|
import { stableStringify } from "../../json.js";
|
|
8
7
|
import { displayTaskPath, helperDirForTaskFile, readRawTaskFile, remoteChangedSinceLastPull, remoteChangedSinceLastPullDetails, selectedTaskFiles, slugFromTaskFile, taskForPush, unbundledHelperDirForTaskFile, validateTaskForPush, } from "../../tasks.js";
|
|
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
12
|
export default class TasksStatus extends BaseCommand {
|
|
13
13
|
static summary = "Show whether local task files are ready and in sync with Mechanic.";
|
|
14
|
-
static description =
|
|
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.`;
|
|
15
15
|
static args = {
|
|
16
16
|
file: Args.string({ required: false, description: "Local task slug, task file, helper directory, or linked task ID. Defaults to every task JSON file." }),
|
|
17
17
|
};
|
|
@@ -22,22 +22,15 @@ export default class TasksStatus extends BaseCommand {
|
|
|
22
22
|
local: Flags.boolean({
|
|
23
23
|
description: "Only check local files and links; do not call Mechanic.",
|
|
24
24
|
}),
|
|
25
|
-
remote: Flags.boolean({
|
|
26
|
-
char: "r",
|
|
27
|
-
description: "Check linked remote tasks. This is the default; kept for compatibility.",
|
|
28
|
-
hidden: true,
|
|
29
|
-
}),
|
|
30
25
|
};
|
|
31
26
|
async run() {
|
|
32
27
|
const { args, flags } = await this.parse(TasksStatus);
|
|
33
|
-
if (flags.local && flags.remote) {
|
|
34
|
-
throw new CliError("Use either --local or --remote, not both.", 2);
|
|
35
|
-
}
|
|
36
28
|
const project = await this.loadProject();
|
|
37
29
|
const files = await selectedTaskFiles(project, args.file, !args.file);
|
|
38
30
|
const statuses = [];
|
|
39
31
|
let client = null;
|
|
40
|
-
const
|
|
32
|
+
const remoteSkippedForLimit = !flags.local && !args.file && files.length > IMPLICIT_REMOTE_CHECK_LIMIT;
|
|
33
|
+
const checkRemote = !flags.local && !remoteSkippedForLimit;
|
|
41
34
|
const getClient = async () => {
|
|
42
35
|
client ||= await this.verifiedClientForProject(project);
|
|
43
36
|
return client;
|
|
@@ -95,11 +88,16 @@ export default class TasksStatus extends BaseCommand {
|
|
|
95
88
|
});
|
|
96
89
|
}
|
|
97
90
|
if (flags.json) {
|
|
98
|
-
|
|
91
|
+
const output = {
|
|
99
92
|
shop_domain: project.shopDomain,
|
|
100
93
|
remote_checked: checkRemote,
|
|
101
94
|
tasks: statuses,
|
|
102
|
-
}
|
|
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);
|
|
103
101
|
return;
|
|
104
102
|
}
|
|
105
103
|
const rows = checkRemote
|
|
@@ -117,6 +115,11 @@ export default class TasksStatus extends BaseCommand {
|
|
|
117
115
|
row.push(status.link.remote_id ? this.taskId(project, status.link.remote_id) : "--", status.details.join("; "));
|
|
118
116
|
rows.push(row);
|
|
119
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
|
+
}
|
|
120
123
|
this.table(rows);
|
|
121
124
|
}
|
|
122
125
|
async helperStatus(project, file, task) {
|
|
@@ -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"}
|
|
@@ -4,15 +4,18 @@ import path from "node:path";
|
|
|
4
4
|
import { BaseCommand } from "../../base-command.js";
|
|
5
5
|
import { CliError } from "../../errors.js";
|
|
6
6
|
import { pathExists } from "../../fs.js";
|
|
7
|
-
import { rawTaskFromHelperDir, readRawTaskFile, unbundledHelperDirForTaskFile, validateTask, } from "../../tasks.js";
|
|
7
|
+
import { rawTaskFromHelperDir, readRawTaskFile, resolveTaskSelector, unbundledHelperDirForTaskFile, validateTask, } from "../../tasks.js";
|
|
8
8
|
function errorMessage(error) {
|
|
9
9
|
return error instanceof Error ? error.message : String(error);
|
|
10
10
|
}
|
|
11
|
+
function looksLikeValidationPath(input) {
|
|
12
|
+
return path.isAbsolute(input) || input.endsWith(".json") || input.includes("/") || input.includes(path.sep);
|
|
13
|
+
}
|
|
11
14
|
export default class TasksValidate extends BaseCommand {
|
|
12
|
-
static summary = "Validate one task
|
|
13
|
-
static description = "Validate one canonical task JSON file,
|
|
15
|
+
static summary = "Validate one local task or directory of task JSON files.";
|
|
16
|
+
static description = "Validate one local task slug, canonical task JSON file, helper task directory, or directory of task JSON files.";
|
|
14
17
|
static args = {
|
|
15
|
-
target: Args.string({ required: true, description: "
|
|
18
|
+
target: Args.string({ required: true, description: "Local task slug, task JSON file, helper dir, or directory of task JSON files." }),
|
|
16
19
|
};
|
|
17
20
|
static flags = {
|
|
18
21
|
json: Flags.boolean({
|
|
@@ -23,25 +26,30 @@ export default class TasksValidate extends BaseCommand {
|
|
|
23
26
|
const { args, flags } = await this.parse(TasksValidate);
|
|
24
27
|
const target = path.resolve(args.target);
|
|
25
28
|
const results = [];
|
|
26
|
-
const stat = await fs.stat(target).catch((
|
|
27
|
-
|
|
28
|
-
});
|
|
29
|
-
if (stat.isFile()) {
|
|
29
|
+
const stat = await fs.stat(target).catch(() => null);
|
|
30
|
+
if (stat?.isFile()) {
|
|
30
31
|
results.push(await this.validateTaskFile(target));
|
|
31
32
|
}
|
|
32
|
-
else if (await pathExists(path.join(target, "task.json"))) {
|
|
33
|
+
else if (stat?.isDirectory() && await pathExists(path.join(target, "task.json"))) {
|
|
33
34
|
results.push(validateTask(await rawTaskFromHelperDir(target), target));
|
|
34
35
|
}
|
|
36
|
+
else if (stat?.isDirectory()) {
|
|
37
|
+
results.push(...await this.validateTaskDirectory(target));
|
|
38
|
+
}
|
|
35
39
|
else {
|
|
36
|
-
|
|
37
|
-
throw new CliError(`Unable to
|
|
38
|
-
}
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
if (looksLikeValidationPath(args.target)) {
|
|
41
|
+
throw new CliError(`Unable to access ${target}: no such file or directory`, 2);
|
|
42
|
+
}
|
|
43
|
+
const project = await this.loadProject();
|
|
44
|
+
const selector = await resolveTaskSelector(project, args.target, { allowHelperDir: true });
|
|
45
|
+
if (selector.helperDir) {
|
|
46
|
+
results.push(validateTask(await rawTaskFromHelperDir(selector.helperDir), selector.helperDir));
|
|
47
|
+
}
|
|
48
|
+
else if (selector.file) {
|
|
49
|
+
results.push(await this.validateTaskFile(selector.file));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
throw new CliError(`No local task file or helper directory found for ${args.target}.`, 2);
|
|
45
53
|
}
|
|
46
54
|
}
|
|
47
55
|
if (results.length === 0) {
|
|
@@ -75,4 +83,18 @@ export default class TasksValidate extends BaseCommand {
|
|
|
75
83
|
}
|
|
76
84
|
return result;
|
|
77
85
|
}
|
|
86
|
+
async validateTaskDirectory(target) {
|
|
87
|
+
const entries = await fs.readdir(target, { withFileTypes: true }).catch((error) => {
|
|
88
|
+
throw new CliError(`Unable to read directory ${target}: ${errorMessage(error)}`, 2);
|
|
89
|
+
});
|
|
90
|
+
const files = entries
|
|
91
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith(".json"))
|
|
92
|
+
.map((entry) => path.join(target, entry.name))
|
|
93
|
+
.sort();
|
|
94
|
+
const results = [];
|
|
95
|
+
for (const file of files) {
|
|
96
|
+
results.push(await this.validateTaskFile(file));
|
|
97
|
+
}
|
|
98
|
+
return results;
|
|
99
|
+
}
|
|
78
100
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -11,5 +11,5 @@ export declare function loadProject(cwd?: string): Promise<Project>;
|
|
|
11
11
|
export declare function saveLinks(project: Project, links: LinksFile): Promise<void>;
|
|
12
12
|
export declare function linkForSlug(project: Project, slug: string): LinkEntry | null;
|
|
13
13
|
export declare function slugForRemoteId(project: Project, remoteId: string): string | null;
|
|
14
|
-
export declare function updateLink(project: Project, slug: string, remoteId: string, contentHash: string): LinksFile;
|
|
14
|
+
export declare function updateLink(project: Project, slug: string, remoteId: string, contentHash: string, localContentHash?: string): LinksFile;
|
|
15
15
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,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;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,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;AAwED,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,CAyBlB;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;AAED,wBAAgB,UAAU,CACxB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,gBAAgB,CAAC,EAAE,MAAM,GACxB,SAAS,CAiBX"}
|
package/dist/config.js
CHANGED
|
@@ -91,11 +91,15 @@ function normalizeLinkEntry(slug, entry) {
|
|
|
91
91
|
if (!entry || typeof entry !== "object" || !entry.remote_id || !entry.last_remote_content_hash) {
|
|
92
92
|
return null;
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
const normalized = {
|
|
95
|
+
file: entry.file || `${DEFAULT_TASKS_DIR}/${slug}.json`,
|
|
96
|
+
remote_id: entry.remote_id,
|
|
97
|
+
last_remote_content_hash: entry.last_remote_content_hash,
|
|
98
|
+
};
|
|
99
|
+
if (typeof entry.last_local_content_hash === "string") {
|
|
100
|
+
normalized.last_local_content_hash = entry.last_local_content_hash;
|
|
101
|
+
}
|
|
102
|
+
return [slug, normalized];
|
|
99
103
|
}
|
|
100
104
|
function normalizeLegacyLinkEntry(slug, entry) {
|
|
101
105
|
if (!entry || typeof entry !== "object" || !entry.task_id || !entry.last_remote_hash) {
|
|
@@ -213,15 +217,19 @@ export function linkForSlug(project, slug) {
|
|
|
213
217
|
export function slugForRemoteId(project, remoteId) {
|
|
214
218
|
return Object.entries(project.links.tasks).find(([, link]) => link.remote_id === remoteId)?.[0] || null;
|
|
215
219
|
}
|
|
216
|
-
export function updateLink(project, slug, remoteId, contentHash) {
|
|
220
|
+
export function updateLink(project, slug, remoteId, contentHash, localContentHash) {
|
|
221
|
+
const entry = {
|
|
222
|
+
file: `${project.tasksDirName}/${slug}.json`,
|
|
223
|
+
remote_id: remoteId,
|
|
224
|
+
last_remote_content_hash: contentHash,
|
|
225
|
+
};
|
|
226
|
+
if (localContentHash && localContentHash !== contentHash) {
|
|
227
|
+
entry.last_local_content_hash = localContentHash;
|
|
228
|
+
}
|
|
217
229
|
return {
|
|
218
230
|
tasks: {
|
|
219
231
|
...project.links.tasks,
|
|
220
|
-
[slug]:
|
|
221
|
-
file: `${project.tasksDirName}/${slug}.json`,
|
|
222
|
-
remote_id: remoteId,
|
|
223
|
-
last_remote_content_hash: contentHash,
|
|
224
|
-
},
|
|
232
|
+
[slug]: entry,
|
|
225
233
|
},
|
|
226
234
|
};
|
|
227
235
|
}
|
package/dist/tasks.js
CHANGED
|
@@ -322,7 +322,7 @@ export function remoteChangedSinceLastPullDetails(force = false) {
|
|
|
322
322
|
return force ? "remote changed since last pull; --force set" : "remote changed since last pull";
|
|
323
323
|
}
|
|
324
324
|
export function remoteChangedSinceLastPullMessage(relativeFile, remoteId) {
|
|
325
|
-
return `${relativeFile} has
|
|
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.`;
|
|
326
326
|
}
|
|
327
327
|
export function taskForPush(task) {
|
|
328
328
|
const { enabled: _enabled, id: _id, remote_id: _remoteId, ...payload } = task;
|
package/dist/types.d.ts
CHANGED
package/dist/types.d.ts.map
CHANGED
|
@@ -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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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type UpdateNotice = {
|
|
2
|
+
currentVersion: string;
|
|
3
|
+
latestVersion: string;
|
|
4
|
+
};
|
|
5
|
+
export type UpdateNoticeOptions = {
|
|
6
|
+
cachePath?: string;
|
|
7
|
+
currentVersion?: string;
|
|
8
|
+
fetchLatestVersion?: () => Promise<string | null>;
|
|
9
|
+
now?: Date;
|
|
10
|
+
};
|
|
11
|
+
export declare function isVersionNewer(candidate: string, current: string): boolean;
|
|
12
|
+
export declare function getUpdateNotice(options?: UpdateNoticeOptions): Promise<UpdateNotice | null>;
|
|
13
|
+
export declare function shouldCheckForUpdates(argv?: string[], env?: NodeJS.ProcessEnv, isTty?: boolean): boolean;
|
|
14
|
+
//# sourceMappingURL=update-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,YAAY,GAAG;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClD,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ,CAAC;AAsBF,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CA+B1E;AA2CD,wBAAsB,eAAe,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA8CrG;AAED,wBAAgB,qBAAqB,CACnC,IAAI,WAAwB,EAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,KAAK,UAAgC,GACpC,OAAO,CAeT"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { appConfigPath, readJson, writeJson } from "./fs.js";
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const packageJson = require("../package.json");
|
|
5
|
+
const PACKAGE_NAME = packageJson.name || "@lightward/mechanic-cli";
|
|
6
|
+
const CURRENT_VERSION = packageJson.version || "0.0.0";
|
|
7
|
+
const NPM_LATEST_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME).replace("%40", "@")}/latest`;
|
|
8
|
+
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
9
|
+
const NOTIFY_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
10
|
+
const FETCH_TIMEOUT_MS = 1500;
|
|
11
|
+
function parseVersion(version) {
|
|
12
|
+
const [core, prerelease] = version.trim().replace(/^v/i, "").split("-", 2);
|
|
13
|
+
const parts = core.split(".");
|
|
14
|
+
if (parts.length < 2 || parts.length > 3 || parts.some((part) => !/^\d+$/.test(part))) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const numbers = parts.map((part) => Number.parseInt(part, 10));
|
|
18
|
+
return {
|
|
19
|
+
numbers: [
|
|
20
|
+
numbers[0] || 0,
|
|
21
|
+
numbers[1] || 0,
|
|
22
|
+
numbers[2] || 0,
|
|
23
|
+
],
|
|
24
|
+
prerelease: prerelease || null,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function isVersionNewer(candidate, current) {
|
|
28
|
+
const candidateParts = parseVersion(candidate);
|
|
29
|
+
const currentParts = parseVersion(current);
|
|
30
|
+
if (!candidateParts || !currentParts) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
for (const index of [0, 1, 2]) {
|
|
34
|
+
if (candidateParts.numbers[index] > currentParts.numbers[index]) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
if (candidateParts.numbers[index] < currentParts.numbers[index]) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!candidateParts.prerelease && currentParts.prerelease) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
if (candidateParts.prerelease && !currentParts.prerelease) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return Boolean(candidateParts.prerelease
|
|
48
|
+
&& currentParts.prerelease
|
|
49
|
+
&& candidateParts.prerelease > currentParts.prerelease);
|
|
50
|
+
}
|
|
51
|
+
function millisecondsSince(value, now) {
|
|
52
|
+
if (!value) {
|
|
53
|
+
return Number.POSITIVE_INFINITY;
|
|
54
|
+
}
|
|
55
|
+
const parsed = Date.parse(value);
|
|
56
|
+
return Number.isFinite(parsed) ? now.getTime() - parsed : Number.POSITIVE_INFINITY;
|
|
57
|
+
}
|
|
58
|
+
async function fetchLatestPackageVersion() {
|
|
59
|
+
const controller = new AbortController();
|
|
60
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
61
|
+
try {
|
|
62
|
+
const response = await fetch(NPM_LATEST_URL, {
|
|
63
|
+
headers: { Accept: "application/json" },
|
|
64
|
+
signal: controller.signal,
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
const body = await response.json();
|
|
70
|
+
return typeof body.version === "string" ? body.version : null;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async function writeCache(cachePath, cache) {
|
|
80
|
+
try {
|
|
81
|
+
await writeJson(cachePath, cache);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Update checks are best-effort and must never affect command behavior.
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export async function getUpdateNotice(options = {}) {
|
|
88
|
+
const now = options.now || new Date();
|
|
89
|
+
const currentVersion = options.currentVersion || CURRENT_VERSION;
|
|
90
|
+
const cachePath = options.cachePath || appConfigPath("update-check.json");
|
|
91
|
+
const fetchLatestVersion = options.fetchLatestVersion || fetchLatestPackageVersion;
|
|
92
|
+
const cache = await readJson(cachePath, {}).catch(() => ({}));
|
|
93
|
+
const checkedRecently = millisecondsSince(cache.checked_at, now) < CHECK_INTERVAL_MS;
|
|
94
|
+
let cacheChanged = false;
|
|
95
|
+
let latestVersion = cache.latest_version || null;
|
|
96
|
+
if (!checkedRecently) {
|
|
97
|
+
const fetchedVersion = await fetchLatestVersion();
|
|
98
|
+
cache.checked_at = now.toISOString();
|
|
99
|
+
cacheChanged = true;
|
|
100
|
+
if (fetchedVersion) {
|
|
101
|
+
latestVersion = fetchedVersion;
|
|
102
|
+
cache.latest_version = fetchedVersion;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!latestVersion || !isVersionNewer(latestVersion, currentVersion)) {
|
|
106
|
+
if (cacheChanged) {
|
|
107
|
+
await writeCache(cachePath, cache);
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const notifiedRecently = millisecondsSince(cache.last_notified_at, now) < NOTIFY_INTERVAL_MS;
|
|
112
|
+
if (notifiedRecently) {
|
|
113
|
+
if (cacheChanged) {
|
|
114
|
+
await writeCache(cachePath, cache);
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
cache.last_notified_at = now.toISOString();
|
|
119
|
+
await writeCache(cachePath, cache);
|
|
120
|
+
return {
|
|
121
|
+
currentVersion,
|
|
122
|
+
latestVersion,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
export function shouldCheckForUpdates(argv = process.argv.slice(2), env = process.env, isTty = process.stdout.isTTY === true) {
|
|
126
|
+
if (!isTty) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
if (env.CI
|
|
130
|
+
|| env.GITHUB_ACTIONS
|
|
131
|
+
|| env.MECHANIC_SKIP_UPDATE_CHECK === "1"
|
|
132
|
+
|| env.MECHANIC_UPDATE_CHECK === "0") {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return !argv.some((arg) => arg === "--json" || arg.startsWith("--json="));
|
|
136
|
+
}
|