@barekey/cli 0.4.0 → 0.5.1
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.js +6 -6
- package/dist/commands/audit.d.ts +2 -0
- package/dist/commands/audit.js +47 -0
- package/dist/commands/auth.js +31 -9
- package/dist/commands/billing.d.ts +2 -0
- package/dist/commands/billing.js +59 -0
- package/dist/commands/env.js +157 -125
- 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 +57 -32
- 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 +499 -0
- package/dist/contracts/index.js +313 -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.js +14 -26
- 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 +6 -6
- package/src/commands/audit.ts +63 -0
- package/src/commands/auth.ts +45 -39
- package/src/commands/billing.ts +70 -0
- package/src/commands/env.ts +211 -218
- 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 +71 -45
- package/src/constants.ts +1 -1
- package/src/context/session-id.ts +14 -0
- package/src/contracts/index.ts +376 -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 +19 -32
- 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
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
export const DeclaredTypeSchema = Schema.Literal("string", "boolean", "int64", "float", "date", "json");
|
|
3
|
+
export const VisibilitySchema = Schema.Literal("private", "public");
|
|
4
|
+
export const RolloutFunctionSchema = Schema.Literal("linear", "step", "ease_in_out");
|
|
5
|
+
export const RuntimeModeSchema = Schema.Literal("centralized", "standalone");
|
|
6
|
+
export const TypegenModeSchema = Schema.Literal("semantic", "minimal");
|
|
7
|
+
const TrimmedStringSchema = Schema.String;
|
|
8
|
+
const NonEmptyStringSchema = Schema.String.pipe(Schema.minLength(1));
|
|
9
|
+
export const RuntimeConfigSchema = Schema.Struct({
|
|
10
|
+
organization: Schema.optional(Schema.NullOr(TrimmedStringSchema)),
|
|
11
|
+
org: Schema.optional(Schema.NullOr(TrimmedStringSchema)),
|
|
12
|
+
project: Schema.optional(Schema.NullOr(TrimmedStringSchema)),
|
|
13
|
+
environment: Schema.optional(Schema.NullOr(TrimmedStringSchema)),
|
|
14
|
+
stage: Schema.optional(Schema.NullOr(TrimmedStringSchema)),
|
|
15
|
+
typegen: Schema.optional(Schema.NullOr(TypegenModeSchema)),
|
|
16
|
+
config: Schema.optional(Schema.Struct({
|
|
17
|
+
typegen: Schema.optional(TypegenModeSchema),
|
|
18
|
+
mode: Schema.optional(RuntimeModeSchema),
|
|
19
|
+
})),
|
|
20
|
+
});
|
|
21
|
+
export const CliConfigSchema = Schema.Union(Schema.Struct({
|
|
22
|
+
baseUrl: NonEmptyStringSchema,
|
|
23
|
+
activeSessionId: NonEmptyStringSchema,
|
|
24
|
+
}), Schema.Struct({
|
|
25
|
+
baseUrl: NonEmptyStringSchema,
|
|
26
|
+
activeAccountId: NonEmptyStringSchema,
|
|
27
|
+
}));
|
|
28
|
+
export const CliSessionSchema = Schema.Union(Schema.Struct({
|
|
29
|
+
accessToken: NonEmptyStringSchema,
|
|
30
|
+
refreshToken: NonEmptyStringSchema,
|
|
31
|
+
accessTokenExpiresAtMs: Schema.Number.pipe(Schema.finite()),
|
|
32
|
+
refreshTokenExpiresAtMs: Schema.Number.pipe(Schema.finite()),
|
|
33
|
+
clerkUserId: NonEmptyStringSchema,
|
|
34
|
+
orgId: Schema.NullOr(NonEmptyStringSchema),
|
|
35
|
+
orgSlug: Schema.NullOr(NonEmptyStringSchema),
|
|
36
|
+
lastOrgId: Schema.optional(Schema.NullOr(NonEmptyStringSchema)),
|
|
37
|
+
lastOrgSlug: Schema.optional(Schema.NullOr(NonEmptyStringSchema)),
|
|
38
|
+
}), Schema.Struct({
|
|
39
|
+
accessToken: NonEmptyStringSchema,
|
|
40
|
+
refreshToken: NonEmptyStringSchema,
|
|
41
|
+
accessTokenExpiresAtMs: Schema.Number.pipe(Schema.finite()),
|
|
42
|
+
refreshTokenExpiresAtMs: Schema.Number.pipe(Schema.finite()),
|
|
43
|
+
clerkUserId: NonEmptyStringSchema,
|
|
44
|
+
orgId: NonEmptyStringSchema,
|
|
45
|
+
orgSlug: NonEmptyStringSchema,
|
|
46
|
+
}));
|
|
47
|
+
export const ErrorEnvelopeSchema = Schema.Struct({
|
|
48
|
+
error: Schema.Struct({
|
|
49
|
+
code: Schema.optional(Schema.String),
|
|
50
|
+
message: Schema.optional(Schema.String),
|
|
51
|
+
requestId: Schema.optional(Schema.NullOr(Schema.String)),
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
export const CliSessionResponseSchema = Schema.Struct({
|
|
55
|
+
clerkUserId: Schema.String,
|
|
56
|
+
displayName: Schema.NullOr(Schema.String),
|
|
57
|
+
email: Schema.NullOr(Schema.String),
|
|
58
|
+
orgId: Schema.String,
|
|
59
|
+
orgSlug: Schema.String,
|
|
60
|
+
source: Schema.Literal("clerk", "cli"),
|
|
61
|
+
requestId: Schema.optional(Schema.String),
|
|
62
|
+
});
|
|
63
|
+
export const DeviceStartResponseSchema = Schema.Struct({
|
|
64
|
+
deviceCode: Schema.String,
|
|
65
|
+
userCode: Schema.String,
|
|
66
|
+
verificationUri: Schema.String,
|
|
67
|
+
intervalSec: Schema.Number.pipe(Schema.finite()),
|
|
68
|
+
expiresInSec: Schema.Number.pipe(Schema.finite()),
|
|
69
|
+
requestId: Schema.optional(Schema.String),
|
|
70
|
+
});
|
|
71
|
+
export const DevicePollPendingSchema = Schema.Struct({
|
|
72
|
+
status: Schema.Literal("pending"),
|
|
73
|
+
intervalSec: Schema.Number.pipe(Schema.finite()),
|
|
74
|
+
requestId: Schema.optional(Schema.String),
|
|
75
|
+
});
|
|
76
|
+
export const DevicePollApprovedSchema = Schema.Struct({
|
|
77
|
+
status: Schema.Literal("approved"),
|
|
78
|
+
intervalSec: Schema.Number.pipe(Schema.finite()),
|
|
79
|
+
accessToken: Schema.String,
|
|
80
|
+
refreshToken: Schema.String,
|
|
81
|
+
accessTokenExpiresAtMs: Schema.Number.pipe(Schema.finite()),
|
|
82
|
+
refreshTokenExpiresAtMs: Schema.Number.pipe(Schema.finite()),
|
|
83
|
+
orgId: Schema.String,
|
|
84
|
+
orgSlug: Schema.String,
|
|
85
|
+
clerkUserId: Schema.String,
|
|
86
|
+
displayName: Schema.NullOr(Schema.String),
|
|
87
|
+
email: Schema.NullOr(Schema.String),
|
|
88
|
+
requestId: Schema.optional(Schema.String),
|
|
89
|
+
});
|
|
90
|
+
export const DevicePollResponseSchema = Schema.Union(DevicePollPendingSchema, DevicePollApprovedSchema);
|
|
91
|
+
export const RefreshResponseSchema = Schema.Struct({
|
|
92
|
+
accessToken: Schema.String,
|
|
93
|
+
refreshToken: Schema.String,
|
|
94
|
+
accessTokenExpiresAtMs: Schema.Number.pipe(Schema.finite()),
|
|
95
|
+
refreshTokenExpiresAtMs: Schema.Number.pipe(Schema.finite()),
|
|
96
|
+
orgId: Schema.String,
|
|
97
|
+
orgSlug: Schema.String,
|
|
98
|
+
clerkUserId: Schema.String,
|
|
99
|
+
displayName: Schema.NullOr(Schema.String),
|
|
100
|
+
email: Schema.NullOr(Schema.String),
|
|
101
|
+
requestId: Schema.optional(Schema.String),
|
|
102
|
+
});
|
|
103
|
+
export const EnvDecisionSchema = Schema.Struct({
|
|
104
|
+
bucket: Schema.Number.pipe(Schema.finite()),
|
|
105
|
+
chance: Schema.Number.pipe(Schema.finite()),
|
|
106
|
+
seed: Schema.optional(Schema.String),
|
|
107
|
+
key: Schema.optional(Schema.String),
|
|
108
|
+
matchedRule: Schema.String,
|
|
109
|
+
});
|
|
110
|
+
export const EnvResolvedValueSchema = Schema.Struct({
|
|
111
|
+
name: Schema.String,
|
|
112
|
+
kind: Schema.Literal("secret", "ab_roll", "rollout"),
|
|
113
|
+
declaredType: DeclaredTypeSchema,
|
|
114
|
+
visibility: VisibilitySchema,
|
|
115
|
+
value: Schema.Unknown,
|
|
116
|
+
decision: Schema.optional(EnvDecisionSchema),
|
|
117
|
+
});
|
|
118
|
+
export const EnvEvaluateResponseSchema = Schema.Struct({
|
|
119
|
+
name: Schema.String,
|
|
120
|
+
kind: Schema.Literal("secret", "ab_roll", "rollout"),
|
|
121
|
+
declaredType: DeclaredTypeSchema,
|
|
122
|
+
visibility: VisibilitySchema,
|
|
123
|
+
value: Schema.Unknown,
|
|
124
|
+
decision: Schema.optional(EnvDecisionSchema),
|
|
125
|
+
});
|
|
126
|
+
export const EnvEvaluateBatchResponseSchema = Schema.Struct({
|
|
127
|
+
values: Schema.Array(EnvResolvedValueSchema),
|
|
128
|
+
});
|
|
129
|
+
export const RolloutMilestoneSchema = Schema.Struct({
|
|
130
|
+
at: Schema.String,
|
|
131
|
+
percentage: Schema.Number.pipe(Schema.finite()),
|
|
132
|
+
});
|
|
133
|
+
export const EnvVariableListItemSchema = Schema.Struct({
|
|
134
|
+
name: Schema.String,
|
|
135
|
+
visibility: VisibilitySchema,
|
|
136
|
+
kind: Schema.Literal("secret", "ab_roll", "rollout"),
|
|
137
|
+
declaredType: DeclaredTypeSchema,
|
|
138
|
+
createdAtMs: Schema.Number.pipe(Schema.finite()),
|
|
139
|
+
updatedAtMs: Schema.Number.pipe(Schema.finite()),
|
|
140
|
+
chance: Schema.NullOr(Schema.Number.pipe(Schema.finite())),
|
|
141
|
+
rolloutFunction: Schema.NullOr(RolloutFunctionSchema),
|
|
142
|
+
rolloutMilestones: Schema.NullOr(Schema.Array(RolloutMilestoneSchema)),
|
|
143
|
+
});
|
|
144
|
+
export const EnvListResponseSchema = Schema.Struct({
|
|
145
|
+
variables: Schema.Array(EnvVariableListItemSchema),
|
|
146
|
+
});
|
|
147
|
+
export const EnvWriteResponseSchema = Schema.Struct({
|
|
148
|
+
createdCount: Schema.Number.pipe(Schema.finite()),
|
|
149
|
+
updatedCount: Schema.Number.pipe(Schema.finite()),
|
|
150
|
+
deletedCount: Schema.Number.pipe(Schema.finite()),
|
|
151
|
+
});
|
|
152
|
+
export const EnvPullValueSchema = Schema.Struct({
|
|
153
|
+
name: Schema.String,
|
|
154
|
+
kind: Schema.Literal("secret", "ab_roll", "rollout"),
|
|
155
|
+
declaredType: DeclaredTypeSchema,
|
|
156
|
+
value: Schema.String,
|
|
157
|
+
});
|
|
158
|
+
export const EnvPullResponseSchema = Schema.Struct({
|
|
159
|
+
values: Schema.Array(EnvPullValueSchema),
|
|
160
|
+
byName: Schema.Record({ key: Schema.String, value: Schema.String }),
|
|
161
|
+
});
|
|
162
|
+
export const TypegenVariableSchema = Schema.Struct({
|
|
163
|
+
name: Schema.String,
|
|
164
|
+
visibility: VisibilitySchema,
|
|
165
|
+
kind: Schema.Literal("secret", "ab_roll", "rollout"),
|
|
166
|
+
declaredType: DeclaredTypeSchema,
|
|
167
|
+
required: Schema.Boolean,
|
|
168
|
+
updatedAtMs: Schema.Number.pipe(Schema.finite()),
|
|
169
|
+
typeScriptType: Schema.String,
|
|
170
|
+
valueATypeScriptType: Schema.NullOr(Schema.String),
|
|
171
|
+
valueBTypeScriptType: Schema.NullOr(Schema.String),
|
|
172
|
+
rolloutFunction: Schema.NullOr(RolloutFunctionSchema),
|
|
173
|
+
rolloutMilestones: Schema.NullOr(Schema.Array(RolloutMilestoneSchema)),
|
|
174
|
+
});
|
|
175
|
+
export const TypegenManifestSchema = Schema.Struct({
|
|
176
|
+
orgId: Schema.String,
|
|
177
|
+
orgSlug: Schema.String,
|
|
178
|
+
projectSlug: Schema.String,
|
|
179
|
+
stageSlug: Schema.String,
|
|
180
|
+
generatedAtMs: Schema.Number.pipe(Schema.finite()),
|
|
181
|
+
manifestVersion: Schema.String,
|
|
182
|
+
variables: Schema.Array(TypegenVariableSchema),
|
|
183
|
+
});
|
|
184
|
+
export const OrganizationSummarySchema = Schema.Struct({
|
|
185
|
+
id: Schema.String,
|
|
186
|
+
slug: Schema.String,
|
|
187
|
+
name: Schema.String,
|
|
188
|
+
role: Schema.String,
|
|
189
|
+
imageUrl: Schema.String,
|
|
190
|
+
});
|
|
191
|
+
export const OrganizationsResponseSchema = Schema.Struct({
|
|
192
|
+
organizations: Schema.Array(OrganizationSummarySchema),
|
|
193
|
+
});
|
|
194
|
+
export const ProjectSummarySchema = Schema.Struct({
|
|
195
|
+
id: Schema.String,
|
|
196
|
+
orgId: Schema.String,
|
|
197
|
+
orgSlug: Schema.String,
|
|
198
|
+
name: Schema.String,
|
|
199
|
+
slug: Schema.String,
|
|
200
|
+
slugBase: Schema.String,
|
|
201
|
+
createdByClerkUserId: Schema.String,
|
|
202
|
+
createdAtMs: Schema.Number.pipe(Schema.finite()),
|
|
203
|
+
updatedAtMs: Schema.Number.pipe(Schema.finite()),
|
|
204
|
+
});
|
|
205
|
+
export const ProjectListItemSchema = Schema.Struct({
|
|
206
|
+
id: Schema.String,
|
|
207
|
+
orgId: Schema.String,
|
|
208
|
+
orgSlug: Schema.String,
|
|
209
|
+
name: Schema.String,
|
|
210
|
+
slug: Schema.String,
|
|
211
|
+
slugBase: Schema.String,
|
|
212
|
+
createdByClerkUserId: Schema.String,
|
|
213
|
+
createdAtMs: Schema.Number.pipe(Schema.finite()),
|
|
214
|
+
updatedAtMs: Schema.Number.pipe(Schema.finite()),
|
|
215
|
+
secretCount: Schema.Number.pipe(Schema.finite()),
|
|
216
|
+
});
|
|
217
|
+
export const ProjectsListResponseSchema = Schema.Struct({
|
|
218
|
+
projects: Schema.Array(ProjectListItemSchema),
|
|
219
|
+
});
|
|
220
|
+
export const ProjectCreateResponseSchema = Schema.Struct({
|
|
221
|
+
project: ProjectSummarySchema,
|
|
222
|
+
});
|
|
223
|
+
export const ProjectDeleteResponseSchema = Schema.Struct({
|
|
224
|
+
deletedProjectId: Schema.String,
|
|
225
|
+
deletedProjectSlug: Schema.String,
|
|
226
|
+
});
|
|
227
|
+
export const StageSummarySchema = Schema.Struct({
|
|
228
|
+
id: Schema.String,
|
|
229
|
+
projectId: Schema.String,
|
|
230
|
+
orgId: Schema.String,
|
|
231
|
+
slug: Schema.String,
|
|
232
|
+
name: Schema.String,
|
|
233
|
+
isDefault: Schema.Boolean,
|
|
234
|
+
variableCount: Schema.Number.pipe(Schema.finite()),
|
|
235
|
+
createdAtMs: Schema.Number.pipe(Schema.finite()),
|
|
236
|
+
updatedAtMs: Schema.Number.pipe(Schema.finite()),
|
|
237
|
+
});
|
|
238
|
+
export const StagesListResponseSchema = Schema.Struct({
|
|
239
|
+
stages: Schema.Array(StageSummarySchema),
|
|
240
|
+
});
|
|
241
|
+
export const StageCreateResponseSchema = Schema.Struct({
|
|
242
|
+
stage: StageSummarySchema,
|
|
243
|
+
});
|
|
244
|
+
export const StageRenameResponseSchema = Schema.Struct({
|
|
245
|
+
stage: StageSummarySchema,
|
|
246
|
+
});
|
|
247
|
+
export const StageDeleteResponseSchema = Schema.Struct({
|
|
248
|
+
deletedStageSlug: Schema.String,
|
|
249
|
+
});
|
|
250
|
+
export const FeatureUsageSchema = Schema.Struct({
|
|
251
|
+
featureId: Schema.String,
|
|
252
|
+
allowed: Schema.Boolean,
|
|
253
|
+
usage: Schema.NullOr(Schema.Number.pipe(Schema.finite())),
|
|
254
|
+
includedUsage: Schema.NullOr(Schema.Number.pipe(Schema.finite())),
|
|
255
|
+
usageLimit: Schema.NullOr(Schema.Number.pipe(Schema.finite())),
|
|
256
|
+
overageAllowed: Schema.NullOr(Schema.Boolean),
|
|
257
|
+
nextResetAtMs: Schema.NullOr(Schema.Number.pipe(Schema.finite())),
|
|
258
|
+
});
|
|
259
|
+
export const BillingCatalogResponseSchema = Schema.Struct({
|
|
260
|
+
variants: Schema.Array(Schema.Unknown),
|
|
261
|
+
featureIds: Schema.Struct({
|
|
262
|
+
staticRequests: Schema.String,
|
|
263
|
+
dynamicRequests: Schema.String,
|
|
264
|
+
storageBytes: Schema.String,
|
|
265
|
+
}),
|
|
266
|
+
});
|
|
267
|
+
export const BillingStatusResponseSchema = Schema.Struct({
|
|
268
|
+
orgId: Schema.String,
|
|
269
|
+
orgRole: Schema.NullOr(Schema.String),
|
|
270
|
+
canManageBilling: Schema.Boolean,
|
|
271
|
+
currentProductId: Schema.NullOr(Schema.String),
|
|
272
|
+
currentTier: Schema.NullOr(Schema.String),
|
|
273
|
+
currentInterval: Schema.NullOr(Schema.String),
|
|
274
|
+
currentOverageMode: Schema.NullOr(Schema.String),
|
|
275
|
+
hasScheduledPlanChange: Schema.Boolean,
|
|
276
|
+
scheduledPlanChange: Schema.NullOr(Schema.Unknown),
|
|
277
|
+
usage: Schema.Struct({
|
|
278
|
+
staticRequests: FeatureUsageSchema,
|
|
279
|
+
dynamicRequests: FeatureUsageSchema,
|
|
280
|
+
storageBytes: FeatureUsageSchema,
|
|
281
|
+
}),
|
|
282
|
+
storageMirrorBytes: Schema.Number.pipe(Schema.finite()),
|
|
283
|
+
variants: Schema.Array(Schema.Unknown),
|
|
284
|
+
});
|
|
285
|
+
export const AuditEventSchema = Schema.Struct({
|
|
286
|
+
id: Schema.String,
|
|
287
|
+
orgId: Schema.String,
|
|
288
|
+
orgSlug: Schema.String,
|
|
289
|
+
projectId: Schema.NullOr(Schema.String),
|
|
290
|
+
projectSlug: Schema.NullOr(Schema.String),
|
|
291
|
+
stageSlug: Schema.NullOr(Schema.String),
|
|
292
|
+
eventType: Schema.String,
|
|
293
|
+
category: Schema.String,
|
|
294
|
+
occurredAtMs: Schema.Number.pipe(Schema.finite()),
|
|
295
|
+
actorSource: Schema.String,
|
|
296
|
+
actorClerkUserId: Schema.NullOr(Schema.String),
|
|
297
|
+
actorDisplayName: Schema.NullOr(Schema.String),
|
|
298
|
+
actorEmail: Schema.NullOr(Schema.String),
|
|
299
|
+
subjectType: Schema.String,
|
|
300
|
+
subjectId: Schema.NullOr(Schema.String),
|
|
301
|
+
subjectName: Schema.NullOr(Schema.String),
|
|
302
|
+
title: Schema.String,
|
|
303
|
+
description: Schema.String,
|
|
304
|
+
severity: Schema.String,
|
|
305
|
+
payloadJson: Schema.String,
|
|
306
|
+
retentionTier: Schema.String,
|
|
307
|
+
expiresAtMs: Schema.NullOr(Schema.Number.pipe(Schema.finite())),
|
|
308
|
+
});
|
|
309
|
+
export const AuditListResponseSchema = Schema.Struct({
|
|
310
|
+
items: Schema.Array(AuditEventSchema),
|
|
311
|
+
nextBeforeOccurredAtMs: Schema.NullOr(Schema.Number.pipe(Schema.finite())),
|
|
312
|
+
hasMore: Schema.Boolean,
|
|
313
|
+
});
|
|
@@ -2,10 +2,22 @@ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
|
+
import { Either, Schema } from "effect";
|
|
6
|
+
import { CliConfigSchema, CliSessionSchema } from "./contracts/index.js";
|
|
5
7
|
const SERVICE_NAME = "barekey-cli";
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
8
|
+
function resolveHomeDir() {
|
|
9
|
+
const configuredHome = process.env.HOME?.trim();
|
|
10
|
+
return configuredHome && configuredHome.length > 0 ? configuredHome : homedir();
|
|
11
|
+
}
|
|
12
|
+
function getConfigDirPath() {
|
|
13
|
+
return path.join(resolveHomeDir(), ".config", "barekey");
|
|
14
|
+
}
|
|
15
|
+
function getConfigPath() {
|
|
16
|
+
return path.join(getConfigDirPath(), "config.json");
|
|
17
|
+
}
|
|
18
|
+
function getCredentialsDirPath() {
|
|
19
|
+
return path.join(getConfigDirPath(), "credentials");
|
|
20
|
+
}
|
|
9
21
|
function runCommand(command, args, input) {
|
|
10
22
|
return new Promise((resolve) => {
|
|
11
23
|
const child = spawn(command, args, {
|
|
@@ -32,14 +44,14 @@ function runCommand(command, args, input) {
|
|
|
32
44
|
});
|
|
33
45
|
}
|
|
34
46
|
async function ensureConfigDir() {
|
|
35
|
-
await mkdir(
|
|
47
|
+
await mkdir(getConfigDirPath(), {
|
|
36
48
|
recursive: true,
|
|
37
49
|
mode: 0o700,
|
|
38
50
|
});
|
|
39
51
|
}
|
|
40
52
|
async function ensureCredentialsDir() {
|
|
41
53
|
await ensureConfigDir();
|
|
42
|
-
await mkdir(
|
|
54
|
+
await mkdir(getCredentialsDirPath(), {
|
|
43
55
|
recursive: true,
|
|
44
56
|
mode: 0o700,
|
|
45
57
|
});
|
|
@@ -61,7 +73,7 @@ async function writeJsonFile(filePath, value) {
|
|
|
61
73
|
});
|
|
62
74
|
}
|
|
63
75
|
function credentialsPathForAccount(accountId) {
|
|
64
|
-
return path.join(
|
|
76
|
+
return path.join(getCredentialsDirPath(), `${encodeURIComponent(accountId)}.json`);
|
|
65
77
|
}
|
|
66
78
|
async function canUseLinuxSecretTool() {
|
|
67
79
|
if (process.platform !== "linux") {
|
|
@@ -153,13 +165,30 @@ async function deleteFromKeychain(account) {
|
|
|
153
165
|
return false;
|
|
154
166
|
}
|
|
155
167
|
export async function saveConfig(config) {
|
|
156
|
-
await writeJsonFile(
|
|
168
|
+
await writeJsonFile(getConfigPath(), config);
|
|
157
169
|
}
|
|
158
170
|
export async function loadConfig() {
|
|
159
|
-
|
|
171
|
+
const decoded = await readJsonFile(getConfigPath());
|
|
172
|
+
if (decoded === null) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
const result = Schema.decodeUnknownEither(CliConfigSchema)(decoded);
|
|
176
|
+
if (Either.isLeft(result)) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
if ("activeSessionId" in result.right) {
|
|
180
|
+
return {
|
|
181
|
+
baseUrl: result.right.baseUrl,
|
|
182
|
+
activeSessionId: result.right.activeSessionId,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
baseUrl: result.right.baseUrl,
|
|
187
|
+
activeSessionId: result.right.activeAccountId,
|
|
188
|
+
};
|
|
160
189
|
}
|
|
161
190
|
export async function clearConfig() {
|
|
162
|
-
await rm(
|
|
191
|
+
await rm(getConfigPath(), {
|
|
163
192
|
force: true,
|
|
164
193
|
});
|
|
165
194
|
}
|
|
@@ -182,14 +211,44 @@ export async function loadCredentials(accountId) {
|
|
|
182
211
|
const fromKeychain = await getFromKeychain(accountId);
|
|
183
212
|
if (fromKeychain !== null) {
|
|
184
213
|
try {
|
|
185
|
-
|
|
214
|
+
const decoded = Schema.decodeUnknownEither(CliSessionSchema)(JSON.parse(fromKeychain));
|
|
215
|
+
if (Either.isRight(decoded)) {
|
|
216
|
+
return {
|
|
217
|
+
accessToken: decoded.right.accessToken,
|
|
218
|
+
refreshToken: decoded.right.refreshToken,
|
|
219
|
+
accessTokenExpiresAtMs: decoded.right.accessTokenExpiresAtMs,
|
|
220
|
+
refreshTokenExpiresAtMs: decoded.right.refreshTokenExpiresAtMs,
|
|
221
|
+
clerkUserId: decoded.right.clerkUserId,
|
|
222
|
+
orgId: decoded.right.orgId ?? null,
|
|
223
|
+
orgSlug: decoded.right.orgSlug ?? null,
|
|
224
|
+
lastOrgId: ("lastOrgId" in decoded.right ? decoded.right.lastOrgId : undefined) ?? decoded.right.orgId ?? null,
|
|
225
|
+
lastOrgSlug: ("lastOrgSlug" in decoded.right ? decoded.right.lastOrgSlug : undefined) ?? decoded.right.orgSlug ?? null,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
186
228
|
}
|
|
187
229
|
catch {
|
|
188
230
|
// Fall back to file credentials when keychain data is malformed.
|
|
189
231
|
}
|
|
190
232
|
}
|
|
191
233
|
const fromFile = await readJsonFile(credentialsPathForAccount(accountId));
|
|
192
|
-
|
|
234
|
+
if (fromFile === null) {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
const decoded = Schema.decodeUnknownEither(CliSessionSchema)(fromFile);
|
|
238
|
+
if (Either.isLeft(decoded)) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
accessToken: decoded.right.accessToken,
|
|
243
|
+
refreshToken: decoded.right.refreshToken,
|
|
244
|
+
accessTokenExpiresAtMs: decoded.right.accessTokenExpiresAtMs,
|
|
245
|
+
refreshTokenExpiresAtMs: decoded.right.refreshTokenExpiresAtMs,
|
|
246
|
+
clerkUserId: decoded.right.clerkUserId,
|
|
247
|
+
orgId: decoded.right.orgId ?? null,
|
|
248
|
+
orgSlug: decoded.right.orgSlug ?? null,
|
|
249
|
+
lastOrgId: ("lastOrgId" in decoded.right ? decoded.right.lastOrgId : undefined) ?? decoded.right.orgId ?? null,
|
|
250
|
+
lastOrgSlug: ("lastOrgSlug" in decoded.right ? decoded.right.lastOrgSlug : undefined) ?? decoded.right.orgSlug ?? null,
|
|
251
|
+
};
|
|
193
252
|
}
|
|
194
253
|
export async function deleteCredentials(accountId) {
|
|
195
254
|
await deleteFromKeychain(accountId);
|
package/dist/http.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
1
2
|
export declare class CliHttpError extends Error {
|
|
2
3
|
readonly code: string;
|
|
3
4
|
readonly status: number;
|
|
@@ -14,9 +15,42 @@ export declare function postJson<TResponse>(input: {
|
|
|
14
15
|
path: string;
|
|
15
16
|
payload: unknown;
|
|
16
17
|
accessToken?: string | null;
|
|
18
|
+
schema?: Schema.Schema<TResponse>;
|
|
17
19
|
}): Promise<TResponse>;
|
|
18
20
|
export declare function getJson<TResponse>(input: {
|
|
19
21
|
baseUrl: string;
|
|
20
22
|
path: string;
|
|
21
23
|
accessToken?: string | null;
|
|
24
|
+
schema?: Schema.Schema<TResponse>;
|
|
22
25
|
}): Promise<TResponse>;
|
|
26
|
+
/**
|
|
27
|
+
* Executes one typed HTTP POST request as an Effect program.
|
|
28
|
+
*
|
|
29
|
+
* @param input The request configuration and response schema.
|
|
30
|
+
* @returns An Effect that succeeds with the decoded JSON response.
|
|
31
|
+
* @remarks CLI command programs use this so schema decode failures and transport failures share one typed path.
|
|
32
|
+
* @lastModified 2026-03-19
|
|
33
|
+
* @author GPT-5.4
|
|
34
|
+
*/
|
|
35
|
+
export declare function postJsonEffect<TResponse>(input: {
|
|
36
|
+
baseUrl: string;
|
|
37
|
+
path: string;
|
|
38
|
+
payload: unknown;
|
|
39
|
+
accessToken?: string | null;
|
|
40
|
+
schema: Schema.Schema<TResponse>;
|
|
41
|
+
}): Effect.Effect<TResponse, CliHttpError, never>;
|
|
42
|
+
/**
|
|
43
|
+
* Executes one typed HTTP GET request as an Effect program.
|
|
44
|
+
*
|
|
45
|
+
* @param input The request configuration and response schema.
|
|
46
|
+
* @returns An Effect that succeeds with the decoded JSON response.
|
|
47
|
+
* @remarks CLI command programs use this so schema decode failures and transport failures share one typed path.
|
|
48
|
+
* @lastModified 2026-03-19
|
|
49
|
+
* @author GPT-5.4
|
|
50
|
+
*/
|
|
51
|
+
export declare function getJsonEffect<TResponse>(input: {
|
|
52
|
+
baseUrl: string;
|
|
53
|
+
path: string;
|
|
54
|
+
accessToken?: string | null;
|
|
55
|
+
schema: Schema.Schema<TResponse>;
|
|
56
|
+
}): Effect.Effect<TResponse, CliHttpError, never>;
|
package/dist/http.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Effect, Either, Schema } from "effect";
|
|
1
2
|
export class CliHttpError extends Error {
|
|
2
3
|
code;
|
|
3
4
|
status;
|
|
@@ -18,6 +19,17 @@ async function parseJson(response) {
|
|
|
18
19
|
return null;
|
|
19
20
|
}
|
|
20
21
|
}
|
|
22
|
+
function decodeResponse(schema, payload) {
|
|
23
|
+
const decoded = Schema.decodeUnknownEither(schema)(payload);
|
|
24
|
+
if (Either.isLeft(decoded)) {
|
|
25
|
+
throw new CliHttpError({
|
|
26
|
+
code: "INVALID_RESPONSE",
|
|
27
|
+
status: 500,
|
|
28
|
+
message: "Barekey returned an unexpected response payload.",
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return decoded.right;
|
|
32
|
+
}
|
|
21
33
|
export async function postJson(input) {
|
|
22
34
|
const response = await fetch(`${input.baseUrl.replace(/\/$/, "")}${input.path}`, {
|
|
23
35
|
method: "POST",
|
|
@@ -41,7 +53,7 @@ export async function postJson(input) {
|
|
|
41
53
|
requestId: payload?.error?.requestId ?? null,
|
|
42
54
|
});
|
|
43
55
|
}
|
|
44
|
-
return parsed;
|
|
56
|
+
return input.schema ? decodeResponse(input.schema, parsed) : parsed;
|
|
45
57
|
}
|
|
46
58
|
export async function getJson(input) {
|
|
47
59
|
const response = await fetch(`${input.baseUrl.replace(/\/$/, "")}${input.path}`, {
|
|
@@ -62,5 +74,47 @@ export async function getJson(input) {
|
|
|
62
74
|
requestId: payload?.error?.requestId ?? null,
|
|
63
75
|
});
|
|
64
76
|
}
|
|
65
|
-
return parsed;
|
|
77
|
+
return input.schema ? decodeResponse(input.schema, parsed) : parsed;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Executes one typed HTTP POST request as an Effect program.
|
|
81
|
+
*
|
|
82
|
+
* @param input The request configuration and response schema.
|
|
83
|
+
* @returns An Effect that succeeds with the decoded JSON response.
|
|
84
|
+
* @remarks CLI command programs use this so schema decode failures and transport failures share one typed path.
|
|
85
|
+
* @lastModified 2026-03-19
|
|
86
|
+
* @author GPT-5.4
|
|
87
|
+
*/
|
|
88
|
+
export function postJsonEffect(input) {
|
|
89
|
+
return Effect.tryPromise({
|
|
90
|
+
try: () => postJson(input),
|
|
91
|
+
catch: (error) => error instanceof CliHttpError
|
|
92
|
+
? error
|
|
93
|
+
: new CliHttpError({
|
|
94
|
+
code: "HTTP_ERROR",
|
|
95
|
+
status: 500,
|
|
96
|
+
message: error instanceof Error ? error.message : "HTTP request failed.",
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Executes one typed HTTP GET request as an Effect program.
|
|
102
|
+
*
|
|
103
|
+
* @param input The request configuration and response schema.
|
|
104
|
+
* @returns An Effect that succeeds with the decoded JSON response.
|
|
105
|
+
* @remarks CLI command programs use this so schema decode failures and transport failures share one typed path.
|
|
106
|
+
* @lastModified 2026-03-19
|
|
107
|
+
* @author GPT-5.4
|
|
108
|
+
*/
|
|
109
|
+
export function getJsonEffect(input) {
|
|
110
|
+
return Effect.tryPromise({
|
|
111
|
+
try: () => getJson(input),
|
|
112
|
+
catch: (error) => error instanceof CliHttpError
|
|
113
|
+
? error
|
|
114
|
+
: new CliHttpError({
|
|
115
|
+
code: "HTTP_ERROR",
|
|
116
|
+
status: 500,
|
|
117
|
+
message: error instanceof Error ? error.message : "HTTP request failed.",
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
66
120
|
}
|
package/dist/index.js
CHANGED
|
@@ -2,12 +2,24 @@
|
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import pc from "picocolors";
|
|
4
4
|
import { registerAuthCommands } from "./commands/auth.js";
|
|
5
|
+
import { registerAuditCommands } from "./commands/audit.js";
|
|
6
|
+
import { registerBillingCommands } from "./commands/billing.js";
|
|
5
7
|
import { registerEnvCommands } from "./commands/env.js";
|
|
8
|
+
import { registerInitCommand } from "./commands/init.js";
|
|
9
|
+
import { registerOrgCommands } from "./commands/org.js";
|
|
10
|
+
import { registerProjectCommands } from "./commands/project.js";
|
|
11
|
+
import { registerStageCommands } from "./commands/stage.js";
|
|
6
12
|
import { registerTypegenCommand } from "./commands/typegen.js";
|
|
7
13
|
import { CLI_DESCRIPTION, CLI_NAME, CLI_VERSION } from "./constants.js";
|
|
8
14
|
const program = new Command();
|
|
9
15
|
program.name(CLI_NAME).description(CLI_DESCRIPTION).version(CLI_VERSION);
|
|
10
16
|
registerAuthCommands(program);
|
|
17
|
+
registerAuditCommands(program);
|
|
18
|
+
registerBillingCommands(program);
|
|
19
|
+
registerInitCommand(program);
|
|
20
|
+
registerOrgCommands(program);
|
|
21
|
+
registerProjectCommands(program);
|
|
22
|
+
registerStageCommands(program);
|
|
11
23
|
registerEnvCommands(program);
|
|
12
24
|
registerTypegenCommand(program);
|
|
13
25
|
program.parseAsync(process.argv).catch((error) => {
|
package/dist/runtime-config.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { access, readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { Either, Schema } from "effect";
|
|
4
|
+
import { RuntimeConfigSchema } from "./contracts/index.js";
|
|
3
5
|
async function fileExists(filePath) {
|
|
4
6
|
try {
|
|
5
7
|
await access(filePath);
|
|
@@ -30,36 +32,22 @@ export async function loadRuntimeConfig() {
|
|
|
30
32
|
}
|
|
31
33
|
const raw = await readFile(configPath, "utf8");
|
|
32
34
|
const parsed = JSON.parse(raw);
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
const decoded = Schema.decodeUnknownEither(RuntimeConfigSchema)(parsed);
|
|
36
|
+
if (Either.isLeft(decoded)) {
|
|
37
|
+
throw new Error(`Invalid barekey.json at ${configPath}.`);
|
|
38
|
+
}
|
|
39
|
+
const config = decoded.right.config;
|
|
40
|
+
const mode = config?.mode ?? "centralized";
|
|
41
|
+
const typegen = mode === "standalone" ? "minimal" : (config?.typegen ?? decoded.right.typegen ?? "semantic");
|
|
36
42
|
return {
|
|
37
43
|
path: configPath,
|
|
38
44
|
config: {
|
|
39
|
-
org:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
? parsed.org.trim()
|
|
43
|
-
: undefined,
|
|
44
|
-
project: typeof parsed.project === "string" ? parsed.project.trim() : undefined,
|
|
45
|
-
environment: typeof parsed.environment === "string"
|
|
46
|
-
? parsed.environment.trim()
|
|
47
|
-
: typeof parsed.stage === "string"
|
|
48
|
-
? parsed.stage.trim()
|
|
49
|
-
: undefined,
|
|
45
|
+
org: (decoded.right.organization ?? decoded.right.org ?? undefined)?.trim() || undefined,
|
|
46
|
+
project: decoded.right.project?.trim() || undefined,
|
|
47
|
+
environment: (decoded.right.environment ?? decoded.right.stage ?? undefined)?.trim() || undefined,
|
|
50
48
|
config: {
|
|
51
|
-
mode
|
|
52
|
-
|
|
53
|
-
: "centralized",
|
|
54
|
-
typegen: (config?.mode === "centralized" || config?.mode === "standalone"
|
|
55
|
-
? config.mode
|
|
56
|
-
: "centralized") === "standalone"
|
|
57
|
-
? "minimal"
|
|
58
|
-
: config?.typegen === "semantic" || config?.typegen === "minimal"
|
|
59
|
-
? config.typegen
|
|
60
|
-
: parsed.typegen === "semantic" || parsed.typegen === "minimal"
|
|
61
|
-
? parsed.typegen
|
|
62
|
-
: "semantic",
|
|
49
|
+
mode,
|
|
50
|
+
typegen,
|
|
63
51
|
},
|
|
64
52
|
},
|
|
65
53
|
};
|