@getmaito/cli 0.1.0 → 0.1.2
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 +8 -0
- package/dist/index.js +165 -9
- package/dist/update-check.d.ts +8 -0
- package/dist/update-check.d.ts.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,6 +22,12 @@ Run commands:
|
|
|
22
22
|
maito posts list
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
Show the installed version:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
maito version
|
|
29
|
+
```
|
|
30
|
+
|
|
25
31
|
## Auth
|
|
26
32
|
|
|
27
33
|
Sign in for full CLI access:
|
|
@@ -57,6 +63,8 @@ Update the global install:
|
|
|
57
63
|
npm update -g @getmaito/cli
|
|
58
64
|
```
|
|
59
65
|
|
|
66
|
+
The CLI checks npm for a newer version at most once per day and prints an update hint after normal human-readable command output. JSON output is not changed.
|
|
67
|
+
|
|
60
68
|
## Release
|
|
61
69
|
|
|
62
70
|
The CLI package is published as `@getmaito/cli`.
|
package/dist/index.js
CHANGED
|
@@ -13693,7 +13693,8 @@ var AutoPlugConfigSchema = exports_external.object({
|
|
|
13693
13693
|
kind: AutoPlugKindSchema,
|
|
13694
13694
|
destination: AutoPlugDestinationSchema.default("first_comment"),
|
|
13695
13695
|
messageTemplate: exports_external.string().trim().min(1).max(1000),
|
|
13696
|
-
ctaLinkId: exports_external.string().min(1).optional()
|
|
13696
|
+
ctaLinkId: exports_external.string().min(1).optional(),
|
|
13697
|
+
issueId: exports_external.string().min(1).optional()
|
|
13697
13698
|
});
|
|
13698
13699
|
// ../contracts/src/billing.ts
|
|
13699
13700
|
var BillingPlanSchema = exports_external.enum([
|
|
@@ -17293,15 +17294,23 @@ function getConfigDir() {
|
|
|
17293
17294
|
}
|
|
17294
17295
|
return process.env.XDG_CONFIG_HOME?.trim() || path.join(os.homedir(), ".config");
|
|
17295
17296
|
}
|
|
17296
|
-
function parseJsonResponse(response, label) {
|
|
17297
|
-
|
|
17298
|
-
|
|
17299
|
-
|
|
17300
|
-
|
|
17301
|
-
|
|
17297
|
+
async function parseJsonResponse(response, label) {
|
|
17298
|
+
const text = await response.text();
|
|
17299
|
+
let payload;
|
|
17300
|
+
if (text.trim()) {
|
|
17301
|
+
try {
|
|
17302
|
+
payload = JSON.parse(text);
|
|
17303
|
+
} catch {
|
|
17304
|
+
if (!response.ok) {
|
|
17305
|
+
throw new Error(formatOAuthError(label, text, response.status));
|
|
17306
|
+
}
|
|
17307
|
+
throw new Error(`Failed to parse ${label} response.`);
|
|
17302
17308
|
}
|
|
17303
|
-
|
|
17304
|
-
|
|
17309
|
+
}
|
|
17310
|
+
if (!response.ok) {
|
|
17311
|
+
throw new Error(formatOAuthError(label, payload, response.status));
|
|
17312
|
+
}
|
|
17313
|
+
return payload;
|
|
17305
17314
|
}
|
|
17306
17315
|
function formatOAuthError(label, payload, status) {
|
|
17307
17316
|
if (payload && typeof payload === "object") {
|
|
@@ -17318,6 +17327,9 @@ function formatOAuthError(label, payload, status) {
|
|
|
17318
17327
|
return `${label} failed: ${message}`;
|
|
17319
17328
|
}
|
|
17320
17329
|
}
|
|
17330
|
+
if (typeof payload === "string" && payload.trim()) {
|
|
17331
|
+
return `${label} failed with status ${status}: ${payload.trim()}`;
|
|
17332
|
+
}
|
|
17321
17333
|
return `${label} failed with status ${status}.`;
|
|
17322
17334
|
}
|
|
17323
17335
|
function requireString(value, fieldName) {
|
|
@@ -17401,11 +17413,132 @@ function printPostList(value) {
|
|
|
17401
17413
|
}
|
|
17402
17414
|
}
|
|
17403
17415
|
|
|
17416
|
+
// src/update-check.ts
|
|
17417
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
17418
|
+
import { createRequire } from "node:module";
|
|
17419
|
+
import os2 from "node:os";
|
|
17420
|
+
import path2 from "node:path";
|
|
17421
|
+
var require2 = createRequire(import.meta.url);
|
|
17422
|
+
var packageJson = require2("../package.json");
|
|
17423
|
+
var PACKAGE_NAME = typeof packageJson.name === "string" ? packageJson.name : "@getmaito/cli";
|
|
17424
|
+
var CURRENT_VERSION = typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
|
|
17425
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
17426
|
+
var REGISTRY_LATEST_URL = "https://registry.npmjs.org/@getmaito%2fcli/latest";
|
|
17427
|
+
var REQUEST_TIMEOUT_MS = 1500;
|
|
17428
|
+
async function maybePrintUpdateNotice(input) {
|
|
17429
|
+
if (input.json || isDisabled()) {
|
|
17430
|
+
return;
|
|
17431
|
+
}
|
|
17432
|
+
const store = await readUpdateCheckStore().catch(() => ({}));
|
|
17433
|
+
const lastCheckedAt = store.lastCheckedAt ? Date.parse(store.lastCheckedAt) : Number.NaN;
|
|
17434
|
+
if (Number.isFinite(lastCheckedAt) && Date.now() - lastCheckedAt < CHECK_INTERVAL_MS) {
|
|
17435
|
+
return;
|
|
17436
|
+
}
|
|
17437
|
+
await writeUpdateCheckStore({
|
|
17438
|
+
lastCheckedAt: new Date().toISOString()
|
|
17439
|
+
}).catch(() => {
|
|
17440
|
+
return;
|
|
17441
|
+
});
|
|
17442
|
+
const latestVersion = await fetchLatestVersion().catch(() => {
|
|
17443
|
+
return;
|
|
17444
|
+
});
|
|
17445
|
+
if (!latestVersion || compareVersions(latestVersion, CURRENT_VERSION) <= 0) {
|
|
17446
|
+
return;
|
|
17447
|
+
}
|
|
17448
|
+
console.error("");
|
|
17449
|
+
console.error(`Update available: ${PACKAGE_NAME} ${CURRENT_VERSION} -> ${latestVersion}`);
|
|
17450
|
+
console.error(`Run: npm update -g ${PACKAGE_NAME}`);
|
|
17451
|
+
}
|
|
17452
|
+
function getCliPackageInfo() {
|
|
17453
|
+
return {
|
|
17454
|
+
name: PACKAGE_NAME,
|
|
17455
|
+
version: CURRENT_VERSION
|
|
17456
|
+
};
|
|
17457
|
+
}
|
|
17458
|
+
function isDisabled() {
|
|
17459
|
+
const value = process.env.MAITO_CLI_DISABLE_UPDATE_CHECK?.trim().toLowerCase();
|
|
17460
|
+
return value === "1" || value === "true" || value === "yes";
|
|
17461
|
+
}
|
|
17462
|
+
async function fetchLatestVersion() {
|
|
17463
|
+
const controller = new AbortController;
|
|
17464
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
17465
|
+
try {
|
|
17466
|
+
const response = await fetch(REGISTRY_LATEST_URL, {
|
|
17467
|
+
headers: {
|
|
17468
|
+
accept: "application/json"
|
|
17469
|
+
},
|
|
17470
|
+
signal: controller.signal
|
|
17471
|
+
});
|
|
17472
|
+
if (!response.ok) {
|
|
17473
|
+
return;
|
|
17474
|
+
}
|
|
17475
|
+
const payload = await response.json();
|
|
17476
|
+
return typeof payload.version === "string" && payload.version.trim() ? payload.version.trim() : undefined;
|
|
17477
|
+
} finally {
|
|
17478
|
+
clearTimeout(timeout);
|
|
17479
|
+
}
|
|
17480
|
+
}
|
|
17481
|
+
async function readUpdateCheckStore() {
|
|
17482
|
+
const filePath = getUpdateCheckFilePath();
|
|
17483
|
+
try {
|
|
17484
|
+
const raw = await readFile2(filePath, "utf8");
|
|
17485
|
+
const parsed = JSON.parse(raw);
|
|
17486
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
17487
|
+
} catch (error48) {
|
|
17488
|
+
if (error48.code === "ENOENT") {
|
|
17489
|
+
return {};
|
|
17490
|
+
}
|
|
17491
|
+
throw error48;
|
|
17492
|
+
}
|
|
17493
|
+
}
|
|
17494
|
+
async function writeUpdateCheckStore(store) {
|
|
17495
|
+
const filePath = getUpdateCheckFilePath();
|
|
17496
|
+
await mkdir2(path2.dirname(filePath), { recursive: true });
|
|
17497
|
+
await writeFile2(filePath, `${JSON.stringify(store, null, 2)}
|
|
17498
|
+
`, {
|
|
17499
|
+
encoding: "utf8",
|
|
17500
|
+
mode: 384
|
|
17501
|
+
});
|
|
17502
|
+
}
|
|
17503
|
+
function getUpdateCheckFilePath() {
|
|
17504
|
+
return path2.join(getConfigDir2(), "maito", "update-check.json");
|
|
17505
|
+
}
|
|
17506
|
+
function getConfigDir2() {
|
|
17507
|
+
if (process.platform === "win32") {
|
|
17508
|
+
return process.env.APPDATA?.trim() || path2.join(os2.homedir(), "AppData", "Roaming");
|
|
17509
|
+
}
|
|
17510
|
+
return process.env.XDG_CONFIG_HOME?.trim() || path2.join(os2.homedir(), ".config");
|
|
17511
|
+
}
|
|
17512
|
+
function compareVersions(left, right) {
|
|
17513
|
+
const leftParts = readVersionParts(left);
|
|
17514
|
+
const rightParts = readVersionParts(right);
|
|
17515
|
+
for (let index = 0;index < 3; index += 1) {
|
|
17516
|
+
const difference = (leftParts[index] ?? 0) - (rightParts[index] ?? 0);
|
|
17517
|
+
if (difference !== 0) {
|
|
17518
|
+
return difference;
|
|
17519
|
+
}
|
|
17520
|
+
}
|
|
17521
|
+
return 0;
|
|
17522
|
+
}
|
|
17523
|
+
function readVersionParts(value) {
|
|
17524
|
+
const release = value.split("-", 1)[0] ?? "";
|
|
17525
|
+
const parts = release.split(".");
|
|
17526
|
+
return [
|
|
17527
|
+
Number.parseInt(parts[0] ?? "0", 10) || 0,
|
|
17528
|
+
Number.parseInt(parts[1] ?? "0", 10) || 0,
|
|
17529
|
+
Number.parseInt(parts[2] ?? "0", 10) || 0
|
|
17530
|
+
];
|
|
17531
|
+
}
|
|
17532
|
+
|
|
17404
17533
|
// src/index.ts
|
|
17405
17534
|
async function main() {
|
|
17406
17535
|
const { positionals, flags } = parseArgs(process.argv.slice(2));
|
|
17407
17536
|
const json2 = readBooleanFlag(flags, "json");
|
|
17408
17537
|
const baseUrl = resolveApiBaseUrl(readStringFlag(flags, "base-url") ?? process.env.MAITO_BASE_URL);
|
|
17538
|
+
if (positionals[0] === "version" || readBooleanFlag(flags, "version")) {
|
|
17539
|
+
printVersion({ json: json2 });
|
|
17540
|
+
return;
|
|
17541
|
+
}
|
|
17409
17542
|
if (positionals.length === 0 || positionals[0] === "help" || readBooleanFlag(flags, "help")) {
|
|
17410
17543
|
printUsage();
|
|
17411
17544
|
return;
|
|
@@ -17422,6 +17555,7 @@ async function main() {
|
|
|
17422
17555
|
return;
|
|
17423
17556
|
}
|
|
17424
17557
|
console.log(`Signed in to ${status.baseUrl}${formatSignedInUser(status.user)}`);
|
|
17558
|
+
await maybePrintUpdateNotice({ json: json2 });
|
|
17425
17559
|
return;
|
|
17426
17560
|
}
|
|
17427
17561
|
if (commandKey === "logout") {
|
|
@@ -17434,10 +17568,12 @@ async function main() {
|
|
|
17434
17568
|
return;
|
|
17435
17569
|
}
|
|
17436
17570
|
console.log(removed ? `Signed out from ${baseUrl}.` : `No saved OAuth session for ${baseUrl}.`);
|
|
17571
|
+
await maybePrintUpdateNotice({ json: json2 });
|
|
17437
17572
|
return;
|
|
17438
17573
|
}
|
|
17439
17574
|
if (commandKey === "auth.status") {
|
|
17440
17575
|
await printAuthStatus({ baseUrl, json: json2 });
|
|
17576
|
+
await maybePrintUpdateNotice({ json: json2 });
|
|
17441
17577
|
return;
|
|
17442
17578
|
}
|
|
17443
17579
|
if (commandKey === "auth.use-api-key") {
|
|
@@ -17448,6 +17584,7 @@ async function main() {
|
|
|
17448
17584
|
return;
|
|
17449
17585
|
}
|
|
17450
17586
|
console.log(`Stored API key for ${baseUrl}.`);
|
|
17587
|
+
await maybePrintUpdateNotice({ json: json2 });
|
|
17451
17588
|
return;
|
|
17452
17589
|
}
|
|
17453
17590
|
if (commandKey === "auth.clear-api-key") {
|
|
@@ -17457,6 +17594,7 @@ async function main() {
|
|
|
17457
17594
|
return;
|
|
17458
17595
|
}
|
|
17459
17596
|
console.log(removed ? `Removed stored API key for ${baseUrl}.` : `No stored API key for ${baseUrl}.`);
|
|
17597
|
+
await maybePrintUpdateNotice({ json: json2 });
|
|
17460
17598
|
return;
|
|
17461
17599
|
}
|
|
17462
17600
|
const context = {
|
|
@@ -17516,6 +17654,7 @@ async function main() {
|
|
|
17516
17654
|
return;
|
|
17517
17655
|
}
|
|
17518
17656
|
printHuman(outputKey, result);
|
|
17657
|
+
await maybePrintUpdateNotice({ json: json2 });
|
|
17519
17658
|
}
|
|
17520
17659
|
async function printAuthStatus(input) {
|
|
17521
17660
|
const [status, storedApiKey] = await Promise.all([
|
|
@@ -17864,6 +18003,10 @@ function parseArgs(argv) {
|
|
|
17864
18003
|
if (!value) {
|
|
17865
18004
|
continue;
|
|
17866
18005
|
}
|
|
18006
|
+
if (value === "-v") {
|
|
18007
|
+
flags.version = true;
|
|
18008
|
+
continue;
|
|
18009
|
+
}
|
|
17867
18010
|
if (!value.startsWith("--")) {
|
|
17868
18011
|
positionals.push(value);
|
|
17869
18012
|
continue;
|
|
@@ -17896,6 +18039,17 @@ function normalizeOutputKey(positionals) {
|
|
|
17896
18039
|
const root = normalizeRoot(positionals[0]);
|
|
17897
18040
|
return [root, positionals[1]].filter(Boolean).join(".");
|
|
17898
18041
|
}
|
|
18042
|
+
function printVersion(input) {
|
|
18043
|
+
const packageInfo = getCliPackageInfo();
|
|
18044
|
+
if (input.json) {
|
|
18045
|
+
printJson({
|
|
18046
|
+
command: "maito",
|
|
18047
|
+
...packageInfo
|
|
18048
|
+
});
|
|
18049
|
+
return;
|
|
18050
|
+
}
|
|
18051
|
+
console.log(`maito ${packageInfo.version}`);
|
|
18052
|
+
}
|
|
17899
18053
|
function requireAction(context, index, command) {
|
|
17900
18054
|
const action = context.positionals[index];
|
|
17901
18055
|
if (!action) {
|
|
@@ -18092,6 +18246,8 @@ function parseJson(value, label) {
|
|
|
18092
18246
|
}
|
|
18093
18247
|
function printUsage() {
|
|
18094
18248
|
console.log(`Usage:
|
|
18249
|
+
maito version [--json]
|
|
18250
|
+
maito --version
|
|
18095
18251
|
maito login [--base-url <url>] [--oauth-client-id <id>] [--json]
|
|
18096
18252
|
maito logout [--base-url <url>] [--json]
|
|
18097
18253
|
maito auth status [--base-url <url>] [--json]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AA4BA,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,iBA8BpE;AAED,wBAAgB,iBAAiB;;;EAKhC"}
|