@shipeasy/openapi 1.0.0 → 1.2.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.
Files changed (40) hide show
  1. package/dist/index.d.ts +9 -7
  2. package/dist/index.js +504 -2672
  3. package/dist/resources/alert-rules.d.ts +48 -0
  4. package/dist/resources/alert-rules.js +66 -0
  5. package/dist/resources/configs.d.ts +6 -2
  6. package/dist/resources/configs.js +67 -2375
  7. package/dist/resources/experiments.d.ts +100 -2
  8. package/dist/resources/experiments.js +158 -105
  9. package/dist/resources/gates.d.ts +51 -8
  10. package/dist/resources/gates.js +102 -70
  11. package/dist/resources/index.d.ts +166 -10
  12. package/dist/resources/index.js +503 -2671
  13. package/dist/resources/killswitches.d.ts +6 -2
  14. package/dist/resources/killswitches.js +113 -2412
  15. package/dist/resources/universes.d.ts +7 -4
  16. package/dist/resources/universes.js +30 -20
  17. package/dist/schemas/alert-rules.d.ts +43 -0
  18. package/dist/schemas/alert-rules.js +27 -0
  19. package/dist/schemas/configs.d.ts +154 -0
  20. package/dist/schemas/configs.js +134 -0
  21. package/dist/schemas/constants.d.ts +6 -0
  22. package/dist/schemas/constants.js +7 -0
  23. package/dist/schemas/experiments.d.ts +245 -0
  24. package/dist/schemas/experiments.js +216 -0
  25. package/dist/schemas/folder.d.ts +10 -0
  26. package/dist/schemas/folder.js +8 -0
  27. package/dist/schemas/gates.d.ts +304 -0
  28. package/dist/schemas/gates.js +172 -0
  29. package/dist/schemas/index.d.ts +11 -0
  30. package/dist/schemas/index.js +729 -0
  31. package/dist/schemas/killswitches.d.ts +110 -0
  32. package/dist/schemas/killswitches.js +226 -0
  33. package/dist/schemas/metric-name.d.ts +5 -0
  34. package/dist/schemas/metric-name.js +6 -0
  35. package/dist/schemas/pagination.d.ts +37 -0
  36. package/dist/schemas/pagination.js +44 -0
  37. package/dist/schemas/universes.d.ts +35 -0
  38. package/dist/schemas/universes.js +55 -0
  39. package/openapi.json +1257 -228
  40. package/package.json +13 -10
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@ function createHttpTransport(opts) {
39
39
  };
40
40
  }
41
41
 
42
- // ../core/src/pagination.ts
42
+ // src/schemas/pagination.ts
43
43
  import { z } from "zod";
44
44
  var DEFAULT_PAGE_SIZE = 100;
45
45
  var MAX_PAGE_SIZE = 500;
@@ -78,140 +78,172 @@ function base64UrlDecode(s) {
78
78
  }
79
79
 
80
80
  // src/resources/gates.ts
81
+ import { z as z4 } from "zod";
82
+
83
+ // src/schemas/gates.ts
81
84
  import { z as z3 } from "zod";
82
85
 
83
- // ../core/src/schemas/gates.ts
86
+ // src/schemas/folder.ts
84
87
  import { z as z2 } from "zod";
85
- var gateRuleSchema = z2.object({
86
- attr: z2.string().min(1).describe(
88
+ var folderSchema = z2.string().max(256).regex(/^[a-zA-Z0-9_-]+$/, "Folder must be alphanumeric, `_` or `-` (no `/`).").nullable().optional().describe(
89
+ "Optional folder name used to group items in the dashboard. Part of the SDK lookup key: an item in folder `checkout` named `new-cart` is referenced as `checkout/new-cart` from the SDK."
90
+ );
91
+
92
+ // src/schemas/gates.ts
93
+ var gateRuleSchema = z3.object({
94
+ attr: z3.string().min(1).describe(
87
95
  "Attribute key on the evaluation context (e.g. `country`, `plan`, `email`). Matched case-sensitively against `Shipeasy.checkGate(user, name)` input."
88
96
  ),
89
- op: z2.enum(["eq", "neq", "in", "not_in", "gt", "gte", "lt", "lte", "contains", "regex"]).describe(
90
- "Comparison operator. Equality: `eq`/`neq`. Set membership: `in`/`not_in` (value is an array). Numeric order: `gt`/`gte`/`lt`/`lte`. String: `contains` (substring), `regex` (JS-flavour pattern, value is the pattern string)."
97
+ op: z3.enum([
98
+ "eq",
99
+ "neq",
100
+ "in",
101
+ "not_in",
102
+ "gt",
103
+ "gte",
104
+ "lt",
105
+ "lte",
106
+ "contains",
107
+ "regex",
108
+ "semver_gt",
109
+ "semver_gte",
110
+ "semver_lt",
111
+ "semver_lte"
112
+ ]).describe(
113
+ "Comparison operator. Equality: `eq`/`neq`. Set membership: `in`/`not_in` (value is an array). Numeric order: `gt`/`gte`/`lt`/`lte`. Semver order: `semver_gt`/`semver_gte`/`semver_lt`/`semver_lte` (value is a dotted version like `4.2.0`). String: `contains` (substring), `regex` (JS-flavour pattern, value is the pattern string)."
91
114
  ),
92
- value: z2.unknown().describe(
93
- "Operand. Shape depends on `op`: scalar for `eq/neq/gt/gte/lt/lte/contains`; array of scalars for `in/not_in`; string pattern for `regex`."
115
+ value: z3.unknown().describe(
116
+ "Operand. Shape depends on `op`: scalar for `eq/neq/gt/gte/lt/lte/contains/semver_*`; array of scalars for `in/not_in`; string pattern for `regex`."
94
117
  )
95
118
  }).describe(
96
119
  "Single targeting predicate. A gate's `rules` array is evaluated with AND semantics; use the gatekeeper `stack` for OR / fall-through logic."
97
120
  );
98
- var gateNameSchema = z2.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/, "lowercase, digits, _/-; max 64 chars").describe(
99
- "Stable gate key used by SDKs (`Shipeasy.checkGate(user, '<name>')`). Lowercase letters, digits, `_` or `-`, must start with a letter/digit, max 64 chars. Immutable after create \u2014 rename = delete + recreate."
121
+ var gateNameSchema = z3.string().regex(
122
+ /^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?)?$/,
123
+ "lowercase, digits, _/-; optional folder.name shape"
124
+ ).max(128).describe(
125
+ "Stable gate key used by SDKs (`Shipeasy.checkGate(user, '<name>')`). Single segment or `folder.name`. Lowercase letters, digits, `_` or `-`; max 128 chars. Immutable after create \u2014 rename = delete + recreate."
100
126
  );
101
- var stackedConditionSchema = z2.object({
102
- id: z2.string().min(1).describe(
127
+ var stackedConditionSchema = z3.object({
128
+ id: z3.string().min(1).describe(
103
129
  "Client-supplied stable id for the stack entry (used for React keys, audit diffs)."
104
130
  ),
105
- type: z2.literal("condition").describe("Discriminator. `condition` = rule-based predicate sub-gate."),
106
- name: z2.string().optional().describe("Human label shown in the dashboard."),
107
- fromTemplate: z2.string().nullable().optional().describe(
131
+ type: z3.literal("condition").describe("Discriminator. `condition` = rule-based predicate sub-gate."),
132
+ name: z3.string().optional().describe("Human label shown in the dashboard."),
133
+ fromTemplate: z3.string().nullable().optional().describe(
108
134
  "Id of the project template this entry was seeded from, or `null` if hand-authored."
109
135
  ),
110
- pass: z2.enum(["all", "any"]).optional().describe("Combinator across `rules`. `all` = AND (default), `any` = OR."),
111
- rules: z2.array(gateRuleSchema).default([]).describe("Predicates evaluated under `pass`. Empty array = match nothing."),
112
- locked: z2.boolean().optional().describe("If `true`, dashboard hides edit controls (e.g. the trailing public-floor entry).")
136
+ pass: z3.enum(["all", "any"]).optional().describe("Combinator across `rules`. `all` = AND (default), `any` = OR."),
137
+ rules: z3.array(gateRuleSchema).default([]).describe("Predicates evaluated under `pass`. Empty array = match nothing."),
138
+ locked: z3.boolean().optional().describe("If `true`, dashboard hides edit controls (e.g. the trailing public-floor entry).")
113
139
  }).describe(
114
140
  "Rule-based sub-gate. When matched, evaluation short-circuits and the gate returns `true` for the current caller."
115
141
  );
116
- var stackedRolloutSchema = z2.object({
117
- id: z2.string().min(1).describe("Client-supplied stable id for the stack entry."),
118
- type: z2.literal("rollout").describe("Discriminator. `rollout` = percentage-bucket sub-gate."),
119
- name: z2.string().optional().describe("Human label shown in the dashboard."),
120
- fromTemplate: z2.string().nullable().optional().describe("Source template id, or `null`."),
121
- rolloutPct: z2.number().int().min(0).max(1e4).describe(
142
+ var stackedRolloutSchema = z3.object({
143
+ id: z3.string().min(1).describe("Client-supplied stable id for the stack entry."),
144
+ type: z3.literal("rollout").describe("Discriminator. `rollout` = percentage-bucket sub-gate."),
145
+ name: z3.string().optional().describe("Human label shown in the dashboard."),
146
+ fromTemplate: z3.string().nullable().optional().describe("Source template id, or `null`."),
147
+ rolloutPct: z3.number().int().min(0).max(1e4).describe(
122
148
  "Bucket size in basis points (0\u201310000 = 0%\u2013100%). `5000` = 50%, `100` = 1%, allows sub-1% precision."
123
149
  ),
124
- bucketBy: z2.string().optional().describe(
150
+ bucketBy: z3.string().optional().describe(
125
151
  "Attribute used to hash the caller into a bucket. Defaults to `user.userID`. Use e.g. `accountID` to bucket whole accounts together."
126
152
  ),
127
- salt: z2.string().optional().describe(
153
+ salt: z3.string().optional().describe(
128
154
  "Per-entry hash salt. Defaults to the gate's salt. Set explicitly to keep two rollouts independent or correlated across gates."
129
155
  ),
130
- locked: z2.boolean().optional().describe("If `true`, dashboard hides edit controls.")
156
+ locked: z3.boolean().optional().describe("If `true`, dashboard hides edit controls.")
131
157
  }).describe(
132
158
  "Percentage-rollout sub-gate. Hashes `bucketBy` (default `userID`) with `salt` and returns `true` for `rolloutPct/10000` fraction of callers."
133
159
  );
134
- var stackedGateEntrySchema = z2.discriminatedUnion("type", [stackedConditionSchema, stackedRolloutSchema]).describe(
160
+ var stackedGateEntrySchema = z3.discriminatedUnion("type", [stackedConditionSchema, stackedRolloutSchema]).describe(
135
161
  "One entry in the ordered gatekeeper stack. Evaluated top-to-bottom; first matching entry decides. Mix `condition` and `rollout` entries to express `internal-only` + `1% beta` + `50% public` in a single gate."
136
162
  );
137
163
  var gateMetadataFields = {
138
- title: z2.string().max(140).optional().describe("Human-readable title shown in the dashboard. Free-form, no key format constraint."),
139
- description: z2.string().max(2e3).optional().describe("Long-form description / runbook. Markdown is rendered in the dashboard."),
140
- folder: z2.string().max(64).optional().describe(
141
- "Folder label for dashboard organisation. Free-form; folders are inferred from the set of values."
142
- ),
143
- group: z2.string().max(64).optional().describe("Group label for dashboard organisation (e.g. team or product area)."),
144
- owner_email: z2.string().max(190).optional().describe("Owner contact. Displayed verbatim; not used for auth.")
145
- };
146
- var gateMetadataPatchSchema = z2.object(gateMetadataFields);
147
- var gateCreateSchema = z2.object({
164
+ title: z3.string().max(140).optional().describe("Human-readable title shown in the dashboard. Free-form, no key format constraint."),
165
+ description: z3.string().max(2e3).optional().describe("Long-form description / runbook. Markdown is rendered in the dashboard."),
166
+ folder: folderSchema,
167
+ group: z3.string().max(64).optional().describe("Group label for dashboard organisation (e.g. team or product area)."),
168
+ owner_email: z3.string().max(190).optional().describe("Owner contact. Displayed verbatim; not used for auth.")
169
+ };
170
+ var gateMetadataPatchSchema = z3.object(gateMetadataFields);
171
+ var gateCreateSchema = z3.object({
148
172
  name: gateNameSchema,
149
- enabled: z2.boolean().default(true).describe(
173
+ enabled: z3.boolean().default(true).describe(
150
174
  "Master switch. Defaults to `true`. Set `false` to create the gate disabled (evaluates to `false` regardless of rules/rollout); flip on via `POST /{id}/enable` or PATCH."
151
175
  ),
152
- rollout_pct: z2.number().int().min(0).max(1e4).default(0).describe(
153
- "Initial rollout in basis points (0\u201310000 = 0%\u2013100%). Use `0` to create the gate dark and ramp via PATCH after deploy validation."
176
+ rollout_pct: z3.number().int().min(0).max(1e4).default(0).describe(
177
+ "Initial rollout in **basis points** (0\u201310000 = 0%\u2013100%) \u2014 `100` here means **1%**, not 100%. Use `rollout_percent` (0\u2013100) below if you'd rather think in percent. Use `0` to create the gate dark and ramp via PATCH after deploy validation."
178
+ ),
179
+ rollout_percent: z3.number().min(0).max(100).optional().describe(
180
+ "Initial rollout as a **percentage** (0\u2013100, fractional ok). Friendlier alias for `rollout_pct`; converted internally to basis points (e.g. `100` here = 10000 bp = 100%). If both `rollout_pct` and `rollout_percent` are set, `rollout_percent` wins."
154
181
  ),
155
- rules: z2.array(gateRuleSchema).default([]).describe(
182
+ rules: z3.array(gateRuleSchema).default([]).describe(
156
183
  "Targeting predicates. AND-combined. If non-empty, the gate returns `true` only for callers that satisfy every rule **and** fall under `rollout_pct`."
157
184
  ),
158
- salt: z2.string().min(1).max(64).optional().describe(
185
+ salt: z3.string().min(1).max(64).optional().describe(
159
186
  "Hash salt for percentage bucketing. Auto-generated if omitted. Provide explicitly to keep a gate's buckets stable across delete/recreate. **Immutable after create** \u2014 there is no PATCH for `salt` because changing it would re-bucket every caller."
160
187
  ),
161
- stack: z2.array(stackedGateEntrySchema).nullable().optional().describe(
188
+ stack: z3.array(stackedGateEntrySchema).nullable().optional().describe(
162
189
  "Optional gatekeeper stack. When provided, takes precedence over `rules` + `rollout_pct` at evaluation time. Omit (or pass `null`) for a flat gate."
163
190
  ),
164
191
  ...gateMetadataFields
165
192
  }).describe(
166
193
  "Body for `POST /api/admin/gates`. At minimum supply `name`; everything else has sensible defaults."
167
194
  );
168
- var gateUpdateSchema = z2.object({
169
- rollout_pct: z2.number().int().min(0).max(1e4).optional().describe("New rollout in basis points (0\u201310000 = 0%\u2013100%). Omit to leave unchanged."),
170
- rules: z2.array(gateRuleSchema).optional().describe(
195
+ var gateUpdateSchema = z3.object({
196
+ rollout_pct: z3.number().int().min(0).max(1e4).optional().describe(
197
+ "New rollout in **basis points** (0\u201310000 = 0%\u2013100%) \u2014 `100` here means **1%**. Use `rollout_percent` (0\u2013100) below for percent. Omit both to leave unchanged."
198
+ ),
199
+ rollout_percent: z3.number().min(0).max(100).optional().describe(
200
+ "New rollout as a **percentage** (0\u2013100). Friendlier alias for `rollout_pct`; converted internally. Wins over `rollout_pct` if both are supplied. Omit both to leave unchanged."
201
+ ),
202
+ rules: z3.array(gateRuleSchema).optional().describe(
171
203
  "Replaces the rule list wholesale. To add a value to an `in` rule, send the full new `rules` array with the augmented `value` (e.g. previous `['US','CA']` \u2192 `['US','CA','GB']`)."
172
204
  ),
173
- enabled: z2.boolean().optional().describe(
205
+ enabled: z3.boolean().optional().describe(
174
206
  "Master switch. `false` makes the gate evaluate to `false` for every caller regardless of `rollout_pct`, `rules`, or `stack` \u2014 use as kill switch."
175
207
  ),
176
- stack: z2.array(stackedGateEntrySchema).nullable().optional().describe(
208
+ stack: z3.array(stackedGateEntrySchema).nullable().optional().describe(
177
209
  "Replaces the gatekeeper stack wholesale. Send `null` to revert to flat `rules` + `rollout_pct` evaluation."
178
210
  ),
179
211
  ...gateMetadataFields
180
212
  }).describe(
181
213
  "Body for `PATCH /api/admin/gates/{id}`. Partial \u2014 only supplied fields change. Array fields (`rules`, `stack`) replace, not merge."
182
214
  );
183
- var gateResponseSchema = z2.object({
184
- id: z2.string().describe("Stable opaque gate id (`gat_\u2026`)."),
215
+ var gateResponseSchema = z3.object({
216
+ id: z3.string().describe("Stable opaque gate id (`gat_\u2026`)."),
185
217
  name: gateNameSchema,
186
218
  /** D1 stores enabled as 0/1; clients see either form. */
187
- enabled: z2.union([z2.boolean(), z2.number().int().min(0).max(1)]).describe("Master switch. Returned as `1`/`0` from D1; treat truthy as enabled."),
219
+ enabled: z3.union([z3.boolean(), z3.number().int().min(0).max(1)]).describe("Master switch. Returned as `1`/`0` from D1; treat truthy as enabled."),
188
220
  /** Rollout percentage in basis points (0–10000 = 0%–100%). */
189
- rolloutPct: z2.number().int().min(0).max(1e4).describe("Current rollout in basis points (0\u201310000)."),
190
- rules: z2.array(gateRuleSchema).optional(),
191
- salt: z2.string().optional().describe("Hash salt used for percentage bucketing."),
192
- title: z2.string().nullable().optional(),
193
- description: z2.string().nullable().optional(),
194
- folder: z2.string().nullable().optional(),
195
- groupName: z2.string().nullable().optional().describe("Group label (note: `groupName` in response, `group` in request)."),
196
- ownerEmail: z2.string().nullable().optional().describe("Owner email (note: `ownerEmail` in response, `owner_email` in request)."),
197
- stack: z2.array(stackedGateEntrySchema).nullable().optional(),
198
- updatedAt: z2.string().describe("ISO-8601 timestamp of last mutation.")
221
+ rolloutPct: z3.number().int().min(0).max(1e4).describe("Current rollout in basis points (0\u201310000)."),
222
+ rules: z3.array(gateRuleSchema).optional(),
223
+ salt: z3.string().optional().describe("Hash salt used for percentage bucketing."),
224
+ title: z3.string().nullable().optional(),
225
+ description: z3.string().nullable().optional(),
226
+ folder: z3.string().nullable().optional(),
227
+ groupName: z3.string().nullable().optional().describe("Group label (note: `groupName` in response, `group` in request)."),
228
+ ownerEmail: z3.string().nullable().optional().describe("Owner email (note: `ownerEmail` in response, `owner_email` in request)."),
229
+ stack: z3.array(stackedGateEntrySchema).nullable().optional(),
230
+ updatedAt: z3.string().describe("ISO-8601 timestamp of last mutation.")
199
231
  });
200
- var gateCreateResponseSchema = z2.object({
201
- id: z2.string().describe("Newly assigned gate id (`gat_\u2026`)."),
232
+ var gateCreateResponseSchema = z3.object({
233
+ id: z3.string().describe("Newly assigned gate id (`gat_\u2026`)."),
202
234
  name: gateNameSchema
203
235
  });
204
- var gateUpdateResponseSchema = z2.object({ id: z2.string().describe("Gate id that was updated.") }).describe("Update returns only the id \u2014 re-fetch via `GET /api/admin/gates` for the full row.");
205
- var gateDeleteResponseSchema = z2.object({ ok: z2.literal(true) });
206
- var gateToggleResponseSchema = z2.object({
207
- id: z2.string(),
208
- enabled: z2.boolean()
236
+ var gateUpdateResponseSchema = z3.object({ id: z3.string().describe("Gate id that was updated.") }).describe("Update returns only the id \u2014 re-fetch via `GET /api/admin/gates` for the full row.");
237
+ var gateDeleteResponseSchema = z3.object({ ok: z3.literal(true) });
238
+ var gateToggleResponseSchema = z3.object({
239
+ id: z3.string(),
240
+ enabled: z3.boolean()
209
241
  });
210
242
 
211
243
  // src/resources/gates.ts
212
- var gateListResponseSchema = z3.object({
213
- data: z3.array(gateResponseSchema),
214
- next_cursor: z3.string().nullable()
244
+ var gateListResponseSchema = z4.object({
245
+ data: z4.array(gateResponseSchema),
246
+ next_cursor: z4.string().nullable()
215
247
  });
216
248
  var BASE = "/api/admin/gates";
217
249
  function gatesClient(t) {
@@ -538,50 +570,72 @@ var gatesResource = {
538
570
  };
539
571
 
540
572
  // src/resources/experiments.ts
573
+ import { z as z7 } from "zod";
574
+
575
+ // src/schemas/experiments.ts
576
+ import { z as z6 } from "zod";
577
+
578
+ // src/schemas/metric-name.ts
541
579
  import { z as z5 } from "zod";
580
+ var metricNameSchema = z5.string().regex(/^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?)?$/).max(128);
542
581
 
543
- // ../core/src/schemas/experiments.ts
544
- import { z as z4 } from "zod";
545
- var experimentNameSchema = z4.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/).describe(
546
- "Stable experiment key (a-z, 0-9, `_`/`-`, must start with letter/digit, max 64 chars). Used by SDKs as `Shipeasy.getExperiment(user, '<name>')`. Immutable after create."
582
+ // src/schemas/experiments.ts
583
+ var experimentInlineMetricSchema = z6.object({
584
+ name: metricNameSchema.optional(),
585
+ query: z6.string().min(1).max(4096).describe("Metric DSL string, e.g. `count_users(checkout_completed)`.")
586
+ });
587
+ var experimentNameSchema = z6.string().regex(/^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?)?$/).max(128).describe(
588
+ "Stable experiment key. Single segment or `folder.name` (a-z, 0-9, `_`/`-`; max 128 chars). Used by SDKs as `Shipeasy.getExperiment(user, '<name>')`. Immutable after create."
547
589
  );
548
- var experimentGroupSchema = z4.object({
549
- name: z4.string().min(1).max(64).describe("Group label (e.g. `control`, `treatment_a`). Max 64 chars."),
550
- weight: z4.number().int().min(0).max(1e4).describe(
590
+ var experimentGroupSchema = z6.object({
591
+ name: z6.string().min(1).max(64).describe("Group label (e.g. `control`, `treatment_a`). Max 64 chars."),
592
+ weight: z6.number().int().min(0).max(1e4).describe(
551
593
  "Allocation weight in basis points (0\u201310000). The sum across all groups must equal exactly **10000** (100%)."
552
594
  ),
553
- params: z4.record(z4.string(), z4.unknown()).default({}).describe(
595
+ params: z6.record(z6.string(), z6.unknown()).default({}).describe(
554
596
  "Per-group parameter values delivered to the SDK when a caller is hashed into this group. Keys must match the experiment's `params` schema."
555
597
  )
556
598
  }).describe("One variant in the experiment. Weights across all groups must sum to 10000.");
557
- var paramSchemaSchema = z4.record(z4.string(), z4.enum(["string", "bool", "number"])).describe(
599
+ var paramSchemaSchema = z6.record(z6.string(), z6.enum(["string", "bool", "number"])).describe(
558
600
  "Map of param-name \u2192 scalar type. Defines the shape of `groups[].params`. Example: `{ headline: 'string', show_cta: 'bool' }`."
559
601
  );
560
- var experimentCreateSchema = z4.object({
602
+ var bucketBySchema = z6.enum(["user_id", "session_id", "device_id"]).describe("Identifier used as the bucketing key. `user_id` is sticky across sessions.");
603
+ var experimentCreateSchema = z6.object({
561
604
  name: experimentNameSchema,
562
- description: z4.string().max(2e3).nullable().default(null).describe("Free-form description. Max 2000 chars, markdown rendered in the dashboard."),
563
- tag: z4.string().max(64).nullable().default(null).describe("Optional tag used to group experiments in the dashboard."),
564
- universe: z4.string().min(1).describe(
605
+ description: z6.string().max(2e3).nullable().default(null).describe("Free-form description. Max 2000 chars, markdown rendered in the dashboard."),
606
+ hypothesis: z6.string().max(4e3).nullable().default(null).describe("Hypothesis statement shown in the editor. Display-only."),
607
+ tag: z6.string().max(64).nullable().default(null).describe("Short tag chip rendered next to the name. Display-only."),
608
+ owner_email: z6.string().max(254).nullable().default(null).describe("Owner email. Display-only."),
609
+ audience: z6.string().max(256).nullable().default(null).describe("Audience label shown in the editor. Display-only."),
610
+ bucket_by: bucketBySchema.nullable().default(null),
611
+ folder: folderSchema,
612
+ universe: z6.string().min(1).describe(
565
613
  "Name of an existing universe in the project. Returns `422` if the universe doesn't exist."
566
614
  ),
567
- targeting_gate: z4.string().nullable().default(null).describe(
615
+ targeting_gate: z6.string().nullable().default(null).describe(
568
616
  "Optional gate name. Only callers that pass the gate are enrolled in the experiment."
569
617
  ),
570
- allocation_pct: z4.number().int().min(0).max(1e4).default(0).describe(
618
+ allocation_pct: z6.number().int().min(0).max(1e4).default(0).describe(
571
619
  "Share of the (gated) audience allocated to the experiment, in basis points (0\u201310000 = 0%\u2013100%). `0` = unallocated. Immutable while the experiment is running."
572
620
  ),
573
- salt: z4.string().min(1).max(64).optional().describe("Hash salt for bucketing. Auto-generated if omitted. Immutable while running."),
621
+ salt: z6.string().min(1).max(64).optional().describe("Hash salt for bucketing. Auto-generated if omitted. Immutable while running."),
574
622
  params: paramSchemaSchema.default({}),
575
- groups: z4.array(experimentGroupSchema).min(2).describe(
623
+ groups: z6.array(experimentGroupSchema).min(2).describe(
576
624
  "Two or more variants. Weights must sum to exactly 10000 (100%). Immutable while running."
577
625
  ),
578
- significance_threshold: z4.number().min(1e-4).max(0.5).default(0.05).describe(
626
+ significance_threshold: z6.number().min(1e-4).max(0.5).default(0.05).describe(
579
627
  "p-value cutoff used by the analysis pass. Defaults to `0.05`. Values other than 0.05 require Pro plan or higher."
580
628
  ),
581
- min_runtime_days: z4.number().int().min(0).max(365).default(0).describe("Minimum days the experiment must run before results are considered conclusive."),
582
- min_sample_size: z4.number().int().min(1).default(100).describe("Minimum exposures per group before results are considered conclusive."),
583
- sequential_testing: z4.boolean().default(false).describe(
629
+ min_runtime_days: z6.number().int().min(0).max(365).default(0).describe("Minimum days the experiment must run before results are considered conclusive."),
630
+ min_sample_size: z6.number().int().min(1).default(100).describe("Minimum exposures per group before results are considered conclusive."),
631
+ sequential_testing: z6.boolean().default(false).describe(
584
632
  "Enable sequential testing (always-valid p-values). Requires Premium plan or higher."
633
+ ),
634
+ goal_metric: experimentInlineMetricSchema.optional().describe(
635
+ "Single goal metric defined inline as a DSL query. The underlying event is auto-created if missing."
636
+ ),
637
+ guardrail_metrics: z6.array(experimentInlineMetricSchema).max(10).default([]).describe(
638
+ "Up to 10 guardrail metrics defined inline. Each is upserted (event + metric) and attached with role=guardrail."
585
639
  )
586
640
  }).refine(
587
641
  (e) => e.groups.reduce((s, g) => s + g.weight, 0) === 1e4,
@@ -589,35 +643,42 @@ var experimentCreateSchema = z4.object({
589
643
  ).describe(
590
644
  "Body for `POST /api/admin/experiments`. `name`, `universe`, and `groups` (\u22652, weights sum to 10000) required."
591
645
  );
592
- var experimentUpdateSchema = z4.object({
646
+ var experimentUpdateSchema = z6.object({
593
647
  name: experimentNameSchema.optional(),
594
- description: z4.string().max(2e3).nullable().optional(),
595
- tag: z4.string().max(64).nullable().optional(),
596
- targeting_gate: z4.string().nullable().optional(),
597
- allocation_pct: z4.number().int().min(0).max(1e4).optional().describe("Basis-points allocation (0\u201310000). Immutable while the experiment is running."),
598
- salt: z4.string().min(1).max(64).optional().describe("Hash salt. Immutable while running."),
599
- universe: z4.string().optional().describe(
648
+ description: z6.string().max(2e3).nullable().optional(),
649
+ hypothesis: z6.string().max(4e3).nullable().optional(),
650
+ tag: z6.string().max(64).nullable().optional(),
651
+ owner_email: z6.string().max(254).nullable().optional(),
652
+ audience: z6.string().max(256).nullable().optional(),
653
+ bucket_by: bucketBySchema.nullable().optional(),
654
+ folder: folderSchema,
655
+ targeting_gate: z6.string().nullable().optional(),
656
+ allocation_pct: z6.number().int().min(0).max(1e4).optional().describe("Basis-points allocation (0\u201310000). Immutable while the experiment is running."),
657
+ salt: z6.string().min(1).max(64).optional().describe("Hash salt. Immutable while running."),
658
+ universe: z6.string().optional().describe(
600
659
  "New universe name. Immutable while running. Returns `422` if the universe doesn't exist."
601
660
  ),
602
661
  params: paramSchemaSchema.optional(),
603
- groups: z4.array(experimentGroupSchema).min(2).optional().describe("Replacement groups. Weights must sum to 10000. Immutable while running."),
604
- significance_threshold: z4.number().min(1e-4).max(0.5).optional(),
605
- min_runtime_days: z4.number().int().min(0).max(365).optional(),
606
- min_sample_size: z4.number().int().min(1).optional(),
607
- sequential_testing: z4.boolean().optional()
662
+ groups: z6.array(experimentGroupSchema).min(2).optional().describe("Replacement groups. Weights must sum to 10000. Immutable while running."),
663
+ significance_threshold: z6.number().min(1e-4).max(0.5).optional(),
664
+ min_runtime_days: z6.number().int().min(0).max(365).optional(),
665
+ min_sample_size: z6.number().int().min(1).optional(),
666
+ sequential_testing: z6.boolean().optional(),
667
+ goal_metric: experimentInlineMetricSchema.optional().describe("Replaces the goal metric (event auto-upserted)."),
668
+ guardrail_metrics: z6.array(experimentInlineMetricSchema).max(10).optional().describe("Replaces the guardrail set wholesale (event auto-upserted per entry).")
608
669
  }).describe(
609
670
  "Body for `PATCH /api/admin/experiments/{id}`. Partial \u2014 only supplied fields change. `allocation_pct`, `groups`, `salt`, `universe`, `params` are immutable while the experiment is running (stop first)."
610
671
  );
611
- var experimentStatusUpdateSchema = z4.object({
612
- status: z4.enum(["draft", "running", "stopped", "archived"]).describe(
613
- "Target status. Allowed transitions: `draft \u2192 running`, `running \u2192 stopped`, `stopped \u2192 archived`, `draft \u2192 archived`. Restarting an archived experiment is not allowed."
672
+ var experimentStatusUpdateSchema = z6.object({
673
+ status: z6.enum(["draft", "running", "stopped", "archived"]).describe(
674
+ "Target status. Allowed transitions: `draft \u2192 running`, `running \u2192 stopped`, `stopped \u2192 archived`, `draft \u2192 archived`, and `archived \u2192 draft` (restore \u2014 only if the experiment never started). Restarting an archived experiment directly is not allowed; restore it to draft first, then start."
614
675
  )
615
676
  }).describe("Body for `POST /api/admin/experiments/{id}/status`.");
616
- var experimentMetricsUpdateSchema = z4.object({
617
- metrics: z4.array(
618
- z4.object({
619
- metric_id: z4.string().describe("Existing metric id in the project."),
620
- role: z4.enum(["goal", "guardrail", "secondary"]).describe(
677
+ var experimentMetricsUpdateSchema = z6.object({
678
+ metrics: z6.array(
679
+ z6.object({
680
+ metric_id: z6.string().describe("Existing metric id in the project."),
681
+ role: z6.enum(["goal", "guardrail", "secondary"]).describe(
621
682
  "Metric role. `goal` drives the decision, `guardrail` blocks ship if degraded, `secondary` is informational."
622
683
  )
623
684
  })
@@ -625,82 +686,87 @@ var experimentMetricsUpdateSchema = z4.object({
625
686
  }).describe(
626
687
  "Body for `POST /api/admin/experiments/{id}/metrics`. Replaces the experiment's metric attachments wholesale. Returns `422` if any `metric_id` is unknown."
627
688
  );
628
- var experimentResponseSchema = z4.object({
629
- id: z4.string().describe("Stable opaque experiment id (`exp_\u2026`)."),
689
+ var experimentResponseSchema = z6.object({
690
+ id: z6.string().describe("Stable opaque experiment id (`exp_\u2026`)."),
630
691
  name: experimentNameSchema,
631
- description: z4.string().nullable(),
632
- tag: z4.string().nullable(),
633
- status: z4.enum(["draft", "running", "stopped", "archived"]),
634
- universe: z4.string().describe("Universe name this experiment draws from."),
635
- targetingGate: z4.string().nullable(),
636
- allocationPct: z4.number().int().describe("Allocation in basis points (0\u201310000)."),
637
- salt: z4.string(),
638
- params: z4.record(z4.string(), z4.enum(["string", "bool", "number"])),
639
- groups: z4.array(experimentGroupSchema),
640
- significanceThreshold: z4.number(),
641
- minRuntimeDays: z4.number().int(),
642
- minSampleSize: z4.number().int(),
643
- sequentialTesting: z4.boolean(),
644
- startedAt: z4.string().nullable().describe("ISO-8601 timestamp the experiment last transitioned to `running`, or `null`."),
645
- stoppedAt: z4.string().nullable().optional(),
646
- updatedAt: z4.string()
692
+ description: z6.string().nullable(),
693
+ hypothesis: z6.string().nullable(),
694
+ tag: z6.string().nullable(),
695
+ ownerEmail: z6.string().nullable(),
696
+ audience: z6.string().nullable(),
697
+ bucketBy: bucketBySchema.nullable(),
698
+ folder: z6.string().nullable(),
699
+ status: z6.enum(["draft", "running", "stopped", "archived"]),
700
+ universe: z6.string().describe("Universe name this experiment draws from."),
701
+ targetingGate: z6.string().nullable(),
702
+ allocationPct: z6.number().int().describe("Allocation in basis points (0\u201310000)."),
703
+ salt: z6.string(),
704
+ params: z6.record(z6.string(), z6.enum(["string", "bool", "number"])),
705
+ groups: z6.array(experimentGroupSchema),
706
+ significanceThreshold: z6.number(),
707
+ minRuntimeDays: z6.number().int(),
708
+ minSampleSize: z6.number().int(),
709
+ sequentialTesting: z6.boolean(),
710
+ startedAt: z6.string().nullable().describe("ISO-8601 timestamp the experiment last transitioned to `running`, or `null`."),
711
+ stoppedAt: z6.string().nullable().optional(),
712
+ updatedAt: z6.string()
647
713
  });
648
- var experimentCreateResponseSchema = z4.object({
649
- id: z4.string().describe("Newly assigned experiment id."),
714
+ var experimentCreateResponseSchema = z6.object({
715
+ id: z6.string().describe("Newly assigned experiment id."),
650
716
  name: experimentNameSchema
651
717
  });
652
- var experimentUpdateResponseSchema = z4.object({
653
- id: z4.string().describe("Experiment id that was updated.")
718
+ var experimentUpdateResponseSchema = z6.object({
719
+ id: z6.string().describe("Experiment id that was updated.")
654
720
  });
655
- var experimentDeleteResponseSchema = z4.object({ ok: z4.literal(true) });
656
- var experimentStatusResponseSchema = z4.object({
657
- id: z4.string(),
658
- status: z4.enum(["draft", "running", "stopped", "archived"])
721
+ var experimentDeleteResponseSchema = z6.object({ ok: z6.literal(true) });
722
+ var experimentStatusResponseSchema = z6.object({
723
+ id: z6.string(),
724
+ status: z6.enum(["draft", "running", "stopped", "archived"])
659
725
  });
660
- var experimentMetricsResponseSchema = z4.object({
661
- id: z4.string(),
662
- metrics: z4.array(
663
- z4.object({
664
- metric_id: z4.string(),
665
- role: z4.enum(["goal", "guardrail", "secondary"])
726
+ var experimentMetricsResponseSchema = z6.object({
727
+ id: z6.string(),
728
+ metrics: z6.array(
729
+ z6.object({
730
+ metric_id: z6.string(),
731
+ role: z6.enum(["goal", "guardrail", "secondary"])
666
732
  })
667
733
  )
668
734
  });
669
- var experimentResultRowSchema = z4.object({
670
- metric: z4.string(),
671
- group_name: z4.string(),
672
- ds: z4.string().describe("Date slice (`YYYY-MM-DD`)."),
673
- n: z4.number().nullable(),
674
- mean: z4.number().nullable(),
675
- delta_pct: z4.number().nullable(),
676
- p_value: z4.number().nullable(),
677
- srm_detected: z4.number().nullable().describe("`1` if sample-ratio mismatch detected, else `0`.")
735
+ var experimentResultRowSchema = z6.object({
736
+ metric: z6.string(),
737
+ group_name: z6.string(),
738
+ ds: z6.string().describe("Date slice (`YYYY-MM-DD`)."),
739
+ n: z6.number().nullable(),
740
+ mean: z6.number().nullable(),
741
+ delta_pct: z6.number().nullable(),
742
+ p_value: z6.number().nullable(),
743
+ srm_detected: z6.number().nullable().describe("`1` if sample-ratio mismatch detected, else `0`.")
678
744
  });
679
- var experimentResultsResponseSchema = z4.object({
680
- experiment: z4.object({
681
- id: z4.string(),
745
+ var experimentResultsResponseSchema = z6.object({
746
+ experiment: z6.object({
747
+ id: z6.string(),
682
748
  name: experimentNameSchema,
683
- status: z4.enum(["draft", "running", "stopped", "archived"])
749
+ status: z6.enum(["draft", "running", "stopped", "archived"])
684
750
  }),
685
- results: z4.array(experimentResultRowSchema)
751
+ results: z6.array(experimentResultRowSchema)
686
752
  });
687
- var experimentTimeseriesResponseSchema = z4.object({
688
- experiment: z4.object({
689
- id: z4.string(),
753
+ var experimentTimeseriesResponseSchema = z6.object({
754
+ experiment: z6.object({
755
+ id: z6.string(),
690
756
  name: experimentNameSchema,
691
- status: z4.enum(["draft", "running", "stopped", "archived"])
757
+ status: z6.enum(["draft", "running", "stopped", "archived"])
692
758
  }),
693
- series: z4.array(experimentResultRowSchema)
759
+ series: z6.array(experimentResultRowSchema)
694
760
  });
695
- var experimentReanalyzeResponseSchema = z4.object({
696
- id: z4.string(),
697
- queued: z4.literal(true)
761
+ var experimentReanalyzeResponseSchema = z6.object({
762
+ id: z6.string(),
763
+ queued: z6.literal(true)
698
764
  });
699
765
 
700
766
  // src/resources/experiments.ts
701
- var experimentListResponseSchema = z5.object({
702
- data: z5.array(experimentResponseSchema),
703
- next_cursor: z5.string().nullable()
767
+ var experimentListResponseSchema = z7.object({
768
+ data: z7.array(experimentResponseSchema),
769
+ next_cursor: z7.string().nullable()
704
770
  });
705
771
  var BASE2 = "/api/admin/experiments";
706
772
  function experimentsClient(t) {
@@ -710,24 +776,29 @@ function experimentsClient(t) {
710
776
  if (opts.cursor) query.cursor = opts.cursor;
711
777
  return t.request("GET", BASE2, void 0, query);
712
778
  }
713
- async function listAll() {
779
+ async function listAllWith(status) {
714
780
  const out = [];
715
781
  let cursor;
716
782
  do {
717
- const page = await list({ limit: 500, cursor });
783
+ const query = { limit: "500" };
784
+ if (cursor) query.cursor = cursor;
785
+ if (status) query.status = status;
786
+ const page = await t.request("GET", BASE2, void 0, query);
718
787
  out.push(...page.data);
719
788
  cursor = page.next_cursor ?? void 0;
720
789
  } while (cursor);
721
790
  return out;
722
791
  }
792
+ async function listAll() {
793
+ return listAllWith();
794
+ }
723
795
  async function resolve(idOrName) {
724
796
  try {
725
797
  return await t.request("GET", `${BASE2}/${idOrName}`);
726
798
  } catch (err) {
727
799
  if (!(err instanceof ApiError) || err.status !== 404) throw err;
728
800
  }
729
- const all = await listAll();
730
- const found = all.find((e) => e.name === idOrName);
801
+ const found = (await listAllWith()).find((e) => e.name === idOrName) ?? (await listAllWith("archived")).find((e) => e.name === idOrName);
731
802
  if (!found) throw new ApiError(`Experiment '${idOrName}' not found`, 404);
732
803
  return found;
733
804
  }
@@ -750,6 +821,7 @@ function experimentsClient(t) {
750
821
  start: (id) => setStatus(id, "running"),
751
822
  stop: (id) => setStatus(id, "stopped"),
752
823
  archive: (id) => setStatus(id, "archived"),
824
+ restore: (id) => setStatus(id, "draft"),
753
825
  setMetrics: (id, input) => t.request("POST", `${BASE2}/${id}/metrics`, experimentMetricsUpdateSchema.parse(input)),
754
826
  results: (id) => t.request("GET", `${BASE2}/${id}/results`),
755
827
  timeseries: (id, metric) => t.request(
@@ -796,7 +868,7 @@ var experimentsResource = {
796
868
  "",
797
869
  "**Identity.** Stable `name` (a-z, 0-9, `_`/`-`, max 64 chars). Immutable after create.",
798
870
  "",
799
- "**Lifecycle.** `draft \u2192 running \u2192 stopped \u2192 archived`. Transition via `POST /{id}/status`. Restarting an archived experiment is not allowed.",
871
+ "**Lifecycle.** `draft \u2192 running \u2192 stopped \u2192 archived`. Transition via `POST /{id}/status`. An archived experiment that never started can be restored with `archived \u2192 draft`; restarting an archived experiment directly is not allowed.",
800
872
  "",
801
873
  "**Allocation.** `allocation_pct` (basis points, 0\u201310000) is the share of the targeted audience enrolled; `groups[].weight` (must sum to 10000) splits the enrolled audience. `targeting_gate` narrows the eligible audience before allocation.",
802
874
  "",
@@ -815,6 +887,7 @@ var experimentsResource = {
815
887
  { name: "start", description: "Transition draft experiment to running" },
816
888
  { name: "stop", description: "Stop a running experiment" },
817
889
  { name: "archive", description: "Archive a stopped experiment" },
890
+ { name: "restore", description: "Restore an archived (never-started) experiment to draft" },
818
891
  { name: "reanalyze", description: "Re-run analysis pass for the experiment" }
819
892
  ],
820
893
  endpoints: [
@@ -995,8 +1068,9 @@ var experimentsResource = {
995
1068
  "- `running \u2192 stopped` \u2014 halts allocation. Existing exposures stay in the dataset.",
996
1069
  "- `stopped \u2192 archived` \u2014 soft-delete.",
997
1070
  "- `draft \u2192 archived` \u2014 discard an unstarted experiment.",
1071
+ "- `archived \u2192 draft` \u2014 restore a soft-deleted experiment so it can be re-completed and started. Allowed only if it never started; one that already ran must be cloned instead.",
998
1072
  "",
999
- "Restarting an `archived` experiment is not allowed; clone instead. Returns `409` on illegal transitions and `429` if the plan's `experiments_running` limit is exceeded on `\u2192 running`."
1073
+ "Restarting an `archived` experiment directly is not allowed \u2014 restore it to `draft` first. Returns `409` on illegal transitions and `429` if the plan's `experiments_running` limit is exceeded on `\u2192 running`."
1000
1074
  ].join("\n"),
1001
1075
  pathParams: { id: "Stable opaque experiment id." },
1002
1076
  request: experimentStatusUpdateSchema,
@@ -1017,6 +1091,11 @@ var experimentsResource = {
1017
1091
  summary: "Archive \u2014 stopped \u2192 archived",
1018
1092
  description: "Soft-deletes the experiment. List endpoints exclude archived rows by default.",
1019
1093
  value: { status: "archived" }
1094
+ },
1095
+ restore: {
1096
+ summary: "Restore \u2014 archived \u2192 draft",
1097
+ description: "Un-deletes a soft-deleted experiment so it can be re-completed and started. Allowed only if it never ran.",
1098
+ value: { status: "draft" }
1020
1099
  }
1021
1100
  },
1022
1101
  response: { id: "exp_01j7wb12c3d4e5f6g7h8j9k0l1", status: "running" }
@@ -1116,2393 +1195,77 @@ var experimentsResource = {
1116
1195
  operationId: "getExperimentTimeseries",
1117
1196
  method: "GET",
1118
1197
  path: "/{id}/timeseries",
1119
- summary: "Get analysis timeseries",
1120
- description: "Same row shape as `/results`, but returns every daily slice rather than the latest. Filter to a single metric with the `metric` query parameter.",
1121
- pathParams: { id: "Stable opaque experiment id." },
1122
- queryParams: {
1123
- metric: {
1124
- schema: z5.string().optional(),
1125
- description: "Optional metric name to filter the series."
1126
- }
1127
- },
1128
- response: experimentTimeseriesResponseSchema,
1129
- examples: {
1130
- response: {
1131
- experiment: {
1132
- id: "exp_01j7wb12c3d4e5f6g7h8j9k0l1",
1133
- name: "checkout_button_color",
1134
- status: "running"
1135
- },
1136
- series: [
1137
- {
1138
- metric: "checkout_completed",
1139
- group_name: "treatment",
1140
- ds: "2026-05-08",
1141
- n: 11200,
1142
- mean: 0.1903,
1143
- delta_pct: 3.9,
1144
- p_value: 0.034,
1145
- srm_detected: 0
1146
- },
1147
- {
1148
- metric: "checkout_completed",
1149
- group_name: "treatment",
1150
- ds: "2026-05-09",
1151
- n: 12519,
1152
- mean: 0.1922,
1153
- delta_pct: 4.8,
1154
- p_value: 0.018,
1155
- srm_detected: 0
1156
- }
1157
- ]
1158
- }
1159
- },
1160
- useCase: "Drive a chart of metric movement over the experiment runtime, or sanity-check the lift is monotonic before deciding."
1161
- },
1162
- {
1163
- operationId: "reanalyzeExperiment",
1164
- method: "POST",
1165
- path: "/{id}/reanalyze",
1166
- summary: "Re-queue analysis",
1167
- description: "Requeues the daily analysis pass for this experiment outside the normal cron cadence. Useful after attaching a new metric or correcting an event taxonomy. The job runs asynchronously.",
1168
- pathParams: { id: "Stable opaque experiment id." },
1169
- response: experimentReanalyzeResponseSchema,
1170
- examples: { response: { id: "exp_01j7wb12c3d4e5f6g7h8j9k0l1", queued: true } },
1171
- useCase: "Force-refresh results after wiring up a new metric without waiting for the next nightly cron tick."
1172
- }
1173
- ]
1174
- };
1175
-
1176
- // src/resources/configs.ts
1177
- import { z as z7 } from "zod";
1178
-
1179
- // ../core/src/schemas/configs.ts
1180
- import { z as z6 } from "zod";
1181
-
1182
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/entity.js
1183
- var entityKind = /* @__PURE__ */ Symbol.for("drizzle:entityKind");
1184
- function is(value, type) {
1185
- if (!value || typeof value !== "object") {
1186
- return false;
1187
- }
1188
- if (value instanceof type) {
1189
- return true;
1190
- }
1191
- if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
1192
- throw new Error(
1193
- `Class "${type.name ?? "<unknown>"}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`
1194
- );
1195
- }
1196
- let cls = Object.getPrototypeOf(value).constructor;
1197
- if (cls) {
1198
- while (cls) {
1199
- if (entityKind in cls && cls[entityKind] === type[entityKind]) {
1200
- return true;
1201
- }
1202
- cls = Object.getPrototypeOf(cls);
1203
- }
1204
- }
1205
- return false;
1206
- }
1207
-
1208
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/column.js
1209
- var Column = class {
1210
- constructor(table, config) {
1211
- this.table = table;
1212
- this.config = config;
1213
- this.name = config.name;
1214
- this.keyAsName = config.keyAsName;
1215
- this.notNull = config.notNull;
1216
- this.default = config.default;
1217
- this.defaultFn = config.defaultFn;
1218
- this.onUpdateFn = config.onUpdateFn;
1219
- this.hasDefault = config.hasDefault;
1220
- this.primary = config.primaryKey;
1221
- this.isUnique = config.isUnique;
1222
- this.uniqueName = config.uniqueName;
1223
- this.uniqueType = config.uniqueType;
1224
- this.dataType = config.dataType;
1225
- this.columnType = config.columnType;
1226
- this.generated = config.generated;
1227
- this.generatedIdentity = config.generatedIdentity;
1228
- }
1229
- static [entityKind] = "Column";
1230
- name;
1231
- keyAsName;
1232
- primary;
1233
- notNull;
1234
- default;
1235
- defaultFn;
1236
- onUpdateFn;
1237
- hasDefault;
1238
- isUnique;
1239
- uniqueName;
1240
- uniqueType;
1241
- dataType;
1242
- columnType;
1243
- enumValues = void 0;
1244
- generated = void 0;
1245
- generatedIdentity = void 0;
1246
- config;
1247
- mapFromDriverValue(value) {
1248
- return value;
1249
- }
1250
- mapToDriverValue(value) {
1251
- return value;
1252
- }
1253
- // ** @internal */
1254
- shouldDisableInsert() {
1255
- return this.config.generated !== void 0 && this.config.generated.type !== "byDefault";
1256
- }
1257
- };
1258
-
1259
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/column-builder.js
1260
- var ColumnBuilder = class {
1261
- static [entityKind] = "ColumnBuilder";
1262
- config;
1263
- constructor(name, dataType, columnType) {
1264
- this.config = {
1265
- name,
1266
- keyAsName: name === "",
1267
- notNull: false,
1268
- default: void 0,
1269
- hasDefault: false,
1270
- primaryKey: false,
1271
- isUnique: false,
1272
- uniqueName: void 0,
1273
- uniqueType: void 0,
1274
- dataType,
1275
- columnType,
1276
- generated: void 0
1277
- };
1278
- }
1279
- /**
1280
- * Changes the data type of the column. Commonly used with `json` columns. Also, useful for branded types.
1281
- *
1282
- * @example
1283
- * ```ts
1284
- * const users = pgTable('users', {
1285
- * id: integer('id').$type<UserId>().primaryKey(),
1286
- * details: json('details').$type<UserDetails>().notNull(),
1287
- * });
1288
- * ```
1289
- */
1290
- $type() {
1291
- return this;
1292
- }
1293
- /**
1294
- * Adds a `not null` clause to the column definition.
1295
- *
1296
- * Affects the `select` model of the table - columns *without* `not null` will be nullable on select.
1297
- */
1298
- notNull() {
1299
- this.config.notNull = true;
1300
- return this;
1301
- }
1302
- /**
1303
- * Adds a `default <value>` clause to the column definition.
1304
- *
1305
- * Affects the `insert` model of the table - columns *with* `default` are optional on insert.
1306
- *
1307
- * If you need to set a dynamic default value, use {@link $defaultFn} instead.
1308
- */
1309
- default(value) {
1310
- this.config.default = value;
1311
- this.config.hasDefault = true;
1312
- return this;
1313
- }
1314
- /**
1315
- * Adds a dynamic default value to the column.
1316
- * The function will be called when the row is inserted, and the returned value will be used as the column value.
1317
- *
1318
- * **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
1319
- */
1320
- $defaultFn(fn) {
1321
- this.config.defaultFn = fn;
1322
- this.config.hasDefault = true;
1323
- return this;
1324
- }
1325
- /**
1326
- * Alias for {@link $defaultFn}.
1327
- */
1328
- $default = this.$defaultFn;
1329
- /**
1330
- * Adds a dynamic update value to the column.
1331
- * The function will be called when the row is updated, and the returned value will be used as the column value if none is provided.
1332
- * If no `default` (or `$defaultFn`) value is provided, the function will be called when the row is inserted as well, and the returned value will be used as the column value.
1333
- *
1334
- * **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
1335
- */
1336
- $onUpdateFn(fn) {
1337
- this.config.onUpdateFn = fn;
1338
- this.config.hasDefault = true;
1339
- return this;
1340
- }
1341
- /**
1342
- * Alias for {@link $onUpdateFn}.
1343
- */
1344
- $onUpdate = this.$onUpdateFn;
1345
- /**
1346
- * Adds a `primary key` clause to the column definition. This implicitly makes the column `not null`.
1347
- *
1348
- * In SQLite, `integer primary key` implicitly makes the column auto-incrementing.
1349
- */
1350
- primaryKey() {
1351
- this.config.primaryKey = true;
1352
- this.config.notNull = true;
1353
- return this;
1354
- }
1355
- /** @internal Sets the name of the column to the key within the table definition if a name was not given. */
1356
- setName(name) {
1357
- if (this.config.name !== "")
1358
- return;
1359
- this.config.name = name;
1360
- }
1361
- };
1362
-
1363
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/table.utils.js
1364
- var TableName = /* @__PURE__ */ Symbol.for("drizzle:Name");
1365
-
1366
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/pg-core/foreign-keys.js
1367
- var ForeignKeyBuilder = class {
1368
- static [entityKind] = "PgForeignKeyBuilder";
1369
- /** @internal */
1370
- reference;
1371
- /** @internal */
1372
- _onUpdate = "no action";
1373
- /** @internal */
1374
- _onDelete = "no action";
1375
- constructor(config, actions) {
1376
- this.reference = () => {
1377
- const { name, columns, foreignColumns } = config();
1378
- return { name, columns, foreignTable: foreignColumns[0].table, foreignColumns };
1379
- };
1380
- if (actions) {
1381
- this._onUpdate = actions.onUpdate;
1382
- this._onDelete = actions.onDelete;
1383
- }
1384
- }
1385
- onUpdate(action) {
1386
- this._onUpdate = action === void 0 ? "no action" : action;
1387
- return this;
1388
- }
1389
- onDelete(action) {
1390
- this._onDelete = action === void 0 ? "no action" : action;
1391
- return this;
1392
- }
1393
- /** @internal */
1394
- build(table) {
1395
- return new ForeignKey(table, this);
1396
- }
1397
- };
1398
- var ForeignKey = class {
1399
- constructor(table, builder) {
1400
- this.table = table;
1401
- this.reference = builder.reference;
1402
- this.onUpdate = builder._onUpdate;
1403
- this.onDelete = builder._onDelete;
1404
- }
1405
- static [entityKind] = "PgForeignKey";
1406
- reference;
1407
- onUpdate;
1408
- onDelete;
1409
- getName() {
1410
- const { name, columns, foreignColumns } = this.reference();
1411
- const columnNames = columns.map((column) => column.name);
1412
- const foreignColumnNames = foreignColumns.map((column) => column.name);
1413
- const chunks = [
1414
- this.table[TableName],
1415
- ...columnNames,
1416
- foreignColumns[0].table[TableName],
1417
- ...foreignColumnNames
1418
- ];
1419
- return name ?? `${chunks.join("_")}_fk`;
1420
- }
1421
- };
1422
-
1423
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/tracing-utils.js
1424
- function iife(fn, ...args) {
1425
- return fn(...args);
1426
- }
1427
-
1428
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/pg-core/unique-constraint.js
1429
- function uniqueKeyName(table, columns) {
1430
- return `${table[TableName]}_${columns.join("_")}_unique`;
1431
- }
1432
- var UniqueConstraintBuilder = class {
1433
- constructor(columns, name) {
1434
- this.name = name;
1435
- this.columns = columns;
1436
- }
1437
- static [entityKind] = "PgUniqueConstraintBuilder";
1438
- /** @internal */
1439
- columns;
1440
- /** @internal */
1441
- nullsNotDistinctConfig = false;
1442
- nullsNotDistinct() {
1443
- this.nullsNotDistinctConfig = true;
1444
- return this;
1445
- }
1446
- /** @internal */
1447
- build(table) {
1448
- return new UniqueConstraint(table, this.columns, this.nullsNotDistinctConfig, this.name);
1449
- }
1450
- };
1451
- var UniqueOnConstraintBuilder = class {
1452
- static [entityKind] = "PgUniqueOnConstraintBuilder";
1453
- /** @internal */
1454
- name;
1455
- constructor(name) {
1456
- this.name = name;
1457
- }
1458
- on(...columns) {
1459
- return new UniqueConstraintBuilder(columns, this.name);
1460
- }
1461
- };
1462
- var UniqueConstraint = class {
1463
- constructor(table, columns, nullsNotDistinct, name) {
1464
- this.table = table;
1465
- this.columns = columns;
1466
- this.name = name ?? uniqueKeyName(this.table, this.columns.map((column) => column.name));
1467
- this.nullsNotDistinct = nullsNotDistinct;
1468
- }
1469
- static [entityKind] = "PgUniqueConstraint";
1470
- columns;
1471
- name;
1472
- nullsNotDistinct = false;
1473
- getName() {
1474
- return this.name;
1475
- }
1476
- };
1477
-
1478
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/pg-core/utils/array.js
1479
- function parsePgArrayValue(arrayString, startFrom, inQuotes) {
1480
- for (let i = startFrom; i < arrayString.length; i++) {
1481
- const char = arrayString[i];
1482
- if (char === "\\") {
1483
- i++;
1484
- continue;
1485
- }
1486
- if (char === '"') {
1487
- return [arrayString.slice(startFrom, i).replace(/\\/g, ""), i + 1];
1488
- }
1489
- if (inQuotes) {
1490
- continue;
1491
- }
1492
- if (char === "," || char === "}") {
1493
- return [arrayString.slice(startFrom, i).replace(/\\/g, ""), i];
1494
- }
1495
- }
1496
- return [arrayString.slice(startFrom).replace(/\\/g, ""), arrayString.length];
1497
- }
1498
- function parsePgNestedArray(arrayString, startFrom = 0) {
1499
- const result = [];
1500
- let i = startFrom;
1501
- let lastCharIsComma = false;
1502
- while (i < arrayString.length) {
1503
- const char = arrayString[i];
1504
- if (char === ",") {
1505
- if (lastCharIsComma || i === startFrom) {
1506
- result.push("");
1507
- }
1508
- lastCharIsComma = true;
1509
- i++;
1510
- continue;
1511
- }
1512
- lastCharIsComma = false;
1513
- if (char === "\\") {
1514
- i += 2;
1515
- continue;
1516
- }
1517
- if (char === '"') {
1518
- const [value2, startFrom2] = parsePgArrayValue(arrayString, i + 1, true);
1519
- result.push(value2);
1520
- i = startFrom2;
1521
- continue;
1522
- }
1523
- if (char === "}") {
1524
- return [result, i + 1];
1525
- }
1526
- if (char === "{") {
1527
- const [value2, startFrom2] = parsePgNestedArray(arrayString, i + 1);
1528
- result.push(value2);
1529
- i = startFrom2;
1530
- continue;
1531
- }
1532
- const [value, newStartFrom] = parsePgArrayValue(arrayString, i, false);
1533
- result.push(value);
1534
- i = newStartFrom;
1535
- }
1536
- return [result, i];
1537
- }
1538
- function parsePgArray(arrayString) {
1539
- const [result] = parsePgNestedArray(arrayString, 1);
1540
- return result;
1541
- }
1542
- function makePgArray(array) {
1543
- return `{${array.map((item) => {
1544
- if (Array.isArray(item)) {
1545
- return makePgArray(item);
1546
- }
1547
- if (typeof item === "string") {
1548
- return `"${item.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
1549
- }
1550
- return `${item}`;
1551
- }).join(",")}}`;
1552
- }
1553
-
1554
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/pg-core/columns/common.js
1555
- var PgColumnBuilder = class extends ColumnBuilder {
1556
- foreignKeyConfigs = [];
1557
- static [entityKind] = "PgColumnBuilder";
1558
- array(size) {
1559
- return new PgArrayBuilder(this.config.name, this, size);
1560
- }
1561
- references(ref, actions = {}) {
1562
- this.foreignKeyConfigs.push({ ref, actions });
1563
- return this;
1564
- }
1565
- unique(name, config) {
1566
- this.config.isUnique = true;
1567
- this.config.uniqueName = name;
1568
- this.config.uniqueType = config?.nulls;
1569
- return this;
1570
- }
1571
- generatedAlwaysAs(as) {
1572
- this.config.generated = {
1573
- as,
1574
- type: "always",
1575
- mode: "stored"
1576
- };
1577
- return this;
1578
- }
1579
- /** @internal */
1580
- buildForeignKeys(column, table) {
1581
- return this.foreignKeyConfigs.map(({ ref, actions }) => {
1582
- return iife(
1583
- (ref2, actions2) => {
1584
- const builder = new ForeignKeyBuilder(() => {
1585
- const foreignColumn = ref2();
1586
- return { columns: [column], foreignColumns: [foreignColumn] };
1587
- });
1588
- if (actions2.onUpdate) {
1589
- builder.onUpdate(actions2.onUpdate);
1590
- }
1591
- if (actions2.onDelete) {
1592
- builder.onDelete(actions2.onDelete);
1593
- }
1594
- return builder.build(table);
1595
- },
1596
- ref,
1597
- actions
1598
- );
1599
- });
1600
- }
1601
- /** @internal */
1602
- buildExtraConfigColumn(table) {
1603
- return new ExtraConfigColumn(table, this.config);
1604
- }
1605
- };
1606
- var PgColumn = class extends Column {
1607
- constructor(table, config) {
1608
- if (!config.uniqueName) {
1609
- config.uniqueName = uniqueKeyName(table, [config.name]);
1610
- }
1611
- super(table, config);
1612
- this.table = table;
1613
- }
1614
- static [entityKind] = "PgColumn";
1615
- };
1616
- var ExtraConfigColumn = class extends PgColumn {
1617
- static [entityKind] = "ExtraConfigColumn";
1618
- getSQLType() {
1619
- return this.getSQLType();
1620
- }
1621
- indexConfig = {
1622
- order: this.config.order ?? "asc",
1623
- nulls: this.config.nulls ?? "last",
1624
- opClass: this.config.opClass
1625
- };
1626
- defaultConfig = {
1627
- order: "asc",
1628
- nulls: "last",
1629
- opClass: void 0
1630
- };
1631
- asc() {
1632
- this.indexConfig.order = "asc";
1633
- return this;
1634
- }
1635
- desc() {
1636
- this.indexConfig.order = "desc";
1637
- return this;
1638
- }
1639
- nullsFirst() {
1640
- this.indexConfig.nulls = "first";
1641
- return this;
1642
- }
1643
- nullsLast() {
1644
- this.indexConfig.nulls = "last";
1645
- return this;
1646
- }
1647
- /**
1648
- * ### PostgreSQL documentation quote
1649
- *
1650
- * > An operator class with optional parameters can be specified for each column of an index.
1651
- * The operator class identifies the operators to be used by the index for that column.
1652
- * For example, a B-tree index on four-byte integers would use the int4_ops class;
1653
- * this operator class includes comparison functions for four-byte integers.
1654
- * In practice the default operator class for the column's data type is usually sufficient.
1655
- * The main point of having operator classes is that for some data types, there could be more than one meaningful ordering.
1656
- * For example, we might want to sort a complex-number data type either by absolute value or by real part.
1657
- * We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index.
1658
- * More information about operator classes check:
1659
- *
1660
- * ### Useful links
1661
- * https://www.postgresql.org/docs/current/sql-createindex.html
1662
- *
1663
- * https://www.postgresql.org/docs/current/indexes-opclass.html
1664
- *
1665
- * https://www.postgresql.org/docs/current/xindex.html
1666
- *
1667
- * ### Additional types
1668
- * If you have the `pg_vector` extension installed in your database, you can use the
1669
- * `vector_l2_ops`, `vector_ip_ops`, `vector_cosine_ops`, `vector_l1_ops`, `bit_hamming_ops`, `bit_jaccard_ops`, `halfvec_l2_ops`, `sparsevec_l2_ops` options, which are predefined types.
1670
- *
1671
- * **You can always specify any string you want in the operator class, in case Drizzle doesn't have it natively in its types**
1672
- *
1673
- * @param opClass
1674
- * @returns
1675
- */
1676
- op(opClass) {
1677
- this.indexConfig.opClass = opClass;
1678
- return this;
1679
- }
1680
- };
1681
- var IndexedColumn = class {
1682
- static [entityKind] = "IndexedColumn";
1683
- constructor(name, keyAsName, type, indexConfig) {
1684
- this.name = name;
1685
- this.keyAsName = keyAsName;
1686
- this.type = type;
1687
- this.indexConfig = indexConfig;
1688
- }
1689
- name;
1690
- keyAsName;
1691
- type;
1692
- indexConfig;
1693
- };
1694
- var PgArrayBuilder = class extends PgColumnBuilder {
1695
- static [entityKind] = "PgArrayBuilder";
1696
- constructor(name, baseBuilder, size) {
1697
- super(name, "array", "PgArray");
1698
- this.config.baseBuilder = baseBuilder;
1699
- this.config.size = size;
1700
- }
1701
- /** @internal */
1702
- build(table) {
1703
- const baseColumn = this.config.baseBuilder.build(table);
1704
- return new PgArray(
1705
- table,
1706
- this.config,
1707
- baseColumn
1708
- );
1709
- }
1710
- };
1711
- var PgArray = class _PgArray extends PgColumn {
1712
- constructor(table, config, baseColumn, range) {
1713
- super(table, config);
1714
- this.baseColumn = baseColumn;
1715
- this.range = range;
1716
- this.size = config.size;
1717
- }
1718
- size;
1719
- static [entityKind] = "PgArray";
1720
- getSQLType() {
1721
- return `${this.baseColumn.getSQLType()}[${typeof this.size === "number" ? this.size : ""}]`;
1722
- }
1723
- mapFromDriverValue(value) {
1724
- if (typeof value === "string") {
1725
- value = parsePgArray(value);
1726
- }
1727
- return value.map((v) => this.baseColumn.mapFromDriverValue(v));
1728
- }
1729
- mapToDriverValue(value, isNestedArray = false) {
1730
- const a = value.map(
1731
- (v) => v === null ? null : is(this.baseColumn, _PgArray) ? this.baseColumn.mapToDriverValue(v, true) : this.baseColumn.mapToDriverValue(v)
1732
- );
1733
- if (isNestedArray)
1734
- return a;
1735
- return makePgArray(a);
1736
- }
1737
- };
1738
-
1739
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/pg-core/columns/enum.js
1740
- var isPgEnumSym = /* @__PURE__ */ Symbol.for("drizzle:isPgEnum");
1741
- function isPgEnum(obj) {
1742
- return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
1743
- }
1744
- var PgEnumColumnBuilder = class extends PgColumnBuilder {
1745
- static [entityKind] = "PgEnumColumnBuilder";
1746
- constructor(name, enumInstance) {
1747
- super(name, "string", "PgEnumColumn");
1748
- this.config.enum = enumInstance;
1749
- }
1750
- /** @internal */
1751
- build(table) {
1752
- return new PgEnumColumn(
1753
- table,
1754
- this.config
1755
- );
1756
- }
1757
- };
1758
- var PgEnumColumn = class extends PgColumn {
1759
- static [entityKind] = "PgEnumColumn";
1760
- enum = this.config.enum;
1761
- enumValues = this.config.enum.enumValues;
1762
- constructor(table, config) {
1763
- super(table, config);
1764
- this.enum = config.enum;
1765
- }
1766
- getSQLType() {
1767
- return this.enum.enumName;
1768
- }
1769
- };
1770
-
1771
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/subquery.js
1772
- var Subquery = class {
1773
- static [entityKind] = "Subquery";
1774
- constructor(sql2, selection, alias, isWith = false) {
1775
- this._ = {
1776
- brand: "Subquery",
1777
- sql: sql2,
1778
- selectedFields: selection,
1779
- alias,
1780
- isWith
1781
- };
1782
- }
1783
- // getSQL(): SQL<unknown> {
1784
- // return new SQL([this]);
1785
- // }
1786
- };
1787
- var WithSubquery = class extends Subquery {
1788
- static [entityKind] = "WithSubquery";
1789
- };
1790
-
1791
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/version.js
1792
- var version = "0.36.4";
1793
-
1794
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/tracing.js
1795
- var otel;
1796
- var rawTracer;
1797
- var tracer = {
1798
- startActiveSpan(name, fn) {
1799
- if (!otel) {
1800
- return fn();
1801
- }
1802
- if (!rawTracer) {
1803
- rawTracer = otel.trace.getTracer("drizzle-orm", version);
1804
- }
1805
- return iife(
1806
- (otel2, rawTracer2) => rawTracer2.startActiveSpan(
1807
- name,
1808
- (span) => {
1809
- try {
1810
- return fn(span);
1811
- } catch (e) {
1812
- span.setStatus({
1813
- code: otel2.SpanStatusCode.ERROR,
1814
- message: e instanceof Error ? e.message : "Unknown error"
1815
- // eslint-disable-line no-instanceof/no-instanceof
1816
- });
1817
- throw e;
1818
- } finally {
1819
- span.end();
1820
- }
1821
- }
1822
- ),
1823
- otel,
1824
- rawTracer
1825
- );
1826
- }
1827
- };
1828
-
1829
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/view-common.js
1830
- var ViewBaseConfig = /* @__PURE__ */ Symbol.for("drizzle:ViewBaseConfig");
1831
-
1832
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/table.js
1833
- var Schema = /* @__PURE__ */ Symbol.for("drizzle:Schema");
1834
- var Columns = /* @__PURE__ */ Symbol.for("drizzle:Columns");
1835
- var ExtraConfigColumns = /* @__PURE__ */ Symbol.for("drizzle:ExtraConfigColumns");
1836
- var OriginalName = /* @__PURE__ */ Symbol.for("drizzle:OriginalName");
1837
- var BaseName = /* @__PURE__ */ Symbol.for("drizzle:BaseName");
1838
- var IsAlias = /* @__PURE__ */ Symbol.for("drizzle:IsAlias");
1839
- var ExtraConfigBuilder = /* @__PURE__ */ Symbol.for("drizzle:ExtraConfigBuilder");
1840
- var IsDrizzleTable = /* @__PURE__ */ Symbol.for("drizzle:IsDrizzleTable");
1841
- var Table = class {
1842
- static [entityKind] = "Table";
1843
- /** @internal */
1844
- static Symbol = {
1845
- Name: TableName,
1846
- Schema,
1847
- OriginalName,
1848
- Columns,
1849
- ExtraConfigColumns,
1850
- BaseName,
1851
- IsAlias,
1852
- ExtraConfigBuilder
1853
- };
1854
- /**
1855
- * @internal
1856
- * Can be changed if the table is aliased.
1857
- */
1858
- [TableName];
1859
- /**
1860
- * @internal
1861
- * Used to store the original name of the table, before any aliasing.
1862
- */
1863
- [OriginalName];
1864
- /** @internal */
1865
- [Schema];
1866
- /** @internal */
1867
- [Columns];
1868
- /** @internal */
1869
- [ExtraConfigColumns];
1870
- /**
1871
- * @internal
1872
- * Used to store the table name before the transformation via the `tableCreator` functions.
1873
- */
1874
- [BaseName];
1875
- /** @internal */
1876
- [IsAlias] = false;
1877
- /** @internal */
1878
- [IsDrizzleTable] = true;
1879
- /** @internal */
1880
- [ExtraConfigBuilder] = void 0;
1881
- constructor(name, schema, baseName) {
1882
- this[TableName] = this[OriginalName] = name;
1883
- this[Schema] = schema;
1884
- this[BaseName] = baseName;
1885
- }
1886
- };
1887
-
1888
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sql/sql.js
1889
- var FakePrimitiveParam = class {
1890
- static [entityKind] = "FakePrimitiveParam";
1891
- };
1892
- function isSQLWrapper(value) {
1893
- return value !== null && value !== void 0 && typeof value.getSQL === "function";
1894
- }
1895
- function mergeQueries(queries) {
1896
- const result = { sql: "", params: [] };
1897
- for (const query of queries) {
1898
- result.sql += query.sql;
1899
- result.params.push(...query.params);
1900
- if (query.typings?.length) {
1901
- if (!result.typings) {
1902
- result.typings = [];
1903
- }
1904
- result.typings.push(...query.typings);
1905
- }
1906
- }
1907
- return result;
1908
- }
1909
- var StringChunk = class {
1910
- static [entityKind] = "StringChunk";
1911
- value;
1912
- constructor(value) {
1913
- this.value = Array.isArray(value) ? value : [value];
1914
- }
1915
- getSQL() {
1916
- return new SQL([this]);
1917
- }
1918
- };
1919
- var SQL = class _SQL {
1920
- constructor(queryChunks) {
1921
- this.queryChunks = queryChunks;
1922
- }
1923
- static [entityKind] = "SQL";
1924
- /** @internal */
1925
- decoder = noopDecoder;
1926
- shouldInlineParams = false;
1927
- append(query) {
1928
- this.queryChunks.push(...query.queryChunks);
1929
- return this;
1930
- }
1931
- toQuery(config) {
1932
- return tracer.startActiveSpan("drizzle.buildSQL", (span) => {
1933
- const query = this.buildQueryFromSourceParams(this.queryChunks, config);
1934
- span?.setAttributes({
1935
- "drizzle.query.text": query.sql,
1936
- "drizzle.query.params": JSON.stringify(query.params)
1937
- });
1938
- return query;
1939
- });
1940
- }
1941
- buildQueryFromSourceParams(chunks, _config) {
1942
- const config = Object.assign({}, _config, {
1943
- inlineParams: _config.inlineParams || this.shouldInlineParams,
1944
- paramStartIndex: _config.paramStartIndex || { value: 0 }
1945
- });
1946
- const {
1947
- casing,
1948
- escapeName,
1949
- escapeParam,
1950
- prepareTyping,
1951
- inlineParams,
1952
- paramStartIndex
1953
- } = config;
1954
- return mergeQueries(chunks.map((chunk) => {
1955
- if (is(chunk, StringChunk)) {
1956
- return { sql: chunk.value.join(""), params: [] };
1957
- }
1958
- if (is(chunk, Name)) {
1959
- return { sql: escapeName(chunk.value), params: [] };
1960
- }
1961
- if (chunk === void 0) {
1962
- return { sql: "", params: [] };
1963
- }
1964
- if (Array.isArray(chunk)) {
1965
- const result = [new StringChunk("(")];
1966
- for (const [i, p] of chunk.entries()) {
1967
- result.push(p);
1968
- if (i < chunk.length - 1) {
1969
- result.push(new StringChunk(", "));
1970
- }
1971
- }
1972
- result.push(new StringChunk(")"));
1973
- return this.buildQueryFromSourceParams(result, config);
1974
- }
1975
- if (is(chunk, _SQL)) {
1976
- return this.buildQueryFromSourceParams(chunk.queryChunks, {
1977
- ...config,
1978
- inlineParams: inlineParams || chunk.shouldInlineParams
1979
- });
1980
- }
1981
- if (is(chunk, Table)) {
1982
- const schemaName = chunk[Table.Symbol.Schema];
1983
- const tableName = chunk[Table.Symbol.Name];
1984
- return {
1985
- sql: schemaName === void 0 ? escapeName(tableName) : escapeName(schemaName) + "." + escapeName(tableName),
1986
- params: []
1987
- };
1988
- }
1989
- if (is(chunk, Column)) {
1990
- const columnName = casing.getColumnCasing(chunk);
1991
- if (_config.invokeSource === "indexes") {
1992
- return { sql: escapeName(columnName), params: [] };
1993
- }
1994
- const schemaName = chunk.table[Table.Symbol.Schema];
1995
- return {
1996
- sql: chunk.table[IsAlias] || schemaName === void 0 ? escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName) : escapeName(schemaName) + "." + escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName),
1997
- params: []
1998
- };
1999
- }
2000
- if (is(chunk, View)) {
2001
- const schemaName = chunk[ViewBaseConfig].schema;
2002
- const viewName = chunk[ViewBaseConfig].name;
2003
- return {
2004
- sql: schemaName === void 0 ? escapeName(viewName) : escapeName(schemaName) + "." + escapeName(viewName),
2005
- params: []
2006
- };
2007
- }
2008
- if (is(chunk, Param)) {
2009
- if (is(chunk.value, Placeholder)) {
2010
- return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
2011
- }
2012
- const mappedValue = chunk.value === null ? null : chunk.encoder.mapToDriverValue(chunk.value);
2013
- if (is(mappedValue, _SQL)) {
2014
- return this.buildQueryFromSourceParams([mappedValue], config);
2015
- }
2016
- if (inlineParams) {
2017
- return { sql: this.mapInlineParam(mappedValue, config), params: [] };
2018
- }
2019
- let typings = ["none"];
2020
- if (prepareTyping) {
2021
- typings = [prepareTyping(chunk.encoder)];
2022
- }
2023
- return { sql: escapeParam(paramStartIndex.value++, mappedValue), params: [mappedValue], typings };
2024
- }
2025
- if (is(chunk, Placeholder)) {
2026
- return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
2027
- }
2028
- if (is(chunk, _SQL.Aliased) && chunk.fieldAlias !== void 0) {
2029
- return { sql: escapeName(chunk.fieldAlias), params: [] };
2030
- }
2031
- if (is(chunk, Subquery)) {
2032
- if (chunk._.isWith) {
2033
- return { sql: escapeName(chunk._.alias), params: [] };
2034
- }
2035
- return this.buildQueryFromSourceParams([
2036
- new StringChunk("("),
2037
- chunk._.sql,
2038
- new StringChunk(") "),
2039
- new Name(chunk._.alias)
2040
- ], config);
2041
- }
2042
- if (isPgEnum(chunk)) {
2043
- if (chunk.schema) {
2044
- return { sql: escapeName(chunk.schema) + "." + escapeName(chunk.enumName), params: [] };
2045
- }
2046
- return { sql: escapeName(chunk.enumName), params: [] };
2047
- }
2048
- if (isSQLWrapper(chunk)) {
2049
- if (chunk.shouldOmitSQLParens?.()) {
2050
- return this.buildQueryFromSourceParams([chunk.getSQL()], config);
2051
- }
2052
- return this.buildQueryFromSourceParams([
2053
- new StringChunk("("),
2054
- chunk.getSQL(),
2055
- new StringChunk(")")
2056
- ], config);
2057
- }
2058
- if (inlineParams) {
2059
- return { sql: this.mapInlineParam(chunk, config), params: [] };
2060
- }
2061
- return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
2062
- }));
2063
- }
2064
- mapInlineParam(chunk, { escapeString }) {
2065
- if (chunk === null) {
2066
- return "null";
2067
- }
2068
- if (typeof chunk === "number" || typeof chunk === "boolean") {
2069
- return chunk.toString();
2070
- }
2071
- if (typeof chunk === "string") {
2072
- return escapeString(chunk);
2073
- }
2074
- if (typeof chunk === "object") {
2075
- const mappedValueAsString = chunk.toString();
2076
- if (mappedValueAsString === "[object Object]") {
2077
- return escapeString(JSON.stringify(chunk));
2078
- }
2079
- return escapeString(mappedValueAsString);
2080
- }
2081
- throw new Error("Unexpected param value: " + chunk);
2082
- }
2083
- getSQL() {
2084
- return this;
2085
- }
2086
- as(alias) {
2087
- if (alias === void 0) {
2088
- return this;
2089
- }
2090
- return new _SQL.Aliased(this, alias);
2091
- }
2092
- mapWith(decoder) {
2093
- this.decoder = typeof decoder === "function" ? { mapFromDriverValue: decoder } : decoder;
2094
- return this;
2095
- }
2096
- inlineParams() {
2097
- this.shouldInlineParams = true;
2098
- return this;
2099
- }
2100
- /**
2101
- * This method is used to conditionally include a part of the query.
2102
- *
2103
- * @param condition - Condition to check
2104
- * @returns itself if the condition is `true`, otherwise `undefined`
2105
- */
2106
- if(condition) {
2107
- return condition ? this : void 0;
2108
- }
2109
- };
2110
- var Name = class {
2111
- constructor(value) {
2112
- this.value = value;
2113
- }
2114
- static [entityKind] = "Name";
2115
- brand;
2116
- getSQL() {
2117
- return new SQL([this]);
2118
- }
2119
- };
2120
- var noopDecoder = {
2121
- mapFromDriverValue: (value) => value
2122
- };
2123
- var noopEncoder = {
2124
- mapToDriverValue: (value) => value
2125
- };
2126
- var noopMapper = {
2127
- ...noopDecoder,
2128
- ...noopEncoder
2129
- };
2130
- var Param = class {
2131
- /**
2132
- * @param value - Parameter value
2133
- * @param encoder - Encoder to convert the value to a driver parameter
2134
- */
2135
- constructor(value, encoder = noopEncoder) {
2136
- this.value = value;
2137
- this.encoder = encoder;
2138
- }
2139
- static [entityKind] = "Param";
2140
- brand;
2141
- getSQL() {
2142
- return new SQL([this]);
2143
- }
2144
- };
2145
- function sql(strings, ...params) {
2146
- const queryChunks = [];
2147
- if (params.length > 0 || strings.length > 0 && strings[0] !== "") {
2148
- queryChunks.push(new StringChunk(strings[0]));
2149
- }
2150
- for (const [paramIndex, param2] of params.entries()) {
2151
- queryChunks.push(param2, new StringChunk(strings[paramIndex + 1]));
2152
- }
2153
- return new SQL(queryChunks);
2154
- }
2155
- ((sql2) => {
2156
- function empty() {
2157
- return new SQL([]);
2158
- }
2159
- sql2.empty = empty;
2160
- function fromList(list) {
2161
- return new SQL(list);
2162
- }
2163
- sql2.fromList = fromList;
2164
- function raw(str) {
2165
- return new SQL([new StringChunk(str)]);
2166
- }
2167
- sql2.raw = raw;
2168
- function join(chunks, separator) {
2169
- const result = [];
2170
- for (const [i, chunk] of chunks.entries()) {
2171
- if (i > 0 && separator !== void 0) {
2172
- result.push(separator);
2173
- }
2174
- result.push(chunk);
2175
- }
2176
- return new SQL(result);
2177
- }
2178
- sql2.join = join;
2179
- function identifier(value) {
2180
- return new Name(value);
2181
- }
2182
- sql2.identifier = identifier;
2183
- function placeholder2(name2) {
2184
- return new Placeholder(name2);
2185
- }
2186
- sql2.placeholder = placeholder2;
2187
- function param2(value, encoder) {
2188
- return new Param(value, encoder);
2189
- }
2190
- sql2.param = param2;
2191
- })(sql || (sql = {}));
2192
- ((SQL2) => {
2193
- class Aliased {
2194
- constructor(sql2, fieldAlias) {
2195
- this.sql = sql2;
2196
- this.fieldAlias = fieldAlias;
2197
- }
2198
- static [entityKind] = "SQL.Aliased";
2199
- /** @internal */
2200
- isSelectionField = false;
2201
- getSQL() {
2202
- return this.sql;
2203
- }
2204
- /** @internal */
2205
- clone() {
2206
- return new Aliased(this.sql, this.fieldAlias);
2207
- }
2208
- }
2209
- SQL2.Aliased = Aliased;
2210
- })(SQL || (SQL = {}));
2211
- var Placeholder = class {
2212
- constructor(name2) {
2213
- this.name = name2;
2214
- }
2215
- static [entityKind] = "Placeholder";
2216
- getSQL() {
2217
- return new SQL([this]);
2218
- }
2219
- };
2220
- var View = class {
2221
- static [entityKind] = "View";
2222
- /** @internal */
2223
- [ViewBaseConfig];
2224
- constructor({ name: name2, schema, selectedFields, query }) {
2225
- this[ViewBaseConfig] = {
2226
- name: name2,
2227
- originalName: name2,
2228
- schema,
2229
- selectedFields,
2230
- query,
2231
- isExisting: !query,
2232
- isAlias: false
2233
- };
2234
- }
2235
- getSQL() {
2236
- return new SQL([this]);
2237
- }
2238
- };
2239
- Column.prototype.getSQL = function() {
2240
- return new SQL([this]);
2241
- };
2242
- Table.prototype.getSQL = function() {
2243
- return new SQL([this]);
2244
- };
2245
- Subquery.prototype.getSQL = function() {
2246
- return new SQL([this]);
2247
- };
2248
-
2249
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/utils.js
2250
- function getColumnNameAndConfig(a, b) {
2251
- return {
2252
- name: typeof a === "string" && a.length > 0 ? a : "",
2253
- config: typeof a === "object" ? a : b
2254
- };
2255
- }
2256
-
2257
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/foreign-keys.js
2258
- var ForeignKeyBuilder2 = class {
2259
- static [entityKind] = "SQLiteForeignKeyBuilder";
2260
- /** @internal */
2261
- reference;
2262
- /** @internal */
2263
- _onUpdate;
2264
- /** @internal */
2265
- _onDelete;
2266
- constructor(config, actions) {
2267
- this.reference = () => {
2268
- const { name, columns, foreignColumns } = config();
2269
- return { name, columns, foreignTable: foreignColumns[0].table, foreignColumns };
2270
- };
2271
- if (actions) {
2272
- this._onUpdate = actions.onUpdate;
2273
- this._onDelete = actions.onDelete;
2274
- }
2275
- }
2276
- onUpdate(action) {
2277
- this._onUpdate = action;
2278
- return this;
2279
- }
2280
- onDelete(action) {
2281
- this._onDelete = action;
2282
- return this;
2283
- }
2284
- /** @internal */
2285
- build(table) {
2286
- return new ForeignKey2(table, this);
2287
- }
2288
- };
2289
- var ForeignKey2 = class {
2290
- constructor(table, builder) {
2291
- this.table = table;
2292
- this.reference = builder.reference;
2293
- this.onUpdate = builder._onUpdate;
2294
- this.onDelete = builder._onDelete;
2295
- }
2296
- static [entityKind] = "SQLiteForeignKey";
2297
- reference;
2298
- onUpdate;
2299
- onDelete;
2300
- getName() {
2301
- const { name, columns, foreignColumns } = this.reference();
2302
- const columnNames = columns.map((column) => column.name);
2303
- const foreignColumnNames = foreignColumns.map((column) => column.name);
2304
- const chunks = [
2305
- this.table[TableName],
2306
- ...columnNames,
2307
- foreignColumns[0].table[TableName],
2308
- ...foreignColumnNames
2309
- ];
2310
- return name ?? `${chunks.join("_")}_fk`;
2311
- }
2312
- };
2313
-
2314
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/unique-constraint.js
2315
- function uniqueKeyName2(table, columns) {
2316
- return `${table[TableName]}_${columns.join("_")}_unique`;
2317
- }
2318
- var UniqueConstraintBuilder2 = class {
2319
- constructor(columns, name) {
2320
- this.name = name;
2321
- this.columns = columns;
2322
- }
2323
- static [entityKind] = "SQLiteUniqueConstraintBuilder";
2324
- /** @internal */
2325
- columns;
2326
- /** @internal */
2327
- build(table) {
2328
- return new UniqueConstraint2(table, this.columns, this.name);
2329
- }
2330
- };
2331
- var UniqueOnConstraintBuilder2 = class {
2332
- static [entityKind] = "SQLiteUniqueOnConstraintBuilder";
2333
- /** @internal */
2334
- name;
2335
- constructor(name) {
2336
- this.name = name;
2337
- }
2338
- on(...columns) {
2339
- return new UniqueConstraintBuilder2(columns, this.name);
2340
- }
2341
- };
2342
- var UniqueConstraint2 = class {
2343
- constructor(table, columns, name) {
2344
- this.table = table;
2345
- this.columns = columns;
2346
- this.name = name ?? uniqueKeyName2(this.table, this.columns.map((column) => column.name));
2347
- }
2348
- static [entityKind] = "SQLiteUniqueConstraint";
2349
- columns;
2350
- name;
2351
- getName() {
2352
- return this.name;
2353
- }
2354
- };
2355
-
2356
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/columns/common.js
2357
- var SQLiteColumnBuilder = class extends ColumnBuilder {
2358
- static [entityKind] = "SQLiteColumnBuilder";
2359
- foreignKeyConfigs = [];
2360
- references(ref, actions = {}) {
2361
- this.foreignKeyConfigs.push({ ref, actions });
2362
- return this;
2363
- }
2364
- unique(name) {
2365
- this.config.isUnique = true;
2366
- this.config.uniqueName = name;
2367
- return this;
2368
- }
2369
- generatedAlwaysAs(as, config) {
2370
- this.config.generated = {
2371
- as,
2372
- type: "always",
2373
- mode: config?.mode ?? "virtual"
2374
- };
2375
- return this;
2376
- }
2377
- /** @internal */
2378
- buildForeignKeys(column, table) {
2379
- return this.foreignKeyConfigs.map(({ ref, actions }) => {
2380
- return ((ref2, actions2) => {
2381
- const builder = new ForeignKeyBuilder2(() => {
2382
- const foreignColumn = ref2();
2383
- return { columns: [column], foreignColumns: [foreignColumn] };
2384
- });
2385
- if (actions2.onUpdate) {
2386
- builder.onUpdate(actions2.onUpdate);
2387
- }
2388
- if (actions2.onDelete) {
2389
- builder.onDelete(actions2.onDelete);
2390
- }
2391
- return builder.build(table);
2392
- })(ref, actions);
2393
- });
2394
- }
2395
- };
2396
- var SQLiteColumn = class extends Column {
2397
- constructor(table, config) {
2398
- if (!config.uniqueName) {
2399
- config.uniqueName = uniqueKeyName2(table, [config.name]);
2400
- }
2401
- super(table, config);
2402
- this.table = table;
2403
- }
2404
- static [entityKind] = "SQLiteColumn";
2405
- };
2406
-
2407
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/columns/blob.js
2408
- var SQLiteBigIntBuilder = class extends SQLiteColumnBuilder {
2409
- static [entityKind] = "SQLiteBigIntBuilder";
2410
- constructor(name) {
2411
- super(name, "bigint", "SQLiteBigInt");
2412
- }
2413
- /** @internal */
2414
- build(table) {
2415
- return new SQLiteBigInt(table, this.config);
2416
- }
2417
- };
2418
- var SQLiteBigInt = class extends SQLiteColumn {
2419
- static [entityKind] = "SQLiteBigInt";
2420
- getSQLType() {
2421
- return "blob";
2422
- }
2423
- mapFromDriverValue(value) {
2424
- return BigInt(Buffer.isBuffer(value) ? value.toString() : String.fromCodePoint(...value));
2425
- }
2426
- mapToDriverValue(value) {
2427
- return Buffer.from(value.toString());
2428
- }
2429
- };
2430
- var SQLiteBlobJsonBuilder = class extends SQLiteColumnBuilder {
2431
- static [entityKind] = "SQLiteBlobJsonBuilder";
2432
- constructor(name) {
2433
- super(name, "json", "SQLiteBlobJson");
2434
- }
2435
- /** @internal */
2436
- build(table) {
2437
- return new SQLiteBlobJson(
2438
- table,
2439
- this.config
2440
- );
2441
- }
2442
- };
2443
- var SQLiteBlobJson = class extends SQLiteColumn {
2444
- static [entityKind] = "SQLiteBlobJson";
2445
- getSQLType() {
2446
- return "blob";
2447
- }
2448
- mapFromDriverValue(value) {
2449
- return JSON.parse(Buffer.isBuffer(value) ? value.toString() : String.fromCodePoint(...value));
2450
- }
2451
- mapToDriverValue(value) {
2452
- return Buffer.from(JSON.stringify(value));
2453
- }
2454
- };
2455
- var SQLiteBlobBufferBuilder = class extends SQLiteColumnBuilder {
2456
- static [entityKind] = "SQLiteBlobBufferBuilder";
2457
- constructor(name) {
2458
- super(name, "buffer", "SQLiteBlobBuffer");
2459
- }
2460
- /** @internal */
2461
- build(table) {
2462
- return new SQLiteBlobBuffer(table, this.config);
2463
- }
2464
- };
2465
- var SQLiteBlobBuffer = class extends SQLiteColumn {
2466
- static [entityKind] = "SQLiteBlobBuffer";
2467
- getSQLType() {
2468
- return "blob";
2469
- }
2470
- };
2471
- function blob(a, b) {
2472
- const { name, config } = getColumnNameAndConfig(a, b);
2473
- if (config?.mode === "json") {
2474
- return new SQLiteBlobJsonBuilder(name);
2475
- }
2476
- if (config?.mode === "bigint") {
2477
- return new SQLiteBigIntBuilder(name);
2478
- }
2479
- return new SQLiteBlobBufferBuilder(name);
2480
- }
2481
-
2482
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/columns/custom.js
2483
- var SQLiteCustomColumnBuilder = class extends SQLiteColumnBuilder {
2484
- static [entityKind] = "SQLiteCustomColumnBuilder";
2485
- constructor(name, fieldConfig, customTypeParams) {
2486
- super(name, "custom", "SQLiteCustomColumn");
2487
- this.config.fieldConfig = fieldConfig;
2488
- this.config.customTypeParams = customTypeParams;
2489
- }
2490
- /** @internal */
2491
- build(table) {
2492
- return new SQLiteCustomColumn(
2493
- table,
2494
- this.config
2495
- );
2496
- }
2497
- };
2498
- var SQLiteCustomColumn = class extends SQLiteColumn {
2499
- static [entityKind] = "SQLiteCustomColumn";
2500
- sqlName;
2501
- mapTo;
2502
- mapFrom;
2503
- constructor(table, config) {
2504
- super(table, config);
2505
- this.sqlName = config.customTypeParams.dataType(config.fieldConfig);
2506
- this.mapTo = config.customTypeParams.toDriver;
2507
- this.mapFrom = config.customTypeParams.fromDriver;
2508
- }
2509
- getSQLType() {
2510
- return this.sqlName;
2511
- }
2512
- mapFromDriverValue(value) {
2513
- return typeof this.mapFrom === "function" ? this.mapFrom(value) : value;
2514
- }
2515
- mapToDriverValue(value) {
2516
- return typeof this.mapTo === "function" ? this.mapTo(value) : value;
2517
- }
2518
- };
2519
- function customType(customTypeParams) {
2520
- return (a, b) => {
2521
- const { name, config } = getColumnNameAndConfig(a, b);
2522
- return new SQLiteCustomColumnBuilder(
2523
- name,
2524
- config,
2525
- customTypeParams
2526
- );
2527
- };
2528
- }
2529
-
2530
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/columns/integer.js
2531
- var SQLiteBaseIntegerBuilder = class extends SQLiteColumnBuilder {
2532
- static [entityKind] = "SQLiteBaseIntegerBuilder";
2533
- constructor(name, dataType, columnType) {
2534
- super(name, dataType, columnType);
2535
- this.config.autoIncrement = false;
2536
- }
2537
- primaryKey(config) {
2538
- if (config?.autoIncrement) {
2539
- this.config.autoIncrement = true;
2540
- }
2541
- this.config.hasDefault = true;
2542
- return super.primaryKey();
2543
- }
2544
- };
2545
- var SQLiteBaseInteger = class extends SQLiteColumn {
2546
- static [entityKind] = "SQLiteBaseInteger";
2547
- autoIncrement = this.config.autoIncrement;
2548
- getSQLType() {
2549
- return "integer";
2550
- }
2551
- };
2552
- var SQLiteIntegerBuilder = class extends SQLiteBaseIntegerBuilder {
2553
- static [entityKind] = "SQLiteIntegerBuilder";
2554
- constructor(name) {
2555
- super(name, "number", "SQLiteInteger");
2556
- }
2557
- build(table) {
2558
- return new SQLiteInteger(
2559
- table,
2560
- this.config
2561
- );
2562
- }
2563
- };
2564
- var SQLiteInteger = class extends SQLiteBaseInteger {
2565
- static [entityKind] = "SQLiteInteger";
2566
- };
2567
- var SQLiteTimestampBuilder = class extends SQLiteBaseIntegerBuilder {
2568
- static [entityKind] = "SQLiteTimestampBuilder";
2569
- constructor(name, mode) {
2570
- super(name, "date", "SQLiteTimestamp");
2571
- this.config.mode = mode;
2572
- }
2573
- /**
2574
- * @deprecated Use `default()` with your own expression instead.
2575
- *
2576
- * Adds `DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer))` to the column, which is the current epoch timestamp in milliseconds.
2577
- */
2578
- defaultNow() {
2579
- return this.default(sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`);
2580
- }
2581
- build(table) {
2582
- return new SQLiteTimestamp(
2583
- table,
2584
- this.config
2585
- );
2586
- }
2587
- };
2588
- var SQLiteTimestamp = class extends SQLiteBaseInteger {
2589
- static [entityKind] = "SQLiteTimestamp";
2590
- mode = this.config.mode;
2591
- mapFromDriverValue(value) {
2592
- if (this.config.mode === "timestamp") {
2593
- return new Date(value * 1e3);
2594
- }
2595
- return new Date(value);
2596
- }
2597
- mapToDriverValue(value) {
2598
- const unix = value.getTime();
2599
- if (this.config.mode === "timestamp") {
2600
- return Math.floor(unix / 1e3);
1198
+ summary: "Get analysis timeseries",
1199
+ description: "Same row shape as `/results`, but returns every daily slice rather than the latest. Filter to a single metric with the `metric` query parameter.",
1200
+ pathParams: { id: "Stable opaque experiment id." },
1201
+ queryParams: {
1202
+ metric: {
1203
+ schema: z7.string().optional(),
1204
+ description: "Optional metric name to filter the series."
1205
+ }
1206
+ },
1207
+ response: experimentTimeseriesResponseSchema,
1208
+ examples: {
1209
+ response: {
1210
+ experiment: {
1211
+ id: "exp_01j7wb12c3d4e5f6g7h8j9k0l1",
1212
+ name: "checkout_button_color",
1213
+ status: "running"
1214
+ },
1215
+ series: [
1216
+ {
1217
+ metric: "checkout_completed",
1218
+ group_name: "treatment",
1219
+ ds: "2026-05-08",
1220
+ n: 11200,
1221
+ mean: 0.1903,
1222
+ delta_pct: 3.9,
1223
+ p_value: 0.034,
1224
+ srm_detected: 0
1225
+ },
1226
+ {
1227
+ metric: "checkout_completed",
1228
+ group_name: "treatment",
1229
+ ds: "2026-05-09",
1230
+ n: 12519,
1231
+ mean: 0.1922,
1232
+ delta_pct: 4.8,
1233
+ p_value: 0.018,
1234
+ srm_detected: 0
1235
+ }
1236
+ ]
1237
+ }
1238
+ },
1239
+ useCase: "Drive a chart of metric movement over the experiment runtime, or sanity-check the lift is monotonic before deciding."
1240
+ },
1241
+ {
1242
+ operationId: "reanalyzeExperiment",
1243
+ method: "POST",
1244
+ path: "/{id}/reanalyze",
1245
+ summary: "Re-queue analysis",
1246
+ description: "Requeues the daily analysis pass for this experiment outside the normal cron cadence. Useful after attaching a new metric or correcting an event taxonomy. The job runs asynchronously.",
1247
+ pathParams: { id: "Stable opaque experiment id." },
1248
+ response: experimentReanalyzeResponseSchema,
1249
+ examples: { response: { id: "exp_01j7wb12c3d4e5f6g7h8j9k0l1", queued: true } },
1250
+ useCase: "Force-refresh results after wiring up a new metric without waiting for the next nightly cron tick."
2601
1251
  }
2602
- return unix;
2603
- }
2604
- };
2605
- var SQLiteBooleanBuilder = class extends SQLiteBaseIntegerBuilder {
2606
- static [entityKind] = "SQLiteBooleanBuilder";
2607
- constructor(name, mode) {
2608
- super(name, "boolean", "SQLiteBoolean");
2609
- this.config.mode = mode;
2610
- }
2611
- build(table) {
2612
- return new SQLiteBoolean(
2613
- table,
2614
- this.config
2615
- );
2616
- }
2617
- };
2618
- var SQLiteBoolean = class extends SQLiteBaseInteger {
2619
- static [entityKind] = "SQLiteBoolean";
2620
- mode = this.config.mode;
2621
- mapFromDriverValue(value) {
2622
- return Number(value) === 1;
2623
- }
2624
- mapToDriverValue(value) {
2625
- return value ? 1 : 0;
2626
- }
2627
- };
2628
- function integer(a, b) {
2629
- const { name, config } = getColumnNameAndConfig(a, b);
2630
- if (config?.mode === "timestamp" || config?.mode === "timestamp_ms") {
2631
- return new SQLiteTimestampBuilder(name, config.mode);
2632
- }
2633
- if (config?.mode === "boolean") {
2634
- return new SQLiteBooleanBuilder(name, config.mode);
2635
- }
2636
- return new SQLiteIntegerBuilder(name);
2637
- }
2638
-
2639
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/columns/numeric.js
2640
- var SQLiteNumericBuilder = class extends SQLiteColumnBuilder {
2641
- static [entityKind] = "SQLiteNumericBuilder";
2642
- constructor(name) {
2643
- super(name, "string", "SQLiteNumeric");
2644
- }
2645
- /** @internal */
2646
- build(table) {
2647
- return new SQLiteNumeric(
2648
- table,
2649
- this.config
2650
- );
2651
- }
2652
- };
2653
- var SQLiteNumeric = class extends SQLiteColumn {
2654
- static [entityKind] = "SQLiteNumeric";
2655
- getSQLType() {
2656
- return "numeric";
2657
- }
2658
- };
2659
- function numeric(name) {
2660
- return new SQLiteNumericBuilder(name ?? "");
2661
- }
2662
-
2663
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/columns/real.js
2664
- var SQLiteRealBuilder = class extends SQLiteColumnBuilder {
2665
- static [entityKind] = "SQLiteRealBuilder";
2666
- constructor(name) {
2667
- super(name, "number", "SQLiteReal");
2668
- }
2669
- /** @internal */
2670
- build(table) {
2671
- return new SQLiteReal(table, this.config);
2672
- }
2673
- };
2674
- var SQLiteReal = class extends SQLiteColumn {
2675
- static [entityKind] = "SQLiteReal";
2676
- getSQLType() {
2677
- return "real";
2678
- }
2679
- };
2680
- function real(name) {
2681
- return new SQLiteRealBuilder(name ?? "");
2682
- }
2683
-
2684
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/columns/text.js
2685
- var SQLiteTextBuilder = class extends SQLiteColumnBuilder {
2686
- static [entityKind] = "SQLiteTextBuilder";
2687
- constructor(name, config) {
2688
- super(name, "string", "SQLiteText");
2689
- this.config.enumValues = config.enum;
2690
- this.config.length = config.length;
2691
- }
2692
- /** @internal */
2693
- build(table) {
2694
- return new SQLiteText(table, this.config);
2695
- }
2696
- };
2697
- var SQLiteText = class extends SQLiteColumn {
2698
- static [entityKind] = "SQLiteText";
2699
- enumValues = this.config.enumValues;
2700
- length = this.config.length;
2701
- constructor(table, config) {
2702
- super(table, config);
2703
- }
2704
- getSQLType() {
2705
- return `text${this.config.length ? `(${this.config.length})` : ""}`;
2706
- }
2707
- };
2708
- var SQLiteTextJsonBuilder = class extends SQLiteColumnBuilder {
2709
- static [entityKind] = "SQLiteTextJsonBuilder";
2710
- constructor(name) {
2711
- super(name, "json", "SQLiteTextJson");
2712
- }
2713
- /** @internal */
2714
- build(table) {
2715
- return new SQLiteTextJson(
2716
- table,
2717
- this.config
2718
- );
2719
- }
2720
- };
2721
- var SQLiteTextJson = class extends SQLiteColumn {
2722
- static [entityKind] = "SQLiteTextJson";
2723
- getSQLType() {
2724
- return "text";
2725
- }
2726
- mapFromDriverValue(value) {
2727
- return JSON.parse(value);
2728
- }
2729
- mapToDriverValue(value) {
2730
- return JSON.stringify(value);
2731
- }
2732
- };
2733
- function text(a, b = {}) {
2734
- const { name, config } = getColumnNameAndConfig(a, b);
2735
- if (config.mode === "json") {
2736
- return new SQLiteTextJsonBuilder(name);
2737
- }
2738
- return new SQLiteTextBuilder(name, config);
2739
- }
2740
-
2741
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/columns/all.js
2742
- function getSQLiteColumnBuilders() {
2743
- return {
2744
- blob,
2745
- customType,
2746
- integer,
2747
- numeric,
2748
- real,
2749
- text
2750
- };
2751
- }
2752
-
2753
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/table.js
2754
- var InlineForeignKeys = /* @__PURE__ */ Symbol.for("drizzle:SQLiteInlineForeignKeys");
2755
- var SQLiteTable = class extends Table {
2756
- static [entityKind] = "SQLiteTable";
2757
- /** @internal */
2758
- static Symbol = Object.assign({}, Table.Symbol, {
2759
- InlineForeignKeys
2760
- });
2761
- /** @internal */
2762
- [Table.Symbol.Columns];
2763
- /** @internal */
2764
- [InlineForeignKeys] = [];
2765
- /** @internal */
2766
- [Table.Symbol.ExtraConfigBuilder] = void 0;
2767
- };
2768
- function sqliteTableBase(name, columns, extraConfig, schema, baseName = name) {
2769
- const rawTable = new SQLiteTable(name, schema, baseName);
2770
- const parsedColumns = typeof columns === "function" ? columns(getSQLiteColumnBuilders()) : columns;
2771
- const builtColumns = Object.fromEntries(
2772
- Object.entries(parsedColumns).map(([name2, colBuilderBase]) => {
2773
- const colBuilder = colBuilderBase;
2774
- colBuilder.setName(name2);
2775
- const column = colBuilder.build(rawTable);
2776
- rawTable[InlineForeignKeys].push(...colBuilder.buildForeignKeys(column, rawTable));
2777
- return [name2, column];
2778
- })
2779
- );
2780
- const table = Object.assign(rawTable, builtColumns);
2781
- table[Table.Symbol.Columns] = builtColumns;
2782
- table[Table.Symbol.ExtraConfigColumns] = builtColumns;
2783
- if (extraConfig) {
2784
- table[SQLiteTable.Symbol.ExtraConfigBuilder] = extraConfig;
2785
- }
2786
- return table;
2787
- }
2788
- var sqliteTable = (name, columns, extraConfig) => {
2789
- return sqliteTableBase(name, columns, extraConfig);
1252
+ ]
2790
1253
  };
2791
1254
 
2792
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/indexes.js
2793
- var IndexBuilderOn = class {
2794
- constructor(name, unique) {
2795
- this.name = name;
2796
- this.unique = unique;
2797
- }
2798
- static [entityKind] = "SQLiteIndexBuilderOn";
2799
- on(...columns) {
2800
- return new IndexBuilder(this.name, columns, this.unique);
2801
- }
2802
- };
2803
- var IndexBuilder = class {
2804
- static [entityKind] = "SQLiteIndexBuilder";
2805
- /** @internal */
2806
- config;
2807
- constructor(name, columns, unique) {
2808
- this.config = {
2809
- name,
2810
- columns,
2811
- unique,
2812
- where: void 0
2813
- };
2814
- }
2815
- /**
2816
- * Condition for partial index.
2817
- */
2818
- where(condition) {
2819
- this.config.where = condition;
2820
- return this;
2821
- }
2822
- /** @internal */
2823
- build(table) {
2824
- return new Index(this.config, table);
2825
- }
2826
- };
2827
- var Index = class {
2828
- static [entityKind] = "SQLiteIndex";
2829
- config;
2830
- constructor(config, table) {
2831
- this.config = { ...config, table };
2832
- }
2833
- };
2834
- function index(name) {
2835
- return new IndexBuilderOn(name, false);
2836
- }
2837
- function uniqueIndex(name) {
2838
- return new IndexBuilderOn(name, true);
2839
- }
1255
+ // src/resources/configs.ts
1256
+ import { z as z9 } from "zod";
2840
1257
 
2841
- // ../../node_modules/.pnpm/drizzle-orm@0.36.4_@cloudflare+workers-types@4.20260416.2_@types+better-sqlite3@7.6.13__6bda8a68f3e10d0b03cd2031bac7989c/node_modules/drizzle-orm/sqlite-core/primary-keys.js
2842
- function primaryKey(...config) {
2843
- if (config[0].columns) {
2844
- return new PrimaryKeyBuilder(config[0].columns, config[0].name);
2845
- }
2846
- return new PrimaryKeyBuilder(config);
2847
- }
2848
- var PrimaryKeyBuilder = class {
2849
- static [entityKind] = "SQLitePrimaryKeyBuilder";
2850
- /** @internal */
2851
- columns;
2852
- /** @internal */
2853
- name;
2854
- constructor(columns, name) {
2855
- this.columns = columns;
2856
- this.name = name;
2857
- }
2858
- /** @internal */
2859
- build(table) {
2860
- return new PrimaryKey(table, this.columns, this.name);
2861
- }
2862
- };
2863
- var PrimaryKey = class {
2864
- constructor(table, columns, name) {
2865
- this.table = table;
2866
- this.columns = columns;
2867
- this.name = name;
2868
- }
2869
- static [entityKind] = "SQLitePrimaryKey";
2870
- columns;
2871
- name;
2872
- getName() {
2873
- return this.name ?? `${this.table[SQLiteTable.Symbol.Name]}_${this.columns.map((column) => column.name).join("_")}_pk`;
2874
- }
2875
- };
1258
+ // src/schemas/configs.ts
1259
+ import { z as z8 } from "zod";
2876
1260
 
2877
- // ../core/src/db/schema.ts
2878
- var projects = sqliteTable(
2879
- "projects",
2880
- {
2881
- id: text("id").primaryKey(),
2882
- name: text("name").notNull(),
2883
- domain: text("domain"),
2884
- ownerEmail: text("owner_email").notNull(),
2885
- plan: text("plan", { enum: ["free", "paid"] }).notNull().default("free"),
2886
- status: text("status", { enum: ["active", "inactive"] }).notNull().default("active"),
2887
- // Stripe billing
2888
- stripeCustomerId: text("stripe_customer_id").unique(),
2889
- stripeSubscriptionId: text("stripe_subscription_id").unique(),
2890
- stripeItemIdBase: text("stripe_item_id_base"),
2891
- stripeItemIdExperiments: text("stripe_item_id_experiments"),
2892
- stripeItemIdGates: text("stripe_item_id_gates"),
2893
- stripeItemIdConfigs: text("stripe_item_id_configs"),
2894
- subscriptionStatus: text("subscription_status", {
2895
- enum: ["none", "trialing", "active", "past_due", "canceled", "incomplete"]
2896
- }).notNull().default("none"),
2897
- currentPeriodEnd: text("current_period_end"),
2898
- trialEndsAt: text("trial_ends_at"),
2899
- cancelAtPeriodEnd: integer("cancel_at_period_end").notNull().default(0),
2900
- billingInterval: text("billing_interval", { enum: ["monthly", "annual"] }).notNull().default("monthly"),
2901
- // Per-project module toggles. Control which surfaces (admin tabs, devtools
2902
- // panels) are exposed for this project. All default to enabled so existing
2903
- // projects keep their full feature set after the migration.
2904
- moduleTranslations: integer("module_translations", { mode: "boolean" }).notNull().default(true),
2905
- moduleConfigs: integer("module_configs", { mode: "boolean" }).notNull().default(true),
2906
- moduleGates: integer("module_gates", { mode: "boolean" }).notNull().default(true),
2907
- moduleExperiments: integer("module_experiments", { mode: "boolean" }).notNull().default(true),
2908
- moduleFeedback: integer("module_feedback", { mode: "boolean" }).notNull().default(true),
2909
- moduleUser: integer("module_user", { mode: "boolean" }).notNull().default(true),
2910
- moduleEvents: integer("module_events", { mode: "boolean" }).notNull().default(true),
2911
- createdAt: text("created_at").notNull(),
2912
- updatedAt: text("updated_at").notNull()
2913
- },
2914
- (t) => ({
2915
- // One project per (owner, domain): a single account can't accidentally
2916
- // create two projects pointing at the same site. Multiple projects per
2917
- // owner are still allowed across different domains, and `domain` may be
2918
- // NULL for projects without a configured site (SQLite treats each NULL
2919
- // as distinct under UNIQUE, so multiple no-domain projects per owner are
2920
- // permitted).
2921
- ownerDomainUniq: uniqueIndex("projects_owner_domain_uniq").on(t.ownerEmail, t.domain)
2922
- })
2923
- );
2924
- var users = sqliteTable("users", {
2925
- email: text("email").primaryKey(),
2926
- termsAcceptedAt: text("terms_accepted_at"),
2927
- termsVersion: text("terms_version"),
2928
- onboardingCompletedAt: text("onboarding_completed_at"),
2929
- createdAt: text("created_at").notNull(),
2930
- updatedAt: text("updated_at").notNull()
2931
- });
2932
- var projectMembers = sqliteTable(
2933
- "project_members",
2934
- {
2935
- id: text("id").primaryKey(),
2936
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
2937
- email: text("email").notNull(),
2938
- role: text("role", { enum: ["admin", "editor", "viewer"] }).notNull().default("editor"),
2939
- status: text("status", { enum: ["active", "pending", "removed"] }).notNull().default("pending"),
2940
- invitedByEmail: text("invited_by_email").notNull(),
2941
- invitedAt: text("invited_at").notNull(),
2942
- acceptedAt: text("accepted_at"),
2943
- removedAt: text("removed_at")
2944
- },
2945
- (t) => ({
2946
- projectIdx: index("project_members_project").on(t.projectId, t.status),
2947
- projectEmailUniq: uniqueIndex("project_members_project_email").on(t.projectId, t.email)
2948
- })
2949
- );
2950
- var sdkKeys = sqliteTable(
2951
- "sdk_keys",
2952
- {
2953
- id: text("id").primaryKey(),
2954
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
2955
- keyHash: text("key_hash").unique().notNull(),
2956
- type: text("type", { enum: ["server", "client", "admin"] }).notNull(),
2957
- scope: text("scope", { enum: ["experiments", "i18n"] }).notNull().default("experiments"),
2958
- createdAt: text("created_at").notNull(),
2959
- revokedAt: text("revoked_at"),
2960
- expiresAt: text("expires_at"),
2961
- // Email of the human who minted this key (admin keys via dashboard or
2962
- // CLI device-flow). Used to authorize cross-project --project overrides
2963
- // by joining against project_members. Null for older keys + for
2964
- // service-to-service keys without a human owner.
2965
- createdByEmail: text("created_by_email")
2966
- },
2967
- (t) => ({ hashIdx: index("sdk_keys_hash").on(t.keyHash) })
2968
- );
2969
- var cliAuthSessions = sqliteTable(
2970
- "cli_auth_sessions",
2971
- {
2972
- state: text("state").primaryKey(),
2973
- codeChallenge: text("code_challenge").notNull(),
2974
- projectId: text("project_id").references(() => projects.id),
2975
- tokenHash: text("token_hash"),
2976
- status: text("status", { enum: ["pending", "complete", "expired"] }).notNull().default("pending"),
2977
- createdAt: text("created_at").notNull(),
2978
- expiresAt: text("expires_at").notNull(),
2979
- completedAt: text("completed_at")
2980
- },
2981
- (t) => ({ expiresIdx: index("cli_auth_sessions_expires").on(t.expiresAt) })
2982
- );
2983
- var cliTokens = sqliteTable(
2984
- "cli_tokens",
2985
- {
2986
- tokenId: text("token_id").primaryKey(),
2987
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
2988
- userEmail: text("user_email").notNull(),
2989
- issuedAt: text("issued_at").notNull(),
2990
- expiresAt: text("expires_at").notNull(),
2991
- revokedAt: text("revoked_at"),
2992
- lastUsedAt: text("last_used_at")
2993
- },
2994
- (t) => ({
2995
- projectIdx: index("cli_tokens_project").on(t.projectId),
2996
- expiresIdx: index("cli_tokens_expires").on(t.expiresAt)
2997
- })
2998
- );
2999
- var analysisFailures = sqliteTable("analysis_failures", {
3000
- projectId: text("project_id").primaryKey().references(() => projects.id),
3001
- failedAt: text("failed_at").notNull(),
3002
- retryCount: integer("retry_count").notNull().default(3),
3003
- messageBody: text("message_body"),
3004
- resolvedAt: text("resolved_at")
3005
- });
3006
- var systemHealth = sqliteTable("system_health", {
3007
- key: text("key").primaryKey(),
3008
- lastFiredAt: text("last_fired_at").notNull(),
3009
- projectsEnqueued: integer("projects_enqueued")
3010
- });
3011
- var auditLog = sqliteTable(
3012
- "audit_log",
3013
- {
3014
- id: text("id").primaryKey(),
3015
- projectId: text("project_id").notNull().references(() => projects.id),
3016
- actorEmail: text("actor_email").notNull(),
3017
- actorType: text("actor_type", { enum: ["user", "cli", "system"] }).notNull(),
3018
- action: text("action").notNull(),
3019
- resourceType: text("resource_type").notNull(),
3020
- resourceId: text("resource_id"),
3021
- payload: text("payload"),
3022
- createdAt: text("created_at").notNull()
3023
- },
3024
- (t) => ({
3025
- projectIdx: index("audit_log_project").on(t.projectId, t.createdAt),
3026
- actorIdx: index("audit_log_actor").on(t.actorEmail),
3027
- resourceIdx: index("audit_log_resource").on(t.resourceType, t.resourceId)
3028
- })
3029
- );
3030
- var gates = sqliteTable(
3031
- "gates",
3032
- {
3033
- id: text("id").primaryKey(),
3034
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3035
- name: text("name").notNull(),
3036
- rules: text("rules", { mode: "json" }).$type().notNull(),
3037
- rolloutPct: integer("rollout_pct").notNull().default(0),
3038
- salt: text("salt").notNull(),
3039
- enabled: integer("enabled").notNull().default(1),
3040
- // Gatekeeper metadata + ordered sub-gate stack. Stack is null on rows that
3041
- // predate the gatekeeper migration; eval falls back to rules+rolloutPct.
3042
- title: text("title"),
3043
- description: text("description"),
3044
- folder: text("folder"),
3045
- groupName: text("group_name"),
3046
- ownerEmail: text("owner_email"),
3047
- stack: text("stack", { mode: "json" }).$type(),
3048
- updatedAt: text("updated_at").notNull(),
3049
- deletedAt: text("deleted_at")
3050
- },
3051
- (t) => ({
3052
- projectIdx: index("gates_project").on(t.projectId),
3053
- projectNameUniq: uniqueIndex("gates_project_name").on(t.projectId, t.name).where(sql`deleted_at is null`)
3054
- })
3055
- );
1261
+ // src/schemas/constants.ts
3056
1262
  var CONFIG_ENVS = ["dev", "staging", "prod"];
3057
1263
  var CONFIG_KINDS = ["config", "killswitch"];
3058
- var DEFAULT_CONFIG_SCHEMA = {
3059
- type: "object",
3060
- properties: {},
3061
- additionalProperties: true
3062
- };
3063
- var configs = sqliteTable(
3064
- "configs",
3065
- {
3066
- id: text("id").primaryKey(),
3067
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3068
- name: text("name").notNull(),
3069
- description: text("description"),
3070
- kind: text("kind", { enum: CONFIG_KINDS }).notNull().default("config"),
3071
- schemaJson: text("schema_json", { mode: "json" }).$type().notNull().default(DEFAULT_CONFIG_SCHEMA),
3072
- updatedAt: text("updated_at").notNull(),
3073
- deletedAt: text("deleted_at")
3074
- },
3075
- (t) => ({
3076
- uniq: uniqueIndex("configs_project_name").on(t.projectId, t.name).where(sql`deleted_at is null`)
3077
- })
3078
- );
3079
- var configValues = sqliteTable(
3080
- "config_values",
3081
- {
3082
- id: text("id").primaryKey(),
3083
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3084
- configId: text("config_id").notNull().references(() => configs.id, { onDelete: "cascade" }),
3085
- env: text("env", { enum: CONFIG_ENVS }).notNull(),
3086
- valueJson: text("value_json", { mode: "json" }).$type().notNull(),
3087
- version: integer("version").notNull(),
3088
- publishedAt: text("published_at").notNull(),
3089
- publishedBy: text("published_by").notNull()
3090
- },
3091
- (t) => ({
3092
- projectIdx: index("config_values_project").on(t.projectId),
3093
- configEnvIdx: index("config_values_config_env").on(t.configId, t.env, t.version),
3094
- uniq: uniqueIndex("config_values_config_env_version").on(t.configId, t.env, t.version)
3095
- })
3096
- );
3097
- var configDrafts = sqliteTable(
3098
- "config_drafts",
3099
- {
3100
- id: text("id").primaryKey(),
3101
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3102
- configId: text("config_id").notNull().references(() => configs.id, { onDelete: "cascade" }),
3103
- env: text("env", { enum: CONFIG_ENVS }).notNull(),
3104
- valueJson: text("value_json", { mode: "json" }).$type().notNull(),
3105
- baseVersion: integer("base_version").notNull(),
3106
- authorEmail: text("author_email").notNull(),
3107
- createdAt: text("created_at").notNull(),
3108
- updatedAt: text("updated_at").notNull()
3109
- },
3110
- (t) => ({
3111
- projectIdx: index("config_drafts_project").on(t.projectId),
3112
- uniq: uniqueIndex("config_drafts_config_env").on(t.configId, t.env)
3113
- })
3114
- );
3115
- var universes = sqliteTable(
3116
- "universes",
3117
- {
3118
- id: text("id").primaryKey(),
3119
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3120
- name: text("name").notNull(),
3121
- unitType: text("unit_type").notNull().default("user_id"),
3122
- holdoutRange: text("holdout_range", { mode: "json" }).$type(),
3123
- createdAt: text("created_at").notNull(),
3124
- deletedAt: text("deleted_at")
3125
- },
3126
- (t) => ({
3127
- projectIdx: index("universes_project").on(t.projectId),
3128
- projectUniq: uniqueIndex("universes_project_name").on(t.projectId, t.name).where(sql`deleted_at is null`)
3129
- })
3130
- );
3131
- var experiments = sqliteTable(
3132
- "experiments",
3133
- {
3134
- id: text("id").primaryKey(),
3135
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3136
- name: text("name").notNull(),
3137
- description: text("description"),
3138
- tag: text("tag"),
3139
- universe: text("universe").notNull(),
3140
- targetingGate: text("targeting_gate"),
3141
- allocationPct: integer("allocation_pct").notNull().default(0),
3142
- salt: text("salt").notNull(),
3143
- params: text("params", { mode: "json" }).$type().notNull(),
3144
- groups: text("groups", { mode: "json" }).$type().notNull(),
3145
- status: text("status", { enum: ["draft", "running", "stopped", "archived"] }).notNull().default("draft"),
3146
- startedAt: text("started_at"),
3147
- stoppedAt: text("stopped_at"),
3148
- significanceThreshold: real("significance_threshold").notNull().default(0.05),
3149
- minRuntimeDays: integer("min_runtime_days").notNull().default(0),
3150
- minSampleSize: integer("min_sample_size").notNull().default(100),
3151
- cupedFrozenAt: text("cuped_frozen_at"),
3152
- sequentialTesting: integer("sequential_testing", { mode: "boolean" }).notNull().default(false),
3153
- hashVersion: integer("hash_version").notNull().default(1),
3154
- updatedAt: text("updated_at").notNull()
3155
- },
3156
- (t) => ({
3157
- projectIdx: index("experiments_project").on(t.projectId),
3158
- projectUniq: uniqueIndex("experiments_project_name").on(t.projectId, t.name)
3159
- })
3160
- );
3161
- var events = sqliteTable(
3162
- "events",
3163
- {
3164
- id: text("id").primaryKey(),
3165
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3166
- name: text("name").notNull(),
3167
- description: text("description"),
3168
- properties: text("properties", { mode: "json" }).$type().notNull().default([]),
3169
- pending: integer("pending").notNull().default(0),
3170
- createdAt: text("created_at").notNull(),
3171
- deletedAt: text("deleted_at")
3172
- },
3173
- (t) => ({
3174
- projectIdx: index("events_project").on(t.projectId),
3175
- projectUniq: uniqueIndex("events_project_name").on(t.projectId, t.name).where(sql`deleted_at is null`)
3176
- })
3177
- );
3178
- var metrics = sqliteTable(
3179
- "metrics",
3180
- {
3181
- id: text("id").primaryKey(),
3182
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3183
- name: text("name").notNull(),
3184
- eventName: text("event_name").notNull(),
3185
- valuePath: text("value_path"),
3186
- aggregation: text("aggregation", {
3187
- enum: ["count_users", "count_events", "sum", "avg", "retention_Nd"]
3188
- }).notNull().default("count_users"),
3189
- winsorizePct: integer("winsorize_pct").notNull().default(99),
3190
- minDetectableEffect: real("min_detectable_effect"),
3191
- updatedAt: text("updated_at").notNull(),
3192
- deletedAt: text("deleted_at")
3193
- },
3194
- (t) => ({
3195
- uniq: uniqueIndex("metrics_project_name").on(t.projectId, t.name).where(sql`deleted_at is null`)
3196
- })
3197
- );
3198
- var experimentMetrics = sqliteTable(
3199
- "experiment_metrics",
3200
- {
3201
- id: text("id").primaryKey(),
3202
- experimentId: text("experiment_id").notNull().references(() => experiments.id, { onDelete: "cascade" }),
3203
- metricId: text("metric_id").notNull().references(() => metrics.id, { onDelete: "cascade" }),
3204
- role: text("role", { enum: ["goal", "guardrail", "secondary"] }).notNull(),
3205
- createdAt: integer("created_at").notNull()
3206
- },
3207
- (t) => ({ uniq: uniqueIndex("exp_metrics_uniq").on(t.experimentId, t.metricId) })
3208
- );
3209
- var experimentResults = sqliteTable(
3210
- "experiment_results",
3211
- {
3212
- projectId: text("project_id").notNull(),
3213
- experiment: text("experiment").notNull(),
3214
- metric: text("metric").notNull(),
3215
- groupName: text("group_name").notNull(),
3216
- ds: text("ds").notNull(),
3217
- n: integer("n"),
3218
- mean: real("mean"),
3219
- variance: real("variance"),
3220
- delta: real("delta"),
3221
- deltaPct: real("delta_pct"),
3222
- ci95Low: real("ci_95_low"),
3223
- ci95High: real("ci_95_high"),
3224
- ci99Low: real("ci_99_low"),
3225
- ci99High: real("ci_99_high"),
3226
- pValue: real("p_value"),
3227
- expectedN: integer("expected_n"),
3228
- srmPValue: real("srm_p_value"),
3229
- srmDetected: integer("srm_detected").notNull().default(0),
3230
- msprtLambda: real("msprt_lambda"),
3231
- msprtSignificant: integer("msprt_significant"),
3232
- isFinal: integer("is_final").notNull().default(0),
3233
- peekWarning: integer("peek_warning").notNull().default(0)
3234
- },
3235
- (t) => ({
3236
- pk: primaryKey({ columns: [t.projectId, t.experiment, t.metric, t.groupName, t.ds] }),
3237
- dsIdx: index("experiment_results_ds").on(t.projectId, t.ds)
3238
- })
3239
- );
3240
- var userMetricBaseline = sqliteTable(
3241
- "user_metric_baseline",
3242
- {
3243
- projectId: text("project_id").notNull(),
3244
- userId: text("user_id").notNull(),
3245
- metricName: text("metric_name").notNull(),
3246
- avgValue: real("avg_value").notNull(),
3247
- updatedDs: text("updated_ds").notNull()
3248
- },
3249
- (t) => ({ pk: primaryKey({ columns: [t.projectId, t.userId, t.metricName] }) })
3250
- );
3251
- var userAliases = sqliteTable(
3252
- "user_aliases",
3253
- {
3254
- projectId: text("project_id").notNull(),
3255
- anonymousId: text("anonymous_id").notNull(),
3256
- userId: text("user_id").notNull(),
3257
- createdAt: text("created_at").notNull()
3258
- },
3259
- (t) => ({
3260
- pk: primaryKey({ columns: [t.projectId, t.anonymousId] }),
3261
- userIdx: index("user_aliases_user").on(t.projectId, t.userId)
3262
- })
3263
- );
3264
- var userAttributes = sqliteTable(
3265
- "user_attributes",
3266
- {
3267
- id: text("id").primaryKey(),
3268
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3269
- name: text("name").notNull(),
3270
- type: text("type", { enum: ["string", "number", "boolean", "enum", "date"] }).notNull(),
3271
- enumValues: text("enum_values", { mode: "json" }).$type(),
3272
- required: integer("required").notNull().default(0),
3273
- description: text("description"),
3274
- sdkPath: text("sdk_path"),
3275
- createdAt: text("created_at").notNull(),
3276
- deletedAt: text("deleted_at")
3277
- },
3278
- (t) => ({
3279
- projectIdx: index("user_attributes_project").on(t.projectId),
3280
- projectUniq: uniqueIndex("user_attributes_project_name").on(t.projectId, t.name).where(sql`deleted_at is null`)
3281
- })
3282
- );
3283
- var labelProfiles = sqliteTable(
3284
- "label_profiles",
3285
- {
3286
- id: text("id").primaryKey(),
3287
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3288
- name: text("name").notNull(),
3289
- defaultChunkId: text("default_chunk_id"),
3290
- createdAt: text("created_at").notNull(),
3291
- deletedAt: text("deleted_at")
3292
- },
3293
- (t) => ({
3294
- projectIdx: index("label_profiles_project").on(t.projectId),
3295
- projectNameUniq: uniqueIndex("label_profiles_project_name").on(t.projectId, t.name).where(sql`deleted_at is null`)
3296
- })
3297
- );
3298
- var labelChunks = sqliteTable(
3299
- "label_chunks",
3300
- {
3301
- id: text("id").primaryKey(),
3302
- projectId: text("project_id").notNull(),
3303
- profileId: text("profile_id").notNull().references(() => labelProfiles.id, { onDelete: "cascade" }),
3304
- name: text("name").notNull(),
3305
- isIndex: integer("is_index").notNull().default(0),
3306
- publishedUrl: text("published_url"),
3307
- publishedHash: text("published_hash"),
3308
- publishedAt: text("published_at"),
3309
- etag: text("etag")
3310
- },
3311
- (t) => ({
3312
- projectIdx: index("label_chunks_project").on(t.projectId),
3313
- profileNameUniq: uniqueIndex("label_chunks_profile_name").on(t.profileId, t.name)
3314
- })
3315
- );
3316
- var labelKeys = sqliteTable(
3317
- "label_keys",
3318
- {
3319
- id: text("id").primaryKey(),
3320
- projectId: text("project_id").notNull(),
3321
- profileId: text("profile_id").notNull().references(() => labelProfiles.id, { onDelete: "cascade" }),
3322
- chunkId: text("chunk_id").notNull().references(() => labelChunks.id, { onDelete: "cascade" }),
3323
- key: text("key").notNull(),
3324
- value: text("value").notNull(),
3325
- description: text("description"),
3326
- // JSON array of variable names extracted from the value's {{var}} placeholders.
3327
- // `null` = no variables detected; `[]` = explicitly none (normalized).
3328
- variables: text("variables", { mode: "json" }).$type(),
3329
- updatedAt: text("updated_at").notNull(),
3330
- updatedBy: text("updated_by").notNull()
3331
- },
3332
- (t) => ({
3333
- projectIdx: index("label_keys_project").on(t.projectId),
3334
- chunkIdx: index("label_keys_chunk").on(t.chunkId),
3335
- profileKeyUniq: uniqueIndex("label_keys_profile_key").on(t.profileId, t.key)
3336
- })
3337
- );
3338
- var labelDrafts = sqliteTable(
3339
- "label_drafts",
3340
- {
3341
- id: text("id").primaryKey(),
3342
- projectId: text("project_id").notNull(),
3343
- profileId: text("profile_id").notNull().references(() => labelProfiles.id, { onDelete: "cascade" }),
3344
- name: text("name").notNull(),
3345
- sourceProfileId: text("source_profile_id").references(() => labelProfiles.id, {
3346
- onDelete: "set null"
3347
- }),
3348
- createdBy: text("created_by").notNull(),
3349
- status: text("status", { enum: ["open", "merged", "abandoned"] }).notNull().default("open"),
3350
- createdAt: text("created_at").notNull(),
3351
- publishedAt: text("published_at")
3352
- },
3353
- (t) => ({
3354
- projectIdx: index("label_drafts_project").on(t.projectId),
3355
- projectNameUniq: uniqueIndex("label_drafts_project_name").on(t.projectId, t.name)
3356
- })
3357
- );
3358
- var labelDraftKeys = sqliteTable(
3359
- "label_draft_keys",
3360
- {
3361
- id: text("id").primaryKey(),
3362
- projectId: text("project_id").notNull(),
3363
- draftId: text("draft_id").notNull().references(() => labelDrafts.id, { onDelete: "cascade" }),
3364
- key: text("key").notNull(),
3365
- value: text("value").notNull(),
3366
- description: text("description"),
3367
- variables: text("variables", { mode: "json" }).$type(),
3368
- updatedBy: text("updated_by").notNull(),
3369
- updatedAt: text("updated_at").notNull()
3370
- },
3371
- (t) => ({
3372
- draftKeyUniq: uniqueIndex("label_draft_keys_draft_key").on(t.draftId, t.key),
3373
- projectIdx: index("label_draft_keys_project").on(t.projectId)
3374
- })
3375
- );
3376
- var BUG_STATUSES = ["open", "triaged", "in_progress", "resolved", "wont_fix"];
3377
- var BUG_PRIORITIES = ["low", "medium", "high", "critical"];
3378
- var bugReports = sqliteTable(
3379
- "bug_reports",
3380
- {
3381
- id: text("id").primaryKey(),
3382
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3383
- title: text("title").notNull(),
3384
- stepsToReproduce: text("steps_to_reproduce").notNull().default(""),
3385
- actualResult: text("actual_result").notNull().default(""),
3386
- expectedResult: text("expected_result").notNull().default(""),
3387
- status: text("status", { enum: BUG_STATUSES }).notNull().default("open"),
3388
- priority: text("priority", { enum: BUG_PRIORITIES }),
3389
- reporterEmail: text("reporter_email"),
3390
- pageUrl: text("page_url"),
3391
- userAgent: text("user_agent"),
3392
- viewport: text("viewport"),
3393
- context: text("context", { mode: "json" }).$type(),
3394
- createdAt: text("created_at").notNull(),
3395
- updatedAt: text("updated_at").notNull()
3396
- },
3397
- (t) => ({
3398
- projectIdx: index("bug_reports_project").on(t.projectId, t.status),
3399
- createdIdx: index("bug_reports_created").on(t.projectId, t.createdAt)
3400
- })
3401
- );
3402
- var FEATURE_REQUEST_STATUSES = [
3403
- "open",
3404
- "considering",
3405
- "planned",
3406
- "shipped",
3407
- "declined"
3408
- ];
3409
- var FEATURE_REQUEST_IMPORTANCES = ["nice_to_have", "important", "critical"];
3410
- var featureRequests = sqliteTable(
3411
- "feature_requests",
3412
- {
3413
- id: text("id").primaryKey(),
3414
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3415
- title: text("title").notNull(),
3416
- description: text("description").notNull().default(""),
3417
- useCase: text("use_case").notNull().default(""),
3418
- importance: text("importance", { enum: FEATURE_REQUEST_IMPORTANCES }).notNull().default("nice_to_have"),
3419
- status: text("status", { enum: FEATURE_REQUEST_STATUSES }).notNull().default("open"),
3420
- reporterEmail: text("reporter_email"),
3421
- pageUrl: text("page_url"),
3422
- userAgent: text("user_agent"),
3423
- context: text("context", { mode: "json" }).$type(),
3424
- createdAt: text("created_at").notNull(),
3425
- updatedAt: text("updated_at").notNull()
3426
- },
3427
- (t) => ({
3428
- projectIdx: index("feature_requests_project").on(t.projectId, t.status),
3429
- createdIdx: index("feature_requests_created").on(t.projectId, t.createdAt)
3430
- })
3431
- );
3432
- var REPORT_KINDS = ["bug", "feature_request"];
3433
- var ATTACHMENT_KINDS = ["screenshot", "recording", "file"];
3434
- var reportAttachments = sqliteTable(
3435
- "report_attachments",
3436
- {
3437
- id: text("id").primaryKey(),
3438
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3439
- reportKind: text("report_kind", { enum: REPORT_KINDS }).notNull(),
3440
- reportId: text("report_id").notNull(),
3441
- kind: text("kind", { enum: ATTACHMENT_KINDS }).notNull(),
3442
- filename: text("filename").notNull(),
3443
- mimeType: text("mime_type").notNull(),
3444
- sizeBytes: integer("size_bytes").notNull(),
3445
- r2Key: text("r2_key").notNull(),
3446
- createdAt: text("created_at").notNull()
3447
- },
3448
- (t) => ({
3449
- reportIdx: index("report_attachments_report").on(t.projectId, t.reportKind, t.reportId)
3450
- })
3451
- );
3452
- var CONNECTOR_PROVIDERS = ["google_sheets"];
3453
- var connectors = sqliteTable(
3454
- "connectors",
3455
- {
3456
- id: text("id").primaryKey(),
3457
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
3458
- provider: text("provider", { enum: CONNECTOR_PROVIDERS }).notNull(),
3459
- name: text("name").notNull(),
3460
- enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
3461
- events: text("events", { mode: "json" }).$type().notNull(),
3462
- config: text("config", { mode: "json" }).$type().notNull(),
3463
- // AES-GCM encrypted JSON: { refresh_token, access_token, expires_at, scope }
3464
- credentialsCipher: text("credentials_cipher"),
3465
- // Display label (e.g., the OAuth account email)
3466
- accountLabel: text("account_label"),
3467
- createdAt: text("created_at").notNull(),
3468
- updatedAt: text("updated_at").notNull()
3469
- },
3470
- (t) => ({
3471
- projectIdx: index("connectors_project").on(t.projectId, t.provider)
3472
- })
3473
- );
3474
- var i18nUsageDaily = sqliteTable(
3475
- "i18n_usage_daily",
3476
- {
3477
- projectId: text("project_id").notNull(),
3478
- sdkKeyId: text("sdk_key_id").notNull(),
3479
- date: text("date").notNull(),
3480
- requestCount: integer("request_count").notNull().default(0)
3481
- },
3482
- (t) => ({
3483
- pk: primaryKey({ columns: [t.projectId, t.sdkKeyId, t.date] }),
3484
- projectDateIdx: index("i18n_usage_daily_project_date").on(t.projectId, t.date)
3485
- })
3486
- );
3487
- var billingEvents = sqliteTable(
3488
- "billing_events",
3489
- {
3490
- // Stripe event ID — INSERT OR IGNORE makes webhook handling idempotent
3491
- id: text("id").primaryKey(),
3492
- projectId: text("project_id").references(() => projects.id, { onDelete: "set null" }),
3493
- type: text("type").notNull(),
3494
- payload: text("payload", { mode: "json" }).$type().notNull(),
3495
- receivedAt: text("received_at").notNull()
3496
- },
3497
- (t) => ({
3498
- projectIdx: index("billing_events_project").on(t.projectId)
3499
- })
3500
- );
3501
1264
 
3502
- // ../core/src/schemas/configs.ts
1265
+ // src/schemas/configs.ts
3503
1266
  var SEGMENT = /^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$/;
3504
1267
  var RESERVED_FOLDER = "_default";
3505
- var configNameSchema = z6.string().max(128).refine(
1268
+ var configNameSchema = z8.string().max(128).refine(
3506
1269
  (s) => {
3507
1270
  const parts = s.split(".");
3508
1271
  if (parts.length !== 2) return false;
@@ -3514,95 +1277,97 @@ var configNameSchema = z6.string().max(128).refine(
3514
1277
  ).describe(
3515
1278
  "Stable config key in `folder.name` form (two lowercase segments separated by a dot, e.g. `pricing.tiers`). Used by SDKs as `Shipeasy.getConfig('<name>')`. Immutable after create."
3516
1279
  );
3517
- var configKindSchema = z6.enum(CONFIG_KINDS);
3518
- var configEnvSchema = z6.enum(CONFIG_ENVS).describe("Target environment. One of the project's configured envs (`dev`, `stage`, `prod`).");
3519
- var jsonSchemaSchema = z6.record(z6.string(), z6.unknown()).refine((s) => s.type === "object", { message: "Top-level schema type must be 'object'" }).describe(
1280
+ var configKindSchema = z8.enum(CONFIG_KINDS);
1281
+ var configEnvSchema = z8.enum(CONFIG_ENVS).describe("Target environment. One of the project's configured envs (`dev`, `stage`, `prod`).");
1282
+ var jsonSchemaSchema = z8.record(z8.string(), z8.unknown()).refine((s) => s.type === "object", { message: "Top-level schema type must be 'object'" }).describe(
3520
1283
  "JSON Schema (draft 2020-12) describing the shape of the config value. Top-level `type` must be `'object'`; every published value is validated against this schema."
3521
1284
  );
3522
- var initialValuesSchema = z6.union([z6.unknown(), z6.record(configEnvSchema, z6.unknown())]).describe(
1285
+ var initialValuesSchema = z8.union([z8.unknown(), z8.record(configEnvSchema, z8.unknown())]).describe(
3523
1286
  "Initial config value. Either a single JSON object applied to every env, or a `{ env: value }` map seeding per-env values. Must match `schema`. Defaults to `{}` on every env when omitted."
3524
1287
  );
3525
- var configCreateSchema = z6.object({
1288
+ var configCreateSchema = z8.object({
3526
1289
  name: configNameSchema,
3527
- description: z6.string().max(512).optional().describe("Optional free-form description shown in the dashboard. Max 512 chars."),
1290
+ description: z8.string().max(512).optional().describe("Optional free-form description shown in the dashboard. Max 512 chars."),
1291
+ folder: folderSchema,
3528
1292
  schema: jsonSchemaSchema,
3529
1293
  value: initialValuesSchema.optional()
3530
1294
  }).describe("Body for `POST /api/admin/configs`. `name` + `schema` required.");
3531
- var configUpdateSchema = z6.object({
1295
+ var configUpdateSchema = z8.object({
3532
1296
  schema: jsonSchemaSchema.optional().describe(
3533
1297
  "Replacement schema. When supplied, the new schema is validated against every published value before it lands."
3534
1298
  ),
3535
- value: z6.unknown().optional().describe(
1299
+ value: z8.unknown().optional().describe(
3536
1300
  "Flat value applied to **every** env. Publishes a new version per env. To target one env, use `PUT /{id}/drafts` then `POST /{id}/publish`."
3537
- )
1301
+ ),
1302
+ folder: folderSchema
3538
1303
  }).describe(
3539
1304
  "Body for `PATCH /api/admin/configs/{id}`. Partial \u2014 only supplied fields change. `value` republishes on every env."
3540
1305
  );
3541
- var configSchemaUpdateSchema = z6.object({ schema: jsonSchemaSchema }).describe("Schema-only update. Does not bump value versions or rebuild KV.");
3542
- var configDraftUpsertSchema = z6.object({
1306
+ var configSchemaUpdateSchema = z8.object({ schema: jsonSchemaSchema }).describe("Schema-only update. Does not bump value versions or rebuild KV.");
1307
+ var configDraftUpsertSchema = z8.object({
3543
1308
  env: configEnvSchema,
3544
- value: z6.unknown().describe("Draft value to stage on `env`. Validated against the config's current schema.")
1309
+ value: z8.unknown().describe("Draft value to stage on `env`. Validated against the config's current schema.")
3545
1310
  }).describe(
3546
1311
  "Body for `PUT /api/admin/configs/{id}/drafts`. Stages a value for a single env without publishing."
3547
1312
  );
3548
- var configPublishSchema = z6.object({ env: configEnvSchema }).describe(
1313
+ var configPublishSchema = z8.object({ env: configEnvSchema }).describe(
3549
1314
  "Body for `POST /api/admin/configs/{id}/publish` and `DELETE /api/admin/configs/{id}/drafts`. Names the target env."
3550
1315
  );
3551
- var configEnvPublishedSchema = z6.object({
3552
- version: z6.number().int().describe("Monotonically increasing version per env."),
3553
- publishedAt: z6.string().describe("ISO-8601 publish timestamp."),
3554
- publishedBy: z6.string().describe("Email/id of the actor who published this version.")
1316
+ var configEnvPublishedSchema = z8.object({
1317
+ version: z8.number().int().describe("Monotonically increasing version per env."),
1318
+ publishedAt: z8.string().describe("ISO-8601 publish timestamp."),
1319
+ publishedBy: z8.string().describe("Email/id of the actor who published this version.")
3555
1320
  });
3556
- var configDraftSummarySchema = z6.object({
3557
- updatedAt: z6.string().describe("ISO-8601 last-edit timestamp on the draft."),
3558
- authorEmail: z6.string().describe("Email/id of the actor who last edited the draft."),
3559
- baseVersion: z6.number().int().describe("Published version the draft was forked from.")
1321
+ var configDraftSummarySchema = z8.object({
1322
+ updatedAt: z8.string().describe("ISO-8601 last-edit timestamp on the draft."),
1323
+ authorEmail: z8.string().describe("Email/id of the actor who last edited the draft."),
1324
+ baseVersion: z8.number().int().describe("Published version the draft was forked from.")
3560
1325
  });
3561
- var configResponseSchema = z6.object({
3562
- id: z6.string().describe("Stable opaque config id (`cfg_\u2026`)."),
1326
+ var configResponseSchema = z8.object({
1327
+ id: z8.string().describe("Stable opaque config id (`cfg_\u2026`)."),
3563
1328
  name: configNameSchema,
3564
- description: z6.string().nullable(),
1329
+ description: z8.string().nullable(),
3565
1330
  schema: jsonSchemaSchema,
3566
- updatedAt: z6.string().describe("ISO-8601 timestamp of last mutation."),
3567
- envs: z6.record(configEnvSchema, configEnvPublishedSchema).describe("Per-env latest published version metadata."),
3568
- drafts: z6.record(configEnvSchema, configDraftSummarySchema).describe("Per-env active drafts (if any)."),
3569
- values: z6.record(configEnvSchema, z6.unknown()).optional().describe("Per-env latest published values (only returned by `GET /{id}`, not list)."),
3570
- draftValues: z6.record(configEnvSchema, z6.unknown()).optional().describe("Per-env draft values (only returned by `GET /{id}`).")
1331
+ updatedAt: z8.string().describe("ISO-8601 timestamp of last mutation."),
1332
+ envs: z8.record(configEnvSchema, configEnvPublishedSchema).describe("Per-env latest published version metadata."),
1333
+ drafts: z8.record(configEnvSchema, configDraftSummarySchema).describe("Per-env active drafts (if any)."),
1334
+ values: z8.record(configEnvSchema, z8.unknown()).optional().describe("Per-env latest published values (only returned by `GET /{id}`, not list)."),
1335
+ draftValues: z8.record(configEnvSchema, z8.unknown()).optional().describe("Per-env draft values (only returned by `GET /{id}`).")
3571
1336
  });
3572
- var configCreateResponseSchema = z6.object({
3573
- id: z6.string().describe("Newly assigned config id."),
1337
+ var configCreateResponseSchema = z8.object({
1338
+ id: z8.string().describe("Newly assigned config id."),
3574
1339
  name: configNameSchema
3575
1340
  });
3576
- var configUpdateResponseSchema = z6.object({
3577
- id: z6.string().describe("Config id that was updated.")
1341
+ var configUpdateResponseSchema = z8.object({
1342
+ id: z8.string().describe("Config id that was updated.")
3578
1343
  });
3579
- var configDeleteResponseSchema = z6.object({ ok: z6.literal(true) });
3580
- var configDraftSaveResponseSchema = z6.object({
3581
- id: z6.string(),
1344
+ var configDeleteResponseSchema = z8.object({ ok: z8.literal(true) });
1345
+ var configDraftSaveResponseSchema = z8.object({
1346
+ id: z8.string(),
3582
1347
  env: configEnvSchema,
3583
- baseVersion: z6.number().int().describe("Published version the draft is based on."),
3584
- updatedAt: z6.string()
1348
+ baseVersion: z8.number().int().describe("Published version the draft is based on."),
1349
+ updatedAt: z8.string()
3585
1350
  });
3586
- var configDraftDiscardResponseSchema = z6.object({ ok: z6.literal(true) });
3587
- var configPublishResponseSchema = z6.object({
3588
- id: z6.string(),
1351
+ var configDraftDiscardResponseSchema = z8.object({ ok: z8.literal(true) });
1352
+ var configPublishResponseSchema = z8.object({
1353
+ id: z8.string(),
3589
1354
  env: configEnvSchema,
3590
- version: z6.number().int().describe("Newly published version on `env`.")
1355
+ version: z8.number().int().describe("Newly published version on `env`.")
3591
1356
  });
3592
- var configActivityEntrySchema = z6.object({
3593
- id: z6.string(),
3594
- action: z6.string().describe("Audit action (e.g. `config.create`, `config.publish`)."),
3595
- actorEmail: z6.string(),
3596
- actorType: z6.enum(["user", "cli", "system"]),
3597
- payload: z6.unknown().nullable(),
3598
- createdAt: z6.string().describe("ISO-8601 timestamp.")
1357
+ var configActivityEntrySchema = z8.object({
1358
+ id: z8.string(),
1359
+ action: z8.string().describe("Audit action (e.g. `config.create`, `config.publish`)."),
1360
+ actorEmail: z8.string(),
1361
+ actorType: z8.enum(["user", "cli", "system"]),
1362
+ payload: z8.unknown().nullable(),
1363
+ createdAt: z8.string().describe("ISO-8601 timestamp.")
3599
1364
  });
3600
- var configActivityResponseSchema = z6.array(configActivityEntrySchema).describe("Recent audit rows for one config, newest first.");
1365
+ var configActivityResponseSchema = z8.array(configActivityEntrySchema).describe("Recent audit rows for one config, newest first.");
3601
1366
 
3602
1367
  // src/resources/configs.ts
3603
- var configListResponseSchema = z7.object({
3604
- data: z7.array(configResponseSchema),
3605
- next_cursor: z7.string().nullable()
1368
+ var configListResponseSchema = z9.object({
1369
+ data: z9.array(configResponseSchema),
1370
+ next_cursor: z9.string().nullable()
3606
1371
  });
3607
1372
  var BASE3 = "/api/admin/configs";
3608
1373
  function configsClient(t) {
@@ -3955,7 +1720,7 @@ var configsResource = {
3955
1720
  pathParams: { id: "Stable opaque config id." },
3956
1721
  queryParams: {
3957
1722
  limit: {
3958
- schema: z7.coerce.number().int().min(1).max(100).default(20),
1723
+ schema: z9.coerce.number().int().min(1).max(100).default(20),
3959
1724
  description: "Max rows to return (1\u2013100). Defaults to 20."
3960
1725
  }
3961
1726
  },
@@ -3978,48 +1743,50 @@ var configsResource = {
3978
1743
  };
3979
1744
 
3980
1745
  // src/resources/universes.ts
3981
- import { z as z9 } from "zod";
1746
+ import { z as z11 } from "zod";
3982
1747
 
3983
- // ../core/src/schemas/universes.ts
3984
- import { z as z8 } from "zod";
3985
- var universeNameSchema = z8.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/).describe(
3986
- "Stable universe key referenced by experiments via `universe: '<name>'`. Lowercase letters, digits, `_` or `-`, max 64 chars. Immutable after create."
1748
+ // src/schemas/universes.ts
1749
+ import { z as z10 } from "zod";
1750
+ var universeNameSchema = z10.string().regex(/^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?)?$/).max(128).describe(
1751
+ "Stable universe key. Single segment or `folder.name`. Lowercase letters, digits, `_` or `-`; max 128 chars. Immutable after create."
3987
1752
  );
3988
- var holdoutRangeSchema = z8.tuple([z8.number().int().min(0).max(9999), z8.number().int().min(0).max(9999)]).refine(([lo, hi]) => lo <= hi, "lo must be <= hi").nullable().describe(
1753
+ var holdoutRangeSchema = z10.tuple([z10.number().int().min(0).max(9999), z10.number().int().min(0).max(9999)]).refine(([lo, hi]) => lo <= hi, "lo must be <= hi").nullable().describe(
3989
1754
  "Inclusive `[lo, hi]` bucket range (0\u20139999) reserved as the **holdout** \u2014 callers hashed into this slice are excluded from every experiment in the universe. `null` disables the holdout. Pro plan or higher required."
3990
1755
  );
3991
- var universeCreateSchema = z8.object({
1756
+ var universeCreateSchema = z10.object({
3992
1757
  name: universeNameSchema,
3993
- unit_type: z8.string().default("user_id").describe(
1758
+ folder: folderSchema,
1759
+ unit_type: z10.string().default("user_id").describe(
3994
1760
  "Unit of randomisation. Typically `user_id`. Use `account_id` to keep whole accounts in the same group across an experiment."
3995
1761
  ),
3996
1762
  holdout_range: holdoutRangeSchema.default(null)
3997
1763
  }).describe("Body for `POST /api/admin/universes`. Only `name` is required.");
3998
- var universeUpdateSchema = z8.object({
1764
+ var universeUpdateSchema = z10.object({
1765
+ folder: folderSchema,
3999
1766
  holdout_range: holdoutRangeSchema.optional()
4000
1767
  }).describe(
4001
1768
  "Body for `PATCH /api/admin/universes/{id}`. Only `holdout_range` is mutable \u2014 name and unit_type are immutable after create."
4002
1769
  );
4003
- var universeResponseSchema = z8.object({
4004
- id: z8.string().describe("Stable opaque universe id."),
1770
+ var universeResponseSchema = z10.object({
1771
+ id: z10.string().describe("Stable opaque universe id."),
4005
1772
  name: universeNameSchema,
4006
- unitType: z8.string().describe("Unit of randomisation. Snake-case in request (`unit_type`), camelCase in response."),
4007
- holdoutRange: z8.tuple([z8.number(), z8.number()]).nullable().describe("Reserved holdout bucket range, or `null` if none."),
4008
- createdAt: z8.string().describe("ISO-8601 timestamp of creation.")
1773
+ unitType: z10.string().describe("Unit of randomisation. Snake-case in request (`unit_type`), camelCase in response."),
1774
+ holdoutRange: z10.tuple([z10.number(), z10.number()]).nullable().describe("Reserved holdout bucket range, or `null` if none."),
1775
+ createdAt: z10.string().describe("ISO-8601 timestamp of creation.")
4009
1776
  });
4010
- var universeCreateResponseSchema = z8.object({
4011
- id: z8.string().describe("Newly assigned universe id."),
1777
+ var universeCreateResponseSchema = z10.object({
1778
+ id: z10.string().describe("Newly assigned universe id."),
4012
1779
  name: universeNameSchema
4013
1780
  });
4014
- var universeUpdateResponseSchema = z8.object({
4015
- id: z8.string().describe("Universe id that was updated.")
1781
+ var universeUpdateResponseSchema = z10.object({
1782
+ id: z10.string().describe("Universe id that was updated.")
4016
1783
  });
4017
- var universeDeleteResponseSchema = z8.object({ ok: z8.literal(true) });
1784
+ var universeDeleteResponseSchema = z10.object({ ok: z10.literal(true) });
4018
1785
 
4019
1786
  // src/resources/universes.ts
4020
- var universeListResponseSchema = z9.object({
4021
- data: z9.array(universeResponseSchema),
4022
- next_cursor: z9.string().nullable()
1787
+ var universeListResponseSchema = z11.object({
1788
+ data: z11.array(universeResponseSchema),
1789
+ next_cursor: z11.string().nullable()
4023
1790
  });
4024
1791
  var BASE4 = "/api/admin/universes";
4025
1792
  function universesClient(t) {
@@ -4189,97 +1956,106 @@ var universesResource = {
4189
1956
  };
4190
1957
 
4191
1958
  // src/resources/killswitches.ts
4192
- import { z as z11 } from "zod";
1959
+ import { z as z13 } from "zod";
4193
1960
 
4194
- // ../core/src/schemas/killswitches.ts
4195
- import { z as z10 } from "zod";
4196
- var switchKeySchema = z10.string().max(64).regex(/^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$/, {
1961
+ // src/schemas/killswitches.ts
1962
+ import { z as z12 } from "zod";
1963
+ var SWITCH_KEY_RE = /^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$/;
1964
+ var switchKeySchema = z12.string().max(64).regex(SWITCH_KEY_RE, {
4197
1965
  message: "Switch keys must be lowercase, no dots."
4198
1966
  }).describe(
4199
1967
  "Single-segment switch key (lowercase letters, digits, `_`/`-`; no dots). Used as the nested switch entry inside a killswitch's `switches` map."
4200
1968
  );
4201
- var killswitchValueSchema = z10.object({
4202
- value: z10.boolean().describe(
1969
+ var killswitchValueSchema = z12.object({
1970
+ value: z12.boolean().describe(
4203
1971
  "Default boolean delivered when no `switches` entry matches the caller's switch key."
4204
1972
  ),
4205
- switches: z10.record(switchKeySchema, z10.boolean()).optional().describe(
1973
+ switches: z12.record(switchKeySchema, z12.boolean()).optional().describe(
4206
1974
  "Per-switch overrides. When present, a matching key takes precedence over `value` on the client."
4207
1975
  )
4208
1976
  }).describe("Runtime killswitch payload returned to SDKs.");
4209
- var killswitchCreateSchema = z10.object({
1977
+ var killswitchCreateSchema = z12.object({
4210
1978
  name: configNameSchema.describe(
4211
1979
  "Stable killswitch key in `folder.name` form (two lowercase segments separated by a dot \u2014 e.g. `payments.checkout`). Immutable after create."
4212
1980
  ),
4213
- description: z10.string().max(512).optional().describe("Optional free-form description shown in the dashboard. Max 512 chars."),
4214
- value: z10.boolean().optional().describe(
1981
+ description: z12.string().max(512).optional().describe("Optional free-form description shown in the dashboard. Max 512 chars."),
1982
+ folder: folderSchema,
1983
+ value: z12.boolean().optional().describe(
4215
1984
  "Default value applied to every env at creation. Defaults to `false`. Use `true` to ship the killswitch pre-tripped."
4216
1985
  ),
4217
- switches: z10.record(switchKeySchema, z10.boolean()).optional().describe(
1986
+ switches: z12.record(switchKeySchema, z12.boolean()).optional().describe(
4218
1987
  "Initial per-switch overrides applied to every env. Empty/omitted leaves the killswitch with only the flat `value`."
4219
1988
  )
4220
1989
  }).describe("Body for `POST /api/admin/killswitches`. Only `name` is required.");
4221
- var killswitchUpdateSchema = z10.object({
4222
- description: z10.string().max(512).nullish().describe("New description, or `null` to clear it. Max 512 chars."),
4223
- value: z10.boolean().optional().describe(
1990
+ var killswitchUpdateSchema = z12.object({
1991
+ description: z12.string().max(512).nullish().describe("New description, or `null` to clear it. Max 512 chars."),
1992
+ folder: folderSchema,
1993
+ value: z12.boolean().optional().describe(
4224
1994
  "Flat value applied to every env. Publishes a new version per env when set. Omit to leave values unchanged."
4225
1995
  ),
4226
- switches: z10.record(switchKeySchema, z10.boolean()).optional().describe(
1996
+ switches: z12.record(switchKeySchema, z12.boolean()).optional().describe(
4227
1997
  "Replace the switches map wholesale on every env. To edit a single entry on a single env use `PUT /{id}/switch` instead."
4228
1998
  )
4229
1999
  }).describe(
4230
2000
  "Body for `PATCH /api/admin/killswitches/{id}`. Partial \u2014 only supplied fields change. `switches` replaces wholesale (no merge)."
4231
2001
  );
4232
- var killswitchSwitchSetSchema = z10.object({
2002
+ var killswitchSwitchSetSchema = z12.object({
4233
2003
  env: configEnvSchema.describe("Target environment (`dev`/`stage`/`prod`)."),
4234
2004
  switchKey: switchKeySchema.describe("Switch key to set."),
4235
- value: z10.boolean().describe("New boolean value for this `switchKey` on this `env`.")
2005
+ value: z12.boolean().describe("New boolean value for this `switchKey` on this `env`.")
4236
2006
  }).describe(
4237
2007
  "Body for `PUT /api/admin/killswitches/{id}/switch`. Sets or updates one switch entry on one env."
4238
2008
  );
4239
- var killswitchSwitchUnsetSchema = z10.object({
2009
+ var killswitchValueSetSchema = z12.object({
2010
+ env: configEnvSchema.describe("Target environment whose flat default flips."),
2011
+ value: z12.boolean().describe("New flat default for this env. Existing switches carry forward unchanged.")
2012
+ }).describe(
2013
+ "Body for the killswitch quick-toggle. Sets the flat `value` on one env without touching its switches."
2014
+ );
2015
+ var killswitchSwitchUnsetSchema = z12.object({
4240
2016
  env: configEnvSchema.describe("Target environment."),
4241
2017
  switchKey: switchKeySchema.describe("Switch key to remove.")
4242
2018
  }).describe(
4243
2019
  "Body for `DELETE /api/admin/killswitches/{id}/switch`. Removes one switch entry from one env."
4244
2020
  );
4245
- var killswitchEnvEntrySchema = z10.object({
4246
- value: z10.boolean().describe("Flat boolean published for this env."),
4247
- switches: z10.record(switchKeySchema, z10.boolean()).optional(),
4248
- version: z10.number().int().describe("Monotonically increasing version per env."),
4249
- publishedAt: z10.string().describe("ISO-8601 publish timestamp for this version.")
2021
+ var killswitchEnvEntrySchema = z12.object({
2022
+ value: z12.boolean().describe("Flat boolean published for this env."),
2023
+ switches: z12.record(switchKeySchema, z12.boolean()).optional(),
2024
+ version: z12.number().int().describe("Monotonically increasing version per env."),
2025
+ publishedAt: z12.string().describe("ISO-8601 publish timestamp for this version.")
4250
2026
  });
4251
- var killswitchResponseSchema = z10.object({
4252
- id: z10.string().describe("Stable opaque killswitch id."),
2027
+ var killswitchResponseSchema = z12.object({
2028
+ id: z12.string().describe("Stable opaque killswitch id."),
4253
2029
  name: configNameSchema,
4254
- description: z10.string().nullable().describe("Free-form description or `null`."),
4255
- updatedAt: z10.string().describe("ISO-8601 timestamp of last mutation."),
4256
- envs: z10.record(configEnvSchema, killswitchEnvEntrySchema).describe("Per-env latest value, switches, version, and publish timestamp.")
2030
+ description: z12.string().nullable().describe("Free-form description or `null`."),
2031
+ updatedAt: z12.string().describe("ISO-8601 timestamp of last mutation."),
2032
+ envs: z12.record(configEnvSchema, killswitchEnvEntrySchema).describe("Per-env latest value, switches, version, and publish timestamp.")
4257
2033
  });
4258
- var killswitchCreateResponseSchema = z10.object({
4259
- id: z10.string().describe("Newly assigned killswitch id."),
2034
+ var killswitchCreateResponseSchema = z12.object({
2035
+ id: z12.string().describe("Newly assigned killswitch id."),
4260
2036
  name: configNameSchema
4261
2037
  });
4262
- var killswitchUpdateResponseSchema = z10.object({
4263
- id: z10.string().describe("Killswitch id that was updated.")
2038
+ var killswitchUpdateResponseSchema = z12.object({
2039
+ id: z12.string().describe("Killswitch id that was updated.")
4264
2040
  });
4265
- var killswitchDeleteResponseSchema = z10.object({ ok: z10.literal(true) });
4266
- var killswitchSwitchSetResponseSchema = z10.object({
4267
- id: z10.string(),
2041
+ var killswitchDeleteResponseSchema = z12.object({ ok: z12.literal(true) });
2042
+ var killswitchSwitchSetResponseSchema = z12.object({
2043
+ id: z12.string(),
4268
2044
  env: configEnvSchema,
4269
2045
  switchKey: switchKeySchema,
4270
- value: z10.boolean()
2046
+ value: z12.boolean()
4271
2047
  });
4272
- var killswitchSwitchUnsetResponseSchema = z10.object({
4273
- id: z10.string(),
2048
+ var killswitchSwitchUnsetResponseSchema = z12.object({
2049
+ id: z12.string(),
4274
2050
  env: configEnvSchema,
4275
2051
  switchKey: switchKeySchema,
4276
- removed: z10.boolean().describe("`true` if the entry existed and was removed, `false` if no-op.")
2052
+ removed: z12.boolean().describe("`true` if the entry existed and was removed, `false` if no-op.")
4277
2053
  });
4278
2054
 
4279
2055
  // src/resources/killswitches.ts
4280
- var killswitchListResponseSchema = z11.object({
4281
- data: z11.array(killswitchResponseSchema),
4282
- next_cursor: z11.string().nullable()
2056
+ var killswitchListResponseSchema = z13.object({
2057
+ data: z13.array(killswitchResponseSchema),
2058
+ next_cursor: z13.string().nullable()
4283
2059
  });
4284
2060
  var BASE5 = "/api/admin/killswitches";
4285
2061
  function killswitchesClient(t) {
@@ -4563,6 +2339,60 @@ var killswitchesResource = {
4563
2339
  ]
4564
2340
  };
4565
2341
 
2342
+ // src/schemas/alert-rules.ts
2343
+ import { z as z14 } from "zod";
2344
+ var ALERT_COMPARATORS = ["gt", "gte", "lt", "lte"];
2345
+ var ALERT_SEVERITIES = ["danger", "warn", "info"];
2346
+ var alertRuleCreateSchema = z14.object({
2347
+ name: z14.string().min(1).max(120).describe("Human label for the rule, shown on the alert and the rules list."),
2348
+ metricId: z14.string().min(1).describe("Id of the metric to evaluate."),
2349
+ comparator: z14.enum(ALERT_COMPARATORS).describe("How the metric value is compared to the threshold (gt/gte/lt/lte)."),
2350
+ threshold: z14.number().finite().describe("Threshold the metric value is compared against."),
2351
+ windowHours: z14.number().int().min(1).max(720).default(24).describe("Lookback window (hours) the metric is aggregated over. 1\u2013720."),
2352
+ severity: z14.enum(ALERT_SEVERITIES).default("warn").describe("Severity of the raised alert."),
2353
+ enabled: z14.boolean().default(true).describe("Whether the rule is evaluated by the cron.")
2354
+ }).strict();
2355
+ var alertRuleUpdateSchema = z14.object({
2356
+ name: z14.string().min(1).max(120),
2357
+ comparator: z14.enum(ALERT_COMPARATORS),
2358
+ threshold: z14.number().finite(),
2359
+ windowHours: z14.number().int().min(1).max(720),
2360
+ severity: z14.enum(ALERT_SEVERITIES),
2361
+ enabled: z14.boolean()
2362
+ }).partial().strict();
2363
+
2364
+ // src/resources/alert-rules.ts
2365
+ var BASE6 = "/api/admin/alert-rules";
2366
+ function alertRulesClient(t) {
2367
+ async function list() {
2368
+ return t.request("GET", BASE6);
2369
+ }
2370
+ async function resolve(idOrName) {
2371
+ const all = await list();
2372
+ const byId = all.find((r) => r.id === idOrName);
2373
+ if (byId) return byId;
2374
+ const byPrefix = all.filter((r) => r.id.startsWith(idOrName));
2375
+ if (byPrefix.length === 1) return byPrefix[0];
2376
+ if (byPrefix.length > 1)
2377
+ throw new ApiError(`Alert rule id prefix '${idOrName}' is ambiguous`, 400);
2378
+ const byName = all.filter((r) => r.name === idOrName);
2379
+ if (byName.length === 1) return byName[0];
2380
+ if (byName.length > 1)
2381
+ throw new ApiError(
2382
+ `Alert rule name '${idOrName}' is ambiguous \u2014 pass an id instead`,
2383
+ 400
2384
+ );
2385
+ throw new ApiError(`Alert rule '${idOrName}' not found`, 404);
2386
+ }
2387
+ return {
2388
+ list,
2389
+ resolve,
2390
+ create: (input) => t.request("POST", BASE6, alertRuleCreateSchema.parse(input)),
2391
+ update: (id, input) => t.request("PATCH", `${BASE6}/${id}`, alertRuleUpdateSchema.parse(input)),
2392
+ delete: (id) => t.request("DELETE", `${BASE6}/${id}`)
2393
+ };
2394
+ }
2395
+
4566
2396
  // src/resources/index.ts
4567
2397
  function createAdminClient(transport) {
4568
2398
  return {
@@ -4571,7 +2401,8 @@ function createAdminClient(transport) {
4571
2401
  experiments: experimentsClient(transport),
4572
2402
  configs: configsClient(transport),
4573
2403
  universes: universesClient(transport),
4574
- killswitches: killswitchesClient(transport)
2404
+ killswitches: killswitchesClient(transport),
2405
+ alertRules: alertRulesClient(transport)
4575
2406
  };
4576
2407
  }
4577
2408
  var RESOURCE_REGISTRY = [
@@ -4586,6 +2417,7 @@ export {
4586
2417
  DEFAULT_PAGE_SIZE,
4587
2418
  MAX_PAGE_SIZE,
4588
2419
  RESOURCE_REGISTRY,
2420
+ alertRulesClient,
4589
2421
  configsClient,
4590
2422
  configsResource,
4591
2423
  createAdminClient,