@abloatai/ablo 0.23.0 → 0.24.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/CHANGELOG.md +20 -0
- package/dist/ai-sdk/coordinated-tool.d.ts +101 -0
- package/dist/ai-sdk/coordinated-tool.js +129 -0
- package/dist/ai-sdk/index.d.ts +42 -0
- package/dist/ai-sdk/index.js +42 -0
- package/dist/cli.cjs +687 -498
- package/dist/client/Ablo.js +4 -0
- package/dist/interfaces/index.d.ts +8 -0
- package/dist/sync/BootstrapHelper.d.ts +16 -0
- package/dist/sync/BootstrapHelper.js +27 -0
- package/dist/sync/schemas.d.ts +1 -0
- package/dist/sync/schemas.js +3 -0
- package/package.json +1 -1
package/dist/client/Ablo.js
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { z } from 'zod';
|
|
22
22
|
import { baseFieldsSchema } from '../schema/schema.js';
|
|
23
|
+
import { schemaHash } from '../schema/serialize.js';
|
|
23
24
|
import { AbloError, AbloAuthenticationError, AbloConnectionError, AbloValidationError, AbloNotFoundError, translateHttpError, toAbloError, claimedError } from '../errors.js';
|
|
24
25
|
import { descriptionFromMeta } from '../coordination/schema.js';
|
|
25
26
|
import { LoadStrategy, PropertyType } from '../types/index.js';
|
|
@@ -222,6 +223,9 @@ function deriveConfigFromSchema(schema) {
|
|
|
222
223
|
defaultNonCreatePriority: 50,
|
|
223
224
|
essentialFields: {},
|
|
224
225
|
classNameFallbackMap: {},
|
|
226
|
+
// Hash this client's schema once so bootstrap can detect drift against the
|
|
227
|
+
// server's active hash (same `schemaHash` the CLI push + server compute).
|
|
228
|
+
expectedSchemaHash: schemaHash(schema),
|
|
225
229
|
};
|
|
226
230
|
}
|
|
227
231
|
// ── Auto model registration from schema ───────────────────────────────────
|
|
@@ -380,6 +380,14 @@ export interface SyncEngineConfig {
|
|
|
380
380
|
* e.g., { TaskModel: 'Task', ProjectModel: 'Project' }
|
|
381
381
|
*/
|
|
382
382
|
classNameFallbackMap: Readonly<Record<string, string>>;
|
|
383
|
+
/**
|
|
384
|
+
* Content hash of the schema THIS client was built against (the same
|
|
385
|
+
* `schemaHash()` the CLI push + server compute). Used purely to detect
|
|
386
|
+
* schema drift: when the server reports a different active hash on bootstrap,
|
|
387
|
+
* the SDK warns the developer to run `ablo push` — otherwise drift only
|
|
388
|
+
* surfaces later as an opaque DB constraint error. Advisory, not enforced.
|
|
389
|
+
*/
|
|
390
|
+
expectedSchemaHash?: string;
|
|
383
391
|
}
|
|
384
392
|
/**
|
|
385
393
|
* Allows consumers to extend the WebSocket event map with
|
|
@@ -18,6 +18,12 @@ export interface BootstrapData {
|
|
|
18
18
|
/** Model types whose server-side query failed (timeout, RLS error, etc.) */
|
|
19
19
|
failedModels?: string[];
|
|
20
20
|
timestamp: number;
|
|
21
|
+
/**
|
|
22
|
+
* The server's ACTIVE schema content hash for this tenant (same `schemaHash`
|
|
23
|
+
* the CLI push computes). Present once the tenant has pushed a schema; the
|
|
24
|
+
* client compares it to its own `config.expectedSchemaHash` to warn on drift.
|
|
25
|
+
*/
|
|
26
|
+
schemaHash?: string;
|
|
21
27
|
}
|
|
22
28
|
export interface BootstrapFetchResult {
|
|
23
29
|
notModified: boolean;
|
|
@@ -72,7 +78,17 @@ import { type ValidatedServerDelta } from './schemas.js';
|
|
|
72
78
|
export declare class BootstrapHelper {
|
|
73
79
|
private options;
|
|
74
80
|
private abortController;
|
|
81
|
+
/** Warn about schema drift at most once per helper. */
|
|
82
|
+
private schemaDriftWarned;
|
|
75
83
|
get baseUrl(): string;
|
|
84
|
+
/**
|
|
85
|
+
* Advisory schema-drift check: compare the server's active schema hash (on the
|
|
86
|
+
* bootstrap response) against the hash this client was built with. A mismatch
|
|
87
|
+
* means the app's schema and the deployed schema have diverged — reads/writes
|
|
88
|
+
* relying on undeployed changes will later fail with an opaque DB constraint
|
|
89
|
+
* error. Warn once, actionably; never throws or blocks the bootstrap.
|
|
90
|
+
*/
|
|
91
|
+
private warnOnSchemaDrift;
|
|
76
92
|
constructor(options: BootstrapOptions);
|
|
77
93
|
/**
|
|
78
94
|
* Update the offline-cache namespace once auth has resolved the server-side
|
|
@@ -10,9 +10,34 @@ import { parseBootstrapResponse } from './schemas.js';
|
|
|
10
10
|
export class BootstrapHelper {
|
|
11
11
|
options;
|
|
12
12
|
abortController = null;
|
|
13
|
+
/** Warn about schema drift at most once per helper. */
|
|
14
|
+
schemaDriftWarned = false;
|
|
13
15
|
get baseUrl() {
|
|
14
16
|
return this.options.baseUrl;
|
|
15
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Advisory schema-drift check: compare the server's active schema hash (on the
|
|
20
|
+
* bootstrap response) against the hash this client was built with. A mismatch
|
|
21
|
+
* means the app's schema and the deployed schema have diverged — reads/writes
|
|
22
|
+
* relying on undeployed changes will later fail with an opaque DB constraint
|
|
23
|
+
* error. Warn once, actionably; never throws or blocks the bootstrap.
|
|
24
|
+
*/
|
|
25
|
+
warnOnSchemaDrift(serverHash) {
|
|
26
|
+
if (this.schemaDriftWarned || !serverHash)
|
|
27
|
+
return;
|
|
28
|
+
const clientHash = getContext().config.expectedSchemaHash;
|
|
29
|
+
if (!clientHash || clientHash === serverHash)
|
|
30
|
+
return;
|
|
31
|
+
this.schemaDriftWarned = true;
|
|
32
|
+
// Self-brand the message ("Ablo:") rather than rely on the default logger's
|
|
33
|
+
// `[Ablo]` namespace — consumers wiring their own logger (pino, etc.) lose
|
|
34
|
+
// that prefix, and a drift warning that reads like the app's own log is
|
|
35
|
+
// worse than none. The brand tells them at a glance who is talking.
|
|
36
|
+
getContext().logger.warn(`Ablo: Schema drift detected — this app was built against schema ${clientHash}, ` +
|
|
37
|
+
`but the deployed schema is ${serverHash}. Operations that depend on schema ` +
|
|
38
|
+
`changes not yet deployed will fail later with an opaque database error. Run ` +
|
|
39
|
+
`\`ablo push\` to deploy your schema (or update this app to match the deployed one).`, { clientSchemaHash: clientHash, serverSchemaHash: serverHash });
|
|
40
|
+
}
|
|
16
41
|
constructor(options) {
|
|
17
42
|
// Defaults are spread first; the explicit `baseUrl` then takes precedence
|
|
18
43
|
// and is computed from `options.baseUrl` (or the localhost fallback).
|
|
@@ -254,6 +279,7 @@ export class BootstrapHelper {
|
|
|
254
279
|
}
|
|
255
280
|
const rawJson = await res.json();
|
|
256
281
|
const data = parseBootstrapResponse(rawJson);
|
|
282
|
+
this.warnOnSchemaDrift(data.schemaHash);
|
|
257
283
|
// Persist payload for offline
|
|
258
284
|
try {
|
|
259
285
|
if (this.options.cacheScope) {
|
|
@@ -326,6 +352,7 @@ export class BootstrapHelper {
|
|
|
326
352
|
}
|
|
327
353
|
const rawJson = await response.json();
|
|
328
354
|
const data = parseBootstrapResponse(rawJson);
|
|
355
|
+
this.warnOnSchemaDrift(data.schemaHash);
|
|
329
356
|
// Save a copy for offline
|
|
330
357
|
try {
|
|
331
358
|
if (this.options.cacheScope) {
|
package/dist/sync/schemas.d.ts
CHANGED
|
@@ -70,6 +70,7 @@ export declare const BootstrapResponseSchema: z.ZodObject<{
|
|
|
70
70
|
deltaCount: z.ZodOptional<z.ZodNumber>;
|
|
71
71
|
failedModels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
72
72
|
timestamp: z.ZodDefault<z.ZodNumber>;
|
|
73
|
+
schemaHash: z.ZodOptional<z.ZodString>;
|
|
73
74
|
}, z.core.$loose>;
|
|
74
75
|
export type ValidatedBootstrapResponse = z.infer<typeof BootstrapResponseSchema>;
|
|
75
76
|
/**
|
package/dist/sync/schemas.js
CHANGED
|
@@ -54,6 +54,9 @@ export const BootstrapResponseSchema = z
|
|
|
54
54
|
deltaCount: z.number().optional(),
|
|
55
55
|
failedModels: z.array(z.string()).optional(),
|
|
56
56
|
timestamp: z.number().default(() => Date.now()),
|
|
57
|
+
// Server's active schema hash (drift detection). Optional: absent from
|
|
58
|
+
// older servers / tenants that have never pushed a schema.
|
|
59
|
+
schemaHash: z.string().optional(),
|
|
57
60
|
})
|
|
58
61
|
.passthrough();
|
|
59
62
|
// ─── Parse Helpers ───────────────────────────────────────────────────────────
|