@secondlayer/shared 2.1.0 → 3.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/src/db/index.d.ts +39 -137
- package/dist/src/db/index.js.map +2 -2
- package/dist/src/db/jsonb.d.ts +5 -1
- package/dist/src/db/jsonb.js.map +2 -2
- package/dist/src/db/queries/account-spend-caps.d.ts +379 -0
- package/dist/src/db/queries/account-spend-caps.js +60 -0
- package/dist/src/db/queries/account-spend-caps.js.map +10 -0
- package/dist/src/db/queries/account-usage.d.ts +403 -0
- package/dist/src/db/queries/account-usage.js +222 -0
- package/dist/src/db/queries/account-usage.js.map +11 -0
- package/dist/src/db/queries/accounts.d.ts +41 -115
- package/dist/src/db/queries/accounts.js +15 -1
- package/dist/src/db/queries/accounts.js.map +3 -3
- package/dist/src/db/queries/integrity.d.ts +27 -114
- package/dist/src/db/queries/projects.d.ts +27 -114
- package/dist/src/db/queries/provisioning-audit.d.ts +27 -114
- package/dist/src/db/queries/subgraph-gaps.d.ts +27 -114
- package/dist/src/db/queries/subgraphs.d.ts +27 -115
- package/dist/src/db/queries/subgraphs.js +2 -3
- package/dist/src/db/queries/subgraphs.js.map +4 -4
- package/dist/src/db/queries/{workflows.d.ts → tenant-compute-addons.d.ts} +50 -149
- package/dist/src/db/queries/tenant-compute-addons.js +47 -0
- package/dist/src/db/queries/tenant-compute-addons.js.map +10 -0
- package/dist/src/db/queries/tenants.d.ts +40 -117
- package/dist/src/db/queries/tenants.js +9 -6
- package/dist/src/db/queries/tenants.js.map +3 -3
- package/dist/src/db/queries/usage.d.ts +28 -139
- package/dist/src/db/queries/usage.js +5 -64
- package/dist/src/db/queries/usage.js.map +4 -5
- package/dist/src/db/schema.d.ts +34 -136
- package/dist/src/errors.d.ts +8 -7
- package/dist/src/errors.js +11 -12
- package/dist/src/errors.js.map +3 -3
- package/dist/src/index.d.ts +46 -143
- package/dist/src/index.js +11 -12
- package/dist/src/index.js.map +4 -4
- package/dist/src/node/local-client.d.ts +27 -114
- package/dist/src/pricing.d.ts +20 -1
- package/dist/src/pricing.js +58 -1
- package/dist/src/pricing.js.map +3 -3
- package/migrations/0045_drop_marketplace_columns.ts +47 -0
- package/migrations/0046_tenant_activity_signal.ts +47 -0
- package/migrations/0047_usage_daily_tenant_id.ts +73 -0
- package/migrations/0048_tenant_compute_addons.ts +49 -0
- package/migrations/0049_accounts_stripe_customer_id.ts +30 -0
- package/migrations/0050_account_spend_caps.ts +45 -0
- package/migrations/0051_workflow_ai_usage_daily.ts +40 -0
- package/migrations/0052_sentries.ts +61 -0
- package/migrations/0053_workflow_runtime.ts +88 -0
- package/migrations/0054_accounts_plan_hobby.ts +32 -0
- package/migrations/0055_ai_usage_account_scope.ts +108 -0
- package/migrations/0056_drop_workflow_sentry_residuals.ts +23 -0
- package/package.json +26 -14
- package/dist/src/db/queries/workflows.js +0 -260
- package/dist/src/db/queries/workflows.js.map +0 -12
- package/dist/src/lib/plans.d.ts +0 -9
- package/dist/src/lib/plans.js +0 -37
- package/dist/src/lib/plans.js.map +0 -10
- package/dist/src/schemas/workflows.d.ts +0 -70
- package/dist/src/schemas/workflows.js +0 -43
- package/dist/src/schemas/workflows.js.map +0 -10
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import { Kysely } from "kysely";
|
|
2
|
+
import { ColumnType, Generated, Selectable, Updateable } from "kysely";
|
|
3
|
+
interface BlocksTable {
|
|
4
|
+
height: number;
|
|
5
|
+
hash: string;
|
|
6
|
+
parent_hash: string;
|
|
7
|
+
burn_block_height: number;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
canonical: Generated<boolean>;
|
|
10
|
+
created_at: Generated<Date>;
|
|
11
|
+
}
|
|
12
|
+
interface TransactionsTable {
|
|
13
|
+
tx_id: string;
|
|
14
|
+
block_height: number;
|
|
15
|
+
tx_index: Generated<number>;
|
|
16
|
+
type: string;
|
|
17
|
+
sender: string;
|
|
18
|
+
status: string;
|
|
19
|
+
contract_id: string | null;
|
|
20
|
+
function_name: string | null;
|
|
21
|
+
function_args: Generated<unknown | null>;
|
|
22
|
+
raw_result: Generated<string | null>;
|
|
23
|
+
raw_tx: string;
|
|
24
|
+
created_at: Generated<Date>;
|
|
25
|
+
}
|
|
26
|
+
interface EventsTable {
|
|
27
|
+
id: Generated<string>;
|
|
28
|
+
tx_id: string;
|
|
29
|
+
block_height: number;
|
|
30
|
+
event_index: number;
|
|
31
|
+
type: string;
|
|
32
|
+
data: unknown;
|
|
33
|
+
created_at: Generated<Date>;
|
|
34
|
+
}
|
|
35
|
+
interface IndexProgressTable {
|
|
36
|
+
network: string;
|
|
37
|
+
last_indexed_block: Generated<number>;
|
|
38
|
+
last_contiguous_block: Generated<number>;
|
|
39
|
+
highest_seen_block: Generated<number>;
|
|
40
|
+
updated_at: Generated<Date>;
|
|
41
|
+
}
|
|
42
|
+
interface SubgraphsTable {
|
|
43
|
+
id: Generated<string>;
|
|
44
|
+
name: string;
|
|
45
|
+
version: Generated<string>;
|
|
46
|
+
status: Generated<string>;
|
|
47
|
+
definition: Record<string, unknown>;
|
|
48
|
+
schema_hash: string;
|
|
49
|
+
handler_path: string;
|
|
50
|
+
schema_name: string | null;
|
|
51
|
+
start_block: Generated<number>;
|
|
52
|
+
last_processed_block: Generated<number>;
|
|
53
|
+
reindex_from_block: number | null;
|
|
54
|
+
reindex_to_block: number | null;
|
|
55
|
+
last_error: string | null;
|
|
56
|
+
last_error_at: Date | null;
|
|
57
|
+
total_processed: Generated<number>;
|
|
58
|
+
total_errors: Generated<number>;
|
|
59
|
+
account_id: string;
|
|
60
|
+
handler_code: string | null;
|
|
61
|
+
source_code: string | null;
|
|
62
|
+
project_id: string | null;
|
|
63
|
+
created_at: Generated<Date>;
|
|
64
|
+
updated_at: Generated<Date>;
|
|
65
|
+
}
|
|
66
|
+
interface SubgraphGapsTable {
|
|
67
|
+
id: Generated<string>;
|
|
68
|
+
subgraph_id: string;
|
|
69
|
+
subgraph_name: string;
|
|
70
|
+
gap_start: number;
|
|
71
|
+
gap_end: number;
|
|
72
|
+
reason: string;
|
|
73
|
+
detected_at: Generated<Date>;
|
|
74
|
+
resolved_at: Date | null;
|
|
75
|
+
}
|
|
76
|
+
interface ApiKeysTable {
|
|
77
|
+
id: Generated<string>;
|
|
78
|
+
key_hash: string;
|
|
79
|
+
key_prefix: string;
|
|
80
|
+
name: string | null;
|
|
81
|
+
status: Generated<string>;
|
|
82
|
+
rate_limit: Generated<number>;
|
|
83
|
+
ip_address: string;
|
|
84
|
+
account_id: string;
|
|
85
|
+
last_used_at: Date | null;
|
|
86
|
+
revoked_at: Date | null;
|
|
87
|
+
created_at: Generated<Date>;
|
|
88
|
+
}
|
|
89
|
+
interface AccountsTable {
|
|
90
|
+
id: Generated<string>;
|
|
91
|
+
email: string;
|
|
92
|
+
plan: Generated<string>;
|
|
93
|
+
display_name: string | null;
|
|
94
|
+
bio: string | null;
|
|
95
|
+
avatar_url: string | null;
|
|
96
|
+
slug: string | null;
|
|
97
|
+
stripe_customer_id: string | null;
|
|
98
|
+
created_at: Generated<Date>;
|
|
99
|
+
}
|
|
100
|
+
interface SessionsTable {
|
|
101
|
+
id: Generated<string>;
|
|
102
|
+
token_hash: string;
|
|
103
|
+
token_prefix: string;
|
|
104
|
+
account_id: string;
|
|
105
|
+
ip_address: string;
|
|
106
|
+
expires_at: Generated<Date>;
|
|
107
|
+
revoked_at: Date | null;
|
|
108
|
+
last_used_at: Date | null;
|
|
109
|
+
created_at: Generated<Date>;
|
|
110
|
+
}
|
|
111
|
+
interface MagicLinksTable {
|
|
112
|
+
id: Generated<string>;
|
|
113
|
+
email: string;
|
|
114
|
+
token: string;
|
|
115
|
+
code: string | null;
|
|
116
|
+
expires_at: Date;
|
|
117
|
+
used_at: Date | null;
|
|
118
|
+
failed_attempts: Generated<number>;
|
|
119
|
+
created_at: Generated<Date>;
|
|
120
|
+
}
|
|
121
|
+
interface UsageDailyTable {
|
|
122
|
+
account_id: string;
|
|
123
|
+
tenant_id: string | null;
|
|
124
|
+
date: string;
|
|
125
|
+
api_requests: Generated<number>;
|
|
126
|
+
deliveries: Generated<number>;
|
|
127
|
+
}
|
|
128
|
+
interface UsageSnapshotsTable {
|
|
129
|
+
id: Generated<string>;
|
|
130
|
+
account_id: string;
|
|
131
|
+
measured_at: Generated<Date>;
|
|
132
|
+
storage_bytes: Generated<number>;
|
|
133
|
+
}
|
|
134
|
+
interface WaitlistTable {
|
|
135
|
+
id: Generated<string>;
|
|
136
|
+
email: string;
|
|
137
|
+
source: Generated<string>;
|
|
138
|
+
status: Generated<string>;
|
|
139
|
+
created_at: Generated<Date>;
|
|
140
|
+
}
|
|
141
|
+
interface AccountInsightsTable {
|
|
142
|
+
id: Generated<string>;
|
|
143
|
+
account_id: string;
|
|
144
|
+
category: string;
|
|
145
|
+
insight_type: string;
|
|
146
|
+
resource_id: string | null;
|
|
147
|
+
severity: string;
|
|
148
|
+
title: string;
|
|
149
|
+
body: string;
|
|
150
|
+
data: unknown;
|
|
151
|
+
dismissed_at: Date | null;
|
|
152
|
+
expires_at: Date | null;
|
|
153
|
+
created_at: Generated<Date>;
|
|
154
|
+
}
|
|
155
|
+
interface AccountAgentRunsTable {
|
|
156
|
+
id: Generated<string>;
|
|
157
|
+
account_id: string;
|
|
158
|
+
started_at: Generated<Date>;
|
|
159
|
+
completed_at: Date | null;
|
|
160
|
+
status: Generated<string>;
|
|
161
|
+
input_tokens: Generated<number>;
|
|
162
|
+
output_tokens: Generated<number>;
|
|
163
|
+
cost_usd: Generated<number>;
|
|
164
|
+
insights_created: Generated<number>;
|
|
165
|
+
error: string | null;
|
|
166
|
+
}
|
|
167
|
+
interface SubgraphProcessingStatsTable {
|
|
168
|
+
id: Generated<string>;
|
|
169
|
+
subgraph_name: string;
|
|
170
|
+
api_key_id: string | null;
|
|
171
|
+
bucket_start: Date | null;
|
|
172
|
+
bucket_end: Date | null;
|
|
173
|
+
blocks_processed: number | null;
|
|
174
|
+
total_time_ms: number | null;
|
|
175
|
+
handler_time_ms: number | null;
|
|
176
|
+
flush_time_ms: number | null;
|
|
177
|
+
max_block_time_ms: number | null;
|
|
178
|
+
max_handler_time_ms: number | null;
|
|
179
|
+
avg_ops_per_block: number | null;
|
|
180
|
+
is_catchup: Generated<boolean>;
|
|
181
|
+
created_at: Generated<Date>;
|
|
182
|
+
}
|
|
183
|
+
interface SubgraphTableSnapshotsTable {
|
|
184
|
+
id: Generated<string>;
|
|
185
|
+
subgraph_name: string;
|
|
186
|
+
api_key_id: string | null;
|
|
187
|
+
table_name: string;
|
|
188
|
+
row_count: number | null;
|
|
189
|
+
created_at: Generated<Date>;
|
|
190
|
+
}
|
|
191
|
+
interface SubgraphHealthSnapshotsTable {
|
|
192
|
+
id: Generated<string>;
|
|
193
|
+
subgraph_id: string;
|
|
194
|
+
total_processed: number;
|
|
195
|
+
total_errors: number;
|
|
196
|
+
last_processed_block: number | null;
|
|
197
|
+
captured_at: Generated<Date>;
|
|
198
|
+
}
|
|
199
|
+
interface SubgraphUsageDailyTable {
|
|
200
|
+
subgraph_id: string;
|
|
201
|
+
date: string;
|
|
202
|
+
query_count: Generated<number>;
|
|
203
|
+
}
|
|
204
|
+
interface ProjectsTable {
|
|
205
|
+
id: Generated<string>;
|
|
206
|
+
name: string;
|
|
207
|
+
slug: string;
|
|
208
|
+
account_id: string;
|
|
209
|
+
settings: Generated<Record<string, unknown>>;
|
|
210
|
+
network: Generated<string>;
|
|
211
|
+
node_rpc: string | null;
|
|
212
|
+
created_at: Generated<Date>;
|
|
213
|
+
updated_at: Generated<Date>;
|
|
214
|
+
}
|
|
215
|
+
interface TeamMembersTable {
|
|
216
|
+
id: Generated<string>;
|
|
217
|
+
project_id: string;
|
|
218
|
+
account_id: string;
|
|
219
|
+
role: Generated<string>;
|
|
220
|
+
invited_by: string | null;
|
|
221
|
+
created_at: Generated<Date>;
|
|
222
|
+
}
|
|
223
|
+
interface TeamInvitationsTable {
|
|
224
|
+
id: Generated<string>;
|
|
225
|
+
project_id: string;
|
|
226
|
+
email: string;
|
|
227
|
+
role: Generated<string>;
|
|
228
|
+
token: string;
|
|
229
|
+
invited_by: string | null;
|
|
230
|
+
expires_at: Date;
|
|
231
|
+
accepted_at: Date | null;
|
|
232
|
+
created_at: Generated<Date>;
|
|
233
|
+
}
|
|
234
|
+
interface ChatSessionsTable {
|
|
235
|
+
id: Generated<string>;
|
|
236
|
+
account_id: string;
|
|
237
|
+
title: string | null;
|
|
238
|
+
summary: unknown | null;
|
|
239
|
+
created_at: Generated<Date>;
|
|
240
|
+
updated_at: Generated<Date>;
|
|
241
|
+
}
|
|
242
|
+
interface ChatMessagesTable {
|
|
243
|
+
id: Generated<string>;
|
|
244
|
+
chat_session_id: string;
|
|
245
|
+
role: string;
|
|
246
|
+
parts: unknown;
|
|
247
|
+
metadata: unknown | null;
|
|
248
|
+
created_at: Generated<Date>;
|
|
249
|
+
}
|
|
250
|
+
interface Database {
|
|
251
|
+
blocks: BlocksTable;
|
|
252
|
+
transactions: TransactionsTable;
|
|
253
|
+
events: EventsTable;
|
|
254
|
+
index_progress: IndexProgressTable;
|
|
255
|
+
subgraphs: SubgraphsTable;
|
|
256
|
+
api_keys: ApiKeysTable;
|
|
257
|
+
accounts: AccountsTable;
|
|
258
|
+
sessions: SessionsTable;
|
|
259
|
+
magic_links: MagicLinksTable;
|
|
260
|
+
usage_daily: UsageDailyTable;
|
|
261
|
+
usage_snapshots: UsageSnapshotsTable;
|
|
262
|
+
waitlist: WaitlistTable;
|
|
263
|
+
account_insights: AccountInsightsTable;
|
|
264
|
+
account_agent_runs: AccountAgentRunsTable;
|
|
265
|
+
subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
|
|
266
|
+
subgraph_processing_stats: SubgraphProcessingStatsTable;
|
|
267
|
+
subgraph_table_snapshots: SubgraphTableSnapshotsTable;
|
|
268
|
+
subgraph_gaps: SubgraphGapsTable;
|
|
269
|
+
subgraph_usage_daily: SubgraphUsageDailyTable;
|
|
270
|
+
projects: ProjectsTable;
|
|
271
|
+
team_members: TeamMembersTable;
|
|
272
|
+
team_invitations: TeamInvitationsTable;
|
|
273
|
+
chat_sessions: ChatSessionsTable;
|
|
274
|
+
chat_messages: ChatMessagesTable;
|
|
275
|
+
tenants: TenantsTable;
|
|
276
|
+
tenant_usage_monthly: TenantUsageMonthlyTable;
|
|
277
|
+
tenant_compute_addons: TenantComputeAddonsTable;
|
|
278
|
+
account_spend_caps: AccountSpendCapsTable;
|
|
279
|
+
provisioning_audit_log: ProvisioningAuditLogTable;
|
|
280
|
+
}
|
|
281
|
+
type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
|
|
282
|
+
interface TenantsTable {
|
|
283
|
+
id: Generated<string>;
|
|
284
|
+
account_id: string;
|
|
285
|
+
slug: string;
|
|
286
|
+
status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
|
|
287
|
+
plan: string;
|
|
288
|
+
cpus: ColumnType<number, number | string, number | string>;
|
|
289
|
+
memory_mb: number;
|
|
290
|
+
storage_limit_mb: number;
|
|
291
|
+
storage_used_mb: number | null;
|
|
292
|
+
pg_container_id: string | null;
|
|
293
|
+
api_container_id: string | null;
|
|
294
|
+
processor_container_id: string | null;
|
|
295
|
+
target_database_url_enc: Buffer;
|
|
296
|
+
tenant_jwt_secret_enc: Buffer;
|
|
297
|
+
anon_key_enc: Buffer;
|
|
298
|
+
service_key_enc: Buffer;
|
|
299
|
+
api_url_internal: string;
|
|
300
|
+
api_url_public: string;
|
|
301
|
+
suspended_at: Date | null;
|
|
302
|
+
last_health_check_at: Date | null;
|
|
303
|
+
last_active_at: Generated<Date>;
|
|
304
|
+
service_gen: Generated<number>;
|
|
305
|
+
anon_gen: Generated<number>;
|
|
306
|
+
project_id: string | null;
|
|
307
|
+
created_at: Generated<Date>;
|
|
308
|
+
updated_at: Generated<Date>;
|
|
309
|
+
}
|
|
310
|
+
interface TenantUsageMonthlyTable {
|
|
311
|
+
id: Generated<string>;
|
|
312
|
+
tenant_id: string;
|
|
313
|
+
period_month: Date;
|
|
314
|
+
storage_peak_mb: Generated<number>;
|
|
315
|
+
storage_avg_mb: Generated<number>;
|
|
316
|
+
storage_last_mb: Generated<number>;
|
|
317
|
+
measurements: Generated<number>;
|
|
318
|
+
first_at: Generated<Date>;
|
|
319
|
+
last_at: Generated<Date>;
|
|
320
|
+
}
|
|
321
|
+
interface TenantComputeAddonsTable {
|
|
322
|
+
id: Generated<string>;
|
|
323
|
+
tenant_id: string;
|
|
324
|
+
memory_mb_delta: Generated<number>;
|
|
325
|
+
cpu_delta: Generated<number | string>;
|
|
326
|
+
storage_mb_delta: Generated<number>;
|
|
327
|
+
effective_from: Generated<Date>;
|
|
328
|
+
effective_until: Date | null;
|
|
329
|
+
stripe_subscription_item_id: string | null;
|
|
330
|
+
created_at: Generated<Date>;
|
|
331
|
+
}
|
|
332
|
+
interface AccountSpendCapsTable {
|
|
333
|
+
account_id: string;
|
|
334
|
+
monthly_cap_cents: number | null;
|
|
335
|
+
compute_cap_cents: number | null;
|
|
336
|
+
storage_cap_cents: number | null;
|
|
337
|
+
ai_cap_cents: number | null;
|
|
338
|
+
alert_threshold_pct: Generated<number>;
|
|
339
|
+
alert_sent_at: Date | null;
|
|
340
|
+
frozen_at: Date | null;
|
|
341
|
+
updated_at: Generated<Date>;
|
|
342
|
+
}
|
|
343
|
+
type AccountSpendCap = Selectable<AccountSpendCapsTable>;
|
|
344
|
+
type UpdateAccountSpendCap = Updateable<AccountSpendCapsTable>;
|
|
345
|
+
type ProvisioningAuditEvent = "provision.start" | "provision.success" | "provision.failure" | "suspend" | "resume" | "resize" | "keys.rotate" | "bastion.key.upload" | "bastion.key.revoke" | "teardown";
|
|
346
|
+
type ProvisioningAuditStatus = "ok" | "error";
|
|
347
|
+
interface ProvisioningAuditLogTable {
|
|
348
|
+
id: Generated<string>;
|
|
349
|
+
tenant_id: string | null;
|
|
350
|
+
tenant_slug: string | null;
|
|
351
|
+
account_id: string | null;
|
|
352
|
+
actor: string;
|
|
353
|
+
event: ProvisioningAuditEvent;
|
|
354
|
+
status: ProvisioningAuditStatus;
|
|
355
|
+
detail: unknown | null;
|
|
356
|
+
error: string | null;
|
|
357
|
+
created_at: Generated<Date>;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Spend-cap state for an account. Both the metering crons (check + set
|
|
361
|
+
* frozen_at) and the dashboard (read + update caps) call through here.
|
|
362
|
+
*/
|
|
363
|
+
declare function getCaps(db: Kysely<Database>, accountId: string): Promise<AccountSpendCap | null>;
|
|
364
|
+
/**
|
|
365
|
+
* Upsert semantics: row is created on first write (default threshold
|
|
366
|
+
* 80%), subsequent writes PATCH. `updated_at` is always bumped.
|
|
367
|
+
*/
|
|
368
|
+
declare function upsertCaps(db: Kysely<Database>, accountId: string, patch: Omit<UpdateAccountSpendCap, "account_id" | "updated_at">): Promise<AccountSpendCap>;
|
|
369
|
+
/** Mark an account frozen at the current time (cap just tripped). */
|
|
370
|
+
declare function freezeAccount(db: Kysely<Database>, accountId: string): Promise<void>;
|
|
371
|
+
/**
|
|
372
|
+
* Clear the frozen + alert state — called on `invoice.paid` webhook at
|
|
373
|
+
* cycle rollover (new billing period starts fresh) OR when the user
|
|
374
|
+
* explicitly raises their cap above current usage.
|
|
375
|
+
*/
|
|
376
|
+
declare function clearFreeze(db: Kysely<Database>, accountId: string): Promise<void>;
|
|
377
|
+
/** Is this account currently cap-frozen? Bulk-checked by metering crons. */
|
|
378
|
+
declare function listFrozenAccountIds(db: Kysely<Database>): Promise<Set<string>>;
|
|
379
|
+
export { upsertCaps, listFrozenAccountIds, getCaps, freezeAccount, clearFreeze };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/db/queries/account-spend-caps.ts
|
|
18
|
+
async function getCaps(db, accountId) {
|
|
19
|
+
const row = await db.selectFrom("account_spend_caps").selectAll().where("account_id", "=", accountId).executeTakeFirst();
|
|
20
|
+
return row ?? null;
|
|
21
|
+
}
|
|
22
|
+
async function upsertCaps(db, accountId, patch) {
|
|
23
|
+
const insert = {
|
|
24
|
+
account_id: accountId,
|
|
25
|
+
monthly_cap_cents: patch.monthly_cap_cents ?? null,
|
|
26
|
+
compute_cap_cents: patch.compute_cap_cents ?? null,
|
|
27
|
+
storage_cap_cents: patch.storage_cap_cents ?? null,
|
|
28
|
+
ai_cap_cents: patch.ai_cap_cents ?? null,
|
|
29
|
+
alert_threshold_pct: patch.alert_threshold_pct ?? 80,
|
|
30
|
+
alert_sent_at: patch.alert_sent_at ?? null,
|
|
31
|
+
frozen_at: patch.frozen_at ?? null
|
|
32
|
+
};
|
|
33
|
+
return db.insertInto("account_spend_caps").values(insert).onConflict((oc) => oc.column("account_id").doUpdateSet({
|
|
34
|
+
...patch,
|
|
35
|
+
updated_at: new Date
|
|
36
|
+
})).returningAll().executeTakeFirstOrThrow();
|
|
37
|
+
}
|
|
38
|
+
async function freezeAccount(db, accountId) {
|
|
39
|
+
await upsertCaps(db, accountId, { frozen_at: new Date });
|
|
40
|
+
}
|
|
41
|
+
async function clearFreeze(db, accountId) {
|
|
42
|
+
await upsertCaps(db, accountId, {
|
|
43
|
+
frozen_at: null,
|
|
44
|
+
alert_sent_at: null
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async function listFrozenAccountIds(db) {
|
|
48
|
+
const rows = await db.selectFrom("account_spend_caps").select("account_id").where("frozen_at", "is not", null).execute();
|
|
49
|
+
return new Set(rows.map((r) => r.account_id));
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
upsertCaps,
|
|
53
|
+
listFrozenAccountIds,
|
|
54
|
+
getCaps,
|
|
55
|
+
freezeAccount,
|
|
56
|
+
clearFreeze
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
//# debugId=ECBEFE5FC18A7EFB64756E2164756E21
|
|
60
|
+
//# sourceMappingURL=account-spend-caps.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/db/queries/account-spend-caps.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Kysely } from \"kysely\";\nimport type {\n\tAccountSpendCap,\n\tDatabase,\n\tInsertAccountSpendCap,\n\tUpdateAccountSpendCap,\n} from \"../types.ts\";\n\n/**\n * Spend-cap state for an account. Both the metering crons (check + set\n * frozen_at) and the dashboard (read + update caps) call through here.\n */\n\nexport async function getCaps(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<AccountSpendCap | null> {\n\tconst row = await db\n\t\t.selectFrom(\"account_spend_caps\")\n\t\t.selectAll()\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.executeTakeFirst();\n\treturn row ?? null;\n}\n\n/**\n * Upsert semantics: row is created on first write (default threshold\n * 80%), subsequent writes PATCH. `updated_at` is always bumped.\n */\nexport async function upsertCaps(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tpatch: Omit<UpdateAccountSpendCap, \"account_id\" | \"updated_at\">,\n): Promise<AccountSpendCap> {\n\tconst insert: InsertAccountSpendCap = {\n\t\taccount_id: accountId,\n\t\tmonthly_cap_cents: patch.monthly_cap_cents ?? null,\n\t\tcompute_cap_cents: patch.compute_cap_cents ?? null,\n\t\tstorage_cap_cents: patch.storage_cap_cents ?? null,\n\t\tai_cap_cents: patch.ai_cap_cents ?? null,\n\t\talert_threshold_pct: patch.alert_threshold_pct ?? 80,\n\t\talert_sent_at: patch.alert_sent_at ?? null,\n\t\tfrozen_at: patch.frozen_at ?? null,\n\t};\n\n\treturn db\n\t\t.insertInto(\"account_spend_caps\")\n\t\t.values(insert)\n\t\t.onConflict((oc) =>\n\t\t\toc.column(\"account_id\").doUpdateSet({\n\t\t\t\t...patch,\n\t\t\t\tupdated_at: new Date(),\n\t\t\t}),\n\t\t)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\n/** Mark an account frozen at the current time (cap just tripped). */\nexport async function freezeAccount(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<void> {\n\tawait upsertCaps(db, accountId, { frozen_at: new Date() });\n}\n\n/**\n * Clear the frozen + alert state — called on `invoice.paid` webhook at\n * cycle rollover (new billing period starts fresh) OR when the user\n * explicitly raises their cap above current usage.\n */\nexport async function clearFreeze(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<void> {\n\tawait upsertCaps(db, accountId, {\n\t\tfrozen_at: null,\n\t\talert_sent_at: null,\n\t});\n}\n\n/** Is this account currently cap-frozen? Bulk-checked by metering crons. */\nexport async function listFrozenAccountIds(\n\tdb: Kysely<Database>,\n): Promise<Set<string>> {\n\tconst rows = await db\n\t\t.selectFrom(\"account_spend_caps\")\n\t\t.select(\"account_id\")\n\t\t.where(\"frozen_at\", \"is not\", null)\n\t\t.execute();\n\treturn new Set(rows.map((r) => r.account_id));\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAaA,eAAsB,OAAO,CAC5B,IACA,WACkC;AAAA,EAClC,MAAM,MAAM,MAAM,GAChB,WAAW,oBAAoB,EAC/B,UAAU,EACV,MAAM,cAAc,KAAK,SAAS,EAClC,iBAAiB;AAAA,EACnB,OAAO,OAAO;AAAA;AAOf,eAAsB,UAAU,CAC/B,IACA,WACA,OAC2B;AAAA,EAC3B,MAAM,SAAgC;AAAA,IACrC,YAAY;AAAA,IACZ,mBAAmB,MAAM,qBAAqB;AAAA,IAC9C,mBAAmB,MAAM,qBAAqB;AAAA,IAC9C,mBAAmB,MAAM,qBAAqB;AAAA,IAC9C,cAAc,MAAM,gBAAgB;AAAA,IACpC,qBAAqB,MAAM,uBAAuB;AAAA,IAClD,eAAe,MAAM,iBAAiB;AAAA,IACtC,WAAW,MAAM,aAAa;AAAA,EAC/B;AAAA,EAEA,OAAO,GACL,WAAW,oBAAoB,EAC/B,OAAO,MAAM,EACb,WAAW,CAAC,OACZ,GAAG,OAAO,YAAY,EAAE,YAAY;AAAA,OAChC;AAAA,IACH,YAAY,IAAI;AAAA,EACjB,CAAC,CACF,EACC,aAAa,EACb,wBAAwB;AAAA;AAI3B,eAAsB,aAAa,CAClC,IACA,WACgB;AAAA,EAChB,MAAM,WAAW,IAAI,WAAW,EAAE,WAAW,IAAI,KAAO,CAAC;AAAA;AAQ1D,eAAsB,WAAW,CAChC,IACA,WACgB;AAAA,EAChB,MAAM,WAAW,IAAI,WAAW;AAAA,IAC/B,WAAW;AAAA,IACX,eAAe;AAAA,EAChB,CAAC;AAAA;AAIF,eAAsB,oBAAoB,CACzC,IACuB;AAAA,EACvB,MAAM,OAAO,MAAM,GACjB,WAAW,oBAAoB,EAC/B,OAAO,YAAY,EACnB,MAAM,aAAa,UAAU,IAAI,EACjC,QAAQ;AAAA,EACV,OAAO,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC;AAAA;",
|
|
8
|
+
"debugId": "ECBEFE5FC18A7EFB64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|