@secondlayer/cli 1.4.0 → 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 +226 -197
- package/dist/cli.js.map +22 -21
- package/dist/index.d.ts +6 -1
- package/dist/index.js +96 -104
- package/dist/index.js.map +13 -12
- package/dist/plugin-manager.d.ts +6 -1
- package/dist/plugin-manager.js +29 -52
- package/dist/plugin-manager.js.map +4 -4
- package/package.json +5 -5
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
|
-
|
|
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.
|
|
4579
|
+
return new SecondLayer({ baseUrl, apiKey: config.apiKey });
|
|
4569
4580
|
}
|
|
4570
4581
|
function authHeaders(config) {
|
|
4571
|
-
return SecondLayer.authHeaders(config.
|
|
4582
|
+
return SecondLayer.authHeaders(config.apiKey);
|
|
4572
4583
|
}
|
|
4573
4584
|
async function createStream(data) {
|
|
4574
4585
|
return (await getClient()).streams.create(data);
|
|
@@ -6363,7 +6374,7 @@ var init_responselike = __esm(() => {
|
|
|
6363
6374
|
|
|
6364
6375
|
// ../../node_modules/json-buffer/index.js
|
|
6365
6376
|
var require_json_buffer = __commonJS((exports) => {
|
|
6366
|
-
exports.stringify = function
|
|
6377
|
+
exports.stringify = function stringify(o) {
|
|
6367
6378
|
if (typeof o == "undefined")
|
|
6368
6379
|
return o;
|
|
6369
6380
|
if (o && Buffer.isBuffer(o))
|
|
@@ -6385,9 +6396,9 @@ var require_json_buffer = __commonJS((exports) => {
|
|
|
6385
6396
|
if (o[k] == undefined)
|
|
6386
6397
|
s += "null";
|
|
6387
6398
|
else
|
|
6388
|
-
s +=
|
|
6399
|
+
s += stringify(o[k]);
|
|
6389
6400
|
} else if (o[k] !== undefined) {
|
|
6390
|
-
s +=
|
|
6401
|
+
s += stringify(k) + ":" + stringify(o[k]);
|
|
6391
6402
|
}
|
|
6392
6403
|
}
|
|
6393
6404
|
}
|
|
@@ -7331,7 +7342,7 @@ var init_FormDataEncoder = __esm(() => {
|
|
|
7331
7342
|
}
|
|
7332
7343
|
}
|
|
7333
7344
|
}
|
|
7334
|
-
[(_FormDataEncoder_CRLF = new WeakMap, _FormDataEncoder_CRLF_BYTES = new WeakMap, _FormDataEncoder_CRLF_BYTES_LENGTH = new WeakMap, _FormDataEncoder_DASHES = new WeakMap, _FormDataEncoder_encoder = new WeakMap, _FormDataEncoder_footer = new WeakMap, _FormDataEncoder_form = new WeakMap, _FormDataEncoder_options = new WeakMap, _FormDataEncoder_instances = new WeakSet, _FormDataEncoder_getFieldHeader = function
|
|
7345
|
+
[(_FormDataEncoder_CRLF = new WeakMap, _FormDataEncoder_CRLF_BYTES = new WeakMap, _FormDataEncoder_CRLF_BYTES_LENGTH = new WeakMap, _FormDataEncoder_DASHES = new WeakMap, _FormDataEncoder_encoder = new WeakMap, _FormDataEncoder_footer = new WeakMap, _FormDataEncoder_form = new WeakMap, _FormDataEncoder_options = new WeakMap, _FormDataEncoder_instances = new WeakSet, _FormDataEncoder_getFieldHeader = function _FormDataEncoder_getFieldHeader(name, value) {
|
|
7335
7346
|
let header = "";
|
|
7336
7347
|
header += `${__classPrivateFieldGet(this, _FormDataEncoder_DASHES, "f")}${this.boundary}${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")}`;
|
|
7337
7348
|
header += `Content-Disposition: form-data; name="${escapeName(name)}"`;
|
|
@@ -7344,7 +7355,7 @@ var init_FormDataEncoder = __esm(() => {
|
|
|
7344
7355
|
header += `${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")}Content-Length: ${isFile(value) ? value.size : value.byteLength}`;
|
|
7345
7356
|
}
|
|
7346
7357
|
return __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(`${header}${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f").repeat(2)}`);
|
|
7347
|
-
}, _FormDataEncoder_getContentLength = function
|
|
7358
|
+
}, _FormDataEncoder_getContentLength = function _FormDataEncoder_getContentLength() {
|
|
7348
7359
|
let length = 0;
|
|
7349
7360
|
for (const [name, raw] of __classPrivateFieldGet(this, _FormDataEncoder_form, "f")) {
|
|
7350
7361
|
const value = isFile(raw) ? raw : __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(normalizeValue(raw));
|
|
@@ -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:
|
|
20217
|
+
error: error2 instanceof Error ? error2 : new Error(getErrorMessage(error2))
|
|
20206
20218
|
});
|
|
20207
|
-
throw new Error(`Plugin "${plugin.name}" failed during config transformation: ${
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
20251
|
+
error: error2 instanceof Error ? error2 : new Error(getErrorMessage(error2))
|
|
20261
20252
|
});
|
|
20262
|
-
this.logger.warn(`Plugin "${plugin.name}" failed to transform contract: ${
|
|
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
|
-
|
|
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:
|
|
20276
|
+
error: error2 instanceof Error ? error2 : new Error(getErrorMessage(error2))
|
|
20297
20277
|
});
|
|
20298
|
-
this.logger.error(`Plugin "${plugin.name}" failed during ${hookName}: ${
|
|
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:
|
|
20320
|
+
error: error2 instanceof Error ? error2 : new Error(getErrorMessage(error2))
|
|
20342
20321
|
});
|
|
20343
|
-
this.logger.warn(`Plugin "${plugin.name}" failed to transform output: ${
|
|
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
|
-
|
|
20362
|
-
|
|
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:
|
|
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) => `${
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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) =>
|
|
20900
|
+
const argsList = func.args.map((arg) => toCamelCase6(arg.name)).join(", ");
|
|
20913
20901
|
const argsTypes = func.args.map((arg) => {
|
|
20914
|
-
const camelName =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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}> {
|
|
@@ -21143,23 +21131,23 @@ var require_ansis = __commonJS((exports, module) => {
|
|
|
21143
21131
|
}, s2 = t2, c2 = l2;
|
|
21144
21132
|
return e2 && (s2 = e2.o + t2, c2 = l2 + e2.c), n(o2, r), o2.p = { open: t2, close: l2, o: s2, c: c2, p: e2 }, o2.open = s2, o2.close = c2, o2;
|
|
21145
21133
|
};
|
|
21146
|
-
var w = new function
|
|
21147
|
-
let s2 = { Ansis:
|
|
21148
|
-
for (let t3 in
|
|
21149
|
-
let r2 =
|
|
21134
|
+
var w = new function e(t2 = f) {
|
|
21135
|
+
let s2 = { Ansis: e, level: t2, isSupported: () => a2, strip: (e2) => e2.replace(/[][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, i), extend(e2) {
|
|
21136
|
+
for (let t3 in e2) {
|
|
21137
|
+
let r2 = e2[t3], l2 = (typeof r2)[0];
|
|
21150
21138
|
l2 === "s" ? (c2(t3, T(...p(r2))), c2(_(t3), v(...p(r2)))) : c2(t3, r2, l2 === "f");
|
|
21151
21139
|
}
|
|
21152
21140
|
return r = o({}, O), n(s2, r), s2;
|
|
21153
|
-
} }, c2 = (
|
|
21154
|
-
O[
|
|
21155
|
-
let n2 = r2 ? (...
|
|
21156
|
-
return l(this,
|
|
21141
|
+
} }, c2 = (e2, t3, r2) => {
|
|
21142
|
+
O[e2] = { get() {
|
|
21143
|
+
let n2 = r2 ? (...e3) => m(this, t3(...e3)) : m(this, t3);
|
|
21144
|
+
return l(this, e2, { value: n2 }), n2;
|
|
21157
21145
|
} };
|
|
21158
|
-
}, a2 = t2 > 0, w2 = (
|
|
21159
|
-
t2 === 2 ? (T = x(C), v = x(E)) : t2 === 1 && (T = $(0, h), v = $(10, b2), C = (
|
|
21160
|
-
let M, I = { fg: C, bg: E, rgb: T, bgRgb: v, hex: y(T), bgHex: y(v), visible: g, reset: w2(0, 0), bold: w2(1, 22), dim: w2(2, 22), italic: w2(3, 23), underline: w2(4, 24), inverse: w2(7, 27), hidden: w2(8, 28), strikethrough: w2(9, 29) }, _ = (
|
|
21161
|
-
return "black,red,green,yellow,blue,magenta,cyan,white,gray".split(",").map((
|
|
21162
|
-
M = _(
|
|
21146
|
+
}, a2 = t2 > 0, w2 = (e2, t3) => a2 ? { open: `\x1B[${e2}m`, close: `\x1B[${t3}m` } : g, y = (e2) => (t3) => e2(...p(t3)), R = (e2, t3) => (r2, l2, n2) => w2(`${e2}8;2;${r2};${l2};${n2}`, t3), $ = (e2, t3) => (r2, l2, n2) => w2(((e3, t4, r3) => d(u(e3, t4, r3)))(r2, l2, n2) + e2, t3), x = (e2) => (t3, r2, l2) => e2(u(t3, r2, l2)), T = R(3, h), v = R(4, b2), C = (e2) => w2("38;5;" + e2, h), E = (e2) => w2("48;5;" + e2, b2);
|
|
21147
|
+
t2 === 2 ? (T = x(C), v = x(E)) : t2 === 1 && (T = $(0, h), v = $(10, b2), C = (e2) => w2(d(e2), h), E = (e2) => w2(d(e2) + 10, b2));
|
|
21148
|
+
let M, I = { fg: C, bg: E, rgb: T, bgRgb: v, hex: y(T), bgHex: y(v), visible: g, reset: w2(0, 0), bold: w2(1, 22), dim: w2(2, 22), italic: w2(3, 23), underline: w2(4, 24), inverse: w2(7, 27), hidden: w2(8, 28), strikethrough: w2(9, 29) }, _ = (e2) => "bg" + e2[0].toUpperCase() + e2.slice(1), k = "Bright";
|
|
21149
|
+
return "black,red,green,yellow,blue,magenta,cyan,white,gray".split(",").map((e2, t3) => {
|
|
21150
|
+
M = _(e2), 8 > t3 ? (I[e2 + k] = w2(90 + t3, h), I[M + k] = w2(100 + t3, b2)) : t3 = 60, I[e2] = w2(30 + t3, h), I[M] = w2(40 + t3, b2);
|
|
21163
21151
|
}), s2.extend(I);
|
|
21164
21152
|
};
|
|
21165
21153
|
module.exports = w, w.default = w;
|
|
@@ -32648,7 +32636,8 @@ __export(exports_generate, {
|
|
|
32648
32636
|
generate: () => generate
|
|
32649
32637
|
});
|
|
32650
32638
|
import path11 from "path";
|
|
32651
|
-
import { toCamelCase as
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
32999
|
-
"@secondlayer/shared": "^0.
|
|
33000
|
-
"@secondlayer/stacks": "^0.0
|
|
33001
|
-
"@secondlayer/views": "^0.
|
|
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
|
-
|
|
33643
|
-
|
|
33644
|
-
|
|
33645
|
-
|
|
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
|
-
|
|
33662
|
-
|
|
33663
|
-
|
|
33664
|
-
|
|
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
|
-
|
|
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}!`);
|
|
@@ -34573,12 +34583,13 @@ init_config();
|
|
|
34573
34583
|
init_output();
|
|
34574
34584
|
import { StacksNodeClient } from "@secondlayer/shared/node";
|
|
34575
34585
|
import { HiroClient } from "@secondlayer/shared/node/hiro-client";
|
|
34586
|
+
import { LocalClient } from "@secondlayer/shared/node/local-client";
|
|
34576
34587
|
import { findGaps, countMissingBlocks } from "@secondlayer/shared/db/queries/integrity";
|
|
34577
34588
|
import { getDb } from "@secondlayer/shared/db";
|
|
34578
34589
|
import { confirm as confirm4 } from "@inquirer/prompts";
|
|
34579
34590
|
var DEV_DATABASE_URL = "postgres://postgres:postgres@localhost:5432/streams_dev";
|
|
34580
34591
|
function registerSyncCommand(program2) {
|
|
34581
|
-
program2.command("sync").description("Fetch missing blocks and index them").option("--from <block>", "Start block height").option("--to <block>", "End block height").option("--gaps", "Auto-detect and fill all gaps").option("--concurrency <n>", "Parallel fetch limit (default: 1 for hiro, 5 for node)").option("--delay <ms>", "Delay between batches in ms (default: 500 for hiro, 0 for node)").option("--source <source>", "Data source: auto, hiro, node", "auto").option("-y, --yes", "Skip confirmation prompt").action(async function() {
|
|
34592
|
+
program2.command("sync").description("Fetch missing blocks and index them").option("--from <block>", "Start block height").option("--to <block>", "End block height").option("--gaps", "Auto-detect and fill all gaps").option("--concurrency <n>", "Parallel fetch limit (default: 1 for hiro, 5 for node)").option("--delay <ms>", "Delay between batches in ms (default: 500 for hiro, 0 for node)").option("--source <source>", "Data source: auto, local, hiro, node", "auto").option("-y, --yes", "Skip confirmation prompt").action(async function() {
|
|
34582
34593
|
const opts = this.opts();
|
|
34583
34594
|
const config = await loadConfig();
|
|
34584
34595
|
const indexerUrl = process.env.INDEXER_URL || `http://localhost:${config.ports.indexer}`;
|
|
@@ -34586,28 +34597,45 @@ function registerSyncCommand(program2) {
|
|
|
34586
34597
|
try {
|
|
34587
34598
|
const nodeClient = new StacksNodeClient;
|
|
34588
34599
|
const hiroClient = new HiroClient;
|
|
34600
|
+
const localClient = new LocalClient;
|
|
34589
34601
|
let useHiro = opts.source === "hiro";
|
|
34590
34602
|
let useNode = opts.source === "node";
|
|
34603
|
+
let useLocal = opts.source === "local";
|
|
34591
34604
|
if (opts.source === "auto" || !opts.source) {
|
|
34592
|
-
|
|
34593
|
-
|
|
34594
|
-
|
|
34595
|
-
|
|
34596
|
-
|
|
34597
|
-
|
|
34605
|
+
if (!process.env.DATABASE_URL) {
|
|
34606
|
+
process.env.DATABASE_URL = DEV_DATABASE_URL;
|
|
34607
|
+
}
|
|
34608
|
+
const db = getDb();
|
|
34609
|
+
const localTip = await localClient.getChainTip(db);
|
|
34610
|
+
if (localTip > 0) {
|
|
34611
|
+
useLocal = true;
|
|
34612
|
+
info(`Using local DB for backfill (tip: block ${localTip})`);
|
|
34613
|
+
} else {
|
|
34614
|
+
const nodeHealthy = await nodeClient.isHealthy();
|
|
34615
|
+
if (nodeHealthy) {
|
|
34616
|
+
const testBlock = await nodeClient.getBlock(1).catch(() => null);
|
|
34617
|
+
if (testBlock) {
|
|
34618
|
+
useNode = true;
|
|
34619
|
+
info("Using local Stacks node for backfill");
|
|
34620
|
+
} else {
|
|
34621
|
+
useHiro = true;
|
|
34622
|
+
info("Node can't serve block data, using Hiro public API");
|
|
34623
|
+
}
|
|
34598
34624
|
} else {
|
|
34599
34625
|
useHiro = true;
|
|
34600
|
-
info("Node
|
|
34626
|
+
info("Node not reachable, using Hiro public API");
|
|
34601
34627
|
}
|
|
34602
|
-
} else {
|
|
34603
|
-
useHiro = true;
|
|
34604
|
-
info("Node not reachable, using Hiro public API");
|
|
34605
34628
|
}
|
|
34606
34629
|
}
|
|
34607
34630
|
if (concurrency === 0) {
|
|
34608
|
-
concurrency = useHiro ? 1 : 5;
|
|
34631
|
+
concurrency = useLocal ? 10 : useHiro ? 1 : 5;
|
|
34609
34632
|
}
|
|
34610
|
-
if (
|
|
34633
|
+
if (useLocal) {
|
|
34634
|
+
if (!process.env.DATABASE_URL) {
|
|
34635
|
+
process.env.DATABASE_URL = DEV_DATABASE_URL;
|
|
34636
|
+
}
|
|
34637
|
+
info("Source: local DB");
|
|
34638
|
+
} else if (useHiro) {
|
|
34611
34639
|
const hiroHealthy = await hiroClient.isHealthy();
|
|
34612
34640
|
if (!hiroHealthy) {
|
|
34613
34641
|
error(`Cannot reach Hiro API at ${hiroClient.getApiUrl()}`);
|
|
@@ -34662,7 +34690,7 @@ Examples:`));
|
|
|
34662
34690
|
const totalBlocks = ranges.reduce((sum, r) => sum + (r.end - r.start + 1), 0);
|
|
34663
34691
|
if (!opts.yes) {
|
|
34664
34692
|
console.log("");
|
|
34665
|
-
const sourceLabel = useHiro ? "Hiro API" : "local node";
|
|
34693
|
+
const sourceLabel = useLocal ? "local DB" : useHiro ? "Hiro API" : "local node";
|
|
34666
34694
|
console.log(`This will fetch ${yellow(totalBlocks.toString())} blocks from ${sourceLabel}.`);
|
|
34667
34695
|
if (useHiro) {
|
|
34668
34696
|
console.log(dim("Note: Hiro API fetches are slower due to per-tx event lookups."));
|
|
@@ -34693,7 +34721,10 @@ Examples:`));
|
|
|
34693
34721
|
const batch = heights.slice(i, i + concurrency);
|
|
34694
34722
|
const results = await Promise.allSettled(batch.map(async (height) => {
|
|
34695
34723
|
let block;
|
|
34696
|
-
if (
|
|
34724
|
+
if (useLocal) {
|
|
34725
|
+
const db = getDb();
|
|
34726
|
+
block = await localClient.getBlockForReplay(db, height);
|
|
34727
|
+
} else if (useHiro) {
|
|
34697
34728
|
block = await hiroClient.getBlockForIndexer(height);
|
|
34698
34729
|
} else {
|
|
34699
34730
|
block = await nodeClient.getBlock(height);
|
|
@@ -35589,6 +35620,17 @@ ${handlersBlock}
|
|
|
35589
35620
|
|
|
35590
35621
|
// src/generators/views.ts
|
|
35591
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
|
|
35592
35634
|
async function generateViewConsumer(viewName, detail) {
|
|
35593
35635
|
const tables = Object.entries(detail.tables);
|
|
35594
35636
|
const rowInterfaces = tables.map(([tableName, tableDef]) => {
|
|
@@ -35641,9 +35683,6 @@ export function createClient(options?: { apiKey?: string; baseUrl?: string }): C
|
|
|
35641
35683
|
`.trimStart();
|
|
35642
35684
|
return formatCode(code);
|
|
35643
35685
|
}
|
|
35644
|
-
function toPascalCase(str) {
|
|
35645
|
-
return str.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
|
|
35646
|
-
}
|
|
35647
35686
|
function viewTypeToTS(type) {
|
|
35648
35687
|
switch (type) {
|
|
35649
35688
|
case "uint":
|
|
@@ -36543,6 +36582,7 @@ async function runLocalDoctor(jsonOutput) {
|
|
|
36543
36582
|
init_config();
|
|
36544
36583
|
init_api_client();
|
|
36545
36584
|
init_output();
|
|
36585
|
+
import { hostname } from "node:os";
|
|
36546
36586
|
import { input as input2 } from "@inquirer/prompts";
|
|
36547
36587
|
function registerAuthCommand(program2) {
|
|
36548
36588
|
const auth = program2.command("auth").description("Manage authentication and API keys");
|
|
@@ -36563,14 +36603,7 @@ function registerAuthCommand(program2) {
|
|
|
36563
36603
|
headers: { "Content-Type": "application/json" },
|
|
36564
36604
|
body: JSON.stringify({ email })
|
|
36565
36605
|
});
|
|
36566
|
-
|
|
36567
|
-
const body = await mlRes.text();
|
|
36568
|
-
let msg = `HTTP ${mlRes.status}`;
|
|
36569
|
-
try {
|
|
36570
|
-
msg = JSON.parse(body).error || msg;
|
|
36571
|
-
} catch {}
|
|
36572
|
-
throw new Error(msg);
|
|
36573
|
-
}
|
|
36606
|
+
await assertOk(mlRes);
|
|
36574
36607
|
console.log(dim("Check your email for a login token."));
|
|
36575
36608
|
const token = await input2({
|
|
36576
36609
|
message: "Token:",
|
|
@@ -36581,19 +36614,32 @@ function registerAuthCommand(program2) {
|
|
|
36581
36614
|
headers: { "Content-Type": "application/json" },
|
|
36582
36615
|
body: JSON.stringify({ token: token.trim() })
|
|
36583
36616
|
});
|
|
36584
|
-
|
|
36585
|
-
const body = await verifyRes.text();
|
|
36586
|
-
let msg = `HTTP ${verifyRes.status}`;
|
|
36587
|
-
try {
|
|
36588
|
-
msg = JSON.parse(body).error || msg;
|
|
36589
|
-
} catch {}
|
|
36590
|
-
throw new Error(msg);
|
|
36591
|
-
}
|
|
36617
|
+
await assertOk(verifyRes);
|
|
36592
36618
|
const result = await verifyRes.json();
|
|
36593
|
-
|
|
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;
|
|
36594
36637
|
await saveConfig(config);
|
|
36638
|
+
try {
|
|
36639
|
+
await fetch(`${apiUrl}/api/auth/logout`, { method: "POST", headers: sessionHeaders });
|
|
36640
|
+
} catch {}
|
|
36595
36641
|
success(`Authenticated as ${result.account.email}`);
|
|
36596
|
-
console.log(dim(`
|
|
36642
|
+
console.log(dim(`Key: ${prefix}...`));
|
|
36597
36643
|
console.log(dim(`Network: ${config.network}`));
|
|
36598
36644
|
console.log(dim(`API: ${apiUrl}`));
|
|
36599
36645
|
} catch (err) {
|
|
@@ -36601,37 +36647,41 @@ function registerAuthCommand(program2) {
|
|
|
36601
36647
|
process.exit(1);
|
|
36602
36648
|
}
|
|
36603
36649
|
});
|
|
36604
|
-
auth.command("logout").description("Revoke
|
|
36650
|
+
auth.command("logout").description("Revoke API key and remove from config").action(async () => {
|
|
36605
36651
|
const config = await loadConfig();
|
|
36606
36652
|
const apiUrl = resolveApiUrl(config);
|
|
36607
|
-
if (!config.
|
|
36653
|
+
if (!config.apiKey) {
|
|
36608
36654
|
error("Not logged in.");
|
|
36609
36655
|
process.exit(1);
|
|
36610
36656
|
}
|
|
36611
36657
|
try {
|
|
36612
|
-
|
|
36613
|
-
|
|
36614
|
-
|
|
36615
|
-
|
|
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
|
+
}
|
|
36616
36668
|
} catch {}
|
|
36617
|
-
delete config.
|
|
36669
|
+
delete config.apiKey;
|
|
36618
36670
|
await saveConfig(config);
|
|
36619
|
-
success("Logged out.
|
|
36671
|
+
success("Logged out. API key revoked.");
|
|
36620
36672
|
});
|
|
36621
36673
|
auth.command("status").description("Show current auth status").action(async () => {
|
|
36622
36674
|
const config = await loadConfig();
|
|
36623
36675
|
const apiUrl = resolveApiUrl(config);
|
|
36624
|
-
const token = config.sessionToken ?? config.apiKey;
|
|
36625
36676
|
const pairs = [
|
|
36626
36677
|
["Network", config.network],
|
|
36627
36678
|
["API", apiUrl || "(not configured)"],
|
|
36628
|
-
["Session", config.sessionToken ? config.sessionToken.slice(0, 14) + "..." : "(none)"],
|
|
36629
36679
|
["API Key", config.apiKey ? config.apiKey.slice(0, 14) + "..." : "(none)"]
|
|
36630
36680
|
];
|
|
36631
|
-
if (
|
|
36681
|
+
if (config.apiKey && apiUrl) {
|
|
36632
36682
|
try {
|
|
36633
36683
|
const res = await fetch(`${apiUrl}/api/accounts/me`, {
|
|
36634
|
-
headers:
|
|
36684
|
+
headers: authHeaders(config)
|
|
36635
36685
|
});
|
|
36636
36686
|
if (res.ok) {
|
|
36637
36687
|
const data = await res.json();
|
|
@@ -36675,14 +36725,7 @@ function registerAuthCommand(program2) {
|
|
|
36675
36725
|
headers,
|
|
36676
36726
|
body: JSON.stringify({ name: options2.name })
|
|
36677
36727
|
});
|
|
36678
|
-
|
|
36679
|
-
const body = await res.text();
|
|
36680
|
-
let msg = `HTTP ${res.status}`;
|
|
36681
|
-
try {
|
|
36682
|
-
msg = JSON.parse(body).error || msg;
|
|
36683
|
-
} catch {}
|
|
36684
|
-
throw new Error(msg);
|
|
36685
|
-
}
|
|
36728
|
+
await assertOk(res);
|
|
36686
36729
|
const { key, prefix } = await res.json();
|
|
36687
36730
|
success(`Created API key: ${prefix}...`);
|
|
36688
36731
|
console.log();
|
|
@@ -36716,24 +36759,18 @@ function registerAuthCommand(program2) {
|
|
|
36716
36759
|
method: "DELETE",
|
|
36717
36760
|
headers
|
|
36718
36761
|
});
|
|
36719
|
-
|
|
36720
|
-
const body = await res.text();
|
|
36721
|
-
let msg = `HTTP ${res.status}`;
|
|
36722
|
-
try {
|
|
36723
|
-
msg = JSON.parse(body).error || msg;
|
|
36724
|
-
} catch {}
|
|
36725
|
-
throw new Error(msg);
|
|
36726
|
-
}
|
|
36762
|
+
await assertOk(res);
|
|
36727
36763
|
success(`Revoked key ${idOrPrefix}`);
|
|
36728
36764
|
} catch (err) {
|
|
36729
36765
|
error(`Failed to revoke key: ${err}`);
|
|
36730
36766
|
process.exit(1);
|
|
36731
36767
|
}
|
|
36732
36768
|
});
|
|
36733
|
-
|
|
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) => {
|
|
36734
36771
|
await rotateKey(options2);
|
|
36735
36772
|
});
|
|
36736
|
-
auth.command("rotate").description("Revoke current API key and create a new one").option("--name <name>", "Name for the new API key",
|
|
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) => {
|
|
36737
36774
|
await rotateKey(options2);
|
|
36738
36775
|
});
|
|
36739
36776
|
}
|
|
@@ -36741,7 +36778,7 @@ async function rotateKey(options2) {
|
|
|
36741
36778
|
const config = await loadConfig();
|
|
36742
36779
|
const apiUrl = resolveApiUrl(config);
|
|
36743
36780
|
const headers = authHeaders(config);
|
|
36744
|
-
if (!config.
|
|
36781
|
+
if (!config.apiKey) {
|
|
36745
36782
|
error("Not logged in. Run `sl auth login` first.");
|
|
36746
36783
|
process.exit(1);
|
|
36747
36784
|
}
|
|
@@ -36766,14 +36803,7 @@ async function rotateKey(options2) {
|
|
|
36766
36803
|
headers: { ...headers, "Content-Type": "application/json" },
|
|
36767
36804
|
body: JSON.stringify({ name: options2.name })
|
|
36768
36805
|
});
|
|
36769
|
-
|
|
36770
|
-
const body = await createRes.text();
|
|
36771
|
-
let msg = `HTTP ${createRes.status}`;
|
|
36772
|
-
try {
|
|
36773
|
-
msg = JSON.parse(body).error || msg;
|
|
36774
|
-
} catch {}
|
|
36775
|
-
throw new Error(msg);
|
|
36776
|
-
}
|
|
36806
|
+
await assertOk(createRes);
|
|
36777
36807
|
const { key, prefix } = await createRes.json();
|
|
36778
36808
|
config.apiKey = key;
|
|
36779
36809
|
await saveConfig(config);
|
|
@@ -37077,8 +37107,7 @@ function registerWhoamiCommand(program2) {
|
|
|
37077
37107
|
program2.command("whoami").description("Show current authenticated account").action(async () => {
|
|
37078
37108
|
const config = await loadConfig();
|
|
37079
37109
|
const apiUrl = resolveApiUrl(config);
|
|
37080
|
-
|
|
37081
|
-
if (!token) {
|
|
37110
|
+
if (!config.apiKey) {
|
|
37082
37111
|
error("Not authenticated. Run: sl auth login");
|
|
37083
37112
|
process.exit(1);
|
|
37084
37113
|
}
|
|
@@ -37144,5 +37173,5 @@ registerWhoamiCommand(program);
|
|
|
37144
37173
|
registerWebhookCommand(program);
|
|
37145
37174
|
program.parse();
|
|
37146
37175
|
|
|
37147
|
-
//# debugId=
|
|
37176
|
+
//# debugId=623C283AFFA2A54D64756E2164756E21
|
|
37148
37177
|
//# sourceMappingURL=cli.js.map
|