@united-robotics/cli 0.4.4 → 0.4.5
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 +55 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,23 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import { chmodSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
5
|
+
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
6
6
|
import { homedir, tmpdir } from "os";
|
|
7
|
-
import { basename, join } from "path";
|
|
7
|
+
import { basename, dirname, join, parse } from "path";
|
|
8
8
|
import { spawnSync } from "child_process";
|
|
9
|
-
var
|
|
10
|
-
var
|
|
9
|
+
var configFileName = "config.json";
|
|
10
|
+
var configDirName = ".united-robotics";
|
|
11
|
+
var globalConfigDir = join(homedir(), configDirName);
|
|
12
|
+
var globalConfigPath = join(globalConfigDir, configFileName);
|
|
11
13
|
var defaultApiUrl = process.env.UR_API_URL ?? "https://united-robotics.rollersoft.com.au";
|
|
12
14
|
function load() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const localPath = findLocalConfigPath(process.cwd());
|
|
16
|
+
for (const path of [process.env.UR_CONFIG, localPath, globalConfigPath].filter(Boolean)) {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
19
|
+
} catch {
|
|
20
|
+
}
|
|
17
21
|
}
|
|
22
|
+
return { apiUrl: defaultApiUrl };
|
|
18
23
|
}
|
|
19
|
-
function save(config) {
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
function save(config, opts = {}) {
|
|
25
|
+
const path = opts.global ? globalConfigPath : localConfigPath(process.cwd());
|
|
26
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
27
|
+
writeFileSync(path, JSON.stringify(config, null, 2));
|
|
22
28
|
}
|
|
23
29
|
async function api(path, init = {}) {
|
|
24
30
|
const cfg = load();
|
|
@@ -28,10 +34,10 @@ async function api(path, init = {}) {
|
|
|
28
34
|
}
|
|
29
35
|
var program = new Command();
|
|
30
36
|
program.name("ur").description("United Robotics customer CLI").version("0.1.0");
|
|
31
|
-
program.command("login").requiredOption("--token <token>").option("--api <url>").action((opts) => {
|
|
37
|
+
program.command("login").requiredOption("--token <token>").option("--api <url>").option("--global", "write ~/.united-robotics/config.json instead of the current workspace").action((opts) => {
|
|
32
38
|
const cfg = load();
|
|
33
|
-
save({ apiUrl: opts.api ?? cfg.apiUrl ?? defaultApiUrl, token: opts.token });
|
|
34
|
-
console.log(
|
|
39
|
+
save({ apiUrl: opts.api ?? cfg.apiUrl ?? defaultApiUrl, token: opts.token }, { global: opts.global });
|
|
40
|
+
console.log(`Logged in to United Robotics (${opts.global ? "global" : "workspace"} config)`);
|
|
35
41
|
});
|
|
36
42
|
program.command("whoami").action(async () => console.log(JSON.stringify(await api("/api/me"), null, 2)));
|
|
37
43
|
program.command("team").argument("<cmd>").action(async (cmd) => {
|
|
@@ -50,10 +56,15 @@ project.command("clone").argument("<projectId>").option("--dest <path>").option(
|
|
|
50
56
|
try {
|
|
51
57
|
if (opts.inPlace && opts.dest) throw new Error("Use either --in-place or --dest, not both.");
|
|
52
58
|
const dest = opts.inPlace ? "." : opts.dest;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
const preservedConfig = opts.inPlace ? preserveInPlaceWorkspaceConfig(process.cwd()) : null;
|
|
60
|
+
try {
|
|
61
|
+
if (opts.inPlace) assertInPlaceCloneTarget(process.cwd());
|
|
62
|
+
const cloneArgs = ["clone", primary.url];
|
|
63
|
+
if (dest) cloneArgs.push(dest);
|
|
64
|
+
runGit(cloneArgs, { cwd: process.cwd(), env: credentials.env, authHint: true });
|
|
65
|
+
} finally {
|
|
66
|
+
preservedConfig?.restore();
|
|
67
|
+
}
|
|
57
68
|
const worktree = dest ?? repoDirName(primary.url);
|
|
58
69
|
configureGitIdentity(worktree, opts.name, opts.email, credentials.env);
|
|
59
70
|
if (opts.submodules) initProjectWorktree(worktree, opts.name, opts.email, credentials.env);
|
|
@@ -179,6 +190,32 @@ function assertInPlaceCloneTarget(cwd) {
|
|
|
179
190
|
throw new Error(`Cannot in-place clone into a non-empty directory (${cwd}). Start from an empty Codex project root, or use --dest <path> intentionally.`);
|
|
180
191
|
}
|
|
181
192
|
}
|
|
193
|
+
function localConfigPath(cwd) {
|
|
194
|
+
return join(cwd, configDirName, configFileName);
|
|
195
|
+
}
|
|
196
|
+
function findLocalConfigPath(start) {
|
|
197
|
+
let dir = start;
|
|
198
|
+
const root = parse(start).root;
|
|
199
|
+
while (true) {
|
|
200
|
+
const candidate = localConfigPath(dir);
|
|
201
|
+
if (existsSync(candidate)) return candidate;
|
|
202
|
+
if (dir === root) return null;
|
|
203
|
+
dir = dirname(dir);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function preserveInPlaceWorkspaceConfig(cwd) {
|
|
207
|
+
const configDir = join(cwd, configDirName);
|
|
208
|
+
const configPath = join(configDir, configFileName);
|
|
209
|
+
if (!existsSync(configPath)) return null;
|
|
210
|
+
const content = readFileSync(configPath, "utf8");
|
|
211
|
+
rmSync(configDir, { recursive: true, force: true });
|
|
212
|
+
return {
|
|
213
|
+
restore: () => {
|
|
214
|
+
mkdirSync(configDir, { recursive: true });
|
|
215
|
+
writeFileSync(configPath, content);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
182
219
|
function gitBin() {
|
|
183
220
|
return process.env.UR_GIT_BIN || (process.platform === "darwin" ? "/usr/bin/git" : "git");
|
|
184
221
|
}
|