@keystrokehq/cli 0.0.132 → 0.0.133
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.mjs +120 -61
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1852,6 +1852,8 @@ const OrganizationSlugSchema = string().trim().toLowerCase().min(2, "Slug must b
|
|
|
1852
1852
|
* fail to load.
|
|
1853
1853
|
*/
|
|
1854
1854
|
const ClaimableOrganizationSlugSchema = OrganizationSlugSchema.refine((slug) => !RESERVED_ORGANIZATION_SLUGS.has(slug), "This slug is reserved");
|
|
1855
|
+
/** Same format as organization slugs — org-scoped, no global reserved list. */
|
|
1856
|
+
const ProjectSlugSchema = OrganizationSlugSchema;
|
|
1855
1857
|
/** Browser→platform request budget (ping + small platform overhead). */
|
|
1856
1858
|
const PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS = 17e3;
|
|
1857
1859
|
/** Normalize a public origin URL (no trailing slash). */
|
|
@@ -2053,6 +2055,17 @@ object({
|
|
|
2053
2055
|
slug: string().trim().min(1),
|
|
2054
2056
|
excludeOrganizationId: string().min(1).optional()
|
|
2055
2057
|
});
|
|
2058
|
+
const ProjectSlugAvailabilityReasonSchema = _enum(["taken", "invalid"]);
|
|
2059
|
+
const ProjectSlugAvailabilityResponseSchema = object({
|
|
2060
|
+
slug: string(),
|
|
2061
|
+
available: boolean(),
|
|
2062
|
+
reason: ProjectSlugAvailabilityReasonSchema.optional(),
|
|
2063
|
+
suggestion: ProjectSlugSchema.optional()
|
|
2064
|
+
});
|
|
2065
|
+
object({
|
|
2066
|
+
slug: string().trim().min(1),
|
|
2067
|
+
excludeProjectId: string().min(1).optional()
|
|
2068
|
+
});
|
|
2056
2069
|
const ProjectStatusSchema = _enum([
|
|
2057
2070
|
"inactive",
|
|
2058
2071
|
"starting",
|
|
@@ -2076,6 +2089,7 @@ const ProjectSchema = object({
|
|
|
2076
2089
|
id: string(),
|
|
2077
2090
|
organizationId: string(),
|
|
2078
2091
|
name: string(),
|
|
2092
|
+
slug: ProjectSlugSchema,
|
|
2079
2093
|
description: string().nullable(),
|
|
2080
2094
|
status: ProjectStatusSchema,
|
|
2081
2095
|
baseUrl: string().nullable(),
|
|
@@ -2116,8 +2130,9 @@ const CreateProjectRequestSchema = object({
|
|
|
2116
2130
|
});
|
|
2117
2131
|
const UpdateProjectRequestSchema = object({
|
|
2118
2132
|
name: string().trim().min(1).optional(),
|
|
2119
|
-
description: string().trim().optional()
|
|
2120
|
-
|
|
2133
|
+
description: string().trim().optional(),
|
|
2134
|
+
slug: ProjectSlugSchema.optional()
|
|
2135
|
+
}).refine((data) => data.name !== void 0 || data.description !== void 0 || data.slug !== void 0, { message: "At least one field is required" });
|
|
2121
2136
|
const CreateProjectResponseSchema = object({ project: ProjectSchema });
|
|
2122
2137
|
const ProjectResponseSchema = object({ project: ProjectSchema });
|
|
2123
2138
|
const ProjectReachabilityResponseSchema = object({ reachable: boolean() });
|
|
@@ -5174,6 +5189,16 @@ function createProjectsResource(http) {
|
|
|
5174
5189
|
} catch (error) {
|
|
5175
5190
|
throw await toPlatformError(error);
|
|
5176
5191
|
}
|
|
5192
|
+
},
|
|
5193
|
+
async checkSlug(slug, options = {}) {
|
|
5194
|
+
const searchParams = new URLSearchParams({ slug });
|
|
5195
|
+
if (options.excludeProjectId) searchParams.set("excludeProjectId", options.excludeProjectId);
|
|
5196
|
+
try {
|
|
5197
|
+
const data = await http.get(`/api/projects/slug-available?${searchParams}`).json();
|
|
5198
|
+
return ProjectSlugAvailabilityResponseSchema.parse(data);
|
|
5199
|
+
} catch (error) {
|
|
5200
|
+
throw await toPlatformError(error);
|
|
5201
|
+
}
|
|
5177
5202
|
}
|
|
5178
5203
|
};
|
|
5179
5204
|
}
|
|
@@ -8587,6 +8612,33 @@ function createCliPlatformClient(config) {
|
|
|
8587
8612
|
});
|
|
8588
8613
|
}
|
|
8589
8614
|
//#endregion
|
|
8615
|
+
//#region src/resolve-resource-ref.ts
|
|
8616
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
8617
|
+
function looksLikeUuid(value) {
|
|
8618
|
+
return UUID_PATTERN.test(value);
|
|
8619
|
+
}
|
|
8620
|
+
function formatProjectLabel(project) {
|
|
8621
|
+
return project.slug;
|
|
8622
|
+
}
|
|
8623
|
+
async function resolveProjectRef(platform, ref) {
|
|
8624
|
+
if (looksLikeUuid(ref)) try {
|
|
8625
|
+
return await platform.projects.get(ref);
|
|
8626
|
+
} catch (error) {
|
|
8627
|
+
if (error instanceof PlatformError && error.status === 404) throw new Error(`Project ${ref} not found in the active organization. Run \`keystroke project list\`, then \`keystroke config use project <slug>\`.`);
|
|
8628
|
+
throw error;
|
|
8629
|
+
}
|
|
8630
|
+
const match = (await platform.projects.list()).find((project) => project.slug === ref);
|
|
8631
|
+
if (!match) throw new Error(`Project "${ref}" not found in the active organization. Run \`keystroke project list\`.`);
|
|
8632
|
+
return match;
|
|
8633
|
+
}
|
|
8634
|
+
function resolveOrganizationRef(organizations, ref) {
|
|
8635
|
+
const byId = organizations.find((entry) => entry.organization.id === ref);
|
|
8636
|
+
if (byId) return byId;
|
|
8637
|
+
const bySlug = organizations.find((entry) => entry.organization.slug === ref);
|
|
8638
|
+
if (bySlug) return bySlug;
|
|
8639
|
+
throw new Error(`Organization "${ref}" was not found or you do not have access`);
|
|
8640
|
+
}
|
|
8641
|
+
//#endregion
|
|
8590
8642
|
//#region src/organization/active-organization.ts
|
|
8591
8643
|
function formatOrganization(membership) {
|
|
8592
8644
|
return `${membership.organization.name} (${membership.role})`;
|
|
@@ -8600,15 +8652,11 @@ async function activateOrganization(config, organizationId) {
|
|
|
8600
8652
|
platform.setActiveOrganizationId(membership.organization.id);
|
|
8601
8653
|
return membership;
|
|
8602
8654
|
}
|
|
8603
|
-
async function pickOrganization(config, organizations,
|
|
8604
|
-
if (
|
|
8605
|
-
const membership = organizations.find((entry) => entry.organization.id === organizationId);
|
|
8606
|
-
if (!membership) throw new Error(`Organization ${organizationId} was not found or you do not have access`);
|
|
8607
|
-
return activateOrganization(config, membership.organization.id);
|
|
8608
|
-
}
|
|
8655
|
+
async function pickOrganization(config, organizations, organizationRef) {
|
|
8656
|
+
if (organizationRef) return activateOrganization(config, resolveOrganizationRef(organizations, organizationRef).organization.id);
|
|
8609
8657
|
if (!process.stdin.isTTY) {
|
|
8610
|
-
const names = organizations.map((entry) => entry.organization.
|
|
8611
|
-
throw new Error(`Multiple organizations found. Run \`keystroke config use org <
|
|
8658
|
+
const names = organizations.map((entry) => entry.organization.slug).join(", ");
|
|
8659
|
+
throw new Error(`Multiple organizations found. Run \`keystroke config use org <slug>\`. Options: ${names}`);
|
|
8612
8660
|
}
|
|
8613
8661
|
return activateOrganization(config, await select({
|
|
8614
8662
|
message: "Select an organization",
|
|
@@ -8622,7 +8670,7 @@ async function selectActiveOrganization(config, options = {}) {
|
|
|
8622
8670
|
const organizations = await listOrganizations(config);
|
|
8623
8671
|
if (organizations.length === 0) throw new Error(`No organization found — create one at ${getWebUrl(config)}`);
|
|
8624
8672
|
if (organizations.length === 1) return activateOrganization(config, organizations[0].organization.id);
|
|
8625
|
-
return pickOrganization(config, organizations, options.organizationId);
|
|
8673
|
+
return pickOrganization(config, organizations, options.organizationRef ?? options.organizationId);
|
|
8626
8674
|
}
|
|
8627
8675
|
async function syncActiveOrganizationAfterLogin(config, options = {}) {
|
|
8628
8676
|
const organizations = await listOrganizations(config);
|
|
@@ -8638,8 +8686,8 @@ async function syncActiveOrganizationAfterLogin(config, options = {}) {
|
|
|
8638
8686
|
process.stdout.write(`Using organization ${membership.organization.name}\n`);
|
|
8639
8687
|
return membership;
|
|
8640
8688
|
}
|
|
8641
|
-
if (options.organizationId) {
|
|
8642
|
-
const membership = await pickOrganization(config, organizations, options.organizationId);
|
|
8689
|
+
if (options.organizationRef ?? options.organizationId) {
|
|
8690
|
+
const membership = await pickOrganization(config, organizations, options.organizationRef ?? options.organizationId);
|
|
8643
8691
|
process.stdout.write(`Using organization ${membership.organization.name}\n`);
|
|
8644
8692
|
return membership;
|
|
8645
8693
|
}
|
|
@@ -8712,19 +8760,19 @@ function resolveOrgPlatformTarget(config) {
|
|
|
8712
8760
|
mode: "platform"
|
|
8713
8761
|
};
|
|
8714
8762
|
}
|
|
8715
|
-
async function resolvePlatformTarget(config,
|
|
8763
|
+
async function resolvePlatformTarget(config, projectRef) {
|
|
8716
8764
|
const platform = createCliPlatformClient(config);
|
|
8717
8765
|
let project;
|
|
8718
8766
|
try {
|
|
8719
|
-
project = await platform
|
|
8767
|
+
project = await resolveProjectRef(platform, projectRef);
|
|
8720
8768
|
} catch (error) {
|
|
8721
|
-
if (error instanceof
|
|
8769
|
+
if (error instanceof Error) throw error;
|
|
8722
8770
|
throw error;
|
|
8723
8771
|
}
|
|
8724
|
-
if (project.status !== "active") throw new Error(`Project ${
|
|
8772
|
+
if (project.status !== "active") throw new Error(`Project ${formatProjectLabel(project)} is not active (${project.status})`);
|
|
8725
8773
|
return {
|
|
8726
|
-
baseUrl: `${getPlatformUrl(config).replace(/\/+$/, "")}/api/projects/${encodeURIComponent(
|
|
8727
|
-
projectId,
|
|
8774
|
+
baseUrl: `${getPlatformUrl(config).replace(/\/+$/, "")}/api/projects/${encodeURIComponent(project.id)}`,
|
|
8775
|
+
projectId: project.id,
|
|
8728
8776
|
mode: "platform"
|
|
8729
8777
|
};
|
|
8730
8778
|
}
|
|
@@ -8742,9 +8790,9 @@ async function resolveApiTarget(config, options = {}) {
|
|
|
8742
8790
|
if (options.projectId) return resolvePlatformTarget(config, options.projectId);
|
|
8743
8791
|
if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(config);
|
|
8744
8792
|
if (!options.projectScoped) return resolveOrgPlatformTarget(config);
|
|
8745
|
-
const
|
|
8746
|
-
if (!
|
|
8747
|
-
return resolvePlatformTarget(config,
|
|
8793
|
+
const projectRef = options.projectId ?? config.get("activeProjectId");
|
|
8794
|
+
if (!projectRef) throw new Error("No project selected. Pass `--project <slug>` or run `keystroke config use project <slug>`.");
|
|
8795
|
+
return resolvePlatformTarget(config, projectRef);
|
|
8748
8796
|
}
|
|
8749
8797
|
//#endregion
|
|
8750
8798
|
//#region src/target-options.ts
|
|
@@ -8755,9 +8803,6 @@ function setCliTargetOptions(options) {
|
|
|
8755
8803
|
function getCliTargetOptions() {
|
|
8756
8804
|
return targetOptions;
|
|
8757
8805
|
}
|
|
8758
|
-
function resolveActiveProjectId(config) {
|
|
8759
|
-
return getCliTargetOptions().projectId ?? config.get("activeProjectId");
|
|
8760
|
-
}
|
|
8761
8806
|
//#endregion
|
|
8762
8807
|
//#region src/errors/example-input.ts
|
|
8763
8808
|
function exampleValueFromValidationMessage(message) {
|
|
@@ -9232,7 +9277,7 @@ function resolveAuthLoginTargets(options, config) {
|
|
|
9232
9277
|
//#endregion
|
|
9233
9278
|
//#region src/commands/auth/login.ts
|
|
9234
9279
|
function registerAuthLoginCommand(auth) {
|
|
9235
|
-
auth.command("login").description("Authenticate via browser device flow").option("--web-url <url>", "Web dashboard origin (omit to use production defaults; local dev: http://localhost:3000)").option("--platform-url <url>", "Platform API origin (derived from web URL when omitted)").option("--org <
|
|
9280
|
+
auth.command("login").description("Authenticate via browser device flow").option("--web-url <url>", "Web dashboard origin (omit to use production defaults; local dev: http://localhost:3000)").option("--platform-url <url>", "Platform API origin (derived from web URL when omitted)").option("--org <slug>", "Active organization slug (skips prompt when you belong to several)").action(async (options) => {
|
|
9236
9281
|
const config = createCliConfig();
|
|
9237
9282
|
const { webUrl, platformUrl } = resolveAuthLoginTargets(options, config);
|
|
9238
9283
|
config.set("webUrl", webUrl);
|
|
@@ -9247,7 +9292,7 @@ function registerAuthLoginCommand(auth) {
|
|
|
9247
9292
|
const user = await getSessionWithBearer(platformUrl, result.accessToken);
|
|
9248
9293
|
if (user) process.stdout.write(`Logged in as ${user.name} (${user.email})\n`);
|
|
9249
9294
|
else process.stdout.write(`Logged in to ${webUrl}\n`);
|
|
9250
|
-
await syncActiveOrganizationAfterLogin(config, {
|
|
9295
|
+
await syncActiveOrganizationAfterLogin(config, { organizationRef: options.org });
|
|
9251
9296
|
} catch (error) {
|
|
9252
9297
|
process.stderr.write(`${formatCliError(error, "Login failed", {
|
|
9253
9298
|
webUrl,
|
|
@@ -9467,6 +9512,18 @@ function collectProjectSource(root) {
|
|
|
9467
9512
|
};
|
|
9468
9513
|
}
|
|
9469
9514
|
//#endregion
|
|
9515
|
+
//#region src/resolve-project-target.ts
|
|
9516
|
+
async function resolveActiveProject(config, platform) {
|
|
9517
|
+
const ref = getCliTargetOptions().projectId ?? config.get("activeProjectId");
|
|
9518
|
+
if (!ref) return;
|
|
9519
|
+
const client = platform ?? createCliPlatformClient(config);
|
|
9520
|
+
if (!getCliTargetOptions().projectId && looksLikeUuid(ref)) return resolveProjectRef(client, ref);
|
|
9521
|
+
return resolveProjectRef(client, ref);
|
|
9522
|
+
}
|
|
9523
|
+
async function resolveActiveProjectId(config) {
|
|
9524
|
+
return (await resolveActiveProject(config))?.id;
|
|
9525
|
+
}
|
|
9526
|
+
//#endregion
|
|
9470
9527
|
//#region src/commands/deploy.ts
|
|
9471
9528
|
const POLL_INTERVAL_MS = 2e3;
|
|
9472
9529
|
const DEPLOY_TIMEOUT_MS = 12e4;
|
|
@@ -9557,8 +9614,8 @@ async function runDeploy(options) {
|
|
|
9557
9614
|
function registerDeployCommand(program) {
|
|
9558
9615
|
program.command("deploy").description("Build, upload, and deploy the project to the platform").option("--dir <path>", "Project directory", process.cwd()).option("--skip-build", "Upload the existing dist/ without rebuilding").action(async (options) => {
|
|
9559
9616
|
try {
|
|
9560
|
-
const projectId = resolveActiveProjectId(createCliConfig());
|
|
9561
|
-
if (!projectId) throw new Error("Usage: keystroke deploy --project <
|
|
9617
|
+
const projectId = await resolveActiveProjectId(createCliConfig());
|
|
9618
|
+
if (!projectId) throw new Error("Usage: keystroke deploy --project <slug>");
|
|
9562
9619
|
await runDeploy({
|
|
9563
9620
|
dir: options.dir,
|
|
9564
9621
|
projectId,
|
|
@@ -10118,7 +10175,7 @@ function writeInactiveDeployHints(projects) {
|
|
|
10118
10175
|
const bin = cliBinaryName();
|
|
10119
10176
|
for (const project of projects) {
|
|
10120
10177
|
if (project.status !== "inactive") continue;
|
|
10121
|
-
process.stderr.write(`Project ${project
|
|
10178
|
+
process.stderr.write(`Project ${formatProjectLabel(project)} is inactive. Deploy with: ${bin} deploy --project ${formatProjectLabel(project)}\n`);
|
|
10122
10179
|
}
|
|
10123
10180
|
}
|
|
10124
10181
|
async function runProjectList(config) {
|
|
@@ -10136,13 +10193,19 @@ async function runProjectList(config) {
|
|
|
10136
10193
|
async function runProjectMetrics(config, options) {
|
|
10137
10194
|
await withActivePlatformClient(config, async (platform) => {
|
|
10138
10195
|
const metrics = await platform.projectMetrics.list();
|
|
10139
|
-
|
|
10196
|
+
if (options.projectRef === void 0) {
|
|
10197
|
+
process.stdout.write(`${JSON.stringify(metrics, null, 2)}\n`);
|
|
10198
|
+
return;
|
|
10199
|
+
}
|
|
10200
|
+
const project = await resolveProjectRef(platform, options.projectRef);
|
|
10201
|
+
const output = Object.fromEntries(Object.entries(metrics).filter(([projectId]) => projectId === project.id));
|
|
10140
10202
|
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
10141
10203
|
});
|
|
10142
10204
|
}
|
|
10143
10205
|
async function runProjectDeploymentsList(config, options) {
|
|
10144
10206
|
await withActivePlatformClient(config, async (platform) => {
|
|
10145
|
-
const
|
|
10207
|
+
const project = await resolveProjectRef(platform, options.projectRef);
|
|
10208
|
+
const deployments = await platform.deployments.listForProject(project.id);
|
|
10146
10209
|
process.stdout.write(`${JSON.stringify({ deployments }, null, 2)}\n`);
|
|
10147
10210
|
});
|
|
10148
10211
|
}
|
|
@@ -10206,10 +10269,10 @@ function registerProjectCommand(program) {
|
|
|
10206
10269
|
process.exitCode = 1;
|
|
10207
10270
|
}
|
|
10208
10271
|
});
|
|
10209
|
-
project.command("metrics").description("List rollup metrics for projects in the active organization").option("--project <
|
|
10272
|
+
project.command("metrics").description("List rollup metrics for projects in the active organization").option("--project <slug>", "Return metrics for a single project").action(async (options) => {
|
|
10210
10273
|
const config = createCliConfig();
|
|
10211
10274
|
try {
|
|
10212
|
-
await runProjectMetrics(config, { ...options.project ? {
|
|
10275
|
+
await runProjectMetrics(config, { ...options.project ? { projectRef: options.project } : {} });
|
|
10213
10276
|
} catch (error) {
|
|
10214
10277
|
process.stderr.write(`${formatCliError(error, "List project metrics failed", {
|
|
10215
10278
|
serverUrl: getPlatformUrl(config),
|
|
@@ -10218,12 +10281,12 @@ function registerProjectCommand(program) {
|
|
|
10218
10281
|
process.exitCode = 1;
|
|
10219
10282
|
}
|
|
10220
10283
|
});
|
|
10221
|
-
project.command("deployments").description("View deployment history for platform projects").command("list").description("List deployment history for a project").option("--project <
|
|
10284
|
+
project.command("deployments").description("View deployment history for platform projects").command("list").description("List deployment history for a project").option("--project <slug>", "Project slug").action(async (options) => {
|
|
10222
10285
|
const config = createCliConfig();
|
|
10223
10286
|
try {
|
|
10224
|
-
const
|
|
10225
|
-
if (!
|
|
10226
|
-
await runProjectDeploymentsList(config, {
|
|
10287
|
+
const projectRef = options.project ?? getCliTargetOptions().projectId ?? config.get("activeProjectId");
|
|
10288
|
+
if (!projectRef) throw new Error("Usage: keystroke project deployments list --project <slug>");
|
|
10289
|
+
await runProjectDeploymentsList(config, { projectRef });
|
|
10227
10290
|
} catch (error) {
|
|
10228
10291
|
process.stderr.write(`${formatCliError(error, "List deployments failed", {
|
|
10229
10292
|
serverUrl: getPlatformUrl(config),
|
|
@@ -10250,8 +10313,8 @@ function registerProjectCommand(program) {
|
|
|
10250
10313
|
project.command("update").description("Update a platform project's name and/or description").option("--name <name>", "Project name").option("--description <description>", "Project description").action(async (options) => {
|
|
10251
10314
|
const config = createCliConfig();
|
|
10252
10315
|
try {
|
|
10253
|
-
const projectId = resolveActiveProjectId(config);
|
|
10254
|
-
if (!projectId) throw new Error("Usage: keystroke --project <
|
|
10316
|
+
const projectId = await resolveActiveProjectId(config);
|
|
10317
|
+
if (!projectId) throw new Error("Usage: keystroke --project <slug> project update --name <name>");
|
|
10255
10318
|
if (!options.name && options.description === void 0) throw new Error("At least one of --name or --description is required");
|
|
10256
10319
|
await runProjectUpdate(config, {
|
|
10257
10320
|
projectId,
|
|
@@ -10269,8 +10332,8 @@ function registerProjectCommand(program) {
|
|
|
10269
10332
|
project.command("delete").description("Delete a platform project").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
|
|
10270
10333
|
const config = createCliConfig();
|
|
10271
10334
|
try {
|
|
10272
|
-
const projectId = resolveActiveProjectId(config);
|
|
10273
|
-
if (!projectId) throw new Error("Usage: keystroke --project <
|
|
10335
|
+
const projectId = await resolveActiveProjectId(config);
|
|
10336
|
+
if (!projectId) throw new Error("Usage: keystroke --project <slug> project delete");
|
|
10274
10337
|
if (!options.yes) throw new Error("Pass --yes to confirm project deletion");
|
|
10275
10338
|
await runProjectDelete(config, projectId);
|
|
10276
10339
|
} catch (error) {
|
|
@@ -10431,27 +10494,23 @@ function registerWorkflowCommand(program) {
|
|
|
10431
10494
|
}
|
|
10432
10495
|
//#endregion
|
|
10433
10496
|
//#region src/commands/config/use-project.ts
|
|
10434
|
-
async function fetchProjectInOrg(config,
|
|
10435
|
-
|
|
10436
|
-
try {
|
|
10437
|
-
return await platform.projects.get(projectId);
|
|
10438
|
-
} catch (error) {
|
|
10439
|
-
if (error instanceof PlatformError && error.status === 404) throw new Error(`Project ${projectId} not found in the active organization. Run \`keystroke project list\`, then \`keystroke config use project <id>\`.`);
|
|
10440
|
-
throw error;
|
|
10441
|
-
}
|
|
10497
|
+
async function fetchProjectInOrg(config, projectRef) {
|
|
10498
|
+
return resolveProjectRef(createCliPlatformClient(config), projectRef);
|
|
10442
10499
|
}
|
|
10443
10500
|
function assertProjectReadyForConfig(project) {
|
|
10444
|
-
|
|
10445
|
-
if (project.status === "
|
|
10501
|
+
const label = formatProjectLabel(project);
|
|
10502
|
+
if (project.status === "failed") throw new Error(project.lastError ? `Project ${label} deploy failed: ${project.lastError}` : `Project ${label} deploy failed`);
|
|
10503
|
+
if (project.status === "starting") throw new Error(`Project ${label} is still starting. Wait for deploy to finish, then run \`keystroke config use project ${label}\`.`);
|
|
10446
10504
|
}
|
|
10447
|
-
async function runConfigUseProject(config,
|
|
10448
|
-
const project = await fetchProjectInOrg(config,
|
|
10505
|
+
async function runConfigUseProject(config, projectRef) {
|
|
10506
|
+
const project = await fetchProjectInOrg(config, projectRef);
|
|
10449
10507
|
assertProjectReadyForConfig(project);
|
|
10450
|
-
config.set("activeProjectId",
|
|
10508
|
+
config.set("activeProjectId", project.id);
|
|
10451
10509
|
config.set("apiTarget", "platform");
|
|
10510
|
+
const label = formatProjectLabel(project);
|
|
10452
10511
|
return {
|
|
10453
|
-
stdout: project.status === "active" ? `Using platform project ${
|
|
10454
|
-
stderr: project.status === "inactive" ? `Project is not active yet. Deploy with: ${cliBinaryName()} deploy --project ${
|
|
10512
|
+
stdout: project.status === "active" ? `Using platform project ${label}\n` : `Using platform project ${label} (${project.status})\n`,
|
|
10513
|
+
stderr: project.status === "inactive" ? `Project is not active yet. Deploy with: ${cliBinaryName()} deploy --project ${label}\n` : void 0
|
|
10455
10514
|
};
|
|
10456
10515
|
}
|
|
10457
10516
|
//#endregion
|
|
@@ -10480,7 +10539,7 @@ function registerConfigCommand(program) {
|
|
|
10480
10539
|
return;
|
|
10481
10540
|
}
|
|
10482
10541
|
if (mode === "org") {
|
|
10483
|
-
const membership = await selectActiveOrganization(cliConfig, {
|
|
10542
|
+
const membership = await selectActiveOrganization(cliConfig, { organizationRef: id });
|
|
10484
10543
|
process.stdout.write(`Using organization ${membership.organization.name}\n`);
|
|
10485
10544
|
return;
|
|
10486
10545
|
}
|
|
@@ -10490,9 +10549,9 @@ function registerConfigCommand(program) {
|
|
|
10490
10549
|
process.stdout.write(activeProjectId ? `Using platform API (default project ${activeProjectId} for project-scoped commands)\n` : "Using platform API\n");
|
|
10491
10550
|
return;
|
|
10492
10551
|
}
|
|
10493
|
-
if (mode !== "project") throw new Error("Usage: keystroke config use [local|cloud|project [
|
|
10552
|
+
if (mode !== "project") throw new Error("Usage: keystroke config use [local|cloud|project [slug]|org [slug]]");
|
|
10494
10553
|
const targetProjectId = id ?? cliConfig.get("activeProjectId");
|
|
10495
|
-
if (!targetProjectId) throw new Error("Usage: keystroke config use project <
|
|
10554
|
+
if (!targetProjectId) throw new Error("Usage: keystroke config use project <slug>");
|
|
10496
10555
|
const result = await runConfigUseProject(cliConfig, targetProjectId);
|
|
10497
10556
|
process.stdout.write(result.stdout);
|
|
10498
10557
|
if (result.stderr) process.stderr.write(result.stderr);
|
|
@@ -10566,7 +10625,7 @@ async function syncSkills(command) {
|
|
|
10566
10625
|
//#endregion
|
|
10567
10626
|
//#region src/program.ts
|
|
10568
10627
|
function createProgram() {
|
|
10569
|
-
const program = new Command().name("keystroke").description("Build, run, and manage keystroke projects").version(readCliVersion()).option("--project <
|
|
10628
|
+
const program = new Command().name("keystroke").description("Build, run, and manage keystroke projects").version(readCliVersion()).option("--project <slug>", "Platform project slug (deploy target or one-off API target)").option("--local", "Force local keystroke server URL").hook("preAction", async (thisCommand, actionCommand) => {
|
|
10570
10629
|
const opts = thisCommand.opts();
|
|
10571
10630
|
setCliTargetOptions({
|
|
10572
10631
|
projectId: opts.project,
|