@secondlayer/cli 21.3.0 → 22.0.0

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
@@ -15,8 +15,8 @@ secondlayer --version
15
15
  Default API is `http://127.0.0.1:3800`. Override with `SECONDLAYER_API_URL`.
16
16
 
17
17
  Writes against a published bind use `INSTANCE_TOKEN` from `secondlayer init`.
18
- Loopback reads need no token. Hosted API and archive credits use
19
- `SECONDLAYER_API_KEY` (`sk-sl_*`).
18
+ Loopback reads need no token. Your hosted account (credits, archive fetches)
19
+ uses `secondlayer login` or `SECONDLAYER_API_KEY` (`sk-sl_*`).
20
20
 
21
21
  ```bash
22
22
  export SECONDLAYER_API_URL=http://127.0.0.1:3800
package/dist/cli.js CHANGED
@@ -2369,12 +2369,12 @@ async function resolveArchiveOpsBearer() {
2369
2369
  };
2370
2370
  }
2371
2371
  function ignoredEnvKeyNote(ignored) {
2372
- return ignored ? " INSTANCE_TOKEN was ignored: it unlocks this instance, not archive credits." : "";
2372
+ return ignored ? " INSTANCE_TOKEN was ignored: it unlocks this instance, not your account." : "";
2373
2373
  }
2374
2374
  async function httpArchiveOps(path, opts = {}) {
2375
2375
  const { bearer, ignoredEnvKey } = await resolveArchiveOpsBearer();
2376
2376
  if (!bearer) {
2377
- throw new CliHttpError(401, "SESSION_EXPIRED", { error: "Not logged in" }, `Archive credits need an account key. ${ARCHIVE_AUTH_HINT}${ignoredEnvKeyNote(ignoredEnvKey)}`);
2377
+ throw new CliHttpError(401, "SESSION_EXPIRED", { error: "Not logged in" }, `This needs your Secondlayer account. ${ARCHIVE_AUTH_HINT}${ignoredEnvKeyNote(ignoredEnvKey)}`);
2378
2378
  }
2379
2379
  try {
2380
2380
  return await request(`${resolveArchiveOpsUrl()}${path}`, {
@@ -2383,12 +2383,12 @@ async function httpArchiveOps(path, opts = {}) {
2383
2383
  });
2384
2384
  } catch (err) {
2385
2385
  if (err instanceof CliHttpError && err.status === 401) {
2386
- throw new CliHttpError(401, err.code, err.body, `Archive credits rejected the credential (${err.message}). ${ARCHIVE_AUTH_HINT}${ignoredEnvKeyNote(ignoredEnvKey)}`);
2386
+ throw new CliHttpError(401, err.code, err.body, `Your account rejected the credential (${err.message}). ${ARCHIVE_AUTH_HINT}${ignoredEnvKeyNote(ignoredEnvKey)}`);
2387
2387
  }
2388
2388
  throw err;
2389
2389
  }
2390
2390
  }
2391
- var CliHttpError, REQUEST_TIMEOUT_MS = 30000, ARCHIVE_AUTH_HINT = "Set SECONDLAYER_API_KEY to your account key (sk-sl_…, from /account/keys), or run `secondlayer login --credits`.", ARCHIVE_CREDENTIAL_RE;
2391
+ var CliHttpError, REQUEST_TIMEOUT_MS = 30000, ARCHIVE_AUTH_HINT = "Set SECONDLAYER_API_KEY to your account key (sk-sl_…, from /account/keys), or run `secondlayer login`.", ARCHIVE_CREDENTIAL_RE;
2392
2392
  var init_http = __esm(() => {
2393
2393
  init_api_url();
2394
2394
  init_resolve_auth();
@@ -202692,7 +202692,7 @@ var {
202692
202692
  // package.json
202693
202693
  var package_default = {
202694
202694
  name: "@secondlayer/cli",
202695
- version: "21.3.0",
202695
+ version: "22.0.0",
202696
202696
  description: "Run a Stacks index on your own hardware — set it up, restore verified history, and keep it current.",
202697
202697
  repository: {
202698
202698
  type: "git",
@@ -202811,7 +202811,7 @@ var BUY_CREDITS_COMMAND = "secondlayer credits buy";
202811
202811
  function formatInsufficientMessage(quote) {
202812
202812
  const shortfallUsd = ((quote.usdMicros - quote.balanceUsdMicros) / 1e6).toFixed(2);
202813
202813
  const balanceUsd = (quote.balanceUsdMicros / 1e6).toFixed(2);
202814
- return `Insufficient archive credits: quote $${quote.usd}, balance $${balanceUsd}, short $${shortfallUsd}. Buy more with \`${BUY_CREDITS_COMMAND}\`.`;
202814
+ return `Insufficient credits: quote $${quote.usd}, balance $${balanceUsd}, short $${shortfallUsd}. Buy more with \`${BUY_CREDITS_COMMAND}\`.`;
202815
202815
  }
202816
202816
  var ARCHIVE_GATE_NOT_CONFIGURED_MESSAGE = "the archive gate is not configured on the server; contact the operator";
202817
202817
  var ALLOWANCE_MONTHLY_BUNDLES = 6;
@@ -204986,7 +204986,7 @@ async function runBuy(opts) {
204986
204986
  human: () => {
204987
204987
  success(`Checkout for $${amount} → ${email}`);
204988
204988
  console.log(res.url);
204989
- console.log(dim("After payment: set SECONDLAYER_API_KEY (or run `secondlayer login --credits`), then run `secondlayer credits balance`"));
204989
+ console.log(dim("After payment: set SECONDLAYER_API_KEY (or run `secondlayer login`), then run `secondlayer credits balance`"));
204990
204990
  }
204991
204991
  });
204992
204992
  }
@@ -205061,8 +205061,8 @@ async function runUsage(opts) {
205061
205061
  });
205062
205062
  }
205063
205063
  function registerCreditsCommand(program) {
205064
- const credits = program.command("credits").description("Buy and check archive credits");
205065
- credits.command("buy").description("Open a one-time Stripe checkout for archive credits").requiredOption("--email <email>", "Receipt email; becomes the account").option("--pack <usd>", `One of ${PACKS.join(", ")}`, "25").option("--json", "Output as JSON").action((opts) => runBuy(opts));
205064
+ const credits = program.command("credits").description("Buy and check your credits");
205065
+ credits.command("buy").description("Open a one-time Stripe checkout for credits").requiredOption("--email <email>", "Receipt email; becomes the account").option("--pack <usd>", `One of ${PACKS.join(", ")}`, "25").option("--json", "Output as JSON").action((opts) => runBuy(opts));
205066
205066
  credits.command("balance").description("Show prepaid archive credit balance").option("--json", "Output as JSON").action((opts) => runBalance(opts));
205067
205067
  credits.command("usage").description("Rows delivered per day: free vs paid, by source").option("--days <n>", "Days to show (max 30)", "30").option("--json", "Output as JSON").action((opts) => runUsage(opts));
205068
205068
  credits.command("refill").description("Opt-in auto-refill when the balance drops under a threshold").option("--below <usd>", "Trigger when balance is under this USD amount").option("--pack <usd>", `Pack to buy (${PACKS.join(", ")})`, "25").option("--off", "Turn auto-refill off").option("--json", "Output as JSON").action((opts) => runRefill(opts));
@@ -207836,16 +207836,16 @@ async function readStdin() {
207836
207836
  chunks.push(chunk);
207837
207837
  return Buffer.concat(chunks).toString("utf8").trim();
207838
207838
  }
207839
- function loginTarget(opts) {
207840
- return opts.credits ? resolveArchiveOpsUrl() : resolveApiUrl();
207839
+ function loginTarget() {
207840
+ return resolveArchiveOpsUrl();
207841
207841
  }
207842
- async function runTokenLogin(opts) {
207842
+ async function runTokenLogin() {
207843
207843
  const token = await readStdin();
207844
207844
  if (!token) {
207845
207845
  error('No token on stdin. Usage: echo "$KEY" | secondlayer login --with-token');
207846
207846
  process.exit(1);
207847
207847
  }
207848
- const target = loginTarget(opts);
207848
+ const target = loginTarget();
207849
207849
  let account;
207850
207850
  try {
207851
207851
  account = await httpAt(target, "/api/accounts/me", { bearer: token });
@@ -207895,7 +207895,11 @@ async function pollDeviceToken(start, deps) {
207895
207895
  await deps.sleep(start.interval * 1000);
207896
207896
  try {
207897
207897
  const res = await deps.post("/api/cli/device/token", { deviceCode: start.deviceCode });
207898
- return { kind: "approved", key: res.key, account: res.account };
207898
+ return {
207899
+ kind: "approved",
207900
+ sessionToken: res.sessionToken,
207901
+ account: res.account
207902
+ };
207899
207903
  } catch (err) {
207900
207904
  if (err instanceof CliHttpError) {
207901
207905
  if (err.status === 428) {
@@ -207905,9 +207909,6 @@ async function pollDeviceToken(start, deps) {
207905
207909
  if (err.status === 403 && err.body.error === "access_denied") {
207906
207910
  return { kind: "denied" };
207907
207911
  }
207908
- if (err.status === 409 && err.body.error === "key_limit") {
207909
- return { kind: "key_limit" };
207910
- }
207911
207912
  if (err.status === 410)
207912
207913
  return { kind: "expired" };
207913
207914
  throw err;
@@ -207918,12 +207919,11 @@ async function pollDeviceToken(start, deps) {
207918
207919
  }
207919
207920
  return { kind: "expired" };
207920
207921
  }
207921
- var KEY_LIMIT_MESSAGE = "You have 50 keys. Revoke one under Keys, then run secondlayer login again.";
207922
207922
  function clientName() {
207923
207923
  return hostname().trim().slice(0, 64) || "this machine";
207924
207924
  }
207925
207925
  async function runDeviceLogin(options = {}) {
207926
- const target = loginTarget(options);
207926
+ const target = loginTarget();
207927
207927
  if (!await shouldContinueLogin(target, options))
207928
207928
  return;
207929
207929
  let start;
@@ -207961,25 +207961,21 @@ async function runDeviceLogin(options = {}) {
207961
207961
  error("Cancelled in the browser.");
207962
207962
  process.exit(1);
207963
207963
  }
207964
- if (outcome.kind === "key_limit") {
207965
- error(KEY_LIMIT_MESSAGE);
207966
- process.exit(1);
207967
- }
207968
207964
  if (outcome.kind === "expired") {
207969
207965
  error("The code expired. Run secondlayer login again.");
207970
207966
  process.exit(1);
207971
207967
  }
207972
207968
  await writeSession({
207973
- token: outcome.key,
207969
+ token: outcome.sessionToken,
207974
207970
  email: outcome.account.email,
207975
207971
  accountId: outcome.account.id,
207976
207972
  expiresAt: sessionExpiry()
207977
207973
  }, target);
207978
207974
  success(`Logged in as ${outcome.account.email} on ${clientName()}`);
207979
- info(dim("This machine has its own key. Revoke it under Keys."));
207975
+ info(dim("Run 'secondlayer logout' to sign this machine out."));
207980
207976
  }
207981
207977
  async function runLoginFlow(options = {}) {
207982
- const target = loginTarget(options);
207978
+ const target = loginTarget();
207983
207979
  if (!await shouldContinueLogin(target, options))
207984
207980
  return;
207985
207981
  const email = await input({
@@ -208019,7 +208015,7 @@ async function runLoginFlow(options = {}) {
208019
208015
  expiresAt: sessionExpiry()
208020
208016
  }, target);
208021
208017
  success(`Logged in as ${verified.account.email}`);
208022
- info(dim(options.credits ? "Run 'secondlayer credits balance' to see your archive credits." : "Run 'secondlayer whoami' to see your account status."));
208018
+ info(dim("Run 'secondlayer whoami' to see your account status."));
208023
208019
  } catch (err) {
208024
208020
  if (err instanceof CliHttpError) {
208025
208021
  error(err.message);
@@ -208030,19 +208026,18 @@ async function runLoginFlow(options = {}) {
208030
208026
  }
208031
208027
  }
208032
208028
  function registerLoginCommand(program) {
208033
- program.command("login").description("Log in to Secondlayer through your browser").option("--force", "Skip the already-logged-in check and re-run the flow").option("--email", "Sign in with an emailed 6-digit code instead of a browser").option("--with-token", "Read an API key from stdin (non-interactive)").option("--credits", "Log in to the archive credits account used by bootstrap, repair, and credits").addHelpText("after", `
208029
+ program.command("login").description("Log in to Secondlayer through your browser").option("--force", "Skip the already-logged-in check and re-run the flow").option("--email", "Sign in with an emailed 6-digit code instead of a browser").option("--with-token", "Read an API key from stdin (non-interactive)").addHelpText("after", `
208034
208030
  Examples:
208035
208031
  $ secondlayer login
208036
208032
  $ secondlayer login --email
208037
- $ secondlayer login --credits
208038
- $ echo "$SECONDLAYER_API_KEY" | secondlayer login --with-token`).action((opts) => opts.withToken ? runTokenLogin({ credits: opts.credits }) : opts.email ? runLoginFlow({ force: opts.force, credits: opts.credits }) : runDeviceLogin({ force: opts.force, credits: opts.credits }));
208033
+ $ echo "$SECONDLAYER_API_KEY" | secondlayer login --with-token`).action((opts) => opts.withToken ? runTokenLogin() : opts.email ? runLoginFlow({ force: opts.force }) : runDeviceLogin({ force: opts.force }));
208039
208034
  }
208040
208035
  // src/commands/logout.ts
208041
208036
  init_http();
208042
208037
  init_output();
208043
208038
  init_session();
208044
- async function runLogout(opts = {}) {
208045
- const target = loginTarget(opts);
208039
+ async function runLogout() {
208040
+ const target = loginTarget();
208046
208041
  const session = await readSession(target);
208047
208042
  if (!session) {
208048
208043
  info(`Not logged in (${target}).`);
@@ -208062,7 +208057,7 @@ async function runLogout(opts = {}) {
208062
208057
  success(`Logged out (${target}).`);
208063
208058
  }
208064
208059
  function registerLogoutCommand(program) {
208065
- program.command("logout").description("Log out and revoke the local session").option("--credits", "Log out of the archive credits account used by bootstrap, repair, and credits").action((opts) => runLogout({ credits: opts.credits }));
208060
+ program.command("logout").description("Sign this machine out of your Secondlayer account").action(() => runLogout());
208066
208061
  }
208067
208062
  // src/commands/backup.ts
208068
208063
  init_fs();
@@ -208476,7 +208471,7 @@ function renderInstanceEnv(env) {
208476
208471
  `SECONDLAYER_API_URL=${env.SECONDLAYER_API_URL}`
208477
208472
  ];
208478
208473
  if (env.SECONDLAYER_API_KEY) {
208479
- lines.push("# Hosted account key for archive credits (sk-sl_*).", `SECONDLAYER_API_KEY=${env.SECONDLAYER_API_KEY}`);
208474
+ lines.push("# Hosted account key for credits and archive fetches (sk-sl_*).", `SECONDLAYER_API_KEY=${env.SECONDLAYER_API_KEY}`);
208480
208475
  }
208481
208476
  lines.push("# Archive trust root: bootstrap, verify, and repair check manifests", "# against this key. Replace it to pin a different archive.", `ARCHIVE_SIGNING_PUBLIC_KEY=${escapeEnvValue(env.ARCHIVE_SIGNING_PUBLIC_KEY)}`, "");
208482
208477
  return lines.join(`
@@ -208664,5 +208659,5 @@ registerCreditsCommand(program);
208664
208659
  registerArchiveCommand(program);
208665
208660
  program.parse();
208666
208661
 
208667
- //# debugId=9552E9D4123BD8E564756E2164756E21
208662
+ //# debugId=32DC3B7BA2B6602D64756E2164756E21
208668
208663
  //# sourceMappingURL=cli.js.map