@secondlayer/cli 1.12.2 → 2.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/dist/cli.js +388 -2221
- package/dist/cli.js.map +22 -36
- package/package.json +7 -6
package/dist/cli.js
CHANGED
|
@@ -2229,9 +2229,6 @@ function migrateConfig(raw) {
|
|
|
2229
2229
|
if (typeof old.dataDir === "string") {
|
|
2230
2230
|
migrated.dataDir = old.dataDir;
|
|
2231
2231
|
}
|
|
2232
|
-
if (typeof old.defaultEndpointUrl === "string") {
|
|
2233
|
-
migrated.defaultEndpointUrl = old.defaultEndpointUrl;
|
|
2234
|
-
}
|
|
2235
2232
|
if (typeof old.nodeInstallPath === "string" || typeof old.nodeNetwork === "string") {
|
|
2236
2233
|
migrated.node = {
|
|
2237
2234
|
installPath: old.nodeInstallPath || "",
|
|
@@ -2273,9 +2270,6 @@ async function loadConfig() {
|
|
|
2273
2270
|
}
|
|
2274
2271
|
}
|
|
2275
2272
|
config = applyEnvOverrides(config);
|
|
2276
|
-
if (!config.defaultEndpointUrl && config.network === "local") {
|
|
2277
|
-
config.defaultEndpointUrl = LOCAL_ENDPOINT_URL;
|
|
2278
|
-
}
|
|
2279
2273
|
return config;
|
|
2280
2274
|
}
|
|
2281
2275
|
function applyEnvOverrides(config) {
|
|
@@ -2304,12 +2298,6 @@ function applyEnvOverrides(config) {
|
|
|
2304
2298
|
result.ports = { ...result.ports, indexer: port };
|
|
2305
2299
|
}
|
|
2306
2300
|
}
|
|
2307
|
-
if (process.env.SL_RECEIVER_PORT) {
|
|
2308
|
-
const port = Number.parseInt(process.env.SL_RECEIVER_PORT, 10);
|
|
2309
|
-
if (!isNaN(port) && port > 0 && port <= 65535) {
|
|
2310
|
-
result.ports = { ...result.ports, receiver: port };
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
2301
|
if (process.env.STACKS_NODE_RPC_URL) {
|
|
2314
2302
|
result.nodeRpcUrl = process.env.STACKS_NODE_RPC_URL;
|
|
2315
2303
|
}
|
|
@@ -2388,7 +2376,6 @@ async function requireLocalNetwork() {
|
|
|
2388
2376
|
console.error(`Error: 'sl local' commands require local mode.`);
|
|
2389
2377
|
console.error(` Current context: ${config.network} (hosted)`);
|
|
2390
2378
|
console.error("");
|
|
2391
|
-
console.error(` To view stream logs, use: sl logs <stream>`);
|
|
2392
2379
|
console.error(` To check system status, use: sl status`);
|
|
2393
2380
|
console.error("");
|
|
2394
2381
|
console.error(` To switch to local mode: sl config set network local`);
|
|
@@ -2401,13 +2388,12 @@ function isDefaultValue(config, key) {
|
|
|
2401
2388
|
const defaultValue = getConfigValue(DEFAULT_CONFIG, key);
|
|
2402
2389
|
return JSON.stringify(currentValue) === JSON.stringify(defaultValue);
|
|
2403
2390
|
}
|
|
2404
|
-
var PortsSchema, NodeSchema, DatabaseSchema, NetworkSchema, API_URLS, ConfigSchema, CONFIG_DIR, CONFIG_PATH,
|
|
2391
|
+
var PortsSchema, NodeSchema, DatabaseSchema, NetworkSchema, API_URLS, ConfigSchema, CONFIG_DIR, CONFIG_PATH, DEFAULT_CONFIG;
|
|
2405
2392
|
var init_config = __esm(() => {
|
|
2406
2393
|
init_fs();
|
|
2407
2394
|
PortsSchema = z.object({
|
|
2408
2395
|
api: z.number().int().min(1).max(65535).default(3800),
|
|
2409
|
-
indexer: z.number().int().min(1).max(65535).default(3700)
|
|
2410
|
-
receiver: z.number().int().min(1).max(65535).default(3900)
|
|
2396
|
+
indexer: z.number().int().min(1).max(65535).default(3700)
|
|
2411
2397
|
});
|
|
2412
2398
|
NodeSchema = z.object({
|
|
2413
2399
|
installPath: z.string().min(1),
|
|
@@ -2429,9 +2415,8 @@ var init_config = __esm(() => {
|
|
|
2429
2415
|
apiKey: z.string().optional(),
|
|
2430
2416
|
nodeRpcUrl: z.string().url().optional(),
|
|
2431
2417
|
dataDir: z.string().default("~/.secondlayer/data"),
|
|
2432
|
-
defaultEndpointUrl: z.string().url().optional(),
|
|
2433
2418
|
node: NodeSchema.optional(),
|
|
2434
|
-
ports: PortsSchema.default({ api: 3800, indexer: 3700
|
|
2419
|
+
ports: PortsSchema.default({ api: 3800, indexer: 3700 }),
|
|
2435
2420
|
database: DatabaseSchema.default({ type: "docker" })
|
|
2436
2421
|
});
|
|
2437
2422
|
CONFIG_DIR = join(homedir(), ".secondlayer");
|
|
@@ -2439,49 +2424,12 @@ var init_config = __esm(() => {
|
|
|
2439
2424
|
DEFAULT_CONFIG = {
|
|
2440
2425
|
network: "mainnet",
|
|
2441
2426
|
dataDir: "~/.secondlayer/data",
|
|
2442
|
-
ports: { api: 3800, indexer: 3700
|
|
2427
|
+
ports: { api: 3800, indexer: 3700 },
|
|
2443
2428
|
database: { type: "docker" }
|
|
2444
2429
|
};
|
|
2445
2430
|
});
|
|
2446
2431
|
|
|
2447
2432
|
// src/lib/api-client.ts
|
|
2448
|
-
var exports_api_client = {};
|
|
2449
|
-
__export(exports_api_client, {
|
|
2450
|
-
updateStreamByName: () => updateStreamByName,
|
|
2451
|
-
updateStream: () => updateStream,
|
|
2452
|
-
updateAccountProfile: () => updateAccountProfile,
|
|
2453
|
-
unpublishSubgraphApi: () => unpublishSubgraphApi,
|
|
2454
|
-
stopSubgraphApi: () => stopSubgraphApi,
|
|
2455
|
-
rotateSecret: () => rotateSecret,
|
|
2456
|
-
resumeAllStreams: () => resumeAllStreams,
|
|
2457
|
-
resolveStreamId: () => resolveStreamId,
|
|
2458
|
-
reindexSubgraphApi: () => reindexSubgraphApi,
|
|
2459
|
-
querySubgraphTableCount: () => querySubgraphTableCount,
|
|
2460
|
-
querySubgraphTable: () => querySubgraphTable,
|
|
2461
|
-
publishSubgraphApi: () => publishSubgraphApi,
|
|
2462
|
-
pauseAllStreams: () => pauseAllStreams,
|
|
2463
|
-
listSubgraphsApi: () => listSubgraphsApi,
|
|
2464
|
-
listStreams: () => listStreams,
|
|
2465
|
-
handleApiError: () => handleApiError,
|
|
2466
|
-
getSubgraphGaps: () => getSubgraphGaps,
|
|
2467
|
-
getSubgraphApi: () => getSubgraphApi,
|
|
2468
|
-
getStream: () => getStream,
|
|
2469
|
-
getQueueStats: () => getQueueStats,
|
|
2470
|
-
getMarketplaceSubgraph: () => getMarketplaceSubgraph,
|
|
2471
|
-
getAccountProfile: () => getAccountProfile,
|
|
2472
|
-
forkMarketplaceSubgraph: () => forkMarketplaceSubgraph,
|
|
2473
|
-
enableStream: () => enableStream,
|
|
2474
|
-
disableStream: () => disableStream,
|
|
2475
|
-
deploySubgraphApi: () => deploySubgraphApi,
|
|
2476
|
-
deleteSubgraphApi: () => deleteSubgraphApi,
|
|
2477
|
-
deleteStream: () => deleteStream,
|
|
2478
|
-
createStream: () => createStream,
|
|
2479
|
-
browseMarketplace: () => browseMarketplace,
|
|
2480
|
-
backfillSubgraphApi: () => backfillSubgraphApi,
|
|
2481
|
-
authHeaders: () => authHeaders,
|
|
2482
|
-
assertOk: () => assertOk,
|
|
2483
|
-
ApiError: () => ApiError
|
|
2484
|
-
});
|
|
2485
2433
|
import { SecondLayer } from "@secondlayer/sdk";
|
|
2486
2434
|
import { ApiError } from "@secondlayer/sdk";
|
|
2487
2435
|
async function assertOk(res) {
|
|
@@ -2506,6 +2454,19 @@ function handleApiError(err, action) {
|
|
|
2506
2454
|
console.error(`Error: Failed to ${action}: ${err}`);
|
|
2507
2455
|
process.exit(1);
|
|
2508
2456
|
}
|
|
2457
|
+
function withErrorHandling(fn, options) {
|
|
2458
|
+
return async (...args) => {
|
|
2459
|
+
try {
|
|
2460
|
+
await fn(...args);
|
|
2461
|
+
} catch (err) {
|
|
2462
|
+
if (options?.onError) {
|
|
2463
|
+
options.onError(err);
|
|
2464
|
+
} else {
|
|
2465
|
+
handleApiError(err, options?.action ?? "execute command");
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
};
|
|
2469
|
+
}
|
|
2509
2470
|
async function getClient() {
|
|
2510
2471
|
const config = await loadConfig();
|
|
2511
2472
|
const baseUrl = resolveApiUrl(config);
|
|
@@ -2514,45 +2475,6 @@ async function getClient() {
|
|
|
2514
2475
|
function authHeaders(config) {
|
|
2515
2476
|
return SecondLayer.authHeaders(config.apiKey);
|
|
2516
2477
|
}
|
|
2517
|
-
async function createStream(data) {
|
|
2518
|
-
return (await getClient()).streams.create(data);
|
|
2519
|
-
}
|
|
2520
|
-
async function updateStream(id, data) {
|
|
2521
|
-
return (await getClient()).streams.update(id, data);
|
|
2522
|
-
}
|
|
2523
|
-
async function updateStreamByName(name, data) {
|
|
2524
|
-
return (await getClient()).streams.updateByName(name, data);
|
|
2525
|
-
}
|
|
2526
|
-
async function listStreams(params) {
|
|
2527
|
-
return (await getClient()).streams.list(params);
|
|
2528
|
-
}
|
|
2529
|
-
async function resolveStreamId(partialId) {
|
|
2530
|
-
return (await getClient()).streams.resolveStreamId(partialId);
|
|
2531
|
-
}
|
|
2532
|
-
async function getStream(id) {
|
|
2533
|
-
return (await getClient()).streams.get(id);
|
|
2534
|
-
}
|
|
2535
|
-
async function deleteStream(id) {
|
|
2536
|
-
return (await getClient()).streams.delete(id);
|
|
2537
|
-
}
|
|
2538
|
-
async function enableStream(id) {
|
|
2539
|
-
return (await getClient()).streams.enable(id);
|
|
2540
|
-
}
|
|
2541
|
-
async function disableStream(id) {
|
|
2542
|
-
return (await getClient()).streams.disable(id);
|
|
2543
|
-
}
|
|
2544
|
-
async function rotateSecret(id) {
|
|
2545
|
-
return (await getClient()).streams.rotateSecret(id);
|
|
2546
|
-
}
|
|
2547
|
-
async function pauseAllStreams() {
|
|
2548
|
-
return (await getClient()).streams.pauseAll();
|
|
2549
|
-
}
|
|
2550
|
-
async function resumeAllStreams() {
|
|
2551
|
-
return (await getClient()).streams.resumeAll();
|
|
2552
|
-
}
|
|
2553
|
-
async function getQueueStats() {
|
|
2554
|
-
return (await getClient()).getQueueStats();
|
|
2555
|
-
}
|
|
2556
2478
|
async function listSubgraphsApi() {
|
|
2557
2479
|
return (await getClient()).subgraphs.list();
|
|
2558
2480
|
}
|
|
@@ -4755,15 +4677,15 @@ __export(exports_dev_state, {
|
|
|
4755
4677
|
clearDevState: () => clearDevState
|
|
4756
4678
|
});
|
|
4757
4679
|
import { homedir as homedir3 } from "node:os";
|
|
4758
|
-
import { join as
|
|
4680
|
+
import { join as join3 } from "node:path";
|
|
4759
4681
|
function getLogsDir() {
|
|
4760
4682
|
return LOGS_DIR;
|
|
4761
4683
|
}
|
|
4762
4684
|
function getLogFile(service) {
|
|
4763
|
-
return
|
|
4685
|
+
return join3(LOGS_DIR, `${service}.log`);
|
|
4764
4686
|
}
|
|
4765
4687
|
async function ensureDirs() {
|
|
4766
|
-
await Bun.$`mkdir -p ${
|
|
4688
|
+
await Bun.$`mkdir -p ${STATE_DIR}`.quiet();
|
|
4767
4689
|
await Bun.$`mkdir -p ${LOGS_DIR}`.quiet();
|
|
4768
4690
|
}
|
|
4769
4691
|
async function loadDevState() {
|
|
@@ -4815,11 +4737,11 @@ async function isDevRunning() {
|
|
|
4815
4737
|
const running = await getRunningServices();
|
|
4816
4738
|
return Object.keys(running).length > 0;
|
|
4817
4739
|
}
|
|
4818
|
-
var
|
|
4740
|
+
var STATE_DIR, DEV_STATE_PATH, LOGS_DIR;
|
|
4819
4741
|
var init_dev_state = __esm(() => {
|
|
4820
|
-
|
|
4821
|
-
DEV_STATE_PATH =
|
|
4822
|
-
LOGS_DIR =
|
|
4742
|
+
STATE_DIR = join3(homedir3(), ".secondlayer");
|
|
4743
|
+
DEV_STATE_PATH = join3(STATE_DIR, "dev.json");
|
|
4744
|
+
LOGS_DIR = join3(STATE_DIR, "logs");
|
|
4823
4745
|
});
|
|
4824
4746
|
|
|
4825
4747
|
// src/utils/format.ts
|
|
@@ -6188,7 +6110,7 @@ var require_get_stream = __commonJS((exports, module) => {
|
|
|
6188
6110
|
this.name = "MaxBufferError";
|
|
6189
6111
|
}
|
|
6190
6112
|
}
|
|
6191
|
-
async function
|
|
6113
|
+
async function getStream(inputStream, options) {
|
|
6192
6114
|
if (!inputStream) {
|
|
6193
6115
|
throw new Error("Expected a stream");
|
|
6194
6116
|
}
|
|
@@ -6221,9 +6143,9 @@ var require_get_stream = __commonJS((exports, module) => {
|
|
|
6221
6143
|
});
|
|
6222
6144
|
return stream2.getBufferedValue();
|
|
6223
6145
|
}
|
|
6224
|
-
module.exports =
|
|
6225
|
-
module.exports.buffer = (stream2, options) =>
|
|
6226
|
-
module.exports.array = (stream2, options) =>
|
|
6146
|
+
module.exports = getStream;
|
|
6147
|
+
module.exports.buffer = (stream2, options) => getStream(stream2, { ...options, encoding: "buffer" });
|
|
6148
|
+
module.exports.array = (stream2, options) => getStream(stream2, { ...options, array: true });
|
|
6227
6149
|
module.exports.MaxBufferError = MaxBufferError;
|
|
6228
6150
|
});
|
|
6229
6151
|
|
|
@@ -6688,9 +6610,9 @@ function lowercaseKeys(object) {
|
|
|
6688
6610
|
|
|
6689
6611
|
// ../../node_modules/responselike/index.js
|
|
6690
6612
|
import { Readable as ReadableStream2 } from "node:stream";
|
|
6691
|
-
var
|
|
6613
|
+
var Response;
|
|
6692
6614
|
var init_responselike = __esm(() => {
|
|
6693
|
-
|
|
6615
|
+
Response = class Response extends ReadableStream2 {
|
|
6694
6616
|
statusCode;
|
|
6695
6617
|
headers;
|
|
6696
6618
|
body;
|
|
@@ -7128,7 +7050,7 @@ class CacheableRequest {
|
|
|
7128
7050
|
response.once("end", resolve);
|
|
7129
7051
|
});
|
|
7130
7052
|
const headers = convertHeaders(revalidatedPolicy.policy.responseHeaders());
|
|
7131
|
-
response = new
|
|
7053
|
+
response = new Response({ statusCode: revalidate.statusCode, headers, body: revalidate.body, url: revalidate.url });
|
|
7132
7054
|
response.cachePolicy = revalidatedPolicy.policy;
|
|
7133
7055
|
response.fromCache = true;
|
|
7134
7056
|
}
|
|
@@ -7204,7 +7126,7 @@ class CacheableRequest {
|
|
|
7204
7126
|
const policy = import_http_cache_semantics.default.fromObject(cacheEntry.cachePolicy);
|
|
7205
7127
|
if (policy.satisfiesWithoutRevalidation(options_) && !options_.forceRefresh) {
|
|
7206
7128
|
const headers = convertHeaders(policy.responseHeaders());
|
|
7207
|
-
const response = new
|
|
7129
|
+
const response = new Response({ statusCode: cacheEntry.statusCode, headers, body: cacheEntry.body, url: cacheEntry.url });
|
|
7208
7130
|
response.cachePolicy = policy;
|
|
7209
7131
|
response.fromCache = true;
|
|
7210
7132
|
ee.emit("response", response);
|
|
@@ -7467,7 +7389,7 @@ var require_get_stream2 = __commonJS((exports, module) => {
|
|
|
7467
7389
|
this.name = "MaxBufferError";
|
|
7468
7390
|
}
|
|
7469
7391
|
}
|
|
7470
|
-
async function
|
|
7392
|
+
async function getStream2(inputStream, options) {
|
|
7471
7393
|
if (!inputStream) {
|
|
7472
7394
|
throw new Error("Expected a stream");
|
|
7473
7395
|
}
|
|
@@ -7500,9 +7422,9 @@ var require_get_stream2 = __commonJS((exports, module) => {
|
|
|
7500
7422
|
});
|
|
7501
7423
|
return stream3.getBufferedValue();
|
|
7502
7424
|
}
|
|
7503
|
-
module.exports =
|
|
7504
|
-
module.exports.buffer = (stream3, options) =>
|
|
7505
|
-
module.exports.array = (stream3, options) =>
|
|
7425
|
+
module.exports = getStream2;
|
|
7426
|
+
module.exports.buffer = (stream3, options) => getStream2(stream3, { ...options, encoding: "buffer" });
|
|
7427
|
+
module.exports.array = (stream3, options) => getStream2(stream3, { ...options, array: true });
|
|
7506
7428
|
module.exports.MaxBufferError = MaxBufferError;
|
|
7507
7429
|
});
|
|
7508
7430
|
|
|
@@ -9304,23 +9226,23 @@ var require_client_request = __commonJS((exports, module) => {
|
|
|
9304
9226
|
var kPendingAgentPromise = Symbol("pendingAgentPromise");
|
|
9305
9227
|
|
|
9306
9228
|
class ClientRequest extends Writable {
|
|
9307
|
-
constructor(
|
|
9229
|
+
constructor(input, options, callback) {
|
|
9308
9230
|
super({
|
|
9309
9231
|
autoDestroy: false,
|
|
9310
9232
|
emitClose: false
|
|
9311
9233
|
});
|
|
9312
|
-
if (typeof
|
|
9313
|
-
|
|
9314
|
-
} else if (
|
|
9315
|
-
|
|
9234
|
+
if (typeof input === "string") {
|
|
9235
|
+
input = urlToHttpOptions(new URL2(input));
|
|
9236
|
+
} else if (input instanceof URL2) {
|
|
9237
|
+
input = urlToHttpOptions(input);
|
|
9316
9238
|
} else {
|
|
9317
|
-
|
|
9239
|
+
input = { ...input };
|
|
9318
9240
|
}
|
|
9319
9241
|
if (typeof options === "function" || options === undefined) {
|
|
9320
9242
|
callback = options;
|
|
9321
|
-
options =
|
|
9243
|
+
options = input;
|
|
9322
9244
|
} else {
|
|
9323
|
-
options = Object.assign(
|
|
9245
|
+
options = Object.assign(input, options);
|
|
9324
9246
|
}
|
|
9325
9247
|
if (options.h2session) {
|
|
9326
9248
|
this[kSession] = options.h2session;
|
|
@@ -9815,19 +9737,19 @@ var require_auto = __commonJS((exports, module) => {
|
|
|
9815
9737
|
};
|
|
9816
9738
|
};
|
|
9817
9739
|
var defaultResolveProtocol = createResolveProtocol(cache, queue);
|
|
9818
|
-
module.exports = async (
|
|
9819
|
-
if (typeof
|
|
9820
|
-
|
|
9821
|
-
} else if (
|
|
9822
|
-
|
|
9740
|
+
module.exports = async (input, options, callback) => {
|
|
9741
|
+
if (typeof input === "string") {
|
|
9742
|
+
input = urlToHttpOptions(new URL2(input));
|
|
9743
|
+
} else if (input instanceof URL2) {
|
|
9744
|
+
input = urlToHttpOptions(input);
|
|
9823
9745
|
} else {
|
|
9824
|
-
|
|
9746
|
+
input = { ...input };
|
|
9825
9747
|
}
|
|
9826
9748
|
if (typeof options === "function" || options === undefined) {
|
|
9827
9749
|
callback = options;
|
|
9828
|
-
options =
|
|
9750
|
+
options = input;
|
|
9829
9751
|
} else {
|
|
9830
|
-
options = Object.assign(
|
|
9752
|
+
options = Object.assign(input, options);
|
|
9831
9753
|
}
|
|
9832
9754
|
options.ALPNProtocols = options.ALPNProtocols || ["h2", "http/1.1"];
|
|
9833
9755
|
if (!Array.isArray(options.ALPNProtocols) || options.ALPNProtocols.length === 0) {
|
|
@@ -10134,7 +10056,7 @@ var require_h2_over_h1 = __commonJS((exports, module) => {
|
|
|
10134
10056
|
var https = __require("https");
|
|
10135
10057
|
var Http2OverHttpX = require_h2_over_hx();
|
|
10136
10058
|
var getAuthorizationHeaders = require_get_auth_headers();
|
|
10137
|
-
var
|
|
10059
|
+
var getStream2 = (request) => new Promise((resolve, reject) => {
|
|
10138
10060
|
const onConnect = (response, socket, head) => {
|
|
10139
10061
|
socket.unshift(head);
|
|
10140
10062
|
request.off("error", reject);
|
|
@@ -10161,7 +10083,7 @@ var require_h2_over_h1 = __commonJS((exports, module) => {
|
|
|
10161
10083
|
},
|
|
10162
10084
|
method: "CONNECT"
|
|
10163
10085
|
}).end();
|
|
10164
|
-
return
|
|
10086
|
+
return getStream2(request);
|
|
10165
10087
|
}
|
|
10166
10088
|
}
|
|
10167
10089
|
module.exports = {
|
|
@@ -10540,7 +10462,7 @@ var init_options = __esm(() => {
|
|
|
10540
10462
|
enableUnixSockets: false
|
|
10541
10463
|
};
|
|
10542
10464
|
Options = class Options {
|
|
10543
|
-
constructor(
|
|
10465
|
+
constructor(input, options, defaults) {
|
|
10544
10466
|
Object.defineProperty(this, "_unixOptions", {
|
|
10545
10467
|
enumerable: true,
|
|
10546
10468
|
configurable: true,
|
|
@@ -10565,10 +10487,10 @@ var init_options = __esm(() => {
|
|
|
10565
10487
|
writable: true,
|
|
10566
10488
|
value: undefined
|
|
10567
10489
|
});
|
|
10568
|
-
assert.any([dist_default.string, dist_default.urlInstance, dist_default.object, dist_default.undefined],
|
|
10490
|
+
assert.any([dist_default.string, dist_default.urlInstance, dist_default.object, dist_default.undefined], input);
|
|
10569
10491
|
assert.any([dist_default.object, dist_default.undefined], options);
|
|
10570
10492
|
assert.any([dist_default.object, dist_default.undefined], defaults);
|
|
10571
|
-
if (
|
|
10493
|
+
if (input instanceof Options || options instanceof Options) {
|
|
10572
10494
|
throw new TypeError("The defaults must be passed as the third argument");
|
|
10573
10495
|
}
|
|
10574
10496
|
this._internals = cloneInternals(defaults?._internals ?? defaults ?? defaultInternals);
|
|
@@ -10576,25 +10498,25 @@ var init_options = __esm(() => {
|
|
|
10576
10498
|
this._merging = false;
|
|
10577
10499
|
this._unixOptions = undefined;
|
|
10578
10500
|
try {
|
|
10579
|
-
if (dist_default.plainObject(
|
|
10501
|
+
if (dist_default.plainObject(input)) {
|
|
10580
10502
|
try {
|
|
10581
|
-
this.merge(
|
|
10503
|
+
this.merge(input);
|
|
10582
10504
|
this.merge(options);
|
|
10583
10505
|
} finally {
|
|
10584
|
-
this.url =
|
|
10506
|
+
this.url = input.url;
|
|
10585
10507
|
}
|
|
10586
10508
|
} else {
|
|
10587
10509
|
try {
|
|
10588
10510
|
this.merge(options);
|
|
10589
10511
|
} finally {
|
|
10590
10512
|
if (options?.url !== undefined) {
|
|
10591
|
-
if (
|
|
10513
|
+
if (input === undefined) {
|
|
10592
10514
|
this.url = options.url;
|
|
10593
10515
|
} else {
|
|
10594
10516
|
throw new TypeError("The `url` option is mutually exclusive with the `input` argument");
|
|
10595
10517
|
}
|
|
10596
|
-
} else if (
|
|
10597
|
-
this.url =
|
|
10518
|
+
} else if (input !== undefined) {
|
|
10519
|
+
this.url = input;
|
|
10598
10520
|
}
|
|
10599
10521
|
}
|
|
10600
10522
|
}
|
|
@@ -13254,9 +13176,6 @@ async function startWorker(options2) {
|
|
|
13254
13176
|
const rootDir = dirname2(dirname2(dirname2(dirname2(import.meta.dir))));
|
|
13255
13177
|
const workerPath = resolve3(rootDir, "packages/worker/src/index.ts");
|
|
13256
13178
|
await serviceManager.start(SERVICE_NAME2, ["bun", "run", "--watch", workerPath], {
|
|
13257
|
-
env: {
|
|
13258
|
-
WORKER_CONCURRENCY: String(options2.concurrency ?? 5)
|
|
13259
|
-
},
|
|
13260
13179
|
onStdout: options2.onLog,
|
|
13261
13180
|
onStderr: options2.onLog
|
|
13262
13181
|
});
|
|
@@ -13286,93 +13205,6 @@ var init_api2 = __esm(() => {
|
|
|
13286
13205
|
init_manager();
|
|
13287
13206
|
});
|
|
13288
13207
|
|
|
13289
|
-
// src/services/receiver-server.ts
|
|
13290
|
-
import { verifySignatureHeader } from "@secondlayer/shared/crypto";
|
|
13291
|
-
function startReceiverServer(options2 = {}) {
|
|
13292
|
-
const port = options2.port ?? 3900;
|
|
13293
|
-
const responseCode = options2.responseCode ?? 200;
|
|
13294
|
-
server = Bun.serve({
|
|
13295
|
-
port,
|
|
13296
|
-
fetch: async (req) => {
|
|
13297
|
-
const url = new URL(req.url);
|
|
13298
|
-
const method = req.method;
|
|
13299
|
-
const path = url.pathname;
|
|
13300
|
-
if (path === "/health" && method === "GET") {
|
|
13301
|
-
return new Response("OK", { status: 200 });
|
|
13302
|
-
}
|
|
13303
|
-
if (method !== "POST") {
|
|
13304
|
-
return new Response("Method not allowed", { status: 405 });
|
|
13305
|
-
}
|
|
13306
|
-
const headers = {};
|
|
13307
|
-
req.headers.forEach((value, key) => {
|
|
13308
|
-
headers[key] = value;
|
|
13309
|
-
});
|
|
13310
|
-
let body;
|
|
13311
|
-
let signatureValid = null;
|
|
13312
|
-
try {
|
|
13313
|
-
const rawBody = await req.text();
|
|
13314
|
-
body = JSON.parse(rawBody);
|
|
13315
|
-
const signatureHeader = headers["x-streams-signature"];
|
|
13316
|
-
if (options2.secret && signatureHeader) {
|
|
13317
|
-
signatureValid = verifySignatureHeader(rawBody, signatureHeader, options2.secret);
|
|
13318
|
-
}
|
|
13319
|
-
} catch {
|
|
13320
|
-
body = null;
|
|
13321
|
-
}
|
|
13322
|
-
const event = {
|
|
13323
|
-
timestamp: new Date,
|
|
13324
|
-
method,
|
|
13325
|
-
path,
|
|
13326
|
-
headers,
|
|
13327
|
-
body,
|
|
13328
|
-
signatureValid
|
|
13329
|
-
};
|
|
13330
|
-
if (options2.onDelivery) {
|
|
13331
|
-
options2.onDelivery(event);
|
|
13332
|
-
} else {
|
|
13333
|
-
logDelivery(event);
|
|
13334
|
-
}
|
|
13335
|
-
return new Response("OK", { status: responseCode });
|
|
13336
|
-
}
|
|
13337
|
-
});
|
|
13338
|
-
return port;
|
|
13339
|
-
}
|
|
13340
|
-
function stopReceiverServer() {
|
|
13341
|
-
if (server) {
|
|
13342
|
-
server.stop();
|
|
13343
|
-
server = null;
|
|
13344
|
-
}
|
|
13345
|
-
}
|
|
13346
|
-
function logDelivery(event) {
|
|
13347
|
-
const time = event.timestamp.toISOString();
|
|
13348
|
-
console.log("");
|
|
13349
|
-
console.log(blue("━".repeat(60)));
|
|
13350
|
-
console.log(green("⚡ Delivery received"));
|
|
13351
|
-
console.log(dim(` ${time}`));
|
|
13352
|
-
console.log(dim(` ${event.method} ${event.path}`));
|
|
13353
|
-
if (event.signatureValid === true) {
|
|
13354
|
-
console.log(green(" ✓ Signature valid"));
|
|
13355
|
-
} else if (event.signatureValid === false) {
|
|
13356
|
-
console.log(red(" ✗ Signature invalid"));
|
|
13357
|
-
} else if (event.headers["x-streams-signature"]) {
|
|
13358
|
-
console.log(yellow(" ⚠ Signature not verified (no secret configured)"));
|
|
13359
|
-
}
|
|
13360
|
-
if (event.body) {
|
|
13361
|
-
console.log(dim(`
|
|
13362
|
-
Payload:`));
|
|
13363
|
-
const lines = JSON.stringify(event.body, null, 2).split(`
|
|
13364
|
-
`);
|
|
13365
|
-
for (const line of lines) {
|
|
13366
|
-
console.log(` ${line}`);
|
|
13367
|
-
}
|
|
13368
|
-
}
|
|
13369
|
-
console.log(blue("━".repeat(60)));
|
|
13370
|
-
}
|
|
13371
|
-
var server = null;
|
|
13372
|
-
var init_receiver_server = __esm(() => {
|
|
13373
|
-
init_output();
|
|
13374
|
-
});
|
|
13375
|
-
|
|
13376
13208
|
// src/services/subgraph-processor.ts
|
|
13377
13209
|
import { dirname as dirname4, resolve as resolve5 } from "node:path";
|
|
13378
13210
|
async function startSubgraphProcessor(options2) {
|
|
@@ -13397,7 +13229,6 @@ var init_services = __esm(() => {
|
|
|
13397
13229
|
init_indexer();
|
|
13398
13230
|
init_worker();
|
|
13399
13231
|
init_api2();
|
|
13400
|
-
init_receiver_server();
|
|
13401
13232
|
init_subgraph_processor();
|
|
13402
13233
|
});
|
|
13403
13234
|
|
|
@@ -13413,7 +13244,7 @@ __export(exports_dev_impl, {
|
|
|
13413
13244
|
isDevAlreadyRunning: () => isDevAlreadyRunning
|
|
13414
13245
|
});
|
|
13415
13246
|
import { mkdirSync as mkdirSync2 } from "node:fs";
|
|
13416
|
-
import { dirname as dirname5, join as
|
|
13247
|
+
import { dirname as dirname5, join as join4, resolve as resolve6 } from "node:path";
|
|
13417
13248
|
async function isDevAlreadyRunning() {
|
|
13418
13249
|
if (await isDevRunning()) {
|
|
13419
13250
|
const running = await getRunningServices();
|
|
@@ -13425,7 +13256,6 @@ async function isDevAlreadyRunning() {
|
|
|
13425
13256
|
console.log(` ${green("sl local logs")} ${dim("View logs")}`);
|
|
13426
13257
|
console.log(` ${green("sl local stop")} ${dim("Stop all services")}`);
|
|
13427
13258
|
console.log(` ${green("sl local status")} ${dim("Show status")}`);
|
|
13428
|
-
console.log(` ${green("sl streams set --all paused --wait")} ${dim("Pause stream processing")}`);
|
|
13429
13259
|
return true;
|
|
13430
13260
|
}
|
|
13431
13261
|
return false;
|
|
@@ -13441,7 +13271,6 @@ async function runBackground(options2) {
|
|
|
13441
13271
|
const dataDir = getDataDir(config);
|
|
13442
13272
|
const indexerPort = options2.stacksNode ? 3701 : Number.parseInt(options2.indexerPort) || config.ports.indexer;
|
|
13443
13273
|
const apiPort = Number.parseInt(options2.apiPort) || config.ports.api;
|
|
13444
|
-
const receiverPort = Number.parseInt(options2.receiverPort) || config.ports.receiver;
|
|
13445
13274
|
if (options2.stacksNode && config.node) {
|
|
13446
13275
|
const validation = await validateNetworkConsistency(config);
|
|
13447
13276
|
if (!validation.valid) {
|
|
@@ -13454,7 +13283,7 @@ async function runBackground(options2) {
|
|
|
13454
13283
|
}
|
|
13455
13284
|
await ensureDirs();
|
|
13456
13285
|
await clearLogs();
|
|
13457
|
-
|
|
13286
|
+
printBanner();
|
|
13458
13287
|
try {
|
|
13459
13288
|
await requireDocker();
|
|
13460
13289
|
} catch (err) {
|
|
@@ -13555,32 +13384,6 @@ async function runBackground(options2) {
|
|
|
13555
13384
|
};
|
|
13556
13385
|
console.log(green(" ✓ Subgraph processor"), dim("processing subgraphs"));
|
|
13557
13386
|
}
|
|
13558
|
-
if (options2.receiver) {
|
|
13559
|
-
const receiverLogFile = getLogFile("receiver");
|
|
13560
|
-
const receiverArgs = [
|
|
13561
|
-
"bun",
|
|
13562
|
-
"run",
|
|
13563
|
-
resolve6(packagesDir, "packages/cli/src/services/receiver-standalone.ts")
|
|
13564
|
-
];
|
|
13565
|
-
const receiverEnv = {
|
|
13566
|
-
...process.env,
|
|
13567
|
-
PORT: String(receiverPort)
|
|
13568
|
-
};
|
|
13569
|
-
if (options2.secret)
|
|
13570
|
-
receiverEnv.SIGNING_SECRET = options2.secret;
|
|
13571
|
-
const receiverProc = Bun.spawn(receiverArgs, {
|
|
13572
|
-
env: receiverEnv,
|
|
13573
|
-
stdout: Bun.file(receiverLogFile),
|
|
13574
|
-
stderr: Bun.file(receiverLogFile)
|
|
13575
|
-
});
|
|
13576
|
-
state.services.receiver = {
|
|
13577
|
-
pid: receiverProc.pid,
|
|
13578
|
-
port: receiverPort,
|
|
13579
|
-
startedAt: new Date().toISOString(),
|
|
13580
|
-
logFile: receiverLogFile
|
|
13581
|
-
};
|
|
13582
|
-
console.log(green(" ✓ Receiver server"), dim(`http://localhost:${receiverPort}`));
|
|
13583
|
-
}
|
|
13584
13387
|
await Bun.sleep(500);
|
|
13585
13388
|
for (const [name, service] of Object.entries(state.services)) {
|
|
13586
13389
|
if (!isProcessRunning(service.pid)) {
|
|
@@ -13589,7 +13392,7 @@ async function runBackground(options2) {
|
|
|
13589
13392
|
}
|
|
13590
13393
|
await saveDevState(state);
|
|
13591
13394
|
console.log("");
|
|
13592
|
-
printUrls(indexerPort, apiPort
|
|
13395
|
+
printUrls(indexerPort, apiPort);
|
|
13593
13396
|
console.log("");
|
|
13594
13397
|
success("Dev environment started in background");
|
|
13595
13398
|
console.log("");
|
|
@@ -13597,7 +13400,6 @@ async function runBackground(options2) {
|
|
|
13597
13400
|
console.log(` ${green("sl local logs -f")} ${dim("Follow logs")}`);
|
|
13598
13401
|
console.log(` ${green("sl local stop")} ${dim("Stop all services")}`);
|
|
13599
13402
|
console.log(` ${green("sl local status")} ${dim("Show status")}`);
|
|
13600
|
-
console.log(` ${green("sl streams set --all paused --wait")} ${dim("Pause stream processing")}`);
|
|
13601
13403
|
console.log("");
|
|
13602
13404
|
process.exit(0);
|
|
13603
13405
|
} catch (err) {
|
|
@@ -13627,20 +13429,16 @@ async function runForeground(options2) {
|
|
|
13627
13429
|
const dataDir = getDataDir(config);
|
|
13628
13430
|
const indexerPort = options2.stacksNode ? 3701 : Number.parseInt(options2.indexerPort) || config.ports.indexer;
|
|
13629
13431
|
const apiPort = Number.parseInt(options2.apiPort) || config.ports.api;
|
|
13630
|
-
const receiverPort = Number.parseInt(options2.receiverPort) || config.ports.receiver;
|
|
13631
13432
|
let devPostgresStarted = false;
|
|
13632
13433
|
const shutdown = async () => {
|
|
13633
13434
|
console.log(`
|
|
13634
13435
|
`);
|
|
13635
13436
|
info("Shutting down services...");
|
|
13636
|
-
if (options2.receiver) {
|
|
13637
|
-
stopReceiverServer();
|
|
13638
|
-
}
|
|
13639
13437
|
await serviceManager.stopAll();
|
|
13640
13438
|
if (devPostgresStarted) {
|
|
13641
13439
|
info("Stopping PostgreSQL container...");
|
|
13642
|
-
await Bun.$`docker stop
|
|
13643
|
-
await Bun.$`docker rm
|
|
13440
|
+
await Bun.$`docker stop secondlayer-dev-postgres`.quiet().nothrow();
|
|
13441
|
+
await Bun.$`docker rm secondlayer-dev-postgres`.quiet().nothrow();
|
|
13644
13442
|
}
|
|
13645
13443
|
success("All services stopped");
|
|
13646
13444
|
process.exit(0);
|
|
@@ -13648,7 +13446,7 @@ async function runForeground(options2) {
|
|
|
13648
13446
|
process.on("SIGINT", shutdown);
|
|
13649
13447
|
process.on("SIGTERM", shutdown);
|
|
13650
13448
|
try {
|
|
13651
|
-
|
|
13449
|
+
printBanner();
|
|
13652
13450
|
try {
|
|
13653
13451
|
await requireDocker();
|
|
13654
13452
|
} catch (err) {
|
|
@@ -13681,10 +13479,6 @@ async function runForeground(options2) {
|
|
|
13681
13479
|
console.log("");
|
|
13682
13480
|
}
|
|
13683
13481
|
process.env.DEV_MODE = "true";
|
|
13684
|
-
if (options2.receiver) {
|
|
13685
|
-
startReceiverServer({ port: receiverPort, secret: options2.secret });
|
|
13686
|
-
console.log(green(" ✓ Receiver server"), dim(`http://localhost:${receiverPort}`));
|
|
13687
|
-
}
|
|
13688
13482
|
await startApi({ port: apiPort, onLog: (line) => logService("api", line) });
|
|
13689
13483
|
console.log(green(" ✓ API"), dim(`http://localhost:${apiPort}`));
|
|
13690
13484
|
await startIndexer({
|
|
@@ -13701,7 +13495,7 @@ async function runForeground(options2) {
|
|
|
13701
13495
|
});
|
|
13702
13496
|
console.log(green(" ✓ Subgraph processor"), dim("processing subgraphs"));
|
|
13703
13497
|
console.log("");
|
|
13704
|
-
printUrls(indexerPort, apiPort
|
|
13498
|
+
printUrls(indexerPort, apiPort);
|
|
13705
13499
|
console.log("");
|
|
13706
13500
|
info("Press Ctrl+C to stop all services");
|
|
13707
13501
|
console.log("");
|
|
@@ -13709,9 +13503,6 @@ async function runForeground(options2) {
|
|
|
13709
13503
|
} catch (err) {
|
|
13710
13504
|
error(`Failed to start services: ${err}`);
|
|
13711
13505
|
await serviceManager.stopAll();
|
|
13712
|
-
if (options2.receiver) {
|
|
13713
|
-
stopReceiverServer();
|
|
13714
|
-
}
|
|
13715
13506
|
process.exit(1);
|
|
13716
13507
|
}
|
|
13717
13508
|
}
|
|
@@ -13734,30 +13525,13 @@ async function showLogs(options2) {
|
|
|
13734
13525
|
return;
|
|
13735
13526
|
}
|
|
13736
13527
|
const lines = Number.parseInt(options2.lines);
|
|
13737
|
-
const verbose = options2.verbose ?? false;
|
|
13738
13528
|
if (options2.follow) {
|
|
13739
|
-
await
|
|
13529
|
+
await followLogs(serviceEntries, lines);
|
|
13740
13530
|
} else {
|
|
13741
|
-
await showStaticLogs(serviceEntries, lines
|
|
13531
|
+
await showStaticLogs(serviceEntries, lines);
|
|
13742
13532
|
}
|
|
13743
13533
|
}
|
|
13744
|
-
function
|
|
13745
|
-
try {
|
|
13746
|
-
const data = JSON.parse(jsonStr);
|
|
13747
|
-
if (data.type !== "delivery" || !data.body)
|
|
13748
|
-
return null;
|
|
13749
|
-
const { body, method, path, timestamp } = data;
|
|
13750
|
-
const streamName = body.streamName ?? body.streamId?.slice(0, 8) ?? "unknown";
|
|
13751
|
-
const height = body.block?.height ?? "?";
|
|
13752
|
-
const txCount = body.matches?.transactions?.length ?? 0;
|
|
13753
|
-
const eventCount = body.matches?.events?.length ?? 0;
|
|
13754
|
-
const dimTimestamp = dim(`[${timestamp}]`);
|
|
13755
|
-
return `${dimTimestamp} ${green("INFO:")} ${method} ${path} — ${streamName} block:${height} (${txCount} txs, ${eventCount} events)`;
|
|
13756
|
-
} catch {
|
|
13757
|
-
return null;
|
|
13758
|
-
}
|
|
13759
|
-
}
|
|
13760
|
-
function formatLogLine2(service, line, verbose) {
|
|
13534
|
+
function formatLogLine2(service, line) {
|
|
13761
13535
|
const colorFn = serviceColors[service] ?? dim;
|
|
13762
13536
|
const prefix = colorFn(`[${service}]`);
|
|
13763
13537
|
const match = line.match(/^(\[\d{4}-\d{2}-\d{2}T[\d:.]+Z\])\s*(INFO|WARN|ERROR|DEBUG):?\s*(.*)$/);
|
|
@@ -13774,14 +13548,9 @@ function formatLogLine2(service, line, verbose) {
|
|
|
13774
13548
|
return `${prefix} ${dimTimestamp} ${dim(level + ":")} ${dim(message)}`;
|
|
13775
13549
|
}
|
|
13776
13550
|
}
|
|
13777
|
-
if (service === "receiver" && !verbose) {
|
|
13778
|
-
const summary = formatDeliverySummary(line);
|
|
13779
|
-
if (summary)
|
|
13780
|
-
return `${prefix} ${summary}`;
|
|
13781
|
-
}
|
|
13782
13551
|
return `${prefix} ${line}`;
|
|
13783
13552
|
}
|
|
13784
|
-
async function showStaticLogs(services, lines
|
|
13553
|
+
async function showStaticLogs(services, lines) {
|
|
13785
13554
|
const allLines = [];
|
|
13786
13555
|
for (const [name, service] of services) {
|
|
13787
13556
|
try {
|
|
@@ -13797,11 +13566,11 @@ async function showStaticLogs(services, lines, verbose) {
|
|
|
13797
13566
|
}
|
|
13798
13567
|
allLines.sort((a, b2) => a.timestamp.getTime() - b2.timestamp.getTime());
|
|
13799
13568
|
for (const { service, line } of allLines.slice(-lines)) {
|
|
13800
|
-
console.log(formatLogLine2(service, line
|
|
13569
|
+
console.log(formatLogLine2(service, line));
|
|
13801
13570
|
}
|
|
13802
13571
|
}
|
|
13803
|
-
async function
|
|
13804
|
-
await showStaticLogs(services, initialLines
|
|
13572
|
+
async function followLogs(services, initialLines) {
|
|
13573
|
+
await showStaticLogs(services, initialLines);
|
|
13805
13574
|
const procs = [];
|
|
13806
13575
|
for (const [name, service] of services) {
|
|
13807
13576
|
const proc = Bun.spawn(["tail", "-f", "-n", "0", service.logFile], {
|
|
@@ -13823,7 +13592,7 @@ async function followLogs2(services, initialLines, verbose) {
|
|
|
13823
13592
|
buffer2 = lines.pop() || "";
|
|
13824
13593
|
for (const line of lines) {
|
|
13825
13594
|
if (line.trim()) {
|
|
13826
|
-
console.log(formatLogLine2(name, line
|
|
13595
|
+
console.log(formatLogLine2(name, line));
|
|
13827
13596
|
}
|
|
13828
13597
|
}
|
|
13829
13598
|
}
|
|
@@ -13853,14 +13622,14 @@ async function stopDev() {
|
|
|
13853
13622
|
}
|
|
13854
13623
|
if (state.dockerContainers.postgres) {
|
|
13855
13624
|
info("Stopping PostgreSQL container...");
|
|
13856
|
-
await Bun.$`docker stop
|
|
13857
|
-
await Bun.$`docker rm
|
|
13625
|
+
await Bun.$`docker stop secondlayer-dev-postgres`.quiet().nothrow();
|
|
13626
|
+
await Bun.$`docker rm secondlayer-dev-postgres`.quiet().nothrow();
|
|
13858
13627
|
}
|
|
13859
13628
|
await clearDevState();
|
|
13860
13629
|
success("Dev environment stopped");
|
|
13861
13630
|
return;
|
|
13862
13631
|
}
|
|
13863
|
-
const pgOrphan = await isContainerRunning("
|
|
13632
|
+
const pgOrphan = await isContainerRunning("secondlayer-dev-postgres");
|
|
13864
13633
|
if (!pgOrphan) {
|
|
13865
13634
|
info("Dev environment is not running");
|
|
13866
13635
|
return;
|
|
@@ -13868,8 +13637,8 @@ async function stopDev() {
|
|
|
13868
13637
|
info("Cleaning up orphaned containers...");
|
|
13869
13638
|
if (pgOrphan) {
|
|
13870
13639
|
info("Stopping PostgreSQL container...");
|
|
13871
|
-
await Bun.$`docker stop
|
|
13872
|
-
await Bun.$`docker rm
|
|
13640
|
+
await Bun.$`docker stop secondlayer-dev-postgres`.quiet().nothrow();
|
|
13641
|
+
await Bun.$`docker rm secondlayer-dev-postgres`.quiet().nothrow();
|
|
13873
13642
|
}
|
|
13874
13643
|
success("Orphaned containers stopped");
|
|
13875
13644
|
}
|
|
@@ -13951,29 +13720,6 @@ async function restartDev() {
|
|
|
13951
13720
|
};
|
|
13952
13721
|
console.log(green(" ✓ Worker"), dim("processing jobs"));
|
|
13953
13722
|
}
|
|
13954
|
-
if (state.services.receiver) {
|
|
13955
|
-
const receiverPort = config.ports.receiver;
|
|
13956
|
-
const receiverLogFile = getLogFile("receiver");
|
|
13957
|
-
const receiverProc = Bun.spawn([
|
|
13958
|
-
"bun",
|
|
13959
|
-
"run",
|
|
13960
|
-
resolve6(packagesDir, "packages/cli/src/services/receiver-standalone.ts")
|
|
13961
|
-
], {
|
|
13962
|
-
env: {
|
|
13963
|
-
...process.env,
|
|
13964
|
-
PORT: String(receiverPort)
|
|
13965
|
-
},
|
|
13966
|
-
stdout: Bun.file(receiverLogFile),
|
|
13967
|
-
stderr: Bun.file(receiverLogFile)
|
|
13968
|
-
});
|
|
13969
|
-
newState.services.receiver = {
|
|
13970
|
-
pid: receiverProc.pid,
|
|
13971
|
-
port: receiverPort,
|
|
13972
|
-
startedAt: new Date().toISOString(),
|
|
13973
|
-
logFile: receiverLogFile
|
|
13974
|
-
};
|
|
13975
|
-
console.log(green(" ✓ Receiver server"), dim(`http://localhost:${receiverPort}`));
|
|
13976
|
-
}
|
|
13977
13723
|
if (state.services.subgraphs) {
|
|
13978
13724
|
const subgraphsLogFile = getLogFile("subgraphs");
|
|
13979
13725
|
const subgraphsProc = Bun.spawn(["bun", "run", resolve6(packagesDir, "packages/subgraphs/src/service.ts")], {
|
|
@@ -14021,8 +13767,8 @@ async function showDevStatus() {
|
|
|
14021
13767
|
printRunningServices(running);
|
|
14022
13768
|
console.log("");
|
|
14023
13769
|
console.log(blue("Docker Containers"));
|
|
14024
|
-
const pgRunning = await isContainerRunning("
|
|
14025
|
-
console.log(` ${pgRunning ? green("✓") : red("✗")} PostgreSQL ${dim("
|
|
13770
|
+
const pgRunning = await isContainerRunning("secondlayer-dev-postgres");
|
|
13771
|
+
console.log(` ${pgRunning ? green("✓") : red("✗")} PostgreSQL ${dim("secondlayer-dev-postgres")}`);
|
|
14026
13772
|
console.log("");
|
|
14027
13773
|
console.log(dim(`Started: ${state.startedAt}`));
|
|
14028
13774
|
console.log(dim(`Logs: ${getLogsDir()}`));
|
|
@@ -14039,32 +13785,26 @@ async function isContainerRunning(name) {
|
|
|
14039
13785
|
const result = await Bun.$`docker ps -q -f name=${name}`.quiet().nothrow();
|
|
14040
13786
|
return result.stdout.toString().trim().length > 0;
|
|
14041
13787
|
}
|
|
14042
|
-
function
|
|
13788
|
+
function printBanner() {
|
|
14043
13789
|
console.log("");
|
|
14044
13790
|
console.log(blue(" ╔═══════════════════════════════════════╗"));
|
|
14045
|
-
console.log(blue(" ║") + "
|
|
13791
|
+
console.log(blue(" ║") + " Secondlayer Dev Server " + blue("║"));
|
|
14046
13792
|
console.log(blue(" ╚═══════════════════════════════════════╝"));
|
|
14047
13793
|
console.log("");
|
|
14048
13794
|
console.log(dim(" Starting services..."));
|
|
14049
13795
|
console.log("");
|
|
14050
13796
|
}
|
|
14051
|
-
function printUrls(indexerPort, apiPort
|
|
13797
|
+
function printUrls(indexerPort, apiPort) {
|
|
14052
13798
|
console.log(dim(" ─────────────────────────────────────────"));
|
|
14053
13799
|
console.log("");
|
|
14054
13800
|
console.log(" " + blue("API:"));
|
|
14055
|
-
console.log(` List
|
|
13801
|
+
console.log(` List subgraphs: curl http://localhost:${apiPort}/api/subgraphs`);
|
|
14056
13802
|
console.log(` Health check: curl http://localhost:${apiPort}/health`);
|
|
14057
13803
|
console.log("");
|
|
14058
13804
|
console.log(" " + blue("Indexer:"));
|
|
14059
13805
|
console.log(` Health check: curl http://localhost:${indexerPort}/health`);
|
|
14060
13806
|
console.log(` Send block: curl -X POST http://localhost:${indexerPort}/new_block -d @block.json`);
|
|
14061
13807
|
console.log("");
|
|
14062
|
-
if (receiverEnabled) {
|
|
14063
|
-
console.log(" " + blue("Test Receiver:"));
|
|
14064
|
-
console.log(` Receives deliveries at http://localhost:${receiverPort}/`);
|
|
14065
|
-
console.log(` Use this URL when creating streams for testing`);
|
|
14066
|
-
console.log("");
|
|
14067
|
-
}
|
|
14068
13808
|
console.log(" " + blue("Stacks Node Config:"));
|
|
14069
13809
|
console.log(dim(" Add to your Stacks node Config.toml:"));
|
|
14070
13810
|
console.log("");
|
|
@@ -14106,19 +13846,19 @@ async function isDatabaseReachable(url) {
|
|
|
14106
13846
|
}
|
|
14107
13847
|
}
|
|
14108
13848
|
async function ensureDevPostgres(dataDir) {
|
|
14109
|
-
const check = await Bun.$`docker ps -q -f name=
|
|
13849
|
+
const check = await Bun.$`docker ps -q -f name=secondlayer-dev-postgres`.quiet().nothrow();
|
|
14110
13850
|
if (check.stdout.toString().trim()) {
|
|
14111
13851
|
return false;
|
|
14112
13852
|
}
|
|
14113
|
-
const pgDataDir =
|
|
13853
|
+
const pgDataDir = join4(dataDir, "postgres");
|
|
14114
13854
|
mkdirSync2(pgDataDir, { recursive: true });
|
|
14115
|
-
const stopped = await Bun.$`docker ps -aq -f name=
|
|
13855
|
+
const stopped = await Bun.$`docker ps -aq -f name=secondlayer-dev-postgres`.quiet().nothrow();
|
|
14116
13856
|
if (stopped.stdout.toString().trim()) {
|
|
14117
|
-
await Bun.$`docker rm
|
|
13857
|
+
await Bun.$`docker rm secondlayer-dev-postgres`.quiet().nothrow();
|
|
14118
13858
|
}
|
|
14119
|
-
await Bun.$`docker run -d --name
|
|
13859
|
+
await Bun.$`docker run -d --name secondlayer-dev-postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=secondlayer_dev -v ${pgDataDir}:/var/lib/postgresql/data -p 5432:5432 postgres:16-alpine`.quiet();
|
|
14120
13860
|
for (let i = 0;i < 30; i++) {
|
|
14121
|
-
const ready = await Bun.$`docker exec
|
|
13861
|
+
const ready = await Bun.$`docker exec secondlayer-dev-postgres pg_isready -U postgres`.quiet().nothrow();
|
|
14122
13862
|
if (ready.exitCode === 0)
|
|
14123
13863
|
return true;
|
|
14124
13864
|
await Bun.sleep(500);
|
|
@@ -14133,7 +13873,7 @@ async function runMigrations(databaseUrl) {
|
|
|
14133
13873
|
throw new Error(`Migration failed: ${result.stderr.toString()}`);
|
|
14134
13874
|
}
|
|
14135
13875
|
}
|
|
14136
|
-
var DEV_DATABASE_URL3 = "postgres://postgres:postgres@localhost:5432/
|
|
13876
|
+
var DEV_DATABASE_URL3 = "postgres://postgres:postgres@localhost:5432/secondlayer_dev", serviceColors;
|
|
14137
13877
|
var init_dev_impl = __esm(() => {
|
|
14138
13878
|
init_config();
|
|
14139
13879
|
init_dev_state();
|
|
@@ -14145,8 +13885,7 @@ var init_dev_impl = __esm(() => {
|
|
|
14145
13885
|
api: blue,
|
|
14146
13886
|
indexer: cyan,
|
|
14147
13887
|
worker: yellow,
|
|
14148
|
-
subgraphs: magenta
|
|
14149
|
-
receiver: green
|
|
13888
|
+
subgraphs: magenta
|
|
14150
13889
|
};
|
|
14151
13890
|
});
|
|
14152
13891
|
|
|
@@ -14161,7 +13900,7 @@ __export(exports_node_impl, {
|
|
|
14161
13900
|
runSetupWizard: () => runSetupWizard,
|
|
14162
13901
|
restartNode: () => restartNode
|
|
14163
13902
|
});
|
|
14164
|
-
import { confirm as
|
|
13903
|
+
import { confirm as confirm4, input as input2, select as select2 } from "@inquirer/prompts";
|
|
14165
13904
|
async function runSetupWizard() {
|
|
14166
13905
|
console.log("");
|
|
14167
13906
|
console.log(blue("Stacks Node Setup Wizard"));
|
|
@@ -14179,7 +13918,7 @@ async function runSetupWizard() {
|
|
|
14179
13918
|
}
|
|
14180
13919
|
success("Docker is running");
|
|
14181
13920
|
console.log("");
|
|
14182
|
-
const installPath = await
|
|
13921
|
+
const installPath = await input2({
|
|
14183
13922
|
message: "Where is stacks-blockchain-docker installed?",
|
|
14184
13923
|
validate: async (value) => {
|
|
14185
13924
|
if (!value.trim())
|
|
@@ -14190,7 +13929,7 @@ async function runSetupWizard() {
|
|
|
14190
13929
|
return true;
|
|
14191
13930
|
}
|
|
14192
13931
|
});
|
|
14193
|
-
const network = await
|
|
13932
|
+
const network = await select2({
|
|
14194
13933
|
message: "Which network?",
|
|
14195
13934
|
choices: [
|
|
14196
13935
|
{ name: "mainnet", value: "mainnet" },
|
|
@@ -14198,18 +13937,18 @@ async function runSetupWizard() {
|
|
|
14198
13937
|
],
|
|
14199
13938
|
default: "mainnet"
|
|
14200
13939
|
});
|
|
14201
|
-
const autoStartIndexer = await
|
|
14202
|
-
message: "Auto-start
|
|
13940
|
+
const autoStartIndexer = await confirm4({
|
|
13941
|
+
message: "Auto-start indexer when node starts?",
|
|
14203
13942
|
default: true
|
|
14204
13943
|
});
|
|
14205
13944
|
let indexerPort = 3700;
|
|
14206
13945
|
if (autoStartIndexer) {
|
|
14207
|
-
const customPort = await
|
|
13946
|
+
const customPort = await confirm4({
|
|
14208
13947
|
message: "Use default indexer port (3700)?",
|
|
14209
13948
|
default: true
|
|
14210
13949
|
});
|
|
14211
13950
|
if (!customPort) {
|
|
14212
|
-
const portInput = await
|
|
13951
|
+
const portInput = await input2({
|
|
14213
13952
|
message: "Enter custom indexer port:",
|
|
14214
13953
|
default: "3700",
|
|
14215
13954
|
validate: (value) => {
|
|
@@ -14304,13 +14043,13 @@ async function startNode(pathOverride, withIndexer) {
|
|
|
14304
14043
|
console.log(" " + green("sl local node logs -f") + dim(" - Follow logs"));
|
|
14305
14044
|
console.log("");
|
|
14306
14045
|
}
|
|
14307
|
-
async function stopNode(_pathOverride, force,
|
|
14046
|
+
async function stopNode(_pathOverride, force, _wait) {
|
|
14308
14047
|
if (!await isNodeRunning()) {
|
|
14309
14048
|
info("Node is not running");
|
|
14310
14049
|
return;
|
|
14311
14050
|
}
|
|
14312
14051
|
if (!force) {
|
|
14313
|
-
const proceed = await
|
|
14052
|
+
const proceed = await confirm4({
|
|
14314
14053
|
message: "Stop the Stacks node?",
|
|
14315
14054
|
default: false
|
|
14316
14055
|
});
|
|
@@ -14320,9 +14059,6 @@ async function stopNode(_pathOverride, force, wait) {
|
|
|
14320
14059
|
}
|
|
14321
14060
|
}
|
|
14322
14061
|
console.log("");
|
|
14323
|
-
if (wait) {
|
|
14324
|
-
await pauseAndWait();
|
|
14325
|
-
}
|
|
14326
14062
|
info("Stopping Stacks node...");
|
|
14327
14063
|
const stopped = await stopNodeContainers();
|
|
14328
14064
|
if (stopped.length === 0) {
|
|
@@ -14331,7 +14067,7 @@ async function stopNode(_pathOverride, force, wait) {
|
|
|
14331
14067
|
}
|
|
14332
14068
|
success(`Stopped: ${stopped.join(", ")}`);
|
|
14333
14069
|
}
|
|
14334
|
-
async function restartNode(pathOverride, force,
|
|
14070
|
+
async function restartNode(pathOverride, force, _wait) {
|
|
14335
14071
|
const config = await loadConfig();
|
|
14336
14072
|
const nodePath = pathOverride || config.node?.installPath;
|
|
14337
14073
|
const network = config.node?.network || "mainnet";
|
|
@@ -14343,7 +14079,7 @@ async function restartNode(pathOverride, force, wait) {
|
|
|
14343
14079
|
const wasRunning = await isNodeRunning();
|
|
14344
14080
|
if (wasRunning) {
|
|
14345
14081
|
if (!force) {
|
|
14346
|
-
const proceed = await
|
|
14082
|
+
const proceed = await confirm4({
|
|
14347
14083
|
message: "Restart the Stacks node?",
|
|
14348
14084
|
default: false
|
|
14349
14085
|
});
|
|
@@ -14353,9 +14089,6 @@ async function restartNode(pathOverride, force, wait) {
|
|
|
14353
14089
|
}
|
|
14354
14090
|
}
|
|
14355
14091
|
console.log("");
|
|
14356
|
-
if (wait) {
|
|
14357
|
-
await pauseAndWait();
|
|
14358
|
-
}
|
|
14359
14092
|
info("Stopping Stacks node...");
|
|
14360
14093
|
const stopped = await stopNodeContainers();
|
|
14361
14094
|
if (stopped.length > 0) {
|
|
@@ -14383,33 +14116,6 @@ async function restartNode(pathOverride, force, wait) {
|
|
|
14383
14116
|
console.log(" " + green("sl local node logs -f") + dim(" - Follow logs"));
|
|
14384
14117
|
console.log("");
|
|
14385
14118
|
}
|
|
14386
|
-
async function pauseAndWait() {
|
|
14387
|
-
const POLL_INTERVAL_MS = 1000;
|
|
14388
|
-
try {
|
|
14389
|
-
info("Pausing streams...");
|
|
14390
|
-
const result = await pauseAllStreams();
|
|
14391
|
-
if (result.paused > 0) {
|
|
14392
|
-
success(`Paused ${result.paused} stream${result.paused === 1 ? "" : "s"}`);
|
|
14393
|
-
}
|
|
14394
|
-
process.stdout.write(dim("Waiting for jobs to complete..."));
|
|
14395
|
-
while (true) {
|
|
14396
|
-
const stats = await getQueueStats();
|
|
14397
|
-
const active = stats.pending + stats.processing;
|
|
14398
|
-
if (active === 0) {
|
|
14399
|
-
process.stdout.write(`
|
|
14400
|
-
`);
|
|
14401
|
-
success("All jobs completed");
|
|
14402
|
-
console.log("");
|
|
14403
|
-
return;
|
|
14404
|
-
}
|
|
14405
|
-
process.stdout.write(`\r${dim(`Waiting for jobs to complete... ${active} remaining`)}`);
|
|
14406
|
-
await Bun.sleep(POLL_INTERVAL_MS);
|
|
14407
|
-
}
|
|
14408
|
-
} catch {
|
|
14409
|
-
warn("Could not pause streams (API may not be running)");
|
|
14410
|
-
console.log("");
|
|
14411
|
-
}
|
|
14412
|
-
}
|
|
14413
14119
|
async function showStatus(pathOverride, jsonOutput) {
|
|
14414
14120
|
const config = await loadConfig();
|
|
14415
14121
|
const nodePath = pathOverride || config.node?.installPath;
|
|
@@ -14505,13 +14211,13 @@ async function showStatus(pathOverride, jsonOutput) {
|
|
|
14505
14211
|
signal: AbortSignal.timeout(2000)
|
|
14506
14212
|
});
|
|
14507
14213
|
if (indexerRes.ok) {
|
|
14508
|
-
console.log(blue("
|
|
14214
|
+
console.log(blue("Indexer"));
|
|
14509
14215
|
console.log(` ${green("+")} Running on port ${indexerPort}`);
|
|
14510
14216
|
console.log("");
|
|
14511
14217
|
}
|
|
14512
14218
|
} catch {
|
|
14513
14219
|
if (config.node) {
|
|
14514
|
-
console.log(blue("
|
|
14220
|
+
console.log(blue("Indexer"));
|
|
14515
14221
|
console.log(` ${dim("-")} ${dim(`Not running (expected on port ${indexerPort})`)}`);
|
|
14516
14222
|
console.log(dim(` Start with: sl local start`));
|
|
14517
14223
|
console.log("");
|
|
@@ -14570,7 +14276,6 @@ async function showConfigCheck(indexerPort) {
|
|
|
14570
14276
|
}
|
|
14571
14277
|
var DEFAULT_RPC_PORT = 20443;
|
|
14572
14278
|
var init_node_impl = __esm(() => {
|
|
14573
|
-
init_api_client();
|
|
14574
14279
|
init_config();
|
|
14575
14280
|
init_network();
|
|
14576
14281
|
init_node_manager();
|
|
@@ -15724,8 +15429,8 @@ var require_fill_range = __commonJS((exports, module) => {
|
|
|
15724
15429
|
return typeof value === "number" || typeof value === "string" && value !== "";
|
|
15725
15430
|
};
|
|
15726
15431
|
var isNumber = (num) => Number.isInteger(+num);
|
|
15727
|
-
var zeros = (
|
|
15728
|
-
let value = `${
|
|
15432
|
+
var zeros = (input3) => {
|
|
15433
|
+
let value = `${input3}`;
|
|
15729
15434
|
let index = -1;
|
|
15730
15435
|
if (value[0] === "-")
|
|
15731
15436
|
value = value.slice(1);
|
|
@@ -15741,27 +15446,27 @@ var require_fill_range = __commonJS((exports, module) => {
|
|
|
15741
15446
|
}
|
|
15742
15447
|
return options2.stringify === true;
|
|
15743
15448
|
};
|
|
15744
|
-
var pad = (
|
|
15449
|
+
var pad = (input3, maxLength, toNumber) => {
|
|
15745
15450
|
if (maxLength > 0) {
|
|
15746
|
-
let dash =
|
|
15451
|
+
let dash = input3[0] === "-" ? "-" : "";
|
|
15747
15452
|
if (dash)
|
|
15748
|
-
|
|
15749
|
-
|
|
15453
|
+
input3 = input3.slice(1);
|
|
15454
|
+
input3 = dash + input3.padStart(dash ? maxLength - 1 : maxLength, "0");
|
|
15750
15455
|
}
|
|
15751
15456
|
if (toNumber === false) {
|
|
15752
|
-
return String(
|
|
15457
|
+
return String(input3);
|
|
15753
15458
|
}
|
|
15754
|
-
return
|
|
15459
|
+
return input3;
|
|
15755
15460
|
};
|
|
15756
|
-
var toMaxLen = (
|
|
15757
|
-
let negative =
|
|
15461
|
+
var toMaxLen = (input3, maxLength) => {
|
|
15462
|
+
let negative = input3[0] === "-" ? "-" : "";
|
|
15758
15463
|
if (negative) {
|
|
15759
|
-
|
|
15464
|
+
input3 = input3.slice(1);
|
|
15760
15465
|
maxLength--;
|
|
15761
15466
|
}
|
|
15762
|
-
while (
|
|
15763
|
-
|
|
15764
|
-
return negative ? "-" +
|
|
15467
|
+
while (input3.length < maxLength)
|
|
15468
|
+
input3 = "0" + input3;
|
|
15469
|
+
return negative ? "-" + input3 : input3;
|
|
15765
15470
|
};
|
|
15766
15471
|
var toSequence = (parts, options2, maxLen) => {
|
|
15767
15472
|
parts.negatives.sort((a, b2) => a < b2 ? -1 : a > b2 ? 1 : 0);
|
|
@@ -16130,25 +15835,25 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
16130
15835
|
CHAR_NO_BREAK_SPACE,
|
|
16131
15836
|
CHAR_ZERO_WIDTH_NOBREAK_SPACE
|
|
16132
15837
|
} = require_constants();
|
|
16133
|
-
var parse2 = (
|
|
16134
|
-
if (typeof
|
|
15838
|
+
var parse2 = (input3, options2 = {}) => {
|
|
15839
|
+
if (typeof input3 !== "string") {
|
|
16135
15840
|
throw new TypeError("Expected a string");
|
|
16136
15841
|
}
|
|
16137
15842
|
const opts = options2 || {};
|
|
16138
15843
|
const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
|
16139
|
-
if (
|
|
16140
|
-
throw new SyntaxError(`Input length (${
|
|
15844
|
+
if (input3.length > max) {
|
|
15845
|
+
throw new SyntaxError(`Input length (${input3.length}), exceeds max characters (${max})`);
|
|
16141
15846
|
}
|
|
16142
|
-
const ast = { type: "root", input:
|
|
15847
|
+
const ast = { type: "root", input: input3, nodes: [] };
|
|
16143
15848
|
const stack = [ast];
|
|
16144
15849
|
let block = ast;
|
|
16145
15850
|
let prev = ast;
|
|
16146
15851
|
let brackets = 0;
|
|
16147
|
-
const length =
|
|
15852
|
+
const length = input3.length;
|
|
16148
15853
|
let index = 0;
|
|
16149
15854
|
let depth = 0;
|
|
16150
15855
|
let value;
|
|
16151
|
-
const advance = () =>
|
|
15856
|
+
const advance = () => input3[index++];
|
|
16152
15857
|
const push = (node) => {
|
|
16153
15858
|
if (node.type === "text" && prev.type === "dot") {
|
|
16154
15859
|
prev.type = "text";
|
|
@@ -16343,10 +16048,10 @@ var require_braces = __commonJS((exports, module) => {
|
|
|
16343
16048
|
var compile = require_compile();
|
|
16344
16049
|
var expand = require_expand();
|
|
16345
16050
|
var parse2 = require_parse();
|
|
16346
|
-
var braces = (
|
|
16051
|
+
var braces = (input3, options2 = {}) => {
|
|
16347
16052
|
let output = [];
|
|
16348
|
-
if (Array.isArray(
|
|
16349
|
-
for (const pattern of
|
|
16053
|
+
if (Array.isArray(input3)) {
|
|
16054
|
+
for (const pattern of input3) {
|
|
16350
16055
|
const result = braces.create(pattern, options2);
|
|
16351
16056
|
if (Array.isArray(result)) {
|
|
16352
16057
|
output.push(...result);
|
|
@@ -16355,31 +16060,31 @@ var require_braces = __commonJS((exports, module) => {
|
|
|
16355
16060
|
}
|
|
16356
16061
|
}
|
|
16357
16062
|
} else {
|
|
16358
|
-
output = [].concat(braces.create(
|
|
16063
|
+
output = [].concat(braces.create(input3, options2));
|
|
16359
16064
|
}
|
|
16360
16065
|
if (options2 && options2.expand === true && options2.nodupes === true) {
|
|
16361
16066
|
output = [...new Set(output)];
|
|
16362
16067
|
}
|
|
16363
16068
|
return output;
|
|
16364
16069
|
};
|
|
16365
|
-
braces.parse = (
|
|
16366
|
-
braces.stringify = (
|
|
16367
|
-
if (typeof
|
|
16368
|
-
return stringify2(braces.parse(
|
|
16070
|
+
braces.parse = (input3, options2 = {}) => parse2(input3, options2);
|
|
16071
|
+
braces.stringify = (input3, options2 = {}) => {
|
|
16072
|
+
if (typeof input3 === "string") {
|
|
16073
|
+
return stringify2(braces.parse(input3, options2), options2);
|
|
16369
16074
|
}
|
|
16370
|
-
return stringify2(
|
|
16075
|
+
return stringify2(input3, options2);
|
|
16371
16076
|
};
|
|
16372
|
-
braces.compile = (
|
|
16373
|
-
if (typeof
|
|
16374
|
-
|
|
16077
|
+
braces.compile = (input3, options2 = {}) => {
|
|
16078
|
+
if (typeof input3 === "string") {
|
|
16079
|
+
input3 = braces.parse(input3, options2);
|
|
16375
16080
|
}
|
|
16376
|
-
return compile(
|
|
16081
|
+
return compile(input3, options2);
|
|
16377
16082
|
};
|
|
16378
|
-
braces.expand = (
|
|
16379
|
-
if (typeof
|
|
16380
|
-
|
|
16083
|
+
braces.expand = (input3, options2 = {}) => {
|
|
16084
|
+
if (typeof input3 === "string") {
|
|
16085
|
+
input3 = braces.parse(input3, options2);
|
|
16381
16086
|
}
|
|
16382
|
-
let result = expand(
|
|
16087
|
+
let result = expand(input3, options2);
|
|
16383
16088
|
if (options2.noempty === true) {
|
|
16384
16089
|
result = result.filter(Boolean);
|
|
16385
16090
|
}
|
|
@@ -16388,11 +16093,11 @@ var require_braces = __commonJS((exports, module) => {
|
|
|
16388
16093
|
}
|
|
16389
16094
|
return result;
|
|
16390
16095
|
};
|
|
16391
|
-
braces.create = (
|
|
16392
|
-
if (
|
|
16393
|
-
return [
|
|
16096
|
+
braces.create = (input3, options2 = {}) => {
|
|
16097
|
+
if (input3 === "" || input3.length < 3) {
|
|
16098
|
+
return [input3];
|
|
16394
16099
|
}
|
|
16395
|
-
return options2.expand !== true ? braces.compile(
|
|
16100
|
+
return options2.expand !== true ? braces.compile(input3, options2) : braces.expand(input3, options2);
|
|
16396
16101
|
};
|
|
16397
16102
|
module.exports = braces;
|
|
16398
16103
|
});
|
|
@@ -16570,26 +16275,26 @@ var require_utils2 = __commonJS((exports) => {
|
|
|
16570
16275
|
}
|
|
16571
16276
|
return win32 === true || path.sep === "\\";
|
|
16572
16277
|
};
|
|
16573
|
-
exports.escapeLast = (
|
|
16574
|
-
const idx =
|
|
16278
|
+
exports.escapeLast = (input3, char, lastIdx) => {
|
|
16279
|
+
const idx = input3.lastIndexOf(char, lastIdx);
|
|
16575
16280
|
if (idx === -1)
|
|
16576
|
-
return
|
|
16577
|
-
if (
|
|
16578
|
-
return exports.escapeLast(
|
|
16579
|
-
return `${
|
|
16281
|
+
return input3;
|
|
16282
|
+
if (input3[idx - 1] === "\\")
|
|
16283
|
+
return exports.escapeLast(input3, char, idx - 1);
|
|
16284
|
+
return `${input3.slice(0, idx)}\\${input3.slice(idx)}`;
|
|
16580
16285
|
};
|
|
16581
|
-
exports.removePrefix = (
|
|
16582
|
-
let output =
|
|
16286
|
+
exports.removePrefix = (input3, state = {}) => {
|
|
16287
|
+
let output = input3;
|
|
16583
16288
|
if (output.startsWith("./")) {
|
|
16584
16289
|
output = output.slice(2);
|
|
16585
16290
|
state.prefix = "./";
|
|
16586
16291
|
}
|
|
16587
16292
|
return output;
|
|
16588
16293
|
};
|
|
16589
|
-
exports.wrapOutput = (
|
|
16294
|
+
exports.wrapOutput = (input3, state = {}, options2 = {}) => {
|
|
16590
16295
|
const prepend = options2.contains ? "" : "^";
|
|
16591
16296
|
const append = options2.contains ? "" : "$";
|
|
16592
|
-
let output = `${prepend}(?:${
|
|
16297
|
+
let output = `${prepend}(?:${input3})${append}`;
|
|
16593
16298
|
if (state.negated === true) {
|
|
16594
16299
|
output = `(?:^(?!${output}).*$)`;
|
|
16595
16300
|
}
|
|
@@ -16625,14 +16330,14 @@ var require_scan = __commonJS((exports, module) => {
|
|
|
16625
16330
|
token.depth = token.isGlobstar ? Infinity : 1;
|
|
16626
16331
|
}
|
|
16627
16332
|
};
|
|
16628
|
-
var scan = (
|
|
16333
|
+
var scan = (input3, options2) => {
|
|
16629
16334
|
const opts = options2 || {};
|
|
16630
|
-
const length =
|
|
16335
|
+
const length = input3.length - 1;
|
|
16631
16336
|
const scanToEnd = opts.parts === true || opts.scanToEnd === true;
|
|
16632
16337
|
const slashes = [];
|
|
16633
16338
|
const tokens = [];
|
|
16634
16339
|
const parts = [];
|
|
16635
|
-
let str =
|
|
16340
|
+
let str = input3;
|
|
16636
16341
|
let index = -1;
|
|
16637
16342
|
let start = 0;
|
|
16638
16343
|
let lastIndex = 0;
|
|
@@ -16855,7 +16560,7 @@ var require_scan = __commonJS((exports, module) => {
|
|
|
16855
16560
|
}
|
|
16856
16561
|
const state = {
|
|
16857
16562
|
prefix,
|
|
16858
|
-
input:
|
|
16563
|
+
input: input3,
|
|
16859
16564
|
start,
|
|
16860
16565
|
base,
|
|
16861
16566
|
glob,
|
|
@@ -16879,7 +16584,7 @@ var require_scan = __commonJS((exports, module) => {
|
|
|
16879
16584
|
for (let idx = 0;idx < slashes.length; idx++) {
|
|
16880
16585
|
const n = prevIndex ? prevIndex + 1 : start;
|
|
16881
16586
|
const i = slashes[idx];
|
|
16882
|
-
const value =
|
|
16587
|
+
const value = input3.slice(n, i);
|
|
16883
16588
|
if (opts.tokens) {
|
|
16884
16589
|
if (idx === 0 && start !== 0) {
|
|
16885
16590
|
tokens[idx].isPrefix = true;
|
|
@@ -16895,8 +16600,8 @@ var require_scan = __commonJS((exports, module) => {
|
|
|
16895
16600
|
}
|
|
16896
16601
|
prevIndex = i;
|
|
16897
16602
|
}
|
|
16898
|
-
if (prevIndex && prevIndex + 1 <
|
|
16899
|
-
const value =
|
|
16603
|
+
if (prevIndex && prevIndex + 1 < input3.length) {
|
|
16604
|
+
const value = input3.slice(prevIndex + 1);
|
|
16900
16605
|
parts.push(value);
|
|
16901
16606
|
if (opts.tokens) {
|
|
16902
16607
|
tokens[tokens.length - 1].value = value;
|
|
@@ -16939,14 +16644,14 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
16939
16644
|
var syntaxError = (type, char) => {
|
|
16940
16645
|
return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
|
|
16941
16646
|
};
|
|
16942
|
-
var parse2 = (
|
|
16943
|
-
if (typeof
|
|
16647
|
+
var parse2 = (input3, options2) => {
|
|
16648
|
+
if (typeof input3 !== "string") {
|
|
16944
16649
|
throw new TypeError("Expected a string");
|
|
16945
16650
|
}
|
|
16946
|
-
|
|
16651
|
+
input3 = REPLACEMENTS[input3] || input3;
|
|
16947
16652
|
const opts = { ...options2 };
|
|
16948
16653
|
const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
|
16949
|
-
let len =
|
|
16654
|
+
let len = input3.length;
|
|
16950
16655
|
if (len > max) {
|
|
16951
16656
|
throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
|
|
16952
16657
|
}
|
|
@@ -16983,7 +16688,7 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
16983
16688
|
opts.noextglob = opts.noext;
|
|
16984
16689
|
}
|
|
16985
16690
|
const state = {
|
|
16986
|
-
input:
|
|
16691
|
+
input: input3,
|
|
16987
16692
|
index: -1,
|
|
16988
16693
|
start: 0,
|
|
16989
16694
|
dot: opts.dot === true,
|
|
@@ -16999,17 +16704,17 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
16999
16704
|
globstar: false,
|
|
17000
16705
|
tokens
|
|
17001
16706
|
};
|
|
17002
|
-
|
|
17003
|
-
len =
|
|
16707
|
+
input3 = utils.removePrefix(input3, state);
|
|
16708
|
+
len = input3.length;
|
|
17004
16709
|
const extglobs = [];
|
|
17005
16710
|
const braces = [];
|
|
17006
16711
|
const stack = [];
|
|
17007
16712
|
let prev = bos;
|
|
17008
16713
|
let value;
|
|
17009
16714
|
const eos = () => state.index === len - 1;
|
|
17010
|
-
const peek = state.peek = (n = 1) =>
|
|
17011
|
-
const advance = state.advance = () =>
|
|
17012
|
-
const remaining = () =>
|
|
16715
|
+
const peek = state.peek = (n = 1) => input3[state.index + n];
|
|
16716
|
+
const advance = state.advance = () => input3[++state.index] || "";
|
|
16717
|
+
const remaining = () => input3.slice(state.index + 1);
|
|
17013
16718
|
const consume = (value2 = "", num = 0) => {
|
|
17014
16719
|
state.consumed += value2;
|
|
17015
16720
|
state.index += num;
|
|
@@ -17099,9 +16804,9 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17099
16804
|
push({ type: "paren", extglob: true, value, output });
|
|
17100
16805
|
decrement("parens");
|
|
17101
16806
|
};
|
|
17102
|
-
if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(
|
|
16807
|
+
if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input3)) {
|
|
17103
16808
|
let backslashes = false;
|
|
17104
|
-
let output =
|
|
16809
|
+
let output = input3.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => {
|
|
17105
16810
|
if (first === "\\") {
|
|
17106
16811
|
backslashes = true;
|
|
17107
16812
|
return m;
|
|
@@ -17135,8 +16840,8 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17135
16840
|
});
|
|
17136
16841
|
}
|
|
17137
16842
|
}
|
|
17138
|
-
if (output ===
|
|
17139
|
-
state.output =
|
|
16843
|
+
if (output === input3 && opts.contains === true) {
|
|
16844
|
+
state.output = input3;
|
|
17140
16845
|
return state;
|
|
17141
16846
|
}
|
|
17142
16847
|
state.output = utils.wrapOutput(output, state, options2);
|
|
@@ -17495,7 +17200,7 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17495
17200
|
continue;
|
|
17496
17201
|
}
|
|
17497
17202
|
while (rest.slice(0, 3) === "/**") {
|
|
17498
|
-
const after =
|
|
17203
|
+
const after = input3[state.index + 4];
|
|
17499
17204
|
if (after && after !== "/") {
|
|
17500
17205
|
break;
|
|
17501
17206
|
}
|
|
@@ -17618,14 +17323,14 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17618
17323
|
}
|
|
17619
17324
|
return state;
|
|
17620
17325
|
};
|
|
17621
|
-
parse2.fastpaths = (
|
|
17326
|
+
parse2.fastpaths = (input3, options2) => {
|
|
17622
17327
|
const opts = { ...options2 };
|
|
17623
17328
|
const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
|
17624
|
-
const len =
|
|
17329
|
+
const len = input3.length;
|
|
17625
17330
|
if (len > max) {
|
|
17626
17331
|
throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
|
|
17627
17332
|
}
|
|
17628
|
-
|
|
17333
|
+
input3 = REPLACEMENTS[input3] || input3;
|
|
17629
17334
|
const win32 = utils.isWindows(options2);
|
|
17630
17335
|
const {
|
|
17631
17336
|
DOT_LITERAL,
|
|
@@ -17680,7 +17385,7 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17680
17385
|
}
|
|
17681
17386
|
}
|
|
17682
17387
|
};
|
|
17683
|
-
const output = utils.removePrefix(
|
|
17388
|
+
const output = utils.removePrefix(input3, state);
|
|
17684
17389
|
let source = create2(output);
|
|
17685
17390
|
if (source && opts.strictSlashes !== true) {
|
|
17686
17391
|
source += `${SLASH_LITERAL}?`;
|
|
@@ -17700,7 +17405,7 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
17700
17405
|
var isObject = (val) => val && typeof val === "object" && !Array.isArray(val);
|
|
17701
17406
|
var picomatch = (glob, options2, returnState = false) => {
|
|
17702
17407
|
if (Array.isArray(glob)) {
|
|
17703
|
-
const fns = glob.map((
|
|
17408
|
+
const fns = glob.map((input3) => picomatch(input3, options2, returnState));
|
|
17704
17409
|
const arrayMatcher = (str) => {
|
|
17705
17410
|
for (const isMatch of fns) {
|
|
17706
17411
|
const state2 = isMatch(str);
|
|
@@ -17725,9 +17430,9 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
17725
17430
|
const ignoreOpts = { ...options2, ignore: null, onMatch: null, onResult: null };
|
|
17726
17431
|
isIgnored = picomatch(opts.ignore, ignoreOpts, returnState);
|
|
17727
17432
|
}
|
|
17728
|
-
const matcher = (
|
|
17729
|
-
const { isMatch, match, output } = picomatch.test(
|
|
17730
|
-
const result = { glob, state, regex, posix, input:
|
|
17433
|
+
const matcher = (input3, returnObject = false) => {
|
|
17434
|
+
const { isMatch, match, output } = picomatch.test(input3, regex, options2, { glob, posix });
|
|
17435
|
+
const result = { glob, state, regex, posix, input: input3, output, match, isMatch };
|
|
17731
17436
|
if (typeof opts.onResult === "function") {
|
|
17732
17437
|
opts.onResult(result);
|
|
17733
17438
|
}
|
|
@@ -17735,7 +17440,7 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
17735
17440
|
result.isMatch = false;
|
|
17736
17441
|
return returnObject ? result : false;
|
|
17737
17442
|
}
|
|
17738
|
-
if (isIgnored(
|
|
17443
|
+
if (isIgnored(input3)) {
|
|
17739
17444
|
if (typeof opts.onIgnore === "function") {
|
|
17740
17445
|
opts.onIgnore(result);
|
|
17741
17446
|
}
|
|
@@ -17752,33 +17457,33 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
17752
17457
|
}
|
|
17753
17458
|
return matcher;
|
|
17754
17459
|
};
|
|
17755
|
-
picomatch.test = (
|
|
17756
|
-
if (typeof
|
|
17460
|
+
picomatch.test = (input3, regex, options2, { glob, posix } = {}) => {
|
|
17461
|
+
if (typeof input3 !== "string") {
|
|
17757
17462
|
throw new TypeError("Expected input to be a string");
|
|
17758
17463
|
}
|
|
17759
|
-
if (
|
|
17464
|
+
if (input3 === "") {
|
|
17760
17465
|
return { isMatch: false, output: "" };
|
|
17761
17466
|
}
|
|
17762
17467
|
const opts = options2 || {};
|
|
17763
17468
|
const format = opts.format || (posix ? utils.toPosixSlashes : null);
|
|
17764
|
-
let match =
|
|
17765
|
-
let output = match && format ? format(
|
|
17469
|
+
let match = input3 === glob;
|
|
17470
|
+
let output = match && format ? format(input3) : input3;
|
|
17766
17471
|
if (match === false) {
|
|
17767
|
-
output = format ? format(
|
|
17472
|
+
output = format ? format(input3) : input3;
|
|
17768
17473
|
match = output === glob;
|
|
17769
17474
|
}
|
|
17770
17475
|
if (match === false || opts.capture === true) {
|
|
17771
17476
|
if (opts.matchBase === true || opts.basename === true) {
|
|
17772
|
-
match = picomatch.matchBase(
|
|
17477
|
+
match = picomatch.matchBase(input3, regex, options2, posix);
|
|
17773
17478
|
} else {
|
|
17774
17479
|
match = regex.exec(output);
|
|
17775
17480
|
}
|
|
17776
17481
|
}
|
|
17777
17482
|
return { isMatch: Boolean(match), match, output };
|
|
17778
17483
|
};
|
|
17779
|
-
picomatch.matchBase = (
|
|
17484
|
+
picomatch.matchBase = (input3, glob, options2, posix = utils.isWindows(options2)) => {
|
|
17780
17485
|
const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options2);
|
|
17781
|
-
return regex.test(path.basename(
|
|
17486
|
+
return regex.test(path.basename(input3));
|
|
17782
17487
|
};
|
|
17783
17488
|
picomatch.isMatch = (str, patterns, options2) => picomatch(patterns, options2)(str);
|
|
17784
17489
|
picomatch.parse = (pattern, options2) => {
|
|
@@ -17786,7 +17491,7 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
17786
17491
|
return pattern.map((p) => picomatch.parse(p, options2));
|
|
17787
17492
|
return parse2(pattern, { ...options2, fastpaths: false });
|
|
17788
17493
|
};
|
|
17789
|
-
picomatch.scan = (
|
|
17494
|
+
picomatch.scan = (input3, options2) => scan(input3, options2);
|
|
17790
17495
|
picomatch.compileRe = (state, options2, returnOutput = false, returnState = false) => {
|
|
17791
17496
|
if (returnOutput === true) {
|
|
17792
17497
|
return state.output;
|
|
@@ -17804,16 +17509,16 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
17804
17509
|
}
|
|
17805
17510
|
return regex;
|
|
17806
17511
|
};
|
|
17807
|
-
picomatch.makeRe = (
|
|
17808
|
-
if (!
|
|
17512
|
+
picomatch.makeRe = (input3, options2 = {}, returnOutput = false, returnState = false) => {
|
|
17513
|
+
if (!input3 || typeof input3 !== "string") {
|
|
17809
17514
|
throw new TypeError("Expected a non-empty string");
|
|
17810
17515
|
}
|
|
17811
17516
|
let parsed = { negated: false, fastpaths: true };
|
|
17812
|
-
if (options2.fastpaths !== false && (
|
|
17813
|
-
parsed.output = parse2.fastpaths(
|
|
17517
|
+
if (options2.fastpaths !== false && (input3[0] === "." || input3[0] === "*")) {
|
|
17518
|
+
parsed.output = parse2.fastpaths(input3, options2);
|
|
17814
17519
|
}
|
|
17815
17520
|
if (!parsed.output) {
|
|
17816
|
-
parsed = parse2(
|
|
17521
|
+
parsed = parse2(input3, options2);
|
|
17817
17522
|
}
|
|
17818
17523
|
return picomatch.compileRe(parsed, options2, returnOutput, returnState);
|
|
17819
17524
|
};
|
|
@@ -17959,10 +17664,10 @@ var require_micromatch = __commonJS((exports, module) => {
|
|
|
17959
17664
|
}
|
|
17960
17665
|
return [].concat(patterns).every((p) => picomatch(p, options2)(str));
|
|
17961
17666
|
};
|
|
17962
|
-
micromatch.capture = (glob,
|
|
17667
|
+
micromatch.capture = (glob, input3, options2) => {
|
|
17963
17668
|
let posix = utils.isWindows(options2);
|
|
17964
17669
|
let regex = picomatch.makeRe(String(glob), { ...options2, capture: true });
|
|
17965
|
-
let match = regex.exec(posix ? utils.toPosixSlashes(
|
|
17670
|
+
let match = regex.exec(posix ? utils.toPosixSlashes(input3) : input3);
|
|
17966
17671
|
if (match) {
|
|
17967
17672
|
return match.slice(1).map((v) => v === undefined ? "" : v);
|
|
17968
17673
|
}
|
|
@@ -18297,12 +18002,12 @@ var require_stream = __commonJS((exports) => {
|
|
|
18297
18002
|
var require_string = __commonJS((exports) => {
|
|
18298
18003
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18299
18004
|
exports.isEmpty = exports.isString = undefined;
|
|
18300
|
-
function isString(
|
|
18301
|
-
return typeof
|
|
18005
|
+
function isString(input3) {
|
|
18006
|
+
return typeof input3 === "string";
|
|
18302
18007
|
}
|
|
18303
18008
|
exports.isString = isString;
|
|
18304
|
-
function isEmpty(
|
|
18305
|
-
return
|
|
18009
|
+
function isEmpty(input3) {
|
|
18010
|
+
return input3 === "";
|
|
18306
18011
|
}
|
|
18307
18012
|
exports.isEmpty = isEmpty;
|
|
18308
18013
|
});
|
|
@@ -18332,8 +18037,8 @@ var require_tasks = __commonJS((exports) => {
|
|
|
18332
18037
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18333
18038
|
exports.convertPatternGroupToTask = exports.convertPatternGroupsToTasks = exports.groupPatternsByBaseDirectory = exports.getNegativePatternsAsPositive = exports.getPositivePatterns = exports.convertPatternsToTasks = exports.generate = undefined;
|
|
18334
18039
|
var utils = require_utils3();
|
|
18335
|
-
function generate(
|
|
18336
|
-
const patterns = processPatterns(
|
|
18040
|
+
function generate(input3, settings) {
|
|
18041
|
+
const patterns = processPatterns(input3, settings);
|
|
18337
18042
|
const ignore = processPatterns(settings.ignore, settings);
|
|
18338
18043
|
const positivePatterns = getPositivePatterns(patterns);
|
|
18339
18044
|
const negativePatterns = getNegativePatternsAsPositive(patterns, ignore);
|
|
@@ -18344,8 +18049,8 @@ var require_tasks = __commonJS((exports) => {
|
|
|
18344
18049
|
return staticTasks.concat(dynamicTasks);
|
|
18345
18050
|
}
|
|
18346
18051
|
exports.generate = generate;
|
|
18347
|
-
function processPatterns(
|
|
18348
|
-
let patterns =
|
|
18052
|
+
function processPatterns(input3, settings) {
|
|
18053
|
+
let patterns = input3;
|
|
18349
18054
|
if (settings.braceExpansion) {
|
|
18350
18055
|
patterns = utils.pattern.expandPatternsWithBraceExpansion(patterns);
|
|
18351
18056
|
}
|
|
@@ -20301,8 +20006,8 @@ var require_out4 = __commonJS((exports, module) => {
|
|
|
20301
20006
|
const provider = new _Provider(settings);
|
|
20302
20007
|
return tasks.map(provider.read, provider);
|
|
20303
20008
|
}
|
|
20304
|
-
function assertPatternsInput(
|
|
20305
|
-
const source = [].concat(
|
|
20009
|
+
function assertPatternsInput(input3) {
|
|
20010
|
+
const source = [].concat(input3);
|
|
20306
20011
|
const isValidSource = source.every((item) => utils.string.isString(item) && !utils.string.isEmpty(item));
|
|
20307
20012
|
if (!isValidSource) {
|
|
20308
20013
|
throw new TypeError("Patterns must be a string (non empty) or an array of strings");
|
|
@@ -22148,7 +21853,7 @@ var init_commands = __esm(() => {
|
|
|
22148
21853
|
});
|
|
22149
21854
|
|
|
22150
21855
|
// ../../node_modules/@antfu/ni/dist/shared/ni.B5qNAuoI.mjs
|
|
22151
|
-
import path3, { join as
|
|
21856
|
+
import path3, { join as join5, dirname as dirname6, resolve as resolve8 } from "node:path";
|
|
22152
21857
|
import process$1 from "node:process";
|
|
22153
21858
|
import require$$0 from "readline";
|
|
22154
21859
|
import require$$2 from "events";
|
|
@@ -22670,10 +22375,10 @@ function requireStyle() {
|
|
|
22670
22375
|
const c2 = requireKleur();
|
|
22671
22376
|
const figures = requireFigures();
|
|
22672
22377
|
const styles3 = Object.freeze({
|
|
22673
|
-
password: { scale: 1, render: (
|
|
22674
|
-
emoji: { scale: 2, render: (
|
|
22675
|
-
invisible: { scale: 0, render: (
|
|
22676
|
-
default: { scale: 1, render: (
|
|
22378
|
+
password: { scale: 1, render: (input3) => "*".repeat(input3.length) },
|
|
22379
|
+
emoji: { scale: 2, render: (input3) => "\uD83D\uDE03".repeat(input3.length) },
|
|
22380
|
+
invisible: { scale: 0, render: (input3) => "" },
|
|
22381
|
+
default: { scale: 1, render: (input3) => `${input3}` }
|
|
22677
22382
|
});
|
|
22678
22383
|
const render = (type) => styles3[type] || styles3.default;
|
|
22679
22384
|
const symbols = Object.freeze({
|
|
@@ -23013,7 +22718,7 @@ ${i2 ? " " : figures.pointerSmall} ${color.red().italic(l2)}`, ``);
|
|
|
23013
22718
|
}
|
|
23014
22719
|
function requireSelect() {
|
|
23015
22720
|
if (hasRequiredSelect)
|
|
23016
|
-
return
|
|
22721
|
+
return select3;
|
|
23017
22722
|
hasRequiredSelect = 1;
|
|
23018
22723
|
const color = requireKleur();
|
|
23019
22724
|
const Prompt = requirePrompt();
|
|
@@ -23159,8 +22864,8 @@ function requireSelect() {
|
|
|
23159
22864
|
this.out.write(this.outputText);
|
|
23160
22865
|
}
|
|
23161
22866
|
}
|
|
23162
|
-
|
|
23163
|
-
return
|
|
22867
|
+
select3 = SelectPrompt;
|
|
22868
|
+
return select3;
|
|
23164
22869
|
}
|
|
23165
22870
|
function requireToggle() {
|
|
23166
22871
|
if (hasRequiredToggle)
|
|
@@ -24532,7 +24237,7 @@ Filtered results for: ${this.inputValue ? this.inputValue : color.gray("Enter so
|
|
|
24532
24237
|
}
|
|
24533
24238
|
function requireConfirm() {
|
|
24534
24239
|
if (hasRequiredConfirm)
|
|
24535
|
-
return
|
|
24240
|
+
return confirm5;
|
|
24536
24241
|
hasRequiredConfirm = 1;
|
|
24537
24242
|
const color = requireKleur();
|
|
24538
24243
|
const Prompt = requirePrompt();
|
|
@@ -24605,8 +24310,8 @@ function requireConfirm() {
|
|
|
24605
24310
|
this.out.write(erase.line + cursor.to(0) + this.outputText);
|
|
24606
24311
|
}
|
|
24607
24312
|
}
|
|
24608
|
-
|
|
24609
|
-
return
|
|
24313
|
+
confirm5 = ConfirmPrompt;
|
|
24314
|
+
return confirm5;
|
|
24610
24315
|
}
|
|
24611
24316
|
function requireElements() {
|
|
24612
24317
|
if (hasRequiredElements)
|
|
@@ -24681,7 +24386,7 @@ function requirePrompts$1() {
|
|
|
24681
24386
|
onSubmit: toSelected
|
|
24682
24387
|
});
|
|
24683
24388
|
};
|
|
24684
|
-
const byTitle = (
|
|
24389
|
+
const byTitle = (input3, choices) => Promise.resolve(choices.filter((item) => item.title.slice(0, input3.length).toLowerCase() === input3.toLowerCase()));
|
|
24685
24390
|
$.autocomplete = (args) => {
|
|
24686
24391
|
args.suggest = args.suggest || byTitle;
|
|
24687
24392
|
args.choices = [].concat(args.choices || []);
|
|
@@ -25163,7 +24868,7 @@ function requireLib() {
|
|
|
25163
24868
|
return lib;
|
|
25164
24869
|
hasRequiredLib = 1;
|
|
25165
24870
|
const { isexe, sync: isexeSync } = requireCjs();
|
|
25166
|
-
const { join:
|
|
24871
|
+
const { join: join6, delimiter, sep, posix: posix2 } = require$$1$2;
|
|
25167
24872
|
const isWindows = process.platform === "win32";
|
|
25168
24873
|
const rSlash = new RegExp(`[${posix2.sep}${sep === posix2.sep ? "" : sep}]`.replace(/(\\)/g, "\\$1"));
|
|
25169
24874
|
const rRel = new RegExp(`^\\.${rSlash.source}`);
|
|
@@ -25190,7 +24895,7 @@ function requireLib() {
|
|
|
25190
24895
|
const getPathPart = (raw, cmd) => {
|
|
25191
24896
|
const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
|
|
25192
24897
|
const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
|
|
25193
|
-
return prefix +
|
|
24898
|
+
return prefix + join6(pathPart, cmd);
|
|
25194
24899
|
};
|
|
25195
24900
|
const which = async (cmd, opt = {}) => {
|
|
25196
24901
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
@@ -25286,7 +24991,7 @@ async function detect2({ autoInstall, programmatic, cwd } = {}) {
|
|
|
25286
24991
|
}
|
|
25287
24992
|
return agent;
|
|
25288
24993
|
}
|
|
25289
|
-
var ini$1, hasRequiredIni, iniExports, prompts$2, kleur, hasRequiredKleur, action, hasRequiredAction, strip, hasRequiredStrip, src, hasRequiredSrc, clear, hasRequiredClear, figures_1, hasRequiredFigures, style, hasRequiredStyle, lines, hasRequiredLines, wrap, hasRequiredWrap, entriesToDisplay, hasRequiredEntriesToDisplay, util, hasRequiredUtil, prompt, hasRequiredPrompt, text, hasRequiredText,
|
|
24994
|
+
var ini$1, hasRequiredIni, iniExports, prompts$2, kleur, hasRequiredKleur, action, hasRequiredAction, strip, hasRequiredStrip, src, hasRequiredSrc, clear, hasRequiredClear, figures_1, hasRequiredFigures, style, hasRequiredStyle, lines, hasRequiredLines, wrap, hasRequiredWrap, entriesToDisplay, hasRequiredEntriesToDisplay, util, hasRequiredUtil, prompt, hasRequiredPrompt, text, hasRequiredText, select3, hasRequiredSelect, toggle, hasRequiredToggle, datepart, hasRequiredDatepart, meridiem, hasRequiredMeridiem, day, hasRequiredDay, hours, hasRequiredHours, milliseconds, hasRequiredMilliseconds, minutes, hasRequiredMinutes, month, hasRequiredMonth, seconds, hasRequiredSeconds, year, hasRequiredYear, dateparts, hasRequiredDateparts, date, hasRequiredDate, number, hasRequiredNumber, multiselect, hasRequiredMultiselect, autocomplete, hasRequiredAutocomplete, autocompleteMultiselect, hasRequiredAutocompleteMultiselect, confirm5, hasRequiredConfirm, elements, hasRequiredElements, hasRequiredPrompts$1, lib$1, hasRequiredLib$1, prompts$1, hasRequiredPrompts, promptsExports, prompts, isBrowser, platform, OSC = "\x1B]", BEL = "\x07", SEP = ";", link = (text2, url) => [
|
|
25290
24995
|
OSC,
|
|
25291
24996
|
"8",
|
|
25292
24997
|
SEP,
|
|
@@ -25339,7 +25044,7 @@ var init_ni_B5qNAuoI = __esm(() => {
|
|
|
25339
25044
|
options2 = {};
|
|
25340
25045
|
libExports = requireLib();
|
|
25341
25046
|
which = /* @__PURE__ */ getDefaultExportFromCjs(libExports);
|
|
25342
|
-
CLI_TEMP_DIR =
|
|
25047
|
+
CLI_TEMP_DIR = join5(os4.tmpdir(), "antfu-ni");
|
|
25343
25048
|
customRcPath = process$1.env.NI_CONFIG_FILE;
|
|
25344
25049
|
home = process$1.platform === "win32" ? process$1.env.USERPROFILE : process$1.env.HOME;
|
|
25345
25050
|
defaultRcPath = path3.join(home || "~/", ".nirc");
|
|
@@ -25970,12 +25675,12 @@ var init_figures = __esm(() => {
|
|
|
25970
25675
|
import tty2 from "node:tty";
|
|
25971
25676
|
var hasColors, format = (open, close) => {
|
|
25972
25677
|
if (!hasColors) {
|
|
25973
|
-
return (
|
|
25678
|
+
return (input3) => input3;
|
|
25974
25679
|
}
|
|
25975
25680
|
const openCode = `\x1B[${open}m`;
|
|
25976
25681
|
const closeCode = `\x1B[${close}m`;
|
|
25977
|
-
return (
|
|
25978
|
-
const string =
|
|
25682
|
+
return (input3) => {
|
|
25683
|
+
const string = input3 + "";
|
|
25979
25684
|
let index = string.indexOf(closeCode);
|
|
25980
25685
|
if (index === -1) {
|
|
25981
25686
|
return openCode + string + closeCode;
|
|
@@ -28084,16 +27789,16 @@ var init_options2 = __esm(() => {
|
|
|
28084
27789
|
var concatenateShell = (file, commandArguments, options3) => options3.shell && commandArguments.length > 0 ? [[file, ...commandArguments].join(" "), [], options3] : [file, commandArguments, options3];
|
|
28085
27790
|
|
|
28086
27791
|
// ../../node_modules/strip-final-newline/index.js
|
|
28087
|
-
function stripFinalNewline(
|
|
28088
|
-
if (typeof
|
|
28089
|
-
return stripFinalNewlineString(
|
|
27792
|
+
function stripFinalNewline(input3) {
|
|
27793
|
+
if (typeof input3 === "string") {
|
|
27794
|
+
return stripFinalNewlineString(input3);
|
|
28090
27795
|
}
|
|
28091
|
-
if (!(ArrayBuffer.isView(
|
|
27796
|
+
if (!(ArrayBuffer.isView(input3) && input3.BYTES_PER_ELEMENT === 1)) {
|
|
28092
27797
|
throw new Error("Input must be a string or a Uint8Array");
|
|
28093
27798
|
}
|
|
28094
|
-
return stripFinalNewlineBinary(
|
|
27799
|
+
return stripFinalNewlineBinary(input3);
|
|
28095
27800
|
}
|
|
28096
|
-
var stripFinalNewlineString = (
|
|
27801
|
+
var stripFinalNewlineString = (input3) => input3.at(-1) === LF ? input3.slice(0, input3.at(-2) === CR ? -2 : -1) : input3, stripFinalNewlineBinary = (input3) => input3.at(-1) === LF_BINARY ? input3.subarray(0, input3.at(-2) === CR_BINARY ? -2 : -1) : input3, LF = `
|
|
28097
27802
|
`, LF_BINARY, CR = "\r", CR_BINARY;
|
|
28098
27803
|
var init_strip_final_newline = __esm(() => {
|
|
28099
27804
|
LF_BINARY = LF.codePointAt(0);
|
|
@@ -29132,21 +28837,21 @@ var init_native = __esm(() => {
|
|
|
29132
28837
|
});
|
|
29133
28838
|
|
|
29134
28839
|
// ../../node_modules/execa/lib/stdio/input-option.js
|
|
29135
|
-
var handleInputOptions = ({ input:
|
|
29136
|
-
...handleInputOption(
|
|
28840
|
+
var handleInputOptions = ({ input: input3, inputFile }, fdNumber) => fdNumber === 0 ? [
|
|
28841
|
+
...handleInputOption(input3),
|
|
29137
28842
|
...handleInputFileOption(inputFile)
|
|
29138
|
-
] : [], handleInputOption = (
|
|
29139
|
-
type: getInputType(
|
|
29140
|
-
value:
|
|
28843
|
+
] : [], handleInputOption = (input3) => input3 === undefined ? [] : [{
|
|
28844
|
+
type: getInputType(input3),
|
|
28845
|
+
value: input3,
|
|
29141
28846
|
optionName: "input"
|
|
29142
|
-
}], getInputType = (
|
|
29143
|
-
if (isReadableStream(
|
|
28847
|
+
}], getInputType = (input3) => {
|
|
28848
|
+
if (isReadableStream(input3, { checkOpen: false })) {
|
|
29144
28849
|
return "nodeStream";
|
|
29145
28850
|
}
|
|
29146
|
-
if (typeof
|
|
28851
|
+
if (typeof input3 === "string") {
|
|
29147
28852
|
return "string";
|
|
29148
28853
|
}
|
|
29149
|
-
if (isUint8Array(
|
|
28854
|
+
if (isUint8Array(input3)) {
|
|
29150
28855
|
return "uint8Array";
|
|
29151
28856
|
}
|
|
29152
28857
|
throw new Error("The `input` option must be a string, a Uint8Array or a Node.js Readable stream.");
|
|
@@ -32262,7 +31967,7 @@ var init_command2 = __esm(() => {
|
|
|
32262
31967
|
var setScriptSync = (boundExeca, createNested, boundOptions) => {
|
|
32263
31968
|
boundExeca.sync = createNested(mapScriptSync, boundOptions);
|
|
32264
31969
|
boundExeca.s = boundExeca.sync;
|
|
32265
|
-
}, mapScriptAsync = ({ options: options3 }) => getScriptOptions(options3), mapScriptSync = ({ options: options3 }) => ({ ...getScriptOptions(options3), isSync: true }), getScriptOptions = (options3) => ({ options: { ...getScriptStdinOption(options3), ...options3 } }), getScriptStdinOption = ({ input:
|
|
31970
|
+
}, mapScriptAsync = ({ options: options3 }) => getScriptOptions(options3), mapScriptSync = ({ options: options3 }) => ({ ...getScriptOptions(options3), isSync: true }), getScriptOptions = (options3) => ({ options: { ...getScriptStdinOption(options3), ...options3 } }), getScriptStdinOption = ({ input: input3, inputFile, stdio }) => input3 === undefined && inputFile === undefined && stdio === undefined ? { stdin: "inherit" } : {}, deepScriptOptions;
|
|
32266
31971
|
var init_script = __esm(() => {
|
|
32267
31972
|
deepScriptOptions = { preferLocal: true };
|
|
32268
31973
|
});
|
|
@@ -32373,20 +32078,20 @@ __export(exports_generate, {
|
|
|
32373
32078
|
import path10 from "path";
|
|
32374
32079
|
import { getErrorMessage as getErrorMessage2 } from "@secondlayer/shared";
|
|
32375
32080
|
import { toCamelCase as toCamelCase8 } from "@secondlayer/stacks/clarity";
|
|
32376
|
-
function isContractAddress(
|
|
32081
|
+
function isContractAddress(input3) {
|
|
32377
32082
|
const contractIdPattern = /^(SP|ST|SM|SN)[A-Z0-9]{38,}\.[a-zA-Z][a-zA-Z0-9-]*$/;
|
|
32378
|
-
return contractIdPattern.test(
|
|
32083
|
+
return contractIdPattern.test(input3);
|
|
32379
32084
|
}
|
|
32380
32085
|
async function parseInputs(inputs) {
|
|
32381
32086
|
const files = [];
|
|
32382
32087
|
const contractIds = [];
|
|
32383
|
-
for (const
|
|
32384
|
-
if (isContractAddress(
|
|
32385
|
-
contractIds.push(
|
|
32088
|
+
for (const input3 of inputs) {
|
|
32089
|
+
if (isContractAddress(input3)) {
|
|
32090
|
+
contractIds.push(input3);
|
|
32386
32091
|
continue;
|
|
32387
32092
|
}
|
|
32388
|
-
if (
|
|
32389
|
-
const matches = await import_fast_glob.default(
|
|
32093
|
+
if (input3.includes("*") || input3.includes("?")) {
|
|
32094
|
+
const matches = await import_fast_glob.default(input3, { cwd: process.cwd(), absolute: true });
|
|
32390
32095
|
for (const file of matches) {
|
|
32391
32096
|
if (file.endsWith(".clar")) {
|
|
32392
32097
|
files.push(file);
|
|
@@ -32394,8 +32099,8 @@ async function parseInputs(inputs) {
|
|
|
32394
32099
|
}
|
|
32395
32100
|
continue;
|
|
32396
32101
|
}
|
|
32397
|
-
if (
|
|
32398
|
-
const absolutePath = path10.resolve(process.cwd(),
|
|
32102
|
+
if (input3.endsWith(".clar")) {
|
|
32103
|
+
const absolutePath = path10.resolve(process.cwd(), input3);
|
|
32399
32104
|
files.push(absolutePath);
|
|
32400
32105
|
}
|
|
32401
32106
|
}
|
|
@@ -32678,8 +32383,8 @@ var {
|
|
|
32678
32383
|
// package.json
|
|
32679
32384
|
var package_default = {
|
|
32680
32385
|
name: "@secondlayer/cli",
|
|
32681
|
-
version: "
|
|
32682
|
-
description: "CLI for
|
|
32386
|
+
version: "2.0.0",
|
|
32387
|
+
description: "CLI for subgraphs and blockchain indexing on Stacks",
|
|
32683
32388
|
type: "module",
|
|
32684
32389
|
bin: {
|
|
32685
32390
|
secondlayer: "./dist/cli.js",
|
|
@@ -32719,11 +32424,12 @@ var package_default = {
|
|
|
32719
32424
|
license: "MIT",
|
|
32720
32425
|
dependencies: {
|
|
32721
32426
|
"@inquirer/prompts": "^8.2.0",
|
|
32722
|
-
"@secondlayer/
|
|
32723
|
-
"@secondlayer/
|
|
32427
|
+
"@secondlayer/bundler": "^0.2.0",
|
|
32428
|
+
"@secondlayer/sdk": "^1.0.0",
|
|
32429
|
+
"@secondlayer/shared": "^1.0.0",
|
|
32724
32430
|
"@secondlayer/stacks": "^0.2.2",
|
|
32725
|
-
"@secondlayer/subgraphs": "^0.11.
|
|
32726
|
-
"@secondlayer/workflows": "^0.0
|
|
32431
|
+
"@secondlayer/subgraphs": "^0.11.6",
|
|
32432
|
+
"@secondlayer/workflows": "^1.0.0",
|
|
32727
32433
|
"@biomejs/js-api": "^0.7.0",
|
|
32728
32434
|
"@biomejs/wasm-nodejs": "^1.9.0",
|
|
32729
32435
|
esbuild: "^0.19.0",
|
|
@@ -32749,46 +32455,42 @@ init_api_client();
|
|
|
32749
32455
|
init_output();
|
|
32750
32456
|
function registerAccountCommand(program2) {
|
|
32751
32457
|
const account = program2.command("account").description("Manage your account profile");
|
|
32752
|
-
account.command("profile").description("View or update your public profile").option("--name <name>", "Set display name").option("--bio <bio>", "Set bio").option("--slug <slug>", "Set public URL slug").option("--json", "Output as JSON").action(async (options) => {
|
|
32753
|
-
|
|
32754
|
-
|
|
32755
|
-
|
|
32756
|
-
|
|
32757
|
-
|
|
32758
|
-
|
|
32759
|
-
|
|
32760
|
-
|
|
32761
|
-
|
|
32762
|
-
|
|
32763
|
-
const updated = await updateAccountProfile(data);
|
|
32764
|
-
if (options.json) {
|
|
32765
|
-
console.log(JSON.stringify(updated, null, 2));
|
|
32766
|
-
return;
|
|
32767
|
-
}
|
|
32768
|
-
success("Profile updated");
|
|
32769
|
-
console.log(formatKeyValue([
|
|
32770
|
-
["Display Name", updated.displayName ?? dim("—")],
|
|
32771
|
-
["Bio", updated.bio ?? dim("—")],
|
|
32772
|
-
["Slug", updated.slug ?? dim("—")]
|
|
32773
|
-
]));
|
|
32774
|
-
return;
|
|
32775
|
-
}
|
|
32776
|
-
const profile = await getAccountProfile();
|
|
32458
|
+
account.command("profile").description("View or update your public profile").option("--name <name>", "Set display name").option("--bio <bio>", "Set bio").option("--slug <slug>", "Set public URL slug").option("--json", "Output as JSON").action(withErrorHandling(async (options) => {
|
|
32459
|
+
const hasUpdates = options.name || options.bio || options.slug;
|
|
32460
|
+
if (hasUpdates) {
|
|
32461
|
+
const data = {};
|
|
32462
|
+
if (options.name)
|
|
32463
|
+
data.display_name = options.name;
|
|
32464
|
+
if (options.bio)
|
|
32465
|
+
data.bio = options.bio;
|
|
32466
|
+
if (options.slug)
|
|
32467
|
+
data.slug = options.slug;
|
|
32468
|
+
const updated = await updateAccountProfile(data);
|
|
32777
32469
|
if (options.json) {
|
|
32778
|
-
console.log(JSON.stringify(
|
|
32470
|
+
console.log(JSON.stringify(updated, null, 2));
|
|
32779
32471
|
return;
|
|
32780
32472
|
}
|
|
32473
|
+
success("Profile updated");
|
|
32781
32474
|
console.log(formatKeyValue([
|
|
32782
|
-
["
|
|
32783
|
-
["
|
|
32784
|
-
["
|
|
32785
|
-
["Bio", profile.bio ?? dim("—")],
|
|
32786
|
-
["Slug", profile.slug ?? dim("—")]
|
|
32475
|
+
["Display Name", updated.displayName ?? dim("—")],
|
|
32476
|
+
["Bio", updated.bio ?? dim("—")],
|
|
32477
|
+
["Slug", updated.slug ?? dim("—")]
|
|
32787
32478
|
]));
|
|
32788
|
-
|
|
32789
|
-
handleApiError(err, "manage profile");
|
|
32479
|
+
return;
|
|
32790
32480
|
}
|
|
32791
|
-
|
|
32481
|
+
const profile = await getAccountProfile();
|
|
32482
|
+
if (options.json) {
|
|
32483
|
+
console.log(JSON.stringify(profile, null, 2));
|
|
32484
|
+
return;
|
|
32485
|
+
}
|
|
32486
|
+
console.log(formatKeyValue([
|
|
32487
|
+
["Email", profile.email],
|
|
32488
|
+
["Plan", profile.plan],
|
|
32489
|
+
["Display Name", profile.displayName ?? dim("—")],
|
|
32490
|
+
["Bio", profile.bio ?? dim("—")],
|
|
32491
|
+
["Slug", profile.slug ?? dim("—")]
|
|
32492
|
+
]));
|
|
32493
|
+
}, { action: "manage profile" }));
|
|
32792
32494
|
}
|
|
32793
32495
|
// src/commands/config.ts
|
|
32794
32496
|
init_config();
|
|
@@ -33117,7 +32819,6 @@ async function printConfigTree(cfg) {
|
|
|
33117
32819
|
console.log(blue("ports:"));
|
|
33118
32820
|
printValue(" api", cfg.ports.api, cfg.ports.api === defaults.ports.api, 2);
|
|
33119
32821
|
printValue(" indexer", cfg.ports.indexer, cfg.ports.indexer === defaults.ports.indexer, 2);
|
|
33120
|
-
printValue(" receiver", cfg.ports.receiver, cfg.ports.receiver === defaults.ports.receiver, 2);
|
|
33121
32822
|
console.log("");
|
|
33122
32823
|
console.log(blue("database:"));
|
|
33123
32824
|
printValue(" type", cfg.database.type, cfg.database.type === "docker", 2);
|
|
@@ -33156,1113 +32857,6 @@ async function validateDatabaseConnection(url) {
|
|
|
33156
32857
|
console.log(dim("The URL was saved but connection failed. Check your database settings."));
|
|
33157
32858
|
}
|
|
33158
32859
|
}
|
|
33159
|
-
// src/commands/setup.ts
|
|
33160
|
-
init_api_client();
|
|
33161
|
-
init_config();
|
|
33162
|
-
import { confirm, input, select as select2 } from "@inquirer/prompts";
|
|
33163
|
-
init_output();
|
|
33164
|
-
var STREAMS_DIR = "streams";
|
|
33165
|
-
function registerSetupCommand(program2) {
|
|
33166
|
-
program2.command("setup").description("Set up a streams project and configure settings").option("--detect-only", "Only detect existing Stacks nodes, don't initialize").option("-y, --yes", "Use defaults without prompts").option("--data-dir <path>", "Data directory path").option("--node-path <path>", "Path to Stacks node").option("--network <network>", "Network (local, testnet, or mainnet)").option("--endpoint-url <url>", "Default endpoint URL for new streams").action(async (options) => {
|
|
33167
|
-
try {
|
|
33168
|
-
if (options.detectOnly) {
|
|
33169
|
-
await runDetection();
|
|
33170
|
-
return;
|
|
33171
|
-
}
|
|
33172
|
-
const hasFlags = options.yes || options.dataDir || options.nodePath || options.network || options.endpointUrl;
|
|
33173
|
-
if (hasFlags) {
|
|
33174
|
-
await runNonInteractive(options);
|
|
33175
|
-
return;
|
|
33176
|
-
}
|
|
33177
|
-
await runWizard();
|
|
33178
|
-
} catch (err) {
|
|
33179
|
-
if (err.name === "ExitPromptError") {
|
|
33180
|
-
console.log(`
|
|
33181
|
-
Setup cancelled.`);
|
|
33182
|
-
process.exit(0);
|
|
33183
|
-
}
|
|
33184
|
-
error(`Failed to initialize: ${err}`);
|
|
33185
|
-
process.exit(1);
|
|
33186
|
-
}
|
|
33187
|
-
});
|
|
33188
|
-
}
|
|
33189
|
-
async function runNonInteractive(options) {
|
|
33190
|
-
const config = await loadConfig();
|
|
33191
|
-
const network = options.network || config.network || "mainnet";
|
|
33192
|
-
config.network = network;
|
|
33193
|
-
if (network !== "local") {
|
|
33194
|
-
await saveConfig(config);
|
|
33195
|
-
const result = await hostedLogin(config);
|
|
33196
|
-
if (!result)
|
|
33197
|
-
process.exit(1);
|
|
33198
|
-
return;
|
|
33199
|
-
}
|
|
33200
|
-
config.dataDir = options.dataDir || config.dataDir || "~/.secondlayer/data";
|
|
33201
|
-
config.defaultEndpointUrl = options.endpointUrl || config.defaultEndpointUrl;
|
|
33202
|
-
if (options.nodePath) {
|
|
33203
|
-
config.node = {
|
|
33204
|
-
installPath: options.nodePath,
|
|
33205
|
-
network: options.network || "mainnet"
|
|
33206
|
-
};
|
|
33207
|
-
}
|
|
33208
|
-
await saveConfig(config);
|
|
33209
|
-
await Bun.$`mkdir -p ${STREAMS_DIR}`.quiet();
|
|
33210
|
-
await Bun.write(`${STREAMS_DIR}/.gitkeep`, "");
|
|
33211
|
-
printSummary(config);
|
|
33212
|
-
}
|
|
33213
|
-
function printBanner() {
|
|
33214
|
-
console.log();
|
|
33215
|
-
console.log(" ╔═══════════════════════════════════════╗");
|
|
33216
|
-
console.log(" ║ SecondLayer CLI Setup ║");
|
|
33217
|
-
console.log(" ╚═══════════════════════════════════════╝");
|
|
33218
|
-
console.log();
|
|
33219
|
-
}
|
|
33220
|
-
async function runWizard() {
|
|
33221
|
-
printBanner();
|
|
33222
|
-
const config = await loadConfig();
|
|
33223
|
-
const network = await select2({
|
|
33224
|
-
message: "How do you want to use Stacks Streams?",
|
|
33225
|
-
choices: [
|
|
33226
|
-
{
|
|
33227
|
-
name: "Hosted mainnet (recommended — zero setup)",
|
|
33228
|
-
value: "mainnet"
|
|
33229
|
-
},
|
|
33230
|
-
{ name: "Hosted testnet", value: "testnet" },
|
|
33231
|
-
{
|
|
33232
|
-
name: "Local development (run your own node + services)",
|
|
33233
|
-
value: "local"
|
|
33234
|
-
}
|
|
33235
|
-
]
|
|
33236
|
-
});
|
|
33237
|
-
config.network = network;
|
|
33238
|
-
if (network !== "local") {
|
|
33239
|
-
await saveConfig(config);
|
|
33240
|
-
const result = await hostedLogin(config);
|
|
33241
|
-
if (!result)
|
|
33242
|
-
process.exit(1);
|
|
33243
|
-
return;
|
|
33244
|
-
}
|
|
33245
|
-
const dataDir = await promptDataDir(config);
|
|
33246
|
-
config.dataDir = dataDir;
|
|
33247
|
-
const nodeConfig = await promptNodeSetup();
|
|
33248
|
-
if (nodeConfig) {
|
|
33249
|
-
config.node = nodeConfig;
|
|
33250
|
-
}
|
|
33251
|
-
const endpointUrl = await promptEndpointUrl(config);
|
|
33252
|
-
config.defaultEndpointUrl = endpointUrl;
|
|
33253
|
-
await saveConfig(config);
|
|
33254
|
-
await Bun.$`mkdir -p ${STREAMS_DIR}`.quiet();
|
|
33255
|
-
await Bun.write(`${STREAMS_DIR}/.gitkeep`, "");
|
|
33256
|
-
printSummary(config);
|
|
33257
|
-
}
|
|
33258
|
-
async function promptDataDir(config) {
|
|
33259
|
-
const defaultDir = "~/.secondlayer/data";
|
|
33260
|
-
const choice = await select2({
|
|
33261
|
-
message: "Where should streams store data?",
|
|
33262
|
-
choices: [
|
|
33263
|
-
{ name: `Default (${defaultDir})`, value: "default" },
|
|
33264
|
-
{ name: "Custom path...", value: "custom" }
|
|
33265
|
-
]
|
|
33266
|
-
});
|
|
33267
|
-
if (choice === "default") {
|
|
33268
|
-
return defaultDir;
|
|
33269
|
-
}
|
|
33270
|
-
const customPath = await input({
|
|
33271
|
-
message: "Enter data directory path:",
|
|
33272
|
-
default: config.dataDir !== defaultDir ? config.dataDir : undefined,
|
|
33273
|
-
validate: (value) => {
|
|
33274
|
-
if (!value.trim())
|
|
33275
|
-
return "Path cannot be empty";
|
|
33276
|
-
return true;
|
|
33277
|
-
}
|
|
33278
|
-
});
|
|
33279
|
-
return customPath;
|
|
33280
|
-
}
|
|
33281
|
-
async function promptNodeSetup() {
|
|
33282
|
-
const choice = await select2({
|
|
33283
|
-
message: "Do you have an existing Stacks node?",
|
|
33284
|
-
choices: [
|
|
33285
|
-
{ name: "Yes, auto-detect", value: "detect" },
|
|
33286
|
-
{ name: "Yes, specify path", value: "manual" },
|
|
33287
|
-
{ name: "No, skip for now", value: "skip" }
|
|
33288
|
-
]
|
|
33289
|
-
});
|
|
33290
|
-
if (choice === "skip") {
|
|
33291
|
-
return null;
|
|
33292
|
-
}
|
|
33293
|
-
if (choice === "detect") {
|
|
33294
|
-
return await handleAutoDetect();
|
|
33295
|
-
}
|
|
33296
|
-
const nodePath = await input({
|
|
33297
|
-
message: "Enter path to Stacks node:",
|
|
33298
|
-
validate: (value) => {
|
|
33299
|
-
if (!value.trim())
|
|
33300
|
-
return "Path cannot be empty";
|
|
33301
|
-
return true;
|
|
33302
|
-
}
|
|
33303
|
-
});
|
|
33304
|
-
const network = await promptNetwork();
|
|
33305
|
-
return { installPath: nodePath, network };
|
|
33306
|
-
}
|
|
33307
|
-
async function handleAutoDetect() {
|
|
33308
|
-
info(`Scanning for Stacks nodes...
|
|
33309
|
-
`);
|
|
33310
|
-
const nodes = await detectStacksNodes();
|
|
33311
|
-
if (nodes.length === 0) {
|
|
33312
|
-
console.log(` No Stacks nodes found.
|
|
33313
|
-
`);
|
|
33314
|
-
const retry = await select2({
|
|
33315
|
-
message: "What would you like to do?",
|
|
33316
|
-
choices: [
|
|
33317
|
-
{ name: "Enter path manually", value: "manual" },
|
|
33318
|
-
{ name: "Skip for now", value: "skip" }
|
|
33319
|
-
]
|
|
33320
|
-
});
|
|
33321
|
-
if (retry === "skip") {
|
|
33322
|
-
return null;
|
|
33323
|
-
}
|
|
33324
|
-
const nodePath = await input({
|
|
33325
|
-
message: "Enter path to Stacks node:",
|
|
33326
|
-
validate: (value) => {
|
|
33327
|
-
if (!value.trim())
|
|
33328
|
-
return "Path cannot be empty";
|
|
33329
|
-
return true;
|
|
33330
|
-
}
|
|
33331
|
-
});
|
|
33332
|
-
const network = await promptNetwork();
|
|
33333
|
-
return { installPath: nodePath, network };
|
|
33334
|
-
}
|
|
33335
|
-
console.log(`Found ${nodes.length} Stacks node${nodes.length > 1 ? "s" : ""}:
|
|
33336
|
-
`);
|
|
33337
|
-
for (const node of nodes) {
|
|
33338
|
-
printNodeInfo(node);
|
|
33339
|
-
}
|
|
33340
|
-
if (nodes.length === 1) {
|
|
33341
|
-
const useNode = await confirm({
|
|
33342
|
-
message: `Use this node?`,
|
|
33343
|
-
default: true
|
|
33344
|
-
});
|
|
33345
|
-
if (useNode) {
|
|
33346
|
-
return { installPath: nodes[0].path, network: nodes[0].network };
|
|
33347
|
-
}
|
|
33348
|
-
return null;
|
|
33349
|
-
}
|
|
33350
|
-
const choices = [
|
|
33351
|
-
...nodes.map((node) => ({
|
|
33352
|
-
name: `${node.path} (${node.network}${node.running ? ", running" : ""})`,
|
|
33353
|
-
value: node.path
|
|
33354
|
-
})),
|
|
33355
|
-
{ name: "None of these", value: "none" }
|
|
33356
|
-
];
|
|
33357
|
-
const selectedPath = await select2({
|
|
33358
|
-
message: "Which node should streams use?",
|
|
33359
|
-
choices
|
|
33360
|
-
});
|
|
33361
|
-
if (selectedPath === "none") {
|
|
33362
|
-
return null;
|
|
33363
|
-
}
|
|
33364
|
-
const selectedNode = nodes.find((n) => n.path === selectedPath);
|
|
33365
|
-
if (!selectedNode)
|
|
33366
|
-
return null;
|
|
33367
|
-
return { installPath: selectedNode.path, network: selectedNode.network };
|
|
33368
|
-
}
|
|
33369
|
-
async function promptNetwork() {
|
|
33370
|
-
const network = await select2({
|
|
33371
|
-
message: "Which network?",
|
|
33372
|
-
choices: [
|
|
33373
|
-
{ name: "mainnet", value: "mainnet" },
|
|
33374
|
-
{ name: "testnet", value: "testnet" }
|
|
33375
|
-
]
|
|
33376
|
-
});
|
|
33377
|
-
return network;
|
|
33378
|
-
}
|
|
33379
|
-
async function promptEndpointUrl(config) {
|
|
33380
|
-
const internalUrl = "http://localhost:3900/receiver";
|
|
33381
|
-
const choice = await select2({
|
|
33382
|
-
message: "Default endpoint URL for new streams?",
|
|
33383
|
-
choices: [
|
|
33384
|
-
{ name: `Internal test server (${internalUrl})`, value: "internal" },
|
|
33385
|
-
{ name: "Custom URL...", value: "custom" }
|
|
33386
|
-
]
|
|
33387
|
-
});
|
|
33388
|
-
if (choice === "internal") {
|
|
33389
|
-
return internalUrl;
|
|
33390
|
-
}
|
|
33391
|
-
const customUrl = await input({
|
|
33392
|
-
message: "Enter endpoint URL:",
|
|
33393
|
-
default: config.defaultEndpointUrl !== internalUrl ? config.defaultEndpointUrl : undefined,
|
|
33394
|
-
validate: (value) => {
|
|
33395
|
-
if (!value.trim())
|
|
33396
|
-
return "URL cannot be empty";
|
|
33397
|
-
try {
|
|
33398
|
-
new URL(value);
|
|
33399
|
-
return true;
|
|
33400
|
-
} catch {
|
|
33401
|
-
return "Must be a valid URL";
|
|
33402
|
-
}
|
|
33403
|
-
}
|
|
33404
|
-
});
|
|
33405
|
-
return customUrl;
|
|
33406
|
-
}
|
|
33407
|
-
async function hostedLogin(config) {
|
|
33408
|
-
const apiUrl = resolveApiUrl(config);
|
|
33409
|
-
info(`Connecting to ${config.network} API...`);
|
|
33410
|
-
console.log();
|
|
33411
|
-
const email = await input({
|
|
33412
|
-
message: "Email address:",
|
|
33413
|
-
validate: (v) => v.includes("@") || "Enter a valid email"
|
|
33414
|
-
});
|
|
33415
|
-
const mlRes = await fetch(`${apiUrl}/api/auth/magic-link`, {
|
|
33416
|
-
method: "POST",
|
|
33417
|
-
headers: { "Content-Type": "application/json" },
|
|
33418
|
-
body: JSON.stringify({ email })
|
|
33419
|
-
});
|
|
33420
|
-
try {
|
|
33421
|
-
await assertOk(mlRes);
|
|
33422
|
-
} catch (e) {
|
|
33423
|
-
error(`Failed to send magic link: ${e instanceof Error ? e.message : e}`);
|
|
33424
|
-
return false;
|
|
33425
|
-
}
|
|
33426
|
-
info("Check your email for a login token.");
|
|
33427
|
-
const token = await input({
|
|
33428
|
-
message: "Paste token from email:",
|
|
33429
|
-
validate: (v) => v.trim().length > 0 || "Token is required"
|
|
33430
|
-
});
|
|
33431
|
-
const verifyRes = await fetch(`${apiUrl}/api/auth/verify`, {
|
|
33432
|
-
method: "POST",
|
|
33433
|
-
headers: { "Content-Type": "application/json" },
|
|
33434
|
-
body: JSON.stringify({ token: token.trim() })
|
|
33435
|
-
});
|
|
33436
|
-
try {
|
|
33437
|
-
await assertOk(verifyRes);
|
|
33438
|
-
} catch (e) {
|
|
33439
|
-
error(`Verification failed: ${e instanceof Error ? e.message : e}`);
|
|
33440
|
-
return false;
|
|
33441
|
-
}
|
|
33442
|
-
const result = await verifyRes.json();
|
|
33443
|
-
const { hostname } = await import("node:os");
|
|
33444
|
-
const sessionHeaders = {
|
|
33445
|
-
Authorization: `Bearer ${result.sessionToken}`,
|
|
33446
|
-
"Content-Type": "application/json"
|
|
33447
|
-
};
|
|
33448
|
-
const keyName = `cli-${hostname().toLowerCase()}`;
|
|
33449
|
-
const listRes = await fetch(`${apiUrl}/api/keys`, {
|
|
33450
|
-
headers: sessionHeaders
|
|
33451
|
-
});
|
|
33452
|
-
if (listRes.ok) {
|
|
33453
|
-
const { keys } = await listRes.json();
|
|
33454
|
-
const existing = keys.find((k) => k.name === keyName && k.status === "active");
|
|
33455
|
-
if (existing) {
|
|
33456
|
-
await fetch(`${apiUrl}/api/keys/${existing.id}`, {
|
|
33457
|
-
method: "DELETE",
|
|
33458
|
-
headers: sessionHeaders
|
|
33459
|
-
});
|
|
33460
|
-
}
|
|
33461
|
-
}
|
|
33462
|
-
const createRes = await fetch(`${apiUrl}/api/keys`, {
|
|
33463
|
-
method: "POST",
|
|
33464
|
-
headers: sessionHeaders,
|
|
33465
|
-
body: JSON.stringify({ name: keyName })
|
|
33466
|
-
});
|
|
33467
|
-
try {
|
|
33468
|
-
await assertOk(createRes);
|
|
33469
|
-
} catch (e) {
|
|
33470
|
-
error(`Failed to create API key: ${e instanceof Error ? e.message : e}`);
|
|
33471
|
-
return false;
|
|
33472
|
-
}
|
|
33473
|
-
const { key } = await createRes.json();
|
|
33474
|
-
config.apiKey = key;
|
|
33475
|
-
await saveConfig(config);
|
|
33476
|
-
try {
|
|
33477
|
-
await fetch(`${apiUrl}/api/auth/logout`, {
|
|
33478
|
-
method: "POST",
|
|
33479
|
-
headers: sessionHeaders
|
|
33480
|
-
});
|
|
33481
|
-
} catch {}
|
|
33482
|
-
const account = result.account;
|
|
33483
|
-
console.log();
|
|
33484
|
-
success(`Authenticated as ${account.email}!`);
|
|
33485
|
-
console.log();
|
|
33486
|
-
console.log(` Plan: ${account.plan}`);
|
|
33487
|
-
console.log(` API: ${apiUrl}`);
|
|
33488
|
-
console.log();
|
|
33489
|
-
console.log(" Next steps:");
|
|
33490
|
-
console.log(" sl streams list # List streams");
|
|
33491
|
-
console.log(" sl streams new <name> # Create a stream");
|
|
33492
|
-
console.log(" sl auth status # Check auth status");
|
|
33493
|
-
console.log();
|
|
33494
|
-
return true;
|
|
33495
|
-
}
|
|
33496
|
-
function printSummary(config) {
|
|
33497
|
-
console.log();
|
|
33498
|
-
success("Configuration saved!");
|
|
33499
|
-
console.log();
|
|
33500
|
-
console.log(" Settings:");
|
|
33501
|
-
console.log(` Data directory: ${config.dataDir}`);
|
|
33502
|
-
if (config.defaultEndpointUrl) {
|
|
33503
|
-
console.log(` Endpoint URL: ${config.defaultEndpointUrl}`);
|
|
33504
|
-
}
|
|
33505
|
-
if (config.node) {
|
|
33506
|
-
console.log(` Node path: ${config.node.installPath}`);
|
|
33507
|
-
console.log(` Network: ${config.node.network}`);
|
|
33508
|
-
}
|
|
33509
|
-
console.log();
|
|
33510
|
-
console.log(" Next steps:");
|
|
33511
|
-
console.log(" sl local start # Start dev services");
|
|
33512
|
-
if (config.node) {
|
|
33513
|
-
console.log(" sl stack start # Start your Stacks node");
|
|
33514
|
-
}
|
|
33515
|
-
console.log(" sl streams new <name> # Create a new stream config");
|
|
33516
|
-
console.log();
|
|
33517
|
-
}
|
|
33518
|
-
async function runDetection() {
|
|
33519
|
-
info(`Scanning for Stacks nodes...
|
|
33520
|
-
`);
|
|
33521
|
-
const nodes = await detectStacksNodes();
|
|
33522
|
-
if (nodes.length === 0) {
|
|
33523
|
-
console.log(` No Stacks nodes found.
|
|
33524
|
-
`);
|
|
33525
|
-
console.log("Checked locations:");
|
|
33526
|
-
console.log(" - Running Docker containers");
|
|
33527
|
-
console.log(" - /Volumes/*/stacks-blockchain-docker");
|
|
33528
|
-
console.log(" - ~/stacks-blockchain-docker");
|
|
33529
|
-
console.log(` - /opt/stacks-*
|
|
33530
|
-
`);
|
|
33531
|
-
console.log("To set up a node manually:");
|
|
33532
|
-
console.log(" sl config set node.installPath /path/to/node");
|
|
33533
|
-
return;
|
|
33534
|
-
}
|
|
33535
|
-
console.log(`Found ${nodes.length} Stacks node${nodes.length > 1 ? "s" : ""}:
|
|
33536
|
-
`);
|
|
33537
|
-
for (const node of nodes) {
|
|
33538
|
-
printNodeInfo(node);
|
|
33539
|
-
}
|
|
33540
|
-
}
|
|
33541
|
-
function printNodeInfo(node) {
|
|
33542
|
-
const status = node.running ? "\x1B[32m●\x1B[0m running" : "\x1B[90m○\x1B[0m stopped";
|
|
33543
|
-
const source = node.source === "container" ? "docker" : "filesystem";
|
|
33544
|
-
console.log(` ${status} ${node.path}`);
|
|
33545
|
-
console.log(` network: ${node.network}, source: ${source}
|
|
33546
|
-
`);
|
|
33547
|
-
}
|
|
33548
|
-
// src/commands/delete.ts
|
|
33549
|
-
init_api_client();
|
|
33550
|
-
init_output();
|
|
33551
|
-
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
33552
|
-
function registerDeleteCommand(program2) {
|
|
33553
|
-
program2.command("delete <id>").alias("rm").description("Delete a stream").option("-f, --force", "Skip confirmation prompt").action(async (id, options) => {
|
|
33554
|
-
try {
|
|
33555
|
-
const stream = await getStream(id);
|
|
33556
|
-
if (!options.force) {
|
|
33557
|
-
const confirmed = await confirm2({
|
|
33558
|
-
message: `Delete stream "${stream.name}" (${stream.id})?`,
|
|
33559
|
-
default: false
|
|
33560
|
-
});
|
|
33561
|
-
if (!confirmed) {
|
|
33562
|
-
warn("Aborted");
|
|
33563
|
-
return;
|
|
33564
|
-
}
|
|
33565
|
-
}
|
|
33566
|
-
await deleteStream(id);
|
|
33567
|
-
success(`Deleted stream: ${stream.name}`);
|
|
33568
|
-
} catch (err) {
|
|
33569
|
-
handleApiError(err, "delete stream");
|
|
33570
|
-
}
|
|
33571
|
-
});
|
|
33572
|
-
}
|
|
33573
|
-
|
|
33574
|
-
// src/commands/get.ts
|
|
33575
|
-
init_api_client();
|
|
33576
|
-
init_output();
|
|
33577
|
-
function registerGetCommand(program2) {
|
|
33578
|
-
program2.command("get <id>").description("Get details of a stream").option("--json", "Output as JSON").action(async (id, options) => {
|
|
33579
|
-
try {
|
|
33580
|
-
const stream = await getStream(id);
|
|
33581
|
-
if (options.json) {
|
|
33582
|
-
console.log(JSON.stringify(stream, null, 2));
|
|
33583
|
-
return;
|
|
33584
|
-
}
|
|
33585
|
-
const statusColor = stream.status === "active" ? green : stream.status === "failed" ? red : stream.status === "paused" ? yellow : dim;
|
|
33586
|
-
console.log(formatKeyValue([
|
|
33587
|
-
["ID", stream.id],
|
|
33588
|
-
["Name", stream.name],
|
|
33589
|
-
["Status", statusColor(stream.status)],
|
|
33590
|
-
["Endpoint URL", stream.endpointUrl],
|
|
33591
|
-
["Total Deliveries", stream.totalDeliveries.toString()],
|
|
33592
|
-
["Failed Deliveries", stream.failedDeliveries.toString()],
|
|
33593
|
-
["Last Triggered", stream.lastTriggeredAt || dim("never")],
|
|
33594
|
-
["Last Block", stream.lastTriggeredBlock?.toString() || dim("n/a")],
|
|
33595
|
-
["Created", stream.createdAt],
|
|
33596
|
-
["Updated", stream.updatedAt]
|
|
33597
|
-
]));
|
|
33598
|
-
if (stream.errorMessage) {
|
|
33599
|
-
console.log(`
|
|
33600
|
-
${red("Error:")} ${stream.errorMessage}`);
|
|
33601
|
-
}
|
|
33602
|
-
console.log(`
|
|
33603
|
-
${dim("Filters:")}`);
|
|
33604
|
-
console.log(JSON.stringify(stream.filters, null, 2));
|
|
33605
|
-
console.log(`
|
|
33606
|
-
${dim("Options:")}`);
|
|
33607
|
-
console.log(JSON.stringify(stream.options, null, 2));
|
|
33608
|
-
} catch (err) {
|
|
33609
|
-
handleApiError(err, "get stream");
|
|
33610
|
-
}
|
|
33611
|
-
});
|
|
33612
|
-
}
|
|
33613
|
-
|
|
33614
|
-
// src/commands/list.ts
|
|
33615
|
-
init_api_client();
|
|
33616
|
-
init_output();
|
|
33617
|
-
function registerListCommand(program2) {
|
|
33618
|
-
program2.command("list").alias("ls").description("List all streams").option("-s, --status <status>", "Filter by status (inactive/active/paused/failed)").option("--json", "Output as JSON").action(async (options) => {
|
|
33619
|
-
try {
|
|
33620
|
-
const { streams, total } = await listStreams({
|
|
33621
|
-
status: options.status
|
|
33622
|
-
});
|
|
33623
|
-
if (options.json) {
|
|
33624
|
-
console.log(JSON.stringify(streams, null, 2));
|
|
33625
|
-
return;
|
|
33626
|
-
}
|
|
33627
|
-
if (streams.length === 0) {
|
|
33628
|
-
console.log("No streams found");
|
|
33629
|
-
return;
|
|
33630
|
-
}
|
|
33631
|
-
const rows = streams.map((s) => {
|
|
33632
|
-
const statusColor = s.status === "active" ? green : s.status === "failed" ? red : s.status === "paused" ? yellow : dim;
|
|
33633
|
-
return [
|
|
33634
|
-
s.id.slice(0, 8),
|
|
33635
|
-
s.name,
|
|
33636
|
-
statusColor(s.status),
|
|
33637
|
-
s.totalDeliveries.toString()
|
|
33638
|
-
];
|
|
33639
|
-
});
|
|
33640
|
-
console.log(formatTable(["ID", "Name", "Status", "Deliveries"], rows));
|
|
33641
|
-
console.log(dim(`
|
|
33642
|
-
${total} stream(s) total`));
|
|
33643
|
-
} catch (err) {
|
|
33644
|
-
handleApiError(err, "list streams");
|
|
33645
|
-
}
|
|
33646
|
-
});
|
|
33647
|
-
}
|
|
33648
|
-
|
|
33649
|
-
// src/commands/logs.ts
|
|
33650
|
-
init_api_client();
|
|
33651
|
-
init_config();
|
|
33652
|
-
init_output();
|
|
33653
|
-
function registerLogsCommand(program2) {
|
|
33654
|
-
program2.command("logs <stream-id>").description("View delivery logs for a stream").option("-f, --follow", "Follow logs in real-time").option("-n, --limit <count>", "Number of logs to show", "20").option("-s, --status <status>", "Filter by status (success|failed)").action(async (streamId, options) => {
|
|
33655
|
-
const config = await loadConfig();
|
|
33656
|
-
try {
|
|
33657
|
-
const fullId = await resolveStreamId(streamId);
|
|
33658
|
-
if (options.follow) {
|
|
33659
|
-
await followLogs(resolveApiUrl(config), fullId, config, options.status);
|
|
33660
|
-
} else {
|
|
33661
|
-
await showRecentLogs(resolveApiUrl(config), fullId, Number.parseInt(options.limit), config, options.status);
|
|
33662
|
-
}
|
|
33663
|
-
} catch (err) {
|
|
33664
|
-
handleApiError(err, "get logs");
|
|
33665
|
-
}
|
|
33666
|
-
});
|
|
33667
|
-
}
|
|
33668
|
-
async function showRecentLogs(apiUrl, streamId, limit, config, status) {
|
|
33669
|
-
const params = new URLSearchParams({ limit: limit.toString() });
|
|
33670
|
-
if (status)
|
|
33671
|
-
params.set("status", status);
|
|
33672
|
-
const response = await fetch(`${apiUrl}/api/streams/${streamId}/deliveries?${params}`, {
|
|
33673
|
-
headers: authHeaders(config)
|
|
33674
|
-
});
|
|
33675
|
-
if (!response.ok) {
|
|
33676
|
-
const body = await response.text();
|
|
33677
|
-
let message = `HTTP ${response.status}`;
|
|
33678
|
-
try {
|
|
33679
|
-
const json = JSON.parse(body);
|
|
33680
|
-
message = json.error || json.message || message;
|
|
33681
|
-
} catch {
|
|
33682
|
-
if (body)
|
|
33683
|
-
message = body;
|
|
33684
|
-
}
|
|
33685
|
-
throw new Error(message);
|
|
33686
|
-
}
|
|
33687
|
-
const data = await response.json();
|
|
33688
|
-
const { deliveries } = data;
|
|
33689
|
-
if (deliveries.length === 0) {
|
|
33690
|
-
console.log(dim("No deliveries yet"));
|
|
33691
|
-
return;
|
|
33692
|
-
}
|
|
33693
|
-
const rows = deliveries.map((d) => {
|
|
33694
|
-
const statusColor = d.status === "success" ? green : red;
|
|
33695
|
-
const time = new Date(d.createdAt).toLocaleTimeString();
|
|
33696
|
-
return [
|
|
33697
|
-
dim(d.id.slice(0, 8)),
|
|
33698
|
-
d.blockHeight.toString(),
|
|
33699
|
-
statusColor(d.status),
|
|
33700
|
-
d.statusCode?.toString() || "-",
|
|
33701
|
-
d.responseTimeMs ? `${d.responseTimeMs}ms` : "-",
|
|
33702
|
-
d.attempts.toString(),
|
|
33703
|
-
dim(time)
|
|
33704
|
-
];
|
|
33705
|
-
});
|
|
33706
|
-
console.log(formatTable(["ID", "Block", "Status", "Code", "Time", "Attempts", "Timestamp"], rows));
|
|
33707
|
-
}
|
|
33708
|
-
async function followLogs(apiUrl, streamId, config, status) {
|
|
33709
|
-
console.log(dim(`Following logs for stream ${streamId}...`));
|
|
33710
|
-
console.log(dim(`Press Ctrl+C to stop
|
|
33711
|
-
`));
|
|
33712
|
-
const response = await fetch(`${apiUrl}/api/logs/${streamId}/stream`, {
|
|
33713
|
-
headers: authHeaders(config)
|
|
33714
|
-
});
|
|
33715
|
-
if (!response.ok) {
|
|
33716
|
-
const body = await response.text();
|
|
33717
|
-
let message = `HTTP ${response.status}`;
|
|
33718
|
-
try {
|
|
33719
|
-
const json = JSON.parse(body);
|
|
33720
|
-
message = json.error || json.message || message;
|
|
33721
|
-
} catch {
|
|
33722
|
-
if (body)
|
|
33723
|
-
message = body;
|
|
33724
|
-
}
|
|
33725
|
-
throw new Error(message);
|
|
33726
|
-
}
|
|
33727
|
-
const reader = response.body?.getReader();
|
|
33728
|
-
if (!reader) {
|
|
33729
|
-
throw new Error("No response body");
|
|
33730
|
-
}
|
|
33731
|
-
const decoder = new TextDecoder;
|
|
33732
|
-
let buffer2 = "";
|
|
33733
|
-
while (true) {
|
|
33734
|
-
const { done, value } = await reader.read();
|
|
33735
|
-
if (done)
|
|
33736
|
-
break;
|
|
33737
|
-
buffer2 += decoder.decode(value, { stream: true });
|
|
33738
|
-
const lines = buffer2.split(`
|
|
33739
|
-
`);
|
|
33740
|
-
buffer2 = lines.pop() || "";
|
|
33741
|
-
let eventType = "";
|
|
33742
|
-
let eventData = "";
|
|
33743
|
-
for (const line of lines) {
|
|
33744
|
-
if (line.startsWith("event:")) {
|
|
33745
|
-
eventType = line.slice(6).trim();
|
|
33746
|
-
} else if (line.startsWith("data:")) {
|
|
33747
|
-
eventData = line.slice(5).trim();
|
|
33748
|
-
} else if (line === "" && eventType && eventData) {
|
|
33749
|
-
if (eventType === "delivery") {
|
|
33750
|
-
try {
|
|
33751
|
-
const delivery = JSON.parse(eventData);
|
|
33752
|
-
if (!status || delivery.status === status) {
|
|
33753
|
-
printDelivery(delivery);
|
|
33754
|
-
}
|
|
33755
|
-
} catch {}
|
|
33756
|
-
}
|
|
33757
|
-
eventType = "";
|
|
33758
|
-
eventData = "";
|
|
33759
|
-
}
|
|
33760
|
-
}
|
|
33761
|
-
}
|
|
33762
|
-
}
|
|
33763
|
-
function printDelivery(d) {
|
|
33764
|
-
const statusColor = d.status === "success" ? green : red;
|
|
33765
|
-
const time = new Date(d.createdAt).toLocaleTimeString();
|
|
33766
|
-
console.log(`${dim(time)} ` + `${statusColor(d.status.padEnd(7))} ` + `block=${d.blockHeight} ` + `code=${d.statusCode || "-"} ` + `time=${d.responseTimeMs ? `${d.responseTimeMs}ms` : "-"} ` + `attempts=${d.attempts}`);
|
|
33767
|
-
if (d.error) {
|
|
33768
|
-
console.log(red(` Error: ${d.error}`));
|
|
33769
|
-
}
|
|
33770
|
-
}
|
|
33771
|
-
|
|
33772
|
-
// src/commands/new.ts
|
|
33773
|
-
init_config();
|
|
33774
|
-
init_fs();
|
|
33775
|
-
init_output();
|
|
33776
|
-
import { join as join3 } from "node:path";
|
|
33777
|
-
|
|
33778
|
-
// src/templates/stream.ts
|
|
33779
|
-
function generateStreamTemplate(name, endpointUrl) {
|
|
33780
|
-
return {
|
|
33781
|
-
name,
|
|
33782
|
-
endpointUrl: endpointUrl || "https://example.com/endpoint",
|
|
33783
|
-
filters: [
|
|
33784
|
-
{
|
|
33785
|
-
type: "contract_call",
|
|
33786
|
-
contractId: "SP000000000000000000002Q6VF78.pox-4"
|
|
33787
|
-
}
|
|
33788
|
-
],
|
|
33789
|
-
options: {
|
|
33790
|
-
decodeClarityValues: true,
|
|
33791
|
-
includeRawTx: false,
|
|
33792
|
-
includeBlockMetadata: true,
|
|
33793
|
-
rateLimit: 10,
|
|
33794
|
-
timeoutMs: 1e4,
|
|
33795
|
-
maxRetries: 3
|
|
33796
|
-
}
|
|
33797
|
-
};
|
|
33798
|
-
}
|
|
33799
|
-
|
|
33800
|
-
// src/commands/new.ts
|
|
33801
|
-
var STREAMS_DIR2 = "streams";
|
|
33802
|
-
function registerNewCommand(program2) {
|
|
33803
|
-
program2.command("new <name>").description("Generate a new stream configuration file").option("-o, --output <path>", "Output path (default: streams/<name>.json)").action(async (name, options) => {
|
|
33804
|
-
try {
|
|
33805
|
-
const config = await loadConfig();
|
|
33806
|
-
const outputPath = options.output || join3(STREAMS_DIR2, `${name}.json`);
|
|
33807
|
-
if (await fileExists(outputPath)) {
|
|
33808
|
-
warn(`File already exists: ${outputPath}`);
|
|
33809
|
-
process.exit(1);
|
|
33810
|
-
}
|
|
33811
|
-
const dir = outputPath.substring(0, outputPath.lastIndexOf("/"));
|
|
33812
|
-
if (dir) {
|
|
33813
|
-
await ensureDir(dir);
|
|
33814
|
-
}
|
|
33815
|
-
const template = generateStreamTemplate(name, config.defaultEndpointUrl);
|
|
33816
|
-
await writeTextFile(outputPath, JSON.stringify(template, null, 2) + `
|
|
33817
|
-
`);
|
|
33818
|
-
success(`Created ${outputPath}`);
|
|
33819
|
-
if (!config.defaultEndpointUrl) {
|
|
33820
|
-
warn("Edit the endpointUrl before registering — it must be a reachable HTTPS endpoint");
|
|
33821
|
-
}
|
|
33822
|
-
console.log(`
|
|
33823
|
-
Edit the file to configure your stream, then run:`);
|
|
33824
|
-
console.log(` sl streams register ${outputPath}`);
|
|
33825
|
-
} catch (err) {
|
|
33826
|
-
error(`Failed to create stream: ${err}`);
|
|
33827
|
-
process.exit(1);
|
|
33828
|
-
}
|
|
33829
|
-
});
|
|
33830
|
-
}
|
|
33831
|
-
|
|
33832
|
-
// src/commands/register.ts
|
|
33833
|
-
init_api_client();
|
|
33834
|
-
init_fs();
|
|
33835
|
-
init_output();
|
|
33836
|
-
import { CreateStreamSchema } from "@secondlayer/shared/schemas";
|
|
33837
|
-
function registerRegisterCommand(program2) {
|
|
33838
|
-
program2.command("register <file>").description("Register a stream from a JSON configuration file").option("-u, --update", "Update existing stream if name matches").action(async (filePath, options) => {
|
|
33839
|
-
try {
|
|
33840
|
-
if (!await fileExists(filePath)) {
|
|
33841
|
-
error(`File not found: ${filePath}`);
|
|
33842
|
-
process.exit(1);
|
|
33843
|
-
}
|
|
33844
|
-
const content = await readJsonFile(filePath);
|
|
33845
|
-
const parsed = CreateStreamSchema.safeParse(content);
|
|
33846
|
-
if (!parsed.success) {
|
|
33847
|
-
error("Invalid stream configuration:");
|
|
33848
|
-
for (const issue of parsed.error.issues) {
|
|
33849
|
-
console.log(` - ${issue.path.join(".")}: ${issue.message}`);
|
|
33850
|
-
}
|
|
33851
|
-
process.exit(1);
|
|
33852
|
-
}
|
|
33853
|
-
const streamData = parsed.data;
|
|
33854
|
-
if (options.update) {
|
|
33855
|
-
try {
|
|
33856
|
-
const updated = await updateStreamByName(streamData.name, streamData);
|
|
33857
|
-
success(`Updated stream: ${updated.name}`);
|
|
33858
|
-
console.log(formatKeyValue([
|
|
33859
|
-
["ID", updated.id],
|
|
33860
|
-
["Name", updated.name]
|
|
33861
|
-
]));
|
|
33862
|
-
return;
|
|
33863
|
-
} catch (err) {
|
|
33864
|
-
if (err instanceof ApiError && err.status === 404) {
|
|
33865
|
-
warn("Stream not found, creating new...");
|
|
33866
|
-
} else {
|
|
33867
|
-
throw err;
|
|
33868
|
-
}
|
|
33869
|
-
}
|
|
33870
|
-
}
|
|
33871
|
-
const result = await createStream(streamData);
|
|
33872
|
-
success(`Registered stream: ${result.stream.name}`);
|
|
33873
|
-
console.log(formatKeyValue([
|
|
33874
|
-
["ID", result.stream.id],
|
|
33875
|
-
["Name", result.stream.name],
|
|
33876
|
-
["Signing Secret", result.signingSecret]
|
|
33877
|
-
]));
|
|
33878
|
-
console.log(dim(`
|
|
33879
|
-
Save the signing secret - it won't be shown again!`));
|
|
33880
|
-
} catch (err) {
|
|
33881
|
-
handleApiError(err, "register stream");
|
|
33882
|
-
}
|
|
33883
|
-
});
|
|
33884
|
-
}
|
|
33885
|
-
|
|
33886
|
-
// src/commands/replay.ts
|
|
33887
|
-
init_api_client();
|
|
33888
|
-
init_config();
|
|
33889
|
-
init_output();
|
|
33890
|
-
function registerReplayCommand(program2) {
|
|
33891
|
-
program2.command("replay <stream-id>").description("Replay blocks through a stream (re-evaluate and re-deliver)").option("--from <block>", "Start block height").option("--to <block>", "End block height").option("--last <count>", "Replay last N blocks").option("--block <height>", "Trigger evaluation for a single block").option("--fixture <path>", "Load block from fixture file (only with --block)").action(async (rawStreamId, options) => {
|
|
33892
|
-
const config = await loadConfig();
|
|
33893
|
-
try {
|
|
33894
|
-
const streamId = await resolveStreamId(rawStreamId);
|
|
33895
|
-
if (options.block) {
|
|
33896
|
-
await triggerBlock(config, streamId, options.block, options.fixture);
|
|
33897
|
-
return;
|
|
33898
|
-
}
|
|
33899
|
-
if (options.fixture) {
|
|
33900
|
-
error("--fixture can only be used with --block");
|
|
33901
|
-
process.exit(1);
|
|
33902
|
-
}
|
|
33903
|
-
let fromBlock;
|
|
33904
|
-
let toBlock;
|
|
33905
|
-
if (options.last) {
|
|
33906
|
-
const lastCount = Number.parseInt(options.last);
|
|
33907
|
-
if (isNaN(lastCount) || lastCount <= 0) {
|
|
33908
|
-
error("--last must be a positive number");
|
|
33909
|
-
process.exit(1);
|
|
33910
|
-
}
|
|
33911
|
-
const statusRes = await fetch(`${resolveApiUrl(config)}/status`, {
|
|
33912
|
-
headers: authHeaders(config)
|
|
33913
|
-
});
|
|
33914
|
-
if (!statusRes.ok) {
|
|
33915
|
-
throw new Error("Failed to get index progress");
|
|
33916
|
-
}
|
|
33917
|
-
const status = await statusRes.json();
|
|
33918
|
-
const progress = status.indexProgress[0];
|
|
33919
|
-
if (!progress) {
|
|
33920
|
-
error("No index progress found");
|
|
33921
|
-
process.exit(1);
|
|
33922
|
-
}
|
|
33923
|
-
toBlock = Number(progress.lastIndexedBlock);
|
|
33924
|
-
fromBlock = Math.max(0, toBlock - lastCount + 1);
|
|
33925
|
-
info(`Replaying last ${lastCount} blocks (${fromBlock} to ${toBlock})`);
|
|
33926
|
-
} else if (options.from && options.to) {
|
|
33927
|
-
fromBlock = Number.parseInt(options.from);
|
|
33928
|
-
toBlock = Number.parseInt(options.to);
|
|
33929
|
-
if (isNaN(fromBlock) || fromBlock < 0) {
|
|
33930
|
-
error("--from must be a non-negative number");
|
|
33931
|
-
process.exit(1);
|
|
33932
|
-
}
|
|
33933
|
-
if (isNaN(toBlock) || toBlock < 0) {
|
|
33934
|
-
error("--to must be a non-negative number");
|
|
33935
|
-
process.exit(1);
|
|
33936
|
-
}
|
|
33937
|
-
if (fromBlock > toBlock) {
|
|
33938
|
-
error("--from must be less than or equal to --to");
|
|
33939
|
-
process.exit(1);
|
|
33940
|
-
}
|
|
33941
|
-
} else {
|
|
33942
|
-
error("Must specify --from/--to, --last, or --block");
|
|
33943
|
-
console.log(dim(`
|
|
33944
|
-
Examples:`));
|
|
33945
|
-
console.log(dim(" sl streams replay <id> --from 100000 --to 100500"));
|
|
33946
|
-
console.log(dim(" sl streams replay <id> --last 1000"));
|
|
33947
|
-
console.log(dim(" sl streams replay <id> --block 100000"));
|
|
33948
|
-
console.log(dim(" sl streams replay <id> --block 100000 --fixture block.json"));
|
|
33949
|
-
process.exit(1);
|
|
33950
|
-
}
|
|
33951
|
-
const response = await fetch(`${resolveApiUrl(config)}/api/streams/${streamId}/replay`, {
|
|
33952
|
-
method: "POST",
|
|
33953
|
-
headers: authHeaders(config),
|
|
33954
|
-
body: JSON.stringify({ fromBlock, toBlock })
|
|
33955
|
-
});
|
|
33956
|
-
if (!response.ok) {
|
|
33957
|
-
const body = await response.text();
|
|
33958
|
-
throw new Error(parseError2(response.status, body));
|
|
33959
|
-
}
|
|
33960
|
-
const result = await response.json();
|
|
33961
|
-
success("Replay started");
|
|
33962
|
-
console.log(formatKeyValue([
|
|
33963
|
-
["Stream ID", result.streamId],
|
|
33964
|
-
["From Block", result.fromBlock.toString()],
|
|
33965
|
-
["To Block", result.toBlock.toString()],
|
|
33966
|
-
["Jobs Created", result.jobCount.toString()]
|
|
33967
|
-
]));
|
|
33968
|
-
console.log(dim(`
|
|
33969
|
-
Jobs will be processed by the worker in block order.`));
|
|
33970
|
-
console.log(dim("Use 'sl streams logs <id> -f' to monitor progress."));
|
|
33971
|
-
} catch (err) {
|
|
33972
|
-
handleApiError(err, "start replay");
|
|
33973
|
-
}
|
|
33974
|
-
});
|
|
33975
|
-
}
|
|
33976
|
-
async function triggerBlock(config, streamId, blockStr, fixturePath) {
|
|
33977
|
-
const blockHeight = Number.parseInt(blockStr);
|
|
33978
|
-
if (isNaN(blockHeight) || blockHeight < 0) {
|
|
33979
|
-
error("Block height must be a non-negative number");
|
|
33980
|
-
process.exit(1);
|
|
33981
|
-
}
|
|
33982
|
-
if (fixturePath) {
|
|
33983
|
-
const file = Bun.file(fixturePath);
|
|
33984
|
-
if (!await file.exists()) {
|
|
33985
|
-
error(`Fixture file not found: ${fixturePath}`);
|
|
33986
|
-
process.exit(1);
|
|
33987
|
-
}
|
|
33988
|
-
const fixture = await file.json();
|
|
33989
|
-
const indexerUrl = process.env.INDEXER_URL || "http://localhost:3700";
|
|
33990
|
-
const indexerRes = await fetch(`${indexerUrl}/new_block`, {
|
|
33991
|
-
method: "POST",
|
|
33992
|
-
headers: { "Content-Type": "application/json" },
|
|
33993
|
-
body: JSON.stringify(fixture)
|
|
33994
|
-
});
|
|
33995
|
-
if (!indexerRes.ok) {
|
|
33996
|
-
error(`Failed to send fixture to indexer: ${await indexerRes.text()}`);
|
|
33997
|
-
process.exit(1);
|
|
33998
|
-
}
|
|
33999
|
-
console.log(dim(`Sent fixture to indexer at block ${blockHeight}`));
|
|
34000
|
-
}
|
|
34001
|
-
const response = await fetch(`${resolveApiUrl(config)}/api/streams/${streamId}/trigger`, {
|
|
34002
|
-
method: "POST",
|
|
34003
|
-
headers: authHeaders(config),
|
|
34004
|
-
body: JSON.stringify({ blockHeight })
|
|
34005
|
-
});
|
|
34006
|
-
if (!response.ok) {
|
|
34007
|
-
const body = await response.text();
|
|
34008
|
-
throw new Error(parseError2(response.status, body));
|
|
34009
|
-
}
|
|
34010
|
-
const result = await response.json();
|
|
34011
|
-
success(`Triggered evaluation for block ${blockHeight}`);
|
|
34012
|
-
console.log(formatKeyValue([
|
|
34013
|
-
["Job ID", result.jobId],
|
|
34014
|
-
["Stream ID", result.streamId],
|
|
34015
|
-
["Block", result.blockHeight.toString()]
|
|
34016
|
-
]));
|
|
34017
|
-
}
|
|
34018
|
-
function parseError2(status, body) {
|
|
34019
|
-
let message = `HTTP ${status}`;
|
|
34020
|
-
try {
|
|
34021
|
-
const json = JSON.parse(body);
|
|
34022
|
-
message = json.error || json.message || message;
|
|
34023
|
-
} catch {
|
|
34024
|
-
if (body)
|
|
34025
|
-
message = body;
|
|
34026
|
-
}
|
|
34027
|
-
return message;
|
|
34028
|
-
}
|
|
34029
|
-
|
|
34030
|
-
// src/commands/rotate-secret.ts
|
|
34031
|
-
init_api_client();
|
|
34032
|
-
init_output();
|
|
34033
|
-
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
34034
|
-
function registerRotateSecretCommand(program2) {
|
|
34035
|
-
program2.command("rotate-secret <id>").description("Generate a new signing secret for a stream").option("-y, --yes", "Skip confirmation prompt").action(async (id, options) => {
|
|
34036
|
-
try {
|
|
34037
|
-
const stream = await getStream(id);
|
|
34038
|
-
if (!options.yes) {
|
|
34039
|
-
const confirmed = await confirm3({
|
|
34040
|
-
message: `Rotate signing secret for "${stream.name}"? The current secret will be invalidated.`,
|
|
34041
|
-
default: false
|
|
34042
|
-
});
|
|
34043
|
-
if (!confirmed) {
|
|
34044
|
-
warn("Cancelled");
|
|
34045
|
-
return;
|
|
34046
|
-
}
|
|
34047
|
-
}
|
|
34048
|
-
const result = await rotateSecret(stream.id);
|
|
34049
|
-
success(`Rotated signing secret for: ${stream.name}`);
|
|
34050
|
-
console.log(formatKeyValue([
|
|
34051
|
-
["Stream", stream.name],
|
|
34052
|
-
["Signing Secret", result.secret]
|
|
34053
|
-
]));
|
|
34054
|
-
console.log(dim(`
|
|
34055
|
-
Save the signing secret - it won't be shown again!`));
|
|
34056
|
-
} catch (err) {
|
|
34057
|
-
handleApiError(err, "rotate secret");
|
|
34058
|
-
}
|
|
34059
|
-
});
|
|
34060
|
-
}
|
|
34061
|
-
|
|
34062
|
-
// src/commands/set.ts
|
|
34063
|
-
init_api_client();
|
|
34064
|
-
init_config();
|
|
34065
|
-
init_output();
|
|
34066
|
-
function registerSetCommand(program2) {
|
|
34067
|
-
program2.command("set [id] [state]").description("Set stream state (active, disabled, paused)").option("--all", "Apply to all streams").option("--wait", "Wait for pending jobs to complete (with paused)").option("--retry", "Re-enable an errored stream").option("--replay-failed", "Also replay failed deliveries (with --retry)").option("-o, --option <kv...>", "Set stream option (key=value, e.g. maxRetries=5)").action(async (id, state, options) => {
|
|
34068
|
-
try {
|
|
34069
|
-
if (options.retry) {
|
|
34070
|
-
if (!id) {
|
|
34071
|
-
error("Stream ID is required with --retry");
|
|
34072
|
-
process.exit(1);
|
|
34073
|
-
}
|
|
34074
|
-
await retryStream(id, options.replayFailed);
|
|
34075
|
-
return;
|
|
34076
|
-
}
|
|
34077
|
-
if (options.all) {
|
|
34078
|
-
if (!state) {
|
|
34079
|
-
error("State is required: sl streams set --all <active|paused>");
|
|
34080
|
-
process.exit(1);
|
|
34081
|
-
}
|
|
34082
|
-
await setAllStreams(state, options.wait);
|
|
34083
|
-
return;
|
|
34084
|
-
}
|
|
34085
|
-
if (options.option?.length) {
|
|
34086
|
-
if (!id) {
|
|
34087
|
-
error("Stream ID is required with --option");
|
|
34088
|
-
process.exit(1);
|
|
34089
|
-
}
|
|
34090
|
-
const parsedOptions = parseOptions2(options.option);
|
|
34091
|
-
await updateStream(id, { options: parsedOptions });
|
|
34092
|
-
success(`Updated stream options: ${Object.entries(parsedOptions).map(([k, v]) => `${k}=${v}`).join(", ")}`);
|
|
34093
|
-
if (!state)
|
|
34094
|
-
return;
|
|
34095
|
-
}
|
|
34096
|
-
if (!id || !state) {
|
|
34097
|
-
error("Usage: sl streams set <id> <active|disabled>");
|
|
34098
|
-
console.log(dim(`
|
|
34099
|
-
Examples:`));
|
|
34100
|
-
console.log(dim(" sl streams set <id> active"));
|
|
34101
|
-
console.log(dim(" sl streams set <id> disabled"));
|
|
34102
|
-
console.log(dim(" sl streams set --all paused --wait"));
|
|
34103
|
-
console.log(dim(" sl streams set <id> --retry --replay-failed"));
|
|
34104
|
-
console.log(dim(" sl streams set <id> --option maxRetries=5"));
|
|
34105
|
-
process.exit(1);
|
|
34106
|
-
}
|
|
34107
|
-
await setSingleStream(id, state);
|
|
34108
|
-
} catch (err) {
|
|
34109
|
-
handleApiError(err, "set stream state");
|
|
34110
|
-
}
|
|
34111
|
-
});
|
|
34112
|
-
}
|
|
34113
|
-
async function setSingleStream(id, state) {
|
|
34114
|
-
switch (state) {
|
|
34115
|
-
case "active": {
|
|
34116
|
-
const stream = await enableStream(id);
|
|
34117
|
-
success(`Enabled stream: ${stream.name} (status: active)`);
|
|
34118
|
-
break;
|
|
34119
|
-
}
|
|
34120
|
-
case "disabled": {
|
|
34121
|
-
const stream = await disableStream(id);
|
|
34122
|
-
success(`Disabled stream: ${stream.name} (status: inactive)`);
|
|
34123
|
-
break;
|
|
34124
|
-
}
|
|
34125
|
-
default:
|
|
34126
|
-
error(`Unknown state: ${state}. Use active, disabled, or paused (with --all)`);
|
|
34127
|
-
process.exit(1);
|
|
34128
|
-
}
|
|
34129
|
-
}
|
|
34130
|
-
async function setAllStreams(state, wait) {
|
|
34131
|
-
switch (state) {
|
|
34132
|
-
case "paused": {
|
|
34133
|
-
const result = await pauseAllStreams();
|
|
34134
|
-
if (result.paused === 0) {
|
|
34135
|
-
info("No active streams to pause");
|
|
34136
|
-
return;
|
|
34137
|
-
}
|
|
34138
|
-
success(`Paused ${result.paused} stream${result.paused === 1 ? "" : "s"}`);
|
|
34139
|
-
if (wait) {
|
|
34140
|
-
await waitForQueueDrain();
|
|
34141
|
-
}
|
|
34142
|
-
break;
|
|
34143
|
-
}
|
|
34144
|
-
case "active": {
|
|
34145
|
-
const result = await resumeAllStreams();
|
|
34146
|
-
if (result.resumed === 0) {
|
|
34147
|
-
info("No paused streams to resume");
|
|
34148
|
-
return;
|
|
34149
|
-
}
|
|
34150
|
-
success(`Resumed ${result.resumed} stream${result.resumed === 1 ? "" : "s"}`);
|
|
34151
|
-
break;
|
|
34152
|
-
}
|
|
34153
|
-
default:
|
|
34154
|
-
error(`Unknown state for --all: ${state}. Use active or paused`);
|
|
34155
|
-
process.exit(1);
|
|
34156
|
-
}
|
|
34157
|
-
}
|
|
34158
|
-
async function retryStream(id, replayFailed) {
|
|
34159
|
-
const config = await loadConfig();
|
|
34160
|
-
const apiUrl = resolveApiUrl(config);
|
|
34161
|
-
const getRes = await fetch(`${apiUrl}/api/streams/${id}`, {
|
|
34162
|
-
headers: authHeaders(config)
|
|
34163
|
-
});
|
|
34164
|
-
if (!getRes.ok) {
|
|
34165
|
-
const body = await getRes.text();
|
|
34166
|
-
throw new Error(parseError3(getRes.status, body));
|
|
34167
|
-
}
|
|
34168
|
-
const stream = await getRes.json();
|
|
34169
|
-
if (stream.status !== "failed") {
|
|
34170
|
-
warn(`Stream is not in failed status (current status: ${stream.status})`);
|
|
34171
|
-
console.log(dim(`
|
|
34172
|
-
Use 'sl streams set <id> active' to enable an inactive stream.`));
|
|
34173
|
-
process.exit(1);
|
|
34174
|
-
}
|
|
34175
|
-
if (stream.errorMessage) {
|
|
34176
|
-
console.log(red(`Previous error: ${stream.errorMessage}`));
|
|
34177
|
-
console.log("");
|
|
34178
|
-
}
|
|
34179
|
-
const enableRes = await fetch(`${apiUrl}/streams/${id}/enable`, {
|
|
34180
|
-
method: "POST",
|
|
34181
|
-
headers: authHeaders(config)
|
|
34182
|
-
});
|
|
34183
|
-
if (!enableRes.ok) {
|
|
34184
|
-
const body = await enableRes.text();
|
|
34185
|
-
throw new Error(parseError3(enableRes.status, body));
|
|
34186
|
-
}
|
|
34187
|
-
success(`Re-enabled stream: ${stream.name}`);
|
|
34188
|
-
if (replayFailed) {
|
|
34189
|
-
info("Replaying failed deliveries...");
|
|
34190
|
-
const replayRes = await fetch(`${apiUrl}/streams/${id}/replay-failed`, {
|
|
34191
|
-
method: "POST",
|
|
34192
|
-
headers: authHeaders(config)
|
|
34193
|
-
});
|
|
34194
|
-
if (!replayRes.ok) {
|
|
34195
|
-
const body = await replayRes.text();
|
|
34196
|
-
warn(`Failed to replay: ${parseError3(replayRes.status, body)}`);
|
|
34197
|
-
} else {
|
|
34198
|
-
const result = await replayRes.json();
|
|
34199
|
-
success(`Enqueued ${result.jobCount} replay jobs`);
|
|
34200
|
-
}
|
|
34201
|
-
}
|
|
34202
|
-
console.log(dim(`
|
|
34203
|
-
Monitor with: sl streams logs ` + id + " -f"));
|
|
34204
|
-
}
|
|
34205
|
-
async function waitForQueueDrain() {
|
|
34206
|
-
const POLL_INTERVAL_MS = 1000;
|
|
34207
|
-
process.stdout.write(dim("Waiting for jobs to complete..."));
|
|
34208
|
-
while (true) {
|
|
34209
|
-
const stats = await getQueueStats();
|
|
34210
|
-
const active = stats.pending + stats.processing;
|
|
34211
|
-
if (active === 0) {
|
|
34212
|
-
process.stdout.write(`
|
|
34213
|
-
`);
|
|
34214
|
-
success("All jobs completed");
|
|
34215
|
-
return;
|
|
34216
|
-
}
|
|
34217
|
-
process.stdout.write(`\r${dim(`Waiting for jobs to complete... ${active} remaining`)}`);
|
|
34218
|
-
await Bun.sleep(POLL_INTERVAL_MS);
|
|
34219
|
-
}
|
|
34220
|
-
}
|
|
34221
|
-
function parseOptions2(kvPairs) {
|
|
34222
|
-
const result = {};
|
|
34223
|
-
for (const kv of kvPairs) {
|
|
34224
|
-
const eqIndex = kv.indexOf("=");
|
|
34225
|
-
if (eqIndex === -1) {
|
|
34226
|
-
throw new Error(`Invalid option format: "${kv}". Use key=value.`);
|
|
34227
|
-
}
|
|
34228
|
-
const key = kv.slice(0, eqIndex);
|
|
34229
|
-
const raw = kv.slice(eqIndex + 1);
|
|
34230
|
-
if (raw === "true")
|
|
34231
|
-
result[key] = true;
|
|
34232
|
-
else if (raw === "false")
|
|
34233
|
-
result[key] = false;
|
|
34234
|
-
else if (raw !== "" && !isNaN(Number(raw)))
|
|
34235
|
-
result[key] = Number(raw);
|
|
34236
|
-
else
|
|
34237
|
-
result[key] = raw;
|
|
34238
|
-
}
|
|
34239
|
-
return result;
|
|
34240
|
-
}
|
|
34241
|
-
function parseError3(status, body) {
|
|
34242
|
-
let message = `HTTP ${status}`;
|
|
34243
|
-
try {
|
|
34244
|
-
const json = JSON.parse(body);
|
|
34245
|
-
message = json.error || json.message || message;
|
|
34246
|
-
} catch {
|
|
34247
|
-
if (body)
|
|
34248
|
-
message = body;
|
|
34249
|
-
}
|
|
34250
|
-
return message;
|
|
34251
|
-
}
|
|
34252
|
-
|
|
34253
|
-
// src/commands/streams.ts
|
|
34254
|
-
function registerStreamsCommand(program2) {
|
|
34255
|
-
const streams = program2.command("streams").description("Manage event streams");
|
|
34256
|
-
registerNewCommand(streams);
|
|
34257
|
-
registerListCommand(streams);
|
|
34258
|
-
registerGetCommand(streams);
|
|
34259
|
-
registerRegisterCommand(streams);
|
|
34260
|
-
registerDeleteCommand(streams);
|
|
34261
|
-
registerSetCommand(streams);
|
|
34262
|
-
registerLogsCommand(streams);
|
|
34263
|
-
registerReplayCommand(streams);
|
|
34264
|
-
registerRotateSecretCommand(streams);
|
|
34265
|
-
}
|
|
34266
32860
|
// src/commands/status.ts
|
|
34267
32861
|
init_api_client();
|
|
34268
32862
|
init_config();
|
|
@@ -34314,14 +32908,6 @@ function printStatus(status) {
|
|
|
34314
32908
|
const dbColor = status.database.status === "ok" ? green : red;
|
|
34315
32909
|
console.log(` Status: ${dbColor(status.database.status)}`);
|
|
34316
32910
|
console.log("");
|
|
34317
|
-
console.log(blue("Job Queue"));
|
|
34318
|
-
console.log(formatKeyValue([
|
|
34319
|
-
[" Pending", status.queue.pending.toString()],
|
|
34320
|
-
[" Processing", status.queue.processing.toString()],
|
|
34321
|
-
[" Completed", status.queue.completed.toString()],
|
|
34322
|
-
[" Failed", status.queue.failed.toString()]
|
|
34323
|
-
]));
|
|
34324
|
-
console.log("");
|
|
34325
32911
|
console.log(blue("Index Progress"));
|
|
34326
32912
|
if (status.indexProgress.length === 0) {
|
|
34327
32913
|
console.log(dim(" No data indexed yet"));
|
|
@@ -34357,25 +32943,11 @@ function printStatus(status) {
|
|
|
34357
32943
|
}
|
|
34358
32944
|
}
|
|
34359
32945
|
console.log("");
|
|
34360
|
-
|
|
34361
|
-
console.log(formatKeyValue([
|
|
34362
|
-
[" Total", status.streams.total.toString()],
|
|
34363
|
-
[" Active", green(status.streams.active.toString())],
|
|
34364
|
-
[" Paused", yellow(status.streams.paused.toString())],
|
|
34365
|
-
[
|
|
34366
|
-
" Error",
|
|
34367
|
-
status.streams.error > 0 ? red(status.streams.error.toString()) : "0"
|
|
34368
|
-
]
|
|
34369
|
-
]));
|
|
34370
|
-
console.log("");
|
|
34371
|
-
if (status.activeSubgraphs !== undefined || status.recentDeliveries !== undefined) {
|
|
32946
|
+
if (status.activeSubgraphs !== undefined) {
|
|
34372
32947
|
console.log(blue("Activity"));
|
|
34373
|
-
|
|
34374
|
-
|
|
34375
|
-
|
|
34376
|
-
if (status.recentDeliveries !== undefined)
|
|
34377
|
-
pairs.push([" Deliveries (24h)", status.recentDeliveries.toString()]);
|
|
34378
|
-
console.log(formatKeyValue(pairs));
|
|
32948
|
+
console.log(formatKeyValue([
|
|
32949
|
+
[" Active Subgraphs", status.activeSubgraphs.toString()]
|
|
32950
|
+
]));
|
|
34379
32951
|
console.log("");
|
|
34380
32952
|
}
|
|
34381
32953
|
console.log(dim(`Last updated: ${status.timestamp}`));
|
|
@@ -34383,7 +32955,7 @@ function printStatus(status) {
|
|
|
34383
32955
|
// src/commands/sync.ts
|
|
34384
32956
|
init_config();
|
|
34385
32957
|
init_output();
|
|
34386
|
-
import { confirm
|
|
32958
|
+
import { confirm } from "@inquirer/prompts";
|
|
34387
32959
|
import { getDb } from "@secondlayer/shared/db";
|
|
34388
32960
|
import {
|
|
34389
32961
|
countMissingBlocks,
|
|
@@ -34392,7 +32964,7 @@ import {
|
|
|
34392
32964
|
import { StacksNodeClient } from "@secondlayer/shared/node";
|
|
34393
32965
|
import { HiroClient } from "@secondlayer/shared/node/hiro-client";
|
|
34394
32966
|
import { LocalClient } from "@secondlayer/shared/node/local-client";
|
|
34395
|
-
var DEV_DATABASE_URL = "postgres://postgres:postgres@localhost:5432/
|
|
32967
|
+
var DEV_DATABASE_URL = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
|
|
34396
32968
|
function registerSyncCommand(program2) {
|
|
34397
32969
|
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() {
|
|
34398
32970
|
const opts = this.opts();
|
|
@@ -34503,7 +33075,7 @@ Examples:`));
|
|
|
34503
33075
|
if (useHiro) {
|
|
34504
33076
|
console.log(dim("Note: Hiro API fetches are slower due to per-tx event lookups."));
|
|
34505
33077
|
}
|
|
34506
|
-
const confirmed = await
|
|
33078
|
+
const confirmed = await confirm({
|
|
34507
33079
|
message: "Continue?",
|
|
34508
33080
|
default: true
|
|
34509
33081
|
});
|
|
@@ -34600,14 +33172,14 @@ Examples:`));
|
|
|
34600
33172
|
init_config();
|
|
34601
33173
|
init_dev_state();
|
|
34602
33174
|
init_output();
|
|
34603
|
-
import { confirm as
|
|
33175
|
+
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
34604
33176
|
import { getDb as getDb2, sql } from "@secondlayer/shared/db";
|
|
34605
33177
|
import {
|
|
34606
33178
|
countMissingBlocks as countMissingBlocks2,
|
|
34607
33179
|
findGaps as findGaps2
|
|
34608
33180
|
} from "@secondlayer/shared/db/queries/integrity";
|
|
34609
33181
|
import { StacksNodeClient as StacksNodeClient2 } from "@secondlayer/shared/node";
|
|
34610
|
-
var DEV_DATABASE_URL2 = "postgres://postgres:postgres@localhost:5432/
|
|
33182
|
+
var DEV_DATABASE_URL2 = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
|
|
34611
33183
|
function registerDbCommand(program2) {
|
|
34612
33184
|
const dbCmd = program2.command("db").description("Inspect indexer database tables").hook("preAction", async () => {
|
|
34613
33185
|
await requireLocalNetwork();
|
|
@@ -34630,7 +33202,7 @@ function registerDbCommand(program2) {
|
|
|
34630
33202
|
const opts = this.opts();
|
|
34631
33203
|
await showGaps(Number.parseInt(opts.limit), opts.json);
|
|
34632
33204
|
});
|
|
34633
|
-
dbCmd.command("reset").description("Truncate all indexed data (blocks, txs, events
|
|
33205
|
+
dbCmd.command("reset").description("Truncate all indexed data (blocks, txs, events)").option("-y, --yes", "Skip confirmation prompt").action(async function() {
|
|
34634
33206
|
const opts = this.opts();
|
|
34635
33207
|
await resetDatabase(opts.yes);
|
|
34636
33208
|
});
|
|
@@ -34806,12 +33378,12 @@ async function resetDatabase(skipConfirm) {
|
|
|
34806
33378
|
console.log(` ${red(blockCount.toString())} blocks`);
|
|
34807
33379
|
console.log(` ${red(txCount.toString())} transactions`);
|
|
34808
33380
|
console.log(` ${red(eventCount.toString())} events`);
|
|
34809
|
-
console.log(` ${dim("+
|
|
33381
|
+
console.log(` ${dim("+ index_progress")}`);
|
|
34810
33382
|
console.log("");
|
|
34811
|
-
console.log(dim("Note:
|
|
33383
|
+
console.log(dim("Note: Subgraph configurations will be preserved."));
|
|
34812
33384
|
console.log("");
|
|
34813
33385
|
if (!skipConfirm) {
|
|
34814
|
-
const confirmed = await
|
|
33386
|
+
const confirmed = await confirm2({
|
|
34815
33387
|
message: "Are you sure you want to reset the database?",
|
|
34816
33388
|
default: false
|
|
34817
33389
|
});
|
|
@@ -34821,7 +33393,7 @@ async function resetDatabase(skipConfirm) {
|
|
|
34821
33393
|
}
|
|
34822
33394
|
}
|
|
34823
33395
|
info("Truncating tables...");
|
|
34824
|
-
await sql`TRUNCATE TABLE
|
|
33396
|
+
await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
|
|
34825
33397
|
console.log("");
|
|
34826
33398
|
success("Database reset complete");
|
|
34827
33399
|
console.log("");
|
|
@@ -34845,10 +33417,10 @@ async function resyncDatabase(skipConfirm, backfill) {
|
|
|
34845
33417
|
console.log(" 3. Fetch all blocks from node (backfill)");
|
|
34846
33418
|
}
|
|
34847
33419
|
console.log("");
|
|
34848
|
-
console.log(dim("Note:
|
|
33420
|
+
console.log(dim("Note: Subgraph configurations will be preserved."));
|
|
34849
33421
|
console.log("");
|
|
34850
33422
|
if (!skipConfirm) {
|
|
34851
|
-
const confirmed = await
|
|
33423
|
+
const confirmed = await confirm2({
|
|
34852
33424
|
message: "Are you sure you want to resync?",
|
|
34853
33425
|
default: false
|
|
34854
33426
|
});
|
|
@@ -34858,7 +33430,7 @@ async function resyncDatabase(skipConfirm, backfill) {
|
|
|
34858
33430
|
}
|
|
34859
33431
|
}
|
|
34860
33432
|
info("Truncating tables...");
|
|
34861
|
-
await sql`TRUNCATE TABLE
|
|
33433
|
+
await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
|
|
34862
33434
|
console.log(green(" ✓ Database reset"));
|
|
34863
33435
|
const state = await loadDevState();
|
|
34864
33436
|
if (state?.services?.indexer && isProcessRunning(state.services.indexer.pid)) {
|
|
@@ -34949,336 +33521,10 @@ async function resyncDatabase(skipConfirm, backfill) {
|
|
|
34949
33521
|
process.exit(1);
|
|
34950
33522
|
}
|
|
34951
33523
|
}
|
|
34952
|
-
// src/commands/receiver.ts
|
|
34953
|
-
init_config();
|
|
34954
|
-
init_output();
|
|
34955
|
-
import { join as join5 } from "node:path";
|
|
34956
|
-
function registerReceiverCommand(program2) {
|
|
34957
|
-
const receiver = program2.command("receiver").description("Receiver development tools").hook("preAction", async () => {
|
|
34958
|
-
await requireLocalNetwork();
|
|
34959
|
-
});
|
|
34960
|
-
receiver.command("init <directory>").description("Scaffold a receiver handler with types and signature verification").option("-n, --name <name>", "Stream name", "my-stream").option("--network <network>", "Network (mainnet/testnet)", "mainnet").option("-p, --port <port>", "Server port", "4000").action(async (directory, options) => {
|
|
34961
|
-
try {
|
|
34962
|
-
const config = await loadConfig();
|
|
34963
|
-
const port = Number.parseInt(options.port);
|
|
34964
|
-
const network = options.network;
|
|
34965
|
-
const dir = join5(process.cwd(), directory);
|
|
34966
|
-
const dirExists = await Bun.file(join5(dir, "package.json")).exists();
|
|
34967
|
-
if (dirExists) {
|
|
34968
|
-
error(`Directory ${directory} already contains a project`);
|
|
34969
|
-
process.exit(1);
|
|
34970
|
-
}
|
|
34971
|
-
await Bun.$`mkdir -p ${dir}`.quiet();
|
|
34972
|
-
await generateServerFile(dir, port);
|
|
34973
|
-
await generateTypesFile(dir);
|
|
34974
|
-
await generateStreamJson(dir, options.name, network, port, config.defaultEndpointUrl);
|
|
34975
|
-
await generateEnvFile(dir);
|
|
34976
|
-
await generatePackageJson(dir, options.name);
|
|
34977
|
-
success(`Created receiver handler in ${directory}/`);
|
|
34978
|
-
console.log("");
|
|
34979
|
-
console.log(" Files created:");
|
|
34980
|
-
console.log(` ${dim("server.ts")} Receiver server with HMAC verification`);
|
|
34981
|
-
console.log(` ${dim("types.ts")} Payload type definitions`);
|
|
34982
|
-
console.log(` ${dim("stream.json")} Stream configuration`);
|
|
34983
|
-
console.log(` ${dim(".env")} Environment variables`);
|
|
34984
|
-
console.log(` ${dim("package.json")} Dependencies`);
|
|
34985
|
-
console.log("");
|
|
34986
|
-
console.log(" Next steps:");
|
|
34987
|
-
console.log(` cd ${directory}`);
|
|
34988
|
-
console.log(" bun install");
|
|
34989
|
-
console.log(" bun server.ts");
|
|
34990
|
-
console.log("");
|
|
34991
|
-
console.log(" Then register your stream:");
|
|
34992
|
-
console.log(` sl streams register ${directory}/stream.json`);
|
|
34993
|
-
console.log("");
|
|
34994
|
-
} catch (err) {
|
|
34995
|
-
error(`Failed to scaffold receiver: ${err}`);
|
|
34996
|
-
process.exit(1);
|
|
34997
|
-
}
|
|
34998
|
-
});
|
|
34999
|
-
}
|
|
35000
|
-
async function generateServerFile(dir, port) {
|
|
35001
|
-
const content = `import type { DeliveryPayload } from "./types.ts";
|
|
35002
|
-
|
|
35003
|
-
const SIGNING_SECRET = process.env.STREAMS_SIGNING_SECRET;
|
|
35004
|
-
|
|
35005
|
-
/**
|
|
35006
|
-
* Verify HMAC signature from Stacks Streams
|
|
35007
|
-
*/
|
|
35008
|
-
async function verifySignature(body: string, signature: string | null): Promise<boolean> {
|
|
35009
|
-
if (!SIGNING_SECRET || !signature) return false;
|
|
35010
|
-
|
|
35011
|
-
const encoder = new TextEncoder();
|
|
35012
|
-
const key = await crypto.subtle.importKey(
|
|
35013
|
-
"raw",
|
|
35014
|
-
encoder.encode(SIGNING_SECRET),
|
|
35015
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
35016
|
-
false,
|
|
35017
|
-
["sign"]
|
|
35018
|
-
);
|
|
35019
|
-
|
|
35020
|
-
const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(body));
|
|
35021
|
-
const expected = Buffer.from(sig).toString("hex");
|
|
35022
|
-
|
|
35023
|
-
return signature === expected;
|
|
35024
|
-
}
|
|
35025
|
-
|
|
35026
|
-
/**
|
|
35027
|
-
* Handle incoming delivery payload
|
|
35028
|
-
*/
|
|
35029
|
-
async function handlePayload(payload: DeliveryPayload): Promise<void> {
|
|
35030
|
-
console.log(\`Block \${payload.block.height}: \${payload.matches.events.length} events\`);
|
|
35031
|
-
|
|
35032
|
-
for (const event of payload.matches.events) {
|
|
35033
|
-
switch (event.type) {
|
|
35034
|
-
case "stx_transfer_event":
|
|
35035
|
-
console.log(\` STX transfer: \${event.data.amount} from \${event.data.sender}\`);
|
|
35036
|
-
// TODO: Insert into your database
|
|
35037
|
-
break;
|
|
35038
|
-
|
|
35039
|
-
case "ft_transfer_event":
|
|
35040
|
-
console.log(\` FT transfer: \${event.data.amount} of \${event.data.asset_identifier}\`);
|
|
35041
|
-
break;
|
|
35042
|
-
|
|
35043
|
-
case "nft_transfer_event":
|
|
35044
|
-
console.log(\` NFT transfer: \${event.data.asset_identifier}\`);
|
|
35045
|
-
break;
|
|
35046
|
-
|
|
35047
|
-
case "contract_call":
|
|
35048
|
-
console.log(\` Contract call: \${event.data.contract_id}.\${event.data.function_name}\`);
|
|
35049
|
-
break;
|
|
35050
|
-
|
|
35051
|
-
default:
|
|
35052
|
-
console.log(\` Event: \${event.type}\`);
|
|
35053
|
-
}
|
|
35054
|
-
}
|
|
35055
|
-
}
|
|
35056
|
-
|
|
35057
|
-
Bun.serve({
|
|
35058
|
-
port: ${port},
|
|
35059
|
-
|
|
35060
|
-
async fetch(req) {
|
|
35061
|
-
const url = new URL(req.url);
|
|
35062
|
-
|
|
35063
|
-
// Health check
|
|
35064
|
-
if (req.method === "GET" && url.pathname === "/health") {
|
|
35065
|
-
return new Response("ok");
|
|
35066
|
-
}
|
|
35067
|
-
|
|
35068
|
-
// Receiver endpoint
|
|
35069
|
-
if (req.method === "POST" && url.pathname === "/payload") {
|
|
35070
|
-
const body = await req.text();
|
|
35071
|
-
const signature = req.headers.get("x-streams-signature");
|
|
35072
|
-
|
|
35073
|
-
// Verify signature
|
|
35074
|
-
if (SIGNING_SECRET) {
|
|
35075
|
-
const valid = await verifySignature(body, signature);
|
|
35076
|
-
if (!valid) {
|
|
35077
|
-
console.error("Invalid signature");
|
|
35078
|
-
return new Response("Invalid signature", { status: 401 });
|
|
35079
|
-
}
|
|
35080
|
-
}
|
|
35081
|
-
|
|
35082
|
-
try {
|
|
35083
|
-
const payload: DeliveryPayload = JSON.parse(body);
|
|
35084
|
-
await handlePayload(payload);
|
|
35085
|
-
return new Response("ok");
|
|
35086
|
-
} catch (err) {
|
|
35087
|
-
console.error("Failed to process payload:", err);
|
|
35088
|
-
return new Response("Internal error", { status: 500 });
|
|
35089
|
-
}
|
|
35090
|
-
}
|
|
35091
|
-
|
|
35092
|
-
return new Response("Not found", { status: 404 });
|
|
35093
|
-
},
|
|
35094
|
-
});
|
|
35095
|
-
|
|
35096
|
-
console.log(\`Receiver server listening on http://localhost:${port}/payload\`);
|
|
35097
|
-
`;
|
|
35098
|
-
await Bun.write(join5(dir, "server.ts"), content);
|
|
35099
|
-
}
|
|
35100
|
-
async function generateTypesFile(dir) {
|
|
35101
|
-
const content = `/**
|
|
35102
|
-
* Stacks Streams Delivery Payload Types
|
|
35103
|
-
*
|
|
35104
|
-
* These types match the payload structure sent by Stacks Streams.
|
|
35105
|
-
*/
|
|
35106
|
-
|
|
35107
|
-
export interface DeliveryPayload {
|
|
35108
|
-
streamId: string;
|
|
35109
|
-
streamName: string;
|
|
35110
|
-
network: "mainnet" | "testnet";
|
|
35111
|
-
block: BlockMetadata;
|
|
35112
|
-
matches: {
|
|
35113
|
-
transactions: TransactionMatch[];
|
|
35114
|
-
events: EventMatch[];
|
|
35115
|
-
};
|
|
35116
|
-
isBackfill: boolean;
|
|
35117
|
-
deliveredAt: string;
|
|
35118
|
-
}
|
|
35119
|
-
|
|
35120
|
-
export interface BlockMetadata {
|
|
35121
|
-
height: number;
|
|
35122
|
-
hash: string;
|
|
35123
|
-
parentHash: string;
|
|
35124
|
-
burnBlockHeight: number;
|
|
35125
|
-
timestamp: number;
|
|
35126
|
-
}
|
|
35127
|
-
|
|
35128
|
-
export interface TransactionMatch {
|
|
35129
|
-
txId: string;
|
|
35130
|
-
type: string;
|
|
35131
|
-
sender: string;
|
|
35132
|
-
status: "success" | "abort_by_response" | "abort_by_post_condition";
|
|
35133
|
-
contractId: string | null;
|
|
35134
|
-
functionName: string | null;
|
|
35135
|
-
rawTx?: string;
|
|
35136
|
-
}
|
|
35137
|
-
|
|
35138
|
-
export type EventMatch =
|
|
35139
|
-
| StxTransferEvent
|
|
35140
|
-
| FtTransferEvent
|
|
35141
|
-
| NftTransferEvent
|
|
35142
|
-
| ContractCallEvent
|
|
35143
|
-
| PrintEvent
|
|
35144
|
-
| GenericEvent;
|
|
35145
|
-
|
|
35146
|
-
interface BaseEvent {
|
|
35147
|
-
txId: string;
|
|
35148
|
-
eventIndex: number;
|
|
35149
|
-
}
|
|
35150
|
-
|
|
35151
|
-
export interface StxTransferEvent extends BaseEvent {
|
|
35152
|
-
type: "stx_transfer_event";
|
|
35153
|
-
data: {
|
|
35154
|
-
sender: string;
|
|
35155
|
-
recipient: string;
|
|
35156
|
-
amount: string;
|
|
35157
|
-
memo: string;
|
|
35158
|
-
};
|
|
35159
|
-
}
|
|
35160
|
-
|
|
35161
|
-
export interface FtTransferEvent extends BaseEvent {
|
|
35162
|
-
type: "ft_transfer_event";
|
|
35163
|
-
data: {
|
|
35164
|
-
sender: string;
|
|
35165
|
-
recipient: string;
|
|
35166
|
-
amount: string;
|
|
35167
|
-
asset_identifier: string;
|
|
35168
|
-
};
|
|
35169
|
-
}
|
|
35170
|
-
|
|
35171
|
-
export interface NftTransferEvent extends BaseEvent {
|
|
35172
|
-
type: "nft_transfer_event";
|
|
35173
|
-
data: {
|
|
35174
|
-
sender: string;
|
|
35175
|
-
recipient: string;
|
|
35176
|
-
asset_identifier: string;
|
|
35177
|
-
value: unknown;
|
|
35178
|
-
};
|
|
35179
|
-
}
|
|
35180
|
-
|
|
35181
|
-
export interface ContractCallEvent extends BaseEvent {
|
|
35182
|
-
type: "contract_call";
|
|
35183
|
-
data: {
|
|
35184
|
-
contract_id: string;
|
|
35185
|
-
function_name: string;
|
|
35186
|
-
function_args: unknown[];
|
|
35187
|
-
};
|
|
35188
|
-
}
|
|
35189
|
-
|
|
35190
|
-
export interface PrintEvent extends BaseEvent {
|
|
35191
|
-
type: "print_event";
|
|
35192
|
-
data: {
|
|
35193
|
-
contract_id: string;
|
|
35194
|
-
topic: string;
|
|
35195
|
-
value: unknown;
|
|
35196
|
-
};
|
|
35197
|
-
}
|
|
35198
|
-
|
|
35199
|
-
export interface GenericEvent extends BaseEvent {
|
|
35200
|
-
type: string;
|
|
35201
|
-
data: unknown;
|
|
35202
|
-
}
|
|
35203
|
-
|
|
35204
|
-
/**
|
|
35205
|
-
* Type guard to narrow event types
|
|
35206
|
-
*/
|
|
35207
|
-
export function isStxTransfer(event: EventMatch): event is StxTransferEvent {
|
|
35208
|
-
return event.type === "stx_transfer_event";
|
|
35209
|
-
}
|
|
35210
|
-
|
|
35211
|
-
export function isFtTransfer(event: EventMatch): event is FtTransferEvent {
|
|
35212
|
-
return event.type === "ft_transfer_event";
|
|
35213
|
-
}
|
|
35214
|
-
|
|
35215
|
-
export function isNftTransfer(event: EventMatch): event is NftTransferEvent {
|
|
35216
|
-
return event.type === "nft_transfer_event";
|
|
35217
|
-
}
|
|
35218
|
-
|
|
35219
|
-
export function isContractCall(event: EventMatch): event is ContractCallEvent {
|
|
35220
|
-
return event.type === "contract_call";
|
|
35221
|
-
}
|
|
35222
|
-
|
|
35223
|
-
export function isPrintEvent(event: EventMatch): event is PrintEvent {
|
|
35224
|
-
return event.type === "print_event";
|
|
35225
|
-
}
|
|
35226
|
-
`;
|
|
35227
|
-
await Bun.write(join5(dir, "types.ts"), content);
|
|
35228
|
-
}
|
|
35229
|
-
async function generateStreamJson(dir, name, network, port, _defaultEndpointUrl) {
|
|
35230
|
-
const content = {
|
|
35231
|
-
name,
|
|
35232
|
-
network,
|
|
35233
|
-
endpointUrl: `http://localhost:${port}/payload`,
|
|
35234
|
-
filters: [
|
|
35235
|
-
{
|
|
35236
|
-
type: "stx_transfer",
|
|
35237
|
-
minAmount: 1e6
|
|
35238
|
-
}
|
|
35239
|
-
],
|
|
35240
|
-
options: {
|
|
35241
|
-
decodeClarityValues: true,
|
|
35242
|
-
includeRawTx: false,
|
|
35243
|
-
includeBlockMetadata: true,
|
|
35244
|
-
rateLimit: 10,
|
|
35245
|
-
timeoutMs: 1e4,
|
|
35246
|
-
maxRetries: 3
|
|
35247
|
-
}
|
|
35248
|
-
};
|
|
35249
|
-
await Bun.write(join5(dir, "stream.json"), JSON.stringify(content, null, 2) + `
|
|
35250
|
-
`);
|
|
35251
|
-
}
|
|
35252
|
-
async function generateEnvFile(dir) {
|
|
35253
|
-
const content = `# Stacks Streams Signing Secret
|
|
35254
|
-
# Get this from: sl streams register stream.json
|
|
35255
|
-
STREAMS_SIGNING_SECRET=
|
|
35256
|
-
|
|
35257
|
-
# Add your database connection, etc.
|
|
35258
|
-
# DATABASE_URL=postgres://...
|
|
35259
|
-
`;
|
|
35260
|
-
await Bun.write(join5(dir, ".env"), content);
|
|
35261
|
-
}
|
|
35262
|
-
async function generatePackageJson(dir, name) {
|
|
35263
|
-
const content = {
|
|
35264
|
-
name: `${name}-receiver`,
|
|
35265
|
-
version: "0.1.0",
|
|
35266
|
-
type: "module",
|
|
35267
|
-
scripts: {
|
|
35268
|
-
start: "bun server.ts",
|
|
35269
|
-
dev: "bun --watch server.ts"
|
|
35270
|
-
},
|
|
35271
|
-
dependencies: {},
|
|
35272
|
-
devDependencies: {
|
|
35273
|
-
"@types/bun": "latest"
|
|
35274
|
-
}
|
|
35275
|
-
};
|
|
35276
|
-
await Bun.write(join5(dir, "package.json"), JSON.stringify(content, null, 2) + `
|
|
35277
|
-
`);
|
|
35278
|
-
}
|
|
35279
33524
|
// src/commands/subgraphs.ts
|
|
35280
33525
|
import { existsSync, mkdirSync, watch } from "node:fs";
|
|
35281
33526
|
import { resolve } from "node:path";
|
|
33527
|
+
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
35282
33528
|
|
|
35283
33529
|
// src/generators/subgraph-scaffold.ts
|
|
35284
33530
|
init_format();
|
|
@@ -35334,11 +33580,11 @@ function mapType(abiType, nullable) {
|
|
|
35334
33580
|
function toCamelCase(str) {
|
|
35335
33581
|
return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
35336
33582
|
}
|
|
35337
|
-
async function generateSubgraphScaffold(
|
|
35338
|
-
const { contractId, functions } =
|
|
33583
|
+
async function generateSubgraphScaffold(input) {
|
|
33584
|
+
const { contractId, functions } = input;
|
|
35339
33585
|
const contractParts = contractId.split(".");
|
|
35340
33586
|
const contractName = contractParts[contractParts.length - 1] ?? contractId;
|
|
35341
|
-
const subgraphName =
|
|
33587
|
+
const subgraphName = input.subgraphName ?? contractName;
|
|
35342
33588
|
const publicFunctions = functions.filter((f) => f.access === "public");
|
|
35343
33589
|
if (publicFunctions.length === 0) {
|
|
35344
33590
|
throw new Error(`No public functions found in ${contractId}`);
|
|
@@ -35484,7 +33730,6 @@ init_config();
|
|
|
35484
33730
|
init_fs();
|
|
35485
33731
|
init_output();
|
|
35486
33732
|
init_clarity();
|
|
35487
|
-
import { confirm as confirm6 } from "@inquirer/prompts";
|
|
35488
33733
|
|
|
35489
33734
|
// src/templates/subgraph.ts
|
|
35490
33735
|
function generateSubgraphTemplate(name) {
|
|
@@ -35630,16 +33875,11 @@ Stopped watching.`);
|
|
|
35630
33875
|
validateSubgraphDefinition(def);
|
|
35631
33876
|
if (config.network !== "local") {
|
|
35632
33877
|
info(`Bundling for remote deploy (${config.network})...`);
|
|
35633
|
-
const
|
|
35634
|
-
const
|
|
35635
|
-
|
|
35636
|
-
|
|
35637
|
-
|
|
35638
|
-
format: "esm",
|
|
35639
|
-
external: ["@secondlayer/subgraphs"],
|
|
35640
|
-
write: false
|
|
35641
|
-
});
|
|
35642
|
-
const handlerCode = new TextDecoder().decode(buildResult.outputFiles[0].contents);
|
|
33878
|
+
const { readFile: readFile2 } = await import("node:fs/promises");
|
|
33879
|
+
const source = await readFile2(absPath, "utf8");
|
|
33880
|
+
const { bundleSubgraphCode } = await import("@secondlayer/bundler");
|
|
33881
|
+
const bundled = await bundleSubgraphCode(source);
|
|
33882
|
+
const handlerCode = bundled.handlerCode;
|
|
35643
33883
|
const result = await deploySubgraphApi({
|
|
35644
33884
|
name: def.name,
|
|
35645
33885
|
version: options2.version,
|
|
@@ -35656,7 +33896,7 @@ Stopped watching.`);
|
|
|
35656
33896
|
if (result.diff) {
|
|
35657
33897
|
const { addedTables, addedColumns, breakingChanges } = result.diff;
|
|
35658
33898
|
if (breakingChanges.length > 0) {
|
|
35659
|
-
warn(
|
|
33899
|
+
warn("Breaking changes detected:");
|
|
35660
33900
|
for (const r of breakingChanges)
|
|
35661
33901
|
warn(` ✗ ${r}`);
|
|
35662
33902
|
}
|
|
@@ -35666,8 +33906,8 @@ Stopped watching.`);
|
|
|
35666
33906
|
info(` + columns: ${t}.${cols.join(", ")}`);
|
|
35667
33907
|
}
|
|
35668
33908
|
}
|
|
35669
|
-
const confirmed = options2.force || await
|
|
35670
|
-
message:
|
|
33909
|
+
const confirmed = options2.force || await confirm3({
|
|
33910
|
+
message: "⚠ This will drop all data and reindex from scratch. Continue?"
|
|
35671
33911
|
});
|
|
35672
33912
|
if (!confirmed) {
|
|
35673
33913
|
info("Aborted.");
|
|
@@ -35797,7 +34037,7 @@ Table endpoints:`));
|
|
|
35797
34037
|
try {
|
|
35798
34038
|
const fromBlock = Number.parseInt(options2.from, 10);
|
|
35799
34039
|
const toBlock = Number.parseInt(options2.to, 10);
|
|
35800
|
-
if (isNaN(fromBlock) || isNaN(toBlock)) {
|
|
34040
|
+
if (Number.isNaN(fromBlock) || Number.isNaN(toBlock)) {
|
|
35801
34041
|
error("--from and --to must be valid block numbers");
|
|
35802
34042
|
process.exit(1);
|
|
35803
34043
|
}
|
|
@@ -35886,7 +34126,10 @@ ${result.meta.total} gap(s), ${result.meta.totalMissingBlocks} total missing blo
|
|
|
35886
34126
|
console.log(dim("No rows found"));
|
|
35887
34127
|
return;
|
|
35888
34128
|
}
|
|
35889
|
-
const
|
|
34129
|
+
const firstRow = rows[0];
|
|
34130
|
+
if (!firstRow)
|
|
34131
|
+
return;
|
|
34132
|
+
const columns = Object.keys(firstRow);
|
|
35890
34133
|
const tableRows = rows.map((row) => columns.map((col) => {
|
|
35891
34134
|
const val = row[col];
|
|
35892
34135
|
if (val === null || val === undefined)
|
|
@@ -35905,8 +34148,8 @@ ${rows.length} row(s)`));
|
|
|
35905
34148
|
subgraphs.command("delete <name>").description("Delete a subgraph and its data").option("-y, --yes", "Skip confirmation").action(async (name, options2) => {
|
|
35906
34149
|
try {
|
|
35907
34150
|
if (!options2.yes) {
|
|
35908
|
-
const { confirm:
|
|
35909
|
-
const ok = await
|
|
34151
|
+
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
|
34152
|
+
const ok = await confirm4({
|
|
35910
34153
|
message: `Delete subgraph "${name}" and all its data? This cannot be undone.`
|
|
35911
34154
|
});
|
|
35912
34155
|
if (!ok) {
|
|
@@ -35964,7 +34207,7 @@ ${rows.length} row(s)`));
|
|
|
35964
34207
|
const client = new StacksApiClient(network, apiKey);
|
|
35965
34208
|
const contractInfo = await client.getContractInfo(contractAddress);
|
|
35966
34209
|
const abi = parseApiResponse(contractInfo);
|
|
35967
|
-
info(
|
|
34210
|
+
info("Generating scaffold...");
|
|
35968
34211
|
const content = await generateSubgraphScaffold({
|
|
35969
34212
|
contractId: contractAddress,
|
|
35970
34213
|
functions: abi.functions
|
|
@@ -35989,7 +34232,7 @@ ${rows.length} row(s)`));
|
|
|
35989
34232
|
const outPath = resolve(options2.output);
|
|
35990
34233
|
info(`Fetching subgraph metadata for "${subgraphName}"...`);
|
|
35991
34234
|
const subgraphDetail = await getSubgraphApi(subgraphName);
|
|
35992
|
-
info(
|
|
34235
|
+
info("Generating typed client...");
|
|
35993
34236
|
const content = await generateSubgraphConsumer(subgraphName, subgraphDetail);
|
|
35994
34237
|
const dir = resolve(outPath, "..");
|
|
35995
34238
|
if (!existsSync(dir))
|
|
@@ -36015,7 +34258,7 @@ function registerStackCommand(program2) {
|
|
|
36015
34258
|
}).action(async (options2) => {
|
|
36016
34259
|
await stackStart(options2);
|
|
36017
34260
|
});
|
|
36018
|
-
stack.command("stop").description("Stop the full stack").option("--no-node", "Skip stopping the Stacks node").option("--no-dev", "Skip stopping dev services").option("--wait", "
|
|
34261
|
+
stack.command("stop").description("Stop the full stack").option("--no-node", "Skip stopping the Stacks node").option("--no-dev", "Skip stopping dev services").option("--wait", "Wait for in-flight work to drain before stopping").hook("preAction", async () => {
|
|
36019
34262
|
await requireLocalNetwork();
|
|
36020
34263
|
}).action(async (options2) => {
|
|
36021
34264
|
await stackStop(options2);
|
|
@@ -36050,13 +34293,13 @@ async function stackStart(options2) {
|
|
|
36050
34293
|
process.exit(1);
|
|
36051
34294
|
}
|
|
36052
34295
|
console.log("");
|
|
36053
|
-
console.log(blue("Starting
|
|
34296
|
+
console.log(blue("Starting Secondlayer Stack"));
|
|
36054
34297
|
console.log(dim(` Network: ${network}`));
|
|
36055
34298
|
console.log("");
|
|
36056
34299
|
if (options2.node) {
|
|
36057
34300
|
const nodePath = config.node?.installPath;
|
|
36058
34301
|
if (!nodePath) {
|
|
36059
|
-
warn("No node configured, skipping. Run 'sl setup' to configure.");
|
|
34302
|
+
warn("No node configured, skipping. Run 'sl local node setup' to configure.");
|
|
36060
34303
|
} else if (await isNodeRunning()) {
|
|
36061
34304
|
info("Node already running");
|
|
36062
34305
|
} else {
|
|
@@ -36126,30 +34369,7 @@ async function stackStart(options2) {
|
|
|
36126
34369
|
}
|
|
36127
34370
|
async function stackStop(options2) {
|
|
36128
34371
|
console.log("");
|
|
36129
|
-
info("Stopping
|
|
36130
|
-
if (options2.wait) {
|
|
36131
|
-
try {
|
|
36132
|
-
const { pauseAllStreams: pauseAllStreams2, getQueueStats: getQueueStats2 } = await Promise.resolve().then(() => (init_api_client(), exports_api_client));
|
|
36133
|
-
info("Pausing streams...");
|
|
36134
|
-
await pauseAllStreams2();
|
|
36135
|
-
process.stdout.write(dim("Waiting for jobs to complete..."));
|
|
36136
|
-
for (let i = 0;i < 300; i++) {
|
|
36137
|
-
const stats = await getQueueStats2();
|
|
36138
|
-
const active = stats.pending + stats.processing;
|
|
36139
|
-
if (active === 0) {
|
|
36140
|
-
process.stdout.write(`
|
|
36141
|
-
`);
|
|
36142
|
-
success("Queue drained");
|
|
36143
|
-
break;
|
|
36144
|
-
}
|
|
36145
|
-
process.stdout.write(`\r${dim(`Waiting for jobs... ${active} remaining`)}`);
|
|
36146
|
-
await Bun.sleep(1000);
|
|
36147
|
-
}
|
|
36148
|
-
} catch {
|
|
36149
|
-
warn("Could not pause streams (API may not be running)");
|
|
36150
|
-
}
|
|
36151
|
-
console.log("");
|
|
36152
|
-
}
|
|
34372
|
+
info("Stopping Secondlayer Stack...");
|
|
36153
34373
|
if (options2.dev) {
|
|
36154
34374
|
if (await isDevRunning()) {
|
|
36155
34375
|
info("Stopping dev services...");
|
|
@@ -36177,7 +34397,7 @@ async function stackStop(options2) {
|
|
|
36177
34397
|
}
|
|
36178
34398
|
}
|
|
36179
34399
|
try {
|
|
36180
|
-
const result = await Bun.$`docker ps -a --format json --filter "name=
|
|
34400
|
+
const result = await Bun.$`docker ps -a --format json --filter "name=secondlayer-dev" --filter "name=stacks"`.quiet().nothrow();
|
|
36181
34401
|
if (result.exitCode === 0) {
|
|
36182
34402
|
const lines = result.stdout.toString().trim().split(`
|
|
36183
34403
|
`).filter(Boolean);
|
|
@@ -36257,7 +34477,7 @@ async function checkHealth() {
|
|
|
36257
34477
|
}
|
|
36258
34478
|
const containers = [];
|
|
36259
34479
|
try {
|
|
36260
|
-
const result = await Bun.$`docker ps -a --format json --filter "name=stacks" --filter "name=
|
|
34480
|
+
const result = await Bun.$`docker ps -a --format json --filter "name=stacks" --filter "name=secondlayer-dev"`.quiet().nothrow();
|
|
36261
34481
|
if (result.exitCode === 0) {
|
|
36262
34482
|
const lines = result.stdout.toString().trim().split(`
|
|
36263
34483
|
`).filter(Boolean);
|
|
@@ -36323,13 +34543,12 @@ async function checkHealth() {
|
|
|
36323
34543
|
}
|
|
36324
34544
|
const infrastructure = { postgres: false };
|
|
36325
34545
|
try {
|
|
36326
|
-
const pg = await Bun.$`docker ps -q -f name=
|
|
34546
|
+
const pg = await Bun.$`docker ps -q -f name=secondlayer-dev-postgres`.quiet().nothrow();
|
|
36327
34547
|
infrastructure.postgres = pg.stdout.toString().trim().length > 0;
|
|
36328
34548
|
} catch {}
|
|
36329
34549
|
const portsToCheck = [
|
|
36330
34550
|
{ port: config.ports.api, name: "API" },
|
|
36331
34551
|
{ port: config.ports.indexer, name: "Indexer" },
|
|
36332
|
-
{ port: config.ports.receiver, name: "Receiver" },
|
|
36333
34552
|
{ port: 20443, name: "Node RPC" }
|
|
36334
34553
|
];
|
|
36335
34554
|
for (const { port, name } of portsToCheck) {
|
|
@@ -36431,17 +34650,6 @@ async function runHostedDoctor(jsonOutput) {
|
|
|
36431
34650
|
}
|
|
36432
34651
|
console.log("");
|
|
36433
34652
|
}
|
|
36434
|
-
const streams = statusData.streams;
|
|
36435
|
-
if (streams) {
|
|
36436
|
-
console.log(blue("Streams"));
|
|
36437
|
-
console.log(formatKeyValue([
|
|
36438
|
-
[" Total", streams.total.toString()],
|
|
36439
|
-
[" Active", green(streams.active.toString())],
|
|
36440
|
-
[" Paused", yellow(streams.paused.toString())],
|
|
36441
|
-
[" Error", streams.error > 0 ? red(streams.error.toString()) : "0"]
|
|
36442
|
-
]));
|
|
36443
|
-
console.log("");
|
|
36444
|
-
}
|
|
36445
34653
|
}
|
|
36446
34654
|
console.log(blue("Issues"));
|
|
36447
34655
|
if (issues.length === 0) {
|
|
@@ -36574,7 +34782,7 @@ init_api_client();
|
|
|
36574
34782
|
init_config();
|
|
36575
34783
|
init_output();
|
|
36576
34784
|
import { hostname } from "node:os";
|
|
36577
|
-
import { input
|
|
34785
|
+
import { input } from "@inquirer/prompts";
|
|
36578
34786
|
function registerAuthCommand(program2) {
|
|
36579
34787
|
const auth = program2.command("auth").description("Manage authentication and API keys");
|
|
36580
34788
|
auth.command("login").description("Login with email via magic link").action(async () => {
|
|
@@ -36584,7 +34792,7 @@ function registerAuthCommand(program2) {
|
|
|
36584
34792
|
error("No API URL configured. Set network with: sl config set network testnet");
|
|
36585
34793
|
process.exit(1);
|
|
36586
34794
|
}
|
|
36587
|
-
const email = await
|
|
34795
|
+
const email = await input({
|
|
36588
34796
|
message: "Email:",
|
|
36589
34797
|
validate: (v) => v.includes("@") || "Enter a valid email"
|
|
36590
34798
|
});
|
|
@@ -36596,7 +34804,7 @@ function registerAuthCommand(program2) {
|
|
|
36596
34804
|
});
|
|
36597
34805
|
await assertOk(mlRes);
|
|
36598
34806
|
console.log(dim("Check your email for a 6-digit login code."));
|
|
36599
|
-
const code = await
|
|
34807
|
+
const code = await input({
|
|
36600
34808
|
message: "Code:",
|
|
36601
34809
|
validate: (v) => /^\d{6}$/.test(v.trim()) || "Enter the 6-digit code from your email"
|
|
36602
34810
|
});
|
|
@@ -36829,20 +35037,14 @@ init_config();
|
|
|
36829
35037
|
init_dev_state();
|
|
36830
35038
|
init_node_manager();
|
|
36831
35039
|
init_output();
|
|
36832
|
-
var DEV_SERVICES = [
|
|
36833
|
-
"api",
|
|
36834
|
-
"indexer",
|
|
36835
|
-
"worker",
|
|
36836
|
-
"receiver",
|
|
36837
|
-
"subgraphs"
|
|
36838
|
-
];
|
|
35040
|
+
var DEV_SERVICES = ["api", "indexer", "worker", "subgraphs"];
|
|
36839
35041
|
function registerLocalCommand(program2) {
|
|
36840
35042
|
const local = program2.command("local").description("Manage local development environment and Stacks node").hook("preAction", async (_thisCommand, actionCommand) => {
|
|
36841
35043
|
if (actionCommand.name() === "help")
|
|
36842
35044
|
return;
|
|
36843
35045
|
await requireLocalNetwork();
|
|
36844
35046
|
});
|
|
36845
|
-
local.command("start").description("Start all local dev services (API, indexer, worker
|
|
35047
|
+
local.command("start").description("Start all local dev services (API, indexer, worker)").option("--indexer-port <port>", "Indexer port", "3700").option("--api-port <port>", "API port", "3800").option("--no-worker", "Skip worker service").option("--stacks-node", "Use port 3701 for indexer (avoids conflict with stacks-blockchain-api)").option("-f, --foreground", "Run in foreground (blocking)").action(async (options2) => {
|
|
36846
35048
|
const { runBackground: runBackground2, runForeground: runForeground2, isDevAlreadyRunning: isDevAlreadyRunning2 } = await Promise.resolve().then(() => (init_dev_impl(), exports_dev_impl));
|
|
36847
35049
|
if (await isDevAlreadyRunning2()) {
|
|
36848
35050
|
return;
|
|
@@ -36864,7 +35066,7 @@ function registerLocalCommand(program2) {
|
|
|
36864
35066
|
local.command("status").description("Show local environment status").action(async () => {
|
|
36865
35067
|
await showLocalStatus();
|
|
36866
35068
|
});
|
|
36867
|
-
local.command("logs").description("View local service logs (dev + node)").option("-s, --service <name>", "Filter by service (api, indexer, worker,
|
|
35069
|
+
local.command("logs").description("View local service logs (dev + node)").option("-s, --service <name>", "Filter by service (api, indexer, worker, subgraphs, node)").option("-f, --follow", "Follow log output").option("-n, --lines <n>", "Number of lines to show", "50").option("-q, --quiet", "Filter out common noise").action(async (options2) => {
|
|
36868
35070
|
await showLocalLogs(options2);
|
|
36869
35071
|
});
|
|
36870
35072
|
const node = local.command("node").description("Manage local Stacks node");
|
|
@@ -36872,15 +35074,15 @@ function registerLocalCommand(program2) {
|
|
|
36872
35074
|
const { runSetupWizard: runSetupWizard2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
|
|
36873
35075
|
await runSetupWizard2();
|
|
36874
35076
|
});
|
|
36875
|
-
node.command("start").description("Start the Stacks node").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("--with-indexer", "Also start
|
|
35077
|
+
node.command("start").description("Start the Stacks node").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("--with-indexer", "Also start indexer").action(async (options2) => {
|
|
36876
35078
|
const { startNode: startNode2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
|
|
36877
35079
|
await startNode2(options2.path, options2.withIndexer);
|
|
36878
35080
|
});
|
|
36879
|
-
node.command("stop").description("Stop the Stacks node").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-f, --force", "Skip confirmation").option("--wait", "
|
|
35081
|
+
node.command("stop").description("Stop the Stacks node").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-f, --force", "Skip confirmation").option("--wait", "Wait for in-flight work to drain first").action(async (options2) => {
|
|
36880
35082
|
const { stopNode: stopNode2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
|
|
36881
35083
|
await stopNode2(options2.path, options2.force, options2.wait);
|
|
36882
35084
|
});
|
|
36883
|
-
node.command("restart").description("Restart the Stacks node (stop then start)").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-f, --force", "Skip confirmation").option("--wait", "
|
|
35085
|
+
node.command("restart").description("Restart the Stacks node (stop then start)").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-f, --force", "Skip confirmation").option("--wait", "Wait for in-flight work to drain before stopping").action(async (options2) => {
|
|
36884
35086
|
const { restartNode: restartNode2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
|
|
36885
35087
|
await restartNode2(options2.path, options2.force, options2.wait);
|
|
36886
35088
|
});
|
|
@@ -36941,7 +35143,6 @@ var serviceColors2 = {
|
|
|
36941
35143
|
indexer: cyan,
|
|
36942
35144
|
worker: yellow,
|
|
36943
35145
|
subgraphs: magenta,
|
|
36944
|
-
receiver: green,
|
|
36945
35146
|
node: red
|
|
36946
35147
|
};
|
|
36947
35148
|
async function showLocalLogs(options2) {
|
|
@@ -36954,8 +35155,7 @@ async function showLocalLogs(options2) {
|
|
|
36954
35155
|
await showLogs2({
|
|
36955
35156
|
follow: options2.follow,
|
|
36956
35157
|
service,
|
|
36957
|
-
lines: options2.lines
|
|
36958
|
-
verbose: options2.verbose
|
|
35158
|
+
lines: options2.lines
|
|
36959
35159
|
});
|
|
36960
35160
|
return;
|
|
36961
35161
|
}
|
|
@@ -36964,9 +35164,9 @@ async function showLocalLogs(options2) {
|
|
|
36964
35164
|
return;
|
|
36965
35165
|
}
|
|
36966
35166
|
if (options2.follow) {
|
|
36967
|
-
await followCombinedLogs(showDev, showNode, lines, options2.quiet ?? false
|
|
35167
|
+
await followCombinedLogs(showDev, showNode, lines, options2.quiet ?? false);
|
|
36968
35168
|
} else {
|
|
36969
|
-
await showStaticCombinedLogs(showDev, showNode, lines, options2.quiet ?? false
|
|
35169
|
+
await showStaticCombinedLogs(showDev, showNode, lines, options2.quiet ?? false);
|
|
36970
35170
|
}
|
|
36971
35171
|
}
|
|
36972
35172
|
async function showNodeLogs(options2) {
|
|
@@ -36985,7 +35185,7 @@ async function showNodeLogs(options2) {
|
|
|
36985
35185
|
console.log(line);
|
|
36986
35186
|
}
|
|
36987
35187
|
}
|
|
36988
|
-
async function showStaticCombinedLogs(showDev, showNode, lines, quiet
|
|
35188
|
+
async function showStaticCombinedLogs(showDev, showNode, lines, quiet) {
|
|
36989
35189
|
const allLines = [];
|
|
36990
35190
|
if (showDev) {
|
|
36991
35191
|
const state = await loadDevState();
|
|
@@ -37016,11 +35216,11 @@ async function showStaticCombinedLogs(showDev, showNode, lines, quiet, verbose)
|
|
|
37016
35216
|
}
|
|
37017
35217
|
allLines.sort((a, b2) => a.timestamp.getTime() - b2.timestamp.getTime());
|
|
37018
35218
|
for (const { service, line } of allLines.slice(-lines)) {
|
|
37019
|
-
console.log(formatLogLine3(service, line
|
|
35219
|
+
console.log(formatLogLine3(service, line));
|
|
37020
35220
|
}
|
|
37021
35221
|
}
|
|
37022
|
-
async function followCombinedLogs(showDev, showNode, initialLines, quiet
|
|
37023
|
-
await showStaticCombinedLogs(showDev, showNode, initialLines, quiet
|
|
35222
|
+
async function followCombinedLogs(showDev, showNode, initialLines, quiet) {
|
|
35223
|
+
await showStaticCombinedLogs(showDev, showNode, initialLines, quiet);
|
|
37024
35224
|
const procs = [];
|
|
37025
35225
|
if (showDev) {
|
|
37026
35226
|
const state = await loadDevState();
|
|
@@ -37031,7 +35231,7 @@ async function followCombinedLogs(showDev, showNode, initialLines, quiet, verbos
|
|
|
37031
35231
|
stderr: "pipe"
|
|
37032
35232
|
});
|
|
37033
35233
|
procs.push(proc);
|
|
37034
|
-
|
|
35234
|
+
pipeProcLogs(proc, name);
|
|
37035
35235
|
}
|
|
37036
35236
|
}
|
|
37037
35237
|
}
|
|
@@ -37041,7 +35241,7 @@ async function followCombinedLogs(showDev, showNode, initialLines, quiet, verbos
|
|
|
37041
35241
|
stderr: "pipe"
|
|
37042
35242
|
});
|
|
37043
35243
|
procs.push(proc);
|
|
37044
|
-
|
|
35244
|
+
pipeProcLogs(proc, "node");
|
|
37045
35245
|
}
|
|
37046
35246
|
process.on("SIGINT", () => {
|
|
37047
35247
|
for (const proc of procs) {
|
|
@@ -37053,7 +35253,7 @@ async function followCombinedLogs(showDev, showNode, initialLines, quiet, verbos
|
|
|
37053
35253
|
});
|
|
37054
35254
|
await new Promise(() => {});
|
|
37055
35255
|
}
|
|
37056
|
-
function
|
|
35256
|
+
function pipeProcLogs(proc, serviceName) {
|
|
37057
35257
|
const readStream2 = async (stream2) => {
|
|
37058
35258
|
if (!stream2)
|
|
37059
35259
|
return;
|
|
@@ -37070,7 +35270,7 @@ function streamLogs(proc, serviceName, verbose) {
|
|
|
37070
35270
|
buffer2 = lines.pop() || "";
|
|
37071
35271
|
for (const line of lines) {
|
|
37072
35272
|
if (line.trim()) {
|
|
37073
|
-
console.log(formatLogLine3(serviceName, line
|
|
35273
|
+
console.log(formatLogLine3(serviceName, line));
|
|
37074
35274
|
}
|
|
37075
35275
|
}
|
|
37076
35276
|
}
|
|
@@ -37078,7 +35278,7 @@ function streamLogs(proc, serviceName, verbose) {
|
|
|
37078
35278
|
readStream2(proc.stdout);
|
|
37079
35279
|
readStream2(proc.stderr);
|
|
37080
35280
|
}
|
|
37081
|
-
function formatLogLine3(service, line
|
|
35281
|
+
function formatLogLine3(service, line) {
|
|
37082
35282
|
const colorFn = serviceColors2[service] ?? dim;
|
|
37083
35283
|
const prefix = colorFn(`[${service}]`);
|
|
37084
35284
|
if (service === "node" && line.startsWith("[")) {
|
|
@@ -37098,29 +35298,8 @@ function formatLogLine3(service, line, verbose) {
|
|
|
37098
35298
|
return `${prefix} ${dimTimestamp} ${dim(level + ":")} ${dim(message)}`;
|
|
37099
35299
|
}
|
|
37100
35300
|
}
|
|
37101
|
-
if (service === "receiver" && !verbose) {
|
|
37102
|
-
const summary = formatDeliverySummary2(line);
|
|
37103
|
-
if (summary)
|
|
37104
|
-
return `${prefix} ${summary}`;
|
|
37105
|
-
}
|
|
37106
35301
|
return `${prefix} ${line}`;
|
|
37107
35302
|
}
|
|
37108
|
-
function formatDeliverySummary2(jsonStr) {
|
|
37109
|
-
try {
|
|
37110
|
-
const data = JSON.parse(jsonStr);
|
|
37111
|
-
if (data.type !== "delivery" || !data.body)
|
|
37112
|
-
return null;
|
|
37113
|
-
const { body, method, path, timestamp } = data;
|
|
37114
|
-
const streamName = body.streamName ?? body.streamId?.slice(0, 8) ?? "unknown";
|
|
37115
|
-
const height = body.block?.height ?? "?";
|
|
37116
|
-
const txCount = body.matches?.transactions?.length ?? 0;
|
|
37117
|
-
const eventCount = body.matches?.events?.length ?? 0;
|
|
37118
|
-
const dimTimestamp = dim(`[${timestamp}]`);
|
|
37119
|
-
return `${dimTimestamp} ${green("INFO:")} ${method} ${path} — ${streamName} block:${height} (${txCount} txs, ${eventCount} events)`;
|
|
37120
|
-
} catch {
|
|
37121
|
-
return null;
|
|
37122
|
-
}
|
|
37123
|
-
}
|
|
37124
35303
|
// src/commands/marketplace.ts
|
|
37125
35304
|
init_api_client();
|
|
37126
35305
|
init_output();
|
|
@@ -37280,28 +35459,19 @@ function registerWorkflowsCommand(program2) {
|
|
|
37280
35459
|
const config = await loadConfig();
|
|
37281
35460
|
if (config.network !== "local") {
|
|
37282
35461
|
info(`Bundling for remote deploy (${config.network})...`);
|
|
37283
|
-
const
|
|
37284
|
-
const
|
|
37285
|
-
|
|
37286
|
-
|
|
37287
|
-
platform: "node",
|
|
37288
|
-
format: "esm",
|
|
37289
|
-
external: ["@secondlayer/workflows"],
|
|
37290
|
-
write: false
|
|
37291
|
-
});
|
|
37292
|
-
const handlerCode = new TextDecoder().decode(buildResult.outputFiles?.[0]?.contents);
|
|
35462
|
+
const { readFile: readFile2 } = await import("node:fs/promises");
|
|
35463
|
+
const source = await readFile2(absPath, "utf8");
|
|
35464
|
+
const { bundleWorkflowCode } = await import("@secondlayer/bundler");
|
|
35465
|
+
const bundled = await bundleWorkflowCode(source);
|
|
37293
35466
|
const deployResult = await getClient2().workflows.deploy({
|
|
37294
|
-
name:
|
|
37295
|
-
trigger:
|
|
37296
|
-
handlerCode,
|
|
37297
|
-
|
|
37298
|
-
|
|
35467
|
+
name: bundled.name,
|
|
35468
|
+
trigger: bundled.trigger,
|
|
35469
|
+
handlerCode: bundled.handlerCode,
|
|
35470
|
+
sourceCode: bundled.sourceCode,
|
|
35471
|
+
retries: bundled.retries,
|
|
35472
|
+
timeout: bundled.timeout
|
|
37299
35473
|
});
|
|
37300
|
-
|
|
37301
|
-
info(`Workflow "${def.name}" is up to date (no changes)`);
|
|
37302
|
-
} else {
|
|
37303
|
-
success(`Workflow "${def.name}" ${deployResult.action} (remote)`);
|
|
37304
|
-
}
|
|
35474
|
+
success(`Workflow "${def.name}" ${deployResult.action} → v${deployResult.version} (remote)`);
|
|
37305
35475
|
} else {
|
|
37306
35476
|
success(`Workflow "${result.name}" is valid`);
|
|
37307
35477
|
info(`Trigger: ${result.trigger.type}`);
|
|
@@ -37388,8 +35558,8 @@ ${items.length} workflow(s) total`));
|
|
|
37388
35558
|
});
|
|
37389
35559
|
workflows.command("trigger <name>").description("Trigger a workflow run").option("--input <json>", "Input JSON string").action(async (name, options2) => {
|
|
37390
35560
|
try {
|
|
37391
|
-
const
|
|
37392
|
-
const result = await getClient2().workflows.trigger(name,
|
|
35561
|
+
const input3 = options2.input ? JSON.parse(options2.input) : undefined;
|
|
35562
|
+
const result = await getClient2().workflows.trigger(name, input3);
|
|
37393
35563
|
success(`Triggered workflow "${name}"`);
|
|
37394
35564
|
info(`Run ID: ${result.runId}`);
|
|
37395
35565
|
} catch (err) {
|
|
@@ -37450,8 +35620,8 @@ ${runs.length} run(s)`));
|
|
|
37450
35620
|
workflows.command("delete <name>").description("Delete a workflow").option("-y, --yes", "Skip confirmation").action(async (name, options2) => {
|
|
37451
35621
|
try {
|
|
37452
35622
|
if (!options2.yes) {
|
|
37453
|
-
const { confirm:
|
|
37454
|
-
const ok = await
|
|
35623
|
+
const { confirm: confirm5 } = await import("@inquirer/prompts");
|
|
35624
|
+
const ok = await confirm5({
|
|
37455
35625
|
message: `Delete workflow "${name}"? This cannot be undone.`
|
|
37456
35626
|
});
|
|
37457
35627
|
if (!ok) {
|
|
@@ -37469,7 +35639,7 @@ ${runs.length} run(s)`));
|
|
|
37469
35639
|
}
|
|
37470
35640
|
// src/cli.ts
|
|
37471
35641
|
var { version } = package_default;
|
|
37472
|
-
program.name("secondlayer").alias("sl").description("SecondLayer CLI —
|
|
35642
|
+
program.name("secondlayer").alias("sl").description("SecondLayer CLI — subgraphs, workflows, and real-time indexing for Stacks").version(version).option("--network <network>", "Override network (local, testnet, mainnet)");
|
|
37473
35643
|
program.hook("preAction", (thisCommand) => {
|
|
37474
35644
|
const net3 = thisCommand.opts().network;
|
|
37475
35645
|
if (net3)
|
|
@@ -37477,10 +35647,10 @@ program.hook("preAction", (thisCommand) => {
|
|
|
37477
35647
|
});
|
|
37478
35648
|
program.addHelpText("after", `
|
|
37479
35649
|
Quickstart:
|
|
37480
|
-
$ sl
|
|
37481
|
-
$ sl
|
|
37482
|
-
$ sl
|
|
37483
|
-
$ sl status
|
|
35650
|
+
$ sl auth login # Authenticate
|
|
35651
|
+
$ sl subgraphs new my-subgraph # Scaffold a subgraph
|
|
35652
|
+
$ sl workflows new my-workflow # Scaffold a workflow
|
|
35653
|
+
$ sl status # Check system health
|
|
37484
35654
|
`);
|
|
37485
35655
|
program.command("generate [files...]").aliases(["gen", "codegen"]).description("Generate TypeScript interfaces from Clarity contracts").option("-c, --config <path>", "Path to config file").option("-o, --out <path>", "Output file path (required when using direct files)").option("-k, --api-key <key>", "Hiro API key (or set HIRO_API_KEY env var)").option("-w, --watch", "Watch for changes").action(async (files, options3) => {
|
|
37486
35656
|
const { generate: generate2 } = await Promise.resolve().then(() => (init_generate(), exports_generate));
|
|
@@ -37490,7 +35660,6 @@ program.command("init").description("Initialize a new secondlayer.config.ts file
|
|
|
37490
35660
|
const { init: init3 } = await Promise.resolve().then(() => (init_init(), exports_init));
|
|
37491
35661
|
await init3();
|
|
37492
35662
|
});
|
|
37493
|
-
registerStreamsCommand(program);
|
|
37494
35663
|
registerSubgraphsCommand(program);
|
|
37495
35664
|
registerWorkflowsCommand(program);
|
|
37496
35665
|
registerMarketplaceCommand(program);
|
|
@@ -37501,12 +35670,10 @@ registerStackCommand(program);
|
|
|
37501
35670
|
registerDbCommand(program);
|
|
37502
35671
|
registerSyncCommand(program);
|
|
37503
35672
|
registerDoctorCommand(program);
|
|
37504
|
-
registerSetupCommand(program);
|
|
37505
35673
|
registerConfigCommand(program);
|
|
37506
35674
|
registerAuthCommand(program);
|
|
37507
35675
|
registerWhoamiCommand(program);
|
|
37508
|
-
registerReceiverCommand(program);
|
|
37509
35676
|
program.parse();
|
|
37510
35677
|
|
|
37511
|
-
//# debugId=
|
|
35678
|
+
//# debugId=4C1634EBC4C4A9EE64756E2164756E21
|
|
37512
35679
|
//# sourceMappingURL=cli.js.map
|