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