@keywaysh/cli 0.1.10 → 0.1.12
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 +118 -37
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -101,7 +101,7 @@ var INTERNAL_POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
|
101
101
|
// package.json
|
|
102
102
|
var package_default = {
|
|
103
103
|
name: "@keywaysh/cli",
|
|
104
|
-
version: "0.1.
|
|
104
|
+
version: "0.1.12",
|
|
105
105
|
description: "One link to all your secrets",
|
|
106
106
|
type: "module",
|
|
107
107
|
bin: {
|
|
@@ -409,9 +409,10 @@ async function deleteConnection(accessToken, connectionId) {
|
|
|
409
409
|
});
|
|
410
410
|
await handleResponse(response);
|
|
411
411
|
}
|
|
412
|
-
function getProviderAuthUrl(provider, redirectUri) {
|
|
413
|
-
const params =
|
|
414
|
-
|
|
412
|
+
function getProviderAuthUrl(provider, accessToken, redirectUri) {
|
|
413
|
+
const params = new URLSearchParams({ token: accessToken });
|
|
414
|
+
if (redirectUri) params.set("redirect_uri", redirectUri);
|
|
415
|
+
return `${API_BASE_URL}/v1/integrations/${provider}/authorize?${params}`;
|
|
415
416
|
}
|
|
416
417
|
async function getConnectionProjects(accessToken, connectionId) {
|
|
417
418
|
const response = await fetchWithTimeout(`${API_BASE_URL}/v1/integrations/connections/${connectionId}/projects`, {
|
|
@@ -1312,23 +1313,20 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
|
|
|
1312
1313
|
if (!allowPrompt || !isInteractive()) {
|
|
1313
1314
|
throw new Error('No Keyway session found. Run "keyway login" to authenticate.');
|
|
1314
1315
|
}
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
console.log(pc6.gray(" Installing the app will also log you in."));
|
|
1316
|
+
const deviceStart = await startDeviceLogin(repoFullName);
|
|
1317
|
+
const installUrl = deviceStart.githubAppInstallUrl || "https://github.com/apps/keyway/installations/new";
|
|
1318
1318
|
console.log("");
|
|
1319
1319
|
const { shouldProceed } = await prompts4({
|
|
1320
1320
|
type: "confirm",
|
|
1321
1321
|
name: "shouldProceed",
|
|
1322
|
-
message: "Open browser to
|
|
1322
|
+
message: "Open browser to sign in?",
|
|
1323
1323
|
initial: true
|
|
1324
1324
|
});
|
|
1325
1325
|
if (!shouldProceed) {
|
|
1326
1326
|
throw new Error('Setup required. Run "keyway init" when ready.');
|
|
1327
1327
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
await openUrl(installUrl);
|
|
1331
|
-
console.log(pc6.blue("\u23F3 Waiting for installation & authorization..."));
|
|
1328
|
+
await openUrl(deviceStart.verificationUriComplete);
|
|
1329
|
+
console.log(pc6.blue("\u23F3 Waiting for authorization..."));
|
|
1332
1330
|
console.log(pc6.gray(" (Press Ctrl+C to cancel)\n"));
|
|
1333
1331
|
const pollIntervalMs = Math.max((deviceStart.interval ?? 5) * 1e3, POLL_INTERVAL_MS);
|
|
1334
1332
|
const startTime = Date.now();
|
|
@@ -1337,30 +1335,73 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
|
|
|
1337
1335
|
while (Date.now() - startTime < POLL_TIMEOUT_MS) {
|
|
1338
1336
|
await sleep(pollIntervalMs);
|
|
1339
1337
|
try {
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1338
|
+
const result = await pollDeviceLogin(deviceStart.deviceCode);
|
|
1339
|
+
if (result.status === "approved" && result.keywayToken) {
|
|
1340
|
+
accessToken = result.keywayToken;
|
|
1341
|
+
await saveAuthToken(result.keywayToken, {
|
|
1342
|
+
githubLogin: result.githubLogin,
|
|
1343
|
+
expiresAt: result.expiresAt
|
|
1344
|
+
});
|
|
1345
|
+
console.log(pc6.green("\u2713 Signed in!"));
|
|
1346
|
+
if (result.githubLogin) {
|
|
1347
|
+
identifyUser(result.githubLogin, {
|
|
1348
|
+
github_username: result.githubLogin,
|
|
1349
|
+
login_method: "device_flow"
|
|
1347
1350
|
});
|
|
1348
|
-
console.log(pc6.green("\u2713 Signed in!"));
|
|
1349
|
-
if (result.githubLogin) {
|
|
1350
|
-
identifyUser(result.githubLogin, {
|
|
1351
|
-
github_username: result.githubLogin,
|
|
1352
|
-
login_method: "github_app"
|
|
1353
|
-
});
|
|
1354
|
-
}
|
|
1355
1351
|
}
|
|
1352
|
+
break;
|
|
1356
1353
|
}
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
}
|
|
1354
|
+
consecutiveErrors = 0;
|
|
1355
|
+
process.stdout.write(pc6.gray("."));
|
|
1356
|
+
} catch (error) {
|
|
1357
|
+
consecutiveErrors++;
|
|
1358
|
+
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
1359
|
+
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
1360
|
+
throw new Error(`Login failed after ${MAX_CONSECUTIVE_ERRORS} consecutive errors: ${errorMsg}`);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
if (!accessToken) {
|
|
1365
|
+
console.log("");
|
|
1366
|
+
console.log(pc6.yellow("\u26A0 Timed out waiting for sign in."));
|
|
1367
|
+
throw new Error("Sign in timed out. Please try again.");
|
|
1368
|
+
}
|
|
1369
|
+
const installStatus = await checkGitHubAppInstallation(repoOwner, repoName, accessToken);
|
|
1370
|
+
if (installStatus.installed) {
|
|
1371
|
+
console.log(pc6.green("\u2713 GitHub App installed"));
|
|
1372
|
+
console.log("");
|
|
1373
|
+
return accessToken;
|
|
1374
|
+
}
|
|
1375
|
+
console.log("");
|
|
1376
|
+
console.log(pc6.yellow("\u26A0 GitHub App not installed on this repository"));
|
|
1377
|
+
console.log(pc6.gray(" The Keyway GitHub App is required for secure access."));
|
|
1378
|
+
console.log("");
|
|
1379
|
+
const { shouldInstall } = await prompts4({
|
|
1380
|
+
type: "confirm",
|
|
1381
|
+
name: "shouldInstall",
|
|
1382
|
+
message: "Open browser to install GitHub App?",
|
|
1383
|
+
initial: true
|
|
1384
|
+
});
|
|
1385
|
+
if (!shouldInstall) {
|
|
1386
|
+
console.log(pc6.gray(`
|
|
1387
|
+
Install later: ${installUrl}`));
|
|
1388
|
+
throw new Error("GitHub App installation required.");
|
|
1389
|
+
}
|
|
1390
|
+
await openUrl(installUrl);
|
|
1391
|
+
console.log(pc6.blue("\u23F3 Waiting for GitHub App installation..."));
|
|
1392
|
+
console.log(pc6.gray(' Add this repository and click "Install"'));
|
|
1393
|
+
console.log(pc6.gray(" Then return here - the CLI will detect it automatically"));
|
|
1394
|
+
console.log(pc6.gray(" (Press Ctrl+C to cancel)\n"));
|
|
1395
|
+
const installStartTime = Date.now();
|
|
1396
|
+
consecutiveErrors = 0;
|
|
1397
|
+
while (Date.now() - installStartTime < POLL_TIMEOUT_MS) {
|
|
1398
|
+
await sleep(POLL_INTERVAL_MS);
|
|
1399
|
+
try {
|
|
1400
|
+
const pollStatus = await checkGitHubAppInstallation(repoOwner, repoName, accessToken);
|
|
1401
|
+
if (pollStatus.installed) {
|
|
1402
|
+
console.log(pc6.green("\u2713 GitHub App installed!"));
|
|
1403
|
+
console.log("");
|
|
1404
|
+
return accessToken;
|
|
1364
1405
|
}
|
|
1365
1406
|
consecutiveErrors = 0;
|
|
1366
1407
|
process.stdout.write(pc6.gray("."));
|
|
@@ -1368,14 +1409,14 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
|
|
|
1368
1409
|
consecutiveErrors++;
|
|
1369
1410
|
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
1370
1411
|
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
1371
|
-
throw new Error(`
|
|
1412
|
+
throw new Error(`Installation check failed after ${MAX_CONSECUTIVE_ERRORS} consecutive errors: ${errorMsg}`);
|
|
1372
1413
|
}
|
|
1373
1414
|
}
|
|
1374
1415
|
}
|
|
1375
1416
|
console.log("");
|
|
1376
|
-
console.log(pc6.yellow("\u26A0 Timed out waiting for
|
|
1417
|
+
console.log(pc6.yellow("\u26A0 Timed out waiting for installation."));
|
|
1377
1418
|
console.log(pc6.gray(` Install the GitHub App: ${installUrl}`));
|
|
1378
|
-
throw new Error("
|
|
1419
|
+
throw new Error("GitHub App installation timed out.");
|
|
1379
1420
|
}
|
|
1380
1421
|
async function ensureGitHubAppInstalledOnly(repoFullName, accessToken) {
|
|
1381
1422
|
const [repoOwner, repoName] = repoFullName.split("/");
|
|
@@ -1970,7 +2011,7 @@ async function connectWithTokenFlow(accessToken, provider, displayName) {
|
|
|
1970
2011
|
}
|
|
1971
2012
|
}
|
|
1972
2013
|
async function connectWithOAuthFlow(accessToken, provider, displayName) {
|
|
1973
|
-
const authUrl = getProviderAuthUrl(provider);
|
|
2014
|
+
const authUrl = getProviderAuthUrl(provider, accessToken);
|
|
1974
2015
|
const startTime = /* @__PURE__ */ new Date();
|
|
1975
2016
|
await openUrl(authUrl);
|
|
1976
2017
|
console.log(pc9.gray("Waiting for authorization..."));
|
|
@@ -2136,12 +2177,24 @@ function mapToRailwayEnvironment(keywayEnv) {
|
|
|
2136
2177
|
};
|
|
2137
2178
|
return mapping[keywayEnv.toLowerCase()] || "production";
|
|
2138
2179
|
}
|
|
2180
|
+
function mapToNetlifyEnvironment(keywayEnv) {
|
|
2181
|
+
const mapping = {
|
|
2182
|
+
production: "production",
|
|
2183
|
+
staging: "branch-deploy",
|
|
2184
|
+
preview: "deploy-preview",
|
|
2185
|
+
dev: "dev",
|
|
2186
|
+
development: "dev"
|
|
2187
|
+
};
|
|
2188
|
+
return mapping[keywayEnv.toLowerCase()] || "production";
|
|
2189
|
+
}
|
|
2139
2190
|
function mapToProviderEnvironment(provider, keywayEnv) {
|
|
2140
2191
|
switch (provider.toLowerCase()) {
|
|
2141
2192
|
case "vercel":
|
|
2142
2193
|
return mapToVercelEnvironment(keywayEnv);
|
|
2143
2194
|
case "railway":
|
|
2144
2195
|
return mapToRailwayEnvironment(keywayEnv);
|
|
2196
|
+
case "netlify":
|
|
2197
|
+
return mapToNetlifyEnvironment(keywayEnv);
|
|
2145
2198
|
default:
|
|
2146
2199
|
return keywayEnv;
|
|
2147
2200
|
}
|
|
@@ -2263,6 +2316,32 @@ async function syncCommand(provider, options = {}) {
|
|
|
2263
2316
|
process.exit(1);
|
|
2264
2317
|
}
|
|
2265
2318
|
console.log(pc10.gray(`Repository: ${repoFullName}`));
|
|
2319
|
+
const vaultExists = await checkVaultExists(accessToken, repoFullName);
|
|
2320
|
+
if (!vaultExists) {
|
|
2321
|
+
console.log(pc10.yellow(`
|
|
2322
|
+
No vault found for ${repoFullName}.`));
|
|
2323
|
+
const { shouldCreate } = await prompts7({
|
|
2324
|
+
type: "confirm",
|
|
2325
|
+
name: "shouldCreate",
|
|
2326
|
+
message: "Create vault now?",
|
|
2327
|
+
initial: true
|
|
2328
|
+
});
|
|
2329
|
+
if (!shouldCreate) {
|
|
2330
|
+
console.log(pc10.gray("Cancelled. Run `keyway init` to create a vault first."));
|
|
2331
|
+
process.exit(0);
|
|
2332
|
+
}
|
|
2333
|
+
console.log(pc10.gray("\nCreating vault..."));
|
|
2334
|
+
try {
|
|
2335
|
+
await initVault(repoFullName, accessToken);
|
|
2336
|
+
console.log(pc10.green(`\u2713 Vault created for ${repoFullName}
|
|
2337
|
+
`));
|
|
2338
|
+
} catch (error) {
|
|
2339
|
+
const message = error instanceof Error ? error.message : "Failed to create vault";
|
|
2340
|
+
console.error(pc10.red(`
|
|
2341
|
+
\u2717 ${message}`));
|
|
2342
|
+
process.exit(1);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2266
2345
|
let { connections } = await getConnections(accessToken);
|
|
2267
2346
|
let connection = connections.find((c) => c.provider === provider.toLowerCase());
|
|
2268
2347
|
if (!connection) {
|
|
@@ -2556,6 +2635,8 @@ async function executeSyncOperation(accessToken, repoFullName, connectionId, pro
|
|
|
2556
2635
|
const preview = await getSyncPreview(accessToken, repoFullName, {
|
|
2557
2636
|
connectionId,
|
|
2558
2637
|
projectId: project.id,
|
|
2638
|
+
serviceId: project.serviceId,
|
|
2639
|
+
// Railway: service ID for service-specific variables
|
|
2559
2640
|
keywayEnvironment: keywayEnv,
|
|
2560
2641
|
providerEnvironment: providerEnv,
|
|
2561
2642
|
direction,
|