@secondlayer/cli 3.5.2 → 3.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +187 -56
- package/dist/cli.js.map +9 -9
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -2530,7 +2530,7 @@ async function request(url, opts) {
|
|
|
2530
2530
|
method: opts.method ?? "GET",
|
|
2531
2531
|
headers,
|
|
2532
2532
|
body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,
|
|
2533
|
-
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
2533
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? REQUEST_TIMEOUT_MS)
|
|
2534
2534
|
});
|
|
2535
2535
|
if (!res.ok) {
|
|
2536
2536
|
let body = {};
|
|
@@ -2957,7 +2957,8 @@ function success(message) {
|
|
|
2957
2957
|
console.log(green(`✓ ${message}`));
|
|
2958
2958
|
}
|
|
2959
2959
|
function error(message) {
|
|
2960
|
-
|
|
2960
|
+
const text = message.trim() || "Command failed.";
|
|
2961
|
+
console.error(red(`✗ ${text}`));
|
|
2961
2962
|
}
|
|
2962
2963
|
function warn(message) {
|
|
2963
2964
|
console.log(yellow(`⚠ ${message}`));
|
|
@@ -2966,17 +2967,17 @@ function info(message) {
|
|
|
2966
2967
|
console.log(blue(`ℹ ${message}`));
|
|
2967
2968
|
}
|
|
2968
2969
|
function stripAnsi(text) {
|
|
2969
|
-
return text.replace(
|
|
2970
|
+
return text.replace(ANSI_ESCAPE_PATTERN, "");
|
|
2970
2971
|
}
|
|
2971
2972
|
function formatTable(headers, rows) {
|
|
2972
2973
|
const widths = headers.map((h, i) => {
|
|
2973
2974
|
const colValues = [h, ...rows.map((r) => r[i] || "")];
|
|
2974
2975
|
return Math.max(...colValues.map((v) => stripAnsi(v).length));
|
|
2975
2976
|
});
|
|
2976
|
-
const headerRow = headers.map((h, i) => h.padEnd(widths[i])).join(" ");
|
|
2977
|
+
const headerRow = headers.map((h, i) => h.padEnd(widths[i] ?? 0)).join(" ");
|
|
2977
2978
|
const separator = widths.map((w) => "-".repeat(w)).join(" ");
|
|
2978
2979
|
const dataRows = rows.map((row) => row.map((cell, i) => {
|
|
2979
|
-
const width = widths[i];
|
|
2980
|
+
const width = widths[i] ?? 0;
|
|
2980
2981
|
const padding = width - stripAnsi(cell).length;
|
|
2981
2982
|
return cell + " ".repeat(Math.max(0, padding));
|
|
2982
2983
|
}).join(" "));
|
|
@@ -2988,7 +2989,7 @@ function formatKeyValue(pairs) {
|
|
|
2988
2989
|
return pairs.map(([key, value]) => `${dim(key.padEnd(maxKeyLen))} ${value}`).join(`
|
|
2989
2990
|
`);
|
|
2990
2991
|
}
|
|
2991
|
-
var colors;
|
|
2992
|
+
var colors, ANSI_ESCAPE_PATTERN;
|
|
2992
2993
|
var init_output = __esm(() => {
|
|
2993
2994
|
colors = {
|
|
2994
2995
|
reset: "\x1B[0m",
|
|
@@ -3001,6 +3002,7 @@ var init_output = __esm(() => {
|
|
|
3001
3002
|
dim: "\x1B[2m",
|
|
3002
3003
|
bold: "\x1B[1m"
|
|
3003
3004
|
};
|
|
3005
|
+
ANSI_ESCAPE_PATTERN = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
|
|
3004
3006
|
});
|
|
3005
3007
|
|
|
3006
3008
|
// src/lib/docker.ts
|
|
@@ -13464,10 +13466,10 @@ var init_manager = __esm(() => {
|
|
|
13464
13466
|
});
|
|
13465
13467
|
|
|
13466
13468
|
// src/services/indexer.ts
|
|
13467
|
-
import { dirname as
|
|
13469
|
+
import { dirname as dirname5, resolve as resolve4 } from "node:path";
|
|
13468
13470
|
async function startIndexer(options2) {
|
|
13469
13471
|
const port = options2.port ?? 3700;
|
|
13470
|
-
const rootDir =
|
|
13472
|
+
const rootDir = dirname5(dirname5(dirname5(dirname5(import.meta.dir))));
|
|
13471
13473
|
const indexerPath = resolve4(rootDir, "packages/indexer/src/index.ts");
|
|
13472
13474
|
await serviceManager.start(SERVICE_NAME, ["bun", "run", "--watch", indexerPath], {
|
|
13473
13475
|
port,
|
|
@@ -13484,9 +13486,9 @@ var init_indexer = __esm(() => {
|
|
|
13484
13486
|
});
|
|
13485
13487
|
|
|
13486
13488
|
// src/services/worker.ts
|
|
13487
|
-
import { dirname as
|
|
13489
|
+
import { dirname as dirname6, resolve as resolve5 } from "node:path";
|
|
13488
13490
|
async function startWorker(options2) {
|
|
13489
|
-
const rootDir =
|
|
13491
|
+
const rootDir = dirname6(dirname6(dirname6(dirname6(import.meta.dir))));
|
|
13490
13492
|
const workerPath = resolve5(rootDir, "packages/worker/src/index.ts");
|
|
13491
13493
|
await serviceManager.start(SERVICE_NAME2, ["bun", "run", "--watch", workerPath], {
|
|
13492
13494
|
onStdout: options2.onLog,
|
|
@@ -13499,10 +13501,10 @@ var init_worker = __esm(() => {
|
|
|
13499
13501
|
});
|
|
13500
13502
|
|
|
13501
13503
|
// src/services/api.ts
|
|
13502
|
-
import { dirname as
|
|
13504
|
+
import { dirname as dirname7, resolve as resolve6 } from "node:path";
|
|
13503
13505
|
async function startApi(options2) {
|
|
13504
13506
|
const port = options2.port ?? 3800;
|
|
13505
|
-
const rootDir =
|
|
13507
|
+
const rootDir = dirname7(dirname7(dirname7(dirname7(import.meta.dir))));
|
|
13506
13508
|
const apiPath = resolve6(rootDir, "packages/api/src/index.ts");
|
|
13507
13509
|
await serviceManager.start(SERVICE_NAME3, ["bun", "run", "--watch", apiPath], {
|
|
13508
13510
|
port,
|
|
@@ -13519,9 +13521,9 @@ var init_api2 = __esm(() => {
|
|
|
13519
13521
|
});
|
|
13520
13522
|
|
|
13521
13523
|
// src/services/subgraph-processor.ts
|
|
13522
|
-
import { dirname as
|
|
13524
|
+
import { dirname as dirname8, resolve as resolve7 } from "node:path";
|
|
13523
13525
|
async function startSubgraphProcessor(options2) {
|
|
13524
|
-
const rootDir =
|
|
13526
|
+
const rootDir = dirname8(dirname8(dirname8(dirname8(import.meta.dir))));
|
|
13525
13527
|
const servicePath = resolve7(rootDir, "packages/subgraphs/src/service.ts");
|
|
13526
13528
|
await serviceManager.start(SERVICE_NAME4, ["bun", "run", "--watch", servicePath], {
|
|
13527
13529
|
env: {
|
|
@@ -13557,7 +13559,7 @@ __export(exports_dev_impl, {
|
|
|
13557
13559
|
isDevAlreadyRunning: () => isDevAlreadyRunning
|
|
13558
13560
|
});
|
|
13559
13561
|
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
13560
|
-
import { dirname as
|
|
13562
|
+
import { dirname as dirname9, join as join8, resolve as resolve8 } from "node:path";
|
|
13561
13563
|
async function isDevAlreadyRunning() {
|
|
13562
13564
|
if (await isDevRunning()) {
|
|
13563
13565
|
const running = await getRunningServices();
|
|
@@ -13635,7 +13637,7 @@ async function runBackground(options2) {
|
|
|
13635
13637
|
startedAt: new Date().toISOString()
|
|
13636
13638
|
};
|
|
13637
13639
|
try {
|
|
13638
|
-
const packagesDir =
|
|
13640
|
+
const packagesDir = dirname9(dirname9(dirname9(dirname9(import.meta.dir))));
|
|
13639
13641
|
const env = { DATABASE_URL: databaseUrl, DEV_MODE: "true" };
|
|
13640
13642
|
const apiLogFile = getLogFile("api");
|
|
13641
13643
|
const apiProc = Bun.spawn(["bun", "run", resolve8(packagesDir, "packages/api/src/index.ts")], {
|
|
@@ -13982,7 +13984,7 @@ async function restartDev() {
|
|
|
13982
13984
|
await clearDevState();
|
|
13983
13985
|
await clearLogs();
|
|
13984
13986
|
const config = await loadConfig();
|
|
13985
|
-
const packagesDir =
|
|
13987
|
+
const packagesDir = dirname9(dirname9(dirname9(dirname9(import.meta.dir))));
|
|
13986
13988
|
const env = state.env;
|
|
13987
13989
|
const newState = {
|
|
13988
13990
|
services: {},
|
|
@@ -14163,7 +14165,7 @@ async function ensureDevPostgres(dataDir) {
|
|
|
14163
14165
|
if (check.stdout.toString().trim()) {
|
|
14164
14166
|
return false;
|
|
14165
14167
|
}
|
|
14166
|
-
const pgDataDir =
|
|
14168
|
+
const pgDataDir = join8(dataDir, "postgres");
|
|
14167
14169
|
mkdirSync3(pgDataDir, { recursive: true });
|
|
14168
14170
|
const stopped = await Bun.$`docker ps -aq -f name=secondlayer-dev-postgres`.quiet().nothrow();
|
|
14169
14171
|
if (stopped.stdout.toString().trim()) {
|
|
@@ -14179,7 +14181,7 @@ async function ensureDevPostgres(dataDir) {
|
|
|
14179
14181
|
throw new Error("PostgreSQL failed to start");
|
|
14180
14182
|
}
|
|
14181
14183
|
async function runMigrations(databaseUrl) {
|
|
14182
|
-
const packagesDir =
|
|
14184
|
+
const packagesDir = dirname9(dirname9(dirname9(dirname9(import.meta.dir))));
|
|
14183
14185
|
const migrateScript = resolve8(packagesDir, "packages/shared/src/db/migrate.ts");
|
|
14184
14186
|
const result = await Bun.$`DATABASE_URL=${databaseUrl} bun run ${migrateScript}`.quiet().nothrow();
|
|
14185
14187
|
if (result.exitCode !== 0) {
|
|
@@ -21907,7 +21909,7 @@ var init_commands = __esm(() => {
|
|
|
21907
21909
|
});
|
|
21908
21910
|
|
|
21909
21911
|
// ../../node_modules/@antfu/ni/dist/shared/ni.B5qNAuoI.mjs
|
|
21910
|
-
import path3, { join as
|
|
21912
|
+
import path3, { join as join9, dirname as dirname10, resolve as resolve9 } from "node:path";
|
|
21911
21913
|
import process$1 from "node:process";
|
|
21912
21914
|
import require$$0 from "readline";
|
|
21913
21915
|
import require$$2 from "events";
|
|
@@ -24922,7 +24924,7 @@ function requireLib() {
|
|
|
24922
24924
|
return lib;
|
|
24923
24925
|
hasRequiredLib = 1;
|
|
24924
24926
|
const { isexe, sync: isexeSync } = requireCjs();
|
|
24925
|
-
const { join:
|
|
24927
|
+
const { join: join10, delimiter, sep, posix: posix2 } = require$$1$2;
|
|
24926
24928
|
const isWindows = process.platform === "win32";
|
|
24927
24929
|
const rSlash = new RegExp(`[${posix2.sep}${sep === posix2.sep ? "" : sep}]`.replace(/(\\)/g, "\\$1"));
|
|
24928
24930
|
const rRel = new RegExp(`^\\.${rSlash.source}`);
|
|
@@ -24949,7 +24951,7 @@ function requireLib() {
|
|
|
24949
24951
|
const getPathPart = (raw, cmd) => {
|
|
24950
24952
|
const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
|
|
24951
24953
|
const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
|
|
24952
|
-
return prefix +
|
|
24954
|
+
return prefix + join10(pathPart, cmd);
|
|
24953
24955
|
};
|
|
24954
24956
|
const which = async (cmd, opt = {}) => {
|
|
24955
24957
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
@@ -25098,7 +25100,7 @@ var init_ni_B5qNAuoI = __esm(() => {
|
|
|
25098
25100
|
options2 = {};
|
|
25099
25101
|
libExports = requireLib();
|
|
25100
25102
|
which = /* @__PURE__ */ getDefaultExportFromCjs(libExports);
|
|
25101
|
-
CLI_TEMP_DIR =
|
|
25103
|
+
CLI_TEMP_DIR = join9(os4.tmpdir(), "antfu-ni");
|
|
25102
25104
|
customRcPath = process$1.env.NI_CONFIG_FILE;
|
|
25103
25105
|
home = process$1.platform === "win32" ? process$1.env.USERPROFILE : process$1.env.HOME;
|
|
25104
25106
|
defaultRcPath = path3.join(home || "~/", ".nirc");
|
|
@@ -25135,14 +25137,14 @@ function isPlainObject2(value) {
|
|
|
25135
25137
|
}
|
|
25136
25138
|
|
|
25137
25139
|
// ../../node_modules/execa/lib/arguments/file-url.js
|
|
25138
|
-
import { fileURLToPath as
|
|
25140
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
25139
25141
|
var safeNormalizeFileUrl = (file, name) => {
|
|
25140
25142
|
const fileString = normalizeFileUrl(normalizeDenoExecPath(file));
|
|
25141
25143
|
if (typeof fileString !== "string") {
|
|
25142
25144
|
throw new TypeError(`${name} must be a string or a file URL: ${fileString}.`);
|
|
25143
25145
|
}
|
|
25144
25146
|
return fileString;
|
|
25145
|
-
}, normalizeDenoExecPath = (file) => isDenoExecPath(file) ? file.toString() : file, isDenoExecPath = (file) => typeof file !== "string" && file && Object.getPrototypeOf(file) === String.prototype, normalizeFileUrl = (file) => file instanceof URL ?
|
|
25147
|
+
}, normalizeDenoExecPath = (file) => isDenoExecPath(file) ? file.toString() : file, isDenoExecPath = (file) => typeof file !== "string" && file && Object.getPrototypeOf(file) === String.prototype, normalizeFileUrl = (file) => file instanceof URL ? fileURLToPath3(file) : file;
|
|
25146
25148
|
var init_file_url = () => {};
|
|
25147
25149
|
|
|
25148
25150
|
// ../../node_modules/execa/lib/methods/parameters.js
|
|
@@ -26438,9 +26440,9 @@ function pathKey(options3 = {}) {
|
|
|
26438
26440
|
import { promisify as promisify4 } from "node:util";
|
|
26439
26441
|
import { execFile as execFileCallback, execFileSync as execFileSyncOriginal } from "node:child_process";
|
|
26440
26442
|
import path4 from "node:path";
|
|
26441
|
-
import { fileURLToPath as
|
|
26443
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
26442
26444
|
function toPath(urlOrPath) {
|
|
26443
|
-
return urlOrPath instanceof URL ?
|
|
26445
|
+
return urlOrPath instanceof URL ? fileURLToPath4(urlOrPath) : urlOrPath;
|
|
26444
26446
|
}
|
|
26445
26447
|
function traversePathUp(startPath) {
|
|
26446
26448
|
return {
|
|
@@ -28822,7 +28824,7 @@ var init_stdio_option = __esm(() => {
|
|
|
28822
28824
|
});
|
|
28823
28825
|
|
|
28824
28826
|
// ../../node_modules/execa/lib/stdio/native.js
|
|
28825
|
-
import { readFileSync as
|
|
28827
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
28826
28828
|
import tty3 from "node:tty";
|
|
28827
28829
|
var handleNativeStream = ({ stdioItem, stdioItem: { type }, isStdioArray, fdNumber, direction, isSync }) => {
|
|
28828
28830
|
if (!isStdioArray || type !== "native") {
|
|
@@ -28854,7 +28856,7 @@ var handleNativeStream = ({ stdioItem, stdioItem: { type }, isStdioArray, fdNumb
|
|
|
28854
28856
|
if (tty3.isatty(targetFdNumber)) {
|
|
28855
28857
|
throw new TypeError(`The \`${optionName}: ${serializeOptionValue(value)}\` option is invalid: it cannot be a TTY with synchronous methods.`);
|
|
28856
28858
|
}
|
|
28857
|
-
return { type: "uint8Array", value: bufferToUint8Array(
|
|
28859
|
+
return { type: "uint8Array", value: bufferToUint8Array(readFileSync3(targetFdNumber)), optionName };
|
|
28858
28860
|
}, getTargetFdNumber = (value, fdNumber) => {
|
|
28859
28861
|
if (value === "inherit") {
|
|
28860
28862
|
return fdNumber;
|
|
@@ -29157,7 +29159,7 @@ var init_handle = __esm(() => {
|
|
|
29157
29159
|
});
|
|
29158
29160
|
|
|
29159
29161
|
// ../../node_modules/execa/lib/stdio/handle-sync.js
|
|
29160
|
-
import { readFileSync as
|
|
29162
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
29161
29163
|
var handleStdioSync = (options3, verboseInfo) => handleStdio(addPropertiesSync, options3, verboseInfo, true), forbiddenIfSync = ({ type, optionName }) => {
|
|
29162
29164
|
throwInvalidSyncValue(optionName, TYPE_TO_MESSAGE[type]);
|
|
29163
29165
|
}, forbiddenNativeIfSync = ({ optionName, value }) => {
|
|
@@ -29185,8 +29187,8 @@ var init_handle_sync = __esm(() => {
|
|
|
29185
29187
|
addPropertiesSync = {
|
|
29186
29188
|
input: {
|
|
29187
29189
|
...addProperties,
|
|
29188
|
-
fileUrl: ({ value }) => ({ contents: [bufferToUint8Array(
|
|
29189
|
-
filePath: ({ value: { file } }) => ({ contents: [bufferToUint8Array(
|
|
29190
|
+
fileUrl: ({ value }) => ({ contents: [bufferToUint8Array(readFileSync4(value))] }),
|
|
29191
|
+
filePath: ({ value: { file } }) => ({ contents: [bufferToUint8Array(readFileSync4(file))] }),
|
|
29190
29192
|
fileNumber: forbiddenIfSync,
|
|
29191
29193
|
iterable: ({ value }) => ({ contents: [...value] }),
|
|
29192
29194
|
string: ({ value }) => ({ contents: [value] }),
|
|
@@ -29555,7 +29557,7 @@ var init_output2 = __esm(() => {
|
|
|
29555
29557
|
});
|
|
29556
29558
|
|
|
29557
29559
|
// ../../node_modules/execa/lib/io/output-sync.js
|
|
29558
|
-
import { writeFileSync as
|
|
29560
|
+
import { writeFileSync as writeFileSync3, appendFileSync } from "node:fs";
|
|
29559
29561
|
var transformOutputSync = ({ fileDescriptors, syncResult: { output }, options: options3, isMaxBuffer, verboseInfo }) => {
|
|
29560
29562
|
if (output === null) {
|
|
29561
29563
|
return { output: Array.from({ length: 3 }) };
|
|
@@ -29648,7 +29650,7 @@ var transformOutputSync = ({ fileDescriptors, syncResult: { output }, options: o
|
|
|
29648
29650
|
appendFileSync(path9, serializedResult);
|
|
29649
29651
|
} else {
|
|
29650
29652
|
outputFiles.add(pathString);
|
|
29651
|
-
|
|
29653
|
+
writeFileSync3(path9, serializedResult);
|
|
29652
29654
|
}
|
|
29653
29655
|
}
|
|
29654
29656
|
};
|
|
@@ -32437,7 +32439,7 @@ var {
|
|
|
32437
32439
|
// package.json
|
|
32438
32440
|
var package_default = {
|
|
32439
32441
|
name: "@secondlayer/cli",
|
|
32440
|
-
version: "3.5.
|
|
32442
|
+
version: "3.5.4",
|
|
32441
32443
|
description: "CLI for subgraphs and blockchain indexing on Stacks",
|
|
32442
32444
|
type: "module",
|
|
32443
32445
|
bin: {
|
|
@@ -32480,10 +32482,10 @@ var package_default = {
|
|
|
32480
32482
|
dependencies: {
|
|
32481
32483
|
"@inquirer/prompts": "^8.2.0",
|
|
32482
32484
|
"@secondlayer/bundler": "^0.3.2",
|
|
32483
|
-
"@secondlayer/sdk": "^3.2.
|
|
32484
|
-
"@secondlayer/shared": "^4.3.
|
|
32485
|
+
"@secondlayer/sdk": "^3.2.2",
|
|
32486
|
+
"@secondlayer/shared": "^4.3.4",
|
|
32485
32487
|
"@secondlayer/stacks": "^2.0.0",
|
|
32486
|
-
"@secondlayer/subgraphs": "^1.2
|
|
32488
|
+
"@secondlayer/subgraphs": "^1.3.2",
|
|
32487
32489
|
"@biomejs/js-api": "^0.7.0",
|
|
32488
32490
|
"@biomejs/wasm-nodejs": "^1.9.0",
|
|
32489
32491
|
esbuild: "^0.19.0",
|
|
@@ -32562,8 +32564,8 @@ async function backfillSubgraphApi(name, options) {
|
|
|
32562
32564
|
async function stopSubgraphApi(name) {
|
|
32563
32565
|
return (await getTenantClient()).subgraphs.stop(name);
|
|
32564
32566
|
}
|
|
32565
|
-
async function deleteSubgraphApi(name) {
|
|
32566
|
-
return (await getTenantClient()).subgraphs.delete(name);
|
|
32567
|
+
async function deleteSubgraphApi(name, options) {
|
|
32568
|
+
return (await getTenantClient()).subgraphs.delete(name, options);
|
|
32567
32569
|
}
|
|
32568
32570
|
async function deploySubgraphApi(data) {
|
|
32569
32571
|
return (await getTenantClient()).subgraphs.deploy(data);
|
|
@@ -33194,6 +33196,7 @@ async function createSubscription(name, opts) {
|
|
|
33194
33196
|
TASK_ID: `${subgraph}-${table}`
|
|
33195
33197
|
});
|
|
33196
33198
|
let signingSecret = null;
|
|
33199
|
+
let provisioningFailed = false;
|
|
33197
33200
|
if (!opts.skipApi) {
|
|
33198
33201
|
try {
|
|
33199
33202
|
if (!sl)
|
|
@@ -33211,8 +33214,9 @@ async function createSubscription(name, opts) {
|
|
|
33211
33214
|
signingSecret = res.signingSecret;
|
|
33212
33215
|
success(`Subscription provisioned: ${blue(res.subscription.id)}`);
|
|
33213
33216
|
} catch (err) {
|
|
33217
|
+
provisioningFailed = true;
|
|
33214
33218
|
warn(`Subscription provisioning failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
33215
|
-
info("Template copied
|
|
33219
|
+
info("Template copied, but the subscription was not created. Provision it in the dashboard, or remove the template directory and rerun this command after fixing the API error.");
|
|
33216
33220
|
}
|
|
33217
33221
|
}
|
|
33218
33222
|
if (signingSecret) {
|
|
@@ -33234,6 +33238,10 @@ ${dim(" ")}${signingSecret}`);
|
|
|
33234
33238
|
}
|
|
33235
33239
|
}
|
|
33236
33240
|
console.log();
|
|
33241
|
+
if (provisioningFailed) {
|
|
33242
|
+
error("Subscription was not created.");
|
|
33243
|
+
process.exit(1);
|
|
33244
|
+
}
|
|
33237
33245
|
success(`Done. Next:
|
|
33238
33246
|
cd ${name}
|
|
33239
33247
|
bun install
|
|
@@ -34307,8 +34315,15 @@ async function resyncDatabase(skipConfirm, backfill) {
|
|
|
34307
34315
|
}
|
|
34308
34316
|
}
|
|
34309
34317
|
// src/commands/subgraphs.ts
|
|
34310
|
-
import {
|
|
34311
|
-
|
|
34318
|
+
import {
|
|
34319
|
+
existsSync as existsSync3,
|
|
34320
|
+
mkdirSync as mkdirSync2,
|
|
34321
|
+
readFileSync as readFileSync2,
|
|
34322
|
+
watch,
|
|
34323
|
+
writeFileSync as writeFileSync2
|
|
34324
|
+
} from "node:fs";
|
|
34325
|
+
import { dirname as dirname4, join as join7, resolve as resolve3 } from "node:path";
|
|
34326
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
34312
34327
|
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
34313
34328
|
|
|
34314
34329
|
// src/generators/subgraph-scaffold.ts
|
|
@@ -34583,6 +34598,45 @@ function parseStartBlockOption(value) {
|
|
|
34583
34598
|
}
|
|
34584
34599
|
return parsed;
|
|
34585
34600
|
}
|
|
34601
|
+
function readCliSubgraphsDependency() {
|
|
34602
|
+
const here = dirname4(fileURLToPath2(import.meta.url));
|
|
34603
|
+
const candidates = [
|
|
34604
|
+
resolve3(here, "..", "..", "package.json"),
|
|
34605
|
+
resolve3(here, "..", "package.json")
|
|
34606
|
+
];
|
|
34607
|
+
for (const candidate of candidates) {
|
|
34608
|
+
if (!existsSync3(candidate))
|
|
34609
|
+
continue;
|
|
34610
|
+
const pkg = JSON.parse(readFileSync2(candidate, "utf8"));
|
|
34611
|
+
const dep = pkg.dependencies?.["@secondlayer/subgraphs"];
|
|
34612
|
+
if (dep)
|
|
34613
|
+
return dep;
|
|
34614
|
+
}
|
|
34615
|
+
return "^1.3.2";
|
|
34616
|
+
}
|
|
34617
|
+
function ensureScaffoldPackageJson(dir) {
|
|
34618
|
+
const packagePath = join7(dir, "package.json");
|
|
34619
|
+
const subgraphsDep = readCliSubgraphsDependency();
|
|
34620
|
+
if (!existsSync3(packagePath)) {
|
|
34621
|
+
writeFileSync2(packagePath, `${JSON.stringify({
|
|
34622
|
+
type: "module",
|
|
34623
|
+
dependencies: {
|
|
34624
|
+
"@secondlayer/subgraphs": subgraphsDep
|
|
34625
|
+
}
|
|
34626
|
+
}, null, 2)}
|
|
34627
|
+
`, "utf8");
|
|
34628
|
+
return;
|
|
34629
|
+
}
|
|
34630
|
+
const pkg = JSON.parse(readFileSync2(packagePath, "utf8"));
|
|
34631
|
+
if (pkg.dependencies?.["@secondlayer/subgraphs"])
|
|
34632
|
+
return;
|
|
34633
|
+
pkg.dependencies = {
|
|
34634
|
+
...pkg.dependencies ?? {},
|
|
34635
|
+
"@secondlayer/subgraphs": subgraphsDep
|
|
34636
|
+
};
|
|
34637
|
+
writeFileSync2(packagePath, `${JSON.stringify(pkg, null, 2)}
|
|
34638
|
+
`, "utf8");
|
|
34639
|
+
}
|
|
34586
34640
|
function createSubgraphDeployPreview(def, options2 = {}) {
|
|
34587
34641
|
const tableColumns = Object.entries(def.schema).map(([table, schema]) => `${table}: ${Object.keys(schema.columns).join(", ") || "(no columns)"}`);
|
|
34588
34642
|
return {
|
|
@@ -34771,6 +34825,7 @@ Stopped watching.`);
|
|
|
34771
34825
|
sources: effectiveDef.sources,
|
|
34772
34826
|
schema: effectiveDef.schema,
|
|
34773
34827
|
handlerCode,
|
|
34828
|
+
sourceCode: source,
|
|
34774
34829
|
...startBlock !== undefined ? { startBlock } : {}
|
|
34775
34830
|
});
|
|
34776
34831
|
if (result.action === "unchanged") {
|
|
@@ -34877,6 +34932,7 @@ ${data.length} subgraph(s) total`));
|
|
|
34877
34932
|
try {
|
|
34878
34933
|
const subgraph = await getSubgraphApi(name);
|
|
34879
34934
|
const rowCounts = Object.entries(subgraph.tables).map(([t, info2]) => `${t}: ${info2.rowCount}`).join(", ") || "N/A";
|
|
34935
|
+
const totalRows = Object.values(subgraph.tables).reduce((sum, info2) => sum + info2.rowCount, 0);
|
|
34880
34936
|
const errorRate = subgraph.health.totalProcessed > 0 ? `${(subgraph.health.errorRate * 100).toFixed(2)}%` : "N/A";
|
|
34881
34937
|
const sync = subgraph.sync;
|
|
34882
34938
|
const syncDisplay = sync ? formatSubgraphSync(sync) : {
|
|
@@ -34895,7 +34951,8 @@ ${data.length} subgraph(s) total`));
|
|
|
34895
34951
|
["Integrity", integrity],
|
|
34896
34952
|
["Gaps", gapSummary],
|
|
34897
34953
|
["Last Block", String(subgraph.lastProcessedBlock)],
|
|
34898
|
-
["
|
|
34954
|
+
["Rows Indexed", totalRows.toLocaleString()],
|
|
34955
|
+
["Table Rows", rowCounts],
|
|
34899
34956
|
["Total Errors", String(subgraph.health.totalErrors)],
|
|
34900
34957
|
["Error Rate", errorRate],
|
|
34901
34958
|
["Last Error", subgraph.health.lastError ?? "none"],
|
|
@@ -35040,9 +35097,9 @@ ${rows.length} row(s)`));
|
|
|
35040
35097
|
handleApiError(err, "query subgraph");
|
|
35041
35098
|
}
|
|
35042
35099
|
});
|
|
35043
|
-
subgraphs.command("delete <name>").description("Delete a subgraph and its data").option("-y, --yes", "Skip confirmation").action(async (name, options2) => {
|
|
35100
|
+
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) => {
|
|
35044
35101
|
try {
|
|
35045
|
-
if (!options2.yes) {
|
|
35102
|
+
if (!options2.yes && !options2.force) {
|
|
35046
35103
|
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
|
35047
35104
|
const ok = await confirm4({
|
|
35048
35105
|
message: `Delete subgraph "${name}" and all its data? This cannot be undone.`
|
|
@@ -35052,7 +35109,9 @@ ${rows.length} row(s)`));
|
|
|
35052
35109
|
return;
|
|
35053
35110
|
}
|
|
35054
35111
|
}
|
|
35055
|
-
const result = await deleteSubgraphApi(name
|
|
35112
|
+
const result = await deleteSubgraphApi(name, {
|
|
35113
|
+
force: options2.force
|
|
35114
|
+
});
|
|
35056
35115
|
success(result.message);
|
|
35057
35116
|
} catch (err) {
|
|
35058
35117
|
handleApiError(err, "delete subgraph");
|
|
@@ -35080,6 +35139,7 @@ ${rows.length} row(s)`));
|
|
|
35080
35139
|
if (!existsSync3(dir))
|
|
35081
35140
|
mkdirSync2(dir, { recursive: true });
|
|
35082
35141
|
await writeTextFile(outPath, content);
|
|
35142
|
+
ensureScaffoldPackageJson(dir);
|
|
35083
35143
|
success(`Created ${outPath}`);
|
|
35084
35144
|
info(`Next: sl subgraphs deploy ${options2.output}`);
|
|
35085
35145
|
} catch (err) {
|
|
@@ -36039,6 +36099,7 @@ init_output();
|
|
|
36039
36099
|
init_project_file();
|
|
36040
36100
|
init_resolve_tenant();
|
|
36041
36101
|
import { confirm as confirm5, input as input4, select as select4 } from "@inquirer/prompts";
|
|
36102
|
+
var INSTANCE_CREATE_TIMEOUT_MS = 180000;
|
|
36042
36103
|
function registerInstanceCommand(program2) {
|
|
36043
36104
|
const instance = program2.command("instance").description("Manage your dedicated Secondlayer instance");
|
|
36044
36105
|
instance.command("create").description("Provision a new dedicated instance for the active project").option("--plan <plan>", "Plan: hobby (free) | launch | grow | scale", "hobby").action(async (opts) => {
|
|
@@ -36049,14 +36110,22 @@ function registerInstanceCommand(program2) {
|
|
|
36049
36110
|
error(`Invalid plan: ${plan} (expected hobby, launch, grow, or scale)`);
|
|
36050
36111
|
process.exit(1);
|
|
36051
36112
|
}
|
|
36113
|
+
const spinner = createSpinner("Provisioning your instance (~60s; safe to interrupt — instance will still be created; check `sl instance info`)");
|
|
36052
36114
|
try {
|
|
36053
36115
|
const res = await httpPlatform(`/api/projects/${encodeURIComponent(activeSlug)}/instance`, {
|
|
36054
36116
|
method: "POST",
|
|
36055
|
-
body: { plan }
|
|
36117
|
+
body: { plan },
|
|
36118
|
+
timeoutMs: INSTANCE_CREATE_TIMEOUT_MS
|
|
36056
36119
|
});
|
|
36057
|
-
|
|
36120
|
+
spinner.succeed(`Instance provisioned: ${res.tenant.slug}`);
|
|
36058
36121
|
printKeyReveal(res.tenant, res.credentials);
|
|
36059
36122
|
} catch (err) {
|
|
36123
|
+
if (isTimeoutError(err)) {
|
|
36124
|
+
spinner.fail("Provision request timed out after 3 minutes.");
|
|
36125
|
+
error("Provisioning may still finish server-side. Run `sl instance info` to check before retrying.");
|
|
36126
|
+
process.exit(1);
|
|
36127
|
+
}
|
|
36128
|
+
spinner.fail("Provision failed.");
|
|
36060
36129
|
handleInstanceError(err, "provision instance");
|
|
36061
36130
|
}
|
|
36062
36131
|
});
|
|
@@ -36135,6 +36204,10 @@ function registerInstanceCommand(program2) {
|
|
|
36135
36204
|
}
|
|
36136
36205
|
const slug = info_.tenant.slug;
|
|
36137
36206
|
if (!opts.yes) {
|
|
36207
|
+
if (!process.stdin.isTTY) {
|
|
36208
|
+
error(`Refusing to prompt in a non-interactive terminal. Re-run with --yes to delete instance "${slug}".`);
|
|
36209
|
+
process.exit(1);
|
|
36210
|
+
}
|
|
36138
36211
|
const typed = await input4({
|
|
36139
36212
|
message: `Type the slug "${slug}" to confirm permanent deletion`,
|
|
36140
36213
|
validate: (v) => v === slug ? true : "Slug must match exactly"
|
|
@@ -36302,6 +36375,43 @@ function printKeyReveal(tenant, creds) {
|
|
|
36302
36375
|
console.log(dim("Run `sl subgraphs deploy <file>` to deploy your first subgraph."));
|
|
36303
36376
|
console.log("");
|
|
36304
36377
|
}
|
|
36378
|
+
function createSpinner(message) {
|
|
36379
|
+
if (!process.stderr.isTTY) {
|
|
36380
|
+
info(message);
|
|
36381
|
+
return {
|
|
36382
|
+
succeed: success,
|
|
36383
|
+
fail: error
|
|
36384
|
+
};
|
|
36385
|
+
}
|
|
36386
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
36387
|
+
let index = 0;
|
|
36388
|
+
const render = () => {
|
|
36389
|
+
const frame = frames[index % frames.length] ?? frames[0];
|
|
36390
|
+
index += 1;
|
|
36391
|
+
process.stderr.write(`\r${blue(frame)} ${message}`);
|
|
36392
|
+
};
|
|
36393
|
+
const clear = () => {
|
|
36394
|
+
clearInterval(timer3);
|
|
36395
|
+
process.stderr.write("\r\x1B[2K");
|
|
36396
|
+
};
|
|
36397
|
+
const timer3 = setInterval(render, 80);
|
|
36398
|
+
render();
|
|
36399
|
+
return {
|
|
36400
|
+
succeed(message2) {
|
|
36401
|
+
clear();
|
|
36402
|
+
success(message2);
|
|
36403
|
+
},
|
|
36404
|
+
fail(message2) {
|
|
36405
|
+
clear();
|
|
36406
|
+
error(message2);
|
|
36407
|
+
}
|
|
36408
|
+
};
|
|
36409
|
+
}
|
|
36410
|
+
function isTimeoutError(err) {
|
|
36411
|
+
if (!(err instanceof Error))
|
|
36412
|
+
return false;
|
|
36413
|
+
return err.name === "TimeoutError" || err.name === "AbortError" || err.message.toLowerCase().includes("timeout");
|
|
36414
|
+
}
|
|
36305
36415
|
function warn_box(message) {
|
|
36306
36416
|
return `${"━".repeat(message.length + 4)}
|
|
36307
36417
|
${message}
|
|
@@ -36321,10 +36431,10 @@ function handleInstanceError(err, action) {
|
|
|
36321
36431
|
error("This project already has an instance. Run `sl instance info` to see it.");
|
|
36322
36432
|
process.exit(1);
|
|
36323
36433
|
}
|
|
36324
|
-
error(err.message);
|
|
36434
|
+
error(err.message || `Failed to ${action}.`);
|
|
36325
36435
|
process.exit(1);
|
|
36326
36436
|
}
|
|
36327
|
-
error(`Failed to ${action}: ${err instanceof Error ? err.message : String(err)}`);
|
|
36437
|
+
error(`Failed to ${action}: ${err instanceof Error ? err.message || "Unknown error" : String(err)}`);
|
|
36328
36438
|
process.exit(1);
|
|
36329
36439
|
}
|
|
36330
36440
|
// src/commands/project.ts
|
|
@@ -36335,15 +36445,24 @@ init_project_file();
|
|
|
36335
36445
|
import { input as input5 } from "@inquirer/prompts";
|
|
36336
36446
|
function registerProjectCommand(program2) {
|
|
36337
36447
|
const project = program2.command("project").description("Manage Secondlayer projects");
|
|
36338
|
-
project.command("create [name]").description("Create a new project").action(async (nameArg) => {
|
|
36448
|
+
project.command("create [name]").description("Create a new project").option("--slug <slug>", "Project URL identifier").action(async (nameArg, options2 = {}) => {
|
|
36339
36449
|
const name = nameArg ?? await input5({
|
|
36340
36450
|
message: "Project name",
|
|
36341
36451
|
validate: (v) => v.length >= 2 ? true : "Name must be at least 2 characters"
|
|
36342
36452
|
});
|
|
36453
|
+
const slug = options2.slug ?? slugifyProjectName(name);
|
|
36454
|
+
const validation = validateProjectSlug(slug);
|
|
36455
|
+
if (validation !== true) {
|
|
36456
|
+
error(`${validation}. Pass --slug <slug> to choose one explicitly.`);
|
|
36457
|
+
process.exit(1);
|
|
36458
|
+
}
|
|
36343
36459
|
try {
|
|
36344
|
-
const res = await httpPlatform("/api/projects", {
|
|
36345
|
-
|
|
36346
|
-
|
|
36460
|
+
const res = await httpPlatform("/api/projects", {
|
|
36461
|
+
method: "POST",
|
|
36462
|
+
body: { name, slug }
|
|
36463
|
+
});
|
|
36464
|
+
success(`Created project ${res.name} (${res.slug})`);
|
|
36465
|
+
const path2 = await writeActiveProject(res.slug, process.cwd());
|
|
36347
36466
|
info(dim(`Bound to this directory → ${path2}`));
|
|
36348
36467
|
info(dim("Next: sl instance create --plan launch"));
|
|
36349
36468
|
} catch (err) {
|
|
@@ -36410,6 +36529,18 @@ function handleProjectError(err) {
|
|
|
36410
36529
|
error(err instanceof Error ? err.message : String(err));
|
|
36411
36530
|
process.exit(1);
|
|
36412
36531
|
}
|
|
36532
|
+
function slugifyProjectName(name) {
|
|
36533
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63).replace(/-+$/g, "");
|
|
36534
|
+
}
|
|
36535
|
+
function validateProjectSlug(slug) {
|
|
36536
|
+
if (slug.length < 2 || slug.length > 63) {
|
|
36537
|
+
return "Project slug must be 2-63 characters";
|
|
36538
|
+
}
|
|
36539
|
+
if (!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(slug)) {
|
|
36540
|
+
return "Project slug must use lowercase letters, numbers, and hyphens, and start/end with a letter or number";
|
|
36541
|
+
}
|
|
36542
|
+
return true;
|
|
36543
|
+
}
|
|
36413
36544
|
// src/cli.ts
|
|
36414
36545
|
var { version } = package_default;
|
|
36415
36546
|
program.name("secondlayer").alias("sl").description("SecondLayer CLI — dedicated Stacks indexing + real-time subgraphs").version(version).option("--network <network>", "Override network (local, testnet, mainnet)");
|
|
@@ -36451,5 +36582,5 @@ registerLocalCommand(program);
|
|
|
36451
36582
|
registerAccountCommand(program);
|
|
36452
36583
|
program.parse();
|
|
36453
36584
|
|
|
36454
|
-
//# debugId=
|
|
36585
|
+
//# debugId=96B7A917235EEA4164756E2164756E21
|
|
36455
36586
|
//# sourceMappingURL=cli.js.map
|