komplian 0.3.4 → 0.3.6
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/komplian-onboard.mjs +65 -47
- package/package.json +1 -1
package/komplian-onboard.mjs
CHANGED
|
@@ -18,6 +18,13 @@ import { homedir } from "node:os";
|
|
|
18
18
|
|
|
19
19
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
20
|
|
|
21
|
+
/** Windows: sin esto, CreateProcess no resuelve gh.cmd / git.exe / npm.cmd como la consola. */
|
|
22
|
+
const IS_WIN = process.platform === "win32";
|
|
23
|
+
|
|
24
|
+
function spawnWin(extra = {}) {
|
|
25
|
+
return IS_WIN ? { ...extra, shell: true } : extra;
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
const c = {
|
|
22
29
|
reset: "\x1b[0m",
|
|
23
30
|
dim: "\x1b[2m",
|
|
@@ -51,10 +58,14 @@ function banner() {
|
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
function ghOk() {
|
|
54
|
-
const r = spawnSync(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
const r = spawnSync(
|
|
62
|
+
"gh",
|
|
63
|
+
["auth", "status", "-h", "github.com"],
|
|
64
|
+
spawnWin({
|
|
65
|
+
encoding: "utf8",
|
|
66
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
67
|
+
})
|
|
68
|
+
);
|
|
58
69
|
return r.status === 0;
|
|
59
70
|
}
|
|
60
71
|
|
|
@@ -65,23 +76,28 @@ function runGhAuth() {
|
|
|
65
76
|
const r = spawnSync(
|
|
66
77
|
"gh",
|
|
67
78
|
["auth", "login", "-h", "github.com", "-s", "repo", "-s", "read:org", "-w"],
|
|
68
|
-
{ stdio: "inherit" }
|
|
79
|
+
spawnWin({ stdio: "inherit" })
|
|
69
80
|
);
|
|
70
81
|
return r.status === 0;
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
function ghApiJson(path) {
|
|
74
|
-
const r = spawnSync(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
85
|
+
const r = spawnSync(
|
|
86
|
+
"gh",
|
|
87
|
+
["api", path],
|
|
88
|
+
spawnWin({
|
|
89
|
+
encoding: "utf8",
|
|
90
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
91
|
+
})
|
|
92
|
+
);
|
|
78
93
|
return { status: r.status, stdout: r.stdout || "", stderr: r.stderr || "" };
|
|
79
94
|
}
|
|
80
95
|
|
|
81
96
|
function verifyOrgMembership(org) {
|
|
82
97
|
const enc = encodeURIComponent(org);
|
|
83
98
|
const mem = ghApiJson(`user/memberships/orgs/${enc}`);
|
|
84
|
-
|
|
99
|
+
/** spawnSync().status = código de salida de `gh` (0 = éxito), no código HTTP. */
|
|
100
|
+
if (mem.status === 0) {
|
|
85
101
|
try {
|
|
86
102
|
const j = JSON.parse(mem.stdout);
|
|
87
103
|
if (j.state === "active") return;
|
|
@@ -94,7 +110,8 @@ function verifyOrgMembership(org) {
|
|
|
94
110
|
process.exit(1);
|
|
95
111
|
}
|
|
96
112
|
}
|
|
97
|
-
|
|
113
|
+
const hint = (mem.stderr + mem.stdout).toLowerCase();
|
|
114
|
+
if (hint.includes("404") || hint.includes("not found")) {
|
|
98
115
|
log(
|
|
99
116
|
`${c.red}✗${c.reset} Esta cuenta ${c.bold}no es miembro${c.reset} de la org ${c.bold}${org}${c.reset}.`
|
|
100
117
|
);
|
|
@@ -103,21 +120,20 @@ function verifyOrgMembership(org) {
|
|
|
103
120
|
);
|
|
104
121
|
process.exit(1);
|
|
105
122
|
}
|
|
106
|
-
|
|
107
|
-
if (mem.status === 403 || hint.includes("read:org") || hint.includes("scope")) {
|
|
123
|
+
if (hint.includes("403") || hint.includes("read:org") || hint.includes("scope")) {
|
|
108
124
|
log(`${c.red}✗${c.reset} Falta scope ${c.bold}read:org${c.reset} en gh.`);
|
|
109
125
|
log(`${c.dim} gh auth refresh -h github.com -s repo -s read:org${c.reset}`);
|
|
110
126
|
process.exit(1);
|
|
111
127
|
}
|
|
112
128
|
log(
|
|
113
|
-
`${c.red}✗${c.reset} No se pudo verificar la org (${mem.status}):\n${c.dim}${(mem.stderr || mem.stdout).trim()}${c.reset}`
|
|
129
|
+
`${c.red}✗${c.reset} No se pudo verificar la org (código ${mem.status}):\n${c.dim}${(mem.stderr || mem.stdout).trim()}${c.reset}`
|
|
114
130
|
);
|
|
115
131
|
process.exit(1);
|
|
116
132
|
}
|
|
117
133
|
|
|
118
134
|
function logGhIdentity() {
|
|
119
135
|
const u = ghApiJson("user");
|
|
120
|
-
if (u.status !==
|
|
136
|
+
if (u.status !== 0) return;
|
|
121
137
|
try {
|
|
122
138
|
const j = JSON.parse(u.stdout);
|
|
123
139
|
if (j.login) {
|
|
@@ -128,30 +144,26 @@ function logGhIdentity() {
|
|
|
128
144
|
}
|
|
129
145
|
}
|
|
130
146
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
const dirs = pathEnv.split(sep).filter(Boolean);
|
|
136
|
-
const exts = isWin
|
|
137
|
-
? ["", ...(process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";")]
|
|
138
|
-
: [""];
|
|
139
|
-
for (const dir of dirs) {
|
|
140
|
-
for (const ext of exts) {
|
|
141
|
-
try {
|
|
142
|
-
const full = join(dir, name + ext);
|
|
143
|
-
if (existsSync(full) && statSync(full).isFile()) return true;
|
|
144
|
-
} catch {
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return false;
|
|
147
|
+
/** Misma resolución que los clones: en Windows hace falta shell para gh.cmd / git / npm. */
|
|
148
|
+
function canRun(cmd, args) {
|
|
149
|
+
const r = spawnSync(cmd, args, spawnWin({ stdio: "ignore" }));
|
|
150
|
+
return r.status === 0 && !r.error;
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
function needCmd(name, hint = "") {
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
const ok =
|
|
155
|
+
name === "gh"
|
|
156
|
+
? canRun("gh", ["version"])
|
|
157
|
+
: name === "git"
|
|
158
|
+
? canRun("git", ["--version"])
|
|
159
|
+
: canRun(name, ["--version"]);
|
|
160
|
+
if (!ok) {
|
|
161
|
+
log(`${c.red}✗${c.reset} No se puede ejecutar ${c.bold}${name}${c.reset} (¿PATH o instalación?).${hint ? ` ${hint}` : ""}`);
|
|
162
|
+
if (IS_WIN) {
|
|
163
|
+
log(
|
|
164
|
+
`${c.dim} Windows: cierra y abre la terminal tras instalar gh/git, o reinicia para refrescar PATH.${c.reset}`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
155
167
|
process.exit(1);
|
|
156
168
|
}
|
|
157
169
|
}
|
|
@@ -164,7 +176,7 @@ function ghRepoList(org) {
|
|
|
164
176
|
const r = spawnSync(
|
|
165
177
|
"gh",
|
|
166
178
|
["repo", "list", org, "--limit", "1000", "--json", "name,isArchived,isFork"],
|
|
167
|
-
{ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
|
|
179
|
+
spawnWin({ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] })
|
|
168
180
|
);
|
|
169
181
|
if (r.status !== 0) {
|
|
170
182
|
log(`${c.red}✗${c.reset} gh repo list falló:\n${r.stderr || r.stdout}`);
|
|
@@ -246,9 +258,11 @@ function cloneOne(org, name, workspace, useSsh) {
|
|
|
246
258
|
: ["repo", "clone", `${org}/${name}`, name];
|
|
247
259
|
const cmd = useSsh ? "git" : "gh";
|
|
248
260
|
const r = spawnSync(cmd, args, {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
261
|
+
...spawnWin({
|
|
262
|
+
cwd: workspace,
|
|
263
|
+
encoding: "utf8",
|
|
264
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
265
|
+
}),
|
|
252
266
|
});
|
|
253
267
|
process.stdout.write("\r\x1b[K");
|
|
254
268
|
if (r.status === 0) {
|
|
@@ -266,11 +280,15 @@ function copyCursorPack(workspace, cursorRepoUrl) {
|
|
|
266
280
|
const tmp = join(workspace, ".cursor-bootstrap-tmp");
|
|
267
281
|
rmSync(tmp, { recursive: true, force: true });
|
|
268
282
|
log(`${c.dim}→${c.reset} Cursor pack (clone superficial)…`);
|
|
269
|
-
const r = spawnSync(
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
283
|
+
const r = spawnSync(
|
|
284
|
+
"git",
|
|
285
|
+
["clone", "--depth", "1", String(cursorRepoUrl).trim(), tmp],
|
|
286
|
+
spawnWin({
|
|
287
|
+
cwd: workspace,
|
|
288
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
289
|
+
encoding: "utf8",
|
|
290
|
+
})
|
|
291
|
+
);
|
|
274
292
|
if (r.status === 0 && existsSync(join(tmp, ".cursor"))) {
|
|
275
293
|
rmSync(rootCursor, { recursive: true, force: true });
|
|
276
294
|
cpSync(join(tmp, ".cursor"), rootCursor, { recursive: true });
|
|
@@ -289,7 +307,7 @@ function copyCursorPack(workspace, cursorRepoUrl) {
|
|
|
289
307
|
function npmInstallEach(workspace) {
|
|
290
308
|
log("");
|
|
291
309
|
log(`${c.cyan}━━ npm install por repo ━━${c.reset}`);
|
|
292
|
-
if (!
|
|
310
|
+
if (!canRun("npm", ["--version"])) {
|
|
293
311
|
log(`${c.yellow}○${c.reset} npm no está en PATH — omito installs`);
|
|
294
312
|
return;
|
|
295
313
|
}
|
|
@@ -299,7 +317,7 @@ function npmInstallEach(workspace) {
|
|
|
299
317
|
const pkg = join(d, "package.json");
|
|
300
318
|
if (!existsSync(pkg)) continue;
|
|
301
319
|
log(`${c.dim}→${c.reset} ${ent}`);
|
|
302
|
-
const ir = spawnSync("npm", ["install"], { cwd: d, stdio: "inherit" });
|
|
320
|
+
const ir = spawnSync("npm", ["install"], spawnWin({ cwd: d, stdio: "inherit" }));
|
|
303
321
|
if (ir.status !== 0) {
|
|
304
322
|
log(`${c.yellow}○${c.reset} npm install con avisos en ${ent}`);
|
|
305
323
|
} else {
|
package/package.json
CHANGED