@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 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
- return response.json().catch(() => {
17298
- throw new Error(`Failed to parse ${label} response.`);
17299
- }).then((payload) => {
17300
- if (!response.ok) {
17301
- throw new Error(formatOAuthError(label, payload, response.status));
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
- return payload;
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,8 @@
1
+ export declare function maybePrintUpdateNotice(input: {
2
+ json: boolean;
3
+ }): Promise<void>;
4
+ export declare function getCliPackageInfo(): {
5
+ name: string;
6
+ version: string;
7
+ };
8
+ //# 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":"AA4BA,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,iBA8BpE;AAED,wBAAgB,iBAAiB;;;EAKhC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getmaito/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "maito": "dist/index.js"