@secondlayer/cli 5.10.1 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -36
- package/dist/cli.js +1553 -1352
- package/dist/cli.js.map +28 -28
- package/dist/core/plugin-manager.js +1 -2
- package/dist/core/plugin-manager.js.map +3 -3
- package/dist/index.js +1 -2
- package/dist/index.js.map +3 -3
- package/dist/plugins/index.js +1 -2
- package/dist/plugins/index.js.map +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -100,7 +100,6 @@ async function getBiome() {
|
|
|
100
100
|
enabled: true
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
|
-
biome.registerProjectFolder();
|
|
104
103
|
}
|
|
105
104
|
return biome;
|
|
106
105
|
}
|
|
@@ -2519,11 +2518,17 @@ var init_session = __esm(() => {
|
|
|
2519
2518
|
});
|
|
2520
2519
|
|
|
2521
2520
|
// src/lib/resolve-auth.ts
|
|
2521
|
+
function resolveApiUrl() {
|
|
2522
|
+
return process.env.SL_API_URL ?? process.env.SL_PLATFORM_API_URL ?? DEFAULT_API_URL;
|
|
2523
|
+
}
|
|
2524
|
+
function resolveEnvKey() {
|
|
2525
|
+
return process.env.SL_API_KEY;
|
|
2526
|
+
}
|
|
2522
2527
|
async function resolveAuth() {
|
|
2523
|
-
const
|
|
2524
|
-
const envKey =
|
|
2525
|
-
if (
|
|
2526
|
-
return { apiUrl
|
|
2528
|
+
const apiUrl = resolveApiUrl();
|
|
2529
|
+
const envKey = resolveEnvKey();
|
|
2530
|
+
if (envKey) {
|
|
2531
|
+
return { apiUrl, ephemeralKey: envKey, fromEnv: true };
|
|
2527
2532
|
}
|
|
2528
2533
|
const session = await readSession();
|
|
2529
2534
|
if (!session) {
|
|
@@ -2531,55 +2536,72 @@ async function resolveAuth() {
|
|
|
2531
2536
|
err.code = "SESSION_EXPIRED";
|
|
2532
2537
|
throw err;
|
|
2533
2538
|
}
|
|
2534
|
-
return {
|
|
2535
|
-
apiUrl: PLATFORM_API_URL2,
|
|
2536
|
-
ephemeralKey: session.token,
|
|
2537
|
-
fromEnv: false
|
|
2538
|
-
};
|
|
2539
|
+
return { apiUrl, ephemeralKey: session.token, fromEnv: false };
|
|
2539
2540
|
}
|
|
2540
|
-
var
|
|
2541
|
+
var DEFAULT_API_URL = "https://api.secondlayer.tools";
|
|
2541
2542
|
var init_resolve_auth = __esm(() => {
|
|
2542
2543
|
init_session();
|
|
2543
|
-
PLATFORM_API_URL2 = process.env.SL_PLATFORM_API_URL ?? "https://api.secondlayer.tools";
|
|
2544
2544
|
});
|
|
2545
2545
|
|
|
2546
2546
|
// src/lib/output.ts
|
|
2547
|
+
function paint(code, text) {
|
|
2548
|
+
return colorEnabled ? `${code}${text}${colors.reset}` : text;
|
|
2549
|
+
}
|
|
2547
2550
|
function red(text) {
|
|
2548
|
-
return
|
|
2551
|
+
return paint(colors.red, text);
|
|
2549
2552
|
}
|
|
2550
2553
|
function green(text) {
|
|
2551
|
-
return
|
|
2554
|
+
return paint(colors.green, text);
|
|
2552
2555
|
}
|
|
2553
2556
|
function yellow(text) {
|
|
2554
|
-
return
|
|
2557
|
+
return paint(colors.yellow, text);
|
|
2555
2558
|
}
|
|
2556
2559
|
function blue(text) {
|
|
2557
|
-
return
|
|
2560
|
+
return paint(colors.blue, text);
|
|
2558
2561
|
}
|
|
2559
2562
|
function magenta(text) {
|
|
2560
|
-
return
|
|
2563
|
+
return paint(colors.magenta, text);
|
|
2561
2564
|
}
|
|
2562
2565
|
function cyan(text) {
|
|
2563
|
-
return
|
|
2566
|
+
return paint(colors.cyan, text);
|
|
2564
2567
|
}
|
|
2565
2568
|
function dim(text) {
|
|
2566
|
-
return
|
|
2569
|
+
return paint(colors.dim, text);
|
|
2567
2570
|
}
|
|
2568
2571
|
function bold(text) {
|
|
2569
|
-
return
|
|
2572
|
+
return paint(colors.bold, text);
|
|
2570
2573
|
}
|
|
2571
2574
|
function success(message) {
|
|
2572
|
-
console.
|
|
2575
|
+
console.error(green(`✓ ${message}`));
|
|
2573
2576
|
}
|
|
2574
2577
|
function error(message) {
|
|
2575
2578
|
const text = message.trim() || "Command failed.";
|
|
2576
2579
|
console.error(red(`✗ ${text}`));
|
|
2577
2580
|
}
|
|
2578
2581
|
function warn(message) {
|
|
2579
|
-
console.
|
|
2582
|
+
console.error(yellow(`⚠ ${message}`));
|
|
2580
2583
|
}
|
|
2581
2584
|
function info(message) {
|
|
2582
|
-
console.
|
|
2585
|
+
console.error(blue(`ℹ ${message}`));
|
|
2586
|
+
}
|
|
2587
|
+
function note(message) {
|
|
2588
|
+
console.error(dim(message));
|
|
2589
|
+
}
|
|
2590
|
+
function printError(message, opts) {
|
|
2591
|
+
error(message);
|
|
2592
|
+
if (opts?.hint)
|
|
2593
|
+
console.error(dim(` → ${opts.hint}`));
|
|
2594
|
+
}
|
|
2595
|
+
function writeData(value) {
|
|
2596
|
+
process.stdout.write(`${value}
|
|
2597
|
+
`);
|
|
2598
|
+
}
|
|
2599
|
+
function output(opts) {
|
|
2600
|
+
if (opts.json) {
|
|
2601
|
+
writeData(JSON.stringify(opts.data, null, 2));
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2604
|
+
opts.human();
|
|
2583
2605
|
}
|
|
2584
2606
|
function stripAnsi(text) {
|
|
2585
2607
|
return text.replace(ANSI_ESCAPE_PATTERN, "");
|
|
@@ -2604,8 +2626,16 @@ function formatKeyValue(pairs) {
|
|
|
2604
2626
|
return pairs.map(([key, value]) => `${dim(key.padEnd(maxKeyLen))} ${value}`).join(`
|
|
2605
2627
|
`);
|
|
2606
2628
|
}
|
|
2607
|
-
var colors, ANSI_ESCAPE_PATTERN;
|
|
2629
|
+
var colorEnabled, colors, ANSI_ESCAPE_PATTERN;
|
|
2608
2630
|
var init_output = __esm(() => {
|
|
2631
|
+
colorEnabled = (() => {
|
|
2632
|
+
const { FORCE_COLOR, NO_COLOR } = process.env;
|
|
2633
|
+
if (FORCE_COLOR !== undefined && FORCE_COLOR !== "0")
|
|
2634
|
+
return true;
|
|
2635
|
+
if (NO_COLOR !== undefined && NO_COLOR !== "")
|
|
2636
|
+
return false;
|
|
2637
|
+
return Boolean(process.stdout.isTTY);
|
|
2638
|
+
})();
|
|
2609
2639
|
colors = {
|
|
2610
2640
|
reset: "\x1B[0m",
|
|
2611
2641
|
red: "\x1B[31m",
|
|
@@ -4916,88 +4946,6 @@ var init_src = __esm(() => {
|
|
|
4916
4946
|
src_default = Postgres;
|
|
4917
4947
|
});
|
|
4918
4948
|
|
|
4919
|
-
// src/lib/dev-state.ts
|
|
4920
|
-
var exports_dev_state = {};
|
|
4921
|
-
__export(exports_dev_state, {
|
|
4922
|
-
saveDevState: () => saveDevState,
|
|
4923
|
-
loadDevState: () => loadDevState,
|
|
4924
|
-
isProcessRunning: () => isProcessRunning,
|
|
4925
|
-
isDevRunning: () => isDevRunning,
|
|
4926
|
-
getRunningServices: () => getRunningServices,
|
|
4927
|
-
getLogsDir: () => getLogsDir,
|
|
4928
|
-
getLogFile: () => getLogFile,
|
|
4929
|
-
ensureDirs: () => ensureDirs,
|
|
4930
|
-
clearLogs: () => clearLogs,
|
|
4931
|
-
clearDevState: () => clearDevState
|
|
4932
|
-
});
|
|
4933
|
-
import { homedir as homedir4 } from "node:os";
|
|
4934
|
-
import { join as join5 } from "node:path";
|
|
4935
|
-
function getLogsDir() {
|
|
4936
|
-
return LOGS_DIR;
|
|
4937
|
-
}
|
|
4938
|
-
function getLogFile(service) {
|
|
4939
|
-
return join5(LOGS_DIR, `${service}.log`);
|
|
4940
|
-
}
|
|
4941
|
-
async function ensureDirs() {
|
|
4942
|
-
await Bun.$`mkdir -p ${STATE_DIR}`.quiet();
|
|
4943
|
-
await Bun.$`mkdir -p ${LOGS_DIR}`.quiet();
|
|
4944
|
-
}
|
|
4945
|
-
async function loadDevState() {
|
|
4946
|
-
const file = Bun.file(DEV_STATE_PATH);
|
|
4947
|
-
if (!await file.exists()) {
|
|
4948
|
-
return null;
|
|
4949
|
-
}
|
|
4950
|
-
try {
|
|
4951
|
-
return await file.json();
|
|
4952
|
-
} catch {
|
|
4953
|
-
return null;
|
|
4954
|
-
}
|
|
4955
|
-
}
|
|
4956
|
-
async function saveDevState(state) {
|
|
4957
|
-
await ensureDirs();
|
|
4958
|
-
await Bun.write(DEV_STATE_PATH, `${JSON.stringify(state, null, 2)}
|
|
4959
|
-
`);
|
|
4960
|
-
}
|
|
4961
|
-
async function clearDevState() {
|
|
4962
|
-
const file = Bun.file(DEV_STATE_PATH);
|
|
4963
|
-
if (await file.exists()) {
|
|
4964
|
-
await Bun.$`rm ${DEV_STATE_PATH}`.quiet();
|
|
4965
|
-
}
|
|
4966
|
-
}
|
|
4967
|
-
async function clearLogs() {
|
|
4968
|
-
await Bun.$`rm -f ${LOGS_DIR}/*.log`.quiet().nothrow();
|
|
4969
|
-
}
|
|
4970
|
-
function isProcessRunning(pid) {
|
|
4971
|
-
try {
|
|
4972
|
-
process.kill(pid, 0);
|
|
4973
|
-
return true;
|
|
4974
|
-
} catch {
|
|
4975
|
-
return false;
|
|
4976
|
-
}
|
|
4977
|
-
}
|
|
4978
|
-
async function getRunningServices() {
|
|
4979
|
-
const state = await loadDevState();
|
|
4980
|
-
if (!state)
|
|
4981
|
-
return {};
|
|
4982
|
-
const running = {};
|
|
4983
|
-
for (const [name, service] of Object.entries(state.services)) {
|
|
4984
|
-
if (isProcessRunning(service.pid)) {
|
|
4985
|
-
running[name] = service;
|
|
4986
|
-
}
|
|
4987
|
-
}
|
|
4988
|
-
return running;
|
|
4989
|
-
}
|
|
4990
|
-
async function isDevRunning() {
|
|
4991
|
-
const running = await getRunningServices();
|
|
4992
|
-
return Object.keys(running).length > 0;
|
|
4993
|
-
}
|
|
4994
|
-
var STATE_DIR, DEV_STATE_PATH, LOGS_DIR;
|
|
4995
|
-
var init_dev_state = __esm(() => {
|
|
4996
|
-
STATE_DIR = join5(homedir4(), ".secondlayer");
|
|
4997
|
-
DEV_STATE_PATH = join5(STATE_DIR, "dev.json");
|
|
4998
|
-
LOGS_DIR = join5(STATE_DIR, "logs");
|
|
4999
|
-
});
|
|
5000
|
-
|
|
5001
4949
|
// src/utils/abi-compat.ts
|
|
5002
4950
|
function normalizeAccess(access) {
|
|
5003
4951
|
if (access === "read_only")
|
|
@@ -12960,6 +12908,88 @@ function inferNetwork(address) {
|
|
|
12960
12908
|
return;
|
|
12961
12909
|
}
|
|
12962
12910
|
|
|
12911
|
+
// src/lib/dev-state.ts
|
|
12912
|
+
var exports_dev_state = {};
|
|
12913
|
+
__export(exports_dev_state, {
|
|
12914
|
+
saveDevState: () => saveDevState,
|
|
12915
|
+
loadDevState: () => loadDevState,
|
|
12916
|
+
isProcessRunning: () => isProcessRunning,
|
|
12917
|
+
isDevRunning: () => isDevRunning,
|
|
12918
|
+
getRunningServices: () => getRunningServices,
|
|
12919
|
+
getLogsDir: () => getLogsDir,
|
|
12920
|
+
getLogFile: () => getLogFile,
|
|
12921
|
+
ensureDirs: () => ensureDirs,
|
|
12922
|
+
clearLogs: () => clearLogs,
|
|
12923
|
+
clearDevState: () => clearDevState
|
|
12924
|
+
});
|
|
12925
|
+
import { homedir as homedir4 } from "node:os";
|
|
12926
|
+
import { join as join8 } from "node:path";
|
|
12927
|
+
function getLogsDir() {
|
|
12928
|
+
return LOGS_DIR;
|
|
12929
|
+
}
|
|
12930
|
+
function getLogFile(service) {
|
|
12931
|
+
return join8(LOGS_DIR, `${service}.log`);
|
|
12932
|
+
}
|
|
12933
|
+
async function ensureDirs() {
|
|
12934
|
+
await Bun.$`mkdir -p ${STATE_DIR}`.quiet();
|
|
12935
|
+
await Bun.$`mkdir -p ${LOGS_DIR}`.quiet();
|
|
12936
|
+
}
|
|
12937
|
+
async function loadDevState() {
|
|
12938
|
+
const file = Bun.file(DEV_STATE_PATH);
|
|
12939
|
+
if (!await file.exists()) {
|
|
12940
|
+
return null;
|
|
12941
|
+
}
|
|
12942
|
+
try {
|
|
12943
|
+
return await file.json();
|
|
12944
|
+
} catch {
|
|
12945
|
+
return null;
|
|
12946
|
+
}
|
|
12947
|
+
}
|
|
12948
|
+
async function saveDevState(state) {
|
|
12949
|
+
await ensureDirs();
|
|
12950
|
+
await Bun.write(DEV_STATE_PATH, `${JSON.stringify(state, null, 2)}
|
|
12951
|
+
`);
|
|
12952
|
+
}
|
|
12953
|
+
async function clearDevState() {
|
|
12954
|
+
const file = Bun.file(DEV_STATE_PATH);
|
|
12955
|
+
if (await file.exists()) {
|
|
12956
|
+
await Bun.$`rm ${DEV_STATE_PATH}`.quiet();
|
|
12957
|
+
}
|
|
12958
|
+
}
|
|
12959
|
+
async function clearLogs() {
|
|
12960
|
+
await Bun.$`rm -f ${LOGS_DIR}/*.log`.quiet().nothrow();
|
|
12961
|
+
}
|
|
12962
|
+
function isProcessRunning(pid) {
|
|
12963
|
+
try {
|
|
12964
|
+
process.kill(pid, 0);
|
|
12965
|
+
return true;
|
|
12966
|
+
} catch {
|
|
12967
|
+
return false;
|
|
12968
|
+
}
|
|
12969
|
+
}
|
|
12970
|
+
async function getRunningServices() {
|
|
12971
|
+
const state = await loadDevState();
|
|
12972
|
+
if (!state)
|
|
12973
|
+
return {};
|
|
12974
|
+
const running = {};
|
|
12975
|
+
for (const [name, service] of Object.entries(state.services)) {
|
|
12976
|
+
if (isProcessRunning(service.pid)) {
|
|
12977
|
+
running[name] = service;
|
|
12978
|
+
}
|
|
12979
|
+
}
|
|
12980
|
+
return running;
|
|
12981
|
+
}
|
|
12982
|
+
async function isDevRunning() {
|
|
12983
|
+
const running = await getRunningServices();
|
|
12984
|
+
return Object.keys(running).length > 0;
|
|
12985
|
+
}
|
|
12986
|
+
var STATE_DIR, DEV_STATE_PATH, LOGS_DIR;
|
|
12987
|
+
var init_dev_state = __esm(() => {
|
|
12988
|
+
STATE_DIR = join8(homedir4(), ".secondlayer");
|
|
12989
|
+
DEV_STATE_PATH = join8(STATE_DIR, "dev.json");
|
|
12990
|
+
LOGS_DIR = join8(STATE_DIR, "logs");
|
|
12991
|
+
});
|
|
12992
|
+
|
|
12963
12993
|
// src/lib/network.ts
|
|
12964
12994
|
function getChainId(network) {
|
|
12965
12995
|
return CHAIN_IDS[network].decimal.toString();
|
|
@@ -13175,15 +13205,15 @@ async function getNodeLogs(options2 = {}) {
|
|
|
13175
13205
|
continue;
|
|
13176
13206
|
if (options2.quiet && shouldFilterLine(line))
|
|
13177
13207
|
continue;
|
|
13178
|
-
const
|
|
13179
|
-
if (
|
|
13180
|
-
yield
|
|
13208
|
+
const output2 = options2.format ? formatLogLine(line) : line;
|
|
13209
|
+
if (output2)
|
|
13210
|
+
yield output2;
|
|
13181
13211
|
}
|
|
13182
13212
|
}
|
|
13183
13213
|
if (buffer2) {
|
|
13184
|
-
const
|
|
13185
|
-
if (
|
|
13186
|
-
yield
|
|
13214
|
+
const output2 = options2.format ? formatLogLine(buffer2) : buffer2;
|
|
13215
|
+
if (output2)
|
|
13216
|
+
yield output2;
|
|
13187
13217
|
}
|
|
13188
13218
|
} finally {
|
|
13189
13219
|
reader.releaseLock();
|
|
@@ -14972,6 +15002,56 @@ var init_source4 = __esm(() => {
|
|
|
14972
15002
|
source_default3 = chalk;
|
|
14973
15003
|
});
|
|
14974
15004
|
|
|
15005
|
+
// src/commands/init.ts
|
|
15006
|
+
var exports_init = {};
|
|
15007
|
+
__export(exports_init, {
|
|
15008
|
+
init: () => init2
|
|
15009
|
+
});
|
|
15010
|
+
import { promises as fs4 } from "node:fs";
|
|
15011
|
+
import path2 from "node:path";
|
|
15012
|
+
async function init2() {
|
|
15013
|
+
const configPath = path2.join(process.cwd(), "secondlayer.config.ts");
|
|
15014
|
+
try {
|
|
15015
|
+
await fs4.access(configPath);
|
|
15016
|
+
console.log(source_default3.yellow("⚠ secondlayer.config.ts already exists"));
|
|
15017
|
+
return;
|
|
15018
|
+
} catch {}
|
|
15019
|
+
const hasClarinetProject = await fileExists2("./Clarinet.toml");
|
|
15020
|
+
let config;
|
|
15021
|
+
if (hasClarinetProject) {
|
|
15022
|
+
config = `import { defineConfig } from '@secondlayer/cli';
|
|
15023
|
+
import { clarinet } from '@secondlayer/cli/plugins';
|
|
15024
|
+
|
|
15025
|
+
export default defineConfig({
|
|
15026
|
+
out: './src/generated/contracts.ts',
|
|
15027
|
+
plugins: [
|
|
15028
|
+
clarinet() // Found Clarinet.toml in current directory
|
|
15029
|
+
]
|
|
15030
|
+
});`;
|
|
15031
|
+
} else {
|
|
15032
|
+
config = `import { defineConfig } from '@secondlayer/cli';
|
|
15033
|
+
|
|
15034
|
+
export default defineConfig({
|
|
15035
|
+
out: './src/generated/contracts.ts',
|
|
15036
|
+
plugins: [],
|
|
15037
|
+
});`;
|
|
15038
|
+
}
|
|
15039
|
+
await fs4.writeFile(configPath, config);
|
|
15040
|
+
console.log(source_default3.green("✓ Created `secondlayer.config.ts`"));
|
|
15041
|
+
console.log("\nRun `secondlayer generate` to generate type-safe interfaces, functions, and hooks!");
|
|
15042
|
+
}
|
|
15043
|
+
async function fileExists2(filePath) {
|
|
15044
|
+
try {
|
|
15045
|
+
await fs4.access(filePath);
|
|
15046
|
+
return true;
|
|
15047
|
+
} catch {
|
|
15048
|
+
return false;
|
|
15049
|
+
}
|
|
15050
|
+
}
|
|
15051
|
+
var init_init = __esm(() => {
|
|
15052
|
+
init_source4();
|
|
15053
|
+
});
|
|
15054
|
+
|
|
14975
15055
|
// ../../node_modules/fast-glob/out/utils/array.js
|
|
14976
15056
|
var require_array = __commonJS((exports) => {
|
|
14977
15057
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -15034,7 +15114,7 @@ var require_path = __commonJS((exports) => {
|
|
|
15034
15114
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15035
15115
|
exports.convertPosixPathToPattern = exports.convertWindowsPathToPattern = exports.convertPathToPattern = exports.escapePosixPath = exports.escapeWindowsPath = exports.escape = exports.removeLeadingDotSegment = exports.makeAbsolute = exports.unixify = undefined;
|
|
15036
15116
|
var os4 = __require("os");
|
|
15037
|
-
var
|
|
15117
|
+
var path3 = __require("path");
|
|
15038
15118
|
var IS_WINDOWS_PLATFORM = os4.platform() === "win32";
|
|
15039
15119
|
var LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2;
|
|
15040
15120
|
var POSIX_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g;
|
|
@@ -15046,7 +15126,7 @@ var require_path = __commonJS((exports) => {
|
|
|
15046
15126
|
}
|
|
15047
15127
|
exports.unixify = unixify;
|
|
15048
15128
|
function makeAbsolute(cwd, filepath) {
|
|
15049
|
-
return
|
|
15129
|
+
return path3.resolve(cwd, filepath);
|
|
15050
15130
|
}
|
|
15051
15131
|
exports.makeAbsolute = makeAbsolute;
|
|
15052
15132
|
function removeLeadingDotSegment(entry) {
|
|
@@ -15356,7 +15436,7 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
15356
15436
|
const stringify2 = (node, parent = {}) => {
|
|
15357
15437
|
const invalidBlock = options2.escapeInvalid && utils.isInvalidBrace(parent);
|
|
15358
15438
|
const invalidNode = node.invalid === true && options2.escapeInvalid === true;
|
|
15359
|
-
let
|
|
15439
|
+
let output2 = "";
|
|
15360
15440
|
if (node.value) {
|
|
15361
15441
|
if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) {
|
|
15362
15442
|
return "\\" + node.value;
|
|
@@ -15368,10 +15448,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
15368
15448
|
}
|
|
15369
15449
|
if (node.nodes) {
|
|
15370
15450
|
for (const child of node.nodes) {
|
|
15371
|
-
|
|
15451
|
+
output2 += stringify2(child);
|
|
15372
15452
|
}
|
|
15373
15453
|
}
|
|
15374
|
-
return
|
|
15454
|
+
return output2;
|
|
15375
15455
|
};
|
|
15376
15456
|
return stringify2(ast);
|
|
15377
15457
|
};
|
|
@@ -15830,7 +15910,7 @@ var require_compile = __commonJS((exports, module) => {
|
|
|
15830
15910
|
const invalidNode = node.invalid === true && options2.escapeInvalid === true;
|
|
15831
15911
|
const invalid = invalidBlock === true || invalidNode === true;
|
|
15832
15912
|
const prefix = options2.escapeInvalid === true ? "\\" : "";
|
|
15833
|
-
let
|
|
15913
|
+
let output2 = "";
|
|
15834
15914
|
if (node.isOpen === true) {
|
|
15835
15915
|
return prefix + node.value;
|
|
15836
15916
|
}
|
|
@@ -15859,10 +15939,10 @@ var require_compile = __commonJS((exports, module) => {
|
|
|
15859
15939
|
}
|
|
15860
15940
|
if (node.nodes) {
|
|
15861
15941
|
for (const child of node.nodes) {
|
|
15862
|
-
|
|
15942
|
+
output2 += walk(child, node);
|
|
15863
15943
|
}
|
|
15864
15944
|
}
|
|
15865
|
-
return
|
|
15945
|
+
return output2;
|
|
15866
15946
|
};
|
|
15867
15947
|
return walk(ast);
|
|
15868
15948
|
};
|
|
@@ -16249,23 +16329,23 @@ var require_braces = __commonJS((exports, module) => {
|
|
|
16249
16329
|
var expand = require_expand();
|
|
16250
16330
|
var parse2 = require_parse();
|
|
16251
16331
|
var braces = (input5, options2 = {}) => {
|
|
16252
|
-
let
|
|
16332
|
+
let output2 = [];
|
|
16253
16333
|
if (Array.isArray(input5)) {
|
|
16254
16334
|
for (const pattern of input5) {
|
|
16255
16335
|
const result = braces.create(pattern, options2);
|
|
16256
16336
|
if (Array.isArray(result)) {
|
|
16257
|
-
|
|
16337
|
+
output2.push(...result);
|
|
16258
16338
|
} else {
|
|
16259
|
-
|
|
16339
|
+
output2.push(result);
|
|
16260
16340
|
}
|
|
16261
16341
|
}
|
|
16262
16342
|
} else {
|
|
16263
|
-
|
|
16343
|
+
output2 = [].concat(braces.create(input5, options2));
|
|
16264
16344
|
}
|
|
16265
16345
|
if (options2 && options2.expand === true && options2.nodupes === true) {
|
|
16266
|
-
|
|
16346
|
+
output2 = [...new Set(output2)];
|
|
16267
16347
|
}
|
|
16268
|
-
return
|
|
16348
|
+
return output2;
|
|
16269
16349
|
};
|
|
16270
16350
|
braces.parse = (input5, options2 = {}) => parse2(input5, options2);
|
|
16271
16351
|
braces.stringify = (input5, options2 = {}) => {
|
|
@@ -16304,7 +16384,7 @@ var require_braces = __commonJS((exports, module) => {
|
|
|
16304
16384
|
|
|
16305
16385
|
// ../../node_modules/picomatch/lib/constants.js
|
|
16306
16386
|
var require_constants2 = __commonJS((exports, module) => {
|
|
16307
|
-
var
|
|
16387
|
+
var path3 = __require("path");
|
|
16308
16388
|
var WIN_SLASH = "\\\\/";
|
|
16309
16389
|
var WIN_NO_SLASH = `[^${WIN_SLASH}]`;
|
|
16310
16390
|
var DOT_LITERAL = "\\.";
|
|
@@ -16426,7 +16506,7 @@ var require_constants2 = __commonJS((exports, module) => {
|
|
|
16426
16506
|
CHAR_UNDERSCORE: 95,
|
|
16427
16507
|
CHAR_VERTICAL_LINE: 124,
|
|
16428
16508
|
CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
|
|
16429
|
-
SEP:
|
|
16509
|
+
SEP: path3.sep,
|
|
16430
16510
|
extglobChars(chars) {
|
|
16431
16511
|
return {
|
|
16432
16512
|
"!": { type: "negate", open: "(?:(?!(?:", close: `))${chars.STAR})` },
|
|
@@ -16444,7 +16524,7 @@ var require_constants2 = __commonJS((exports, module) => {
|
|
|
16444
16524
|
|
|
16445
16525
|
// ../../node_modules/picomatch/lib/utils.js
|
|
16446
16526
|
var require_utils2 = __commonJS((exports) => {
|
|
16447
|
-
var
|
|
16527
|
+
var path3 = __require("path");
|
|
16448
16528
|
var win32 = process.platform === "win32";
|
|
16449
16529
|
var {
|
|
16450
16530
|
REGEX_BACKSLASH,
|
|
@@ -16473,7 +16553,7 @@ var require_utils2 = __commonJS((exports) => {
|
|
|
16473
16553
|
if (options2 && typeof options2.windows === "boolean") {
|
|
16474
16554
|
return options2.windows;
|
|
16475
16555
|
}
|
|
16476
|
-
return win32 === true ||
|
|
16556
|
+
return win32 === true || path3.sep === "\\";
|
|
16477
16557
|
};
|
|
16478
16558
|
exports.escapeLast = (input5, char, lastIdx) => {
|
|
16479
16559
|
const idx = input5.lastIndexOf(char, lastIdx);
|
|
@@ -16484,21 +16564,21 @@ var require_utils2 = __commonJS((exports) => {
|
|
|
16484
16564
|
return `${input5.slice(0, idx)}\\${input5.slice(idx)}`;
|
|
16485
16565
|
};
|
|
16486
16566
|
exports.removePrefix = (input5, state = {}) => {
|
|
16487
|
-
let
|
|
16488
|
-
if (
|
|
16489
|
-
|
|
16567
|
+
let output2 = input5;
|
|
16568
|
+
if (output2.startsWith("./")) {
|
|
16569
|
+
output2 = output2.slice(2);
|
|
16490
16570
|
state.prefix = "./";
|
|
16491
16571
|
}
|
|
16492
|
-
return
|
|
16572
|
+
return output2;
|
|
16493
16573
|
};
|
|
16494
16574
|
exports.wrapOutput = (input5, state = {}, options2 = {}) => {
|
|
16495
16575
|
const prepend = options2.contains ? "" : "^";
|
|
16496
16576
|
const append = options2.contains ? "" : "$";
|
|
16497
|
-
let
|
|
16577
|
+
let output2 = `${prepend}(?:${input5})${append}`;
|
|
16498
16578
|
if (state.negated === true) {
|
|
16499
|
-
|
|
16579
|
+
output2 = `(?:^(?!${output2}).*$)`;
|
|
16500
16580
|
}
|
|
16501
|
-
return
|
|
16581
|
+
return output2;
|
|
16502
16582
|
};
|
|
16503
16583
|
});
|
|
16504
16584
|
|
|
@@ -16976,14 +17056,14 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
16976
17056
|
token.prev = prev;
|
|
16977
17057
|
token.parens = state.parens;
|
|
16978
17058
|
token.output = state.output;
|
|
16979
|
-
const
|
|
17059
|
+
const output2 = (opts.capture ? "(" : "") + token.open;
|
|
16980
17060
|
increment("parens");
|
|
16981
17061
|
push({ type, value: value2, output: state.output ? "" : ONE_CHAR });
|
|
16982
|
-
push({ type: "paren", extglob: true, value: advance(), output });
|
|
17062
|
+
push({ type: "paren", extglob: true, value: advance(), output: output2 });
|
|
16983
17063
|
extglobs.push(token);
|
|
16984
17064
|
};
|
|
16985
17065
|
const extglobClose = (token) => {
|
|
16986
|
-
let
|
|
17066
|
+
let output2 = token.close + (opts.capture ? ")" : "");
|
|
16987
17067
|
let rest;
|
|
16988
17068
|
if (token.type === "negate") {
|
|
16989
17069
|
let extglobStar = star;
|
|
@@ -16991,22 +17071,22 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
16991
17071
|
extglobStar = globstar(opts);
|
|
16992
17072
|
}
|
|
16993
17073
|
if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) {
|
|
16994
|
-
|
|
17074
|
+
output2 = token.close = `)$))${extglobStar}`;
|
|
16995
17075
|
}
|
|
16996
17076
|
if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
|
|
16997
17077
|
const expression = parse2(rest, { ...options2, fastpaths: false }).output;
|
|
16998
|
-
|
|
17078
|
+
output2 = token.close = `)${expression})${extglobStar})`;
|
|
16999
17079
|
}
|
|
17000
17080
|
if (token.prev.type === "bos") {
|
|
17001
17081
|
state.negatedExtglob = true;
|
|
17002
17082
|
}
|
|
17003
17083
|
}
|
|
17004
|
-
push({ type: "paren", extglob: true, value, output });
|
|
17084
|
+
push({ type: "paren", extglob: true, value, output: output2 });
|
|
17005
17085
|
decrement("parens");
|
|
17006
17086
|
};
|
|
17007
17087
|
if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input5)) {
|
|
17008
17088
|
let backslashes = false;
|
|
17009
|
-
let
|
|
17089
|
+
let output2 = input5.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => {
|
|
17010
17090
|
if (first === "\\") {
|
|
17011
17091
|
backslashes = true;
|
|
17012
17092
|
return m;
|
|
@@ -17033,18 +17113,18 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17033
17113
|
});
|
|
17034
17114
|
if (backslashes === true) {
|
|
17035
17115
|
if (opts.unescape === true) {
|
|
17036
|
-
|
|
17116
|
+
output2 = output2.replace(/\\/g, "");
|
|
17037
17117
|
} else {
|
|
17038
|
-
|
|
17118
|
+
output2 = output2.replace(/\\+/g, (m) => {
|
|
17039
17119
|
return m.length % 2 === 0 ? "\\\\" : m ? "\\" : "";
|
|
17040
17120
|
});
|
|
17041
17121
|
}
|
|
17042
17122
|
}
|
|
17043
|
-
if (
|
|
17123
|
+
if (output2 === input5 && opts.contains === true) {
|
|
17044
17124
|
state.output = input5;
|
|
17045
17125
|
return state;
|
|
17046
17126
|
}
|
|
17047
|
-
state.output = utils.wrapOutput(
|
|
17127
|
+
state.output = utils.wrapOutput(output2, state, options2);
|
|
17048
17128
|
return state;
|
|
17049
17129
|
}
|
|
17050
17130
|
while (!eos()) {
|
|
@@ -17214,7 +17294,7 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17214
17294
|
push({ type: "text", value, output: value });
|
|
17215
17295
|
continue;
|
|
17216
17296
|
}
|
|
17217
|
-
let
|
|
17297
|
+
let output2 = ")";
|
|
17218
17298
|
if (brace.dots === true) {
|
|
17219
17299
|
const arr = tokens.slice();
|
|
17220
17300
|
const range = [];
|
|
@@ -17227,20 +17307,20 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17227
17307
|
range.unshift(arr[i].value);
|
|
17228
17308
|
}
|
|
17229
17309
|
}
|
|
17230
|
-
|
|
17310
|
+
output2 = expandRange(range, opts);
|
|
17231
17311
|
state.backtrack = true;
|
|
17232
17312
|
}
|
|
17233
17313
|
if (brace.comma !== true && brace.dots !== true) {
|
|
17234
17314
|
const out = state.output.slice(0, brace.outputIndex);
|
|
17235
17315
|
const toks = state.tokens.slice(brace.tokensIndex);
|
|
17236
17316
|
brace.value = brace.output = "\\{";
|
|
17237
|
-
value =
|
|
17317
|
+
value = output2 = "\\}";
|
|
17238
17318
|
state.output = out;
|
|
17239
17319
|
for (const t of toks) {
|
|
17240
17320
|
state.output += t.output || t.value;
|
|
17241
17321
|
}
|
|
17242
17322
|
}
|
|
17243
|
-
push({ type: "brace", value, output });
|
|
17323
|
+
push({ type: "brace", value, output: output2 });
|
|
17244
17324
|
decrement("braces");
|
|
17245
17325
|
braces.pop();
|
|
17246
17326
|
continue;
|
|
@@ -17253,13 +17333,13 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17253
17333
|
continue;
|
|
17254
17334
|
}
|
|
17255
17335
|
if (value === ",") {
|
|
17256
|
-
let
|
|
17336
|
+
let output2 = value;
|
|
17257
17337
|
const brace = braces[braces.length - 1];
|
|
17258
17338
|
if (brace && stack[stack.length - 1] === "braces") {
|
|
17259
17339
|
brace.comma = true;
|
|
17260
|
-
|
|
17340
|
+
output2 = "|";
|
|
17261
17341
|
}
|
|
17262
|
-
push({ type: "comma", value, output });
|
|
17342
|
+
push({ type: "comma", value, output: output2 });
|
|
17263
17343
|
continue;
|
|
17264
17344
|
}
|
|
17265
17345
|
if (value === "/") {
|
|
@@ -17300,14 +17380,14 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17300
17380
|
}
|
|
17301
17381
|
if (prev && prev.type === "paren") {
|
|
17302
17382
|
const next = peek();
|
|
17303
|
-
let
|
|
17383
|
+
let output2 = value;
|
|
17304
17384
|
if (next === "<" && !utils.supportsLookbehinds()) {
|
|
17305
17385
|
throw new Error("Node.js v10 or higher is required for regex lookbehinds");
|
|
17306
17386
|
}
|
|
17307
17387
|
if (prev.value === "(" && !/[!=<:]/.test(next) || next === "<" && !/<([!=]|\w+>)/.test(remaining())) {
|
|
17308
|
-
|
|
17388
|
+
output2 = `\\${value}`;
|
|
17309
17389
|
}
|
|
17310
|
-
push({ type: "text", value, output });
|
|
17390
|
+
push({ type: "text", value, output: output2 });
|
|
17311
17391
|
continue;
|
|
17312
17392
|
}
|
|
17313
17393
|
if (opts.dot !== true && (prev.type === "slash" || prev.type === "bos")) {
|
|
@@ -17585,8 +17665,8 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17585
17665
|
}
|
|
17586
17666
|
}
|
|
17587
17667
|
};
|
|
17588
|
-
const
|
|
17589
|
-
let source = create2(
|
|
17668
|
+
const output2 = utils.removePrefix(input5, state);
|
|
17669
|
+
let source = create2(output2);
|
|
17590
17670
|
if (source && opts.strictSlashes !== true) {
|
|
17591
17671
|
source += `${SLASH_LITERAL}?`;
|
|
17592
17672
|
}
|
|
@@ -17597,7 +17677,7 @@ var require_parse2 = __commonJS((exports, module) => {
|
|
|
17597
17677
|
|
|
17598
17678
|
// ../../node_modules/picomatch/lib/picomatch.js
|
|
17599
17679
|
var require_picomatch = __commonJS((exports, module) => {
|
|
17600
|
-
var
|
|
17680
|
+
var path3 = __require("path");
|
|
17601
17681
|
var scan = require_scan();
|
|
17602
17682
|
var parse2 = require_parse2();
|
|
17603
17683
|
var utils = require_utils2();
|
|
@@ -17631,8 +17711,8 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
17631
17711
|
isIgnored = picomatch(opts.ignore, ignoreOpts, returnState);
|
|
17632
17712
|
}
|
|
17633
17713
|
const matcher = (input5, returnObject = false) => {
|
|
17634
|
-
const { isMatch, match, output } = picomatch.test(input5, regex, options2, { glob, posix });
|
|
17635
|
-
const result = { glob, state, regex, posix, input: input5, output, match, isMatch };
|
|
17714
|
+
const { isMatch, match, output: output2 } = picomatch.test(input5, regex, options2, { glob, posix });
|
|
17715
|
+
const result = { glob, state, regex, posix, input: input5, output: output2, match, isMatch };
|
|
17636
17716
|
if (typeof opts.onResult === "function") {
|
|
17637
17717
|
opts.onResult(result);
|
|
17638
17718
|
}
|
|
@@ -17667,23 +17747,23 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
17667
17747
|
const opts = options2 || {};
|
|
17668
17748
|
const format = opts.format || (posix ? utils.toPosixSlashes : null);
|
|
17669
17749
|
let match = input5 === glob;
|
|
17670
|
-
let
|
|
17750
|
+
let output2 = match && format ? format(input5) : input5;
|
|
17671
17751
|
if (match === false) {
|
|
17672
|
-
|
|
17673
|
-
match =
|
|
17752
|
+
output2 = format ? format(input5) : input5;
|
|
17753
|
+
match = output2 === glob;
|
|
17674
17754
|
}
|
|
17675
17755
|
if (match === false || opts.capture === true) {
|
|
17676
17756
|
if (opts.matchBase === true || opts.basename === true) {
|
|
17677
17757
|
match = picomatch.matchBase(input5, regex, options2, posix);
|
|
17678
17758
|
} else {
|
|
17679
|
-
match = regex.exec(
|
|
17759
|
+
match = regex.exec(output2);
|
|
17680
17760
|
}
|
|
17681
17761
|
}
|
|
17682
|
-
return { isMatch: Boolean(match), match, output };
|
|
17762
|
+
return { isMatch: Boolean(match), match, output: output2 };
|
|
17683
17763
|
};
|
|
17684
17764
|
picomatch.matchBase = (input5, glob, options2, posix = utils.isWindows(options2)) => {
|
|
17685
17765
|
const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options2);
|
|
17686
|
-
return regex.test(
|
|
17766
|
+
return regex.test(path3.basename(input5));
|
|
17687
17767
|
};
|
|
17688
17768
|
picomatch.isMatch = (str, patterns, options2) => picomatch(patterns, options2)(str);
|
|
17689
17769
|
picomatch.parse = (pattern, options2) => {
|
|
@@ -17904,7 +17984,7 @@ var require_micromatch = __commonJS((exports, module) => {
|
|
|
17904
17984
|
var require_pattern = __commonJS((exports) => {
|
|
17905
17985
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17906
17986
|
exports.isAbsolute = exports.partitionAbsoluteAndRelative = exports.removeDuplicateSlashes = exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.isPatternRelatedToParentDirectory = exports.getPatternsOutsideCurrentDirectory = exports.getPatternsInsideCurrentDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = undefined;
|
|
17907
|
-
var
|
|
17987
|
+
var path3 = __require("path");
|
|
17908
17988
|
var globParent = require_glob_parent();
|
|
17909
17989
|
var micromatch = require_micromatch();
|
|
17910
17990
|
var GLOBSTAR = "**";
|
|
@@ -17999,7 +18079,7 @@ var require_pattern = __commonJS((exports) => {
|
|
|
17999
18079
|
}
|
|
18000
18080
|
exports.endsWithSlashGlobStar = endsWithSlashGlobStar;
|
|
18001
18081
|
function isAffectDepthOfReadingPattern(pattern) {
|
|
18002
|
-
const basename =
|
|
18082
|
+
const basename = path3.basename(pattern);
|
|
18003
18083
|
return endsWithSlashGlobStar(pattern) || isStaticPattern(basename);
|
|
18004
18084
|
}
|
|
18005
18085
|
exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
|
|
@@ -18057,7 +18137,7 @@ var require_pattern = __commonJS((exports) => {
|
|
|
18057
18137
|
}
|
|
18058
18138
|
exports.partitionAbsoluteAndRelative = partitionAbsoluteAndRelative;
|
|
18059
18139
|
function isAbsolute(pattern) {
|
|
18060
|
-
return
|
|
18140
|
+
return path3.isAbsolute(pattern);
|
|
18061
18141
|
}
|
|
18062
18142
|
exports.isAbsolute = isAbsolute;
|
|
18063
18143
|
});
|
|
@@ -18220,10 +18300,10 @@ var require_utils3 = __commonJS((exports) => {
|
|
|
18220
18300
|
exports.array = array;
|
|
18221
18301
|
var errno = require_errno();
|
|
18222
18302
|
exports.errno = errno;
|
|
18223
|
-
var
|
|
18224
|
-
exports.fs =
|
|
18225
|
-
var
|
|
18226
|
-
exports.path =
|
|
18303
|
+
var fs5 = require_fs();
|
|
18304
|
+
exports.fs = fs5;
|
|
18305
|
+
var path3 = require_path();
|
|
18306
|
+
exports.path = path3;
|
|
18227
18307
|
var pattern = require_pattern();
|
|
18228
18308
|
exports.pattern = pattern;
|
|
18229
18309
|
var stream2 = require_stream();
|
|
@@ -18319,8 +18399,8 @@ var require_tasks = __commonJS((exports) => {
|
|
|
18319
18399
|
var require_async = __commonJS((exports) => {
|
|
18320
18400
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18321
18401
|
exports.read = undefined;
|
|
18322
|
-
function read(
|
|
18323
|
-
settings.fs.lstat(
|
|
18402
|
+
function read(path3, settings, callback) {
|
|
18403
|
+
settings.fs.lstat(path3, (lstatError, lstat) => {
|
|
18324
18404
|
if (lstatError !== null) {
|
|
18325
18405
|
callFailureCallback(callback, lstatError);
|
|
18326
18406
|
return;
|
|
@@ -18329,7 +18409,7 @@ var require_async = __commonJS((exports) => {
|
|
|
18329
18409
|
callSuccessCallback(callback, lstat);
|
|
18330
18410
|
return;
|
|
18331
18411
|
}
|
|
18332
|
-
settings.fs.stat(
|
|
18412
|
+
settings.fs.stat(path3, (statError, stat2) => {
|
|
18333
18413
|
if (statError !== null) {
|
|
18334
18414
|
if (settings.throwErrorOnBrokenSymbolicLink) {
|
|
18335
18415
|
callFailureCallback(callback, statError);
|
|
@@ -18358,13 +18438,13 @@ var require_async = __commonJS((exports) => {
|
|
|
18358
18438
|
var require_sync = __commonJS((exports) => {
|
|
18359
18439
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18360
18440
|
exports.read = undefined;
|
|
18361
|
-
function read(
|
|
18362
|
-
const lstat = settings.fs.lstatSync(
|
|
18441
|
+
function read(path3, settings) {
|
|
18442
|
+
const lstat = settings.fs.lstatSync(path3);
|
|
18363
18443
|
if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) {
|
|
18364
18444
|
return lstat;
|
|
18365
18445
|
}
|
|
18366
18446
|
try {
|
|
18367
|
-
const stat2 = settings.fs.statSync(
|
|
18447
|
+
const stat2 = settings.fs.statSync(path3);
|
|
18368
18448
|
if (settings.markSymbolicLink) {
|
|
18369
18449
|
stat2.isSymbolicLink = () => true;
|
|
18370
18450
|
}
|
|
@@ -18383,12 +18463,12 @@ var require_sync = __commonJS((exports) => {
|
|
|
18383
18463
|
var require_fs2 = __commonJS((exports) => {
|
|
18384
18464
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18385
18465
|
exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = undefined;
|
|
18386
|
-
var
|
|
18466
|
+
var fs5 = __require("fs");
|
|
18387
18467
|
exports.FILE_SYSTEM_ADAPTER = {
|
|
18388
|
-
lstat:
|
|
18389
|
-
stat:
|
|
18390
|
-
lstatSync:
|
|
18391
|
-
statSync:
|
|
18468
|
+
lstat: fs5.lstat,
|
|
18469
|
+
stat: fs5.stat,
|
|
18470
|
+
lstatSync: fs5.lstatSync,
|
|
18471
|
+
statSync: fs5.statSync
|
|
18392
18472
|
};
|
|
18393
18473
|
function createFileSystemAdapter(fsMethods) {
|
|
18394
18474
|
if (fsMethods === undefined) {
|
|
@@ -18402,13 +18482,13 @@ var require_fs2 = __commonJS((exports) => {
|
|
|
18402
18482
|
// ../../node_modules/@nodelib/fs.stat/out/settings.js
|
|
18403
18483
|
var require_settings = __commonJS((exports) => {
|
|
18404
18484
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18405
|
-
var
|
|
18485
|
+
var fs5 = require_fs2();
|
|
18406
18486
|
|
|
18407
18487
|
class Settings {
|
|
18408
18488
|
constructor(_options = {}) {
|
|
18409
18489
|
this._options = _options;
|
|
18410
18490
|
this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true);
|
|
18411
|
-
this.fs =
|
|
18491
|
+
this.fs = fs5.createFileSystemAdapter(this._options.fs);
|
|
18412
18492
|
this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false);
|
|
18413
18493
|
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
|
|
18414
18494
|
}
|
|
@@ -18427,17 +18507,17 @@ var require_out = __commonJS((exports) => {
|
|
|
18427
18507
|
var sync = require_sync();
|
|
18428
18508
|
var settings_1 = require_settings();
|
|
18429
18509
|
exports.Settings = settings_1.default;
|
|
18430
|
-
function stat2(
|
|
18510
|
+
function stat2(path3, optionsOrSettingsOrCallback, callback) {
|
|
18431
18511
|
if (typeof optionsOrSettingsOrCallback === "function") {
|
|
18432
|
-
async.read(
|
|
18512
|
+
async.read(path3, getSettings(), optionsOrSettingsOrCallback);
|
|
18433
18513
|
return;
|
|
18434
18514
|
}
|
|
18435
|
-
async.read(
|
|
18515
|
+
async.read(path3, getSettings(optionsOrSettingsOrCallback), callback);
|
|
18436
18516
|
}
|
|
18437
18517
|
exports.stat = stat2;
|
|
18438
|
-
function statSync2(
|
|
18518
|
+
function statSync2(path3, optionsOrSettings) {
|
|
18439
18519
|
const settings = getSettings(optionsOrSettings);
|
|
18440
|
-
return sync.read(
|
|
18520
|
+
return sync.read(path3, settings);
|
|
18441
18521
|
}
|
|
18442
18522
|
exports.statSync = statSync2;
|
|
18443
18523
|
function getSettings(settingsOrOptions = {}) {
|
|
@@ -18553,8 +18633,8 @@ var require_fs3 = __commonJS((exports) => {
|
|
|
18553
18633
|
var require_utils4 = __commonJS((exports) => {
|
|
18554
18634
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18555
18635
|
exports.fs = undefined;
|
|
18556
|
-
var
|
|
18557
|
-
exports.fs =
|
|
18636
|
+
var fs5 = require_fs3();
|
|
18637
|
+
exports.fs = fs5;
|
|
18558
18638
|
});
|
|
18559
18639
|
|
|
18560
18640
|
// ../../node_modules/@nodelib/fs.scandir/out/providers/common.js
|
|
@@ -18640,16 +18720,16 @@ var require_async2 = __commonJS((exports) => {
|
|
|
18640
18720
|
return;
|
|
18641
18721
|
}
|
|
18642
18722
|
const tasks = names.map((name) => {
|
|
18643
|
-
const
|
|
18723
|
+
const path3 = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
|
|
18644
18724
|
return (done) => {
|
|
18645
|
-
fsStat.stat(
|
|
18725
|
+
fsStat.stat(path3, settings.fsStatSettings, (error2, stats) => {
|
|
18646
18726
|
if (error2 !== null) {
|
|
18647
18727
|
done(error2);
|
|
18648
18728
|
return;
|
|
18649
18729
|
}
|
|
18650
18730
|
const entry = {
|
|
18651
18731
|
name,
|
|
18652
|
-
path:
|
|
18732
|
+
path: path3,
|
|
18653
18733
|
dirent: utils.fs.createDirentFromStats(name, stats)
|
|
18654
18734
|
};
|
|
18655
18735
|
if (settings.stats) {
|
|
@@ -18737,14 +18817,14 @@ var require_sync2 = __commonJS((exports) => {
|
|
|
18737
18817
|
var require_fs4 = __commonJS((exports) => {
|
|
18738
18818
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18739
18819
|
exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = undefined;
|
|
18740
|
-
var
|
|
18820
|
+
var fs5 = __require("fs");
|
|
18741
18821
|
exports.FILE_SYSTEM_ADAPTER = {
|
|
18742
|
-
lstat:
|
|
18743
|
-
stat:
|
|
18744
|
-
lstatSync:
|
|
18745
|
-
statSync:
|
|
18746
|
-
readdir:
|
|
18747
|
-
readdirSync:
|
|
18822
|
+
lstat: fs5.lstat,
|
|
18823
|
+
stat: fs5.stat,
|
|
18824
|
+
lstatSync: fs5.lstatSync,
|
|
18825
|
+
statSync: fs5.statSync,
|
|
18826
|
+
readdir: fs5.readdir,
|
|
18827
|
+
readdirSync: fs5.readdirSync
|
|
18748
18828
|
};
|
|
18749
18829
|
function createFileSystemAdapter(fsMethods) {
|
|
18750
18830
|
if (fsMethods === undefined) {
|
|
@@ -18758,16 +18838,16 @@ var require_fs4 = __commonJS((exports) => {
|
|
|
18758
18838
|
// ../../node_modules/@nodelib/fs.scandir/out/settings.js
|
|
18759
18839
|
var require_settings2 = __commonJS((exports) => {
|
|
18760
18840
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18761
|
-
var
|
|
18841
|
+
var path3 = __require("path");
|
|
18762
18842
|
var fsStat = require_out();
|
|
18763
|
-
var
|
|
18843
|
+
var fs5 = require_fs4();
|
|
18764
18844
|
|
|
18765
18845
|
class Settings {
|
|
18766
18846
|
constructor(_options = {}) {
|
|
18767
18847
|
this._options = _options;
|
|
18768
18848
|
this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false);
|
|
18769
|
-
this.fs =
|
|
18770
|
-
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator,
|
|
18849
|
+
this.fs = fs5.createFileSystemAdapter(this._options.fs);
|
|
18850
|
+
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path3.sep);
|
|
18771
18851
|
this.stats = this._getValue(this._options.stats, false);
|
|
18772
18852
|
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
|
|
18773
18853
|
this.fsStatSettings = new fsStat.Settings({
|
|
@@ -18791,17 +18871,17 @@ var require_out2 = __commonJS((exports) => {
|
|
|
18791
18871
|
var sync = require_sync2();
|
|
18792
18872
|
var settings_1 = require_settings2();
|
|
18793
18873
|
exports.Settings = settings_1.default;
|
|
18794
|
-
function scandir(
|
|
18874
|
+
function scandir(path3, optionsOrSettingsOrCallback, callback) {
|
|
18795
18875
|
if (typeof optionsOrSettingsOrCallback === "function") {
|
|
18796
|
-
async.read(
|
|
18876
|
+
async.read(path3, getSettings(), optionsOrSettingsOrCallback);
|
|
18797
18877
|
return;
|
|
18798
18878
|
}
|
|
18799
|
-
async.read(
|
|
18879
|
+
async.read(path3, getSettings(optionsOrSettingsOrCallback), callback);
|
|
18800
18880
|
}
|
|
18801
18881
|
exports.scandir = scandir;
|
|
18802
|
-
function scandirSync(
|
|
18882
|
+
function scandirSync(path3, optionsOrSettings) {
|
|
18803
18883
|
const settings = getSettings(optionsOrSettings);
|
|
18804
|
-
return sync.read(
|
|
18884
|
+
return sync.read(path3, settings);
|
|
18805
18885
|
}
|
|
18806
18886
|
exports.scandirSync = scandirSync;
|
|
18807
18887
|
function getSettings(settingsOrOptions = {}) {
|
|
@@ -19402,7 +19482,7 @@ var require_sync4 = __commonJS((exports) => {
|
|
|
19402
19482
|
// ../../node_modules/@nodelib/fs.walk/out/settings.js
|
|
19403
19483
|
var require_settings3 = __commonJS((exports) => {
|
|
19404
19484
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19405
|
-
var
|
|
19485
|
+
var path3 = __require("path");
|
|
19406
19486
|
var fsScandir = require_out2();
|
|
19407
19487
|
|
|
19408
19488
|
class Settings {
|
|
@@ -19413,7 +19493,7 @@ var require_settings3 = __commonJS((exports) => {
|
|
|
19413
19493
|
this.deepFilter = this._getValue(this._options.deepFilter, null);
|
|
19414
19494
|
this.entryFilter = this._getValue(this._options.entryFilter, null);
|
|
19415
19495
|
this.errorFilter = this._getValue(this._options.errorFilter, null);
|
|
19416
|
-
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator,
|
|
19496
|
+
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path3.sep);
|
|
19417
19497
|
this.fsScandirSettings = new fsScandir.Settings({
|
|
19418
19498
|
followSymbolicLinks: this._options.followSymbolicLinks,
|
|
19419
19499
|
fs: this._options.fs,
|
|
@@ -19469,7 +19549,7 @@ var require_out3 = __commonJS((exports) => {
|
|
|
19469
19549
|
// ../../node_modules/fast-glob/out/readers/reader.js
|
|
19470
19550
|
var require_reader2 = __commonJS((exports) => {
|
|
19471
19551
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19472
|
-
var
|
|
19552
|
+
var path3 = __require("path");
|
|
19473
19553
|
var fsStat = require_out();
|
|
19474
19554
|
var utils = require_utils3();
|
|
19475
19555
|
|
|
@@ -19483,7 +19563,7 @@ var require_reader2 = __commonJS((exports) => {
|
|
|
19483
19563
|
});
|
|
19484
19564
|
}
|
|
19485
19565
|
_getFullEntryPath(filepath) {
|
|
19486
|
-
return
|
|
19566
|
+
return path3.resolve(this._settings.cwd, filepath);
|
|
19487
19567
|
}
|
|
19488
19568
|
_makeEntry(stats, pattern) {
|
|
19489
19569
|
const entry = {
|
|
@@ -19880,7 +19960,7 @@ var require_entry2 = __commonJS((exports) => {
|
|
|
19880
19960
|
// ../../node_modules/fast-glob/out/providers/provider.js
|
|
19881
19961
|
var require_provider = __commonJS((exports) => {
|
|
19882
19962
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19883
|
-
var
|
|
19963
|
+
var path3 = __require("path");
|
|
19884
19964
|
var deep_1 = require_deep();
|
|
19885
19965
|
var entry_1 = require_entry();
|
|
19886
19966
|
var error_1 = require_error2();
|
|
@@ -19895,7 +19975,7 @@ var require_provider = __commonJS((exports) => {
|
|
|
19895
19975
|
this.entryTransformer = new entry_2.default(this._settings);
|
|
19896
19976
|
}
|
|
19897
19977
|
_getRootDirectory(task) {
|
|
19898
|
-
return
|
|
19978
|
+
return path3.resolve(this._settings.cwd, task.base);
|
|
19899
19979
|
}
|
|
19900
19980
|
_getReaderOptions(task) {
|
|
19901
19981
|
const basePath = task.base === "." ? "" : task.base;
|
|
@@ -20064,16 +20144,16 @@ var require_sync6 = __commonJS((exports) => {
|
|
|
20064
20144
|
var require_settings4 = __commonJS((exports) => {
|
|
20065
20145
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20066
20146
|
exports.DEFAULT_FILE_SYSTEM_ADAPTER = undefined;
|
|
20067
|
-
var
|
|
20147
|
+
var fs5 = __require("fs");
|
|
20068
20148
|
var os4 = __require("os");
|
|
20069
20149
|
var CPU_COUNT = Math.max(os4.cpus().length, 1);
|
|
20070
20150
|
exports.DEFAULT_FILE_SYSTEM_ADAPTER = {
|
|
20071
|
-
lstat:
|
|
20072
|
-
lstatSync:
|
|
20073
|
-
stat:
|
|
20074
|
-
statSync:
|
|
20075
|
-
readdir:
|
|
20076
|
-
readdirSync:
|
|
20151
|
+
lstat: fs5.lstat,
|
|
20152
|
+
lstatSync: fs5.lstatSync,
|
|
20153
|
+
stat: fs5.stat,
|
|
20154
|
+
statSync: fs5.statSync,
|
|
20155
|
+
readdir: fs5.readdir,
|
|
20156
|
+
readdirSync: fs5.readdirSync
|
|
20077
20157
|
};
|
|
20078
20158
|
|
|
20079
20159
|
class Settings {
|
|
@@ -20776,16 +20856,16 @@ var init_contract = __esm(() => {
|
|
|
20776
20856
|
|
|
20777
20857
|
// src/utils/config.ts
|
|
20778
20858
|
import { randomBytes } from "node:crypto";
|
|
20779
|
-
import { promises as
|
|
20859
|
+
import { promises as fs5 } from "node:fs";
|
|
20780
20860
|
import { createRequire as createRequire2 } from "node:module";
|
|
20781
20861
|
import { tmpdir } from "node:os";
|
|
20782
|
-
import
|
|
20862
|
+
import path3 from "node:path";
|
|
20783
20863
|
import { pathToFileURL } from "node:url";
|
|
20784
20864
|
async function findConfigFile(cwd) {
|
|
20785
20865
|
for (const fileName of CONFIG_FILE_NAMES) {
|
|
20786
|
-
const filePath =
|
|
20866
|
+
const filePath = path3.join(cwd, fileName);
|
|
20787
20867
|
try {
|
|
20788
|
-
await
|
|
20868
|
+
await fs5.access(filePath);
|
|
20789
20869
|
return filePath;
|
|
20790
20870
|
} catch {}
|
|
20791
20871
|
}
|
|
@@ -20793,21 +20873,21 @@ async function findConfigFile(cwd) {
|
|
|
20793
20873
|
}
|
|
20794
20874
|
async function loadConfig2(configPath) {
|
|
20795
20875
|
const cwd = process.cwd();
|
|
20796
|
-
const resolvedPath = configPath ?
|
|
20876
|
+
const resolvedPath = configPath ? path3.resolve(cwd, configPath) : await findConfigFile(cwd);
|
|
20797
20877
|
if (!resolvedPath) {
|
|
20798
20878
|
throw new Error("No config file found. Create a secondlayer.config.ts file or specify a path with --config");
|
|
20799
20879
|
}
|
|
20800
20880
|
let config;
|
|
20801
20881
|
if (resolvedPath.endsWith(".ts")) {
|
|
20802
|
-
const code = await
|
|
20882
|
+
const code = await fs5.readFile(resolvedPath, "utf-8");
|
|
20803
20883
|
let replacementPath;
|
|
20804
20884
|
try {
|
|
20805
20885
|
const require2 = createRequire2(import.meta.url);
|
|
20806
20886
|
const packagePath = require2.resolve("@secondlayer/cli");
|
|
20807
20887
|
replacementPath = pathToFileURL(packagePath).href;
|
|
20808
20888
|
} catch {
|
|
20809
|
-
const currentModuleDir =
|
|
20810
|
-
const indexPath =
|
|
20889
|
+
const currentModuleDir = path3.dirname(new URL(import.meta.url).pathname);
|
|
20890
|
+
const indexPath = path3.resolve(currentModuleDir, "../index");
|
|
20811
20891
|
replacementPath = pathToFileURL(indexPath).href;
|
|
20812
20892
|
}
|
|
20813
20893
|
const transformedCode = code.replace(/from\s+["']@secondlayer\/cli["']/g, `from '${replacementPath}'`);
|
|
@@ -20817,14 +20897,14 @@ async function loadConfig2(configPath) {
|
|
|
20817
20897
|
target: "node18",
|
|
20818
20898
|
loader: "ts"
|
|
20819
20899
|
});
|
|
20820
|
-
const tempPath =
|
|
20821
|
-
await
|
|
20900
|
+
const tempPath = path3.join(tmpdir(), `secondlayer-config-${randomBytes(4).toString("hex")}.mjs`);
|
|
20901
|
+
await fs5.writeFile(tempPath, result.code);
|
|
20822
20902
|
try {
|
|
20823
20903
|
const fileUrl = pathToFileURL(tempPath).href;
|
|
20824
20904
|
const module = await import(fileUrl);
|
|
20825
20905
|
config = module.default;
|
|
20826
20906
|
} finally {
|
|
20827
|
-
await
|
|
20907
|
+
await fs5.unlink(tempPath).catch(() => {});
|
|
20828
20908
|
}
|
|
20829
20909
|
} else {
|
|
20830
20910
|
const fileUrl = pathToFileURL(resolvedPath).href;
|
|
@@ -21794,11 +21874,11 @@ var init_commands = __esm(() => {
|
|
|
21794
21874
|
});
|
|
21795
21875
|
|
|
21796
21876
|
// ../../node_modules/@antfu/ni/dist/shared/ni.B5qNAuoI.mjs
|
|
21797
|
-
import
|
|
21877
|
+
import path4, { join as join11, dirname as dirname12, resolve as resolve9 } from "node:path";
|
|
21798
21878
|
import process$1 from "node:process";
|
|
21799
21879
|
import require$$0 from "readline";
|
|
21800
21880
|
import require$$2 from "events";
|
|
21801
|
-
import
|
|
21881
|
+
import fs6, { promises, existsSync as existsSync6 } from "node:fs";
|
|
21802
21882
|
import require$$0$1 from "os";
|
|
21803
21883
|
import require$$1 from "tty";
|
|
21804
21884
|
import os4 from "node:os";
|
|
@@ -22030,32 +22110,32 @@ function requireKleur() {
|
|
|
22030
22110
|
}
|
|
22031
22111
|
const $ = {
|
|
22032
22112
|
enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY),
|
|
22033
|
-
reset:
|
|
22034
|
-
bold:
|
|
22035
|
-
dim:
|
|
22036
|
-
italic:
|
|
22037
|
-
underline:
|
|
22038
|
-
inverse:
|
|
22039
|
-
hidden:
|
|
22040
|
-
strikethrough:
|
|
22041
|
-
black:
|
|
22042
|
-
red:
|
|
22043
|
-
green:
|
|
22044
|
-
yellow:
|
|
22045
|
-
blue:
|
|
22046
|
-
magenta:
|
|
22047
|
-
cyan:
|
|
22048
|
-
white:
|
|
22049
|
-
gray:
|
|
22050
|
-
grey:
|
|
22051
|
-
bgBlack:
|
|
22052
|
-
bgRed:
|
|
22053
|
-
bgGreen:
|
|
22054
|
-
bgYellow:
|
|
22055
|
-
bgBlue:
|
|
22056
|
-
bgMagenta:
|
|
22057
|
-
bgCyan:
|
|
22058
|
-
bgWhite:
|
|
22113
|
+
reset: init3(0, 0),
|
|
22114
|
+
bold: init3(1, 22),
|
|
22115
|
+
dim: init3(2, 22),
|
|
22116
|
+
italic: init3(3, 23),
|
|
22117
|
+
underline: init3(4, 24),
|
|
22118
|
+
inverse: init3(7, 27),
|
|
22119
|
+
hidden: init3(8, 28),
|
|
22120
|
+
strikethrough: init3(9, 29),
|
|
22121
|
+
black: init3(30, 39),
|
|
22122
|
+
red: init3(31, 39),
|
|
22123
|
+
green: init3(32, 39),
|
|
22124
|
+
yellow: init3(33, 39),
|
|
22125
|
+
blue: init3(34, 39),
|
|
22126
|
+
magenta: init3(35, 39),
|
|
22127
|
+
cyan: init3(36, 39),
|
|
22128
|
+
white: init3(37, 39),
|
|
22129
|
+
gray: init3(90, 39),
|
|
22130
|
+
grey: init3(90, 39),
|
|
22131
|
+
bgBlack: init3(40, 49),
|
|
22132
|
+
bgRed: init3(41, 49),
|
|
22133
|
+
bgGreen: init3(42, 49),
|
|
22134
|
+
bgYellow: init3(43, 49),
|
|
22135
|
+
bgBlue: init3(44, 49),
|
|
22136
|
+
bgMagenta: init3(45, 49),
|
|
22137
|
+
bgCyan: init3(46, 49),
|
|
22138
|
+
bgWhite: init3(47, 49)
|
|
22059
22139
|
};
|
|
22060
22140
|
function run(arr, str) {
|
|
22061
22141
|
let i2 = 0, tmp, beg = "", end = "";
|
|
@@ -22099,7 +22179,7 @@ function requireKleur() {
|
|
|
22099
22179
|
ctx.bgWhite = $.bgWhite.bind(ctx);
|
|
22100
22180
|
return ctx;
|
|
22101
22181
|
}
|
|
22102
|
-
function
|
|
22182
|
+
function init3(open, close) {
|
|
22103
22183
|
let blk = {
|
|
22104
22184
|
open: `\x1B[${open}m`,
|
|
22105
22185
|
close: `\x1B[${close}m`,
|
|
@@ -23754,11 +23834,11 @@ Instructions:
|
|
|
23754
23834
|
if (this.done) {
|
|
23755
23835
|
return this.value.filter((e2) => e2.selected).map((v2) => v2.title).join(", ");
|
|
23756
23836
|
}
|
|
23757
|
-
const
|
|
23837
|
+
const output2 = [color.gray(this.hint), this.renderInstructions()];
|
|
23758
23838
|
if (this.value[this.cursor].disabled) {
|
|
23759
|
-
|
|
23839
|
+
output2.push(color.yellow(this.warn));
|
|
23760
23840
|
}
|
|
23761
|
-
return
|
|
23841
|
+
return output2.join(" ");
|
|
23762
23842
|
}
|
|
23763
23843
|
render() {
|
|
23764
23844
|
if (this.closed)
|
|
@@ -24146,11 +24226,11 @@ Filtered results for: ${this.inputValue ? this.inputValue : color.gray("Enter so
|
|
|
24146
24226
|
if (this.done) {
|
|
24147
24227
|
return this.value.filter((e2) => e2.selected).map((v2) => v2.title).join(", ");
|
|
24148
24228
|
}
|
|
24149
|
-
const
|
|
24229
|
+
const output2 = [color.gray(this.hint), this.renderInstructions(), this.renderCurrentInput()];
|
|
24150
24230
|
if (this.filteredOptions.length && this.filteredOptions[this.cursor].disabled) {
|
|
24151
|
-
|
|
24231
|
+
output2.push(color.yellow(this.warn));
|
|
24152
24232
|
}
|
|
24153
|
-
return
|
|
24233
|
+
return output2.join(" ");
|
|
24154
24234
|
}
|
|
24155
24235
|
render() {
|
|
24156
24236
|
if (this.closed)
|
|
@@ -24647,10 +24727,10 @@ function requirePosix() {
|
|
|
24647
24727
|
posix.sync = posix.isexe = undefined;
|
|
24648
24728
|
const fs_1 = require$$0$2;
|
|
24649
24729
|
const promises_1 = require$$1$1;
|
|
24650
|
-
const isexe = async (
|
|
24730
|
+
const isexe = async (path5, options2 = {}) => {
|
|
24651
24731
|
const { ignoreErrors = false } = options2;
|
|
24652
24732
|
try {
|
|
24653
|
-
return checkStat(await (0, promises_1.stat)(
|
|
24733
|
+
return checkStat(await (0, promises_1.stat)(path5), options2);
|
|
24654
24734
|
} catch (e2) {
|
|
24655
24735
|
const er = e2;
|
|
24656
24736
|
if (ignoreErrors || er.code === "EACCES")
|
|
@@ -24659,10 +24739,10 @@ function requirePosix() {
|
|
|
24659
24739
|
}
|
|
24660
24740
|
};
|
|
24661
24741
|
posix.isexe = isexe;
|
|
24662
|
-
const sync = (
|
|
24742
|
+
const sync = (path5, options2 = {}) => {
|
|
24663
24743
|
const { ignoreErrors = false } = options2;
|
|
24664
24744
|
try {
|
|
24665
|
-
return checkStat((0, fs_1.statSync)(
|
|
24745
|
+
return checkStat((0, fs_1.statSync)(path5), options2);
|
|
24666
24746
|
} catch (e2) {
|
|
24667
24747
|
const er = e2;
|
|
24668
24748
|
if (ignoreErrors || er.code === "EACCES")
|
|
@@ -24699,10 +24779,10 @@ function requireWin32() {
|
|
|
24699
24779
|
win32.sync = win32.isexe = undefined;
|
|
24700
24780
|
const fs_1 = require$$0$2;
|
|
24701
24781
|
const promises_1 = require$$1$1;
|
|
24702
|
-
const isexe = async (
|
|
24782
|
+
const isexe = async (path5, options2 = {}) => {
|
|
24703
24783
|
const { ignoreErrors = false } = options2;
|
|
24704
24784
|
try {
|
|
24705
|
-
return checkStat(await (0, promises_1.stat)(
|
|
24785
|
+
return checkStat(await (0, promises_1.stat)(path5), path5, options2);
|
|
24706
24786
|
} catch (e2) {
|
|
24707
24787
|
const er = e2;
|
|
24708
24788
|
if (ignoreErrors || er.code === "EACCES")
|
|
@@ -24711,10 +24791,10 @@ function requireWin32() {
|
|
|
24711
24791
|
}
|
|
24712
24792
|
};
|
|
24713
24793
|
win32.isexe = isexe;
|
|
24714
|
-
const sync = (
|
|
24794
|
+
const sync = (path5, options2 = {}) => {
|
|
24715
24795
|
const { ignoreErrors = false } = options2;
|
|
24716
24796
|
try {
|
|
24717
|
-
return checkStat((0, fs_1.statSync)(
|
|
24797
|
+
return checkStat((0, fs_1.statSync)(path5), path5, options2);
|
|
24718
24798
|
} catch (e2) {
|
|
24719
24799
|
const er = e2;
|
|
24720
24800
|
if (ignoreErrors || er.code === "EACCES")
|
|
@@ -24723,7 +24803,7 @@ function requireWin32() {
|
|
|
24723
24803
|
}
|
|
24724
24804
|
};
|
|
24725
24805
|
win32.sync = sync;
|
|
24726
|
-
const checkPathExt = (
|
|
24806
|
+
const checkPathExt = (path5, options2) => {
|
|
24727
24807
|
const { pathExt = process.env.PATHEXT || "" } = options2;
|
|
24728
24808
|
const peSplit = pathExt.split(";");
|
|
24729
24809
|
if (peSplit.indexOf("") !== -1) {
|
|
@@ -24731,14 +24811,14 @@ function requireWin32() {
|
|
|
24731
24811
|
}
|
|
24732
24812
|
for (let i2 = 0;i2 < peSplit.length; i2++) {
|
|
24733
24813
|
const p2 = peSplit[i2].toLowerCase();
|
|
24734
|
-
const ext =
|
|
24814
|
+
const ext = path5.substring(path5.length - p2.length).toLowerCase();
|
|
24735
24815
|
if (p2 && ext === p2) {
|
|
24736
24816
|
return true;
|
|
24737
24817
|
}
|
|
24738
24818
|
}
|
|
24739
24819
|
return false;
|
|
24740
24820
|
};
|
|
24741
|
-
const checkStat = (stat2,
|
|
24821
|
+
const checkStat = (stat2, path5, options2) => stat2.isFile() && checkPathExt(path5, options2);
|
|
24742
24822
|
return win32;
|
|
24743
24823
|
}
|
|
24744
24824
|
function requireOptions() {
|
|
@@ -24988,7 +25068,7 @@ var init_ni_B5qNAuoI = __esm(() => {
|
|
|
24988
25068
|
CLI_TEMP_DIR = join11(os4.tmpdir(), "antfu-ni");
|
|
24989
25069
|
customRcPath = process$1.env.NI_CONFIG_FILE;
|
|
24990
25070
|
home = process$1.platform === "win32" ? process$1.env.USERPROFILE : process$1.env.HOME;
|
|
24991
|
-
defaultRcPath =
|
|
25071
|
+
defaultRcPath = path4.join(home || "~/", ".nirc");
|
|
24992
25072
|
});
|
|
24993
25073
|
|
|
24994
25074
|
// ../../node_modules/@antfu/ni/dist/index.mjs
|
|
@@ -25858,8 +25938,8 @@ var init_command = __esm(() => {
|
|
|
25858
25938
|
var require_windows = __commonJS((exports, module) => {
|
|
25859
25939
|
module.exports = isexe;
|
|
25860
25940
|
isexe.sync = sync;
|
|
25861
|
-
var
|
|
25862
|
-
function checkPathExt(
|
|
25941
|
+
var fs7 = __require("fs");
|
|
25942
|
+
function checkPathExt(path5, options3) {
|
|
25863
25943
|
var pathext = options3.pathExt !== undefined ? options3.pathExt : process.env.PATHEXT;
|
|
25864
25944
|
if (!pathext) {
|
|
25865
25945
|
return true;
|
|
@@ -25870,25 +25950,25 @@ var require_windows = __commonJS((exports, module) => {
|
|
|
25870
25950
|
}
|
|
25871
25951
|
for (var i2 = 0;i2 < pathext.length; i2++) {
|
|
25872
25952
|
var p2 = pathext[i2].toLowerCase();
|
|
25873
|
-
if (p2 &&
|
|
25953
|
+
if (p2 && path5.substr(-p2.length).toLowerCase() === p2) {
|
|
25874
25954
|
return true;
|
|
25875
25955
|
}
|
|
25876
25956
|
}
|
|
25877
25957
|
return false;
|
|
25878
25958
|
}
|
|
25879
|
-
function checkStat(stat2,
|
|
25959
|
+
function checkStat(stat2, path5, options3) {
|
|
25880
25960
|
if (!stat2.isSymbolicLink() && !stat2.isFile()) {
|
|
25881
25961
|
return false;
|
|
25882
25962
|
}
|
|
25883
|
-
return checkPathExt(
|
|
25963
|
+
return checkPathExt(path5, options3);
|
|
25884
25964
|
}
|
|
25885
|
-
function isexe(
|
|
25886
|
-
|
|
25887
|
-
cb(er, er ? false : checkStat(stat2,
|
|
25965
|
+
function isexe(path5, options3, cb) {
|
|
25966
|
+
fs7.stat(path5, function(er, stat2) {
|
|
25967
|
+
cb(er, er ? false : checkStat(stat2, path5, options3));
|
|
25888
25968
|
});
|
|
25889
25969
|
}
|
|
25890
|
-
function sync(
|
|
25891
|
-
return checkStat(
|
|
25970
|
+
function sync(path5, options3) {
|
|
25971
|
+
return checkStat(fs7.statSync(path5), path5, options3);
|
|
25892
25972
|
}
|
|
25893
25973
|
});
|
|
25894
25974
|
|
|
@@ -25896,14 +25976,14 @@ var require_windows = __commonJS((exports, module) => {
|
|
|
25896
25976
|
var require_mode = __commonJS((exports, module) => {
|
|
25897
25977
|
module.exports = isexe;
|
|
25898
25978
|
isexe.sync = sync;
|
|
25899
|
-
var
|
|
25900
|
-
function isexe(
|
|
25901
|
-
|
|
25979
|
+
var fs7 = __require("fs");
|
|
25980
|
+
function isexe(path5, options3, cb) {
|
|
25981
|
+
fs7.stat(path5, function(er, stat2) {
|
|
25902
25982
|
cb(er, er ? false : checkStat(stat2, options3));
|
|
25903
25983
|
});
|
|
25904
25984
|
}
|
|
25905
|
-
function sync(
|
|
25906
|
-
return checkStat(
|
|
25985
|
+
function sync(path5, options3) {
|
|
25986
|
+
return checkStat(fs7.statSync(path5), options3);
|
|
25907
25987
|
}
|
|
25908
25988
|
function checkStat(stat2, options3) {
|
|
25909
25989
|
return stat2.isFile() && checkMode(stat2, options3);
|
|
@@ -25925,7 +26005,7 @@ var require_mode = __commonJS((exports, module) => {
|
|
|
25925
26005
|
|
|
25926
26006
|
// ../../node_modules/isexe/index.js
|
|
25927
26007
|
var require_isexe = __commonJS((exports, module) => {
|
|
25928
|
-
var
|
|
26008
|
+
var fs7 = __require("fs");
|
|
25929
26009
|
var core2;
|
|
25930
26010
|
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
25931
26011
|
core2 = require_windows();
|
|
@@ -25934,7 +26014,7 @@ var require_isexe = __commonJS((exports, module) => {
|
|
|
25934
26014
|
}
|
|
25935
26015
|
module.exports = isexe;
|
|
25936
26016
|
isexe.sync = sync;
|
|
25937
|
-
function isexe(
|
|
26017
|
+
function isexe(path5, options3, cb) {
|
|
25938
26018
|
if (typeof options3 === "function") {
|
|
25939
26019
|
cb = options3;
|
|
25940
26020
|
options3 = {};
|
|
@@ -25944,7 +26024,7 @@ var require_isexe = __commonJS((exports, module) => {
|
|
|
25944
26024
|
throw new TypeError("callback not provided");
|
|
25945
26025
|
}
|
|
25946
26026
|
return new Promise(function(resolve10, reject) {
|
|
25947
|
-
isexe(
|
|
26027
|
+
isexe(path5, options3 || {}, function(er, is2) {
|
|
25948
26028
|
if (er) {
|
|
25949
26029
|
reject(er);
|
|
25950
26030
|
} else {
|
|
@@ -25953,7 +26033,7 @@ var require_isexe = __commonJS((exports, module) => {
|
|
|
25953
26033
|
});
|
|
25954
26034
|
});
|
|
25955
26035
|
}
|
|
25956
|
-
core2(
|
|
26036
|
+
core2(path5, options3 || {}, function(er, is2) {
|
|
25957
26037
|
if (er) {
|
|
25958
26038
|
if (er.code === "EACCES" || options3 && options3.ignoreErrors) {
|
|
25959
26039
|
er = null;
|
|
@@ -25963,9 +26043,9 @@ var require_isexe = __commonJS((exports, module) => {
|
|
|
25963
26043
|
cb(er, is2);
|
|
25964
26044
|
});
|
|
25965
26045
|
}
|
|
25966
|
-
function sync(
|
|
26046
|
+
function sync(path5, options3) {
|
|
25967
26047
|
try {
|
|
25968
|
-
return core2.sync(
|
|
26048
|
+
return core2.sync(path5, options3 || {});
|
|
25969
26049
|
} catch (er) {
|
|
25970
26050
|
if (options3 && options3.ignoreErrors || er.code === "EACCES") {
|
|
25971
26051
|
return false;
|
|
@@ -25979,7 +26059,7 @@ var require_isexe = __commonJS((exports, module) => {
|
|
|
25979
26059
|
// ../../node_modules/which/which.js
|
|
25980
26060
|
var require_which = __commonJS((exports, module) => {
|
|
25981
26061
|
var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
25982
|
-
var
|
|
26062
|
+
var path5 = __require("path");
|
|
25983
26063
|
var COLON = isWindows ? ";" : ":";
|
|
25984
26064
|
var isexe = require_isexe();
|
|
25985
26065
|
var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
@@ -26015,7 +26095,7 @@ var require_which = __commonJS((exports, module) => {
|
|
|
26015
26095
|
return opt.all && found.length ? resolve10(found) : reject(getNotFoundError(cmd));
|
|
26016
26096
|
const ppRaw = pathEnv[i2];
|
|
26017
26097
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
26018
|
-
const pCmd =
|
|
26098
|
+
const pCmd = path5.join(pathPart, cmd);
|
|
26019
26099
|
const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
26020
26100
|
resolve10(subStep(p2, i2, 0));
|
|
26021
26101
|
});
|
|
@@ -26042,7 +26122,7 @@ var require_which = __commonJS((exports, module) => {
|
|
|
26042
26122
|
for (let i2 = 0;i2 < pathEnv.length; i2++) {
|
|
26043
26123
|
const ppRaw = pathEnv[i2];
|
|
26044
26124
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
26045
|
-
const pCmd =
|
|
26125
|
+
const pCmd = path5.join(pathPart, cmd);
|
|
26046
26126
|
const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
26047
26127
|
for (let j2 = 0;j2 < pathExt.length; j2++) {
|
|
26048
26128
|
const cur = p2 + pathExt[j2];
|
|
@@ -26083,7 +26163,7 @@ var require_path_key = __commonJS((exports, module) => {
|
|
|
26083
26163
|
|
|
26084
26164
|
// ../../node_modules/cross-spawn/lib/util/resolveCommand.js
|
|
26085
26165
|
var require_resolveCommand = __commonJS((exports, module) => {
|
|
26086
|
-
var
|
|
26166
|
+
var path5 = __require("path");
|
|
26087
26167
|
var which2 = require_which();
|
|
26088
26168
|
var getPathKey = require_path_key();
|
|
26089
26169
|
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
@@ -26100,7 +26180,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
|
|
|
26100
26180
|
try {
|
|
26101
26181
|
resolved = which2.sync(parsed.command, {
|
|
26102
26182
|
path: env2[getPathKey({ env: env2 })],
|
|
26103
|
-
pathExt: withoutPathExt ?
|
|
26183
|
+
pathExt: withoutPathExt ? path5.delimiter : undefined
|
|
26104
26184
|
});
|
|
26105
26185
|
} catch (e2) {} finally {
|
|
26106
26186
|
if (shouldSwitchCwd) {
|
|
@@ -26108,7 +26188,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
|
|
|
26108
26188
|
}
|
|
26109
26189
|
}
|
|
26110
26190
|
if (resolved) {
|
|
26111
|
-
resolved =
|
|
26191
|
+
resolved = path5.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
|
|
26112
26192
|
}
|
|
26113
26193
|
return resolved;
|
|
26114
26194
|
}
|
|
@@ -26153,8 +26233,8 @@ var require_shebang_command = __commonJS((exports, module) => {
|
|
|
26153
26233
|
if (!match) {
|
|
26154
26234
|
return null;
|
|
26155
26235
|
}
|
|
26156
|
-
const [
|
|
26157
|
-
const binary =
|
|
26236
|
+
const [path5, argument] = match[0].replace(/#! ?/, "").split(" ");
|
|
26237
|
+
const binary = path5.split("/").pop();
|
|
26158
26238
|
if (binary === "env") {
|
|
26159
26239
|
return argument;
|
|
26160
26240
|
}
|
|
@@ -26164,16 +26244,16 @@ var require_shebang_command = __commonJS((exports, module) => {
|
|
|
26164
26244
|
|
|
26165
26245
|
// ../../node_modules/cross-spawn/lib/util/readShebang.js
|
|
26166
26246
|
var require_readShebang = __commonJS((exports, module) => {
|
|
26167
|
-
var
|
|
26247
|
+
var fs7 = __require("fs");
|
|
26168
26248
|
var shebangCommand = require_shebang_command();
|
|
26169
26249
|
function readShebang(command) {
|
|
26170
26250
|
const size2 = 150;
|
|
26171
26251
|
const buffer2 = Buffer.alloc(size2);
|
|
26172
26252
|
let fd;
|
|
26173
26253
|
try {
|
|
26174
|
-
fd =
|
|
26175
|
-
|
|
26176
|
-
|
|
26254
|
+
fd = fs7.openSync(command, "r");
|
|
26255
|
+
fs7.readSync(fd, buffer2, 0, size2, 0);
|
|
26256
|
+
fs7.closeSync(fd);
|
|
26177
26257
|
} catch (e2) {}
|
|
26178
26258
|
return shebangCommand(buffer2.toString());
|
|
26179
26259
|
}
|
|
@@ -26182,7 +26262,7 @@ var require_readShebang = __commonJS((exports, module) => {
|
|
|
26182
26262
|
|
|
26183
26263
|
// ../../node_modules/cross-spawn/lib/parse.js
|
|
26184
26264
|
var require_parse3 = __commonJS((exports, module) => {
|
|
26185
|
-
var
|
|
26265
|
+
var path5 = __require("path");
|
|
26186
26266
|
var resolveCommand2 = require_resolveCommand();
|
|
26187
26267
|
var escape2 = require_escape();
|
|
26188
26268
|
var readShebang = require_readShebang();
|
|
@@ -26207,7 +26287,7 @@ var require_parse3 = __commonJS((exports, module) => {
|
|
|
26207
26287
|
const needsShell = !isExecutableRegExp.test(commandFile);
|
|
26208
26288
|
if (parsed.options.forceShell || needsShell) {
|
|
26209
26289
|
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
26210
|
-
parsed.command =
|
|
26290
|
+
parsed.command = path5.normalize(parsed.command);
|
|
26211
26291
|
parsed.command = escape2.command(parsed.command);
|
|
26212
26292
|
parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
|
|
26213
26293
|
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
@@ -26324,7 +26404,7 @@ function pathKey(options3 = {}) {
|
|
|
26324
26404
|
// ../../node_modules/unicorn-magic/node.js
|
|
26325
26405
|
import { promisify as promisify4 } from "node:util";
|
|
26326
26406
|
import { execFile as execFileCallback, execFileSync as execFileSyncOriginal } from "node:child_process";
|
|
26327
|
-
import
|
|
26407
|
+
import path5 from "node:path";
|
|
26328
26408
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
26329
26409
|
function toPath(urlOrPath) {
|
|
26330
26410
|
return urlOrPath instanceof URL ? fileURLToPath4(urlOrPath) : urlOrPath;
|
|
@@ -26332,12 +26412,12 @@ function toPath(urlOrPath) {
|
|
|
26332
26412
|
function traversePathUp(startPath) {
|
|
26333
26413
|
return {
|
|
26334
26414
|
*[Symbol.iterator]() {
|
|
26335
|
-
let currentPath =
|
|
26415
|
+
let currentPath = path5.resolve(toPath(startPath));
|
|
26336
26416
|
let previousPath;
|
|
26337
26417
|
while (previousPath !== currentPath) {
|
|
26338
26418
|
yield currentPath;
|
|
26339
26419
|
previousPath = currentPath;
|
|
26340
|
-
currentPath =
|
|
26420
|
+
currentPath = path5.resolve(currentPath, "..");
|
|
26341
26421
|
}
|
|
26342
26422
|
}
|
|
26343
26423
|
};
|
|
@@ -26350,7 +26430,7 @@ var init_node = __esm(() => {
|
|
|
26350
26430
|
|
|
26351
26431
|
// ../../node_modules/npm-run-path/index.js
|
|
26352
26432
|
import process7 from "node:process";
|
|
26353
|
-
import
|
|
26433
|
+
import path6 from "node:path";
|
|
26354
26434
|
var npmRunPath = ({
|
|
26355
26435
|
cwd = process7.cwd(),
|
|
26356
26436
|
path: pathOption = process7.env[pathKey()],
|
|
@@ -26358,25 +26438,25 @@ var npmRunPath = ({
|
|
|
26358
26438
|
execPath = process7.execPath,
|
|
26359
26439
|
addExecPath = true
|
|
26360
26440
|
} = {}) => {
|
|
26361
|
-
const cwdPath =
|
|
26441
|
+
const cwdPath = path6.resolve(toPath(cwd));
|
|
26362
26442
|
const result = [];
|
|
26363
|
-
const pathParts = pathOption.split(
|
|
26443
|
+
const pathParts = pathOption.split(path6.delimiter);
|
|
26364
26444
|
if (preferLocal) {
|
|
26365
26445
|
applyPreferLocal(result, pathParts, cwdPath);
|
|
26366
26446
|
}
|
|
26367
26447
|
if (addExecPath) {
|
|
26368
26448
|
applyExecPath(result, pathParts, execPath, cwdPath);
|
|
26369
26449
|
}
|
|
26370
|
-
return pathOption === "" || pathOption ===
|
|
26450
|
+
return pathOption === "" || pathOption === path6.delimiter ? `${result.join(path6.delimiter)}${pathOption}` : [...result, pathOption].join(path6.delimiter);
|
|
26371
26451
|
}, applyPreferLocal = (result, pathParts, cwdPath) => {
|
|
26372
26452
|
for (const directory of traversePathUp(cwdPath)) {
|
|
26373
|
-
const pathPart =
|
|
26453
|
+
const pathPart = path6.join(directory, "node_modules/.bin");
|
|
26374
26454
|
if (!pathParts.includes(pathPart)) {
|
|
26375
26455
|
result.push(pathPart);
|
|
26376
26456
|
}
|
|
26377
26457
|
}
|
|
26378
26458
|
}, applyExecPath = (result, pathParts, execPath, cwdPath) => {
|
|
26379
|
-
const pathPart =
|
|
26459
|
+
const pathPart = path6.resolve(cwdPath, toPath(execPath), "..");
|
|
26380
26460
|
if (!pathParts.includes(pathPart)) {
|
|
26381
26461
|
result.push(pathPart);
|
|
26382
26462
|
}
|
|
@@ -27486,7 +27566,7 @@ var init_timeout = __esm(() => {
|
|
|
27486
27566
|
|
|
27487
27567
|
// ../../node_modules/execa/lib/methods/node.js
|
|
27488
27568
|
import { execPath, execArgv } from "node:process";
|
|
27489
|
-
import
|
|
27569
|
+
import path7 from "node:path";
|
|
27490
27570
|
var mapNode = ({ options: options3 }) => {
|
|
27491
27571
|
if (options3.node === false) {
|
|
27492
27572
|
throw new TypeError('The "node" option cannot be false with `execaNode()`.');
|
|
@@ -27504,7 +27584,7 @@ var mapNode = ({ options: options3 }) => {
|
|
|
27504
27584
|
throw new TypeError('The "execPath" option has been removed. Please use the "nodePath" option instead.');
|
|
27505
27585
|
}
|
|
27506
27586
|
const normalizedNodePath = safeNormalizeFileUrl(nodePath, 'The "nodePath" option');
|
|
27507
|
-
const resolvedNodePath =
|
|
27587
|
+
const resolvedNodePath = path7.resolve(cwd, normalizedNodePath);
|
|
27508
27588
|
const newOptions = {
|
|
27509
27589
|
...options3,
|
|
27510
27590
|
nodePath: resolvedNodePath,
|
|
@@ -27514,7 +27594,7 @@ var mapNode = ({ options: options3 }) => {
|
|
|
27514
27594
|
if (!shouldHandleNode) {
|
|
27515
27595
|
return [file, commandArguments, newOptions];
|
|
27516
27596
|
}
|
|
27517
|
-
if (
|
|
27597
|
+
if (path7.basename(file, ".exe") === "node") {
|
|
27518
27598
|
throw new TypeError('When the "node" option is true, the first argument does not need to be "node".');
|
|
27519
27599
|
}
|
|
27520
27600
|
return [
|
|
@@ -27605,11 +27685,11 @@ var init_encoding_option = __esm(() => {
|
|
|
27605
27685
|
|
|
27606
27686
|
// ../../node_modules/execa/lib/arguments/cwd.js
|
|
27607
27687
|
import { statSync as statSync2 } from "node:fs";
|
|
27608
|
-
import
|
|
27688
|
+
import path8 from "node:path";
|
|
27609
27689
|
import process8 from "node:process";
|
|
27610
27690
|
var normalizeCwd = (cwd = getDefaultCwd()) => {
|
|
27611
27691
|
const cwdString = safeNormalizeFileUrl(cwd, 'The "cwd" option');
|
|
27612
|
-
return
|
|
27692
|
+
return path8.resolve(cwdString);
|
|
27613
27693
|
}, getDefaultCwd = () => {
|
|
27614
27694
|
try {
|
|
27615
27695
|
return process8.cwd();
|
|
@@ -27641,7 +27721,7 @@ var init_cwd = __esm(() => {
|
|
|
27641
27721
|
});
|
|
27642
27722
|
|
|
27643
27723
|
// ../../node_modules/execa/lib/arguments/options.js
|
|
27644
|
-
import
|
|
27724
|
+
import path9 from "node:path";
|
|
27645
27725
|
import process9 from "node:process";
|
|
27646
27726
|
var import_cross_spawn, normalizeOptions = (filePath, rawArguments, rawOptions) => {
|
|
27647
27727
|
rawOptions.cwd = normalizeCwd(rawOptions.cwd);
|
|
@@ -27659,7 +27739,7 @@ var import_cross_spawn, normalizeOptions = (filePath, rawArguments, rawOptions)
|
|
|
27659
27739
|
options3.killSignal = normalizeKillSignal(options3.killSignal);
|
|
27660
27740
|
options3.forceKillAfterDelay = normalizeForceKillAfterDelay(options3.forceKillAfterDelay);
|
|
27661
27741
|
options3.lines = options3.lines.map((lines2, fdNumber) => lines2 && !BINARY_ENCODINGS.has(options3.encoding) && options3.buffer[fdNumber]);
|
|
27662
|
-
if (process9.platform === "win32" &&
|
|
27742
|
+
if (process9.platform === "win32" && path9.basename(file, ".exe") === "cmd") {
|
|
27663
27743
|
commandArguments.unshift("/q");
|
|
27664
27744
|
}
|
|
27665
27745
|
return { file, commandArguments, options: options3 };
|
|
@@ -27907,7 +27987,7 @@ var handleMaxBuffer = ({ error: error2, stream: stream2, readableObjectMode, lin
|
|
|
27907
27987
|
return { streamName: "IPC output", threshold, unit: "messages" };
|
|
27908
27988
|
}
|
|
27909
27989
|
return { streamName: getStreamName(fdNumber), threshold, unit };
|
|
27910
|
-
}, isMaxBufferSync = (resultError,
|
|
27990
|
+
}, isMaxBufferSync = (resultError, output2, maxBuffer) => resultError?.code === "ENOBUFS" && output2 !== null && output2.some((result) => result !== null && result.length > getMaxBufferSync(maxBuffer)), truncateMaxBufferSync = (result, isMaxBuffer, maxBuffer) => {
|
|
27911
27991
|
if (!isMaxBuffer) {
|
|
27912
27992
|
return result;
|
|
27913
27993
|
}
|
|
@@ -29443,13 +29523,13 @@ var init_output2 = __esm(() => {
|
|
|
29443
29523
|
|
|
29444
29524
|
// ../../node_modules/execa/lib/io/output-sync.js
|
|
29445
29525
|
import { writeFileSync as writeFileSync5, appendFileSync } from "node:fs";
|
|
29446
|
-
var transformOutputSync = ({ fileDescriptors, syncResult: { output }, options: options3, isMaxBuffer, verboseInfo }) => {
|
|
29447
|
-
if (
|
|
29526
|
+
var transformOutputSync = ({ fileDescriptors, syncResult: { output: output2 }, options: options3, isMaxBuffer, verboseInfo }) => {
|
|
29527
|
+
if (output2 === null) {
|
|
29448
29528
|
return { output: Array.from({ length: 3 }) };
|
|
29449
29529
|
}
|
|
29450
29530
|
const state = {};
|
|
29451
29531
|
const outputFiles = new Set([]);
|
|
29452
|
-
const transformedOutput =
|
|
29532
|
+
const transformedOutput = output2.map((result, fdNumber) => transformOutputResultSync({
|
|
29453
29533
|
result,
|
|
29454
29534
|
fileDescriptors,
|
|
29455
29535
|
fdNumber,
|
|
@@ -29529,13 +29609,13 @@ var transformOutputSync = ({ fileDescriptors, syncResult: { output }, options: o
|
|
|
29529
29609
|
state.error ??= error2;
|
|
29530
29610
|
}
|
|
29531
29611
|
}, writeToFiles = (serializedResult, stdioItems, outputFiles) => {
|
|
29532
|
-
for (const { path:
|
|
29533
|
-
const pathString = typeof
|
|
29612
|
+
for (const { path: path10, append } of stdioItems.filter(({ type }) => FILE_TYPES.has(type))) {
|
|
29613
|
+
const pathString = typeof path10 === "string" ? path10 : path10.toString();
|
|
29534
29614
|
if (append || outputFiles.has(pathString)) {
|
|
29535
|
-
appendFileSync(
|
|
29615
|
+
appendFileSync(path10, serializedResult);
|
|
29536
29616
|
} else {
|
|
29537
29617
|
outputFiles.add(pathString);
|
|
29538
|
-
writeFileSync5(
|
|
29618
|
+
writeFileSync5(path10, serializedResult);
|
|
29539
29619
|
}
|
|
29540
29620
|
}
|
|
29541
29621
|
};
|
|
@@ -29608,10 +29688,10 @@ var init_exit_async = __esm(() => {
|
|
|
29608
29688
|
});
|
|
29609
29689
|
|
|
29610
29690
|
// ../../node_modules/execa/lib/resolve/exit-sync.js
|
|
29611
|
-
var getExitResultSync = ({ error: error2, status: exitCode, signal, output }, { maxBuffer }) => {
|
|
29691
|
+
var getExitResultSync = ({ error: error2, status: exitCode, signal, output: output2 }, { maxBuffer }) => {
|
|
29612
29692
|
const resultError = getResultError(error2, exitCode, signal);
|
|
29613
29693
|
const timedOut2 = resultError?.code === "ETIMEDOUT";
|
|
29614
|
-
const isMaxBuffer = isMaxBufferSync(resultError,
|
|
29694
|
+
const isMaxBuffer = isMaxBufferSync(resultError, output2, maxBuffer);
|
|
29615
29695
|
return {
|
|
29616
29696
|
resultError,
|
|
29617
29697
|
exitCode,
|
|
@@ -29691,15 +29771,15 @@ var execaCoreSync = (rawFile, rawArguments, rawOptions) => {
|
|
|
29691
29771
|
return syncResult;
|
|
29692
29772
|
}
|
|
29693
29773
|
const { resultError, exitCode, signal, timedOut: timedOut2, isMaxBuffer } = getExitResultSync(syncResult, options3);
|
|
29694
|
-
const { output, error: error2 = resultError } = transformOutputSync({
|
|
29774
|
+
const { output: output2, error: error2 = resultError } = transformOutputSync({
|
|
29695
29775
|
fileDescriptors,
|
|
29696
29776
|
syncResult,
|
|
29697
29777
|
options: options3,
|
|
29698
29778
|
isMaxBuffer,
|
|
29699
29779
|
verboseInfo
|
|
29700
29780
|
});
|
|
29701
|
-
const stdio =
|
|
29702
|
-
const all2 = stripNewline(getAllSync(
|
|
29781
|
+
const stdio = output2.map((stdioOutput, fdNumber) => stripNewline(stdioOutput, options3, fdNumber));
|
|
29782
|
+
const all2 = stripNewline(getAllSync(output2, options3), options3, "all");
|
|
29703
29783
|
return getSyncResult({
|
|
29704
29784
|
error: error2,
|
|
29705
29785
|
exitCode,
|
|
@@ -30924,7 +31004,7 @@ var getStreamOutput = async ({ stream: stream2, onStreamEnd, fdNumber, encoding,
|
|
|
30924
31004
|
stripFinalNewline: stripFinalNewlineValue,
|
|
30925
31005
|
allMixed
|
|
30926
31006
|
});
|
|
30927
|
-
const [
|
|
31007
|
+
const [output2] = await Promise.all([
|
|
30928
31008
|
getStreamContents({
|
|
30929
31009
|
stream: stream2,
|
|
30930
31010
|
iterable,
|
|
@@ -30935,7 +31015,7 @@ var getStreamOutput = async ({ stream: stream2, onStreamEnd, fdNumber, encoding,
|
|
|
30935
31015
|
}),
|
|
30936
31016
|
logPromise
|
|
30937
31017
|
]);
|
|
30938
|
-
return
|
|
31018
|
+
return output2;
|
|
30939
31019
|
}, logOutputAsync = async ({ stream: stream2, onStreamEnd, fdNumber, encoding, allMixed, verboseInfo, streamInfo: { fileDescriptors } }) => {
|
|
30940
31020
|
if (!shouldLogOutput({
|
|
30941
31021
|
stdioItems: fileDescriptors[fdNumber]?.stdioItems,
|
|
@@ -31061,7 +31141,7 @@ var waitForStdioStreams = ({ subprocess, encoding, buffer: buffer2, maxBuffer, l
|
|
|
31061
31141
|
await onStreamEnd;
|
|
31062
31142
|
return;
|
|
31063
31143
|
}
|
|
31064
|
-
const [
|
|
31144
|
+
const [output2] = await Promise.all([
|
|
31065
31145
|
getStreamOutput({
|
|
31066
31146
|
stream: stream2,
|
|
31067
31147
|
onStreamEnd,
|
|
@@ -31077,7 +31157,7 @@ var waitForStdioStreams = ({ subprocess, encoding, buffer: buffer2, maxBuffer, l
|
|
|
31077
31157
|
}),
|
|
31078
31158
|
onStreamEnd
|
|
31079
31159
|
]);
|
|
31080
|
-
return
|
|
31160
|
+
return output2;
|
|
31081
31161
|
};
|
|
31082
31162
|
var init_stdio = __esm(() => {
|
|
31083
31163
|
init_contents();
|
|
@@ -31938,8 +32018,8 @@ var init_execa = __esm(() => {
|
|
|
31938
32018
|
});
|
|
31939
32019
|
|
|
31940
32020
|
// src/utils/dependencies.ts
|
|
31941
|
-
import { promises as
|
|
31942
|
-
import
|
|
32021
|
+
import { promises as fs7 } from "node:fs";
|
|
32022
|
+
import path10 from "node:path";
|
|
31943
32023
|
async function getPackageManager(targetDir) {
|
|
31944
32024
|
const packageManager = await detect2({ programmatic: true, cwd: targetDir });
|
|
31945
32025
|
if (packageManager === "yarn@berry")
|
|
@@ -31954,16 +32034,16 @@ async function getPackageManager(targetDir) {
|
|
|
31954
32034
|
}
|
|
31955
32035
|
async function hasPackageJson(targetDir) {
|
|
31956
32036
|
try {
|
|
31957
|
-
const packageJsonPath =
|
|
31958
|
-
await
|
|
32037
|
+
const packageJsonPath = path10.join(targetDir, "package.json");
|
|
32038
|
+
await fs7.access(packageJsonPath);
|
|
31959
32039
|
return true;
|
|
31960
32040
|
} catch {
|
|
31961
32041
|
return false;
|
|
31962
32042
|
}
|
|
31963
32043
|
}
|
|
31964
32044
|
async function readPackageJson(targetDir) {
|
|
31965
|
-
const packageJsonPath =
|
|
31966
|
-
const content = await
|
|
32045
|
+
const packageJsonPath = path10.join(targetDir, "package.json");
|
|
32046
|
+
const content = await fs7.readFile(packageJsonPath, "utf-8");
|
|
31967
32047
|
return JSON.parse(content);
|
|
31968
32048
|
}
|
|
31969
32049
|
async function getMissingDependenciesFor(targetDir, requiredDeps) {
|
|
@@ -32016,7 +32096,7 @@ __export(exports_generate, {
|
|
|
32016
32096
|
resolveContract: () => resolveContract,
|
|
32017
32097
|
generate: () => generate
|
|
32018
32098
|
});
|
|
32019
|
-
import
|
|
32099
|
+
import path11 from "node:path";
|
|
32020
32100
|
import { getErrorMessage as getErrorMessage2 } from "@secondlayer/shared";
|
|
32021
32101
|
import { toCamelCase as toCamelCase8 } from "@secondlayer/stacks/clarity";
|
|
32022
32102
|
function isContractAddress(input5) {
|
|
@@ -32041,7 +32121,7 @@ async function parseInputs(inputs) {
|
|
|
32041
32121
|
continue;
|
|
32042
32122
|
}
|
|
32043
32123
|
if (input5.endsWith(".clar")) {
|
|
32044
|
-
const absolutePath =
|
|
32124
|
+
const absolutePath = path11.resolve(process.cwd(), input5);
|
|
32045
32125
|
files.push(absolutePath);
|
|
32046
32126
|
}
|
|
32047
32127
|
}
|
|
@@ -32051,7 +32131,7 @@ async function parseInputs(inputs) {
|
|
|
32051
32131
|
};
|
|
32052
32132
|
}
|
|
32053
32133
|
function deriveContractName(filePath) {
|
|
32054
|
-
const basename =
|
|
32134
|
+
const basename = path11.basename(filePath, ".clar");
|
|
32055
32135
|
return basename.replace(/[-_](.)/g, (_2, char) => char.toUpperCase()).replace(/^(.)/, (_2, char) => char.toLowerCase()).replace(/^\d/, "_$&");
|
|
32056
32136
|
}
|
|
32057
32137
|
async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddress) {
|
|
@@ -32178,9 +32258,9 @@ ${getErrorMessage2(error2)}`));
|
|
|
32178
32258
|
}
|
|
32179
32259
|
async function resolveContract(source, network, apiKey, apiUrl) {
|
|
32180
32260
|
if (source.source) {
|
|
32181
|
-
const filePath =
|
|
32261
|
+
const filePath = path11.resolve(process.cwd(), source.source);
|
|
32182
32262
|
const abi = await parseClarityFile(filePath);
|
|
32183
|
-
const name = source.name ||
|
|
32263
|
+
const name = source.name || path11.basename(source.source, ".clar").replace(/-/g, "_").replace(/^\d/, "_$&");
|
|
32184
32264
|
const address = typeof source.address === "string" ? source.address : source.address?.[network] || DEFAULT_DEVNET_ADDRESS;
|
|
32185
32265
|
const { address: contractAddress, contractName } = address.includes(".") ? parseContractId(address) : { address, contractName: name };
|
|
32186
32266
|
return {
|
|
@@ -32256,56 +32336,6 @@ var init_generate = __esm(() => {
|
|
|
32256
32336
|
import_fast_glob = __toESM(require_out4(), 1);
|
|
32257
32337
|
});
|
|
32258
32338
|
|
|
32259
|
-
// src/commands/init.ts
|
|
32260
|
-
var exports_init = {};
|
|
32261
|
-
__export(exports_init, {
|
|
32262
|
-
init: () => init2
|
|
32263
|
-
});
|
|
32264
|
-
import { promises as fs7 } from "node:fs";
|
|
32265
|
-
import path11 from "node:path";
|
|
32266
|
-
async function init2() {
|
|
32267
|
-
const configPath = path11.join(process.cwd(), "secondlayer.config.ts");
|
|
32268
|
-
try {
|
|
32269
|
-
await fs7.access(configPath);
|
|
32270
|
-
console.log(source_default3.yellow("⚠ secondlayer.config.ts already exists"));
|
|
32271
|
-
return;
|
|
32272
|
-
} catch {}
|
|
32273
|
-
const hasClarinetProject = await fileExists2("./Clarinet.toml");
|
|
32274
|
-
let config;
|
|
32275
|
-
if (hasClarinetProject) {
|
|
32276
|
-
config = `import { defineConfig } from '@secondlayer/cli';
|
|
32277
|
-
import { clarinet } from '@secondlayer/cli/plugins';
|
|
32278
|
-
|
|
32279
|
-
export default defineConfig({
|
|
32280
|
-
out: './src/generated/contracts.ts',
|
|
32281
|
-
plugins: [
|
|
32282
|
-
clarinet() // Found Clarinet.toml in current directory
|
|
32283
|
-
]
|
|
32284
|
-
});`;
|
|
32285
|
-
} else {
|
|
32286
|
-
config = `import { defineConfig } from '@secondlayer/cli';
|
|
32287
|
-
|
|
32288
|
-
export default defineConfig({
|
|
32289
|
-
out: './src/generated/contracts.ts',
|
|
32290
|
-
plugins: [],
|
|
32291
|
-
});`;
|
|
32292
|
-
}
|
|
32293
|
-
await fs7.writeFile(configPath, config);
|
|
32294
|
-
console.log(source_default3.green("✓ Created `secondlayer.config.ts`"));
|
|
32295
|
-
console.log("\nRun `secondlayer generate` to generate type-safe interfaces, functions, and hooks!");
|
|
32296
|
-
}
|
|
32297
|
-
async function fileExists2(filePath) {
|
|
32298
|
-
try {
|
|
32299
|
-
await fs7.access(filePath);
|
|
32300
|
-
return true;
|
|
32301
|
-
} catch {
|
|
32302
|
-
return false;
|
|
32303
|
-
}
|
|
32304
|
-
}
|
|
32305
|
-
var init_init = __esm(() => {
|
|
32306
|
-
init_source4();
|
|
32307
|
-
});
|
|
32308
|
-
|
|
32309
32339
|
// ../../node_modules/commander/esm.mjs
|
|
32310
32340
|
var import__ = __toESM(require_commander(), 1);
|
|
32311
32341
|
var {
|
|
@@ -32324,7 +32354,7 @@ var {
|
|
|
32324
32354
|
// package.json
|
|
32325
32355
|
var package_default = {
|
|
32326
32356
|
name: "@secondlayer/cli",
|
|
32327
|
-
version: "
|
|
32357
|
+
version: "7.0.0",
|
|
32328
32358
|
repository: {
|
|
32329
32359
|
type: "git",
|
|
32330
32360
|
url: "git+https://github.com/ryanwaits/secondlayer.git",
|
|
@@ -32402,7 +32432,7 @@ var package_default = {
|
|
|
32402
32432
|
import { ApiError, SecondLayer } from "@secondlayer/sdk";
|
|
32403
32433
|
|
|
32404
32434
|
// src/lib/http.ts
|
|
32405
|
-
|
|
32435
|
+
init_resolve_auth();
|
|
32406
32436
|
|
|
32407
32437
|
class CliHttpError extends Error {
|
|
32408
32438
|
status;
|
|
@@ -32416,7 +32446,6 @@ class CliHttpError extends Error {
|
|
|
32416
32446
|
this.body = body;
|
|
32417
32447
|
}
|
|
32418
32448
|
}
|
|
32419
|
-
var PLATFORM_API_URL = process.env.SL_PLATFORM_API_URL ?? "https://api.secondlayer.tools";
|
|
32420
32449
|
var REQUEST_TIMEOUT_MS = 30000;
|
|
32421
32450
|
async function request(url, opts) {
|
|
32422
32451
|
const headers = {
|
|
@@ -32447,33 +32476,49 @@ async function request(url, opts) {
|
|
|
32447
32476
|
return await res.json();
|
|
32448
32477
|
}
|
|
32449
32478
|
async function httpPlatform(path2, opts = {}) {
|
|
32450
|
-
|
|
32451
|
-
|
|
32479
|
+
let auth;
|
|
32480
|
+
try {
|
|
32481
|
+
auth = await resolveAuth();
|
|
32482
|
+
} catch {
|
|
32452
32483
|
throw new CliHttpError(401, "SESSION_EXPIRED", { error: "Not logged in" }, "Not logged in — run `sl login`");
|
|
32453
32484
|
}
|
|
32454
|
-
return request(`${
|
|
32485
|
+
return request(`${auth.apiUrl}${path2}`, {
|
|
32455
32486
|
...opts,
|
|
32456
|
-
bearer:
|
|
32487
|
+
bearer: auth.ephemeralKey
|
|
32457
32488
|
});
|
|
32458
32489
|
}
|
|
32459
32490
|
async function httpPlatformAnon(path2, opts = {}) {
|
|
32460
|
-
return request(`${
|
|
32491
|
+
return request(`${resolveApiUrl()}${path2}`, opts);
|
|
32461
32492
|
}
|
|
32462
32493
|
|
|
32463
32494
|
// src/lib/api-client.ts
|
|
32495
|
+
init_output();
|
|
32464
32496
|
init_resolve_auth();
|
|
32497
|
+
function nextStepHint(status) {
|
|
32498
|
+
if (status === undefined)
|
|
32499
|
+
return;
|
|
32500
|
+
if (status === 403)
|
|
32501
|
+
return "You may not have access — check your active project with `sl whoami`.";
|
|
32502
|
+
if (status === 404)
|
|
32503
|
+
return "Check the name/slug — run the matching `list` command to see what exists.";
|
|
32504
|
+
if (status === 400 || status === 422)
|
|
32505
|
+
return "Check the command arguments and flags — see `--help` for the expected format.";
|
|
32506
|
+
if (status === 429)
|
|
32507
|
+
return "Rate limited — wait a moment and retry.";
|
|
32508
|
+
if (status >= 500)
|
|
32509
|
+
return "Server error — retry shortly, or check `sl status`.";
|
|
32510
|
+
return;
|
|
32511
|
+
}
|
|
32465
32512
|
function handleApiError(err, action) {
|
|
32466
|
-
|
|
32467
|
-
|
|
32468
|
-
|
|
32469
|
-
|
|
32470
|
-
}
|
|
32471
|
-
}
|
|
32472
|
-
if (err instanceof ApiError && err.status === 401) {
|
|
32473
|
-
console.error("Authentication required. Run: sl login");
|
|
32513
|
+
const status = err instanceof ApiError || err instanceof CliHttpError ? err.status : undefined;
|
|
32514
|
+
if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED" || status === 401) {
|
|
32515
|
+
printError("Authentication required.", {
|
|
32516
|
+
hint: "Run `sl login` to re-authenticate."
|
|
32517
|
+
});
|
|
32474
32518
|
process.exit(1);
|
|
32475
32519
|
}
|
|
32476
|
-
|
|
32520
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
32521
|
+
printError(`Failed to ${action}: ${detail}`, { hint: nextStepHint(status) });
|
|
32477
32522
|
process.exit(1);
|
|
32478
32523
|
}
|
|
32479
32524
|
function withErrorHandling(fn, options) {
|
|
@@ -32541,105 +32586,116 @@ async function updateAccountProfile(data) {
|
|
|
32541
32586
|
|
|
32542
32587
|
// src/commands/account.ts
|
|
32543
32588
|
init_output();
|
|
32544
|
-
|
|
32545
|
-
|
|
32546
|
-
|
|
32547
|
-
|
|
32548
|
-
|
|
32549
|
-
|
|
32550
|
-
|
|
32551
|
-
|
|
32552
|
-
|
|
32553
|
-
|
|
32554
|
-
|
|
32555
|
-
data.slug = options.slug;
|
|
32556
|
-
const updated = await updateAccountProfile(data);
|
|
32557
|
-
if (options.json) {
|
|
32558
|
-
console.log(JSON.stringify(updated, null, 2));
|
|
32559
|
-
return;
|
|
32560
|
-
}
|
|
32561
|
-
success("Profile updated");
|
|
32562
|
-
console.log(formatKeyValue([
|
|
32563
|
-
["Display Name", updated.displayName ?? dim("—")],
|
|
32564
|
-
["Bio", updated.bio ?? dim("—")],
|
|
32565
|
-
["Slug", updated.slug ?? dim("—")]
|
|
32566
|
-
]));
|
|
32567
|
-
return;
|
|
32568
|
-
}
|
|
32569
|
-
const profile = await getAccountProfile();
|
|
32570
|
-
if (options.json) {
|
|
32571
|
-
console.log(JSON.stringify(profile, null, 2));
|
|
32572
|
-
return;
|
|
32589
|
+
|
|
32590
|
+
// src/commands/billing.ts
|
|
32591
|
+
init_output();
|
|
32592
|
+
async function runBillingStatus(json) {
|
|
32593
|
+
let res;
|
|
32594
|
+
try {
|
|
32595
|
+
res = await httpPlatform("/api/billing/status");
|
|
32596
|
+
} catch (err) {
|
|
32597
|
+
if (err instanceof CliHttpError) {
|
|
32598
|
+
error(err.message);
|
|
32599
|
+
process.exit(1);
|
|
32573
32600
|
}
|
|
32601
|
+
throw err;
|
|
32602
|
+
}
|
|
32603
|
+
output({ json, data: res, human: () => renderBillingStatus(res) });
|
|
32604
|
+
}
|
|
32605
|
+
function addBillingCommand(parent) {
|
|
32606
|
+
parent.command("billing").description("Show your plan, Stripe subscription, trial, and discounts").option("--json", "Output as JSON").action((options) => runBillingStatus(options.json));
|
|
32607
|
+
}
|
|
32608
|
+
function renderBillingStatus(res) {
|
|
32609
|
+
if (!res.subscription) {
|
|
32574
32610
|
console.log(formatKeyValue([
|
|
32611
|
+
["Plan", "Free during open beta"],
|
|
32612
|
+
["Cost", dim("$0 — no limits, no charges")],
|
|
32613
|
+
["Paid plans", dim("coming after beta")]
|
|
32614
|
+
]));
|
|
32615
|
+
return;
|
|
32616
|
+
}
|
|
32617
|
+
const rows = [];
|
|
32618
|
+
rows.push(["Plan", res.plan]);
|
|
32619
|
+
rows.push([
|
|
32620
|
+
"Customer",
|
|
32621
|
+
res.stripeCustomerId ?? dim("(none — no subscription yet)")
|
|
32622
|
+
]);
|
|
32623
|
+
const sub = res.subscription;
|
|
32624
|
+
rows.push(["Subscription", `${sub.id} (${sub.status})`]);
|
|
32625
|
+
if (sub.tier)
|
|
32626
|
+
rows.push(["Tier", sub.tier]);
|
|
32627
|
+
if (sub.amountCents !== null && sub.interval) {
|
|
32628
|
+
const dollars = (sub.amountCents / 100).toFixed(2);
|
|
32629
|
+
rows.push(["Price", `$${dollars} / ${sub.interval}`]);
|
|
32630
|
+
}
|
|
32631
|
+
if (sub.trialEnd) {
|
|
32632
|
+
const days = Math.max(0, Math.round((new Date(sub.trialEnd).getTime() - Date.now()) / 86400000));
|
|
32633
|
+
rows.push([
|
|
32634
|
+
"Trial ends",
|
|
32635
|
+
`${formatDate(sub.trialEnd)} (${days}d remaining)`
|
|
32636
|
+
]);
|
|
32637
|
+
}
|
|
32638
|
+
if (sub.currentPeriodEnd) {
|
|
32639
|
+
rows.push(["Renews", formatDate(sub.currentPeriodEnd)]);
|
|
32640
|
+
}
|
|
32641
|
+
if (sub.cancelAtPeriodEnd) {
|
|
32642
|
+
rows.push(["Cancels at period end", "yes"]);
|
|
32643
|
+
}
|
|
32644
|
+
if (sub.discount) {
|
|
32645
|
+
const off = sub.discount.percentOff !== null ? `${sub.discount.percentOff}% off` : sub.discount.amountOff !== null ? `$${(sub.discount.amountOff / 100).toFixed(2)} off` : "discount";
|
|
32646
|
+
const label = sub.discount.code ? `${sub.discount.code} (${sub.discount.name ?? "coupon"})` : sub.discount.name ?? "applied";
|
|
32647
|
+
rows.push(["Discount", `${label} — ${off}, ${sub.discount.duration}`]);
|
|
32648
|
+
}
|
|
32649
|
+
console.log(formatKeyValue(rows));
|
|
32650
|
+
}
|
|
32651
|
+
function formatDate(iso) {
|
|
32652
|
+
return new Date(iso).toISOString().slice(0, 10);
|
|
32653
|
+
}
|
|
32654
|
+
|
|
32655
|
+
// src/commands/account.ts
|
|
32656
|
+
async function showProfile(json) {
|
|
32657
|
+
const profile = await getAccountProfile();
|
|
32658
|
+
output({
|
|
32659
|
+
json,
|
|
32660
|
+
data: profile,
|
|
32661
|
+
human: () => console.log(formatKeyValue([
|
|
32575
32662
|
["Email", profile.email],
|
|
32576
32663
|
["Plan", profile.plan],
|
|
32577
32664
|
["Display Name", profile.displayName ?? dim("—")],
|
|
32578
32665
|
["Bio", profile.bio ?? dim("—")],
|
|
32579
32666
|
["Slug", profile.slug ?? dim("—")]
|
|
32580
|
-
]))
|
|
32581
|
-
}
|
|
32667
|
+
]))
|
|
32668
|
+
});
|
|
32582
32669
|
}
|
|
32583
|
-
|
|
32584
|
-
|
|
32585
|
-
|
|
32586
|
-
|
|
32587
|
-
|
|
32588
|
-
|
|
32589
|
-
|
|
32590
|
-
|
|
32591
|
-
|
|
32592
|
-
|
|
32593
|
-
|
|
32594
|
-
|
|
32595
|
-
|
|
32596
|
-
|
|
32597
|
-
}
|
|
32598
|
-
if (!res.subscription) {
|
|
32670
|
+
async function applyProfileUpdate(options) {
|
|
32671
|
+
const data = {};
|
|
32672
|
+
if (options.name)
|
|
32673
|
+
data.display_name = options.name;
|
|
32674
|
+
if (options.bio)
|
|
32675
|
+
data.bio = options.bio;
|
|
32676
|
+
if (options.slug)
|
|
32677
|
+
data.slug = options.slug;
|
|
32678
|
+
const updated = await updateAccountProfile(data);
|
|
32679
|
+
output({
|
|
32680
|
+
json: options.json,
|
|
32681
|
+
data: updated,
|
|
32682
|
+
human: () => {
|
|
32683
|
+
success("Profile updated");
|
|
32599
32684
|
console.log(formatKeyValue([
|
|
32600
|
-
["
|
|
32601
|
-
["
|
|
32602
|
-
["
|
|
32685
|
+
["Display Name", updated.displayName ?? dim("—")],
|
|
32686
|
+
["Bio", updated.bio ?? dim("—")],
|
|
32687
|
+
["Slug", updated.slug ?? dim("—")]
|
|
32603
32688
|
]));
|
|
32604
|
-
return;
|
|
32605
|
-
}
|
|
32606
|
-
const rows = [];
|
|
32607
|
-
rows.push(["Plan", res.plan]);
|
|
32608
|
-
rows.push([
|
|
32609
|
-
"Customer",
|
|
32610
|
-
res.stripeCustomerId ?? dim("(none — no subscription yet)")
|
|
32611
|
-
]);
|
|
32612
|
-
const sub = res.subscription;
|
|
32613
|
-
rows.push(["Subscription", `${sub.id} (${sub.status})`]);
|
|
32614
|
-
if (sub.tier)
|
|
32615
|
-
rows.push(["Tier", sub.tier]);
|
|
32616
|
-
if (sub.amountCents !== null && sub.interval) {
|
|
32617
|
-
const dollars = (sub.amountCents / 100).toFixed(2);
|
|
32618
|
-
rows.push(["Price", `$${dollars} / ${sub.interval}`]);
|
|
32619
|
-
}
|
|
32620
|
-
if (sub.trialEnd) {
|
|
32621
|
-
const days = Math.max(0, Math.round((new Date(sub.trialEnd).getTime() - Date.now()) / 86400000));
|
|
32622
|
-
rows.push([
|
|
32623
|
-
"Trial ends",
|
|
32624
|
-
`${formatDate(sub.trialEnd)} (${days}d remaining)`
|
|
32625
|
-
]);
|
|
32626
32689
|
}
|
|
32627
|
-
if (sub.currentPeriodEnd) {
|
|
32628
|
-
rows.push(["Renews", formatDate(sub.currentPeriodEnd)]);
|
|
32629
|
-
}
|
|
32630
|
-
if (sub.cancelAtPeriodEnd) {
|
|
32631
|
-
rows.push(["Cancels at period end", "yes"]);
|
|
32632
|
-
}
|
|
32633
|
-
if (sub.discount) {
|
|
32634
|
-
const off = sub.discount.percentOff !== null ? `${sub.discount.percentOff}% off` : sub.discount.amountOff !== null ? `$${(sub.discount.amountOff / 100).toFixed(2)} off` : "discount";
|
|
32635
|
-
const label = sub.discount.code ? `${sub.discount.code} (${sub.discount.name ?? "coupon"})` : sub.discount.name ?? "applied";
|
|
32636
|
-
rows.push(["Discount", `${label} — ${off}, ${sub.discount.duration}`]);
|
|
32637
|
-
}
|
|
32638
|
-
console.log(formatKeyValue(rows));
|
|
32639
32690
|
});
|
|
32640
32691
|
}
|
|
32641
|
-
function
|
|
32642
|
-
|
|
32692
|
+
function registerAccountCommand(program2) {
|
|
32693
|
+
const account = program2.command("account").description("Manage your account profile");
|
|
32694
|
+
addBillingCommand(account);
|
|
32695
|
+
account.command("get").description("Show your account profile").option("--json", "Output as JSON").action(withErrorHandling(async (options) => showProfile(options.json), { action: "show profile" }));
|
|
32696
|
+
account.command("update").description("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) => applyProfileUpdate(options), {
|
|
32697
|
+
action: "update profile"
|
|
32698
|
+
}));
|
|
32643
32699
|
}
|
|
32644
32700
|
// src/commands/config.ts
|
|
32645
32701
|
init_config();
|
|
@@ -32885,10 +32941,14 @@ async function detectStacksNodes() {
|
|
|
32885
32941
|
init_output();
|
|
32886
32942
|
function registerConfigCommand(program2) {
|
|
32887
32943
|
const config = program2.command("config").description("Manage CLI configuration");
|
|
32888
|
-
config.command("
|
|
32944
|
+
config.command("get").description("Show current configuration").option("--json", "Output as JSON").action(async (options) => {
|
|
32889
32945
|
try {
|
|
32890
32946
|
const cfg = await loadConfig();
|
|
32891
|
-
|
|
32947
|
+
if (options.json) {
|
|
32948
|
+
writeData(JSON.stringify(cfg, null, 2));
|
|
32949
|
+
return;
|
|
32950
|
+
}
|
|
32951
|
+
note(`Config file: ${getConfigPath()}`);
|
|
32892
32952
|
console.log("");
|
|
32893
32953
|
await printConfigTree(cfg);
|
|
32894
32954
|
} catch (err) {
|
|
@@ -32896,7 +32956,11 @@ function registerConfigCommand(program2) {
|
|
|
32896
32956
|
process.exit(1);
|
|
32897
32957
|
}
|
|
32898
32958
|
});
|
|
32899
|
-
config.command("set <key> <value>").description("Set a configuration value (supports dot notation: ports.api)").option("--no-validate", "Skip connection validation for database/redis URLs").
|
|
32959
|
+
config.command("set <key> <value>").description("Set a configuration value (supports dot notation: ports.api)").option("--no-validate", "Skip connection validation for database/redis URLs").addHelpText("after", `
|
|
32960
|
+
Examples:
|
|
32961
|
+
$ sl config set network local
|
|
32962
|
+
$ sl config set ports.api 3800
|
|
32963
|
+
$ sl config set database.url postgres://localhost:5432/secondlayer_dev`).action(async (key, value, options) => {
|
|
32900
32964
|
try {
|
|
32901
32965
|
await setConfigValue(key, value);
|
|
32902
32966
|
success(`Set ${key} = ${value}`);
|
|
@@ -32926,7 +32990,7 @@ function registerConfigCommand(program2) {
|
|
|
32926
32990
|
process.exit(1);
|
|
32927
32991
|
}
|
|
32928
32992
|
});
|
|
32929
|
-
config.command("
|
|
32993
|
+
config.command("delete").description("Delete all configuration (remove the config file)").option("-y, --yes", "Skip confirmation").action(async (opts) => {
|
|
32930
32994
|
try {
|
|
32931
32995
|
if (!opts.yes && !await confirmDestructive("Delete the config file?")) {
|
|
32932
32996
|
return;
|
|
@@ -33031,20 +33095,97 @@ async function validateDatabaseConnection(url) {
|
|
|
33031
33095
|
console.log(dim("The URL was saved but connection failed. Check your database settings."));
|
|
33032
33096
|
}
|
|
33033
33097
|
}
|
|
33034
|
-
// src/commands/
|
|
33035
|
-
|
|
33036
|
-
|
|
33037
|
-
|
|
33038
|
-
|
|
33039
|
-
|
|
33040
|
-
|
|
33041
|
-
|
|
33042
|
-
|
|
33043
|
-
|
|
33044
|
-
|
|
33045
|
-
|
|
33046
|
-
|
|
33047
|
-
|
|
33098
|
+
// src/commands/status.ts
|
|
33099
|
+
init_config();
|
|
33100
|
+
init_output();
|
|
33101
|
+
function registerStatusCommand(program2) {
|
|
33102
|
+
program2.command("status").description("Show system status").option("--json", "Output as JSON").action(async (options) => {
|
|
33103
|
+
const config = await loadConfig();
|
|
33104
|
+
try {
|
|
33105
|
+
const status = await httpPlatform("/status");
|
|
33106
|
+
output({
|
|
33107
|
+
json: options.json,
|
|
33108
|
+
data: status,
|
|
33109
|
+
human: () => printStatus(status)
|
|
33110
|
+
});
|
|
33111
|
+
} catch (err) {
|
|
33112
|
+
if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED") {
|
|
33113
|
+
console.error("Not logged in. Run: sl login");
|
|
33114
|
+
process.exit(1);
|
|
33115
|
+
}
|
|
33116
|
+
console.log("");
|
|
33117
|
+
console.log(blue("System Status"));
|
|
33118
|
+
console.log(` ${red("NOT RUNNING")}`);
|
|
33119
|
+
console.log("");
|
|
33120
|
+
if (config.network === "local") {
|
|
33121
|
+
console.log(dim(" API service is not running."));
|
|
33122
|
+
console.log(dim(" Start with: sl local start"));
|
|
33123
|
+
} else {
|
|
33124
|
+
console.log(dim(" Can't reach the platform API."));
|
|
33125
|
+
console.log(dim(" Check your connection or try again."));
|
|
33126
|
+
}
|
|
33127
|
+
console.log("");
|
|
33128
|
+
process.exit(1);
|
|
33129
|
+
}
|
|
33130
|
+
});
|
|
33131
|
+
}
|
|
33132
|
+
function printStatus(status) {
|
|
33133
|
+
console.log("");
|
|
33134
|
+
const statusColor = status.status === "healthy" ? green : red;
|
|
33135
|
+
console.log(blue("System Status"));
|
|
33136
|
+
console.log(` ${statusColor(status.status.toUpperCase())}${status.network ? dim(` (${status.network})`) : ""}`);
|
|
33137
|
+
console.log("");
|
|
33138
|
+
console.log(blue("Database"));
|
|
33139
|
+
const dbColor = status.database.status === "ok" ? green : red;
|
|
33140
|
+
console.log(` Status: ${dbColor(status.database.status)}`);
|
|
33141
|
+
console.log("");
|
|
33142
|
+
console.log(blue("Index Progress"));
|
|
33143
|
+
if (status.indexProgress.length === 0) {
|
|
33144
|
+
console.log(dim(" No data indexed yet"));
|
|
33145
|
+
} else {
|
|
33146
|
+
for (const p of status.indexProgress) {
|
|
33147
|
+
const behind = p.highestSeenBlock - p.lastIndexedBlock;
|
|
33148
|
+
const behindStr = behind > 0 ? yellow(` (${behind} behind)`) : green(" (synced)");
|
|
33149
|
+
console.log(` ${p.network}: block ${p.lastIndexedBlock}${behindStr}`);
|
|
33150
|
+
if (status.chainTip && status.chainTip > 0) {
|
|
33151
|
+
const pct = Math.min(p.lastIndexedBlock / status.chainTip * 100, 100);
|
|
33152
|
+
const barWidth = 30;
|
|
33153
|
+
const filled = Math.round(pct / 100 * barWidth);
|
|
33154
|
+
const empty = barWidth - filled;
|
|
33155
|
+
const bar = `${"█".repeat(filled)}${"░".repeat(empty)}`;
|
|
33156
|
+
const pctStr = `${pct.toFixed(1)}%`;
|
|
33157
|
+
const color = pct >= 99.9 ? green : pct >= 50 ? yellow : red;
|
|
33158
|
+
console.log(` ${dim("chain:")} ${color(bar)} ${color(pctStr)} ${dim(`(tip: ${status.chainTip.toLocaleString()})`)}`);
|
|
33159
|
+
}
|
|
33160
|
+
const contiguous = p.lastContiguousBlock ?? 0;
|
|
33161
|
+
if (status.integrity === "complete") {
|
|
33162
|
+
console.log(` ${dim("contiguous:")} ${contiguous} ${green("(complete)")}`);
|
|
33163
|
+
} else {
|
|
33164
|
+
const gapCount = status.gaps?.length ?? 0;
|
|
33165
|
+
const missing = status.totalMissingBlocks ?? 0;
|
|
33166
|
+
console.log(` ${dim("contiguous:")} ${contiguous} ${yellow(`(${gapCount} gaps, ${missing} missing blocks)`)}`);
|
|
33167
|
+
if (status.gaps) {
|
|
33168
|
+
for (const gap of status.gaps.slice(0, 5)) {
|
|
33169
|
+
const range = gap.gapStart === gap.gapEnd ? `${gap.gapStart}` : `${gap.gapStart}-${gap.gapEnd}`;
|
|
33170
|
+
console.log(` ${dim("gap:")} ${range} ${dim(`(${gap.size} block${gap.size > 1 ? "s" : ""})`)}`);
|
|
33171
|
+
}
|
|
33172
|
+
}
|
|
33173
|
+
}
|
|
33174
|
+
}
|
|
33175
|
+
}
|
|
33176
|
+
console.log("");
|
|
33177
|
+
if (status.activeSubgraphs !== undefined) {
|
|
33178
|
+
console.log(blue("Activity"));
|
|
33179
|
+
console.log(formatKeyValue([
|
|
33180
|
+
[" Active Subgraphs", status.activeSubgraphs.toString()]
|
|
33181
|
+
]));
|
|
33182
|
+
console.log("");
|
|
33183
|
+
}
|
|
33184
|
+
console.log(dim(`Last updated: ${status.timestamp}`));
|
|
33185
|
+
}
|
|
33186
|
+
// src/commands/subscriptions.ts
|
|
33187
|
+
import { confirm } from "@inquirer/prompts";
|
|
33188
|
+
import { sign } from "@secondlayer/shared/crypto/standard-webhooks";
|
|
33048
33189
|
|
|
33049
33190
|
// src/lib/filter-params.ts
|
|
33050
33191
|
var FILTER_OPERATORS = ["eq", "neq", "gt", "gte", "lt", "lte"];
|
|
@@ -33112,9 +33253,8 @@ function parseSubscriptionFilter(args) {
|
|
|
33112
33253
|
return Object.keys(filters).length > 0 ? filters : undefined;
|
|
33113
33254
|
}
|
|
33114
33255
|
|
|
33115
|
-
// src/commands/
|
|
33256
|
+
// src/commands/subscriptions.ts
|
|
33116
33257
|
init_output();
|
|
33117
|
-
init_resolve_auth();
|
|
33118
33258
|
|
|
33119
33259
|
// src/lib/subscription-validation.ts
|
|
33120
33260
|
import {
|
|
@@ -33134,6 +33274,23 @@ async function validateSubscriptionTargetFromApi(client, input) {
|
|
|
33134
33274
|
}
|
|
33135
33275
|
}
|
|
33136
33276
|
|
|
33277
|
+
// src/commands/create.ts
|
|
33278
|
+
import {
|
|
33279
|
+
copyFileSync,
|
|
33280
|
+
existsSync,
|
|
33281
|
+
mkdirSync,
|
|
33282
|
+
readFileSync,
|
|
33283
|
+
readdirSync,
|
|
33284
|
+
statSync,
|
|
33285
|
+
writeFileSync
|
|
33286
|
+
} from "node:fs";
|
|
33287
|
+
import { dirname as dirname2, join as join4, relative, resolve } from "node:path";
|
|
33288
|
+
import { fileURLToPath } from "node:url";
|
|
33289
|
+
import { input, select as select2 } from "@inquirer/prompts";
|
|
33290
|
+
import { SecondLayer as SecondLayer2 } from "@secondlayer/sdk";
|
|
33291
|
+
init_output();
|
|
33292
|
+
init_resolve_auth();
|
|
33293
|
+
|
|
33137
33294
|
// src/utils/urls.ts
|
|
33138
33295
|
function deriveBaseUrl(apiUrl) {
|
|
33139
33296
|
const override = process.env.SL_DASHBOARD_URL?.trim();
|
|
@@ -33364,104 +33521,22 @@ async function getSubscriptionClient(opts) {
|
|
|
33364
33521
|
apiKey: resolvedConfig.apiKey
|
|
33365
33522
|
});
|
|
33366
33523
|
}
|
|
33367
|
-
function
|
|
33368
|
-
|
|
33369
|
-
|
|
33524
|
+
function addSubscriptionScaffold(parent, commandSpec, opts) {
|
|
33525
|
+
parent.command(commandSpec).description(opts.description).option("-r, --runtime <runtime>", "inngest | trigger | cloudflare | node").option("-s, --subgraph <name>", "Subgraph to subscribe to").option("-t, --table <name>", "Table to subscribe to").option("-u, --url <url>", "Webhook URL").option("--auth-token <token>", "Bearer token for receiver API auth").option("--filter <kv...>", "Filter as key=value (supports .eq/.neq/.gt/.gte/.lt/.lte suffixes)").option("--service-key <key>", "SL_SERVICE_KEY override").option("--base-url <url>", "SL_API_URL override").option("--skip-api", "Copy template only, don't call the API").option("--no-scaffold", "Skip the local runtime template directory (webhook-only setups)").addHelpText("after", `
|
|
33526
|
+
Examples:
|
|
33527
|
+
$ ${opts.examplePrefix} my-sub -s my-graph -t transfers -u https://example.com/webhook
|
|
33528
|
+
$ ${opts.examplePrefix} my-sub -s my-graph -t balances -r inngest --filter amount.gte=1000`).action(async (name, options) => {
|
|
33370
33529
|
await createSubscription(name, options);
|
|
33371
33530
|
});
|
|
33372
33531
|
}
|
|
33373
|
-
|
|
33374
|
-
|
|
33375
|
-
|
|
33376
|
-
|
|
33377
|
-
program2.command("status").description("Show system status").option("--json", "Output as JSON").action(async (options) => {
|
|
33378
|
-
const config = await loadConfig();
|
|
33379
|
-
try {
|
|
33380
|
-
const status = await httpPlatform("/status");
|
|
33381
|
-
if (options.json) {
|
|
33382
|
-
console.log(JSON.stringify(status, null, 2));
|
|
33383
|
-
return;
|
|
33384
|
-
}
|
|
33385
|
-
printStatus(status);
|
|
33386
|
-
} catch (err) {
|
|
33387
|
-
if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED") {
|
|
33388
|
-
console.error("Not logged in. Run: sl login");
|
|
33389
|
-
process.exit(1);
|
|
33390
|
-
}
|
|
33391
|
-
console.log("");
|
|
33392
|
-
console.log(blue("System Status"));
|
|
33393
|
-
console.log(` ${red("NOT RUNNING")}`);
|
|
33394
|
-
console.log("");
|
|
33395
|
-
if (config.network === "local") {
|
|
33396
|
-
console.log(dim(" API service is not running."));
|
|
33397
|
-
console.log(dim(" Start with: sl local start"));
|
|
33398
|
-
} else {
|
|
33399
|
-
console.log(dim(" Can't reach the platform API."));
|
|
33400
|
-
console.log(dim(" Check your connection or try again."));
|
|
33401
|
-
}
|
|
33402
|
-
console.log("");
|
|
33403
|
-
process.exit(1);
|
|
33404
|
-
}
|
|
33532
|
+
function addSubscriptionsCreateCommand(subscriptions) {
|
|
33533
|
+
addSubscriptionScaffold(subscriptions, "create <name>", {
|
|
33534
|
+
description: "Create a subscription receiver for a runtime",
|
|
33535
|
+
examplePrefix: "sl subscriptions create"
|
|
33405
33536
|
});
|
|
33406
33537
|
}
|
|
33407
|
-
|
|
33408
|
-
console.log("");
|
|
33409
|
-
const statusColor = status.status === "healthy" ? green : red;
|
|
33410
|
-
console.log(blue("System Status"));
|
|
33411
|
-
console.log(` ${statusColor(status.status.toUpperCase())}${status.network ? dim(` (${status.network})`) : ""}`);
|
|
33412
|
-
console.log("");
|
|
33413
|
-
console.log(blue("Database"));
|
|
33414
|
-
const dbColor = status.database.status === "ok" ? green : red;
|
|
33415
|
-
console.log(` Status: ${dbColor(status.database.status)}`);
|
|
33416
|
-
console.log("");
|
|
33417
|
-
console.log(blue("Index Progress"));
|
|
33418
|
-
if (status.indexProgress.length === 0) {
|
|
33419
|
-
console.log(dim(" No data indexed yet"));
|
|
33420
|
-
} else {
|
|
33421
|
-
for (const p of status.indexProgress) {
|
|
33422
|
-
const behind = p.highestSeenBlock - p.lastIndexedBlock;
|
|
33423
|
-
const behindStr = behind > 0 ? yellow(` (${behind} behind)`) : green(" (synced)");
|
|
33424
|
-
console.log(` ${p.network}: block ${p.lastIndexedBlock}${behindStr}`);
|
|
33425
|
-
if (status.chainTip && status.chainTip > 0) {
|
|
33426
|
-
const pct = Math.min(p.lastIndexedBlock / status.chainTip * 100, 100);
|
|
33427
|
-
const barWidth = 30;
|
|
33428
|
-
const filled = Math.round(pct / 100 * barWidth);
|
|
33429
|
-
const empty = barWidth - filled;
|
|
33430
|
-
const bar = `${"█".repeat(filled)}${"░".repeat(empty)}`;
|
|
33431
|
-
const pctStr = `${pct.toFixed(1)}%`;
|
|
33432
|
-
const color = pct >= 99.9 ? green : pct >= 50 ? yellow : red;
|
|
33433
|
-
console.log(` ${dim("chain:")} ${color(bar)} ${color(pctStr)} ${dim(`(tip: ${status.chainTip.toLocaleString()})`)}`);
|
|
33434
|
-
}
|
|
33435
|
-
const contiguous = p.lastContiguousBlock ?? 0;
|
|
33436
|
-
if (status.integrity === "complete") {
|
|
33437
|
-
console.log(` ${dim("contiguous:")} ${contiguous} ${green("(complete)")}`);
|
|
33438
|
-
} else {
|
|
33439
|
-
const gapCount = status.gaps?.length ?? 0;
|
|
33440
|
-
const missing = status.totalMissingBlocks ?? 0;
|
|
33441
|
-
console.log(` ${dim("contiguous:")} ${contiguous} ${yellow(`(${gapCount} gaps, ${missing} missing blocks)`)}`);
|
|
33442
|
-
if (status.gaps) {
|
|
33443
|
-
for (const gap of status.gaps.slice(0, 5)) {
|
|
33444
|
-
const range = gap.gapStart === gap.gapEnd ? `${gap.gapStart}` : `${gap.gapStart}-${gap.gapEnd}`;
|
|
33445
|
-
console.log(` ${dim("gap:")} ${range} ${dim(`(${gap.size} block${gap.size > 1 ? "s" : ""})`)}`);
|
|
33446
|
-
}
|
|
33447
|
-
}
|
|
33448
|
-
}
|
|
33449
|
-
}
|
|
33450
|
-
}
|
|
33451
|
-
console.log("");
|
|
33452
|
-
if (status.activeSubgraphs !== undefined) {
|
|
33453
|
-
console.log(blue("Activity"));
|
|
33454
|
-
console.log(formatKeyValue([
|
|
33455
|
-
[" Active Subgraphs", status.activeSubgraphs.toString()]
|
|
33456
|
-
]));
|
|
33457
|
-
console.log("");
|
|
33458
|
-
}
|
|
33459
|
-
console.log(dim(`Last updated: ${status.timestamp}`));
|
|
33460
|
-
}
|
|
33538
|
+
|
|
33461
33539
|
// src/commands/subscriptions.ts
|
|
33462
|
-
import { confirm } from "@inquirer/prompts";
|
|
33463
|
-
import { sign } from "@secondlayer/shared/crypto/standard-webhooks";
|
|
33464
|
-
init_output();
|
|
33465
33540
|
function commonOptions(cmd) {
|
|
33466
33541
|
return cmd.option("--service-key <key>", "SL_SERVICE_KEY override").option("--base-url <url>", "SL_API_URL override");
|
|
33467
33542
|
}
|
|
@@ -33818,6 +33893,7 @@ async function confirmOrExit(message, yes) {
|
|
|
33818
33893
|
}
|
|
33819
33894
|
function registerSubscriptionsCommand(program2) {
|
|
33820
33895
|
const subscriptions = commonOptions(program2.command("subscriptions").alias("subs").description("Manage subgraph table subscriptions"));
|
|
33896
|
+
addSubscriptionsCreateCommand(subscriptions);
|
|
33821
33897
|
commonOptions(subscriptions.command("list").alias("ls").description("List subscriptions").option("--json", "Output as JSON")).action(async (options) => {
|
|
33822
33898
|
try {
|
|
33823
33899
|
const client = await getSubscriptionClient(options);
|
|
@@ -33856,7 +33932,11 @@ ${data.length} subscription(s) total`));
|
|
|
33856
33932
|
handleApiError(err, "get subscription");
|
|
33857
33933
|
}
|
|
33858
33934
|
});
|
|
33859
|
-
commonOptions(subscriptions.command("update <idOrName>").description("Update subscription config").option("--name <name>", "Rename subscription").option("--url <url>", "Webhook URL").option("--auth-token <token>", "Set bearer token auth config").option("--format <format>", "standard-webhooks | inngest | trigger | cloudflare | cloudevents | raw").option("--runtime <runtime>", "inngest | trigger | cloudflare | node | none").option("--filter <kv...>", "Filter as key=value (supports .eq/.neq/.gt/.gte/.lt/.lte suffixes)").option("--clear-filter", "Replace filter with {}").option("--max-retries <n>", "Maximum delivery retries").option("--timeout-ms <n>", "Delivery timeout in milliseconds").option("--concurrency <n>", "Per-subscription delivery concurrency").option("--json", "Output as JSON")
|
|
33935
|
+
commonOptions(subscriptions.command("update <idOrName>").description("Update subscription config").option("--name <name>", "Rename subscription").option("--url <url>", "Webhook URL").option("--auth-token <token>", "Set bearer token auth config").option("--format <format>", "standard-webhooks | inngest | trigger | cloudflare | cloudevents | raw").option("--runtime <runtime>", "inngest | trigger | cloudflare | node | none").option("--filter <kv...>", "Filter as key=value (supports .eq/.neq/.gt/.gte/.lt/.lte suffixes)").option("--clear-filter", "Replace filter with {}").option("--max-retries <n>", "Maximum delivery retries").option("--timeout-ms <n>", "Delivery timeout in milliseconds").option("--concurrency <n>", "Per-subscription delivery concurrency").option("--json", "Output as JSON").addHelpText("after", `
|
|
33936
|
+
Examples:
|
|
33937
|
+
$ sl subscriptions update my-sub --url https://example.com/hook
|
|
33938
|
+
$ sl subscriptions update my-sub --filter amount.gte=1000 --max-retries 5
|
|
33939
|
+
$ sl subscriptions update my-sub --clear-filter`)).action(async (idOrName, options) => {
|
|
33860
33940
|
try {
|
|
33861
33941
|
const client = await getSubscriptionClient(options);
|
|
33862
33942
|
const patch = buildUpdatePatch(options);
|
|
@@ -33892,7 +33972,7 @@ ${data.length} subscription(s) total`));
|
|
|
33892
33972
|
}
|
|
33893
33973
|
});
|
|
33894
33974
|
}
|
|
33895
|
-
commonOptions(subscriptions.command("delete <idOrName>").description("Delete a subscription").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON")).action(async (idOrName, options) => {
|
|
33975
|
+
commonOptions(subscriptions.command("delete <idOrName>").alias("rm").description("Delete a subscription").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON")).action(async (idOrName, options) => {
|
|
33896
33976
|
try {
|
|
33897
33977
|
const client = await getSubscriptionClient(options);
|
|
33898
33978
|
let resolved = null;
|
|
@@ -33983,7 +34063,9 @@ ${data.length} subscription(s) total`));
|
|
|
33983
34063
|
handleApiError(err, "requeue dead-letter row");
|
|
33984
34064
|
}
|
|
33985
34065
|
});
|
|
33986
|
-
commonOptions(subscriptions.command("replay <idOrName>").description("Replay a block range").requiredOption("--from-block <n>", "Start block height").requiredOption("--to-block <n>", "End block height").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON")
|
|
34066
|
+
commonOptions(subscriptions.command("replay <idOrName>").description("Replay a block range").requiredOption("--from-block <n>", "Start block height").requiredOption("--to-block <n>", "End block height").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON").addHelpText("after", `
|
|
34067
|
+
Examples:
|
|
34068
|
+
$ sl subscriptions replay my-sub --from-block 150000 --to-block 160000 -y`)).action(async (idOrName, options) => {
|
|
33987
34069
|
try {
|
|
33988
34070
|
const fromBlock = requireIntegerOption(options.fromBlock, "--from-block");
|
|
33989
34071
|
const toBlock = requireIntegerOption(options.toBlock, "--to-block");
|
|
@@ -34080,363 +34162,10 @@ POST result:`));
|
|
|
34080
34162
|
}
|
|
34081
34163
|
});
|
|
34082
34164
|
}
|
|
34083
|
-
// src/commands/db.ts
|
|
34084
|
-
init_config();
|
|
34085
|
-
init_dev_state();
|
|
34086
|
-
init_output();
|
|
34087
|
-
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
34088
|
-
import { getDb, sql } from "@secondlayer/shared/db";
|
|
34089
|
-
import {
|
|
34090
|
-
countMissingBlocks,
|
|
34091
|
-
findGaps
|
|
34092
|
-
} from "@secondlayer/shared/db/queries/integrity";
|
|
34093
|
-
import { StacksNodeClient } from "@secondlayer/shared/node";
|
|
34094
|
-
var DEV_DATABASE_URL = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
|
|
34095
|
-
function registerDbCommand(program2) {
|
|
34096
|
-
const dbCmd = program2.command("db").description("Inspect indexer database tables").hook("preAction", async () => {
|
|
34097
|
-
await requireLocalNetwork();
|
|
34098
|
-
}).action(async () => {
|
|
34099
|
-
await showOverview(10);
|
|
34100
|
-
});
|
|
34101
|
-
dbCmd.command("blocks").description("Show recent blocks").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
|
|
34102
|
-
const opts = this.opts();
|
|
34103
|
-
await showBlocks(Number.parseInt(opts.limit), opts.json);
|
|
34104
|
-
});
|
|
34105
|
-
dbCmd.command("txs").description("Show recent transactions").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
|
|
34106
|
-
const opts = this.opts();
|
|
34107
|
-
await showTransactions(Number.parseInt(opts.limit), opts.json);
|
|
34108
|
-
});
|
|
34109
|
-
dbCmd.command("events").description("Show recent events").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
|
|
34110
|
-
const opts = this.opts();
|
|
34111
|
-
await showEvents(Number.parseInt(opts.limit), opts.json);
|
|
34112
|
-
});
|
|
34113
|
-
dbCmd.command("gaps").description("Show gaps in indexed block data").option("--limit <n>", "Number of gaps to show", "50").option("--json", "Output as JSON").action(async function() {
|
|
34114
|
-
const opts = this.opts();
|
|
34115
|
-
await showGaps(Number.parseInt(opts.limit), opts.json);
|
|
34116
|
-
});
|
|
34117
|
-
dbCmd.command("reset").description("Truncate all indexed data (blocks, txs, events)").option("-y, --yes", "Skip confirmation prompt").action(async function() {
|
|
34118
|
-
const opts = this.opts();
|
|
34119
|
-
await resetDatabase(opts.yes);
|
|
34120
|
-
});
|
|
34121
|
-
dbCmd.command("resync").description("Reset database and restart indexer for fresh sync").option("-y, --yes", "Skip confirmation prompt").option("--backfill", "After reset, fetch all blocks from node").action(async function() {
|
|
34122
|
-
const opts = this.opts();
|
|
34123
|
-
await resyncDatabase(opts.yes, opts.backfill);
|
|
34124
|
-
});
|
|
34125
|
-
}
|
|
34126
|
-
function ensureDb() {
|
|
34127
|
-
if (!process.env.DATABASE_URL) {
|
|
34128
|
-
process.env.DATABASE_URL = DEV_DATABASE_URL;
|
|
34129
|
-
}
|
|
34130
|
-
return getDb();
|
|
34131
|
-
}
|
|
34132
|
-
async function showOverview(_limit) {
|
|
34133
|
-
try {
|
|
34134
|
-
const db = ensureDb();
|
|
34135
|
-
const blockCountResult = await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst();
|
|
34136
|
-
const txCountResult = await db.selectFrom("transactions").select(sql`count(*)`.as("count")).executeTakeFirst();
|
|
34137
|
-
const eventCountResult = await db.selectFrom("events").select(sql`count(*)`.as("count")).executeTakeFirst();
|
|
34138
|
-
const blockCount = blockCountResult?.count ?? 0;
|
|
34139
|
-
const txCount = txCountResult?.count ?? 0;
|
|
34140
|
-
const eventCount = eventCountResult?.count ?? 0;
|
|
34141
|
-
const latest = await db.selectFrom("blocks").select(["height", "hash", "timestamp"]).orderBy("height", "desc").limit(1).executeTakeFirst();
|
|
34142
|
-
console.log("");
|
|
34143
|
-
console.log(blue("Database Overview"));
|
|
34144
|
-
console.log("");
|
|
34145
|
-
console.log(` Blocks: ${green(blockCount.toString())}`);
|
|
34146
|
-
console.log(` Transactions: ${green(txCount.toString())}`);
|
|
34147
|
-
console.log(` Events: ${green(eventCount.toString())}`);
|
|
34148
|
-
console.log("");
|
|
34149
|
-
if (latest) {
|
|
34150
|
-
const time = new Date(latest.timestamp * 1000).toISOString();
|
|
34151
|
-
console.log(blue("Latest Block"));
|
|
34152
|
-
console.log(` Height: ${latest.height}`);
|
|
34153
|
-
console.log(` Hash: ${dim(latest.hash.slice(0, 20))}...`);
|
|
34154
|
-
console.log(` Time: ${time}`);
|
|
34155
|
-
console.log("");
|
|
34156
|
-
}
|
|
34157
|
-
console.log(dim(`Use 'sl db blocks|txs|events' to see records`));
|
|
34158
|
-
console.log("");
|
|
34159
|
-
process.exit(0);
|
|
34160
|
-
} catch (err) {
|
|
34161
|
-
error(`Failed to query database: ${err}`);
|
|
34162
|
-
console.log(dim(`
|
|
34163
|
-
Make sure PostgreSQL is running.`));
|
|
34164
|
-
console.log(dim("Run 'sl local start' to start all services."));
|
|
34165
|
-
process.exit(1);
|
|
34166
|
-
}
|
|
34167
|
-
}
|
|
34168
|
-
async function showBlocks(limit, json) {
|
|
34169
|
-
try {
|
|
34170
|
-
const db = ensureDb();
|
|
34171
|
-
const rows = await db.selectFrom("blocks").select(["height", "hash", "timestamp", "canonical"]).orderBy("height", "desc").limit(limit).execute();
|
|
34172
|
-
if (json) {
|
|
34173
|
-
console.log(JSON.stringify(rows, null, 2));
|
|
34174
|
-
process.exit(0);
|
|
34175
|
-
}
|
|
34176
|
-
console.log("");
|
|
34177
|
-
console.log(blue(`Recent Blocks (${rows.length})`));
|
|
34178
|
-
console.log("");
|
|
34179
|
-
console.log(dim(" HEIGHT".padEnd(10)) + dim("HASH".padEnd(24)) + dim("TIME"));
|
|
34180
|
-
for (const row of rows) {
|
|
34181
|
-
const time = new Date(row.timestamp * 1000).toLocaleTimeString();
|
|
34182
|
-
const canonicalMark = row.canonical ? "" : yellow(" (reorg)");
|
|
34183
|
-
console.log(` ${row.height.toString().padEnd(10)}${`${row.hash.slice(0, 20)}... `.padEnd(24)}${time}${canonicalMark}`);
|
|
34184
|
-
}
|
|
34185
|
-
console.log("");
|
|
34186
|
-
process.exit(0);
|
|
34187
|
-
} catch (err) {
|
|
34188
|
-
error(`Failed to query blocks: ${err}`);
|
|
34189
|
-
process.exit(1);
|
|
34190
|
-
}
|
|
34191
|
-
}
|
|
34192
|
-
async function showTransactions(limit, json) {
|
|
34193
|
-
try {
|
|
34194
|
-
const db = ensureDb();
|
|
34195
|
-
const rows = await db.selectFrom("transactions").select([
|
|
34196
|
-
"tx_id",
|
|
34197
|
-
"block_height",
|
|
34198
|
-
"type",
|
|
34199
|
-
"sender",
|
|
34200
|
-
"status",
|
|
34201
|
-
"contract_id",
|
|
34202
|
-
"function_name"
|
|
34203
|
-
]).orderBy("block_height", "desc").limit(limit).execute();
|
|
34204
|
-
if (json) {
|
|
34205
|
-
console.log(JSON.stringify(rows, null, 2));
|
|
34206
|
-
process.exit(0);
|
|
34207
|
-
}
|
|
34208
|
-
console.log("");
|
|
34209
|
-
console.log(blue(`Recent Transactions (${rows.length})`));
|
|
34210
|
-
console.log("");
|
|
34211
|
-
console.log(dim(" BLOCK".padEnd(8)) + dim("TYPE".padEnd(18)) + dim("SENDER".padEnd(20)) + dim("CONTRACT/FUNCTION"));
|
|
34212
|
-
for (const row of rows) {
|
|
34213
|
-
const statusColor = row.status === "success" ? green : yellow;
|
|
34214
|
-
const contractInfo = row.contract_id ? `${row.contract_id.split(".")[1] || row.contract_id}${row.function_name ? `::${row.function_name}` : ""}` : "-";
|
|
34215
|
-
console.log(` ${statusColor(row.block_height.toString().padEnd(8))}${row.type.padEnd(18)}${`${row.sender.slice(0, 18)}... `.padEnd(20)}${contractInfo}`);
|
|
34216
|
-
}
|
|
34217
|
-
console.log("");
|
|
34218
|
-
process.exit(0);
|
|
34219
|
-
} catch (err) {
|
|
34220
|
-
error(`Failed to query transactions: ${err}`);
|
|
34221
|
-
process.exit(1);
|
|
34222
|
-
}
|
|
34223
|
-
}
|
|
34224
|
-
async function showEvents(limit, json) {
|
|
34225
|
-
try {
|
|
34226
|
-
const db = ensureDb();
|
|
34227
|
-
const rows = await db.selectFrom("events").select(["block_height", "tx_id", "event_index", "type", "data"]).orderBy("block_height", "desc").limit(limit).execute();
|
|
34228
|
-
if (json) {
|
|
34229
|
-
console.log(JSON.stringify(rows, null, 2));
|
|
34230
|
-
process.exit(0);
|
|
34231
|
-
}
|
|
34232
|
-
console.log("");
|
|
34233
|
-
console.log(blue(`Recent Events (${rows.length})`));
|
|
34234
|
-
console.log("");
|
|
34235
|
-
if (rows.length === 0) {
|
|
34236
|
-
console.log(dim(" No events found"));
|
|
34237
|
-
console.log("");
|
|
34238
|
-
process.exit(0);
|
|
34239
|
-
}
|
|
34240
|
-
console.log(dim(" BLOCK".padEnd(8)) + dim("INDEX".padEnd(8)) + dim("TYPE".padEnd(24)) + dim("TX"));
|
|
34241
|
-
for (const row of rows) {
|
|
34242
|
-
console.log(` ${row.block_height.toString().padEnd(8)}` + `${row.event_index.toString().padEnd(8)}` + `${row.type.padEnd(24)}` + `${row.tx_id.slice(0, 16)}...`);
|
|
34243
|
-
}
|
|
34244
|
-
console.log("");
|
|
34245
|
-
process.exit(0);
|
|
34246
|
-
} catch (err) {
|
|
34247
|
-
error(`Failed to query events: ${err}`);
|
|
34248
|
-
process.exit(1);
|
|
34249
|
-
}
|
|
34250
|
-
}
|
|
34251
|
-
async function showGaps(limit, json) {
|
|
34252
|
-
try {
|
|
34253
|
-
const db = ensureDb();
|
|
34254
|
-
const gaps = await findGaps(db, limit);
|
|
34255
|
-
const missing = await countMissingBlocks(db);
|
|
34256
|
-
if (json) {
|
|
34257
|
-
console.log(JSON.stringify({ gaps, totalMissingBlocks: missing }, null, 2));
|
|
34258
|
-
process.exit(0);
|
|
34259
|
-
}
|
|
34260
|
-
console.log("");
|
|
34261
|
-
if (gaps.length === 0) {
|
|
34262
|
-
console.log(green("No gaps detected — block data is contiguous"));
|
|
34263
|
-
console.log("");
|
|
34264
|
-
process.exit(0);
|
|
34265
|
-
}
|
|
34266
|
-
console.log(blue(`Block Gaps (${gaps.length})`));
|
|
34267
|
-
console.log("");
|
|
34268
|
-
console.log(dim(" GAP_START".padEnd(14)) + dim("GAP_END".padEnd(14)) + dim("SIZE"));
|
|
34269
|
-
for (const gap of gaps) {
|
|
34270
|
-
console.log(` ${gap.gapStart.toString().padEnd(14)}` + `${gap.gapEnd.toString().padEnd(14)}` + `${gap.size}`);
|
|
34271
|
-
}
|
|
34272
|
-
console.log("");
|
|
34273
|
-
console.log(`${yellow(gaps.length.toString())} gaps, ${red(missing.toString())} missing blocks`);
|
|
34274
|
-
console.log("");
|
|
34275
|
-
process.exit(0);
|
|
34276
|
-
} catch (err) {
|
|
34277
|
-
error(`Failed to query gaps: ${err}`);
|
|
34278
|
-
process.exit(1);
|
|
34279
|
-
}
|
|
34280
|
-
}
|
|
34281
|
-
async function resetDatabase(skipConfirm) {
|
|
34282
|
-
try {
|
|
34283
|
-
const db = ensureDb();
|
|
34284
|
-
const blockCount = (await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
|
|
34285
|
-
const txCount = (await db.selectFrom("transactions").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
|
|
34286
|
-
const eventCount = (await db.selectFrom("events").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
|
|
34287
|
-
console.log("");
|
|
34288
|
-
console.log(yellow("This will delete all indexed blockchain data:"));
|
|
34289
|
-
console.log("");
|
|
34290
|
-
console.log(` ${red(blockCount.toString())} blocks`);
|
|
34291
|
-
console.log(` ${red(txCount.toString())} transactions`);
|
|
34292
|
-
console.log(` ${red(eventCount.toString())} events`);
|
|
34293
|
-
console.log(` ${dim("+ index_progress")}`);
|
|
34294
|
-
console.log("");
|
|
34295
|
-
console.log(dim("Note: Subgraph configurations will be preserved."));
|
|
34296
|
-
console.log("");
|
|
34297
|
-
if (!skipConfirm) {
|
|
34298
|
-
const confirmed = await confirm2({
|
|
34299
|
-
message: "Are you sure you want to reset the database?",
|
|
34300
|
-
default: false
|
|
34301
|
-
});
|
|
34302
|
-
if (!confirmed) {
|
|
34303
|
-
info("Cancelled");
|
|
34304
|
-
process.exit(0);
|
|
34305
|
-
}
|
|
34306
|
-
}
|
|
34307
|
-
info("Truncating tables...");
|
|
34308
|
-
await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
|
|
34309
|
-
console.log("");
|
|
34310
|
-
success("Database reset complete");
|
|
34311
|
-
console.log("");
|
|
34312
|
-
console.log(dim("Run 'sl local restart' to restart the indexer for fresh sync."));
|
|
34313
|
-
console.log("");
|
|
34314
|
-
process.exit(0);
|
|
34315
|
-
} catch (err) {
|
|
34316
|
-
error(`Failed to reset database: ${err}`);
|
|
34317
|
-
process.exit(1);
|
|
34318
|
-
}
|
|
34319
|
-
}
|
|
34320
|
-
async function resyncDatabase(skipConfirm, backfill) {
|
|
34321
|
-
try {
|
|
34322
|
-
const db = ensureDb();
|
|
34323
|
-
const blockCount = (await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
|
|
34324
|
-
console.log("");
|
|
34325
|
-
console.log(yellow("This will:"));
|
|
34326
|
-
console.log(` 1. Delete all indexed data (${red(blockCount.toString())} blocks)`);
|
|
34327
|
-
console.log(" 2. Restart the indexer for fresh sync");
|
|
34328
|
-
if (backfill) {
|
|
34329
|
-
console.log(" 3. Fetch all blocks from node (backfill)");
|
|
34330
|
-
}
|
|
34331
|
-
console.log("");
|
|
34332
|
-
console.log(dim("Note: Subgraph configurations will be preserved."));
|
|
34333
|
-
console.log("");
|
|
34334
|
-
if (!skipConfirm) {
|
|
34335
|
-
const confirmed = await confirm2({
|
|
34336
|
-
message: "Are you sure you want to resync?",
|
|
34337
|
-
default: false
|
|
34338
|
-
});
|
|
34339
|
-
if (!confirmed) {
|
|
34340
|
-
info("Cancelled");
|
|
34341
|
-
process.exit(0);
|
|
34342
|
-
}
|
|
34343
|
-
}
|
|
34344
|
-
info("Truncating tables...");
|
|
34345
|
-
await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
|
|
34346
|
-
console.log(green(" ✓ Database reset"));
|
|
34347
|
-
const state = await loadDevState();
|
|
34348
|
-
if (state?.services?.indexer && isProcessRunning(state.services.indexer.pid)) {
|
|
34349
|
-
info("Restarting indexer...");
|
|
34350
|
-
try {
|
|
34351
|
-
process.kill(state.services.indexer.pid, "SIGTERM");
|
|
34352
|
-
await Bun.sleep(1000);
|
|
34353
|
-
} catch {}
|
|
34354
|
-
if (isProcessRunning(state.services.indexer.pid)) {
|
|
34355
|
-
try {
|
|
34356
|
-
process.kill(state.services.indexer.pid, "SIGKILL");
|
|
34357
|
-
} catch {}
|
|
34358
|
-
}
|
|
34359
|
-
console.log(green(" ✓ Indexer stopped"));
|
|
34360
|
-
console.log("");
|
|
34361
|
-
info("Run 'sl local restart' to start fresh sync");
|
|
34362
|
-
} else {
|
|
34363
|
-
console.log("");
|
|
34364
|
-
success("Database reset complete");
|
|
34365
|
-
console.log("");
|
|
34366
|
-
if (!backfill) {
|
|
34367
|
-
console.log(dim("Indexer not running. Start with 'sl local start' to begin sync."));
|
|
34368
|
-
}
|
|
34369
|
-
}
|
|
34370
|
-
if (backfill) {
|
|
34371
|
-
console.log("");
|
|
34372
|
-
info("Starting backfill from node...");
|
|
34373
|
-
const nodeClient = new StacksNodeClient;
|
|
34374
|
-
const healthy = await nodeClient.isHealthy();
|
|
34375
|
-
if (!healthy) {
|
|
34376
|
-
warn(`Cannot reach Stacks node at ${nodeClient.getRpcUrl()}`);
|
|
34377
|
-
console.log(dim("Run 'sl sync --from 1 --to <tip>' manually once the node is available."));
|
|
34378
|
-
console.log("");
|
|
34379
|
-
process.exit(0);
|
|
34380
|
-
}
|
|
34381
|
-
const nodeInfo = await nodeClient.getInfo();
|
|
34382
|
-
const tip = nodeInfo.stacks_tip_height;
|
|
34383
|
-
info(`Node tip: block ${tip}. Fetching blocks 1 to ${tip}...`);
|
|
34384
|
-
console.log(dim(`This may take a while. Run 'sl sync --from 1 --to ${tip}' if interrupted.`));
|
|
34385
|
-
console.log("");
|
|
34386
|
-
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
34387
|
-
const config = await loadConfig2();
|
|
34388
|
-
const indexerUrl = process.env.INDEXER_URL || `http://localhost:${config.ports.indexer}`;
|
|
34389
|
-
const concurrency = 5;
|
|
34390
|
-
let fetched = 0;
|
|
34391
|
-
let errors = 0;
|
|
34392
|
-
for (let i = 1;i <= tip; i += concurrency) {
|
|
34393
|
-
const batch = [];
|
|
34394
|
-
for (let j = i;j < i + concurrency && j <= tip; j++) {
|
|
34395
|
-
batch.push(j);
|
|
34396
|
-
}
|
|
34397
|
-
const results = await Promise.allSettled(batch.map(async (height) => {
|
|
34398
|
-
const block = await nodeClient.getBlock(height);
|
|
34399
|
-
if (!block)
|
|
34400
|
-
throw new Error(`Block ${height} not found`);
|
|
34401
|
-
const res = await fetch(`${indexerUrl}/new_block`, {
|
|
34402
|
-
method: "POST",
|
|
34403
|
-
headers: {
|
|
34404
|
-
"Content-Type": "application/json",
|
|
34405
|
-
"X-Source": "backfill"
|
|
34406
|
-
},
|
|
34407
|
-
body: JSON.stringify(block)
|
|
34408
|
-
});
|
|
34409
|
-
if (!res.ok)
|
|
34410
|
-
throw new Error(`Indexer rejected block ${height}: ${res.status}`);
|
|
34411
|
-
}));
|
|
34412
|
-
for (const r of results) {
|
|
34413
|
-
if (r.status === "fulfilled")
|
|
34414
|
-
fetched++;
|
|
34415
|
-
else
|
|
34416
|
-
errors++;
|
|
34417
|
-
}
|
|
34418
|
-
const pct = Math.round((fetched + errors) / tip * 100);
|
|
34419
|
-
process.stdout.write(`\r ${green(`${fetched}`)} fetched, ${errors > 0 ? red(`${errors} errors`) : "0 errors"} (${pct}%)`);
|
|
34420
|
-
}
|
|
34421
|
-
console.log("");
|
|
34422
|
-
console.log("");
|
|
34423
|
-
if (errors === 0) {
|
|
34424
|
-
success(`Backfill complete: ${fetched} blocks indexed`);
|
|
34425
|
-
} else {
|
|
34426
|
-
warn(`Backfill complete: ${fetched} indexed, ${errors} errors`);
|
|
34427
|
-
}
|
|
34428
|
-
}
|
|
34429
|
-
console.log("");
|
|
34430
|
-
process.exit(0);
|
|
34431
|
-
} catch (err) {
|
|
34432
|
-
error(`Failed to resync: ${err}`);
|
|
34433
|
-
process.exit(1);
|
|
34434
|
-
}
|
|
34435
|
-
}
|
|
34436
34165
|
// src/commands/devnet.ts
|
|
34437
34166
|
import { spawnSync } from "node:child_process";
|
|
34438
34167
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
34439
|
-
import { dirname as dirname4, join as
|
|
34168
|
+
import { dirname as dirname4, join as join6 } from "node:path";
|
|
34440
34169
|
|
|
34441
34170
|
// src/lib/devnet-compose.ts
|
|
34442
34171
|
var DEFAULT_IMAGE_OWNER = "ryanwaits";
|
|
@@ -34579,14 +34308,14 @@ volumes:
|
|
|
34579
34308
|
|
|
34580
34309
|
// src/lib/devnet-config.ts
|
|
34581
34310
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
34582
|
-
import { dirname as dirname3, join as
|
|
34311
|
+
import { dirname as dirname3, join as join5, parse as parsePath } from "node:path";
|
|
34583
34312
|
import { parse as parseToml } from "smol-toml";
|
|
34584
34313
|
var DEFAULT_INDEXER_OBSERVER = "host.docker.internal:3700";
|
|
34585
34314
|
function findClarinetProject(startDir) {
|
|
34586
34315
|
let dir = startDir;
|
|
34587
34316
|
const { root } = parsePath(dir);
|
|
34588
34317
|
while (true) {
|
|
34589
|
-
if (existsSync2(
|
|
34318
|
+
if (existsSync2(join5(dir, "Clarinet.toml")))
|
|
34590
34319
|
return dir;
|
|
34591
34320
|
if (dir === root)
|
|
34592
34321
|
return null;
|
|
@@ -34633,7 +34362,7 @@ stacks_node_events_observers = [${entry}]
|
|
|
34633
34362
|
|
|
34634
34363
|
// src/commands/devnet.ts
|
|
34635
34364
|
init_output();
|
|
34636
|
-
var COMPOSE_REL =
|
|
34365
|
+
var COMPOSE_REL = join6(".secondlayer", "docker-compose.yml");
|
|
34637
34366
|
function ensureDocker() {
|
|
34638
34367
|
const probe = spawnSync("docker", ["info"], { stdio: "ignore" });
|
|
34639
34368
|
if (probe.error || probe.status !== 0) {
|
|
@@ -34668,16 +34397,16 @@ function registerDevnetCommand(program2) {
|
|
|
34668
34397
|
devnet.command("down").description("Stop the local Secondlayer stack started by `sl devnet connect`").option("--project <dir>", "Clarinet project directory").option("--purge", "Also remove volumes (wipes the local index)").action(async (options) => {
|
|
34669
34398
|
await down(options);
|
|
34670
34399
|
});
|
|
34671
|
-
devnet.command("status").description("Snapshot of the local stack: ingest, subgraphs, and recent activity").option("-w, --watch", "Refresh every 2s until Ctrl-C").option("
|
|
34400
|
+
devnet.command("status").description("Snapshot of the local stack: ingest, subgraphs, and recent activity").option("-w, --watch", "Refresh every 2s until Ctrl-C").option("--limit <n>", "Recent activity rows to show", "12").action(async (options) => {
|
|
34672
34401
|
await status(options);
|
|
34673
34402
|
});
|
|
34674
|
-
devnet.command("logs [service]").description("Tail stack logs — all services, or one of: indexer, api, subgraph-processor, postgres").option("--project <dir>", "Clarinet project directory").option("-f, --follow", "Follow log output").option("-n, --
|
|
34403
|
+
devnet.command("logs [service]").description("Tail stack logs — all services, or one of: indexer, api, subgraph-processor, postgres").option("--project <dir>", "Clarinet project directory").option("-f, --follow", "Follow log output").option("-n, --lines <n>", "Lines to show from the end of each log").action(async (service, options) => {
|
|
34675
34404
|
await logs(service, options);
|
|
34676
34405
|
});
|
|
34677
34406
|
}
|
|
34678
34407
|
function resolveProject(explicit) {
|
|
34679
34408
|
if (explicit) {
|
|
34680
|
-
if (!existsSync3(
|
|
34409
|
+
if (!existsSync3(join6(explicit, "Clarinet.toml"))) {
|
|
34681
34410
|
error(`No Clarinet.toml in ${explicit}`);
|
|
34682
34411
|
process.exit(1);
|
|
34683
34412
|
}
|
|
@@ -34693,7 +34422,7 @@ function resolveProject(explicit) {
|
|
|
34693
34422
|
}
|
|
34694
34423
|
async function connect(options) {
|
|
34695
34424
|
const project = resolveProject(options.project);
|
|
34696
|
-
const devnetToml =
|
|
34425
|
+
const devnetToml = join6(project, "settings", "Devnet.toml");
|
|
34697
34426
|
mkdirSync2(dirname4(devnetToml), { recursive: true });
|
|
34698
34427
|
const result = ensureEventObserver(devnetToml, DEFAULT_INDEXER_OBSERVER);
|
|
34699
34428
|
console.log(`${green("✓")} found Clarinet.toml`);
|
|
@@ -34703,7 +34432,7 @@ async function connect(options) {
|
|
|
34703
34432
|
console.log(`${green("✓")} ${result.status === "created" ? "created" : "patched"} settings/Devnet.toml`);
|
|
34704
34433
|
console.log(dim(` + stacks_node_events_observers = ["${DEFAULT_INDEXER_OBSERVER}"]`));
|
|
34705
34434
|
}
|
|
34706
|
-
const composePath =
|
|
34435
|
+
const composePath = join6(project, COMPOSE_REL);
|
|
34707
34436
|
mkdirSync2(dirname4(composePath), { recursive: true });
|
|
34708
34437
|
writeFileSync3(composePath, buildDevnetCompose({ owner: options.owner, imageTag: options.imageTag }));
|
|
34709
34438
|
console.log(`${green("✓")} wrote ${COMPOSE_REL}`);
|
|
@@ -34727,13 +34456,13 @@ ${bold("Secondlayer stack up")}`);
|
|
|
34727
34456
|
console.log(`
|
|
34728
34457
|
${bold("Next:")}`);
|
|
34729
34458
|
console.log(` ${yellow("clarinet devnet start")} ${dim("# auto-deploys + streams to the indexer")}`);
|
|
34730
|
-
console.log(` ${yellow("SL_API_URL=http://localhost:3800
|
|
34459
|
+
console.log(` ${yellow("SL_API_URL=http://localhost:3800 SL_API_KEY=dummy sl subgraphs deploy ./subgraph.ts")}`);
|
|
34731
34460
|
console.log(dim(`
|
|
34732
34461
|
Stop with: sl devnet down`));
|
|
34733
34462
|
}
|
|
34734
34463
|
async function down(options) {
|
|
34735
34464
|
const project = resolveProject(options.project);
|
|
34736
|
-
const composePath =
|
|
34465
|
+
const composePath = join6(project, COMPOSE_REL);
|
|
34737
34466
|
if (!existsSync3(composePath)) {
|
|
34738
34467
|
error(`No ${COMPOSE_REL} in ${project} — nothing to stop. Run \`sl devnet connect\` first.`);
|
|
34739
34468
|
process.exit(1);
|
|
@@ -34748,7 +34477,7 @@ async function down(options) {
|
|
|
34748
34477
|
}
|
|
34749
34478
|
async function logs(service, options) {
|
|
34750
34479
|
const project = resolveProject(options.project);
|
|
34751
|
-
const composePath =
|
|
34480
|
+
const composePath = join6(project, COMPOSE_REL);
|
|
34752
34481
|
if (!existsSync3(composePath)) {
|
|
34753
34482
|
error(`No ${COMPOSE_REL} in ${project} — run \`sl devnet connect\` first.`);
|
|
34754
34483
|
process.exit(1);
|
|
@@ -34758,7 +34487,7 @@ async function logs(service, options) {
|
|
|
34758
34487
|
process.exit(1);
|
|
34759
34488
|
}
|
|
34760
34489
|
ensureDocker();
|
|
34761
|
-
const args = ["logs", "--tail", options.
|
|
34490
|
+
const args = ["logs", "--tail", options.lines ?? "200"];
|
|
34762
34491
|
if (options.follow)
|
|
34763
34492
|
args.push("-f");
|
|
34764
34493
|
if (service)
|
|
@@ -34875,9 +34604,9 @@ import {
|
|
|
34875
34604
|
watch,
|
|
34876
34605
|
writeFileSync as writeFileSync4
|
|
34877
34606
|
} from "node:fs";
|
|
34878
|
-
import { dirname as dirname5, join as
|
|
34607
|
+
import { dirname as dirname5, join as join7, resolve as resolve2 } from "node:path";
|
|
34879
34608
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
34880
|
-
import { confirm as
|
|
34609
|
+
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
34881
34610
|
|
|
34882
34611
|
// src/generators/subgraph-scaffold.ts
|
|
34883
34612
|
init_format();
|
|
@@ -35140,9 +34869,40 @@ init_fs();
|
|
|
35140
34869
|
init_output();
|
|
35141
34870
|
|
|
35142
34871
|
// src/commands/login.ts
|
|
35143
|
-
import { confirm as
|
|
34872
|
+
import { confirm as confirm2, input as input2 } from "@inquirer/prompts";
|
|
35144
34873
|
init_output();
|
|
35145
34874
|
init_session();
|
|
34875
|
+
function sessionExpiry() {
|
|
34876
|
+
return new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString();
|
|
34877
|
+
}
|
|
34878
|
+
async function readStdin() {
|
|
34879
|
+
const chunks = [];
|
|
34880
|
+
for await (const chunk of process.stdin)
|
|
34881
|
+
chunks.push(chunk);
|
|
34882
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
34883
|
+
}
|
|
34884
|
+
async function runTokenLogin() {
|
|
34885
|
+
const token = await readStdin();
|
|
34886
|
+
if (!token) {
|
|
34887
|
+
error('No token on stdin. Usage: echo "$KEY" | sl login --with-token');
|
|
34888
|
+
process.exit(1);
|
|
34889
|
+
}
|
|
34890
|
+
process.env.SL_API_KEY = token;
|
|
34891
|
+
let account;
|
|
34892
|
+
try {
|
|
34893
|
+
account = await httpPlatform("/api/accounts/me");
|
|
34894
|
+
} catch (err) {
|
|
34895
|
+
error(err instanceof CliHttpError ? `Token rejected: ${err.message}` : err instanceof Error ? err.message : String(err));
|
|
34896
|
+
process.exit(1);
|
|
34897
|
+
}
|
|
34898
|
+
await writeSession({
|
|
34899
|
+
token,
|
|
34900
|
+
email: account.email,
|
|
34901
|
+
accountId: account.id,
|
|
34902
|
+
expiresAt: sessionExpiry()
|
|
34903
|
+
});
|
|
34904
|
+
success(`Logged in as ${account.email}`);
|
|
34905
|
+
}
|
|
35146
34906
|
async function runLoginFlow(options = {}) {
|
|
35147
34907
|
if (!options.force) {
|
|
35148
34908
|
const existing = await readSession();
|
|
@@ -35153,7 +34913,7 @@ async function runLoginFlow(options = {}) {
|
|
|
35153
34913
|
return;
|
|
35154
34914
|
}
|
|
35155
34915
|
try {
|
|
35156
|
-
const proceed = await
|
|
34916
|
+
const proceed = await confirm2({
|
|
35157
34917
|
message: "Log in as a different user?",
|
|
35158
34918
|
default: false
|
|
35159
34919
|
});
|
|
@@ -35197,12 +34957,11 @@ async function runLoginFlow(options = {}) {
|
|
|
35197
34957
|
method: "POST",
|
|
35198
34958
|
body: { email, code }
|
|
35199
34959
|
});
|
|
35200
|
-
const expiresAt = new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString();
|
|
35201
34960
|
await writeSession({
|
|
35202
34961
|
token: verified.sessionToken,
|
|
35203
34962
|
email: verified.account.email,
|
|
35204
34963
|
accountId: verified.account.id,
|
|
35205
|
-
expiresAt
|
|
34964
|
+
expiresAt: sessionExpiry()
|
|
35206
34965
|
});
|
|
35207
34966
|
success(`Logged in as ${verified.account.email}`);
|
|
35208
34967
|
info(dim("Run 'sl whoami' to see your account status."));
|
|
@@ -35216,7 +34975,10 @@ async function runLoginFlow(options = {}) {
|
|
|
35216
34975
|
}
|
|
35217
34976
|
}
|
|
35218
34977
|
function registerLoginCommand(program2) {
|
|
35219
|
-
program2.command("login").description("Log in to Secondlayer (magic-link email)").option("
|
|
34978
|
+
program2.command("login").description("Log in to Secondlayer (magic-link email)").option("--force", "Skip the already-logged-in check and re-run the flow").option("--with-token", "Read an API key from stdin (non-interactive)").addHelpText("after", `
|
|
34979
|
+
Examples:
|
|
34980
|
+
$ sl login
|
|
34981
|
+
$ echo "$SL_API_KEY" | sl login --with-token`).action((opts) => opts.withToken ? runTokenLogin() : runLoginFlow({ force: opts.force }));
|
|
35220
34982
|
}
|
|
35221
34983
|
|
|
35222
34984
|
// src/lib/require-auth.ts
|
|
@@ -35622,7 +35384,7 @@ async function loadSubgraphWithDepCheck(absPath) {
|
|
|
35622
35384
|
if (!missingSdk)
|
|
35623
35385
|
throw err;
|
|
35624
35386
|
warn("Missing dependency: @secondlayer/subgraphs");
|
|
35625
|
-
const install = await
|
|
35387
|
+
const install = await confirm3({
|
|
35626
35388
|
message: "Install with `bun add @secondlayer/subgraphs`?",
|
|
35627
35389
|
default: true
|
|
35628
35390
|
});
|
|
@@ -35678,19 +35440,48 @@ function formatSubgraphSpecOutput(spec, format) {
|
|
|
35678
35440
|
return `${JSON.stringify(spec, null, 2)}
|
|
35679
35441
|
`;
|
|
35680
35442
|
}
|
|
35681
|
-
async function writeOrPrintSubgraphSpec(spec, format,
|
|
35443
|
+
async function writeOrPrintSubgraphSpec(spec, format, output2) {
|
|
35682
35444
|
const text = formatSubgraphSpecOutput(spec, format);
|
|
35683
|
-
if (!
|
|
35445
|
+
if (!output2) {
|
|
35684
35446
|
process.stdout.write(text);
|
|
35685
35447
|
return;
|
|
35686
35448
|
}
|
|
35687
|
-
const outPath = resolve2(
|
|
35449
|
+
const outPath = resolve2(output2);
|
|
35688
35450
|
const dir = resolve2(outPath, "..");
|
|
35689
35451
|
if (!existsSync4(dir))
|
|
35690
35452
|
mkdirSync3(dir, { recursive: true });
|
|
35691
35453
|
await writeTextFile(outPath, text);
|
|
35692
35454
|
success(`Created ${outPath}`);
|
|
35693
35455
|
}
|
|
35456
|
+
async function specFromLocalFile(absPath, format, specOptions) {
|
|
35457
|
+
const { readFile: readFile3 } = await import("node:fs/promises");
|
|
35458
|
+
const { bundleSubgraphCode } = await import("@secondlayer/bundler");
|
|
35459
|
+
const { generateSubgraphSQL } = await import("@secondlayer/subgraphs");
|
|
35460
|
+
const {
|
|
35461
|
+
generateSubgraphAgentSchema,
|
|
35462
|
+
generateSubgraphMarkdown,
|
|
35463
|
+
generateSubgraphOpenApi
|
|
35464
|
+
} = await import("@secondlayer/shared/subgraphs/spec");
|
|
35465
|
+
const source = await readFile3(absPath, "utf8");
|
|
35466
|
+
const bundled = await bundleSubgraphCode(source);
|
|
35467
|
+
const { hash } = generateSubgraphSQL({
|
|
35468
|
+
name: bundled.name,
|
|
35469
|
+
version: bundled.version,
|
|
35470
|
+
description: bundled.description,
|
|
35471
|
+
sources: bundled.sources,
|
|
35472
|
+
schema: bundled.schema,
|
|
35473
|
+
handlers: {}
|
|
35474
|
+
});
|
|
35475
|
+
const detail = createLocalSubgraphDetail({
|
|
35476
|
+
name: bundled.name,
|
|
35477
|
+
version: bundled.version,
|
|
35478
|
+
description: bundled.description,
|
|
35479
|
+
sources: bundled.sources,
|
|
35480
|
+
schema: bundled.schema,
|
|
35481
|
+
schemaHash: hash
|
|
35482
|
+
});
|
|
35483
|
+
return format === "openapi" ? generateSubgraphOpenApi(detail, specOptions) : format === "agent" ? generateSubgraphAgentSchema(detail, specOptions) : generateSubgraphMarkdown(detail, specOptions);
|
|
35484
|
+
}
|
|
35694
35485
|
function createLocalSubgraphDetail(input3) {
|
|
35695
35486
|
const tables = {};
|
|
35696
35487
|
for (const [tableName, rawTable] of Object.entries(input3.schema)) {
|
|
@@ -35765,7 +35556,7 @@ function readCliSubgraphsDependency() {
|
|
|
35765
35556
|
return "^1.3.2";
|
|
35766
35557
|
}
|
|
35767
35558
|
function ensureScaffoldPackageJson(dir) {
|
|
35768
|
-
const packagePath =
|
|
35559
|
+
const packagePath = join7(dir, "package.json");
|
|
35769
35560
|
const subgraphsDep = readCliSubgraphsDependency();
|
|
35770
35561
|
if (!existsSync4(packagePath)) {
|
|
35771
35562
|
writeFileSync4(packagePath, `${JSON.stringify({
|
|
@@ -35883,7 +35674,10 @@ function formatSubgraphSync(sync) {
|
|
|
35883
35674
|
}
|
|
35884
35675
|
function registerSubgraphsCommand(program2) {
|
|
35885
35676
|
const subgraphs = program2.command("subgraphs").description("Manage materialized subgraphs");
|
|
35886
|
-
subgraphs.command("
|
|
35677
|
+
subgraphs.command("create <name>").description("Create a new subgraph definition file").option("--template <slug>", `Foundation Dataset starter (one of: ${SUBGRAPH_TEMPLATE_SLUGS.join(", ")})`).addHelpText("after", `
|
|
35678
|
+
Examples:
|
|
35679
|
+
$ sl subgraphs new my-graph
|
|
35680
|
+
$ sl subgraphs new token-balances --template sip-010-balances`).action(async (name, opts) => {
|
|
35887
35681
|
const slug = opts.template ?? "basic";
|
|
35888
35682
|
if (!SUBGRAPH_TEMPLATE_SLUGS.includes(slug)) {
|
|
35889
35683
|
error(`Unknown template "${opts.template}". Available templates:
|
|
@@ -35925,9 +35719,9 @@ ${SUBGRAPH_TEMPLATE_SLUGS.map((s) => ` ${s.padEnd(20)} ${SUBGRAPH_TEMPLATE_DESC
|
|
|
35925
35719
|
const def = mod.default ?? mod;
|
|
35926
35720
|
const { validateSubgraphDefinition } = await import("@secondlayer/subgraphs/validate");
|
|
35927
35721
|
const { deploySchema } = await import("@secondlayer/subgraphs");
|
|
35928
|
-
const { getDb
|
|
35722
|
+
const { getDb } = await import("@secondlayer/shared/db");
|
|
35929
35723
|
validateSubgraphDefinition(def);
|
|
35930
|
-
const db =
|
|
35724
|
+
const db = getDb();
|
|
35931
35725
|
const result = await deploySchema(db, def, absPath, {
|
|
35932
35726
|
forceReindex: false
|
|
35933
35727
|
});
|
|
@@ -35969,14 +35763,14 @@ Stopped watching.`);
|
|
|
35969
35763
|
});
|
|
35970
35764
|
await new Promise(() => {});
|
|
35971
35765
|
});
|
|
35972
|
-
subgraphs.command("deploy <file>").description("Deploy a subgraph definition file").option("--start-block <n>", "Override the subgraph definition startBlock for this deploy").option("--dry-run", "Validate and preview deploy without writing changes").option("
|
|
35766
|
+
subgraphs.command("deploy <file>").description("Deploy a subgraph definition file").option("--start-block <n>", "Override the subgraph definition startBlock for this deploy").option("--dry-run", "Validate and preview deploy without writing changes").option("-y, --yes", "Skip the reindex confirmation prompt").option("--database-url <url>", "BYO data plane: write the subgraph's schema/rows to your own Postgres. With --dry-run, prints the DDL + grant script and verifies the connection.").option("--strict", "Run `tsc --noEmit` against the handler before deploy (slower; catches TS type errors)").action(async (file, options2) => {
|
|
35973
35767
|
try {
|
|
35974
35768
|
const absPath = resolve2(file);
|
|
35975
35769
|
const config = await loadConfig();
|
|
35976
35770
|
if (config.network !== "local") {
|
|
35977
35771
|
await requireAuth();
|
|
35978
35772
|
}
|
|
35979
|
-
const dryRun = options2.dryRun
|
|
35773
|
+
const dryRun = options2.dryRun;
|
|
35980
35774
|
const startBlock = parseStartBlockOption(options2.startBlock);
|
|
35981
35775
|
if (startBlock !== undefined) {
|
|
35982
35776
|
warn(`--start-block ${startBlock} overrides the definition's startBlock for this deploy.`);
|
|
@@ -36059,7 +35853,7 @@ Stopped watching.`);
|
|
|
36059
35853
|
info(` + columns: ${t}.${cols.join(", ")}`);
|
|
36060
35854
|
}
|
|
36061
35855
|
}
|
|
36062
|
-
const confirmed = options2.
|
|
35856
|
+
const confirmed = options2.yes || await confirm3({
|
|
36063
35857
|
message: "⚠ This will drop all data and reindex from scratch. Continue?"
|
|
36064
35858
|
});
|
|
36065
35859
|
if (!confirmed) {
|
|
@@ -36093,8 +35887,8 @@ Stopped watching.`);
|
|
|
36093
35887
|
return;
|
|
36094
35888
|
}
|
|
36095
35889
|
const { deploySchema } = await import("@secondlayer/subgraphs");
|
|
36096
|
-
const { getDb
|
|
36097
|
-
const db =
|
|
35890
|
+
const { getDb, closeDb } = await import("@secondlayer/shared/db");
|
|
35891
|
+
const db = getDb();
|
|
36098
35892
|
const result = await deploySchema(db, effectiveDef, absPath, {
|
|
36099
35893
|
version: undefined,
|
|
36100
35894
|
forceReindex: startBlock !== undefined
|
|
@@ -36145,7 +35939,7 @@ ${data.length} subgraph(s) total`));
|
|
|
36145
35939
|
handleApiError(err, "list subgraphs");
|
|
36146
35940
|
}
|
|
36147
35941
|
});
|
|
36148
|
-
subgraphs.command("status <name>").description("Show detailed subgraph status").option("-w, --watch", "Refresh every 2s until synced or Ctrl-C").action(async (name, options2) => {
|
|
35942
|
+
subgraphs.command("status <name>").alias("get").description("Show detailed subgraph status").option("-w, --watch", "Refresh every 2s until synced or Ctrl-C").action(async (name, options2) => {
|
|
36149
35943
|
const renderOnce = async () => {
|
|
36150
35944
|
const subgraph = await getSubgraphApi(name);
|
|
36151
35945
|
const rowCounts = Object.entries(subgraph.tables).map(([t, info2]) => `${t}: ${info2.rowCount}`).join(", ") || "N/A";
|
|
@@ -36210,64 +36004,24 @@ Synced — exiting watch.`));
|
|
|
36210
36004
|
handleApiError(err, "get subgraph status");
|
|
36211
36005
|
}
|
|
36212
36006
|
});
|
|
36213
|
-
subgraphs.command("spec <
|
|
36007
|
+
subgraphs.command("spec <nameOrFile>").description("Output API documentation for a deployed subgraph or a local subgraph file").option("--format <format>", "Output format: openapi, agent, markdown", "openapi").option("-o, --output <path>", "Write output to a file").option("--server <url>", "Override the server URL in generated docs").action(async (nameOrFile, options2) => {
|
|
36214
36008
|
try {
|
|
36215
36009
|
const format = parseSubgraphSpecFormat(options2.format);
|
|
36216
36010
|
const specOptions = options2.server ? { serverUrl: options2.server } : undefined;
|
|
36217
|
-
const
|
|
36218
|
-
|
|
36219
|
-
} catch (err) {
|
|
36220
|
-
if (err instanceof Error && err.message.startsWith("--format")) {
|
|
36221
|
-
error(err.message);
|
|
36222
|
-
process.exit(1);
|
|
36223
|
-
}
|
|
36224
|
-
handleApiError(err, "generate subgraph spec");
|
|
36225
|
-
}
|
|
36226
|
-
});
|
|
36227
|
-
subgraphs.command("inspect <file>").description("Output API documentation for a local subgraph file").option("--format <format>", "Output format: openapi, agent, markdown", "agent").option("-o, --output <path>", "Write output to a file").option("--server <url>", "Override the server URL in generated docs").action(async (file, options2) => {
|
|
36228
|
-
try {
|
|
36229
|
-
const format = parseSubgraphSpecFormat(options2.format);
|
|
36230
|
-
const absPath = resolve2(file);
|
|
36231
|
-
if (!existsSync4(absPath)) {
|
|
36011
|
+
const absPath = resolve2(nameOrFile);
|
|
36012
|
+
if (nameOrFile.endsWith(".ts") && !existsSync4(absPath)) {
|
|
36232
36013
|
error(`File not found: ${absPath}`);
|
|
36233
36014
|
process.exit(1);
|
|
36234
36015
|
}
|
|
36235
|
-
const
|
|
36236
|
-
const
|
|
36237
|
-
const { generateSubgraphSQL } = await import("@secondlayer/subgraphs");
|
|
36238
|
-
const {
|
|
36239
|
-
generateSubgraphAgentSchema,
|
|
36240
|
-
generateSubgraphMarkdown,
|
|
36241
|
-
generateSubgraphOpenApi
|
|
36242
|
-
} = await import("@secondlayer/shared/subgraphs/spec");
|
|
36243
|
-
const source = await readFile3(absPath, "utf8");
|
|
36244
|
-
const bundled = await bundleSubgraphCode(source);
|
|
36245
|
-
const { hash } = generateSubgraphSQL({
|
|
36246
|
-
name: bundled.name,
|
|
36247
|
-
version: bundled.version,
|
|
36248
|
-
description: bundled.description,
|
|
36249
|
-
sources: bundled.sources,
|
|
36250
|
-
schema: bundled.schema,
|
|
36251
|
-
handlers: {}
|
|
36252
|
-
});
|
|
36253
|
-
const detail = createLocalSubgraphDetail({
|
|
36254
|
-
name: bundled.name,
|
|
36255
|
-
version: bundled.version,
|
|
36256
|
-
description: bundled.description,
|
|
36257
|
-
sources: bundled.sources,
|
|
36258
|
-
schema: bundled.schema,
|
|
36259
|
-
schemaHash: hash
|
|
36260
|
-
});
|
|
36261
|
-
const specOptions = options2.server ? { serverUrl: options2.server } : undefined;
|
|
36262
|
-
const spec = format === "openapi" ? generateSubgraphOpenApi(detail, specOptions) : format === "agent" ? generateSubgraphAgentSchema(detail, specOptions) : generateSubgraphMarkdown(detail, specOptions);
|
|
36016
|
+
const isLocalFile = nameOrFile.endsWith(".ts");
|
|
36017
|
+
const spec = isLocalFile ? await specFromLocalFile(absPath, format, specOptions) : format === "openapi" ? await getSubgraphOpenApi(nameOrFile, specOptions) : format === "agent" ? await getSubgraphAgentSchema(nameOrFile, specOptions) : await getSubgraphMarkdown(nameOrFile, specOptions);
|
|
36263
36018
|
await writeOrPrintSubgraphSpec(spec, format, options2.output);
|
|
36264
36019
|
} catch (err) {
|
|
36265
36020
|
if (err instanceof Error && err.message.startsWith("--format")) {
|
|
36266
36021
|
error(err.message);
|
|
36267
36022
|
process.exit(1);
|
|
36268
36023
|
}
|
|
36269
|
-
|
|
36270
|
-
process.exit(1);
|
|
36024
|
+
handleApiError(err, "generate subgraph spec");
|
|
36271
36025
|
}
|
|
36272
36026
|
});
|
|
36273
36027
|
subgraphs.command("codegen <file>").description("Generate an ORM schema (Prisma or Drizzle) for a subgraph's tables — point it at your BYO database").option("--target <orm>", "ORM target: prisma | drizzle", "prisma").option("--schema <name>", "Postgres schema name (defaults to subgraph_<name>)").option("--env <var>", "datasource url env var", "DATABASE_URL").option("--models-only", "Emit only Prisma models (compose via prismaSchemaFolder)").option("-o, --output <path>", "Write to a file (defaults to stdout)").action(async (file, options2) => {
|
|
@@ -36312,20 +36066,25 @@ Synced — exiting watch.`));
|
|
|
36312
36066
|
process.exit(1);
|
|
36313
36067
|
}
|
|
36314
36068
|
});
|
|
36315
|
-
subgraphs.command("reindex <name>").description("Reindex a subgraph from historical blocks (drops + reprocesses)").option("--from <
|
|
36069
|
+
subgraphs.command("reindex <name>").description("Reindex a subgraph from historical blocks (drops + reprocesses)").option("--from-block <n>", "Start block height").option("--to-block <n>", "End block height").option("-y, --yes", "Skip confirmation").addHelpText("after", `
|
|
36070
|
+
Examples:
|
|
36071
|
+
$ sl subgraphs reindex my-graph -y
|
|
36072
|
+
$ sl subgraphs reindex my-graph --from-block 150000 --to-block 160000 -y`).action(async (name, options2) => {
|
|
36316
36073
|
try {
|
|
36317
|
-
const
|
|
36318
|
-
const
|
|
36074
|
+
const fromRaw = options2.fromBlock;
|
|
36075
|
+
const toRaw = options2.toBlock;
|
|
36076
|
+
const fromBlock = fromRaw ? Number.parseInt(fromRaw, 10) : undefined;
|
|
36077
|
+
const toBlock = toRaw ? Number.parseInt(toRaw, 10) : undefined;
|
|
36319
36078
|
if (!options2.yes) {
|
|
36320
36079
|
if (!process.stdin.isTTY) {
|
|
36321
36080
|
error("Interactive prompt unavailable (stdin is not a TTY). Re-run with -y to skip confirmation.");
|
|
36322
36081
|
process.exit(1);
|
|
36323
36082
|
}
|
|
36324
|
-
const { confirm:
|
|
36083
|
+
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
|
36325
36084
|
const range = fromBlock !== undefined && toBlock !== undefined ? ` for blocks [${fromBlock}, ${toBlock}]` : fromBlock !== undefined ? ` from block ${fromBlock}` : toBlock !== undefined ? ` up to block ${toBlock}` : "";
|
|
36326
36085
|
let ok = false;
|
|
36327
36086
|
try {
|
|
36328
|
-
ok = await
|
|
36087
|
+
ok = await confirm4({
|
|
36329
36088
|
message: `Reindex subgraph "${name}"${range}? Existing rows in this range will be dropped and reprocessed.`,
|
|
36330
36089
|
default: false
|
|
36331
36090
|
});
|
|
@@ -36353,23 +36112,34 @@ Synced — exiting watch.`));
|
|
|
36353
36112
|
handleApiError(err, "reindex subgraph");
|
|
36354
36113
|
}
|
|
36355
36114
|
});
|
|
36356
|
-
subgraphs.command("backfill <name>").description("Backfill a block range without dropping existing data").
|
|
36115
|
+
subgraphs.command("backfill <name>").description("Backfill a block range without dropping existing data").option("--from-block <n>", "Start block height").option("--to-block <n>", "End block height").addHelpText("after", `
|
|
36116
|
+
Examples:
|
|
36117
|
+
$ sl subgraphs backfill my-graph --from-block 150000 --to-block 160000`).action(async (name, options2) => {
|
|
36357
36118
|
try {
|
|
36358
|
-
const
|
|
36359
|
-
const
|
|
36119
|
+
const fromRaw = options2.fromBlock;
|
|
36120
|
+
const toRaw = options2.toBlock;
|
|
36121
|
+
if (!fromRaw || !toRaw) {
|
|
36122
|
+
error("--from-block and --to-block are required");
|
|
36123
|
+
process.exit(1);
|
|
36124
|
+
}
|
|
36125
|
+
const fromBlock = Number.parseInt(fromRaw, 10);
|
|
36126
|
+
const toBlock = Number.parseInt(toRaw, 10);
|
|
36360
36127
|
if (Number.isNaN(fromBlock) || Number.isNaN(toBlock)) {
|
|
36361
|
-
error("--from and --to must be valid block numbers");
|
|
36128
|
+
error("--from-block and --to-block must be valid block numbers");
|
|
36362
36129
|
process.exit(1);
|
|
36363
36130
|
}
|
|
36364
36131
|
info(`Backfilling subgraph "${name}" from block ${fromBlock} to ${toBlock}...`);
|
|
36365
|
-
const result = await backfillSubgraphApi(name, {
|
|
36132
|
+
const result = await backfillSubgraphApi(name, {
|
|
36133
|
+
fromBlock,
|
|
36134
|
+
toBlock
|
|
36135
|
+
});
|
|
36366
36136
|
success(result.message);
|
|
36367
36137
|
info(`From block ${result.fromBlock} to ${result.toBlock}`);
|
|
36368
36138
|
} catch (err) {
|
|
36369
36139
|
handleApiError(err, "backfill subgraph");
|
|
36370
36140
|
}
|
|
36371
36141
|
});
|
|
36372
|
-
subgraphs.command("
|
|
36142
|
+
subgraphs.command("cancel <name>").description("Cancel a running reindex or backfill operation").action(async (name) => {
|
|
36373
36143
|
try {
|
|
36374
36144
|
info(`Stopping operation for subgraph "${name}"...`);
|
|
36375
36145
|
const result = await stopSubgraphApi(name);
|
|
@@ -36407,7 +36177,11 @@ ${result.meta.total} gap(s), ${result.meta.totalMissingBlocks} total missing blo
|
|
|
36407
36177
|
handleApiError(err, "get subgraph gaps");
|
|
36408
36178
|
}
|
|
36409
36179
|
});
|
|
36410
|
-
subgraphs.command("query <name> <table>").description("Query a subgraph table").option("--sort <column>", "Sort by column").option("--order <dir>", "Sort direction (asc|desc)", "asc").option("--limit <n>", "Max rows to return", "20").option("--offset <n>", "Skip first N rows").option("--fields <cols>", "Comma-separated columns to include").option("--filter <kv...>", "Filter as key=value (supports .gte/.lte/.gt/.lt/.neq suffixes)").option("--count", "Return row count only").option("--json", "Output as JSON").
|
|
36180
|
+
subgraphs.command("query <name> <table>").description("Query a subgraph table").option("--sort <column>", "Sort by column").option("--order <dir>", "Sort direction (asc|desc)", "asc").option("--limit <n>", "Max rows to return", "20").option("--offset <n>", "Skip first N rows").option("--fields <cols>", "Comma-separated columns to include").option("--filter <kv...>", "Filter as key=value (supports .gte/.lte/.gt/.lt/.neq suffixes)").option("--count", "Return row count only").option("--json", "Output as JSON").addHelpText("after", `
|
|
36181
|
+
Examples:
|
|
36182
|
+
$ sl subgraphs query my-graph balances --filter holder=SP2J6ZY... --limit 50
|
|
36183
|
+
$ sl subgraphs query my-graph transfers --filter amount.gte=1000 --sort _block_height --order desc
|
|
36184
|
+
$ sl subgraphs query my-graph balances --count`).action(async (name, table, options2) => {
|
|
36411
36185
|
try {
|
|
36412
36186
|
let filters;
|
|
36413
36187
|
try {
|
|
@@ -36461,17 +36235,17 @@ ${rows.length} row(s)`));
|
|
|
36461
36235
|
handleApiError(err, "query subgraph");
|
|
36462
36236
|
}
|
|
36463
36237
|
});
|
|
36464
|
-
subgraphs.command("delete <name>").description("Delete a subgraph and its data").option("-y, --yes", "Skip confirmation").option("--force", "Cancel active operations and force delete").action(async (name, options2) => {
|
|
36238
|
+
subgraphs.command("delete <name>").alias("rm").description("Delete a subgraph and its data").option("-y, --yes", "Skip confirmation").option("--force", "Cancel active operations and force delete").action(async (name, options2) => {
|
|
36465
36239
|
try {
|
|
36466
36240
|
if (!options2.yes && !options2.force) {
|
|
36467
36241
|
if (!process.stdin.isTTY) {
|
|
36468
36242
|
error("Interactive prompt unavailable (stdin is not a TTY). Re-run with -y to skip confirmation.");
|
|
36469
36243
|
process.exit(1);
|
|
36470
36244
|
}
|
|
36471
|
-
const { confirm:
|
|
36245
|
+
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
|
36472
36246
|
let ok = false;
|
|
36473
36247
|
try {
|
|
36474
|
-
ok = await
|
|
36248
|
+
ok = await confirm4({
|
|
36475
36249
|
message: `Delete subgraph "${name}" and all its data? This cannot be undone.`
|
|
36476
36250
|
});
|
|
36477
36251
|
} catch (promptErr) {
|
|
@@ -36505,7 +36279,11 @@ ${rows.length} row(s)`));
|
|
|
36505
36279
|
handleApiError(err, "delete subgraph");
|
|
36506
36280
|
}
|
|
36507
36281
|
});
|
|
36508
|
-
subgraphs.command("scaffold [contractAddress]").description("Scaffold a defineSubgraph() file
|
|
36282
|
+
subgraphs.command("scaffold [contractAddress]").description("Scaffold a defineSubgraph() file from a contract or trait").option("-o, --output <path>", "Output file path (required)").option("-k, --api-key <key>", "Stacks node API key for direct RPC URLs").option("--functions <names>", "Comma-separated public functions to index as typed contract_call tables").option("--trait <std>", "Scaffold a trait-scoped source (sip-009|sip-010|sip-013) — no contract needed").option("--no-install", "Skip bun install after writing package.json").addHelpText("after", `
|
|
36283
|
+
Examples:
|
|
36284
|
+
$ sl subgraphs scaffold SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft -o subgraphs/apes.ts
|
|
36285
|
+
$ sl subgraphs scaffold SP00...token --functions transfer,mint -o subgraphs/token.ts
|
|
36286
|
+
$ sl subgraphs scaffold --trait sip-010 -o subgraphs/all-ft.ts`).action(async (contractAddress, options2) => {
|
|
36509
36287
|
try {
|
|
36510
36288
|
if (!options2.output) {
|
|
36511
36289
|
error("--output <path> is required");
|
|
@@ -36564,7 +36342,7 @@ ${rows.length} row(s)`));
|
|
|
36564
36342
|
process.exit(1);
|
|
36565
36343
|
}
|
|
36566
36344
|
});
|
|
36567
|
-
subgraphs.command("client <subgraphName>").
|
|
36345
|
+
subgraphs.command("client <subgraphName>").description("Generate a typed query client for a deployed subgraph").option("-o, --output <path>", "Output file path (required)").action(async (subgraphName, options2) => {
|
|
36568
36346
|
try {
|
|
36569
36347
|
if (!options2.output) {
|
|
36570
36348
|
error("--output <path> is required");
|
|
@@ -36585,187 +36363,9 @@ ${rows.length} row(s)`));
|
|
|
36585
36363
|
}
|
|
36586
36364
|
});
|
|
36587
36365
|
}
|
|
36588
|
-
// src/commands/stack.ts
|
|
36589
|
-
init_config();
|
|
36590
|
-
init_dev_state();
|
|
36591
|
-
init_docker();
|
|
36592
|
-
init_network();
|
|
36593
|
-
init_node_manager();
|
|
36594
|
-
init_output();
|
|
36595
|
-
function registerStackCommand(program2) {
|
|
36596
|
-
const stack = program2.command("stack").description("Manage the full stack");
|
|
36597
|
-
stack.command("start").description("Start the full stack (node + dev services)").option("--no-node", "Skip starting the Stacks node").option("--no-dev", "Skip starting dev services").option("--network <network>", "Override network (mainnet|testnet)").hook("preAction", async () => {
|
|
36598
|
-
await requireLocalNetwork();
|
|
36599
|
-
}).action(async (options2) => {
|
|
36600
|
-
await stackStart(options2);
|
|
36601
|
-
});
|
|
36602
|
-
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 () => {
|
|
36603
|
-
await requireLocalNetwork();
|
|
36604
|
-
}).action(async (options2) => {
|
|
36605
|
-
await stackStop(options2);
|
|
36606
|
-
});
|
|
36607
|
-
stack.command("restart").description("Restart the full stack").option("--no-node", "Skip restarting the Stacks node").option("--no-dev", "Skip restarting dev services").hook("preAction", async () => {
|
|
36608
|
-
await requireLocalNetwork();
|
|
36609
|
-
}).action(async (options2) => {
|
|
36610
|
-
await stackStop({ ...options2, wait: false });
|
|
36611
|
-
await stackStart(options2);
|
|
36612
|
-
});
|
|
36613
|
-
}
|
|
36614
|
-
async function stackStart(options2) {
|
|
36615
|
-
const config = await loadConfig();
|
|
36616
|
-
try {
|
|
36617
|
-
await requireDocker();
|
|
36618
|
-
} catch (err) {
|
|
36619
|
-
if (err instanceof DockerNotAvailableError) {
|
|
36620
|
-
error(err.message);
|
|
36621
|
-
process.exit(1);
|
|
36622
|
-
}
|
|
36623
|
-
throw err;
|
|
36624
|
-
}
|
|
36625
|
-
const network = options2.network ?? config.node?.network ?? "mainnet";
|
|
36626
|
-
const validation = await validateNetworkConsistency(config);
|
|
36627
|
-
if (!validation.valid) {
|
|
36628
|
-
error("Network mismatch detected:");
|
|
36629
|
-
for (const issue of validation.issues) {
|
|
36630
|
-
console.log(red(` - ${issue}`));
|
|
36631
|
-
}
|
|
36632
|
-
console.log("");
|
|
36633
|
-
console.log(dim("Fix your config or stop mismatched containers first."));
|
|
36634
|
-
process.exit(1);
|
|
36635
|
-
}
|
|
36636
|
-
console.log("");
|
|
36637
|
-
console.log(blue("Starting Secondlayer Stack"));
|
|
36638
|
-
console.log(dim(` Network: ${network}`));
|
|
36639
|
-
console.log("");
|
|
36640
|
-
if (options2.node) {
|
|
36641
|
-
const nodePath = config.node?.installPath;
|
|
36642
|
-
if (!nodePath) {
|
|
36643
|
-
warn("No node configured, skipping. Run 'sl local node setup' to configure.");
|
|
36644
|
-
} else if (await isNodeRunning()) {
|
|
36645
|
-
info("Node already running");
|
|
36646
|
-
} else {
|
|
36647
|
-
info("Starting Stacks node...");
|
|
36648
|
-
const started = await startNodeContainers(nodePath, network);
|
|
36649
|
-
if (!started) {
|
|
36650
|
-
error("Failed to start node containers");
|
|
36651
|
-
process.exit(1);
|
|
36652
|
-
}
|
|
36653
|
-
success("Node containers started");
|
|
36654
|
-
info("Waiting for node RPC...");
|
|
36655
|
-
let rpcReady = false;
|
|
36656
|
-
for (let i = 0;i < 60; i++) {
|
|
36657
|
-
try {
|
|
36658
|
-
const res = await fetch("http://localhost:20443/v2/info", {
|
|
36659
|
-
signal: AbortSignal.timeout(2000)
|
|
36660
|
-
});
|
|
36661
|
-
if (res.ok) {
|
|
36662
|
-
rpcReady = true;
|
|
36663
|
-
break;
|
|
36664
|
-
}
|
|
36665
|
-
} catch {}
|
|
36666
|
-
await Bun.sleep(1000);
|
|
36667
|
-
}
|
|
36668
|
-
if (rpcReady) {
|
|
36669
|
-
success("Node RPC responsive");
|
|
36670
|
-
const postValidation = await validateNetworkConsistency(config);
|
|
36671
|
-
if (!postValidation.valid) {
|
|
36672
|
-
warn("Post-start chain ID mismatch:");
|
|
36673
|
-
for (const issue of postValidation.issues) {
|
|
36674
|
-
console.log(yellow(` - ${issue}`));
|
|
36675
|
-
}
|
|
36676
|
-
}
|
|
36677
|
-
} else {
|
|
36678
|
-
warn("Node RPC not responsive after 60s (may still be starting)");
|
|
36679
|
-
}
|
|
36680
|
-
}
|
|
36681
|
-
console.log("");
|
|
36682
|
-
}
|
|
36683
|
-
if (options2.dev) {
|
|
36684
|
-
if (await isDevRunning()) {
|
|
36685
|
-
info("Dev services already running");
|
|
36686
|
-
} else {
|
|
36687
|
-
const args = [
|
|
36688
|
-
"bun",
|
|
36689
|
-
"run",
|
|
36690
|
-
`${import.meta.dir}/../../bin/secondlayer.ts`,
|
|
36691
|
-
"dev",
|
|
36692
|
-
"start"
|
|
36693
|
-
];
|
|
36694
|
-
if (config.node?.installPath) {
|
|
36695
|
-
args.push("--stacks-node");
|
|
36696
|
-
}
|
|
36697
|
-
info("Starting dev services...");
|
|
36698
|
-
const proc = Bun.spawn(args, {
|
|
36699
|
-
stdin: "inherit",
|
|
36700
|
-
stdout: "inherit",
|
|
36701
|
-
stderr: "inherit"
|
|
36702
|
-
});
|
|
36703
|
-
await proc.exited;
|
|
36704
|
-
}
|
|
36705
|
-
}
|
|
36706
|
-
console.log("");
|
|
36707
|
-
success("Stack started");
|
|
36708
|
-
console.log(dim("Run 'sl status' to check health"));
|
|
36709
|
-
console.log("");
|
|
36710
|
-
}
|
|
36711
|
-
async function stackStop(options2) {
|
|
36712
|
-
console.log("");
|
|
36713
|
-
info("Stopping Secondlayer Stack...");
|
|
36714
|
-
if (options2.dev) {
|
|
36715
|
-
if (await isDevRunning()) {
|
|
36716
|
-
info("Stopping dev services...");
|
|
36717
|
-
const proc = Bun.spawn([
|
|
36718
|
-
"bun",
|
|
36719
|
-
"run",
|
|
36720
|
-
`${import.meta.dir}/../../bin/secondlayer.ts`,
|
|
36721
|
-
"dev",
|
|
36722
|
-
"stop"
|
|
36723
|
-
], { stdin: "inherit", stdout: "inherit", stderr: "inherit" });
|
|
36724
|
-
await proc.exited;
|
|
36725
|
-
} else {
|
|
36726
|
-
info("Dev services not running");
|
|
36727
|
-
}
|
|
36728
|
-
}
|
|
36729
|
-
if (options2.node) {
|
|
36730
|
-
if (await isNodeRunning()) {
|
|
36731
|
-
info("Stopping node containers...");
|
|
36732
|
-
const stopped = await stopNodeContainers();
|
|
36733
|
-
if (stopped.length > 0) {
|
|
36734
|
-
success(`Stopped: ${stopped.join(", ")}`);
|
|
36735
|
-
}
|
|
36736
|
-
} else {
|
|
36737
|
-
info("Node not running");
|
|
36738
|
-
}
|
|
36739
|
-
}
|
|
36740
|
-
try {
|
|
36741
|
-
const result = await Bun.$`docker ps -a --format json --filter "name=secondlayer-dev" --filter "name=stacks"`.quiet().nothrow();
|
|
36742
|
-
if (result.exitCode === 0) {
|
|
36743
|
-
const lines = result.stdout.toString().trim().split(`
|
|
36744
|
-
`).filter(Boolean);
|
|
36745
|
-
const orphans = [];
|
|
36746
|
-
for (const line of lines) {
|
|
36747
|
-
try {
|
|
36748
|
-
const c = JSON.parse(line);
|
|
36749
|
-
const name = c.Names || c.Name;
|
|
36750
|
-
if (name && c.Status?.includes("Exited")) {
|
|
36751
|
-
orphans.push(name);
|
|
36752
|
-
}
|
|
36753
|
-
} catch {}
|
|
36754
|
-
}
|
|
36755
|
-
if (orphans.length > 0) {
|
|
36756
|
-
info(`Cleaning up ${orphans.length} orphaned container(s)...`);
|
|
36757
|
-
for (const name of orphans) {
|
|
36758
|
-
await Bun.$`docker rm ${name}`.quiet().nothrow();
|
|
36759
|
-
}
|
|
36760
|
-
}
|
|
36761
|
-
}
|
|
36762
|
-
} catch {}
|
|
36763
|
-
console.log("");
|
|
36764
|
-
success("Stack stopped");
|
|
36765
|
-
console.log("");
|
|
36766
|
-
}
|
|
36767
36366
|
// src/commands/streams.ts
|
|
36768
36367
|
init_output();
|
|
36368
|
+
init_resolve_auth();
|
|
36769
36369
|
import { createStreamsClient } from "@secondlayer/sdk";
|
|
36770
36370
|
var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
|
|
36771
36371
|
var VALID_TYPES = [
|
|
@@ -36782,9 +36382,9 @@ var VALID_TYPES = [
|
|
|
36782
36382
|
"print"
|
|
36783
36383
|
];
|
|
36784
36384
|
function readApiKey() {
|
|
36785
|
-
const key =
|
|
36385
|
+
const key = resolveEnvKey();
|
|
36786
36386
|
if (!key) {
|
|
36787
|
-
error("
|
|
36387
|
+
error("No API key set. Export SL_API_KEY (issue one at https://www.secondlayer.tools/platform/api-keys).");
|
|
36788
36388
|
process.exit(1);
|
|
36789
36389
|
}
|
|
36790
36390
|
return key;
|
|
@@ -36825,40 +36425,45 @@ function parseHeight(value, name) {
|
|
|
36825
36425
|
return n;
|
|
36826
36426
|
}
|
|
36827
36427
|
function registerStreamsCommand(program2) {
|
|
36828
|
-
const streams = program2.command("streams").description("Read raw chain events from Streams (requires
|
|
36428
|
+
const streams = program2.command("streams").description("Read raw chain events from Streams (requires SL_API_KEY)");
|
|
36829
36429
|
streams.command("tip").description("Print current canonical tip").action(async () => {
|
|
36830
36430
|
try {
|
|
36831
36431
|
const tip = await client().tip();
|
|
36832
|
-
|
|
36833
|
-
`);
|
|
36432
|
+
writeData(JSON.stringify(tip, null, 2));
|
|
36834
36433
|
} catch (err) {
|
|
36835
36434
|
error(err instanceof Error ? err.message : String(err));
|
|
36836
36435
|
process.exit(1);
|
|
36837
36436
|
}
|
|
36838
36437
|
});
|
|
36839
|
-
streams.command("events").description("List events (cursor-paginated; one page per call)").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--contract-id <id>", "filter to a single contract identifier").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--from-
|
|
36438
|
+
streams.command("events").description("List events (cursor-paginated; one page per call)").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--contract-id <id>", "filter to a single contract identifier").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--from-block <n>", "filter to blocks >= n").option("--to-block <n>", "filter to blocks <= n").option("--limit <n>", "page size (1-1000, default 100)", "100").addHelpText("after", `
|
|
36439
|
+
Examples:
|
|
36440
|
+
$ sl streams events --types stx_transfer,print --limit 50
|
|
36441
|
+
$ sl streams events --contract-id SP00....token --from-block 150000 --to-block 160000
|
|
36442
|
+
$ sl streams events --cursor 150000:3`).action(async (options2) => {
|
|
36840
36443
|
try {
|
|
36841
36444
|
const envelope = await client().events.list({
|
|
36842
36445
|
types: parseTypes(options2.types),
|
|
36843
36446
|
contractId: options2.contractId,
|
|
36844
36447
|
cursor: options2.cursor,
|
|
36845
|
-
fromHeight: parseHeight(options2.
|
|
36846
|
-
toHeight: parseHeight(options2.
|
|
36448
|
+
fromHeight: parseHeight(options2.fromBlock, "--from-block"),
|
|
36449
|
+
toHeight: parseHeight(options2.toBlock, "--to-block"),
|
|
36847
36450
|
limit: parseLimit(options2.limit)
|
|
36848
36451
|
});
|
|
36849
|
-
|
|
36850
|
-
`);
|
|
36452
|
+
writeData(JSON.stringify(envelope, null, 2));
|
|
36851
36453
|
} catch (err) {
|
|
36852
36454
|
error(err instanceof Error ? err.message : String(err));
|
|
36853
36455
|
process.exit(1);
|
|
36854
36456
|
}
|
|
36855
36457
|
});
|
|
36856
|
-
streams.command("consume").description("Long-running pull from a cursor; emits one event per line (jsonl) until SIGINT or --max-pages").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--contract-id <id>", "filter to a single contract identifier").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--batch-size <n>", "events per batch (1-1000, default 100)", "100").option("--max-pages <n>", "stop after N pages (default: run until SIGINT)").
|
|
36458
|
+
streams.command("consume").description("Long-running pull from a cursor; emits one event per line (jsonl) until SIGINT or --max-pages").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--contract-id <id>", "filter to a single contract identifier").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--batch-size <n>", "events per batch (1-1000, default 100)", "100").option("--max-pages <n>", "stop after N pages (default: run until SIGINT)").addHelpText("after", `
|
|
36459
|
+
Examples:
|
|
36460
|
+
$ sl streams consume --types print --cursor 150000:0
|
|
36461
|
+
$ sl streams consume --types stx_transfer --batch-size 500 --max-pages 10`).action(async (options2) => {
|
|
36857
36462
|
try {
|
|
36858
36463
|
const types6 = parseTypes(options2.types);
|
|
36859
36464
|
const batchSize = parseLimit(options2.batchSize) ?? 100;
|
|
36860
36465
|
const maxPages = options2.maxPages ? Number.parseInt(options2.maxPages, 10) : undefined;
|
|
36861
|
-
|
|
36466
|
+
note("# streaming events to stdout (jsonl); next_cursor printed to stderr");
|
|
36862
36467
|
await client().events.consume({
|
|
36863
36468
|
fromCursor: options2.cursor,
|
|
36864
36469
|
types: types6,
|
|
@@ -36889,8 +36494,7 @@ function registerStreamsCommand(program2) {
|
|
|
36889
36494
|
since: options2.since,
|
|
36890
36495
|
limit: parseLimit(options2.limit)
|
|
36891
36496
|
});
|
|
36892
|
-
|
|
36893
|
-
`);
|
|
36497
|
+
writeData(JSON.stringify(envelope, null, 2));
|
|
36894
36498
|
} catch (err) {
|
|
36895
36499
|
error(err instanceof Error ? err.message : String(err));
|
|
36896
36500
|
process.exit(1);
|
|
@@ -36902,8 +36506,7 @@ function registerStreamsCommand(program2) {
|
|
|
36902
36506
|
if (height === undefined)
|
|
36903
36507
|
throw new Error("<height> is required");
|
|
36904
36508
|
const block = await client().canonical(height);
|
|
36905
|
-
|
|
36906
|
-
`);
|
|
36509
|
+
writeData(JSON.stringify(block, null, 2));
|
|
36907
36510
|
} catch (err) {
|
|
36908
36511
|
error(err instanceof Error ? err.message : String(err));
|
|
36909
36512
|
process.exit(1);
|
|
@@ -36933,14 +36536,17 @@ function registerDatasetsCommand(program2) {
|
|
|
36933
36536
|
datasets.command("list").description("List the dataset catalog + freshness").action(async () => {
|
|
36934
36537
|
try {
|
|
36935
36538
|
const catalog = await client2().listDatasets();
|
|
36936
|
-
|
|
36937
|
-
`);
|
|
36539
|
+
writeData(JSON.stringify(catalog, null, 2));
|
|
36938
36540
|
} catch (err) {
|
|
36939
36541
|
error(`Failed to list datasets: ${err}`);
|
|
36940
36542
|
process.exit(1);
|
|
36941
36543
|
}
|
|
36942
36544
|
});
|
|
36943
|
-
datasets.command("query <dataset>").description(`Query a cursor-paginated dataset (${Object.keys(CURSOR_SLUGS).join(", ")})`).option("--filter <key=value...>", "Filter as key=value (e.g. --filter stacker=SP… --filter address=SP…)").option("--limit <n>", "Rows per page").option("--cursor <cursor>", "Resume token from a previous next_cursor").option("--json", "Print the full envelope as JSON").
|
|
36545
|
+
datasets.command("query <dataset>").description(`Query a cursor-paginated dataset (${Object.keys(CURSOR_SLUGS).join(", ")})`).option("--filter <key=value...>", "Filter as key=value (e.g. --filter stacker=SP… --filter address=SP…)").option("--limit <n>", "Rows per page").option("--cursor <cursor>", "Resume token from a previous next_cursor").option("--json", "Print the full envelope as JSON").addHelpText("after", `
|
|
36546
|
+
Examples:
|
|
36547
|
+
$ sl datasets query stx-transfers --filter sender=SP2J6ZY... --limit 100
|
|
36548
|
+
$ sl datasets query sbtc-events --filter amount.gte=1000
|
|
36549
|
+
$ sl datasets query bns-events --cursor 150000:3 --json`).action(async (dataset, options2) => {
|
|
36944
36550
|
try {
|
|
36945
36551
|
const params = parseFilters(options2.filter);
|
|
36946
36552
|
if (options2.limit)
|
|
@@ -36948,16 +36554,15 @@ function registerDatasetsCommand(program2) {
|
|
|
36948
36554
|
if (options2.cursor)
|
|
36949
36555
|
params.cursor = options2.cursor;
|
|
36950
36556
|
const env = await client2().query(dataset, params);
|
|
36951
|
-
|
|
36952
|
-
|
|
36953
|
-
|
|
36954
|
-
|
|
36955
|
-
|
|
36956
|
-
|
|
36957
|
-
|
|
36958
|
-
info(`next_cursor: ${env.next_cursor}`);
|
|
36557
|
+
output({
|
|
36558
|
+
json: options2.json,
|
|
36559
|
+
data: env,
|
|
36560
|
+
human: () => {
|
|
36561
|
+
writeData(JSON.stringify(env.rows, null, 2));
|
|
36562
|
+
if (env.next_cursor)
|
|
36563
|
+
note(`next_cursor: ${env.next_cursor}`);
|
|
36959
36564
|
}
|
|
36960
|
-
}
|
|
36565
|
+
});
|
|
36961
36566
|
} catch (err) {
|
|
36962
36567
|
error(`Failed to query dataset: ${err}`);
|
|
36963
36568
|
process.exit(1);
|
|
@@ -37315,6 +36920,532 @@ async function runLocalDoctor(jsonOutput) {
|
|
|
37315
36920
|
}
|
|
37316
36921
|
// src/commands/local.ts
|
|
37317
36922
|
init_config();
|
|
36923
|
+
|
|
36924
|
+
// src/commands/db.ts
|
|
36925
|
+
init_config();
|
|
36926
|
+
init_dev_state();
|
|
36927
|
+
init_output();
|
|
36928
|
+
import { confirm as confirm4 } from "@inquirer/prompts";
|
|
36929
|
+
import { getDb, sql } from "@secondlayer/shared/db";
|
|
36930
|
+
import {
|
|
36931
|
+
countMissingBlocks,
|
|
36932
|
+
findGaps
|
|
36933
|
+
} from "@secondlayer/shared/db/queries/integrity";
|
|
36934
|
+
import { StacksNodeClient } from "@secondlayer/shared/node";
|
|
36935
|
+
var DEV_DATABASE_URL = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
|
|
36936
|
+
function addDbCommand(parent) {
|
|
36937
|
+
const dbCmd = parent.command("db").description("Inspect indexer database tables").addHelpText("after", `
|
|
36938
|
+
Subcommands:
|
|
36939
|
+
blocks Show recent blocks
|
|
36940
|
+
txs Show recent transactions
|
|
36941
|
+
events Show recent events
|
|
36942
|
+
gaps Show gaps in indexed block data
|
|
36943
|
+
truncate Truncate all indexed data
|
|
36944
|
+
resync Reset database and restart indexer
|
|
36945
|
+
|
|
36946
|
+
Run \`sl db\` with no subcommand to print an overview.`).hook("preAction", async () => {
|
|
36947
|
+
await requireLocalNetwork();
|
|
36948
|
+
}).action(async () => {
|
|
36949
|
+
await showOverview(10);
|
|
36950
|
+
});
|
|
36951
|
+
dbCmd.command("blocks").description("Show recent blocks").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
|
|
36952
|
+
const opts = this.opts();
|
|
36953
|
+
await showBlocks(Number.parseInt(opts.limit), opts.json);
|
|
36954
|
+
});
|
|
36955
|
+
dbCmd.command("txs").description("Show recent transactions").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
|
|
36956
|
+
const opts = this.opts();
|
|
36957
|
+
await showTransactions(Number.parseInt(opts.limit), opts.json);
|
|
36958
|
+
});
|
|
36959
|
+
dbCmd.command("events").description("Show recent events").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
|
|
36960
|
+
const opts = this.opts();
|
|
36961
|
+
await showEvents(Number.parseInt(opts.limit), opts.json);
|
|
36962
|
+
});
|
|
36963
|
+
dbCmd.command("gaps").description("Show gaps in indexed block data").option("--limit <n>", "Number of gaps to show", "50").option("--json", "Output as JSON").action(async function() {
|
|
36964
|
+
const opts = this.opts();
|
|
36965
|
+
await showGaps(Number.parseInt(opts.limit), opts.json);
|
|
36966
|
+
});
|
|
36967
|
+
dbCmd.command("truncate").description("Truncate all indexed data (blocks, txs, events)").option("-y, --yes", "Skip confirmation prompt").action(async function() {
|
|
36968
|
+
const opts = this.opts();
|
|
36969
|
+
await resetDatabase(opts.yes);
|
|
36970
|
+
});
|
|
36971
|
+
dbCmd.command("resync").description("Reset database and restart indexer for fresh sync").option("-y, --yes", "Skip confirmation prompt").option("--backfill", "After reset, fetch all blocks from node").action(async function() {
|
|
36972
|
+
const opts = this.opts();
|
|
36973
|
+
await resyncDatabase(opts.yes, opts.backfill);
|
|
36974
|
+
});
|
|
36975
|
+
}
|
|
36976
|
+
function ensureDb() {
|
|
36977
|
+
if (!process.env.DATABASE_URL) {
|
|
36978
|
+
process.env.DATABASE_URL = DEV_DATABASE_URL;
|
|
36979
|
+
}
|
|
36980
|
+
return getDb();
|
|
36981
|
+
}
|
|
36982
|
+
async function showOverview(_limit) {
|
|
36983
|
+
try {
|
|
36984
|
+
const db = ensureDb();
|
|
36985
|
+
const blockCountResult = await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst();
|
|
36986
|
+
const txCountResult = await db.selectFrom("transactions").select(sql`count(*)`.as("count")).executeTakeFirst();
|
|
36987
|
+
const eventCountResult = await db.selectFrom("events").select(sql`count(*)`.as("count")).executeTakeFirst();
|
|
36988
|
+
const blockCount = blockCountResult?.count ?? 0;
|
|
36989
|
+
const txCount = txCountResult?.count ?? 0;
|
|
36990
|
+
const eventCount = eventCountResult?.count ?? 0;
|
|
36991
|
+
const latest = await db.selectFrom("blocks").select(["height", "hash", "timestamp"]).orderBy("height", "desc").limit(1).executeTakeFirst();
|
|
36992
|
+
console.log("");
|
|
36993
|
+
console.log(blue("Database Overview"));
|
|
36994
|
+
console.log("");
|
|
36995
|
+
console.log(` Blocks: ${green(blockCount.toString())}`);
|
|
36996
|
+
console.log(` Transactions: ${green(txCount.toString())}`);
|
|
36997
|
+
console.log(` Events: ${green(eventCount.toString())}`);
|
|
36998
|
+
console.log("");
|
|
36999
|
+
if (latest) {
|
|
37000
|
+
const time = new Date(latest.timestamp * 1000).toISOString();
|
|
37001
|
+
console.log(blue("Latest Block"));
|
|
37002
|
+
console.log(` Height: ${latest.height}`);
|
|
37003
|
+
console.log(` Hash: ${dim(latest.hash.slice(0, 20))}...`);
|
|
37004
|
+
console.log(` Time: ${time}`);
|
|
37005
|
+
console.log("");
|
|
37006
|
+
}
|
|
37007
|
+
console.log(dim(`Use 'sl db blocks|txs|events' to see records`));
|
|
37008
|
+
console.log("");
|
|
37009
|
+
process.exit(0);
|
|
37010
|
+
} catch (err) {
|
|
37011
|
+
error(`Failed to query database: ${err}`);
|
|
37012
|
+
console.log(dim(`
|
|
37013
|
+
Make sure PostgreSQL is running.`));
|
|
37014
|
+
console.log(dim("Run 'sl local start' to start all services."));
|
|
37015
|
+
process.exit(1);
|
|
37016
|
+
}
|
|
37017
|
+
}
|
|
37018
|
+
async function showBlocks(limit, json) {
|
|
37019
|
+
try {
|
|
37020
|
+
const db = ensureDb();
|
|
37021
|
+
const rows = await db.selectFrom("blocks").select(["height", "hash", "timestamp", "canonical"]).orderBy("height", "desc").limit(limit).execute();
|
|
37022
|
+
if (json) {
|
|
37023
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
37024
|
+
process.exit(0);
|
|
37025
|
+
}
|
|
37026
|
+
console.log("");
|
|
37027
|
+
console.log(blue(`Recent Blocks (${rows.length})`));
|
|
37028
|
+
console.log("");
|
|
37029
|
+
console.log(dim(" HEIGHT".padEnd(10)) + dim("HASH".padEnd(24)) + dim("TIME"));
|
|
37030
|
+
for (const row of rows) {
|
|
37031
|
+
const time = new Date(row.timestamp * 1000).toLocaleTimeString();
|
|
37032
|
+
const canonicalMark = row.canonical ? "" : yellow(" (reorg)");
|
|
37033
|
+
console.log(` ${row.height.toString().padEnd(10)}${`${row.hash.slice(0, 20)}... `.padEnd(24)}${time}${canonicalMark}`);
|
|
37034
|
+
}
|
|
37035
|
+
console.log("");
|
|
37036
|
+
process.exit(0);
|
|
37037
|
+
} catch (err) {
|
|
37038
|
+
error(`Failed to query blocks: ${err}`);
|
|
37039
|
+
process.exit(1);
|
|
37040
|
+
}
|
|
37041
|
+
}
|
|
37042
|
+
async function showTransactions(limit, json) {
|
|
37043
|
+
try {
|
|
37044
|
+
const db = ensureDb();
|
|
37045
|
+
const rows = await db.selectFrom("transactions").select([
|
|
37046
|
+
"tx_id",
|
|
37047
|
+
"block_height",
|
|
37048
|
+
"type",
|
|
37049
|
+
"sender",
|
|
37050
|
+
"status",
|
|
37051
|
+
"contract_id",
|
|
37052
|
+
"function_name"
|
|
37053
|
+
]).orderBy("block_height", "desc").limit(limit).execute();
|
|
37054
|
+
if (json) {
|
|
37055
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
37056
|
+
process.exit(0);
|
|
37057
|
+
}
|
|
37058
|
+
console.log("");
|
|
37059
|
+
console.log(blue(`Recent Transactions (${rows.length})`));
|
|
37060
|
+
console.log("");
|
|
37061
|
+
console.log(dim(" BLOCK".padEnd(8)) + dim("TYPE".padEnd(18)) + dim("SENDER".padEnd(20)) + dim("CONTRACT/FUNCTION"));
|
|
37062
|
+
for (const row of rows) {
|
|
37063
|
+
const statusColor = row.status === "success" ? green : yellow;
|
|
37064
|
+
const contractInfo = row.contract_id ? `${row.contract_id.split(".")[1] || row.contract_id}${row.function_name ? `::${row.function_name}` : ""}` : "-";
|
|
37065
|
+
console.log(` ${statusColor(row.block_height.toString().padEnd(8))}${row.type.padEnd(18)}${`${row.sender.slice(0, 18)}... `.padEnd(20)}${contractInfo}`);
|
|
37066
|
+
}
|
|
37067
|
+
console.log("");
|
|
37068
|
+
process.exit(0);
|
|
37069
|
+
} catch (err) {
|
|
37070
|
+
error(`Failed to query transactions: ${err}`);
|
|
37071
|
+
process.exit(1);
|
|
37072
|
+
}
|
|
37073
|
+
}
|
|
37074
|
+
async function showEvents(limit, json) {
|
|
37075
|
+
try {
|
|
37076
|
+
const db = ensureDb();
|
|
37077
|
+
const rows = await db.selectFrom("events").select(["block_height", "tx_id", "event_index", "type", "data"]).orderBy("block_height", "desc").limit(limit).execute();
|
|
37078
|
+
if (json) {
|
|
37079
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
37080
|
+
process.exit(0);
|
|
37081
|
+
}
|
|
37082
|
+
console.log("");
|
|
37083
|
+
console.log(blue(`Recent Events (${rows.length})`));
|
|
37084
|
+
console.log("");
|
|
37085
|
+
if (rows.length === 0) {
|
|
37086
|
+
console.log(dim(" No events found"));
|
|
37087
|
+
console.log("");
|
|
37088
|
+
process.exit(0);
|
|
37089
|
+
}
|
|
37090
|
+
console.log(dim(" BLOCK".padEnd(8)) + dim("INDEX".padEnd(8)) + dim("TYPE".padEnd(24)) + dim("TX"));
|
|
37091
|
+
for (const row of rows) {
|
|
37092
|
+
console.log(` ${row.block_height.toString().padEnd(8)}` + `${row.event_index.toString().padEnd(8)}` + `${row.type.padEnd(24)}` + `${row.tx_id.slice(0, 16)}...`);
|
|
37093
|
+
}
|
|
37094
|
+
console.log("");
|
|
37095
|
+
process.exit(0);
|
|
37096
|
+
} catch (err) {
|
|
37097
|
+
error(`Failed to query events: ${err}`);
|
|
37098
|
+
process.exit(1);
|
|
37099
|
+
}
|
|
37100
|
+
}
|
|
37101
|
+
async function showGaps(limit, json) {
|
|
37102
|
+
try {
|
|
37103
|
+
const db = ensureDb();
|
|
37104
|
+
const gaps = await findGaps(db, limit);
|
|
37105
|
+
const missing = await countMissingBlocks(db);
|
|
37106
|
+
if (json) {
|
|
37107
|
+
console.log(JSON.stringify({ gaps, totalMissingBlocks: missing }, null, 2));
|
|
37108
|
+
process.exit(0);
|
|
37109
|
+
}
|
|
37110
|
+
console.log("");
|
|
37111
|
+
if (gaps.length === 0) {
|
|
37112
|
+
console.log(green("No gaps detected — block data is contiguous"));
|
|
37113
|
+
console.log("");
|
|
37114
|
+
process.exit(0);
|
|
37115
|
+
}
|
|
37116
|
+
console.log(blue(`Block Gaps (${gaps.length})`));
|
|
37117
|
+
console.log("");
|
|
37118
|
+
console.log(dim(" GAP_START".padEnd(14)) + dim("GAP_END".padEnd(14)) + dim("SIZE"));
|
|
37119
|
+
for (const gap of gaps) {
|
|
37120
|
+
console.log(` ${gap.gapStart.toString().padEnd(14)}` + `${gap.gapEnd.toString().padEnd(14)}` + `${gap.size}`);
|
|
37121
|
+
}
|
|
37122
|
+
console.log("");
|
|
37123
|
+
console.log(`${yellow(gaps.length.toString())} gaps, ${red(missing.toString())} missing blocks`);
|
|
37124
|
+
console.log("");
|
|
37125
|
+
process.exit(0);
|
|
37126
|
+
} catch (err) {
|
|
37127
|
+
error(`Failed to query gaps: ${err}`);
|
|
37128
|
+
process.exit(1);
|
|
37129
|
+
}
|
|
37130
|
+
}
|
|
37131
|
+
async function resetDatabase(skipConfirm) {
|
|
37132
|
+
try {
|
|
37133
|
+
const db = ensureDb();
|
|
37134
|
+
const blockCount = (await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
|
|
37135
|
+
const txCount = (await db.selectFrom("transactions").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
|
|
37136
|
+
const eventCount = (await db.selectFrom("events").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
|
|
37137
|
+
console.log("");
|
|
37138
|
+
console.log(yellow("This will delete all indexed blockchain data:"));
|
|
37139
|
+
console.log("");
|
|
37140
|
+
console.log(` ${red(blockCount.toString())} blocks`);
|
|
37141
|
+
console.log(` ${red(txCount.toString())} transactions`);
|
|
37142
|
+
console.log(` ${red(eventCount.toString())} events`);
|
|
37143
|
+
console.log(` ${dim("+ index_progress")}`);
|
|
37144
|
+
console.log("");
|
|
37145
|
+
console.log(dim("Note: Subgraph configurations will be preserved."));
|
|
37146
|
+
console.log("");
|
|
37147
|
+
if (!skipConfirm) {
|
|
37148
|
+
const confirmed = await confirm4({
|
|
37149
|
+
message: "Are you sure you want to reset the database?",
|
|
37150
|
+
default: false
|
|
37151
|
+
});
|
|
37152
|
+
if (!confirmed) {
|
|
37153
|
+
info("Cancelled");
|
|
37154
|
+
process.exit(0);
|
|
37155
|
+
}
|
|
37156
|
+
}
|
|
37157
|
+
info("Truncating tables...");
|
|
37158
|
+
await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
|
|
37159
|
+
console.log("");
|
|
37160
|
+
success("Database reset complete");
|
|
37161
|
+
console.log("");
|
|
37162
|
+
console.log(dim("Run 'sl local restart' to restart the indexer for fresh sync."));
|
|
37163
|
+
console.log("");
|
|
37164
|
+
process.exit(0);
|
|
37165
|
+
} catch (err) {
|
|
37166
|
+
error(`Failed to reset database: ${err}`);
|
|
37167
|
+
process.exit(1);
|
|
37168
|
+
}
|
|
37169
|
+
}
|
|
37170
|
+
async function resyncDatabase(skipConfirm, backfill) {
|
|
37171
|
+
try {
|
|
37172
|
+
const db = ensureDb();
|
|
37173
|
+
const blockCount = (await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
|
|
37174
|
+
console.log("");
|
|
37175
|
+
console.log(yellow("This will:"));
|
|
37176
|
+
console.log(` 1. Delete all indexed data (${red(blockCount.toString())} blocks)`);
|
|
37177
|
+
console.log(" 2. Restart the indexer for fresh sync");
|
|
37178
|
+
if (backfill) {
|
|
37179
|
+
console.log(" 3. Fetch all blocks from node (backfill)");
|
|
37180
|
+
}
|
|
37181
|
+
console.log("");
|
|
37182
|
+
console.log(dim("Note: Subgraph configurations will be preserved."));
|
|
37183
|
+
console.log("");
|
|
37184
|
+
if (!skipConfirm) {
|
|
37185
|
+
const confirmed = await confirm4({
|
|
37186
|
+
message: "Are you sure you want to resync?",
|
|
37187
|
+
default: false
|
|
37188
|
+
});
|
|
37189
|
+
if (!confirmed) {
|
|
37190
|
+
info("Cancelled");
|
|
37191
|
+
process.exit(0);
|
|
37192
|
+
}
|
|
37193
|
+
}
|
|
37194
|
+
info("Truncating tables...");
|
|
37195
|
+
await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
|
|
37196
|
+
console.log(green(" ✓ Database reset"));
|
|
37197
|
+
const state = await loadDevState();
|
|
37198
|
+
if (state?.services?.indexer && isProcessRunning(state.services.indexer.pid)) {
|
|
37199
|
+
info("Restarting indexer...");
|
|
37200
|
+
try {
|
|
37201
|
+
process.kill(state.services.indexer.pid, "SIGTERM");
|
|
37202
|
+
await Bun.sleep(1000);
|
|
37203
|
+
} catch {}
|
|
37204
|
+
if (isProcessRunning(state.services.indexer.pid)) {
|
|
37205
|
+
try {
|
|
37206
|
+
process.kill(state.services.indexer.pid, "SIGKILL");
|
|
37207
|
+
} catch {}
|
|
37208
|
+
}
|
|
37209
|
+
console.log(green(" ✓ Indexer stopped"));
|
|
37210
|
+
console.log("");
|
|
37211
|
+
info("Run 'sl local restart' to start fresh sync");
|
|
37212
|
+
} else {
|
|
37213
|
+
console.log("");
|
|
37214
|
+
success("Database reset complete");
|
|
37215
|
+
console.log("");
|
|
37216
|
+
if (!backfill) {
|
|
37217
|
+
console.log(dim("Indexer not running. Start with 'sl local start' to begin sync."));
|
|
37218
|
+
}
|
|
37219
|
+
}
|
|
37220
|
+
if (backfill) {
|
|
37221
|
+
console.log("");
|
|
37222
|
+
info("Starting backfill from node...");
|
|
37223
|
+
const nodeClient = new StacksNodeClient;
|
|
37224
|
+
const healthy = await nodeClient.isHealthy();
|
|
37225
|
+
if (!healthy) {
|
|
37226
|
+
warn(`Cannot reach Stacks node at ${nodeClient.getRpcUrl()}`);
|
|
37227
|
+
console.log(dim("Run 'sl sync --from 1 --to <tip>' manually once the node is available."));
|
|
37228
|
+
console.log("");
|
|
37229
|
+
process.exit(0);
|
|
37230
|
+
}
|
|
37231
|
+
const nodeInfo = await nodeClient.getInfo();
|
|
37232
|
+
const tip = nodeInfo.stacks_tip_height;
|
|
37233
|
+
info(`Node tip: block ${tip}. Fetching blocks 1 to ${tip}...`);
|
|
37234
|
+
console.log(dim(`This may take a while. Run 'sl sync --from 1 --to ${tip}' if interrupted.`));
|
|
37235
|
+
console.log("");
|
|
37236
|
+
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
37237
|
+
const config = await loadConfig2();
|
|
37238
|
+
const indexerUrl = process.env.INDEXER_URL || `http://localhost:${config.ports.indexer}`;
|
|
37239
|
+
const concurrency = 5;
|
|
37240
|
+
let fetched = 0;
|
|
37241
|
+
let errors2 = 0;
|
|
37242
|
+
for (let i = 1;i <= tip; i += concurrency) {
|
|
37243
|
+
const batch = [];
|
|
37244
|
+
for (let j = i;j < i + concurrency && j <= tip; j++) {
|
|
37245
|
+
batch.push(j);
|
|
37246
|
+
}
|
|
37247
|
+
const results = await Promise.allSettled(batch.map(async (height) => {
|
|
37248
|
+
const block = await nodeClient.getBlock(height);
|
|
37249
|
+
if (!block)
|
|
37250
|
+
throw new Error(`Block ${height} not found`);
|
|
37251
|
+
const res = await fetch(`${indexerUrl}/new_block`, {
|
|
37252
|
+
method: "POST",
|
|
37253
|
+
headers: {
|
|
37254
|
+
"Content-Type": "application/json",
|
|
37255
|
+
"X-Source": "backfill"
|
|
37256
|
+
},
|
|
37257
|
+
body: JSON.stringify(block)
|
|
37258
|
+
});
|
|
37259
|
+
if (!res.ok)
|
|
37260
|
+
throw new Error(`Indexer rejected block ${height}: ${res.status}`);
|
|
37261
|
+
}));
|
|
37262
|
+
for (const r of results) {
|
|
37263
|
+
if (r.status === "fulfilled")
|
|
37264
|
+
fetched++;
|
|
37265
|
+
else
|
|
37266
|
+
errors2++;
|
|
37267
|
+
}
|
|
37268
|
+
const pct = Math.round((fetched + errors2) / tip * 100);
|
|
37269
|
+
process.stdout.write(`\r ${green(`${fetched}`)} fetched, ${errors2 > 0 ? red(`${errors2} errors`) : "0 errors"} (${pct}%)`);
|
|
37270
|
+
}
|
|
37271
|
+
console.log("");
|
|
37272
|
+
console.log("");
|
|
37273
|
+
if (errors2 === 0) {
|
|
37274
|
+
success(`Backfill complete: ${fetched} blocks indexed`);
|
|
37275
|
+
} else {
|
|
37276
|
+
warn(`Backfill complete: ${fetched} indexed, ${errors2} errors`);
|
|
37277
|
+
}
|
|
37278
|
+
}
|
|
37279
|
+
console.log("");
|
|
37280
|
+
process.exit(0);
|
|
37281
|
+
} catch (err) {
|
|
37282
|
+
error(`Failed to resync: ${err}`);
|
|
37283
|
+
process.exit(1);
|
|
37284
|
+
}
|
|
37285
|
+
}
|
|
37286
|
+
|
|
37287
|
+
// src/commands/stack.ts
|
|
37288
|
+
init_config();
|
|
37289
|
+
init_dev_state();
|
|
37290
|
+
init_docker();
|
|
37291
|
+
init_network();
|
|
37292
|
+
init_node_manager();
|
|
37293
|
+
init_output();
|
|
37294
|
+
async function stackStart(options2) {
|
|
37295
|
+
const config = await loadConfig();
|
|
37296
|
+
try {
|
|
37297
|
+
await requireDocker();
|
|
37298
|
+
} catch (err) {
|
|
37299
|
+
if (err instanceof DockerNotAvailableError) {
|
|
37300
|
+
error(err.message);
|
|
37301
|
+
process.exit(1);
|
|
37302
|
+
}
|
|
37303
|
+
throw err;
|
|
37304
|
+
}
|
|
37305
|
+
const network = process.env.STACKS_NETWORK ?? config.node?.network ?? "mainnet";
|
|
37306
|
+
const validation = await validateNetworkConsistency(config);
|
|
37307
|
+
if (!validation.valid) {
|
|
37308
|
+
error("Network mismatch detected:");
|
|
37309
|
+
for (const issue of validation.issues) {
|
|
37310
|
+
console.log(red(` - ${issue}`));
|
|
37311
|
+
}
|
|
37312
|
+
console.log("");
|
|
37313
|
+
console.log(dim("Fix your config or stop mismatched containers first."));
|
|
37314
|
+
process.exit(1);
|
|
37315
|
+
}
|
|
37316
|
+
console.log("");
|
|
37317
|
+
console.log(blue("Starting Secondlayer Stack"));
|
|
37318
|
+
console.log(dim(` Network: ${network}`));
|
|
37319
|
+
console.log("");
|
|
37320
|
+
if (options2.node) {
|
|
37321
|
+
const nodePath = config.node?.installPath;
|
|
37322
|
+
if (!nodePath) {
|
|
37323
|
+
warn("No node configured, skipping. Run 'sl local node setup' to configure.");
|
|
37324
|
+
} else if (await isNodeRunning()) {
|
|
37325
|
+
info("Node already running");
|
|
37326
|
+
} else {
|
|
37327
|
+
info("Starting Stacks node...");
|
|
37328
|
+
const started = await startNodeContainers(nodePath, network);
|
|
37329
|
+
if (!started) {
|
|
37330
|
+
error("Failed to start node containers");
|
|
37331
|
+
process.exit(1);
|
|
37332
|
+
}
|
|
37333
|
+
success("Node containers started");
|
|
37334
|
+
info("Waiting for node RPC...");
|
|
37335
|
+
let rpcReady = false;
|
|
37336
|
+
for (let i = 0;i < 60; i++) {
|
|
37337
|
+
try {
|
|
37338
|
+
const res = await fetch("http://localhost:20443/v2/info", {
|
|
37339
|
+
signal: AbortSignal.timeout(2000)
|
|
37340
|
+
});
|
|
37341
|
+
if (res.ok) {
|
|
37342
|
+
rpcReady = true;
|
|
37343
|
+
break;
|
|
37344
|
+
}
|
|
37345
|
+
} catch {}
|
|
37346
|
+
await Bun.sleep(1000);
|
|
37347
|
+
}
|
|
37348
|
+
if (rpcReady) {
|
|
37349
|
+
success("Node RPC responsive");
|
|
37350
|
+
const postValidation = await validateNetworkConsistency(config);
|
|
37351
|
+
if (!postValidation.valid) {
|
|
37352
|
+
warn("Post-start chain ID mismatch:");
|
|
37353
|
+
for (const issue of postValidation.issues) {
|
|
37354
|
+
console.log(yellow(` - ${issue}`));
|
|
37355
|
+
}
|
|
37356
|
+
}
|
|
37357
|
+
} else {
|
|
37358
|
+
warn("Node RPC not responsive after 60s (may still be starting)");
|
|
37359
|
+
}
|
|
37360
|
+
}
|
|
37361
|
+
console.log("");
|
|
37362
|
+
}
|
|
37363
|
+
if (options2.dev) {
|
|
37364
|
+
if (await isDevRunning()) {
|
|
37365
|
+
info("Dev services already running");
|
|
37366
|
+
} else {
|
|
37367
|
+
const args = [
|
|
37368
|
+
"bun",
|
|
37369
|
+
"run",
|
|
37370
|
+
`${import.meta.dir}/../../bin/secondlayer.ts`,
|
|
37371
|
+
"dev",
|
|
37372
|
+
"start"
|
|
37373
|
+
];
|
|
37374
|
+
if (config.node?.installPath) {
|
|
37375
|
+
args.push("--stacks-node");
|
|
37376
|
+
}
|
|
37377
|
+
info("Starting dev services...");
|
|
37378
|
+
const proc = Bun.spawn(args, {
|
|
37379
|
+
stdin: "inherit",
|
|
37380
|
+
stdout: "inherit",
|
|
37381
|
+
stderr: "inherit"
|
|
37382
|
+
});
|
|
37383
|
+
await proc.exited;
|
|
37384
|
+
}
|
|
37385
|
+
}
|
|
37386
|
+
console.log("");
|
|
37387
|
+
success("Stack started");
|
|
37388
|
+
console.log(dim("Run 'sl status' to check health"));
|
|
37389
|
+
console.log("");
|
|
37390
|
+
}
|
|
37391
|
+
async function stackStop(options2) {
|
|
37392
|
+
console.log("");
|
|
37393
|
+
info("Stopping Secondlayer Stack...");
|
|
37394
|
+
if (options2.dev) {
|
|
37395
|
+
if (await isDevRunning()) {
|
|
37396
|
+
info("Stopping dev services...");
|
|
37397
|
+
const proc = Bun.spawn([
|
|
37398
|
+
"bun",
|
|
37399
|
+
"run",
|
|
37400
|
+
`${import.meta.dir}/../../bin/secondlayer.ts`,
|
|
37401
|
+
"dev",
|
|
37402
|
+
"stop"
|
|
37403
|
+
], { stdin: "inherit", stdout: "inherit", stderr: "inherit" });
|
|
37404
|
+
await proc.exited;
|
|
37405
|
+
} else {
|
|
37406
|
+
info("Dev services not running");
|
|
37407
|
+
}
|
|
37408
|
+
}
|
|
37409
|
+
if (options2.node) {
|
|
37410
|
+
if (await isNodeRunning()) {
|
|
37411
|
+
info("Stopping node containers...");
|
|
37412
|
+
const stopped = await stopNodeContainers();
|
|
37413
|
+
if (stopped.length > 0) {
|
|
37414
|
+
success(`Stopped: ${stopped.join(", ")}`);
|
|
37415
|
+
}
|
|
37416
|
+
} else {
|
|
37417
|
+
info("Node not running");
|
|
37418
|
+
}
|
|
37419
|
+
}
|
|
37420
|
+
try {
|
|
37421
|
+
const result = await Bun.$`docker ps -a --format json --filter "name=secondlayer-dev" --filter "name=stacks"`.quiet().nothrow();
|
|
37422
|
+
if (result.exitCode === 0) {
|
|
37423
|
+
const lines = result.stdout.toString().trim().split(`
|
|
37424
|
+
`).filter(Boolean);
|
|
37425
|
+
const orphans = [];
|
|
37426
|
+
for (const line of lines) {
|
|
37427
|
+
try {
|
|
37428
|
+
const c = JSON.parse(line);
|
|
37429
|
+
const name = c.Names || c.Name;
|
|
37430
|
+
if (name && c.Status?.includes("Exited")) {
|
|
37431
|
+
orphans.push(name);
|
|
37432
|
+
}
|
|
37433
|
+
} catch {}
|
|
37434
|
+
}
|
|
37435
|
+
if (orphans.length > 0) {
|
|
37436
|
+
info(`Cleaning up ${orphans.length} orphaned container(s)...`);
|
|
37437
|
+
for (const name of orphans) {
|
|
37438
|
+
await Bun.$`docker rm ${name}`.quiet().nothrow();
|
|
37439
|
+
}
|
|
37440
|
+
}
|
|
37441
|
+
}
|
|
37442
|
+
} catch {}
|
|
37443
|
+
console.log("");
|
|
37444
|
+
success("Stack stopped");
|
|
37445
|
+
console.log("");
|
|
37446
|
+
}
|
|
37447
|
+
|
|
37448
|
+
// src/commands/local.ts
|
|
37318
37449
|
init_dev_state();
|
|
37319
37450
|
init_node_manager();
|
|
37320
37451
|
init_output();
|
|
@@ -37325,7 +37456,7 @@ function registerLocalCommand(program2) {
|
|
|
37325
37456
|
return;
|
|
37326
37457
|
await requireLocalNetwork();
|
|
37327
37458
|
});
|
|
37328
|
-
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("
|
|
37459
|
+
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("--foreground", "Run in foreground (blocking)").action(async (options2) => {
|
|
37329
37460
|
const { runBackground: runBackground2, runForeground: runForeground2, isDevAlreadyRunning: isDevAlreadyRunning2 } = await Promise.resolve().then(() => (init_dev_impl(), exports_dev_impl));
|
|
37330
37461
|
if (await isDevAlreadyRunning2()) {
|
|
37331
37462
|
return;
|
|
@@ -37344,12 +37475,36 @@ function registerLocalCommand(program2) {
|
|
|
37344
37475
|
const { restartDev: restartDev2 } = await Promise.resolve().then(() => (init_dev_impl(), exports_dev_impl));
|
|
37345
37476
|
await restartDev2();
|
|
37346
37477
|
});
|
|
37478
|
+
local.command("up").description("Start the full local stack (Stacks node + dev services)").option("--devnet", "Run against a local Clarinet devnet instead").option("--no-node", "Skip starting the Stacks node").option("--no-dev", "Skip starting dev services").option("--project <dir>", "[--devnet] Clarinet project directory").option("--image-tag <tag>", "[--devnet] Published image tag to run").option("--owner <owner>", "[--devnet] ghcr image owner to pull from").option("--no-up", "[--devnet] Patch config + write compose without starting").action(async (options2) => {
|
|
37479
|
+
if (options2.devnet) {
|
|
37480
|
+
await connect({
|
|
37481
|
+
project: options2.project,
|
|
37482
|
+
imageTag: options2.imageTag ?? DEFAULT_IMAGE_TAG,
|
|
37483
|
+
owner: options2.owner,
|
|
37484
|
+
up: options2.up
|
|
37485
|
+
});
|
|
37486
|
+
} else {
|
|
37487
|
+
await stackStart({ node: options2.node, dev: options2.dev });
|
|
37488
|
+
}
|
|
37489
|
+
});
|
|
37490
|
+
local.command("down").description("Stop the full local stack").option("--devnet", "Stop a local Clarinet devnet instead").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").option("--project <dir>", "[--devnet] Clarinet project directory").option("--purge", "[--devnet] Also remove volumes (wipes the local index)").action(async (options2) => {
|
|
37491
|
+
if (options2.devnet) {
|
|
37492
|
+
await down({ project: options2.project, purge: options2.purge });
|
|
37493
|
+
} else {
|
|
37494
|
+
await stackStop({
|
|
37495
|
+
node: options2.node,
|
|
37496
|
+
dev: options2.dev,
|
|
37497
|
+
wait: options2.wait
|
|
37498
|
+
});
|
|
37499
|
+
}
|
|
37500
|
+
});
|
|
37347
37501
|
local.command("status").description("Show local environment status").action(async () => {
|
|
37348
37502
|
await showLocalStatus();
|
|
37349
37503
|
});
|
|
37350
37504
|
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) => {
|
|
37351
37505
|
await showLocalLogs(options2);
|
|
37352
37506
|
});
|
|
37507
|
+
addDbCommand(local);
|
|
37353
37508
|
const node = local.command("node").description("Manage local Stacks node");
|
|
37354
37509
|
node.command("setup").description("Interactive setup wizard for Stacks node").action(async () => {
|
|
37355
37510
|
const { runSetupWizard: runSetupWizard2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
|
|
@@ -37359,13 +37514,13 @@ function registerLocalCommand(program2) {
|
|
|
37359
37514
|
const { startNode: startNode2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
|
|
37360
37515
|
await startNode2(options2.path, options2.withIndexer);
|
|
37361
37516
|
});
|
|
37362
|
-
node.command("stop").description("Stop the Stacks node").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-
|
|
37517
|
+
node.command("stop").description("Stop the Stacks node").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-y, --yes", "Skip confirmation").option("--wait", "Wait for in-flight work to drain first").action(async (options2) => {
|
|
37363
37518
|
const { stopNode: stopNode2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
|
|
37364
|
-
await stopNode2(options2.path, options2.
|
|
37519
|
+
await stopNode2(options2.path, options2.yes, options2.wait);
|
|
37365
37520
|
});
|
|
37366
|
-
node.command("restart").description("Restart the Stacks node (stop then start)").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-
|
|
37521
|
+
node.command("restart").description("Restart the Stacks node (stop then start)").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-y, --yes", "Skip confirmation").option("--wait", "Wait for in-flight work to drain before stopping").action(async (options2) => {
|
|
37367
37522
|
const { restartNode: restartNode2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
|
|
37368
|
-
await restartNode2(options2.path, options2.
|
|
37523
|
+
await restartNode2(options2.path, options2.yes, options2.wait);
|
|
37369
37524
|
});
|
|
37370
37525
|
node.command("status").description("Show Stacks node status").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("--json", "Output as JSON").action(async (options2) => {
|
|
37371
37526
|
const { showStatus: showStatus2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
|
|
@@ -37639,19 +37794,19 @@ async function writeActiveProject(slug, cwd) {
|
|
|
37639
37794
|
}
|
|
37640
37795
|
|
|
37641
37796
|
// src/commands/whoami.ts
|
|
37642
|
-
|
|
37797
|
+
init_resolve_auth();
|
|
37643
37798
|
function registerWhoamiCommand(program2) {
|
|
37644
|
-
program2.command("whoami").description("Show
|
|
37645
|
-
|
|
37646
|
-
|
|
37799
|
+
program2.command("whoami").description("Show the active account, credential source, and project").option("--json", "Output as JSON").action(async (options2) => {
|
|
37800
|
+
let auth;
|
|
37801
|
+
try {
|
|
37802
|
+
auth = await resolveAuth();
|
|
37803
|
+
} catch {
|
|
37647
37804
|
error("Not logged in. Run: sl login");
|
|
37648
|
-
process.exit(
|
|
37805
|
+
process.exit(1);
|
|
37649
37806
|
}
|
|
37650
|
-
|
|
37651
|
-
rows.push(["Email", session.email]);
|
|
37807
|
+
let account;
|
|
37652
37808
|
try {
|
|
37653
|
-
|
|
37654
|
-
rows.push(["Plan", account.plan]);
|
|
37809
|
+
account = await httpPlatform("/api/accounts/me");
|
|
37655
37810
|
} catch (err) {
|
|
37656
37811
|
if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED") {
|
|
37657
37812
|
error("Session expired. Run: sl login");
|
|
@@ -37661,13 +37816,34 @@ function registerWhoamiCommand(program2) {
|
|
|
37661
37816
|
}
|
|
37662
37817
|
const config = await loadConfig();
|
|
37663
37818
|
const active = await readActiveProject(process.cwd(), config.defaultProject);
|
|
37664
|
-
|
|
37665
|
-
|
|
37666
|
-
|
|
37667
|
-
|
|
37668
|
-
|
|
37669
|
-
|
|
37670
|
-
|
|
37819
|
+
const authSource = auth.fromEnv ? "API key (env)" : "session";
|
|
37820
|
+
output({
|
|
37821
|
+
json: options2.json,
|
|
37822
|
+
data: {
|
|
37823
|
+
email: account.email,
|
|
37824
|
+
plan: account.plan,
|
|
37825
|
+
apiUrl: auth.apiUrl,
|
|
37826
|
+
authSource,
|
|
37827
|
+
project: active ? { slug: active.slug, source: active.resolvedFrom } : null
|
|
37828
|
+
},
|
|
37829
|
+
human: () => {
|
|
37830
|
+
const rows = [];
|
|
37831
|
+
rows.push(["Email", account.email]);
|
|
37832
|
+
rows.push(["Plan", account.plan]);
|
|
37833
|
+
rows.push(["API URL", auth.apiUrl]);
|
|
37834
|
+
rows.push(["Auth", dim(authSource)]);
|
|
37835
|
+
if (active) {
|
|
37836
|
+
rows.push(["Project", active.slug]);
|
|
37837
|
+
rows.push(["Project source", dim(active.resolvedFrom)]);
|
|
37838
|
+
} else {
|
|
37839
|
+
rows.push([
|
|
37840
|
+
"Project",
|
|
37841
|
+
dim("(none — run `sl project create <name>`)")
|
|
37842
|
+
]);
|
|
37843
|
+
}
|
|
37844
|
+
console.log(formatKeyValue(rows));
|
|
37845
|
+
}
|
|
37846
|
+
});
|
|
37671
37847
|
});
|
|
37672
37848
|
}
|
|
37673
37849
|
// src/commands/logout.ts
|
|
@@ -37696,7 +37872,7 @@ init_config();
|
|
|
37696
37872
|
import { input as input4 } from "@inquirer/prompts";
|
|
37697
37873
|
init_output();
|
|
37698
37874
|
function registerProjectCommand(program2) {
|
|
37699
|
-
const project = program2.command("project").description("Manage Secondlayer projects");
|
|
37875
|
+
const project = program2.command("projects").alias("project").description("Manage Secondlayer projects");
|
|
37700
37876
|
project.command("create [name]").description("Create a new project").option("--slug <slug>", "Project URL identifier").action(async (nameArg, options2 = {}) => {
|
|
37701
37877
|
const name = nameArg ?? await input4({
|
|
37702
37878
|
message: "Project name",
|
|
@@ -37726,24 +37902,30 @@ function registerProjectCommand(program2) {
|
|
|
37726
37902
|
handleProjectError(err);
|
|
37727
37903
|
}
|
|
37728
37904
|
});
|
|
37729
|
-
project.command("list").description("List projects in your account").action(async () => {
|
|
37905
|
+
project.command("list").alias("ls").description("List projects in your account").option("--json", "Output as JSON").action(async (options2) => {
|
|
37730
37906
|
try {
|
|
37731
37907
|
const res = await httpPlatform("/api/projects");
|
|
37732
|
-
if (res.projects.length === 0) {
|
|
37733
|
-
info("No projects yet — run `sl project create <name>` to start.");
|
|
37734
|
-
return;
|
|
37735
|
-
}
|
|
37736
37908
|
const active = await readActiveProject(process.cwd(), (await loadConfig()).defaultProject);
|
|
37737
|
-
|
|
37738
|
-
|
|
37739
|
-
|
|
37740
|
-
|
|
37741
|
-
|
|
37742
|
-
|
|
37743
|
-
|
|
37744
|
-
|
|
37745
|
-
|
|
37746
|
-
|
|
37909
|
+
output({
|
|
37910
|
+
json: options2.json,
|
|
37911
|
+
data: { projects: res.projects, active: active?.slug ?? null },
|
|
37912
|
+
human: () => {
|
|
37913
|
+
if (res.projects.length === 0) {
|
|
37914
|
+
info("No projects yet — run `sl project create <name>` to start.");
|
|
37915
|
+
return;
|
|
37916
|
+
}
|
|
37917
|
+
const rows = res.projects.map((p) => [
|
|
37918
|
+
p.slug === active?.slug ? `* ${p.slug}` : ` ${p.slug}`,
|
|
37919
|
+
p.name,
|
|
37920
|
+
p.network,
|
|
37921
|
+
new Date(p.createdAt).toLocaleDateString()
|
|
37922
|
+
]);
|
|
37923
|
+
console.log(formatTable(["", "Name", "Network", "Created"], rows));
|
|
37924
|
+
if (active) {
|
|
37925
|
+
console.log(dim(`Active: ${active.slug} (from ${active.resolvedFrom})`));
|
|
37926
|
+
}
|
|
37927
|
+
}
|
|
37928
|
+
});
|
|
37747
37929
|
} catch (err) {
|
|
37748
37930
|
handleProjectError(err);
|
|
37749
37931
|
}
|
|
@@ -37763,16 +37945,22 @@ function registerProjectCommand(program2) {
|
|
|
37763
37945
|
info(dim(`Written to ${path2}`));
|
|
37764
37946
|
info(dim("Tip: add `.secondlayer/` to .gitignore — it's account-personal."));
|
|
37765
37947
|
});
|
|
37766
|
-
project.command("
|
|
37948
|
+
project.command("get").description("Show the active project for this directory").option("--json", "Output as JSON").action(async (options2) => {
|
|
37767
37949
|
const config = await loadConfig();
|
|
37768
37950
|
const active = await readActiveProject(process.cwd(), config.defaultProject);
|
|
37769
|
-
|
|
37770
|
-
|
|
37771
|
-
|
|
37772
|
-
|
|
37773
|
-
|
|
37774
|
-
|
|
37775
|
-
|
|
37951
|
+
output({
|
|
37952
|
+
json: options2.json,
|
|
37953
|
+
data: active ? { slug: active.slug, source: active.resolvedFrom } : null,
|
|
37954
|
+
human: () => {
|
|
37955
|
+
if (!active) {
|
|
37956
|
+
info("No active project.");
|
|
37957
|
+
info(dim("Run 'sl project create <name>' or 'sl project use <slug>'."));
|
|
37958
|
+
return;
|
|
37959
|
+
}
|
|
37960
|
+
console.log(active.slug);
|
|
37961
|
+
console.log(dim(`(from ${active.resolvedFrom})`));
|
|
37962
|
+
}
|
|
37963
|
+
});
|
|
37776
37964
|
});
|
|
37777
37965
|
}
|
|
37778
37966
|
function handleProjectError(err) {
|
|
@@ -37801,23 +37989,24 @@ function validateProjectSlug(slug) {
|
|
|
37801
37989
|
}
|
|
37802
37990
|
// src/cli.ts
|
|
37803
37991
|
var { version } = package_default;
|
|
37804
|
-
program.name("secondlayer").alias("sl").description("SecondLayer CLI — dedicated Stacks indexing + real-time subgraphs").version(version).option("--network <network>", "Override network (local, testnet, mainnet)");
|
|
37992
|
+
program.name("secondlayer").alias("sl").description("SecondLayer CLI — dedicated Stacks indexing + real-time subgraphs").version(version).option("--network <network>", "Override network (local, testnet, mainnet)").option("--api-key <key>", "API credential (overrides SL_API_KEY)").option("--api-url <url>", "API endpoint (overrides SL_API_URL)").showSuggestionAfterError(true).showHelpAfterError("(run `sl --help` to see available commands)");
|
|
37805
37993
|
program.hook("preAction", (thisCommand) => {
|
|
37806
|
-
const
|
|
37807
|
-
if (
|
|
37808
|
-
process.env.STACKS_NETWORK =
|
|
37994
|
+
const { network, apiKey, apiUrl } = thisCommand.opts();
|
|
37995
|
+
if (network)
|
|
37996
|
+
process.env.STACKS_NETWORK = network;
|
|
37997
|
+
if (apiKey)
|
|
37998
|
+
process.env.SL_API_KEY = apiKey;
|
|
37999
|
+
if (apiUrl)
|
|
38000
|
+
process.env.SL_API_URL = apiUrl;
|
|
37809
38001
|
});
|
|
37810
38002
|
program.addHelpText("after", `
|
|
37811
38003
|
Quickstart:
|
|
37812
38004
|
$ sl login # Authenticate (magic-link email)
|
|
37813
|
-
$ sl subgraphs
|
|
38005
|
+
$ sl subgraphs create my-watcher --template sip-010-balances
|
|
37814
38006
|
$ sl subgraphs deploy subgraphs/my-watcher.ts
|
|
37815
38007
|
$ sl subgraphs status my-watcher
|
|
37816
38008
|
`);
|
|
37817
|
-
program.
|
|
37818
|
-
const { generate: generate2 } = await Promise.resolve().then(() => (init_generate(), exports_generate));
|
|
37819
|
-
await generate2(files, options3);
|
|
37820
|
-
});
|
|
38009
|
+
program.commandsGroup("Getting started:");
|
|
37821
38010
|
program.command("init").description("Initialize a new secondlayer.config.ts file").action(async () => {
|
|
37822
38011
|
const { init: init3 } = await Promise.resolve().then(() => (init_init(), exports_init));
|
|
37823
38012
|
await init3();
|
|
@@ -37825,22 +38014,34 @@ program.command("init").description("Initialize a new secondlayer.config.ts file
|
|
|
37825
38014
|
registerLoginCommand(program);
|
|
37826
38015
|
registerLogoutCommand(program);
|
|
37827
38016
|
registerWhoamiCommand(program);
|
|
37828
|
-
|
|
38017
|
+
program.commandsGroup("Data products:");
|
|
37829
38018
|
registerSubgraphsCommand(program);
|
|
37830
|
-
registerCreateCommand(program);
|
|
37831
38019
|
registerSubscriptionsCommand(program);
|
|
37832
38020
|
registerStreamsCommand(program);
|
|
37833
38021
|
registerDatasetsCommand(program);
|
|
38022
|
+
program.commandsGroup("Project & codegen:");
|
|
38023
|
+
registerProjectCommand(program);
|
|
38024
|
+
var configureGenerate = (cmd) => cmd.option("-c, --config <path>", "Path to config file").option("-o, --output <path>", "Output file path (required when using direct files)").option("-k, --api-key <key>", "Stacks node API key for direct RPC URLs").option("-w, --watch", "Watch for changes").action(async (files, options3) => {
|
|
38025
|
+
options3.out = options3.output;
|
|
38026
|
+
const { generate: generate2 } = await Promise.resolve().then(() => (init_generate(), exports_generate));
|
|
38027
|
+
await generate2(files, options3);
|
|
38028
|
+
});
|
|
38029
|
+
var contracts = program.command("contracts").description("Work with Clarity contracts");
|
|
38030
|
+
configureGenerate(contracts.command("generate [files...]").aliases(["gen"]).description("Generate TypeScript interfaces from Clarity contracts")).addHelpText("after", `
|
|
38031
|
+
Examples:
|
|
38032
|
+
$ sl contracts generate
|
|
38033
|
+
$ sl contracts generate ./contracts/pool.clar -o ./src/generated.ts
|
|
38034
|
+
$ sl contracts generate --config secondlayer.config.ts --watch`);
|
|
38035
|
+
program.commandsGroup("Local development:");
|
|
38036
|
+
registerLocalCommand(program);
|
|
38037
|
+
registerDevnetCommand(program);
|
|
38038
|
+
program.commandsGroup("Diagnostics:");
|
|
37834
38039
|
registerStatusCommand(program);
|
|
37835
|
-
registerStackCommand(program);
|
|
37836
|
-
registerDbCommand(program);
|
|
37837
38040
|
registerDoctorCommand(program);
|
|
37838
38041
|
registerConfigCommand(program);
|
|
37839
|
-
|
|
37840
|
-
registerDevnetCommand(program);
|
|
38042
|
+
program.commandsGroup("Account:");
|
|
37841
38043
|
registerAccountCommand(program);
|
|
37842
|
-
registerBillingCommand(program);
|
|
37843
38044
|
program.parse();
|
|
37844
38045
|
|
|
37845
|
-
//# debugId=
|
|
38046
|
+
//# debugId=E63D3732E427AF4164756E2164756E21
|
|
37846
38047
|
//# sourceMappingURL=cli.js.map
|