@secondlayer/cli 1.4.1 → 1.5.1

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/cli.js CHANGED
@@ -2202,8 +2202,8 @@ function migrateConfig(raw) {
2202
2202
  if (typeof old.apiKey === "string") {
2203
2203
  migrated.apiKey = old.apiKey;
2204
2204
  }
2205
- if (typeof old.sessionToken === "string") {
2206
- migrated.sessionToken = old.sessionToken;
2205
+ if (typeof old.sessionToken === "string" && !migrated.apiKey) {
2206
+ console.warn("Warning: config contains sessionToken but no apiKey. Run `sl auth login` to re-authenticate.");
2207
2207
  }
2208
2208
  if (typeof old.apiUrl === "string" && old.apiUrl !== "http://localhost:3800") {
2209
2209
  migrated.apiUrl = old.apiUrl;
@@ -2268,9 +2268,6 @@ function applyEnvOverrides(config) {
2268
2268
  if (process.env.SECONDLAYER_API_KEY) {
2269
2269
  result.apiKey = process.env.SECONDLAYER_API_KEY;
2270
2270
  }
2271
- if (process.env.SECONDLAYER_SESSION_TOKEN) {
2272
- result.sessionToken = process.env.SECONDLAYER_SESSION_TOKEN;
2273
- }
2274
2271
  if (process.env.SL_DATA_DIR) {
2275
2272
  result.dataDir = process.env.SL_DATA_DIR;
2276
2273
  }
@@ -2406,7 +2403,6 @@ var init_config = __esm(() => {
2406
2403
  network: NetworkSchema.default("mainnet"),
2407
2404
  apiUrl: z.string().url().optional(),
2408
2405
  apiKey: z.string().optional(),
2409
- sessionToken: z.string().optional(),
2410
2406
  dataDir: z.string().default("~/.secondlayer/data"),
2411
2407
  defaultWebhookUrl: z.string().url().optional(),
2412
2408
  node: NodeSchema.optional(),
@@ -4550,10 +4546,25 @@ __export(exports_api_client, {
4550
4546
  deleteStream: () => deleteStream,
4551
4547
  createStream: () => createStream,
4552
4548
  authHeaders: () => authHeaders,
4549
+ assertOk: () => assertOk,
4553
4550
  ApiError: () => ApiError
4554
4551
  });
4555
4552
  import { SecondLayer } from "@secondlayer/sdk";
4556
4553
  import { ApiError } from "@secondlayer/sdk";
4554
+ async function assertOk(res) {
4555
+ if (res.ok)
4556
+ return;
4557
+ const body = await res.text();
4558
+ try {
4559
+ const parsed = JSON.parse(body);
4560
+ if (typeof parsed.error === "string" && parsed.error)
4561
+ throw new Error(parsed.error);
4562
+ } catch (e) {
4563
+ if (e instanceof Error && e.message !== body)
4564
+ throw e;
4565
+ }
4566
+ throw new Error(`HTTP ${res.status}`);
4567
+ }
4557
4568
  function handleApiError(err, action) {
4558
4569
  if (err instanceof ApiError && err.status === 401) {
4559
4570
  console.error("Error: Authentication required. Run: sl auth login");
@@ -4565,10 +4576,10 @@ function handleApiError(err, action) {
4565
4576
  async function getClient() {
4566
4577
  const config = await loadConfig();
4567
4578
  const baseUrl = resolveApiUrl(config);
4568
- return new SecondLayer({ baseUrl, apiKey: config.sessionToken ?? config.apiKey });
4579
+ return new SecondLayer({ baseUrl, apiKey: config.apiKey });
4569
4580
  }
4570
4581
  function authHeaders(config) {
4571
- return SecondLayer.authHeaders(config.sessionToken ?? config.apiKey);
4582
+ return SecondLayer.authHeaders(config.apiKey);
4572
4583
  }
4573
4584
  async function createStream(data) {
4574
4585
  return (await getClient()).streams.create(data);
@@ -20157,6 +20168,8 @@ function isDirectFileContract(c) {
20157
20168
  import { promises as fs3 } from "fs";
20158
20169
  import path from "path";
20159
20170
  import { isValidAddress as _validateStacksAddress } from "@secondlayer/stacks";
20171
+ import { getErrorMessage } from "@secondlayer/shared";
20172
+ import { toCamelCase as toCamelCase2 } from "@secondlayer/stacks/clarity";
20160
20173
 
20161
20174
  class PluginManager {
20162
20175
  plugins = [];
@@ -20199,12 +20212,11 @@ class PluginManager {
20199
20212
  success: true
20200
20213
  });
20201
20214
  } catch (error2) {
20202
- const err = error2;
20203
20215
  this.recordHookResult(plugin.name, "transformConfig", {
20204
20216
  success: false,
20205
- error: err
20217
+ error: error2 instanceof Error ? error2 : new Error(getErrorMessage(error2))
20206
20218
  });
20207
- throw new Error(`Plugin "${plugin.name}" failed during config transformation: ${err.message}`);
20219
+ throw new Error(`Plugin "${plugin.name}" failed during config transformation: ${getErrorMessage(error2)}`);
20208
20220
  }
20209
20221
  }
20210
20222
  }
@@ -20218,31 +20230,11 @@ class PluginManager {
20218
20230
  const processedContracts = [];
20219
20231
  for (let contract of contracts) {
20220
20232
  if (isClarinetContract(contract) && contract.abi) {
20221
- const address = typeof contract.address === "string" ? contract.address : "";
20222
- const parsed = parseContractId(address);
20223
- const processed = {
20224
- name: contract.name || parsed.contractName,
20225
- address: parsed.address,
20226
- contractName: parsed.contractName,
20227
- abi: contract.abi,
20228
- source: "local",
20229
- metadata: { source: "clarinet" }
20230
- };
20231
- processedContracts.push(processed);
20233
+ processedContracts.push(this.contractToProcessed(contract, "clarinet"));
20232
20234
  continue;
20233
20235
  }
20234
20236
  if (isDirectFileContract(contract) && contract.abi) {
20235
- const address = typeof contract.address === "string" ? contract.address : "";
20236
- const parsed = parseContractId(address);
20237
- const processed = {
20238
- name: contract.name || parsed.contractName,
20239
- address: parsed.address,
20240
- contractName: parsed.contractName,
20241
- abi: contract.abi,
20242
- source: "local",
20243
- metadata: { source: "direct" }
20244
- };
20245
- processedContracts.push(processed);
20237
+ processedContracts.push(this.contractToProcessed(contract, "direct"));
20246
20238
  continue;
20247
20239
  }
20248
20240
  for (const plugin of this.plugins) {
@@ -20254,27 +20246,16 @@ class PluginManager {
20254
20246
  success: true
20255
20247
  });
20256
20248
  } catch (error2) {
20257
- const err = error2;
20258
20249
  this.recordHookResult(plugin.name, "transformContract", {
20259
20250
  success: false,
20260
- error: err
20251
+ error: error2 instanceof Error ? error2 : new Error(getErrorMessage(error2))
20261
20252
  });
20262
- this.logger.warn(`Plugin "${plugin.name}" failed to transform contract: ${err.message}`);
20253
+ this.logger.warn(`Plugin "${plugin.name}" failed to transform contract: ${getErrorMessage(error2)}`);
20263
20254
  }
20264
20255
  }
20265
20256
  }
20266
20257
  if (contract.abi) {
20267
- const addressStr = typeof contract.address === "string" ? contract.address : "";
20268
- const parsed = parseContractId(addressStr);
20269
- const processed = {
20270
- name: contract.name || parsed.contractName || "unknown",
20271
- address: parsed.address || "unknown",
20272
- contractName: parsed.contractName || contract.name || "unknown",
20273
- abi: contract.abi,
20274
- source: "api",
20275
- metadata: contract.metadata
20276
- };
20277
- processedContracts.push(processed);
20258
+ processedContracts.push(this.contractToProcessed(contract, "api"));
20278
20259
  }
20279
20260
  }
20280
20261
  return processedContracts;
@@ -20290,12 +20271,11 @@ class PluginManager {
20290
20271
  success: true
20291
20272
  });
20292
20273
  } catch (error2) {
20293
- const err = error2;
20294
20274
  this.recordHookResult(plugin.name, hookName, {
20295
20275
  success: false,
20296
- error: err
20276
+ error: error2 instanceof Error ? error2 : new Error(getErrorMessage(error2))
20297
20277
  });
20298
- this.logger.error(`Plugin "${plugin.name}" failed during ${hookName}: ${err.message}`);
20278
+ this.logger.error(`Plugin "${plugin.name}" failed during ${hookName}: ${getErrorMessage(error2)}`);
20299
20279
  }
20300
20280
  }
20301
20281
  }
@@ -20335,12 +20315,11 @@ class PluginManager {
20335
20315
  success: true
20336
20316
  });
20337
20317
  } catch (error2) {
20338
- const err = error2;
20339
20318
  this.recordHookResult(plugin.name, "transformOutput", {
20340
20319
  success: false,
20341
- error: err
20320
+ error: error2 instanceof Error ? error2 : new Error(getErrorMessage(error2))
20342
20321
  });
20343
- this.logger.warn(`Plugin "${plugin.name}" failed to transform output: ${err.message}`);
20322
+ this.logger.warn(`Plugin "${plugin.name}" failed to transform output: ${getErrorMessage(error2)}`);
20344
20323
  }
20345
20324
  }
20346
20325
  }
@@ -20358,15 +20337,26 @@ class PluginManager {
20358
20337
  await this.utils.ensureDir(path.dirname(resolvedPath));
20359
20338
  await this.utils.writeFile(resolvedPath, output.content);
20360
20339
  } catch (error2) {
20361
- const err = error2;
20362
- this.logger.error(`Failed to write ${output.path}: ${err.message}`);
20363
- throw err;
20340
+ this.logger.error(`Failed to write ${output.path}: ${getErrorMessage(error2)}`);
20341
+ throw error2;
20364
20342
  }
20365
20343
  }
20366
20344
  }
20367
20345
  getExecutionResults() {
20368
20346
  return new Map(this.executionContext.results);
20369
20347
  }
20348
+ contractToProcessed(contract, source) {
20349
+ const address = typeof contract.address === "string" ? contract.address : "";
20350
+ const parsed = parseContractId(address);
20351
+ return {
20352
+ name: contract.name || parsed.contractName || "unknown",
20353
+ address: parsed.address || "unknown",
20354
+ contractName: parsed.contractName || contract.name || "unknown",
20355
+ abi: contract.abi,
20356
+ source: source === "api" ? "api" : "local",
20357
+ metadata: contract.metadata ?? { source }
20358
+ };
20359
+ }
20370
20360
  augmentOutput(outputs, outputKey, contractName, content) {
20371
20361
  const existing = outputs.get(outputKey);
20372
20362
  if (!existing) {
@@ -20403,9 +20393,7 @@ ${JSON.stringify(content, null, 2)}`;
20403
20393
  }
20404
20394
  createUtils() {
20405
20395
  return {
20406
- toCamelCase: (str) => {
20407
- return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
20408
- },
20396
+ toCamelCase: toCamelCase2,
20409
20397
  toKebabCase: (str) => {
20410
20398
  return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
20411
20399
  },
@@ -20554,7 +20542,7 @@ var init_config2 = __esm(() => {
20554
20542
 
20555
20543
  // src/utils/type-mapping.ts
20556
20544
  import {
20557
- toCamelCase,
20545
+ toCamelCase as toCamelCase3,
20558
20546
  isAbiList,
20559
20547
  isAbiTuple,
20560
20548
  isAbiOptional as isAbiOptional2,
@@ -20613,7 +20601,7 @@ function clarityTypeToTS(type) {
20613
20601
  return `${innerType}[]`;
20614
20602
  }
20615
20603
  if (isAbiTuple(type)) {
20616
- const fields = type.tuple.map((field) => `${toCamelCase(field.name)}: ${clarityTypeToTS(field.type)}`).join("; ");
20604
+ const fields = type.tuple.map((field) => `${toCamelCase3(field.name)}: ${clarityTypeToTS(field.type)}`).join("; ");
20617
20605
  return `{ ${fields} }`;
20618
20606
  }
20619
20607
  if (isAbiResponse(type)) {
@@ -20630,7 +20618,7 @@ var init_type_mapping = () => {};
20630
20618
 
20631
20619
  // src/utils/clarity-conversion.ts
20632
20620
  import {
20633
- toCamelCase as toCamelCase2,
20621
+ toCamelCase as toCamelCase4,
20634
20622
  isAbiStringAscii as isAbiStringAscii3,
20635
20623
  isAbiStringUtf8 as isAbiStringUtf83,
20636
20624
  isAbiBuffer as isAbiBuffer3,
@@ -20728,7 +20716,7 @@ function generateClarityConversion(argName, argType) {
20728
20716
  const requiredFields = type.tuple.map((f) => f.name);
20729
20717
  const fieldNames = JSON.stringify(requiredFields);
20730
20718
  const fields = type.tuple.map((field) => {
20731
- const camelFieldName = toCamelCase2(field.name);
20719
+ const camelFieldName = toCamelCase4(field.name);
20732
20720
  const fieldConversion = generateClarityConversion(`tupleValue.${camelFieldName}`, { type: field.type });
20733
20721
  return `"${field.name}": ${fieldConversion}`;
20734
20722
  }).join(", ");
@@ -20769,11 +20757,11 @@ function generateClarityConversion(argName, argType) {
20769
20757
  var init_clarity_conversion = () => {};
20770
20758
 
20771
20759
  // src/utils/generator-helpers.ts
20772
- import { toCamelCase as toCamelCase3, isAbiTuple as isAbiTuple3 } from "@secondlayer/stacks/clarity";
20760
+ import { toCamelCase as toCamelCase5, isAbiTuple as isAbiTuple3 } from "@secondlayer/stacks/clarity";
20773
20761
  function generateMapKeyConversion(keyType) {
20774
20762
  if (isAbiTuple3(keyType)) {
20775
20763
  const fields = keyType.tuple.map((field) => {
20776
- const camelFieldName = toCamelCase3(field.name);
20764
+ const camelFieldName = toCamelCase5(field.name);
20777
20765
  const fieldConversion = generateClarityConversion(`key.${camelFieldName}`, { type: field.type });
20778
20766
  return `"${field.name}": ${fieldConversion}`;
20779
20767
  }).join(", ");
@@ -20788,7 +20776,7 @@ var init_generator_helpers = __esm(() => {
20788
20776
 
20789
20777
  // src/generators/contract.ts
20790
20778
  import {
20791
- toCamelCase as toCamelCase4
20779
+ toCamelCase as toCamelCase6
20792
20780
  } from "@secondlayer/stacks/clarity";
20793
20781
  function generateNetworkUtils() {
20794
20782
  return `/**
@@ -20880,7 +20868,7 @@ function generateAbiConstant(name, abi) {
20880
20868
  return `export const ${name}Abi = ${abiJson} as const`;
20881
20869
  }
20882
20870
  function generateMethod(func, address, contractName) {
20883
- const methodName = toCamelCase4(func.name);
20871
+ const methodName = toCamelCase6(func.name);
20884
20872
  if (func.args.length === 0) {
20885
20873
  return `${methodName}() {
20886
20874
  return {
@@ -20893,7 +20881,7 @@ function generateMethod(func, address, contractName) {
20893
20881
  }
20894
20882
  if (func.args.length === 1) {
20895
20883
  const originalArgName = func.args[0].name;
20896
- const argName = toCamelCase4(originalArgName);
20884
+ const argName = toCamelCase6(originalArgName);
20897
20885
  const argType = getTypeForArg(func.args[0]);
20898
20886
  const clarityConversion = generateClarityConversion(argName, func.args[0]);
20899
20887
  return `${methodName}(...args: [{ ${argName}: ${argType} }] | [${argType}]) {
@@ -20909,17 +20897,17 @@ function generateMethod(func, address, contractName) {
20909
20897
  }
20910
20898
  }`;
20911
20899
  }
20912
- const argsList = func.args.map((arg) => toCamelCase4(arg.name)).join(", ");
20900
+ const argsList = func.args.map((arg) => toCamelCase6(arg.name)).join(", ");
20913
20901
  const argsTypes = func.args.map((arg) => {
20914
- const camelName = toCamelCase4(arg.name);
20902
+ const camelName = toCamelCase6(arg.name);
20915
20903
  return `${camelName}: ${getTypeForArg(arg)}`;
20916
20904
  }).join("; ");
20917
20905
  const argsArray = func.args.map((arg) => {
20918
- const argName = toCamelCase4(arg.name);
20906
+ const argName = toCamelCase6(arg.name);
20919
20907
  return generateClarityConversion(argName, arg);
20920
20908
  }).join(", ");
20921
20909
  const objectAccess = func.args.map((arg) => {
20922
- const camelName = toCamelCase4(arg.name);
20910
+ const camelName = toCamelCase6(arg.name);
20923
20911
  return `args[0].${camelName}`;
20924
20912
  }).join(", ");
20925
20913
  const positionTypes = func.args.map((arg) => getTypeForArg(arg)).join(", ");
@@ -20941,7 +20929,7 @@ function generateMapsObject(maps, address, contractName) {
20941
20929
  return "";
20942
20930
  }
20943
20931
  const mapMethods = maps.map((map) => {
20944
- const methodName = toCamelCase4(map.name);
20932
+ const methodName = toCamelCase6(map.name);
20945
20933
  const keyType = getTypeForArg({ type: map.key });
20946
20934
  const valueType = getTypeForArg({ type: map.value });
20947
20935
  const keyConversion = generateMapKeyConversion(map.key);
@@ -21002,7 +20990,7 @@ function generateVarsObject(variables, address, contractName) {
21002
20990
  return "";
21003
20991
  }
21004
20992
  const varMethods = dataVars.map((variable) => {
21005
- const methodName = toCamelCase4(variable.name);
20993
+ const methodName = toCamelCase6(variable.name);
21006
20994
  const valueType = getTypeForArg({ type: variable.type });
21007
20995
  return `${methodName}: {
21008
20996
  async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
@@ -21047,7 +21035,7 @@ function generateConstantsObject(variables, address, contractName) {
21047
21035
  return "";
21048
21036
  }
21049
21037
  const constMethods = constants.map((constant) => {
21050
- const methodName = toCamelCase4(constant.name);
21038
+ const methodName = toCamelCase6(constant.name);
21051
21039
  const valueType = getTypeForArg({ type: constant.type });
21052
21040
  return `${methodName}: {
21053
21041
  async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
@@ -32648,7 +32636,8 @@ __export(exports_generate, {
32648
32636
  generate: () => generate
32649
32637
  });
32650
32638
  import path11 from "path";
32651
- import { toCamelCase as toCamelCase5 } from "@secondlayer/stacks/clarity";
32639
+ import { toCamelCase as toCamelCase7 } from "@secondlayer/stacks/clarity";
32640
+ import { getErrorMessage as getErrorMessage2 } from "@secondlayer/shared";
32652
32641
  function isContractAddress(input4) {
32653
32642
  const contractIdPattern = /^(SP|ST|SM|SN)[A-Z0-9]{38,}\.[a-zA-Z][a-zA-Z0-9-]*$/;
32654
32643
  return contractIdPattern.test(input4);
@@ -32709,7 +32698,7 @@ async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddre
32709
32698
  const apiClient = new StacksApiClient(network, apiKey);
32710
32699
  const contractInfo = await apiClient.getContractInfo(contractId);
32711
32700
  const abi = parseApiResponse(contractInfo);
32712
- const name = toCamelCase5(contractName);
32701
+ const name = toCamelCase7(contractName);
32713
32702
  contracts.push({
32714
32703
  name,
32715
32704
  address: contractId,
@@ -32717,7 +32706,7 @@ async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddre
32717
32706
  _directFile: true
32718
32707
  });
32719
32708
  } catch (error2) {
32720
- throw new Error(`Failed to fetch contract ${contractId}: ${error2.message}`);
32709
+ throw new Error(`Failed to fetch contract ${contractId}: ${getErrorMessage2(error2)}`);
32721
32710
  }
32722
32711
  }
32723
32712
  return {
@@ -32799,8 +32788,8 @@ To get started:`);
32799
32788
  } catch (error2) {
32800
32789
  console.error(source_default3.red("✗ Generation failed"));
32801
32790
  console.error(source_default3.red(`
32802
- ${error2.message}`));
32803
- if (process.env.DEBUG) {
32791
+ ${getErrorMessage2(error2)}`));
32792
+ if (process.env.DEBUG && error2 instanceof Error) {
32804
32793
  console.error(error2.stack);
32805
32794
  }
32806
32795
  process.exit(1);
@@ -32867,7 +32856,7 @@ async function resolveContracts(source, defaultNetwork, apiKey, apiUrl) {
32867
32856
  source: "api"
32868
32857
  });
32869
32858
  } catch (error2) {
32870
- console.warn(`Warning: Failed to resolve contract for ${network}: ${error2.message}`);
32859
+ console.warn(`Warning: Failed to resolve contract for ${network}: ${getErrorMessage2(error2)}`);
32871
32860
  }
32872
32861
  }
32873
32862
  return resolvedContracts;
@@ -32954,7 +32943,7 @@ var {
32954
32943
  // package.json
32955
32944
  var package_default = {
32956
32945
  name: "@secondlayer/cli",
32957
- version: "1.4.1",
32946
+ version: "1.5.1",
32958
32947
  description: "CLI for streams, views, and real-time blockchain indexing on Stacks",
32959
32948
  type: "module",
32960
32949
  bin: {
@@ -32995,10 +32984,10 @@ var package_default = {
32995
32984
  license: "MIT",
32996
32985
  dependencies: {
32997
32986
  "@inquirer/prompts": "^8.2.0",
32998
- "@secondlayer/sdk": "^0.4.1",
32999
- "@secondlayer/shared": "^0.3.0",
33000
- "@secondlayer/stacks": "^0.1.0",
33001
- "@secondlayer/views": "^0.2.4",
32987
+ "@secondlayer/sdk": "^0.5.0",
32988
+ "@secondlayer/shared": "^0.4.0",
32989
+ "@secondlayer/stacks": "^0.2.0",
32990
+ "@secondlayer/views": "^0.3.0",
33002
32991
  "@biomejs/js-api": "^0.7.0",
33003
32992
  "@biomejs/wasm-nodejs": "^1.9.0",
33004
32993
  esbuild: "^0.19.0",
@@ -33387,6 +33376,7 @@ async function validateDatabaseConnection(url) {
33387
33376
  }
33388
33377
  // src/commands/setup.ts
33389
33378
  init_output();
33379
+ init_api_client();
33390
33380
  import { select as select2, input, confirm } from "@inquirer/prompts";
33391
33381
  init_config();
33392
33382
  var STREAMS_DIR = "streams";
@@ -33639,13 +33629,10 @@ async function hostedLogin(config) {
33639
33629
  headers: { "Content-Type": "application/json" },
33640
33630
  body: JSON.stringify({ email })
33641
33631
  });
33642
- if (!mlRes.ok) {
33643
- const body = await mlRes.text();
33644
- let msg = `HTTP ${mlRes.status}`;
33645
- try {
33646
- msg = JSON.parse(body).error || msg;
33647
- } catch {}
33648
- error(`Failed to send magic link: ${msg}`);
33632
+ try {
33633
+ await assertOk(mlRes);
33634
+ } catch (e) {
33635
+ error(`Failed to send magic link: ${e instanceof Error ? e.message : e}`);
33649
33636
  return false;
33650
33637
  }
33651
33638
  info("Check your email for a login token.");
@@ -33658,18 +33645,41 @@ async function hostedLogin(config) {
33658
33645
  headers: { "Content-Type": "application/json" },
33659
33646
  body: JSON.stringify({ token: token.trim() })
33660
33647
  });
33661
- if (!verifyRes.ok) {
33662
- const body = await verifyRes.text();
33663
- let msg = `HTTP ${verifyRes.status}`;
33664
- try {
33665
- msg = JSON.parse(body).error || msg;
33666
- } catch {}
33667
- error(`Verification failed: ${msg}`);
33648
+ try {
33649
+ await assertOk(verifyRes);
33650
+ } catch (e) {
33651
+ error(`Verification failed: ${e instanceof Error ? e.message : e}`);
33668
33652
  return false;
33669
33653
  }
33670
33654
  const result = await verifyRes.json();
33671
- config.sessionToken = result.sessionToken;
33655
+ const { hostname } = await import("node:os");
33656
+ const sessionHeaders = { Authorization: `Bearer ${result.sessionToken}`, "Content-Type": "application/json" };
33657
+ const keyName = `cli-${hostname().toLowerCase()}`;
33658
+ const listRes = await fetch(`${apiUrl}/api/keys`, { headers: sessionHeaders });
33659
+ if (listRes.ok) {
33660
+ const { keys } = await listRes.json();
33661
+ const existing = keys.find((k) => k.name === keyName && k.status === "active");
33662
+ if (existing) {
33663
+ await fetch(`${apiUrl}/api/keys/${existing.id}`, { method: "DELETE", headers: sessionHeaders });
33664
+ }
33665
+ }
33666
+ const createRes = await fetch(`${apiUrl}/api/keys`, {
33667
+ method: "POST",
33668
+ headers: sessionHeaders,
33669
+ body: JSON.stringify({ name: keyName })
33670
+ });
33671
+ try {
33672
+ await assertOk(createRes);
33673
+ } catch (e) {
33674
+ error(`Failed to create API key: ${e instanceof Error ? e.message : e}`);
33675
+ return false;
33676
+ }
33677
+ const { key } = await createRes.json();
33678
+ config.apiKey = key;
33672
33679
  await saveConfig(config);
33680
+ try {
33681
+ await fetch(`${apiUrl}/api/auth/logout`, { method: "POST", headers: sessionHeaders });
33682
+ } catch {}
33673
33683
  const account = result.account;
33674
33684
  console.log();
33675
33685
  success(`Authenticated as ${account.email}!`);
@@ -35610,6 +35620,17 @@ ${handlersBlock}
35610
35620
 
35611
35621
  // src/generators/views.ts
35612
35622
  init_format();
35623
+
35624
+ // src/utils/case-conversion.ts
35625
+ import { toCamelCase } from "@secondlayer/stacks/clarity";
35626
+ function capitalize(str) {
35627
+ return str.charAt(0).toUpperCase() + str.slice(1);
35628
+ }
35629
+ function toPascalCase(str) {
35630
+ return capitalize(toCamelCase(str));
35631
+ }
35632
+
35633
+ // src/generators/views.ts
35613
35634
  async function generateViewConsumer(viewName, detail) {
35614
35635
  const tables = Object.entries(detail.tables);
35615
35636
  const rowInterfaces = tables.map(([tableName, tableDef]) => {
@@ -35662,9 +35683,6 @@ export function createClient(options?: { apiKey?: string; baseUrl?: string }): C
35662
35683
  `.trimStart();
35663
35684
  return formatCode(code);
35664
35685
  }
35665
- function toPascalCase(str) {
35666
- return str.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
35667
- }
35668
35686
  function viewTypeToTS(type) {
35669
35687
  switch (type) {
35670
35688
  case "uint":
@@ -36564,6 +36582,7 @@ async function runLocalDoctor(jsonOutput) {
36564
36582
  init_config();
36565
36583
  init_api_client();
36566
36584
  init_output();
36585
+ import { hostname } from "node:os";
36567
36586
  import { input as input2 } from "@inquirer/prompts";
36568
36587
  function registerAuthCommand(program2) {
36569
36588
  const auth = program2.command("auth").description("Manage authentication and API keys");
@@ -36584,14 +36603,7 @@ function registerAuthCommand(program2) {
36584
36603
  headers: { "Content-Type": "application/json" },
36585
36604
  body: JSON.stringify({ email })
36586
36605
  });
36587
- if (!mlRes.ok) {
36588
- const body = await mlRes.text();
36589
- let msg = `HTTP ${mlRes.status}`;
36590
- try {
36591
- msg = JSON.parse(body).error || msg;
36592
- } catch {}
36593
- throw new Error(msg);
36594
- }
36606
+ await assertOk(mlRes);
36595
36607
  console.log(dim("Check your email for a login token."));
36596
36608
  const token = await input2({
36597
36609
  message: "Token:",
@@ -36602,19 +36614,32 @@ function registerAuthCommand(program2) {
36602
36614
  headers: { "Content-Type": "application/json" },
36603
36615
  body: JSON.stringify({ token: token.trim() })
36604
36616
  });
36605
- if (!verifyRes.ok) {
36606
- const body = await verifyRes.text();
36607
- let msg = `HTTP ${verifyRes.status}`;
36608
- try {
36609
- msg = JSON.parse(body).error || msg;
36610
- } catch {}
36611
- throw new Error(msg);
36612
- }
36617
+ await assertOk(verifyRes);
36613
36618
  const result = await verifyRes.json();
36614
- config.sessionToken = result.sessionToken;
36619
+ const sessionHeaders = { Authorization: `Bearer ${result.sessionToken}`, "Content-Type": "application/json" };
36620
+ const keyName = `cli-${hostname().toLowerCase()}`;
36621
+ const listRes = await fetch(`${apiUrl}/api/keys`, { headers: sessionHeaders });
36622
+ if (listRes.ok) {
36623
+ const { keys: keys2 } = await listRes.json();
36624
+ const existing = keys2.find((k) => k.name === keyName && k.status === "active");
36625
+ if (existing) {
36626
+ await fetch(`${apiUrl}/api/keys/${existing.id}`, { method: "DELETE", headers: sessionHeaders });
36627
+ }
36628
+ }
36629
+ const createRes = await fetch(`${apiUrl}/api/keys`, {
36630
+ method: "POST",
36631
+ headers: sessionHeaders,
36632
+ body: JSON.stringify({ name: keyName })
36633
+ });
36634
+ await assertOk(createRes);
36635
+ const { key, prefix } = await createRes.json();
36636
+ config.apiKey = key;
36615
36637
  await saveConfig(config);
36638
+ try {
36639
+ await fetch(`${apiUrl}/api/auth/logout`, { method: "POST", headers: sessionHeaders });
36640
+ } catch {}
36616
36641
  success(`Authenticated as ${result.account.email}`);
36617
- console.log(dim(`Plan: ${result.account.plan}`));
36642
+ console.log(dim(`Key: ${prefix}...`));
36618
36643
  console.log(dim(`Network: ${config.network}`));
36619
36644
  console.log(dim(`API: ${apiUrl}`));
36620
36645
  } catch (err) {
@@ -36622,37 +36647,41 @@ function registerAuthCommand(program2) {
36622
36647
  process.exit(1);
36623
36648
  }
36624
36649
  });
36625
- auth.command("logout").description("Revoke session and remove from config").action(async () => {
36650
+ auth.command("logout").description("Revoke API key and remove from config").action(async () => {
36626
36651
  const config = await loadConfig();
36627
36652
  const apiUrl = resolveApiUrl(config);
36628
- if (!config.sessionToken) {
36653
+ if (!config.apiKey) {
36629
36654
  error("Not logged in.");
36630
36655
  process.exit(1);
36631
36656
  }
36632
36657
  try {
36633
- await fetch(`${apiUrl}/api/auth/logout`, {
36634
- method: "POST",
36635
- headers: { Authorization: `Bearer ${config.sessionToken}` }
36636
- });
36658
+ const headers = authHeaders(config);
36659
+ const listRes = await fetch(`${apiUrl}/api/keys`, { headers });
36660
+ if (listRes.ok) {
36661
+ const { keys: keys2 } = await listRes.json();
36662
+ const currentPrefix = config.apiKey.slice(0, 14);
36663
+ const match = keys2.find((k) => currentPrefix.startsWith(k.prefix));
36664
+ if (match) {
36665
+ await fetch(`${apiUrl}/api/keys/${match.id}`, { method: "DELETE", headers });
36666
+ }
36667
+ }
36637
36668
  } catch {}
36638
- delete config.sessionToken;
36669
+ delete config.apiKey;
36639
36670
  await saveConfig(config);
36640
- success("Logged out. Session revoked.");
36671
+ success("Logged out. API key revoked.");
36641
36672
  });
36642
36673
  auth.command("status").description("Show current auth status").action(async () => {
36643
36674
  const config = await loadConfig();
36644
36675
  const apiUrl = resolveApiUrl(config);
36645
- const token = config.sessionToken ?? config.apiKey;
36646
36676
  const pairs = [
36647
36677
  ["Network", config.network],
36648
36678
  ["API", apiUrl || "(not configured)"],
36649
- ["Session", config.sessionToken ? config.sessionToken.slice(0, 14) + "..." : "(none)"],
36650
36679
  ["API Key", config.apiKey ? config.apiKey.slice(0, 14) + "..." : "(none)"]
36651
36680
  ];
36652
- if (token && apiUrl) {
36681
+ if (config.apiKey && apiUrl) {
36653
36682
  try {
36654
36683
  const res = await fetch(`${apiUrl}/api/accounts/me`, {
36655
- headers: { Authorization: `Bearer ${token}` }
36684
+ headers: authHeaders(config)
36656
36685
  });
36657
36686
  if (res.ok) {
36658
36687
  const data = await res.json();
@@ -36696,14 +36725,7 @@ function registerAuthCommand(program2) {
36696
36725
  headers,
36697
36726
  body: JSON.stringify({ name: options2.name })
36698
36727
  });
36699
- if (!res.ok) {
36700
- const body = await res.text();
36701
- let msg = `HTTP ${res.status}`;
36702
- try {
36703
- msg = JSON.parse(body).error || msg;
36704
- } catch {}
36705
- throw new Error(msg);
36706
- }
36728
+ await assertOk(res);
36707
36729
  const { key, prefix } = await res.json();
36708
36730
  success(`Created API key: ${prefix}...`);
36709
36731
  console.log();
@@ -36737,24 +36759,18 @@ function registerAuthCommand(program2) {
36737
36759
  method: "DELETE",
36738
36760
  headers
36739
36761
  });
36740
- if (!res.ok) {
36741
- const body = await res.text();
36742
- let msg = `HTTP ${res.status}`;
36743
- try {
36744
- msg = JSON.parse(body).error || msg;
36745
- } catch {}
36746
- throw new Error(msg);
36747
- }
36762
+ await assertOk(res);
36748
36763
  success(`Revoked key ${idOrPrefix}`);
36749
36764
  } catch (err) {
36750
36765
  error(`Failed to revoke key: ${err}`);
36751
36766
  process.exit(1);
36752
36767
  }
36753
36768
  });
36754
- keys.command("rotate").description("Revoke current API key and create a new one").option("--name <name>", "Name for the new API key", "cli").action(async (options2) => {
36769
+ const defaultKeyName = `cli-${hostname().toLowerCase()}`;
36770
+ keys.command("rotate").description("Revoke current API key and create a new one").option("--name <name>", "Name for the new API key", defaultKeyName).action(async (options2) => {
36755
36771
  await rotateKey(options2);
36756
36772
  });
36757
- auth.command("rotate").description("Revoke current API key and create a new one").option("--name <name>", "Name for the new API key", "cli").action(async (options2) => {
36773
+ auth.command("rotate").description("Revoke current API key and create a new one").option("--name <name>", "Name for the new API key", defaultKeyName).action(async (options2) => {
36758
36774
  await rotateKey(options2);
36759
36775
  });
36760
36776
  }
@@ -36762,7 +36778,7 @@ async function rotateKey(options2) {
36762
36778
  const config = await loadConfig();
36763
36779
  const apiUrl = resolveApiUrl(config);
36764
36780
  const headers = authHeaders(config);
36765
- if (!config.sessionToken && !config.apiKey) {
36781
+ if (!config.apiKey) {
36766
36782
  error("Not logged in. Run `sl auth login` first.");
36767
36783
  process.exit(1);
36768
36784
  }
@@ -36787,14 +36803,7 @@ async function rotateKey(options2) {
36787
36803
  headers: { ...headers, "Content-Type": "application/json" },
36788
36804
  body: JSON.stringify({ name: options2.name })
36789
36805
  });
36790
- if (!createRes.ok) {
36791
- const body = await createRes.text();
36792
- let msg = `HTTP ${createRes.status}`;
36793
- try {
36794
- msg = JSON.parse(body).error || msg;
36795
- } catch {}
36796
- throw new Error(msg);
36797
- }
36806
+ await assertOk(createRes);
36798
36807
  const { key, prefix } = await createRes.json();
36799
36808
  config.apiKey = key;
36800
36809
  await saveConfig(config);
@@ -37098,8 +37107,7 @@ function registerWhoamiCommand(program2) {
37098
37107
  program2.command("whoami").description("Show current authenticated account").action(async () => {
37099
37108
  const config = await loadConfig();
37100
37109
  const apiUrl = resolveApiUrl(config);
37101
- const token = config.sessionToken ?? config.apiKey;
37102
- if (!token) {
37110
+ if (!config.apiKey) {
37103
37111
  error("Not authenticated. Run: sl auth login");
37104
37112
  process.exit(1);
37105
37113
  }
@@ -37165,5 +37173,5 @@ registerWhoamiCommand(program);
37165
37173
  registerWebhookCommand(program);
37166
37174
  program.parse();
37167
37175
 
37168
- //# debugId=E0C86F93180D107264756E2164756E21
37176
+ //# debugId=623C283AFFA2A54D64756E2164756E21
37169
37177
  //# sourceMappingURL=cli.js.map