@braingrid/cli 0.2.45 → 0.2.47
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/CHANGELOG.md +13 -0
- package/dist/cli.js +75 -58
- package/dist/cli.js.map +1 -1
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.47] - 2026-02-20
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **Build hooks** — enforce git push before build session exit, source shared log-helper instead of duplicating logging setup
|
|
15
|
+
|
|
16
|
+
## [0.2.46] - 2026-02-20
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **Build sync errors** — log sync errors and add bulk status fallback
|
|
21
|
+
- **Cut-release command** — restore `/cut-release` slash command lost during previous refactor
|
|
22
|
+
|
|
10
23
|
## [0.2.45] - 2026-02-20
|
|
11
24
|
|
|
12
25
|
### Fixed
|
package/dist/cli.js
CHANGED
|
@@ -228,7 +228,7 @@ async function axiosWithRetry(config2, options) {
|
|
|
228
228
|
|
|
229
229
|
// src/build-config.ts
|
|
230
230
|
var BUILD_ENV = true ? "production" : process.env.NODE_ENV === "test" ? "development" : "production";
|
|
231
|
-
var CLI_VERSION = true ? "0.2.
|
|
231
|
+
var CLI_VERSION = true ? "0.2.47" : "0.0.0-test";
|
|
232
232
|
var PRODUCTION_CONFIG = {
|
|
233
233
|
apiUrl: "https://app.braingrid.ai",
|
|
234
234
|
workosAuthUrl: "https://auth.braingrid.ai",
|
|
@@ -2631,10 +2631,33 @@ var ProjectService = class {
|
|
|
2631
2631
|
// src/services/setup-service.ts
|
|
2632
2632
|
import * as fs2 from "fs/promises";
|
|
2633
2633
|
import * as path2 from "path";
|
|
2634
|
+
import axios5 from "axios";
|
|
2634
2635
|
var GITHUB_OWNER = "BrainGridAI";
|
|
2635
2636
|
var GITHUB_REPO = "braingrid";
|
|
2637
|
+
var GITHUB_API_BASE = `https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents`;
|
|
2636
2638
|
var MAX_RETRIES = 3;
|
|
2637
2639
|
var INITIAL_RETRY_DELAY = 100;
|
|
2640
|
+
async function getGitHubToken() {
|
|
2641
|
+
try {
|
|
2642
|
+
const { stdout } = await execAsync("gh auth token");
|
|
2643
|
+
return stdout.trim() || null;
|
|
2644
|
+
} catch {
|
|
2645
|
+
return null;
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
var cachedHeaders = null;
|
|
2649
|
+
async function getGitHubHeaders() {
|
|
2650
|
+
if (cachedHeaders) return cachedHeaders;
|
|
2651
|
+
const headers = {
|
|
2652
|
+
Accept: "application/vnd.github.v3+json"
|
|
2653
|
+
};
|
|
2654
|
+
const token = await getGitHubToken();
|
|
2655
|
+
if (token) {
|
|
2656
|
+
headers.Authorization = `token ${token}`;
|
|
2657
|
+
}
|
|
2658
|
+
cachedHeaders = headers;
|
|
2659
|
+
return headers;
|
|
2660
|
+
}
|
|
2638
2661
|
var BEGIN_MARKER = "<!-- BEGIN BRAINGRID INTEGRATION -->";
|
|
2639
2662
|
var END_MARKER = "<!-- END BRAINGRID INTEGRATION -->";
|
|
2640
2663
|
async function withRetry(fn, retries = MAX_RETRIES, delay = INITIAL_RETRY_DELAY) {
|
|
@@ -2644,8 +2667,7 @@ async function withRetry(fn, retries = MAX_RETRIES, delay = INITIAL_RETRY_DELAY)
|
|
|
2644
2667
|
if (retries === 0) {
|
|
2645
2668
|
throw error;
|
|
2646
2669
|
}
|
|
2647
|
-
const
|
|
2648
|
-
const isNetworkError = errorMessage.includes("ECONNRESET") || errorMessage.includes("ETIMEDOUT") || errorMessage.includes("ENOTFOUND") || errorMessage.includes("network");
|
|
2670
|
+
const isNetworkError = axios5.isAxiosError(error) && !error.response;
|
|
2649
2671
|
if (!isNetworkError) {
|
|
2650
2672
|
throw error;
|
|
2651
2673
|
}
|
|
@@ -2654,37 +2676,41 @@ async function withRetry(fn, retries = MAX_RETRIES, delay = INITIAL_RETRY_DELAY)
|
|
|
2654
2676
|
}
|
|
2655
2677
|
}
|
|
2656
2678
|
function parseGitHubError(error) {
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
return "GitHub API rate limit exceeded. Please wait a few minutes and try again.\nCheck rate limit status: gh api rate_limit";
|
|
2663
|
-
}
|
|
2664
|
-
if (errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
|
|
2665
|
-
return "GitHub CLI is not authenticated. Run: gh auth login";
|
|
2666
|
-
}
|
|
2667
|
-
try {
|
|
2668
|
-
const match = errorMessage.match(/\{.*\}/s);
|
|
2669
|
-
if (match) {
|
|
2670
|
-
const errorData = JSON.parse(match[0]);
|
|
2671
|
-
return errorData.message || errorMessage;
|
|
2679
|
+
if (axios5.isAxiosError(error)) {
|
|
2680
|
+
const status = error.response?.status;
|
|
2681
|
+
const data = error.response?.data;
|
|
2682
|
+
if (status === 404) {
|
|
2683
|
+
return "File or directory not found in BrainGrid repository";
|
|
2672
2684
|
}
|
|
2673
|
-
|
|
2685
|
+
if (status === 403) {
|
|
2686
|
+
return "GitHub API rate limit exceeded. Please wait a few minutes and try again.\nTip: Install GitHub CLI (gh) for higher rate limits: https://cli.github.com";
|
|
2687
|
+
}
|
|
2688
|
+
if (status === 401) {
|
|
2689
|
+
return "GitHub API authentication failed. Your gh auth token may be expired.";
|
|
2690
|
+
}
|
|
2691
|
+
if (data?.message) {
|
|
2692
|
+
return data.message;
|
|
2693
|
+
}
|
|
2694
|
+
if (!error.response) {
|
|
2695
|
+
return `Network error: ${error.message}`;
|
|
2696
|
+
}
|
|
2697
|
+
return error.message;
|
|
2674
2698
|
}
|
|
2675
|
-
return
|
|
2699
|
+
return error instanceof Error ? error.message : String(error);
|
|
2676
2700
|
}
|
|
2677
|
-
async function fetchFileFromGitHub(
|
|
2701
|
+
async function fetchFileFromGitHub(filePath) {
|
|
2678
2702
|
return withRetry(async () => {
|
|
2679
2703
|
try {
|
|
2680
|
-
const
|
|
2681
|
-
const {
|
|
2682
|
-
|
|
2704
|
+
const headers = await getGitHubHeaders();
|
|
2705
|
+
const { data: response } = await axios5.get(
|
|
2706
|
+
`${GITHUB_API_BASE}/${filePath}`,
|
|
2707
|
+
{ headers }
|
|
2708
|
+
);
|
|
2683
2709
|
if (response.type !== "file") {
|
|
2684
|
-
throw new Error(`Path ${
|
|
2710
|
+
throw new Error(`Path ${filePath} is not a file`);
|
|
2685
2711
|
}
|
|
2686
2712
|
if (!response.content || !response.encoding) {
|
|
2687
|
-
throw new Error(`No content found for file ${
|
|
2713
|
+
throw new Error(`No content found for file ${filePath}`);
|
|
2688
2714
|
}
|
|
2689
2715
|
if (response.encoding !== "base64") {
|
|
2690
2716
|
throw new Error(`Unexpected encoding: ${response.encoding}`);
|
|
@@ -2692,19 +2718,27 @@ async function fetchFileFromGitHub(path7) {
|
|
|
2692
2718
|
const content = Buffer.from(response.content, "base64").toString("utf8");
|
|
2693
2719
|
return content;
|
|
2694
2720
|
} catch (error) {
|
|
2721
|
+
if (axios5.isAxiosError(error) && !error.response) {
|
|
2722
|
+
throw error;
|
|
2723
|
+
}
|
|
2724
|
+
if (error instanceof Error && error.message.startsWith("Failed to fetch file")) {
|
|
2725
|
+
throw error;
|
|
2726
|
+
}
|
|
2695
2727
|
const parsedError = parseGitHubError(error);
|
|
2696
|
-
throw new Error(`Failed to fetch file ${
|
|
2728
|
+
throw new Error(`Failed to fetch file ${filePath}: ${parsedError}`);
|
|
2697
2729
|
}
|
|
2698
2730
|
});
|
|
2699
2731
|
}
|
|
2700
|
-
async function listGitHubDirectory(
|
|
2732
|
+
async function listGitHubDirectory(dirPath) {
|
|
2701
2733
|
return withRetry(async () => {
|
|
2702
2734
|
try {
|
|
2703
|
-
const
|
|
2704
|
-
const {
|
|
2705
|
-
|
|
2735
|
+
const headers = await getGitHubHeaders();
|
|
2736
|
+
const { data: response } = await axios5.get(
|
|
2737
|
+
`${GITHUB_API_BASE}/${dirPath}`,
|
|
2738
|
+
{ headers }
|
|
2739
|
+
);
|
|
2706
2740
|
if (!Array.isArray(response)) {
|
|
2707
|
-
throw new Error(`Path ${
|
|
2741
|
+
throw new Error(`Path ${dirPath} is not a directory`);
|
|
2708
2742
|
}
|
|
2709
2743
|
return response.map((item) => ({
|
|
2710
2744
|
name: item.name,
|
|
@@ -2712,8 +2746,14 @@ async function listGitHubDirectory(path7) {
|
|
|
2712
2746
|
path: item.path
|
|
2713
2747
|
}));
|
|
2714
2748
|
} catch (error) {
|
|
2749
|
+
if (axios5.isAxiosError(error) && !error.response) {
|
|
2750
|
+
throw error;
|
|
2751
|
+
}
|
|
2752
|
+
if (error instanceof Error && error.message.startsWith("Failed to list directory")) {
|
|
2753
|
+
throw error;
|
|
2754
|
+
}
|
|
2715
2755
|
const parsedError = parseGitHubError(error);
|
|
2716
|
-
throw new Error(`Failed to list directory ${
|
|
2756
|
+
throw new Error(`Failed to list directory ${dirPath}: ${parsedError}`);
|
|
2717
2757
|
}
|
|
2718
2758
|
});
|
|
2719
2759
|
}
|
|
@@ -3358,7 +3398,7 @@ function showSpinner(message, color = chalk7.cyan) {
|
|
|
3358
3398
|
import chalk8 from "chalk";
|
|
3359
3399
|
|
|
3360
3400
|
// src/utils/version.ts
|
|
3361
|
-
import
|
|
3401
|
+
import axios6 from "axios";
|
|
3362
3402
|
var PACKAGE_NAME = "@braingrid/cli";
|
|
3363
3403
|
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
|
|
3364
3404
|
function getCurrentVersion() {
|
|
@@ -3366,7 +3406,7 @@ function getCurrentVersion() {
|
|
|
3366
3406
|
}
|
|
3367
3407
|
async function getLatestVersion(timeout = 1e4) {
|
|
3368
3408
|
try {
|
|
3369
|
-
const response = await
|
|
3409
|
+
const response = await axios6.get(NPM_REGISTRY_URL, {
|
|
3370
3410
|
timeout
|
|
3371
3411
|
});
|
|
3372
3412
|
return response.data["dist-tags"].latest;
|
|
@@ -3467,25 +3507,6 @@ async function fileExists(filePath) {
|
|
|
3467
3507
|
return false;
|
|
3468
3508
|
}
|
|
3469
3509
|
}
|
|
3470
|
-
async function checkPrerequisites() {
|
|
3471
|
-
try {
|
|
3472
|
-
await execAsync("gh --version");
|
|
3473
|
-
} catch {
|
|
3474
|
-
return {
|
|
3475
|
-
success: false,
|
|
3476
|
-
message: chalk9.red("\u274C GitHub CLI is not installed.\n\n") + chalk9.dim("Install instructions:\n") + chalk9.dim(" macOS: ") + chalk9.cyan("brew install gh") + chalk9.dim("\n") + chalk9.dim(" Windows: ") + chalk9.cyan("winget install GitHub.CLI") + chalk9.dim("\n") + chalk9.dim(" Linux: See ") + chalk9.cyan("https://cli.github.com/manual/installation") + chalk9.dim("\n\n") + chalk9.dim("After installing, run: ") + chalk9.cyan("gh auth login")
|
|
3477
|
-
};
|
|
3478
|
-
}
|
|
3479
|
-
try {
|
|
3480
|
-
await execAsync("gh auth status");
|
|
3481
|
-
} catch {
|
|
3482
|
-
return {
|
|
3483
|
-
success: false,
|
|
3484
|
-
message: chalk9.red("\u274C Not authenticated with GitHub CLI.\n\n") + chalk9.dim("Please run: ") + chalk9.cyan("gh auth login")
|
|
3485
|
-
};
|
|
3486
|
-
}
|
|
3487
|
-
return null;
|
|
3488
|
-
}
|
|
3489
3510
|
async function getFileList(sourcePaths, targetPaths) {
|
|
3490
3511
|
const operations = [];
|
|
3491
3512
|
async function processDirectory(sourceDir, targetDir, dirIndex) {
|
|
@@ -3583,10 +3604,6 @@ async function installFiles(operations, force, dirCount) {
|
|
|
3583
3604
|
return { installedPerDir, skipped, cancelled: false };
|
|
3584
3605
|
}
|
|
3585
3606
|
async function _handleSetup(config2, opts) {
|
|
3586
|
-
const prerequisiteError = await checkPrerequisites();
|
|
3587
|
-
if (prerequisiteError) {
|
|
3588
|
-
return prerequisiteError;
|
|
3589
|
-
}
|
|
3590
3607
|
console.log(chalk9.bold(`\u{1F680} Setting up ${config2.name} integration...
|
|
3591
3608
|
`));
|
|
3592
3609
|
const operations = await getFileList(config2.sourceDirs, config2.targetDirs);
|