@datacore-one/cli 1.0.7 → 1.0.9
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/index.js +166 -76
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -8502,7 +8502,7 @@ function checkNode(platform2) {
|
|
|
8502
8502
|
if (installed) {
|
|
8503
8503
|
version = getVersion("node", "-v");
|
|
8504
8504
|
const major = parseInt(version?.replace("v", "").split(".")[0] ?? "0", 10);
|
|
8505
|
-
meetsMin = major >=
|
|
8505
|
+
meetsMin = major >= 20;
|
|
8506
8506
|
}
|
|
8507
8507
|
return {
|
|
8508
8508
|
name: "node",
|
|
@@ -9687,6 +9687,38 @@ function runArgs(cmd, args, opts) {
|
|
|
9687
9687
|
return false;
|
|
9688
9688
|
}
|
|
9689
9689
|
}
|
|
9690
|
+
function runArgsWithError(cmd, args, opts) {
|
|
9691
|
+
try {
|
|
9692
|
+
execFileSync2(cmd, args, { stdio: "pipe", cwd: opts?.cwd, timeout: opts?.timeout });
|
|
9693
|
+
return { ok: true };
|
|
9694
|
+
} catch (err) {
|
|
9695
|
+
const stderr = err?.stderr?.toString().trim() || "";
|
|
9696
|
+
return { ok: false, stderr };
|
|
9697
|
+
}
|
|
9698
|
+
}
|
|
9699
|
+
function initGitInDir(repoUrl, dir, timeout = 300000) {
|
|
9700
|
+
let r = runArgsWithError("git", ["init"], { cwd: dir, timeout: 30000 });
|
|
9701
|
+
if (!r.ok)
|
|
9702
|
+
return r;
|
|
9703
|
+
r = runArgsWithError("git", ["remote", "add", "origin", repoUrl], { cwd: dir, timeout: 5000 });
|
|
9704
|
+
if (!r.ok) {
|
|
9705
|
+
r = runArgsWithError("git", ["remote", "set-url", "origin", repoUrl], { cwd: dir, timeout: 5000 });
|
|
9706
|
+
if (!r.ok)
|
|
9707
|
+
return r;
|
|
9708
|
+
}
|
|
9709
|
+
r = runArgsWithError("git", ["fetch", "origin"], { cwd: dir, timeout });
|
|
9710
|
+
if (!r.ok)
|
|
9711
|
+
return r;
|
|
9712
|
+
const headRef = runArgsOutput("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], { timeout: 5000 });
|
|
9713
|
+
const branch = headRef?.replace("refs/remotes/origin/", "") || "main";
|
|
9714
|
+
r = runArgsWithError("git", ["reset", `origin/${branch}`], { cwd: dir, timeout: 30000 });
|
|
9715
|
+
if (!r.ok)
|
|
9716
|
+
return r;
|
|
9717
|
+
runArgs("git", ["branch", "-M", branch], { cwd: dir });
|
|
9718
|
+
runArgs("git", ["branch", "--set-upstream-to", `origin/${branch}`], { cwd: dir });
|
|
9719
|
+
runArgs("git", ["checkout", "--", "."], { cwd: dir, timeout: 60000 });
|
|
9720
|
+
return { ok: true };
|
|
9721
|
+
}
|
|
9690
9722
|
function runArgsOutput(cmd, args, opts) {
|
|
9691
9723
|
try {
|
|
9692
9724
|
return execFileSync2(cmd, args, { encoding: "utf-8", stdio: "pipe", timeout: opts?.timeout }).trim();
|
|
@@ -9870,7 +9902,7 @@ function isInitialized() {
|
|
|
9870
9902
|
}
|
|
9871
9903
|
}
|
|
9872
9904
|
async function initDatacore(options = {}) {
|
|
9873
|
-
const { nonInteractive = false, skipChecks = false, stream = false, verbose = false } = options;
|
|
9905
|
+
const { nonInteractive = false, skipChecks = false, stream = false, verbose = false, force = false } = options;
|
|
9874
9906
|
const isTTY = stream && process.stdout.isTTY;
|
|
9875
9907
|
const interactive = isTTY && !nonInteractive;
|
|
9876
9908
|
const platform2 = detectPlatform();
|
|
@@ -10065,94 +10097,151 @@ async function initDatacore(options = {}) {
|
|
|
10065
10097
|
console.log();
|
|
10066
10098
|
}
|
|
10067
10099
|
const ghAuth = checkGhAuth();
|
|
10068
|
-
|
|
10100
|
+
const upstreamUrl = `https://github.com/${UPSTREAM_REPO}.git`;
|
|
10101
|
+
let ghUser;
|
|
10102
|
+
if (ghAuth.available) {
|
|
10103
|
+
ghUser = ghAuth.user || runArgsOutput("gh", ["api", "user", "-q", ".login"], { timeout: 15000 });
|
|
10104
|
+
const forkSpinner = isTTY ? new Spinner("Checking fork...") : null;
|
|
10105
|
+
forkSpinner?.start();
|
|
10106
|
+
const forkExists = runArgs("gh", ["repo", "view", `${ghUser}/datacore`], { cwd: process.env.HOME, timeout: 30000 });
|
|
10107
|
+
if (!forkExists) {
|
|
10108
|
+
forkSpinner?.update("Forking repository...");
|
|
10109
|
+
const forked = runArgs("gh", ["repo", "fork", UPSTREAM_REPO, "--clone=false"], { timeout: 30000 });
|
|
10110
|
+
if (forked) {
|
|
10111
|
+
forkSpinner?.succeed(`Forked to ${ghUser}/datacore`);
|
|
10112
|
+
} else {
|
|
10113
|
+
forkSpinner?.fail("Fork failed (will clone upstream directly)");
|
|
10114
|
+
result.warnings.push("Could not fork repository - will clone directly");
|
|
10115
|
+
ghUser = undefined;
|
|
10116
|
+
}
|
|
10117
|
+
} else {
|
|
10118
|
+
forkSpinner?.succeed(`Fork exists: ${ghUser}/datacore`);
|
|
10119
|
+
}
|
|
10120
|
+
}
|
|
10121
|
+
const cloneUrls = [];
|
|
10122
|
+
if (ghUser) {
|
|
10123
|
+
cloneUrls.push(`https://github.com/${ghUser}/datacore.git`);
|
|
10124
|
+
cloneUrls.push(`git@github.com:${ghUser}/datacore.git`);
|
|
10125
|
+
}
|
|
10126
|
+
if (!ghAuth.available && interactive) {
|
|
10127
|
+
const customUrl = await prompt(" Repository URL", upstreamUrl);
|
|
10128
|
+
cloneUrls.push(customUrl);
|
|
10129
|
+
const sshUrl = customUrl.replace("https://github.com/", "git@github.com:");
|
|
10130
|
+
if (sshUrl !== customUrl)
|
|
10131
|
+
cloneUrls.push(sshUrl);
|
|
10132
|
+
} else {
|
|
10133
|
+
cloneUrls.push(upstreamUrl);
|
|
10134
|
+
cloneUrls.push(`git@github.com:${UPSTREAM_REPO}.git`);
|
|
10135
|
+
}
|
|
10136
|
+
if (!ghAuth.available && interactive) {
|
|
10137
|
+
console.log(` ${c2.dim}GitHub CLI not authenticated. Cloning upstream directly.${c2.reset}`);
|
|
10138
|
+
console.log(` ${c2.dim}You can fork later with: gh repo fork --remote${c2.reset}`);
|
|
10139
|
+
console.log();
|
|
10140
|
+
}
|
|
10141
|
+
const hasGitDir = existsSync9(join10(DATA_DIR8, ".git"));
|
|
10142
|
+
const hasValidGit = hasGitDir && runArgs("git", ["rev-parse", "HEAD"], { cwd: DATA_DIR8, timeout: 5000 });
|
|
10143
|
+
if (hasValidGit) {
|
|
10069
10144
|
if (isTTY)
|
|
10070
10145
|
console.log(` ${c2.green}✓${c2.reset} Found existing repository at ~/Data`);
|
|
10071
|
-
const
|
|
10072
|
-
|
|
10146
|
+
const pullSpinner = isTTY ? new Spinner("Pulling latest changes...") : null;
|
|
10147
|
+
pullSpinner?.start();
|
|
10073
10148
|
if (runArgs("git", ["pull", "--rebase", "--autostash"], { cwd: DATA_DIR8, timeout: 60000 })) {
|
|
10074
|
-
|
|
10149
|
+
pullSpinner?.succeed("Repository up to date");
|
|
10075
10150
|
} else {
|
|
10076
|
-
|
|
10151
|
+
pullSpinner?.fail("Pull failed (non-fatal, continuing)");
|
|
10077
10152
|
result.warnings.push("Could not pull latest changes");
|
|
10078
10153
|
}
|
|
10079
|
-
|
|
10080
|
-
if (
|
|
10081
|
-
|
|
10082
|
-
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
|
|
10154
|
+
const currentUpstream = runArgsOutput("git", ["remote", "get-url", "upstream"]);
|
|
10155
|
+
if (!currentUpstream) {
|
|
10156
|
+
runArgs("git", ["remote", "add", "upstream", upstreamUrl], { cwd: DATA_DIR8 });
|
|
10157
|
+
}
|
|
10158
|
+
} else {
|
|
10159
|
+
mkdirSync6(DATA_DIR8, { recursive: true });
|
|
10160
|
+
const cloneSpinner = isTTY ? new Spinner("Cloning into ~/Data...") : null;
|
|
10161
|
+
cloneSpinner?.start();
|
|
10162
|
+
let lastCloneErr = "";
|
|
10163
|
+
let cloned = false;
|
|
10164
|
+
for (const url of cloneUrls) {
|
|
10165
|
+
const r = runArgsWithError("git", ["clone", url, "."], { cwd: DATA_DIR8, timeout: 300000 });
|
|
10166
|
+
if (r.ok) {
|
|
10167
|
+
cloned = true;
|
|
10168
|
+
break;
|
|
10169
|
+
}
|
|
10170
|
+
lastCloneErr = r.stderr || "";
|
|
10171
|
+
if (lastCloneErr.includes("already exists and is not an empty directory"))
|
|
10172
|
+
break;
|
|
10173
|
+
}
|
|
10174
|
+
if (cloned) {
|
|
10175
|
+
cloneSpinner?.succeed("Cloned into ~/Data");
|
|
10176
|
+
result.created.push(DATA_DIR8);
|
|
10177
|
+
if (ghUser) {
|
|
10178
|
+
runArgs("git", ["remote", "add", "upstream", upstreamUrl], { cwd: DATA_DIR8 });
|
|
10179
|
+
}
|
|
10180
|
+
} else if (lastCloneErr.includes("already exists and is not an empty directory")) {
|
|
10181
|
+
if (!force) {
|
|
10182
|
+
cloneSpinner?.fail("~/Data is not empty");
|
|
10183
|
+
const entries = readdirSync3(DATA_DIR8);
|
|
10184
|
+
if (isTTY) {
|
|
10185
|
+
console.log(` ${c2.dim}~/Data contains ${entries.length} items but is not a git repository.${c2.reset}`);
|
|
10186
|
+
console.log(` ${c2.dim}Use --force to initialize git in the existing directory.${c2.reset}`);
|
|
10187
|
+
console.log(` ${c2.dim}Or remove/rename ~/Data for a fresh install.${c2.reset}`);
|
|
10092
10188
|
}
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
let
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
|
|
10106
|
-
if (!cloned) {
|
|
10107
|
-
cloned = runArgs("git", ["clone", `git@github.com:${UPSTREAM_REPO}.git`, "."], { cwd: DATA_DIR8, timeout: 300000 });
|
|
10189
|
+
result.errors.push("~/Data exists and is not empty. Use --force to re-initialize.");
|
|
10190
|
+
op.failStep("clone_repo", "Directory not empty");
|
|
10191
|
+
op.fail("~/Data is not empty");
|
|
10192
|
+
return result;
|
|
10193
|
+
}
|
|
10194
|
+
cloneSpinner?.update("Initializing git in existing ~/Data...");
|
|
10195
|
+
let initOk = false;
|
|
10196
|
+
let lastInitErr = "";
|
|
10197
|
+
for (const url of cloneUrls) {
|
|
10198
|
+
const r = initGitInDir(url, DATA_DIR8);
|
|
10199
|
+
if (r.ok) {
|
|
10200
|
+
initOk = true;
|
|
10201
|
+
break;
|
|
10108
10202
|
}
|
|
10203
|
+
lastInitErr = r.stderr || "";
|
|
10109
10204
|
}
|
|
10110
|
-
if (
|
|
10111
|
-
cloneSpinner?.succeed("
|
|
10112
|
-
|
|
10113
|
-
|
|
10205
|
+
if (initOk) {
|
|
10206
|
+
cloneSpinner?.succeed("Git initialized in existing ~/Data");
|
|
10207
|
+
if (ghUser) {
|
|
10208
|
+
runArgs("git", ["remote", "add", "upstream", upstreamUrl], { cwd: DATA_DIR8 });
|
|
10209
|
+
}
|
|
10114
10210
|
} else {
|
|
10115
|
-
cloneSpinner?.fail("
|
|
10116
|
-
result.errors.push(
|
|
10117
|
-
|
|
10118
|
-
|
|
10211
|
+
cloneSpinner?.fail("Could not initialize git");
|
|
10212
|
+
result.errors.push(`Git init failed: ${lastInitErr}`);
|
|
10213
|
+
if (lastInitErr.includes("Authentication") || lastInitErr.includes("403") || lastInitErr.includes("401")) {
|
|
10214
|
+
if (isTTY)
|
|
10215
|
+
console.log(` ${c2.dim}Check your GitHub access: gh auth status${c2.reset}`);
|
|
10216
|
+
}
|
|
10217
|
+
op.failStep("clone_repo", "Git init failed");
|
|
10218
|
+
op.fail("Git init failed");
|
|
10119
10219
|
return result;
|
|
10120
10220
|
}
|
|
10121
10221
|
} else {
|
|
10122
|
-
|
|
10123
|
-
if (
|
|
10124
|
-
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
|
|
10134
|
-
|
|
10135
|
-
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
}
|
|
10139
|
-
if (cloned) {
|
|
10140
|
-
spinner?.succeed("Cloned into ~/Data");
|
|
10141
|
-
result.created.push(DATA_DIR8);
|
|
10222
|
+
cloneSpinner?.fail("Clone failed");
|
|
10223
|
+
if (lastCloneErr.includes("not found") || lastCloneErr.includes("not exist") || lastCloneErr.includes("does not appear to be a git repository")) {
|
|
10224
|
+
result.errors.push("Repository not found");
|
|
10225
|
+
if (isTTY) {
|
|
10226
|
+
if (ghUser) {
|
|
10227
|
+
console.log(` ${c2.dim}Neither ${ghUser}/datacore nor ${UPSTREAM_REPO} could be cloned.${c2.reset}`);
|
|
10228
|
+
}
|
|
10229
|
+
console.log(` ${c2.dim}Ensure you have access to ${UPSTREAM_REPO} and try again.${c2.reset}`);
|
|
10230
|
+
console.log(` ${c2.dim}Check access: gh repo view ${UPSTREAM_REPO}${c2.reset}`);
|
|
10231
|
+
}
|
|
10232
|
+
} else if (lastCloneErr.includes("Authentication") || lastCloneErr.includes("Permission") || lastCloneErr.includes("403") || lastCloneErr.includes("401")) {
|
|
10233
|
+
result.errors.push("Authentication failed");
|
|
10234
|
+
if (isTTY) {
|
|
10235
|
+
console.log(` ${c2.dim}Could not authenticate with GitHub.${c2.reset}`);
|
|
10236
|
+
console.log(` ${c2.dim}Try: gh auth login${c2.reset}`);
|
|
10237
|
+
}
|
|
10142
10238
|
} else {
|
|
10143
|
-
|
|
10144
|
-
result.errors.push(`Could not clone from ${repoUrl}`);
|
|
10145
|
-
op.failStep("clone_repo", "Clone failed");
|
|
10146
|
-
op.fail("Clone failed");
|
|
10147
|
-
return result;
|
|
10239
|
+
result.errors.push(`Clone failed: ${lastCloneErr}`);
|
|
10148
10240
|
}
|
|
10241
|
+
op.failStep("clone_repo", "Clone failed");
|
|
10242
|
+
op.fail("Clone failed");
|
|
10243
|
+
return result;
|
|
10149
10244
|
}
|
|
10150
|
-
} else {
|
|
10151
|
-
if (isTTY) {
|
|
10152
|
-
console.log(` ${c2.yellow}⚠${c2.reset} ~/Data exists but is not a git repository`);
|
|
10153
|
-
console.log(` ${c2.dim}Expected a cloned Datacore repo. Some features may not work.${c2.reset}`);
|
|
10154
|
-
}
|
|
10155
|
-
result.warnings.push(`${DATA_DIR8} is not a git repository`);
|
|
10156
10245
|
}
|
|
10157
10246
|
const dipsDir = join10(DATACORE_DIR, "dips");
|
|
10158
10247
|
if (existsSync9(DATACORE_DIR) && !existsSync9(join10(dipsDir, ".git"))) {
|
|
@@ -10924,7 +11013,7 @@ async function initDatacore(options = {}) {
|
|
|
10924
11013
|
}
|
|
10925
11014
|
|
|
10926
11015
|
// src/index.ts
|
|
10927
|
-
var VERSION = "1.0.
|
|
11016
|
+
var VERSION = "1.0.9";
|
|
10928
11017
|
var args = process.argv.slice(2);
|
|
10929
11018
|
var parsed = parseArgs(args);
|
|
10930
11019
|
async function handleMeta(command, cmdArgs, flags, format) {
|
|
@@ -10948,7 +11037,8 @@ async function handleMeta(command, cmdArgs, flags, format) {
|
|
|
10948
11037
|
nonInteractive: flags.yes === true,
|
|
10949
11038
|
skipChecks: flags["skip-checks"] === true,
|
|
10950
11039
|
stream: format === "human",
|
|
10951
|
-
verbose: flags.verbose === true
|
|
11040
|
+
verbose: flags.verbose === true,
|
|
11041
|
+
force: flags.force === true
|
|
10952
11042
|
});
|
|
10953
11043
|
if (format === "json") {
|
|
10954
11044
|
output(result, format);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datacore-one/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "CLI for setting up and managing Datacore installations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"prepublishOnly": "bun run build"
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": ">=
|
|
23
|
+
"node": ">=20"
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
|
26
26
|
"datacore",
|