-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathfeatureFlags.ts
More file actions
91 lines (76 loc) · 3.18 KB
/
featureFlags.ts
File metadata and controls
91 lines (76 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { z } from "zod";
export const FEATURE_FLAG = {
defaultWorkerInstanceGroupId: "defaultWorkerInstanceGroupId",
runsListRepository: "runsListRepository",
taskEventRepository: "taskEventRepository",
hasQueryAccess: "hasQueryAccess",
hasLogsPageAccess: "hasLogsPageAccess",
hasAiAccess: "hasAiAccess",
hasComputeAccess: "hasComputeAccess",
hasPrivateConnections: "hasPrivateConnections",
} as const;
export const FeatureFlagCatalog = {
[FEATURE_FLAG.defaultWorkerInstanceGroupId]: z.string(),
[FEATURE_FLAG.runsListRepository]: z.enum(["clickhouse", "postgres"]),
[FEATURE_FLAG.taskEventRepository]: z.enum(["clickhouse", "clickhouse_v2", "postgres"]),
[FEATURE_FLAG.hasQueryAccess]: z.coerce.boolean(),
[FEATURE_FLAG.hasLogsPageAccess]: z.coerce.boolean(),
[FEATURE_FLAG.hasAiAccess]: z.coerce.boolean(),
[FEATURE_FLAG.hasComputeAccess]: z.coerce.boolean(),
[FEATURE_FLAG.hasPrivateConnections]: z.coerce.boolean(),
};
export type FeatureFlagKey = keyof typeof FeatureFlagCatalog;
// Infrastructure flags that are read-only on the global flags page.
// Shown with current/resolved value but no controls.
export const GLOBAL_LOCKED_FLAGS: FeatureFlagKey[] = [
FEATURE_FLAG.defaultWorkerInstanceGroupId,
FEATURE_FLAG.runsListRepository,
FEATURE_FLAG.taskEventRepository,
];
// Flags that are read-only on the org-level dialog.
// Shown with global value but no controls (org can't override these).
export const ORG_LOCKED_FLAGS: FeatureFlagKey[] = [
FEATURE_FLAG.defaultWorkerInstanceGroupId,
FEATURE_FLAG.runsListRepository,
FEATURE_FLAG.taskEventRepository,
];
// Create a Zod schema from the existing catalog
export const FeatureFlagCatalogSchema = z.object(FeatureFlagCatalog);
export type FeatureFlagCatalog = z.infer<typeof FeatureFlagCatalogSchema>;
// Utility function to validate a feature flag value
export function validateFeatureFlagValue<T extends FeatureFlagKey>(
key: T,
value: unknown
): z.SafeParseReturnType<unknown, z.infer<(typeof FeatureFlagCatalog)[T]>> {
return FeatureFlagCatalog[key].safeParse(value);
}
// Utility function to validate all feature flags at once
export function validateAllFeatureFlags(values: Record<string, unknown>) {
return FeatureFlagCatalogSchema.safeParse(values);
}
// Utility function to validate partial feature flags (all keys optional)
export function validatePartialFeatureFlags(values: Record<string, unknown>) {
return FeatureFlagCatalogSchema.partial().safeParse(values);
}
// Utility types for catalog-driven UI rendering
export type FlagControlType =
| { type: "boolean" }
| { type: "enum"; options: string[] }
| { type: "string" };
export function getFlagControlType(schema: z.ZodTypeAny): FlagControlType {
const typeName = schema._def.typeName;
if (typeName === "ZodBoolean") {
return { type: "boolean" };
}
if (typeName === "ZodEnum") {
return { type: "enum", options: schema._def.values as string[] };
}
return { type: "string" };
}
export function getAllFlagControlTypes(): Record<string, FlagControlType> {
const result: Record<string, FlagControlType> = {};
for (const [key, schema] of Object.entries(FeatureFlagCatalog)) {
result[key] = getFlagControlType(schema);
}
return result;
}