@abloatai/transaction 0.38.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/auth/index.d.ts +16 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +10 -1
- package/dist/auth/index.js.map +1 -1
- 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 +6 -0
- package/dist/errorCodes.d.ts.map +1 -1
- package/dist/errorCodes.js +6 -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 +2 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +2 -2
- 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 +13 -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/select.d.ts +13 -0
- package/dist/schema/select.d.ts.map +1 -1
- package/dist/schema/select.js +26 -0
- package/dist/schema/select.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/httpClient.d.ts.map +1 -1
- package/dist/transport/httpClient.js +10 -1
- package/dist/transport/httpClient.js.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/auth.d.ts +7 -1
- package/dist/wire/auth.d.ts.map +1 -1
- package/dist/wire/auth.js +26 -3
- package/dist/wire/auth.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/auth/index.ts +31 -3
- 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 +24 -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 +3 -1
- package/src/schema/roles.ts +26 -3
- package/src/schema/schema.ts +15 -0
- package/src/schema/select.ts +30 -0
- package/src/transport/httpClient.ts +8 -1
- package/src/transport/wsFrameHandlers.ts +9 -3
- package/src/wire/accountResponses.ts +76 -0
- package/src/wire/auth.ts +30 -3
- package/src/wire/dataSourceResponses.ts +188 -0
- package/src/wire/index.ts +33 -0
- package/src/wire/pricing.ts +41 -0
|
@@ -19,6 +19,9 @@ import { z } from 'zod';
|
|
|
19
19
|
// response exists to stop withholding.
|
|
20
20
|
import { fieldMetaSchema, relationMetaSchema } from './modelShape.js';
|
|
21
21
|
import { onStaleModeSchema } from '../coordination/schema.js';
|
|
22
|
+
// The price's own vocabulary. A dashboard that restated the tier names or the
|
|
23
|
+
// meter set would be a second definition of what the invoice is computed from.
|
|
24
|
+
import { meterEventSchema, planTierSchema, rateBracketSchema } from './pricing.js';
|
|
22
25
|
import type { SyncDeltaAction } from './delta.js';
|
|
23
26
|
import { deltaSchema } from './delta.js';
|
|
24
27
|
// Kept for the {@link ListEnvelope} references below; `GET /v1/logs`'s own
|
|
@@ -325,3 +328,76 @@ export const usageReportResponseSchema = z.object({
|
|
|
325
328
|
data_freshness_seconds: z.number(),
|
|
326
329
|
});
|
|
327
330
|
export type UsageReportResponse = z.infer<typeof usageReportResponseSchema>;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* One meter's month-to-date usage, as a management surface shows it.
|
|
334
|
+
*
|
|
335
|
+
* `eventName` is the pricing contract's closed set rather than a free string,
|
|
336
|
+
* so a surface cannot render a meter the price does not recognise. `billable`
|
|
337
|
+
* says whether the meter reaches an invoice at all: bootstraps are recorded and
|
|
338
|
+
* gated but never charged, and a usage table that does not say so reads as a
|
|
339
|
+
* bill nobody sent.
|
|
340
|
+
*/
|
|
341
|
+
export const meterUsageSchema = z.object({
|
|
342
|
+
eventName: meterEventSchema,
|
|
343
|
+
displayName: z.string(),
|
|
344
|
+
/** Operations counted this period. */
|
|
345
|
+
total: z.number(),
|
|
346
|
+
/** Requests behind that total. A commit of 500 operations counts once here. */
|
|
347
|
+
count: z.number(),
|
|
348
|
+
/** The plan's monthly allowance for this meter; null where it is ungated. */
|
|
349
|
+
monthlyMax: z.number().nullable(),
|
|
350
|
+
billable: z.boolean(),
|
|
351
|
+
});
|
|
352
|
+
export type MeterUsage = z.infer<typeof meterUsageSchema>;
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* What the period costs, computed once by the server from the pricing contract.
|
|
356
|
+
*
|
|
357
|
+
* The client renders these rather than recomputing them. A dashboard that does
|
|
358
|
+
* its own arithmetic is a second implementation of the price, and the one a
|
|
359
|
+
* customer reads before they are billed, so it is the copy that has to be
|
|
360
|
+
* right and the one nothing checks.
|
|
361
|
+
*/
|
|
362
|
+
export const billingSummarySchema = z.object({
|
|
363
|
+
tier: planTierSchema,
|
|
364
|
+
/** The tier as it reads on the pricing page. */
|
|
365
|
+
label: z.string(),
|
|
366
|
+
/** The monthly floor in USD; null where terms are contractual. */
|
|
367
|
+
monthlyMinimumUsd: z.number().nullable(),
|
|
368
|
+
/** Operations the floor already covers, or the hard cap on a capped tier. */
|
|
369
|
+
includedOps: z.number().nullable(),
|
|
370
|
+
/** Where the tier stops rather than bills; null on every metered tier. */
|
|
371
|
+
hardCapOps: z.number().nullable(),
|
|
372
|
+
/** The daily burst guard; null on every metered tier. */
|
|
373
|
+
dailyCapOps: z.number().nullable(),
|
|
374
|
+
/** Every billable meter, collapsed into the one number the price uses. */
|
|
375
|
+
opsUsed: z.number(),
|
|
376
|
+
/** The floor or the metered usage, whichever is greater. null = contract. */
|
|
377
|
+
projectedBillUsd: z.number().nullable(),
|
|
378
|
+
/** True where the published card is a starting point, not the terms. */
|
|
379
|
+
contractPriced: z.boolean(),
|
|
380
|
+
/**
|
|
381
|
+
* The rate card in force, so a surface can show what the next operation
|
|
382
|
+
* costs without shipping a copy of the price to the browser.
|
|
383
|
+
*/
|
|
384
|
+
rateCard: z.array(rateBracketSchema).readonly(),
|
|
385
|
+
});
|
|
386
|
+
export type BillingSummary = z.infer<typeof billingSummarySchema>;
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* `GET /v1/dashboard/usage-summary` — month-to-date usage and what it costs.
|
|
390
|
+
*
|
|
391
|
+
* Distinct from {@link usageReportResponseSchema}, which answers the public
|
|
392
|
+
* `GET /v1/usage` with daily buckets for a caller doing its own analysis. This
|
|
393
|
+
* one answers the question a person opens a dashboard to ask: what have I used,
|
|
394
|
+
* and what will it cost.
|
|
395
|
+
*/
|
|
396
|
+
export const usageSummaryResponseSchema = z.object({
|
|
397
|
+
plan: planTierSchema,
|
|
398
|
+
/** Start of the billing period the numbers cover, ISO-8601. */
|
|
399
|
+
periodStart: z.string(),
|
|
400
|
+
meters: z.array(meterUsageSchema).readonly(),
|
|
401
|
+
billing: billingSummarySchema,
|
|
402
|
+
});
|
|
403
|
+
export type UsageSummaryResponse = z.infer<typeof usageSummaryResponseSchema>;
|
package/src/wire/auth.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { z } from 'zod';
|
|
14
|
-
import { grantedOperationSchema } from '../auth/capability.js';
|
|
14
|
+
import { capabilityOperationSchema, grantedOperationSchema } from '../auth/capability.js';
|
|
15
15
|
import { syncGroupInputSchema } from '../coordination/schema.js';
|
|
16
16
|
|
|
17
17
|
/** The participant this session acts as. */
|
|
@@ -48,8 +48,25 @@ export const ephemeralKeyRequestSchema = z.object({
|
|
|
48
48
|
schemaOwnerOrgId: z.string().min(1).optional(),
|
|
49
49
|
/** Narrow the session to these sync groups. */
|
|
50
50
|
syncGroups: z.array(syncGroupInputSchema).readonly().optional(),
|
|
51
|
-
/**
|
|
52
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Least-privilege allowlist, named model by model. For a caller that knows
|
|
53
|
+
* the schema the session will resolve. Exactly one of this and
|
|
54
|
+
* {@link ephemeralKeyRequestSchema.shape.activeSchemaOperations} is required.
|
|
55
|
+
*/
|
|
56
|
+
operations: z.array(grantedOperationSchema).min(1).optional(),
|
|
57
|
+
/**
|
|
58
|
+
* The same allowlist expressed as verbs alone, for a caller that CANNOT know
|
|
59
|
+
* the models: an identity service minting sessions for organizations whose
|
|
60
|
+
* schemas it does not own has no way to name them, and a grant is checked
|
|
61
|
+
* against the session's schema at mint time, so naming another schema's
|
|
62
|
+
* models fails every time.
|
|
63
|
+
*
|
|
64
|
+
* The server expands these across the models in the session's active schema
|
|
65
|
+
* and stores the concrete result, so what lands on the credential is the same
|
|
66
|
+
* enumerated allowlist as the field above. A verb is granted only where the
|
|
67
|
+
* model admits it — an immutable model takes `read` and nothing else.
|
|
68
|
+
*/
|
|
69
|
+
activeSchemaOperations: z.array(capabilityOperationSchema).min(1).optional(),
|
|
53
70
|
/** Lifetime in seconds. Capped by the server's maximum. */
|
|
54
71
|
ttlSeconds: z.number().int().positive().optional(),
|
|
55
72
|
/** A human-readable tag recorded with the key, for debugging. */
|
|
@@ -63,6 +80,16 @@ export const ephemeralKeyRequestSchema = z.object({
|
|
|
63
80
|
'schemaProjectId and schemaOwnerOrgId must be provided together',
|
|
64
81
|
path: ['schemaProjectId'],
|
|
65
82
|
},
|
|
83
|
+
).refine(
|
|
84
|
+
(request) =>
|
|
85
|
+
(request.operations === undefined) !== (request.activeSchemaOperations === undefined),
|
|
86
|
+
{
|
|
87
|
+
// Exactly one, never both and never neither. Neither would leave the
|
|
88
|
+
// credential with an empty allowlist, which reads as UNRESTRICTED at the
|
|
89
|
+
// gate rather than as nothing; both would leave two answers to one question.
|
|
90
|
+
message: 'provide either operations or activeSchemaOperations, not both',
|
|
91
|
+
path: ['operations'],
|
|
92
|
+
},
|
|
66
93
|
);
|
|
67
94
|
export type EphemeralKeyRequest = z.infer<typeof ephemeralKeyRequestSchema>;
|
|
68
95
|
|
|
@@ -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>;
|