@barekey/cli 0.3.3 → 0.5.0
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/README.md +53 -12
- package/bun.lock +9 -3
- package/dist/auth-provider.js +7 -4
- package/dist/command-utils.d.ts +1 -1
- package/dist/command-utils.js +7 -6
- package/dist/commands/audit.d.ts +2 -0
- package/dist/commands/audit.js +47 -0
- package/dist/commands/auth.js +22 -7
- package/dist/commands/billing.d.ts +2 -0
- package/dist/commands/billing.js +62 -0
- package/dist/commands/env.js +158 -98
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +32 -0
- package/dist/commands/org.d.ts +2 -0
- package/dist/commands/org.js +85 -0
- package/dist/commands/project.d.ts +2 -0
- package/dist/commands/project.js +99 -0
- package/dist/commands/stage.d.ts +2 -0
- package/dist/commands/stage.js +125 -0
- package/dist/commands/target-prompts.d.ts +184 -0
- package/dist/commands/target-prompts.js +312 -0
- package/dist/commands/typegen.d.ts +2 -2
- package/dist/commands/typegen.js +61 -22
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/context/session-id.d.ts +11 -0
- package/dist/context/session-id.js +14 -0
- package/dist/contracts/index.d.ts +491 -0
- package/dist/contracts/index.js +307 -0
- package/dist/credentials-store.js +70 -11
- package/dist/http.d.ts +34 -0
- package/dist/http.js +56 -2
- package/dist/index.js +12 -0
- package/dist/runtime-config.d.ts +4 -0
- package/dist/runtime-config.js +16 -11
- package/dist/typegen/core.d.ts +45 -0
- package/dist/typegen/core.js +219 -0
- package/dist/types.d.ts +5 -3
- package/package.json +2 -2
- package/src/auth-provider.ts +8 -5
- package/src/command-utils.ts +8 -7
- package/src/commands/audit.ts +63 -0
- package/src/commands/auth.ts +32 -37
- package/src/commands/billing.ts +73 -0
- package/src/commands/env.ts +215 -189
- package/src/commands/init.ts +47 -0
- package/src/commands/org.ts +104 -0
- package/src/commands/project.ts +130 -0
- package/src/commands/stage.ts +167 -0
- package/src/commands/target-prompts.ts +357 -0
- package/src/commands/typegen.ts +75 -29
- package/src/constants.ts +1 -1
- package/src/context/session-id.ts +14 -0
- package/src/contracts/index.ts +370 -0
- package/src/credentials-store.ts +86 -12
- package/src/http.ts +78 -2
- package/src/index.ts +12 -0
- package/src/runtime-config.ts +25 -14
- package/src/typegen/core.ts +311 -0
- package/src/types.ts +5 -3
- package/test/command-utils.test.ts +47 -0
- package/test/credentials-store.test.ts +40 -0
- package/test/runtime-config.test.ts +125 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { cancel, isCancel, select } from "@clack/prompts";
|
|
2
|
+
|
|
3
|
+
import { createCliAuthProvider } from "../auth-provider.js";
|
|
4
|
+
import { requireLocalSession } from "../command-utils.js";
|
|
5
|
+
import {
|
|
6
|
+
OrganizationsResponseSchema,
|
|
7
|
+
ProjectCreateResponseSchema,
|
|
8
|
+
ProjectDeleteResponseSchema,
|
|
9
|
+
ProjectsListResponseSchema,
|
|
10
|
+
StageCreateResponseSchema,
|
|
11
|
+
StageDeleteResponseSchema,
|
|
12
|
+
StageRenameResponseSchema,
|
|
13
|
+
StagesListResponseSchema,
|
|
14
|
+
} from "../contracts/index.js";
|
|
15
|
+
import { getJson, postJson } from "../http.js";
|
|
16
|
+
|
|
17
|
+
async function resolveManagementAccess() {
|
|
18
|
+
const local = await requireLocalSession();
|
|
19
|
+
const authProvider = createCliAuthProvider();
|
|
20
|
+
const accessToken = await authProvider.getAccessToken();
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
local,
|
|
24
|
+
accessToken,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Loads organizations for the current CLI user.
|
|
30
|
+
*
|
|
31
|
+
* @returns The accessible organizations for the signed-in user.
|
|
32
|
+
* @remarks Interactive command flows use this to avoid any hidden org-scoped auth fallback.
|
|
33
|
+
* @lastModified 2026-03-19
|
|
34
|
+
* @author GPT-5.4
|
|
35
|
+
*/
|
|
36
|
+
export async function listOrganizationsForCurrentUser() {
|
|
37
|
+
const { local, accessToken } = await resolveManagementAccess();
|
|
38
|
+
const response = await getJson({
|
|
39
|
+
baseUrl: local.baseUrl,
|
|
40
|
+
path: "/v1/cli/orgs",
|
|
41
|
+
accessToken,
|
|
42
|
+
schema: OrganizationsResponseSchema,
|
|
43
|
+
});
|
|
44
|
+
return response.organizations;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Loads projects for one organization.
|
|
49
|
+
*
|
|
50
|
+
* @param orgSlug The organization slug to inspect.
|
|
51
|
+
* @returns The projects for the organization.
|
|
52
|
+
* @remarks Project-scoped CLI flows call the same backend contract as `barekey init`.
|
|
53
|
+
* @lastModified 2026-03-19
|
|
54
|
+
* @author GPT-5.4
|
|
55
|
+
*/
|
|
56
|
+
export async function listProjectsForOrganization(orgSlug: string) {
|
|
57
|
+
const { local, accessToken } = await resolveManagementAccess();
|
|
58
|
+
const response = await postJson({
|
|
59
|
+
baseUrl: local.baseUrl,
|
|
60
|
+
path: "/v1/cli/projects/list",
|
|
61
|
+
accessToken,
|
|
62
|
+
payload: {
|
|
63
|
+
orgSlug,
|
|
64
|
+
},
|
|
65
|
+
schema: ProjectsListResponseSchema,
|
|
66
|
+
});
|
|
67
|
+
return response.projects;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Loads stages for one project.
|
|
72
|
+
*
|
|
73
|
+
* @param orgSlug The organization slug to inspect.
|
|
74
|
+
* @param projectSlug The project slug to inspect.
|
|
75
|
+
* @returns The stages for the selected project.
|
|
76
|
+
* @remarks Stage prompts use this to drive repo initialization and stage management flows.
|
|
77
|
+
* @lastModified 2026-03-19
|
|
78
|
+
* @author GPT-5.4
|
|
79
|
+
*/
|
|
80
|
+
export async function listStagesForProject(orgSlug: string, projectSlug: string) {
|
|
81
|
+
const { local, accessToken } = await resolveManagementAccess();
|
|
82
|
+
const response = await postJson({
|
|
83
|
+
baseUrl: local.baseUrl,
|
|
84
|
+
path: "/v1/cli/stages/list",
|
|
85
|
+
accessToken,
|
|
86
|
+
payload: {
|
|
87
|
+
orgSlug,
|
|
88
|
+
projectSlug,
|
|
89
|
+
},
|
|
90
|
+
schema: StagesListResponseSchema,
|
|
91
|
+
});
|
|
92
|
+
return response.stages;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Creates one project for one organization.
|
|
97
|
+
*
|
|
98
|
+
* @param orgSlug The organization slug that should own the project.
|
|
99
|
+
* @param name The project name to create.
|
|
100
|
+
* @returns The created project summary.
|
|
101
|
+
* @remarks CLI project-create flows use this helper so the command stays a thin prompt wrapper.
|
|
102
|
+
* @lastModified 2026-03-19
|
|
103
|
+
* @author GPT-5.4
|
|
104
|
+
*/
|
|
105
|
+
export async function createProjectForOrganization(orgSlug: string, name: string) {
|
|
106
|
+
const { local, accessToken } = await resolveManagementAccess();
|
|
107
|
+
const response = await postJson({
|
|
108
|
+
baseUrl: local.baseUrl,
|
|
109
|
+
path: "/v1/cli/projects/create",
|
|
110
|
+
accessToken,
|
|
111
|
+
payload: {
|
|
112
|
+
orgSlug,
|
|
113
|
+
name,
|
|
114
|
+
},
|
|
115
|
+
schema: ProjectCreateResponseSchema,
|
|
116
|
+
});
|
|
117
|
+
return response.project;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Deletes one project for one organization.
|
|
122
|
+
*
|
|
123
|
+
* @param orgSlug The organization slug that owns the project.
|
|
124
|
+
* @param projectSlug The project slug to delete.
|
|
125
|
+
* @returns The deleted project payload.
|
|
126
|
+
* @remarks Destructive project flows use this shared helper so command handlers stay focused on prompts and output.
|
|
127
|
+
* @lastModified 2026-03-19
|
|
128
|
+
* @author GPT-5.4
|
|
129
|
+
*/
|
|
130
|
+
export async function deleteProjectForOrganization(orgSlug: string, projectSlug: string) {
|
|
131
|
+
const { local, accessToken } = await resolveManagementAccess();
|
|
132
|
+
return await postJson({
|
|
133
|
+
baseUrl: local.baseUrl,
|
|
134
|
+
path: "/v1/cli/projects/delete",
|
|
135
|
+
accessToken,
|
|
136
|
+
payload: {
|
|
137
|
+
orgSlug,
|
|
138
|
+
projectSlug,
|
|
139
|
+
},
|
|
140
|
+
schema: ProjectDeleteResponseSchema,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Creates one stage for one project.
|
|
146
|
+
*
|
|
147
|
+
* @param orgSlug The organization slug that owns the project.
|
|
148
|
+
* @param projectSlug The project slug that should receive the stage.
|
|
149
|
+
* @param name The stage name to create.
|
|
150
|
+
* @returns The created stage summary.
|
|
151
|
+
* @remarks CLI stage-create flows use this helper so the command stays a thin prompt wrapper.
|
|
152
|
+
* @lastModified 2026-03-19
|
|
153
|
+
* @author GPT-5.4
|
|
154
|
+
*/
|
|
155
|
+
export async function createStageForProject(orgSlug: string, projectSlug: string, name: string) {
|
|
156
|
+
const { local, accessToken } = await resolveManagementAccess();
|
|
157
|
+
const response = await postJson({
|
|
158
|
+
baseUrl: local.baseUrl,
|
|
159
|
+
path: "/v1/cli/stages/create",
|
|
160
|
+
accessToken,
|
|
161
|
+
payload: {
|
|
162
|
+
orgSlug,
|
|
163
|
+
projectSlug,
|
|
164
|
+
name,
|
|
165
|
+
},
|
|
166
|
+
schema: StageCreateResponseSchema,
|
|
167
|
+
});
|
|
168
|
+
return response.stage;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Renames one stage for one project.
|
|
173
|
+
*
|
|
174
|
+
* @param orgSlug The organization slug that owns the project.
|
|
175
|
+
* @param projectSlug The project slug that owns the stage.
|
|
176
|
+
* @param stageSlug The stage slug to rename.
|
|
177
|
+
* @param name The next display name for the stage.
|
|
178
|
+
* @returns The updated stage summary.
|
|
179
|
+
* @remarks Stage rename keeps immutable slugs and only patches the display name.
|
|
180
|
+
* @lastModified 2026-03-19
|
|
181
|
+
* @author GPT-5.4
|
|
182
|
+
*/
|
|
183
|
+
export async function renameStageForProject(
|
|
184
|
+
orgSlug: string,
|
|
185
|
+
projectSlug: string,
|
|
186
|
+
stageSlug: string,
|
|
187
|
+
name: string,
|
|
188
|
+
) {
|
|
189
|
+
const { local, accessToken } = await resolveManagementAccess();
|
|
190
|
+
const response = await postJson({
|
|
191
|
+
baseUrl: local.baseUrl,
|
|
192
|
+
path: "/v1/cli/stages/rename",
|
|
193
|
+
accessToken,
|
|
194
|
+
payload: {
|
|
195
|
+
orgSlug,
|
|
196
|
+
projectSlug,
|
|
197
|
+
stageSlug,
|
|
198
|
+
name,
|
|
199
|
+
},
|
|
200
|
+
schema: StageRenameResponseSchema,
|
|
201
|
+
});
|
|
202
|
+
return response.stage;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Deletes one stage for one project.
|
|
207
|
+
*
|
|
208
|
+
* @param orgSlug The organization slug that owns the project.
|
|
209
|
+
* @param projectSlug The project slug that owns the stage.
|
|
210
|
+
* @param stageSlug The stage slug to delete.
|
|
211
|
+
* @returns The deleted stage payload.
|
|
212
|
+
* @remarks Destructive stage flows use this helper so command handlers stay prompt-focused.
|
|
213
|
+
* @lastModified 2026-03-19
|
|
214
|
+
* @author GPT-5.4
|
|
215
|
+
*/
|
|
216
|
+
export async function deleteStageForProject(
|
|
217
|
+
orgSlug: string,
|
|
218
|
+
projectSlug: string,
|
|
219
|
+
stageSlug: string,
|
|
220
|
+
) {
|
|
221
|
+
const { local, accessToken } = await resolveManagementAccess();
|
|
222
|
+
return await postJson({
|
|
223
|
+
baseUrl: local.baseUrl,
|
|
224
|
+
path: "/v1/cli/stages/delete",
|
|
225
|
+
accessToken,
|
|
226
|
+
payload: {
|
|
227
|
+
orgSlug,
|
|
228
|
+
projectSlug,
|
|
229
|
+
stageSlug,
|
|
230
|
+
},
|
|
231
|
+
schema: StageDeleteResponseSchema,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Resolves one organization target from an explicit flag or an interactive selection.
|
|
237
|
+
*
|
|
238
|
+
* @param orgSlug The optionally supplied organization slug.
|
|
239
|
+
* @returns The resolved organization slug.
|
|
240
|
+
* @remarks Non-interactive runs must provide the target explicitly or via local repo config higher up the call stack.
|
|
241
|
+
* @lastModified 2026-03-19
|
|
242
|
+
* @author GPT-5.4
|
|
243
|
+
*/
|
|
244
|
+
export async function promptForOrganizationSlug(orgSlug: string | undefined): Promise<string> {
|
|
245
|
+
const explicit = orgSlug?.trim();
|
|
246
|
+
if (explicit && explicit.length > 0) {
|
|
247
|
+
return explicit;
|
|
248
|
+
}
|
|
249
|
+
if (!process.stdout.isTTY) {
|
|
250
|
+
throw new Error("Organization slug is required in non-interactive mode.");
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const organizations = await listOrganizationsForCurrentUser();
|
|
254
|
+
if (organizations.length === 0) {
|
|
255
|
+
throw new Error("No organizations found. Create one first with barekey org create.");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const selected = await select({
|
|
259
|
+
message: "Which organization should Barekey use?",
|
|
260
|
+
options: organizations.map((organization) => ({
|
|
261
|
+
value: organization.slug,
|
|
262
|
+
label: organization.name,
|
|
263
|
+
hint: organization.slug,
|
|
264
|
+
})),
|
|
265
|
+
});
|
|
266
|
+
if (isCancel(selected)) {
|
|
267
|
+
cancel("Command canceled.");
|
|
268
|
+
process.exit(0);
|
|
269
|
+
}
|
|
270
|
+
return selected;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Resolves one project target from an explicit flag or an interactive selection.
|
|
275
|
+
*
|
|
276
|
+
* @param orgSlug The owning organization slug.
|
|
277
|
+
* @param projectSlug The optionally supplied project slug.
|
|
278
|
+
* @returns The resolved project slug.
|
|
279
|
+
* @remarks This intentionally loads live project choices instead of guessing from auth state.
|
|
280
|
+
* @lastModified 2026-03-19
|
|
281
|
+
* @author GPT-5.4
|
|
282
|
+
*/
|
|
283
|
+
export async function promptForProjectSlug(
|
|
284
|
+
orgSlug: string,
|
|
285
|
+
projectSlug: string | undefined,
|
|
286
|
+
): Promise<string> {
|
|
287
|
+
const explicit = projectSlug?.trim();
|
|
288
|
+
if (explicit && explicit.length > 0) {
|
|
289
|
+
return explicit;
|
|
290
|
+
}
|
|
291
|
+
if (!process.stdout.isTTY) {
|
|
292
|
+
throw new Error("Project slug is required in non-interactive mode.");
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const projects = await listProjectsForOrganization(orgSlug);
|
|
296
|
+
if (projects.length === 0) {
|
|
297
|
+
throw new Error("No projects found. Create one first with barekey project create.");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const selected = await select({
|
|
301
|
+
message: "Which project should Barekey use?",
|
|
302
|
+
options: projects.map((project) => ({
|
|
303
|
+
value: project.slug,
|
|
304
|
+
label: project.name,
|
|
305
|
+
hint: project.slug,
|
|
306
|
+
})),
|
|
307
|
+
});
|
|
308
|
+
if (isCancel(selected)) {
|
|
309
|
+
cancel("Command canceled.");
|
|
310
|
+
process.exit(0);
|
|
311
|
+
}
|
|
312
|
+
return selected;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Resolves one stage target from an explicit flag or an interactive selection.
|
|
317
|
+
*
|
|
318
|
+
* @param orgSlug The owning organization slug.
|
|
319
|
+
* @param projectSlug The owning project slug.
|
|
320
|
+
* @param stageSlug The optionally supplied stage slug.
|
|
321
|
+
* @returns The resolved stage slug.
|
|
322
|
+
* @remarks This is used by `barekey init` so local repo setup can be a guided flow.
|
|
323
|
+
* @lastModified 2026-03-19
|
|
324
|
+
* @author GPT-5.4
|
|
325
|
+
*/
|
|
326
|
+
export async function promptForStageSlug(
|
|
327
|
+
orgSlug: string,
|
|
328
|
+
projectSlug: string,
|
|
329
|
+
stageSlug: string | undefined,
|
|
330
|
+
): Promise<string> {
|
|
331
|
+
const explicit = stageSlug?.trim();
|
|
332
|
+
if (explicit && explicit.length > 0) {
|
|
333
|
+
return explicit;
|
|
334
|
+
}
|
|
335
|
+
if (!process.stdout.isTTY) {
|
|
336
|
+
throw new Error("Stage slug is required in non-interactive mode.");
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const stages = await listStagesForProject(orgSlug, projectSlug);
|
|
340
|
+
if (stages.length === 0) {
|
|
341
|
+
throw new Error("No stages found. Create one first with barekey stage create.");
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const selected = await select({
|
|
345
|
+
message: "Which stage should Barekey use?",
|
|
346
|
+
options: stages.map((stage) => ({
|
|
347
|
+
value: stage.slug,
|
|
348
|
+
label: stage.name,
|
|
349
|
+
hint: stage.slug,
|
|
350
|
+
})),
|
|
351
|
+
});
|
|
352
|
+
if (isCancel(selected)) {
|
|
353
|
+
cancel("Command canceled.");
|
|
354
|
+
process.exit(0);
|
|
355
|
+
}
|
|
356
|
+
return selected;
|
|
357
|
+
}
|
package/src/commands/typegen.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import { BarekeyClient } from "@barekey/sdk/server";
|
|
2
|
-
import type { BarekeyTypegenResult } from "@barekey/sdk/server";
|
|
3
1
|
import { Command } from "commander";
|
|
4
2
|
import pc from "picocolors";
|
|
5
3
|
|
|
4
|
+
import { createCliAuthProvider } from "../auth-provider.js";
|
|
6
5
|
import {
|
|
7
6
|
addTargetOptions,
|
|
8
7
|
requireLocalSession,
|
|
9
8
|
resolveTarget,
|
|
10
9
|
type EnvTargetOptions,
|
|
11
10
|
} from "../command-utils.js";
|
|
11
|
+
import { TypegenManifestSchema } from "../contracts/index.js";
|
|
12
|
+
import { getJson } from "../http.js";
|
|
13
|
+
import { loadRuntimeConfig } from "../runtime-config.js";
|
|
14
|
+
import {
|
|
15
|
+
type CliTypegenResult,
|
|
16
|
+
writeInstalledSdkGeneratedTypes,
|
|
17
|
+
} from "../typegen/core.js";
|
|
12
18
|
|
|
13
19
|
const DEFAULT_TYPEGEN_WATCH_INTERVAL_MS = 5_000;
|
|
14
20
|
|
|
15
|
-
export function formatTypegenResultMessage(result:
|
|
21
|
+
export function formatTypegenResultMessage(result: CliTypegenResult): string {
|
|
16
22
|
const title = result.written
|
|
17
23
|
? pc.green(pc.bold("Typegen complete"))
|
|
18
24
|
: pc.cyan(pc.bold("Typegen already up to date"));
|
|
@@ -60,35 +66,69 @@ function sleep(milliseconds: number): Promise<void> {
|
|
|
60
66
|
});
|
|
61
67
|
}
|
|
62
68
|
|
|
63
|
-
async function
|
|
64
|
-
|
|
69
|
+
async function resolveTypegenContext(options: EnvTargetOptions): Promise<{
|
|
70
|
+
baseUrl: string | null;
|
|
71
|
+
accessToken: string | null;
|
|
65
72
|
organization: string;
|
|
66
73
|
project: string;
|
|
67
74
|
environment: string;
|
|
75
|
+
runtimeMode: "centralized" | "standalone";
|
|
76
|
+
typegenMode: "semantic" | "minimal";
|
|
77
|
+
localEnvRoot: string | null;
|
|
68
78
|
}> {
|
|
69
|
-
const
|
|
79
|
+
const runtime = await loadRuntimeConfig();
|
|
80
|
+
const local = runtime?.config.config?.mode === "standalone" ? null : await requireLocalSession();
|
|
70
81
|
const target = await resolveTarget(options, local);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
const authProvider = local === null ? null : createCliAuthProvider();
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
baseUrl: local?.baseUrl ?? null,
|
|
86
|
+
accessToken: authProvider === null ? null : await authProvider.getAccessToken(),
|
|
87
|
+
organization: target.orgSlug ?? "local",
|
|
88
|
+
project: target.projectSlug.trim().length > 0 ? target.projectSlug : "standalone",
|
|
89
|
+
environment: target.stageSlug.trim().length > 0 ? target.stageSlug : "local",
|
|
90
|
+
runtimeMode: runtime?.config.config?.mode ?? "centralized",
|
|
91
|
+
typegenMode: runtime?.config.config?.typegen ?? "semantic",
|
|
92
|
+
localEnvRoot: runtime?.path ?? null,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function fetchManifest(options: EnvTargetOptions) {
|
|
97
|
+
const context = await resolveTypegenContext(options);
|
|
98
|
+
if (context.baseUrl === null || context.accessToken === null) {
|
|
99
|
+
throw new Error("Typegen currently requires centralized Barekey auth.");
|
|
74
100
|
}
|
|
75
101
|
|
|
102
|
+
const searchParams = new URLSearchParams({
|
|
103
|
+
orgSlug: context.organization,
|
|
104
|
+
projectSlug: context.project,
|
|
105
|
+
stageSlug: context.environment,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const manifest = await getJson({
|
|
109
|
+
baseUrl: context.baseUrl,
|
|
110
|
+
path: `/v1/typegen/manifest?${searchParams.toString()}`,
|
|
111
|
+
accessToken: context.accessToken,
|
|
112
|
+
schema: TypegenManifestSchema,
|
|
113
|
+
});
|
|
114
|
+
|
|
76
115
|
return {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
project: target.projectSlug,
|
|
80
|
-
environment: target.stageSlug,
|
|
81
|
-
typegen: false,
|
|
82
|
-
}),
|
|
83
|
-
organization,
|
|
84
|
-
project: target.projectSlug,
|
|
85
|
-
environment: target.stageSlug,
|
|
116
|
+
manifest,
|
|
117
|
+
context,
|
|
86
118
|
};
|
|
87
119
|
}
|
|
88
120
|
|
|
89
121
|
async function runTypegen(options: EnvTargetOptions): Promise<void> {
|
|
90
|
-
const {
|
|
91
|
-
const result = await
|
|
122
|
+
const { manifest, context } = await fetchManifest(options);
|
|
123
|
+
const result = await writeInstalledSdkGeneratedTypes(manifest, {
|
|
124
|
+
baseUrl: context.baseUrl,
|
|
125
|
+
orgSlug: context.organization,
|
|
126
|
+
projectSlug: context.project,
|
|
127
|
+
stageSlug: context.environment,
|
|
128
|
+
typegenMode: context.typegenMode,
|
|
129
|
+
runtimeMode: context.runtimeMode,
|
|
130
|
+
localEnvRoot: context.localEnvRoot,
|
|
131
|
+
});
|
|
92
132
|
|
|
93
133
|
console.log(formatTypegenResultMessage(result));
|
|
94
134
|
}
|
|
@@ -99,13 +139,13 @@ async function runTypegenWatch(
|
|
|
99
139
|
},
|
|
100
140
|
): Promise<void> {
|
|
101
141
|
const intervalMs = parseTypegenWatchInterval(options.interval);
|
|
102
|
-
const {
|
|
142
|
+
const { context } = await fetchManifest(options);
|
|
103
143
|
|
|
104
144
|
console.log(
|
|
105
145
|
formatTypegenWatchStartedMessage({
|
|
106
|
-
organization,
|
|
107
|
-
project,
|
|
108
|
-
environment,
|
|
146
|
+
organization: context.organization,
|
|
147
|
+
project: context.project,
|
|
148
|
+
environment: context.environment,
|
|
109
149
|
intervalMs,
|
|
110
150
|
}),
|
|
111
151
|
);
|
|
@@ -120,7 +160,16 @@ async function runTypegenWatch(
|
|
|
120
160
|
try {
|
|
121
161
|
let isFirstRun = true;
|
|
122
162
|
while (!stopped) {
|
|
123
|
-
const
|
|
163
|
+
const { manifest, context: nextContext } = await fetchManifest(options);
|
|
164
|
+
const result = await writeInstalledSdkGeneratedTypes(manifest, {
|
|
165
|
+
baseUrl: nextContext.baseUrl,
|
|
166
|
+
orgSlug: nextContext.organization,
|
|
167
|
+
projectSlug: nextContext.project,
|
|
168
|
+
stageSlug: nextContext.environment,
|
|
169
|
+
typegenMode: nextContext.typegenMode,
|
|
170
|
+
runtimeMode: nextContext.runtimeMode,
|
|
171
|
+
localEnvRoot: nextContext.localEnvRoot,
|
|
172
|
+
});
|
|
124
173
|
if (isFirstRun || result.written) {
|
|
125
174
|
if (!isFirstRun) {
|
|
126
175
|
console.log("");
|
|
@@ -147,10 +196,7 @@ export function registerTypegenCommand(program: Command): void {
|
|
|
147
196
|
.command("typegen")
|
|
148
197
|
.description("Generate Barekey SDK types in the installed @barekey/sdk module")
|
|
149
198
|
.option("--watch", "Keep generated types up to date during development", false)
|
|
150
|
-
.option(
|
|
151
|
-
"--interval <ms>",
|
|
152
|
-
"Polling interval for --watch in milliseconds",
|
|
153
|
-
),
|
|
199
|
+
.option("--interval <ms>", "Polling interval for --watch in milliseconds"),
|
|
154
200
|
).action(async (options: EnvTargetOptions & { watch?: boolean; interval?: string }) => {
|
|
155
201
|
if (options.watch) {
|
|
156
202
|
await runTypegenWatch(options);
|
package/src/constants.ts
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the stable CLI session id for one base URL and Clerk user.
|
|
3
|
+
*
|
|
4
|
+
* @param baseUrl The Barekey API base URL.
|
|
5
|
+
* @param clerkUserId The authenticated Clerk user id.
|
|
6
|
+
* @returns The normalized CLI session id.
|
|
7
|
+
* @remarks CLI auth is global per user and base URL, not per organization.
|
|
8
|
+
* @lastModified 2026-03-19
|
|
9
|
+
* @author GPT-5.4
|
|
10
|
+
*/
|
|
11
|
+
export function buildSessionId(baseUrl: string, clerkUserId: string): string {
|
|
12
|
+
const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
|
|
13
|
+
return `${normalizedBaseUrl}::${clerkUserId}`;
|
|
14
|
+
}
|