@abloatai/transaction 0.39.0 → 0.40.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/coordination/events.d.ts +9 -0
- package/dist/coordination/events.d.ts.map +1 -1
- package/dist/coordination/index.d.ts +2 -2
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +1 -1
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/schema.d.ts +226 -34
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +180 -48
- package/dist/coordination/schema.js.map +1 -1
- package/dist/coordination/trace.d.ts.map +1 -1
- package/dist/coordination/trace.js +9 -1
- package/dist/coordination/trace.js.map +1 -1
- package/dist/errorCodes.d.ts +5 -0
- package/dist/errorCodes.d.ts.map +1 -1
- package/dist/errorCodes.js +5 -0
- package/dist/errorCodes.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +9 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/policy/types.d.ts +10 -2
- package/dist/policy/types.d.ts.map +1 -1
- package/dist/policy/types.js.map +1 -1
- package/dist/pricing.d.ts +194 -0
- package/dist/pricing.d.ts.map +1 -0
- package/dist/pricing.js +330 -0
- package/dist/pricing.js.map +1 -0
- package/dist/resources/functionalUpdate.d.ts.map +1 -1
- package/dist/resources/functionalUpdate.js +8 -8
- package/dist/resources/functionalUpdate.js.map +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/roles.d.ts +19 -0
- package/dist/schema/roles.d.ts.map +1 -1
- package/dist/schema/roles.js +23 -3
- package/dist/schema/roles.js.map +1 -1
- package/dist/schema/schema.d.ts +1 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +1 -1
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/tenancy.d.ts +1 -1
- package/dist/transactions/settlement/commitEnvelope.d.ts +10 -2
- package/dist/transactions/settlement/commitEnvelope.d.ts.map +1 -1
- package/dist/transactions/settlement/pendingWrite.d.ts +10 -2
- package/dist/transactions/settlement/pendingWrite.d.ts.map +1 -1
- package/dist/transport/wsFrameHandlers.d.ts.map +1 -1
- package/dist/transport/wsFrameHandlers.js +9 -3
- package/dist/transport/wsFrameHandlers.js.map +1 -1
- package/dist/wire/accountResponses.d.ts +100 -0
- package/dist/wire/accountResponses.d.ts.map +1 -1
- package/dist/wire/accountResponses.js +70 -0
- package/dist/wire/accountResponses.js.map +1 -1
- package/dist/wire/commit.d.ts +708 -100
- package/dist/wire/commit.d.ts.map +1 -1
- package/dist/wire/dataSourceResponses.d.ts +171 -0
- package/dist/wire/dataSourceResponses.d.ts.map +1 -0
- package/dist/wire/dataSourceResponses.js +168 -0
- package/dist/wire/dataSourceResponses.js.map +1 -0
- package/dist/wire/frames.d.ts +20 -4
- package/dist/wire/frames.d.ts.map +1 -1
- package/dist/wire/inboundFrames.d.ts +102 -14
- package/dist/wire/inboundFrames.d.ts.map +1 -1
- package/dist/wire/index.d.ts +4 -2
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +5 -1
- package/dist/wire/index.js.map +1 -1
- package/dist/wire/pricing.d.ts +43 -0
- package/dist/wire/pricing.d.ts.map +1 -0
- package/dist/wire/pricing.js +36 -0
- package/dist/wire/pricing.js.map +1 -0
- package/package.json +6 -1
- package/src/coordination/events.ts +9 -0
- package/src/coordination/index.ts +8 -0
- package/src/coordination/schema.ts +200 -51
- package/src/coordination/trace.ts +9 -1
- package/src/errorCodes.ts +20 -0
- package/src/errors.ts +9 -2
- package/src/index.ts +4 -0
- package/src/policy/types.ts +10 -2
- package/src/pricing.ts +350 -0
- package/src/resources/functionalUpdate.ts +11 -11
- package/src/schema/index.ts +2 -0
- package/src/schema/roles.ts +26 -3
- package/src/schema/schema.ts +2 -0
- package/src/transport/wsFrameHandlers.ts +9 -3
- package/src/wire/accountResponses.ts +76 -0
- package/src/wire/dataSourceResponses.ts +188 -0
- package/src/wire/index.ts +33 -0
- package/src/wire/pricing.ts +41 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the DATASOURCE routes answer with — the connect surface you reach
|
|
3
|
+
* through `ablo connect` and its verbs: `POST /v1/datasources` (register),
|
|
4
|
+
* `POST /v1/datasources/validate` (readiness from Ablo's own network),
|
|
5
|
+
* `POST /v1/datasources/locate` (which plane holds a database),
|
|
6
|
+
* `GET /v1/datasources` (this plane's registrations), and
|
|
7
|
+
* `DELETE /v1/datasources` (deregister).
|
|
8
|
+
*
|
|
9
|
+
* These are the shapes the server, the CLI, and the dashboard have to agree
|
|
10
|
+
* on. Before this module each consumer spelled them out again — the server
|
|
11
|
+
* inline in `c.json({ … })`, the CLI in three separate hand-rolled decoders —
|
|
12
|
+
* so a renamed field surfaced as `undefined` in a success message, and a
|
|
13
|
+
* warning the server attached (a replication slot still holding the customer's
|
|
14
|
+
* write-ahead log) was silently dropped by a reader that never knew the key
|
|
15
|
+
* existed.
|
|
16
|
+
*
|
|
17
|
+
* Reader stance: fields beyond each response's core verdict are OPTIONAL here
|
|
18
|
+
* even where today's server always sends them. The CLI dials deployments that
|
|
19
|
+
* skew across releases, and a strict parse would refuse a run that succeeded —
|
|
20
|
+
* the worst failure class this surface has. The parse still fails loudly on a
|
|
21
|
+
* body that is not the response at all (a proxy's HTML page, another route's
|
|
22
|
+
* answer), which is the drift this module exists to catch.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { z } from 'zod';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The readiness vocabulary — every invariant the engine's preflights can name
|
|
29
|
+
* in a failure. ONE definition site: the server's probes type their `item`
|
|
30
|
+
* against {@link ReadinessItem}, so an item outside this list cannot compile,
|
|
31
|
+
* and the CLI's plain-language renderer is total over it, so an item added
|
|
32
|
+
* here fails the CLI build until it has a label. That closed loop is what
|
|
33
|
+
* stops the vocabulary drifting apart in three files again — the CLI shipped
|
|
34
|
+
* without a label for `server_version` for exactly that reason.
|
|
35
|
+
*
|
|
36
|
+
* On the WIRE `item` stays an open string (see {@link readinessFailureSchema})
|
|
37
|
+
* so an older reader survives a newer server; this list is the closed set
|
|
38
|
+
* producers may emit, not a parse constraint.
|
|
39
|
+
*/
|
|
40
|
+
export const READINESS_ITEMS = [
|
|
41
|
+
'server_version',
|
|
42
|
+
'wal_level',
|
|
43
|
+
'publication',
|
|
44
|
+
'replication_role',
|
|
45
|
+
'replica_identity',
|
|
46
|
+
'table_select',
|
|
47
|
+
'write_role',
|
|
48
|
+
'row_security',
|
|
49
|
+
'database_privileges',
|
|
50
|
+
'schema_privileges',
|
|
51
|
+
'table_ownership',
|
|
52
|
+
'idempotency_ledger',
|
|
53
|
+
'table_privileges',
|
|
54
|
+
'logical_marker',
|
|
55
|
+
'publication_drift',
|
|
56
|
+
] as const;
|
|
57
|
+
export type ReadinessItem = (typeof READINESS_ITEMS)[number];
|
|
58
|
+
|
|
59
|
+
const READINESS_ITEM_SET: ReadonlySet<string> = new Set(READINESS_ITEMS);
|
|
60
|
+
|
|
61
|
+
/** Whether a wire `item` is one this build's vocabulary knows — the reader's
|
|
62
|
+
* branch between a labelled rendering and the raw-name fallback. */
|
|
63
|
+
export function isReadinessItem(item: string): item is ReadinessItem {
|
|
64
|
+
return READINESS_ITEM_SET.has(item);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The advisory vocabulary — recommendations that never block a registration. */
|
|
68
|
+
export const READINESS_ADVISORY_ITEMS = ['slot_failover'] as const;
|
|
69
|
+
export type ReadinessAdvisoryItem = (typeof READINESS_ADVISORY_ITEMS)[number];
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* One failing readiness invariant, with its fix in hand. `item` names the
|
|
73
|
+
* invariant — see {@link READINESS_ITEMS} for the set a producer may emit,
|
|
74
|
+
* and why the wire keeps it open here. `fix` carries the exact statement or
|
|
75
|
+
* step that resolves it; `actual` the observed value, when one exists.
|
|
76
|
+
*/
|
|
77
|
+
export const readinessFailureSchema = z.object({
|
|
78
|
+
item: z.string(),
|
|
79
|
+
actual: z.string().optional(),
|
|
80
|
+
fix: z.string(),
|
|
81
|
+
});
|
|
82
|
+
export type ReadinessFailure = z.infer<typeof readinessFailureSchema>;
|
|
83
|
+
|
|
84
|
+
/** A recommendation that rides beside the verdict without changing it. */
|
|
85
|
+
export const readinessAdvisorySchema = z.object({
|
|
86
|
+
item: z.string(),
|
|
87
|
+
recommendation: z.string(),
|
|
88
|
+
});
|
|
89
|
+
export type ReadinessAdvisory = z.infer<typeof readinessAdvisorySchema>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* One registration, as the routes report it — the credential-free projection
|
|
93
|
+
* of a data source. This is the row of `GET /v1/datasources` and the success
|
|
94
|
+
* body of `POST /v1/datasources`. Everything here is safe to display: the
|
|
95
|
+
* credential is decomposed at registration and never returns.
|
|
96
|
+
*/
|
|
97
|
+
export const datasourceSummarySchema = z
|
|
98
|
+
.object({
|
|
99
|
+
/** Asserted when present; optional because an older deployment may omit
|
|
100
|
+
* the discriminator, and refusing its answer would refuse a run that
|
|
101
|
+
* succeeded. */
|
|
102
|
+
object: z.literal('datasource').optional(),
|
|
103
|
+
id: z.string().optional(),
|
|
104
|
+
/** How writes reach the database: Ablo's own scoped role, or the signed
|
|
105
|
+
* endpoint fallback. Unknown future kinds degrade to absent rather than
|
|
106
|
+
* failing the parse. */
|
|
107
|
+
connection: z.enum(['direct', 'endpoint']).optional().catch(undefined),
|
|
108
|
+
/** host:port of the connection — safe to display. */
|
|
109
|
+
host: z.string().optional(),
|
|
110
|
+
database: z.string().optional(),
|
|
111
|
+
schema: z.string().optional(),
|
|
112
|
+
display_name: z.string().optional(),
|
|
113
|
+
status: z.string().optional(),
|
|
114
|
+
livemode: z.boolean().optional(),
|
|
115
|
+
})
|
|
116
|
+
.loose();
|
|
117
|
+
export type DatasourceSummary = z.infer<typeof datasourceSummarySchema>;
|
|
118
|
+
|
|
119
|
+
/** `GET /v1/datasources` — every registration on the calling key's plane. */
|
|
120
|
+
export const datasourceListResponseSchema = z.object({
|
|
121
|
+
object: z.literal('list'),
|
|
122
|
+
data: z.array(datasourceSummarySchema).readonly(),
|
|
123
|
+
});
|
|
124
|
+
export type DatasourceListResponse = z.infer<typeof datasourceListResponseSchema>;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* `POST /v1/datasources/validate` — replication readiness as judged from
|
|
128
|
+
* Ablo's own network, the network replication actually runs from.
|
|
129
|
+
*
|
|
130
|
+
* `reachable` and `ready` are the verdict and always present; `reason` carries
|
|
131
|
+
* the driver's words when the engine couldn't reach the host either; `failures`
|
|
132
|
+
* is the checklist, each entry with its fix.
|
|
133
|
+
*/
|
|
134
|
+
export const datasourceValidationResponseSchema = z.object({
|
|
135
|
+
object: z.literal('datasource_validation').optional(),
|
|
136
|
+
connection: z.enum(['direct', 'endpoint']).optional().catch(undefined),
|
|
137
|
+
reachable: z.boolean(),
|
|
138
|
+
ready: z.boolean(),
|
|
139
|
+
reason: z.string().optional(),
|
|
140
|
+
failures: z.array(readinessFailureSchema).readonly(),
|
|
141
|
+
advisories: z.array(readinessAdvisorySchema).readonly().optional(),
|
|
142
|
+
});
|
|
143
|
+
export type DatasourceValidationResponse = z.infer<typeof datasourceValidationResponseSchema>;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* `POST /v1/datasources/locate` — which plane already holds a database.
|
|
147
|
+
* A targeted lookup, not an enumeration: the caller must hold the connection
|
|
148
|
+
* string, and the answer is only the holding plane. `held: null` means no
|
|
149
|
+
* other plane holds it and a registration would not conflict.
|
|
150
|
+
*/
|
|
151
|
+
export const datasourceLocationResponseSchema = z.object({
|
|
152
|
+
object: z.literal('datasource_location').optional(),
|
|
153
|
+
held: z
|
|
154
|
+
.object({
|
|
155
|
+
project: z.string().nullable(),
|
|
156
|
+
branch: z.string(),
|
|
157
|
+
})
|
|
158
|
+
.nullable(),
|
|
159
|
+
});
|
|
160
|
+
export type DatasourceLocationResponse = z.infer<typeof datasourceLocationResponseSchema>;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* `DELETE /v1/datasources` — what the deregistration let go of.
|
|
164
|
+
*
|
|
165
|
+
* `replication_slot` is the part a reader must not drop: when Ablo stopped
|
|
166
|
+
* reading but the slot survived (`released: false`), that slot is still on the
|
|
167
|
+
* customer's database holding their write-ahead log, and `remove_with` carries
|
|
168
|
+
* the statement that removes it. Nothing else will ever release it.
|
|
169
|
+
*/
|
|
170
|
+
export const datasourceDisconnectedResponseSchema = z.object({
|
|
171
|
+
object: z.literal('datasource_disconnected').optional(),
|
|
172
|
+
organization_id: z.string().optional(),
|
|
173
|
+
environment: z.string().optional(),
|
|
174
|
+
cleared: z.object({
|
|
175
|
+
direct: z.boolean(),
|
|
176
|
+
endpoints: z.number(),
|
|
177
|
+
}),
|
|
178
|
+
replication_slot: z
|
|
179
|
+
.object({
|
|
180
|
+
slot: z.string(),
|
|
181
|
+
released: z.boolean(),
|
|
182
|
+
detail: z.string().optional(),
|
|
183
|
+
remove_with: z.string().optional(),
|
|
184
|
+
warning: z.string().optional(),
|
|
185
|
+
})
|
|
186
|
+
.optional(),
|
|
187
|
+
});
|
|
188
|
+
export type DatasourceDisconnectedResponse = z.infer<typeof datasourceDisconnectedResponseSchema>;
|
package/src/wire/index.ts
CHANGED
|
@@ -274,6 +274,9 @@ export {
|
|
|
274
274
|
logEventSchema,
|
|
275
275
|
usageBucketSchema,
|
|
276
276
|
usageReportResponseSchema,
|
|
277
|
+
meterUsageSchema,
|
|
278
|
+
billingSummarySchema,
|
|
279
|
+
usageSummaryResponseSchema,
|
|
277
280
|
controlKeySchema,
|
|
278
281
|
controlKeyListResponseSchema,
|
|
279
282
|
keyMintedResponseSchema,
|
|
@@ -290,12 +293,42 @@ export type {
|
|
|
290
293
|
LogEvent,
|
|
291
294
|
UsageBucket,
|
|
292
295
|
UsageReportResponse,
|
|
296
|
+
MeterUsage,
|
|
297
|
+
BillingSummary,
|
|
298
|
+
UsageSummaryResponse,
|
|
293
299
|
ControlKey,
|
|
294
300
|
ControlKeyListResponse,
|
|
295
301
|
KeyMintedResponse,
|
|
296
302
|
KeyRevokedResponse,
|
|
297
303
|
} from './accountResponses.js';
|
|
298
304
|
|
|
305
|
+
// The datasource routes' responses — the `ablo connect` surface: register,
|
|
306
|
+
// validate, locate, list, deregister. What the server, the CLI, and the
|
|
307
|
+
// dashboard agree on.
|
|
308
|
+
export {
|
|
309
|
+
READINESS_ITEMS,
|
|
310
|
+
READINESS_ADVISORY_ITEMS,
|
|
311
|
+
isReadinessItem,
|
|
312
|
+
readinessFailureSchema,
|
|
313
|
+
readinessAdvisorySchema,
|
|
314
|
+
datasourceSummarySchema,
|
|
315
|
+
datasourceListResponseSchema,
|
|
316
|
+
datasourceValidationResponseSchema,
|
|
317
|
+
datasourceLocationResponseSchema,
|
|
318
|
+
datasourceDisconnectedResponseSchema,
|
|
319
|
+
} from './dataSourceResponses.js';
|
|
320
|
+
export type {
|
|
321
|
+
ReadinessItem,
|
|
322
|
+
ReadinessAdvisoryItem,
|
|
323
|
+
ReadinessFailure,
|
|
324
|
+
ReadinessAdvisory,
|
|
325
|
+
DatasourceSummary,
|
|
326
|
+
DatasourceListResponse,
|
|
327
|
+
DatasourceValidationResponse,
|
|
328
|
+
DatasourceLocationResponse,
|
|
329
|
+
DatasourceDisconnectedResponse,
|
|
330
|
+
} from './dataSourceResponses.js';
|
|
331
|
+
|
|
299
332
|
// The inbound socket surface: every frame the server can send, and how each
|
|
300
333
|
// one's payload is validated.
|
|
301
334
|
export {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pricing vocabulary that crosses the wire: the tier names, the meter
|
|
3
|
+
* names, and the shape of one rate-card step. Account responses carry these,
|
|
4
|
+
* so they live in the dependency-free wire layer; the pricing contract
|
|
5
|
+
* (`../pricing.ts`) derives the rate card, the plans, and the bill arithmetic
|
|
6
|
+
* from them and re-exports them for its consumers.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
|
|
10
|
+
export const planTierSchema = z.enum(['free', 'scale', 'enterprise']);
|
|
11
|
+
export type PlanTier = z.infer<typeof planTierSchema>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Every meter the engine records, over any transport. This is the closed set
|
|
15
|
+
* behind the loose `eventName` strings that `UsageRecorder` and the quota gate
|
|
16
|
+
* pass around.
|
|
17
|
+
*
|
|
18
|
+
* Recording and pricing are separate questions. A meter exists so usage can be
|
|
19
|
+
* gated and attributed; whether it reaches an invoice is `METER_EVENT_AXIS`.
|
|
20
|
+
* Bootstraps are recorded and quota-gated but deliberately unpriced: a bootstrap
|
|
21
|
+
* is what a client does once to become useful, and charging for it would price
|
|
22
|
+
* the act of connecting.
|
|
23
|
+
*/
|
|
24
|
+
export const meterEventSchema = z.enum([
|
|
25
|
+
'api.commit_ops',
|
|
26
|
+
'api.model_reads',
|
|
27
|
+
'api.claim_creates',
|
|
28
|
+
'api.bootstraps',
|
|
29
|
+
]);
|
|
30
|
+
export type MeterEvent = z.infer<typeof meterEventSchema>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* One step of the rate card. `throughOps` is the cumulative ceiling the rate
|
|
34
|
+
* applies up to, and `null` marks the final, unbounded step. Rates are marginal:
|
|
35
|
+
* crossing a ceiling reprices the operations above it, never the ones below.
|
|
36
|
+
*/
|
|
37
|
+
export const rateBracketSchema = z.object({
|
|
38
|
+
throughOps: z.number().int().positive().nullable(),
|
|
39
|
+
usdPerMillionOps: z.number().nonnegative(),
|
|
40
|
+
});
|
|
41
|
+
export type RateBracket = z.infer<typeof rateBracketSchema>;
|