@farthershore/cli 0.3.7 → 0.3.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/dist/output.js ADDED
@@ -0,0 +1,28 @@
1
+ // Output formatting: tables, JSON, colors
2
+ import chalk from "chalk";
3
+ export function json(data) {
4
+ return JSON.stringify(data, null, 2);
5
+ }
6
+ export function success(msg) {
7
+ console.log(chalk.green(`✓ ${msg}`));
8
+ }
9
+ export function error(msg) {
10
+ console.error(chalk.red(`✗ ${msg}`));
11
+ }
12
+ export function warn(msg) {
13
+ console.warn(chalk.yellow(`⚠ ${msg}`));
14
+ }
15
+ export function info(msg) {
16
+ console.log(chalk.dim(msg));
17
+ }
18
+ export function heading(msg) {
19
+ console.log(chalk.bold(msg));
20
+ }
21
+ export function isTTY() {
22
+ return process.stdout.isTTY === true;
23
+ }
24
+ export function outputFormat(flagFormat) {
25
+ if (flagFormat === "json" || flagFormat === "table")
26
+ return flagFormat;
27
+ return isTTY() ? "table" : "json";
28
+ }
@@ -0,0 +1,53 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Per-error-code remediation hints.
3
+ //
4
+ // When `core` returns a 4XX/5XX with a known `error.code`, the CLI prints
5
+ // the code alongside the message AND a 1-line "next step" so users (and
6
+ // agents) don't have to grep docs to figure out what to do.
7
+ //
8
+ // Codes are kept as raw strings — the CLI doesn't depend on the SDK, and
9
+ // pulling in `@farther-shore/sdk` just for a string union would be more
10
+ // coupling than this is worth. If a code is missing here, no remediation
11
+ // is shown — fail-safe, never wrong.
12
+ // ---------------------------------------------------------------------------
13
+ const REMEDIATIONS = {
14
+ // --- Auth ---
15
+ UNAUTHORIZED: "Token is invalid or revoked. Run `farthershore set-key` to update it.",
16
+ FORBIDDEN: "Your token doesn't have access to this resource. Check the org / product scope.",
17
+ INVALID_ACCESS_KEY: "Token format is wrong. Generate a new one at https://farthershore.com/settings/tokens.",
18
+ MAKER_TOKEN_REVOKED: "This maker token was revoked. Mint a new one in the product settings.",
19
+ MAKER_TOKEN_NO_PRODUCT: "Maker token is not bound to a product. Re-create it from the product page.",
20
+ // --- Stripe ---
21
+ STRIPE_NOT_CONFIGURED: "Stripe isn't connected on this product. Connect it in the dashboard before running billing operations.",
22
+ STRIPE_BALANCE_OUTSTANDING: "Customer has an outstanding balance. Resolve the invoice in Stripe before retrying.",
23
+ CHECKOUT_SESSION_FAILED: "Stripe rejected the checkout request. Check that the plan exists and Stripe credentials are valid.",
24
+ // --- Product / config ---
25
+ PRODUCT_NOT_FOUND: "Check the product slug. Run `farthershore` (no args) for a list of products you can see.",
26
+ PRODUCT_REPO_NOT_LINKED: "Link a GitHub repo to this product before running `apply`.",
27
+ PRODUCT_YAML_NOT_FOUND: "No product.yaml on the target branch. Push a config file before running `apply`.",
28
+ YAML_PARSE_ERROR: "product.yaml is not valid YAML. Run `farthershore validate` locally to see the parse error.",
29
+ GITHUB_NOT_CONNECTED: "Connect GitHub on the org page before running `init` (it provisions the repo).",
30
+ BRANCH_NO_MATCHING_ENV: "The current branch isn't mapped to an environment. Add a branch rule in product settings or pass --branch explicitly.",
31
+ // --- Plans / pricing ---
32
+ PLAN_NOT_FOUND: "Plan key doesn't exist on this product. Check `plans:` in product.yaml.",
33
+ PLAN_HAS_ACTIVE_SUBSCRIPTIONS: "Plan has active subscribers and can't be deleted. Migrate them to another plan first.",
34
+ PLAN_SLUG_CONFLICT: "Another plan already uses this key. Pick a unique key in product.yaml.",
35
+ SLUG_CONFLICT: "This product slug is taken. Pick a different name.",
36
+ SLUG_BLOCKED: "This slug is reserved or blocked. Pick a different name.",
37
+ SLUG_RESERVED: "This slug is reserved by Farther Shore. Pick a different name.",
38
+ SLUG_INVALID_FORMAT: "Slug must be lowercase letters, digits, and hyphens (no leading/trailing hyphen).",
39
+ // --- Generic ---
40
+ RATE_LIMIT_EXCEEDED: "You've hit the rate limit. Wait a moment and retry.",
41
+ VALIDATION_ERROR: "Request is malformed. The `details` field has the field-level errors.",
42
+ CONFLICT: "The resource is in a state that conflicts with the request. Inspect `details` to learn more.",
43
+ };
44
+ /**
45
+ * Look up a one-line remediation hint for a server error code. Returns
46
+ * `undefined` if no hint is registered — callers should treat that as
47
+ * "show no hint" rather than a fallback string.
48
+ */
49
+ export function getRemediation(code) {
50
+ if (!code)
51
+ return undefined;
52
+ return REMEDIATIONS[code];
53
+ }
package/dist/types.d.ts CHANGED
@@ -33,6 +33,8 @@ export type Plan = BuilderPlan;
33
33
  export type CliConfig = {
34
34
  apiUrl: string;
35
35
  activeOrg?: string;
36
+ activeProductId?: string;
37
+ activeProductName?: string;
36
38
  defaultFormat?: "table" | "json" | "yaml";
37
39
  };
38
40
  export type Credentials = {
package/dist/types.js ADDED
@@ -0,0 +1,23 @@
1
+ // Shared types for the FartherShore CLI
2
+ /**
3
+ * Error thrown by the CLI for any non-success path. Carries the canonical
4
+ * `code` from core's `{ error: { code, message, details? } }` envelope so
5
+ * the global error handler can print the code alongside the message and
6
+ * dispatch a remediation hint when one is registered for that code.
7
+ *
8
+ * `code`/`details` are optional because the same class also gets thrown for
9
+ * local (non-API) failures — e.g. "no token configured" — where there's no
10
+ * server-side code to surface.
11
+ */
12
+ export class CliError extends Error {
13
+ status;
14
+ code;
15
+ details;
16
+ constructor(message, status, extra) {
17
+ super(message);
18
+ this.status = status;
19
+ this.name = "CliError";
20
+ this.code = extra?.code;
21
+ this.details = extra?.details;
22
+ }
23
+ }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@farthershore/cli",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "FartherShore CLI — create and configure API products",
5
5
  "type": "module",
6
6
  "bin": {
7
- "farthershore": "./dist/index.js"
7
+ "farthershore": "dist/index.js"
8
8
  },
9
9
  "files": [
10
10
  "dist"
@@ -17,13 +17,11 @@
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",
20
- "url": "https://github.com/farther-shore/farthershore.git"
20
+ "url": "git+https://github.com/farther-shore/farthershore.git"
21
21
  },
22
22
  "scripts": {
23
23
  "dev": "tsx src/index.ts",
24
- "build": "rm -rf dist && npm run build:types && npm run build:bundle",
25
- "build:types": "tsc --emitDeclarationOnly",
26
- "build:bundle": "esbuild src/index.ts --bundle --platform=node --format=esm --target=node22 --outfile=dist/index.js --external:chalk --external:commander --external:yaml --external:zod && chmod +x dist/index.js",
24
+ "build": "tsc",
27
25
  "prepublishOnly": "npm run build",
28
26
  "test": "vitest run",
29
27
  "lint": "prettier --check \"src/**/*.ts\" && eslint .",
@@ -41,15 +39,14 @@
41
39
  "author": "Farther Shore",
42
40
  "license": "MIT",
43
41
  "dependencies": {
42
+ "@farther-shore/shared-types": "^0.28.2",
44
43
  "chalk": "^5.4.1",
45
44
  "commander": "^13.1.0",
46
45
  "yaml": "^2.8.3",
47
46
  "zod": "^4.3.6"
48
47
  },
49
48
  "devDependencies": {
50
- "@farther-shore/shared-types": "^0.28.2",
51
49
  "@types/node": "^22.19.17",
52
- "esbuild": "^0.28.0",
53
50
  "eslint": "^9.39.4",
54
51
  "eslint-plugin-sonarjs": "^4.0.3",
55
52
  "prettier": "^3.8.1",