@abloatai/ablo 0.10.1 → 0.11.1
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 +34 -0
- package/README.md +63 -23
- package/dist/BaseSyncedStore.d.ts +75 -0
- package/dist/BaseSyncedStore.js +193 -8
- package/dist/Database.d.ts +10 -2
- package/dist/Database.js +15 -1
- package/dist/SyncClient.d.ts +12 -1
- package/dist/SyncClient.js +110 -26
- package/dist/agent/Agent.d.ts +9 -9
- package/dist/agent/Agent.js +16 -16
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +2 -2
- package/dist/agent/types.d.ts +1 -1
- package/dist/agent/types.js +1 -1
- package/dist/ai-sdk/{intent-broadcast.d.ts → claim-broadcast.d.ts} +10 -10
- package/dist/ai-sdk/{intent-broadcast.js → claim-broadcast.js} +6 -6
- package/dist/ai-sdk/coordination-context.d.ts +9 -9
- package/dist/ai-sdk/coordination-context.js +8 -8
- package/dist/ai-sdk/index.d.ts +1 -1
- package/dist/ai-sdk/index.js +1 -1
- package/dist/ai-sdk/wrap.d.ts +4 -4
- package/dist/ai-sdk/wrap.js +4 -4
- package/dist/api/index.d.ts +2 -2
- package/dist/cli.cjs +369 -67
- package/dist/client/Ablo.d.ts +30 -63
- package/dist/client/Ablo.js +124 -103
- package/dist/client/ApiClient.d.ts +6 -5
- package/dist/client/ApiClient.js +86 -62
- package/dist/client/auth.d.ts +9 -4
- package/dist/client/auth.js +40 -5
- package/dist/client/createModelProxy.d.ts +41 -54
- package/dist/client/createModelProxy.js +123 -20
- package/dist/client/httpClient.d.ts +2 -0
- package/dist/client/httpClient.js +1 -1
- package/dist/client/index.d.ts +3 -3
- package/dist/client/writeOptionsSchema.d.ts +4 -4
- package/dist/client/writeOptionsSchema.js +4 -4
- package/dist/coordination/schema.d.ts +249 -38
- package/dist/coordination/schema.js +172 -39
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +4 -4
- package/dist/errorCodes.d.ts +9 -9
- package/dist/errorCodes.js +16 -16
- package/dist/errors.d.ts +51 -2
- package/dist/errors.js +94 -5
- package/dist/interfaces/index.d.ts +8 -4
- package/dist/policy/index.d.ts +1 -1
- package/dist/policy/types.d.ts +13 -13
- package/dist/policy/types.js +8 -8
- package/dist/react/AbloProvider.d.ts +51 -4
- package/dist/react/AbloProvider.js +95 -11
- package/dist/react/context.d.ts +26 -9
- package/dist/react/context.js +2 -2
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +4 -4
- package/dist/react/useAblo.js +5 -5
- package/dist/react/{useIntent.d.ts → useClaim.d.ts} +9 -9
- package/dist/react/useClaim.js +42 -0
- package/dist/schema/index.js +1 -1
- package/dist/schema/schema.d.ts +3 -3
- package/dist/schema/sugar.d.ts +3 -3
- package/dist/schema/sugar.js +3 -3
- package/dist/schema/sync-delta-wire.d.ts +8 -8
- package/dist/server/commit.d.ts +2 -2
- package/dist/sync/AreaOfInterestManager.d.ts +162 -0
- package/dist/sync/AreaOfInterestManager.js +233 -0
- package/dist/sync/BootstrapHelper.d.ts +9 -1
- package/dist/sync/BootstrapHelper.js +15 -5
- package/dist/sync/NetworkProbe.d.ts +1 -1
- package/dist/sync/NetworkProbe.js +1 -1
- package/dist/sync/SyncWebSocket.d.ts +59 -25
- package/dist/sync/SyncWebSocket.js +123 -26
- package/dist/sync/awaitClaimGrant.d.ts +40 -0
- package/dist/sync/awaitClaimGrant.js +86 -0
- package/dist/sync/createClaimStream.d.ts +34 -0
- package/dist/sync/{createIntentStream.js → createClaimStream.js} +92 -81
- package/dist/sync/createPresenceStream.js +3 -2
- package/dist/sync/participants.d.ts +10 -10
- package/dist/sync/participants.js +17 -10
- package/dist/sync/schemas.d.ts +8 -8
- package/dist/transactions/TransactionQueue.d.ts +23 -0
- package/dist/transactions/TransactionQueue.js +186 -12
- package/dist/types/global.d.ts +18 -13
- package/dist/types/global.js +11 -6
- package/dist/types/index.d.ts +9 -7
- package/dist/types/index.js +2 -2
- package/dist/types/streams.d.ts +114 -98
- package/dist/types/streams.js +1 -1
- package/dist/utils/asyncIterator.d.ts +1 -1
- package/dist/utils/asyncIterator.js +1 -1
- package/dist/wire/frames.d.ts +2 -2
- package/docs/api.md +3 -3
- package/docs/client-behavior.md +6 -3
- package/docs/coordination.md +13 -3
- package/docs/data-sources.md +29 -9
- package/docs/migration.md +40 -0
- package/docs/quickstart.md +61 -33
- package/docs/react.md +46 -0
- package/llms-full.txt +25 -8
- package/llms.txt +11 -9
- package/package.json +3 -2
- package/dist/react/useIntent.js +0 -42
- package/dist/sync/awaitIntentGrant.d.ts +0 -40
- package/dist/sync/awaitIntentGrant.js +0 -62
- package/dist/sync/createIntentStream.d.ts +0 -34
package/dist/cli.cjs
CHANGED
|
@@ -212180,11 +212180,11 @@ var require_commonjs2 = __commonJS({
|
|
|
212180
212180
|
if (pad) {
|
|
212181
212181
|
const need = width - c.length;
|
|
212182
212182
|
if (need > 0) {
|
|
212183
|
-
const
|
|
212183
|
+
const z6 = new Array(need + 1).join("0");
|
|
212184
212184
|
if (i < 0) {
|
|
212185
|
-
c = "-" +
|
|
212185
|
+
c = "-" + z6 + c.slice(1);
|
|
212186
212186
|
} else {
|
|
212187
|
-
c =
|
|
212187
|
+
c = z6 + c;
|
|
212188
212188
|
}
|
|
212189
212189
|
}
|
|
212190
212190
|
}
|
|
@@ -276682,8 +276682,8 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
276682
276682
|
if (i) process.stdout.write(`${I2} ${l2}...`);
|
|
276683
276683
|
else if (t === "timer") process.stdout.write(`${I2} ${l2} ${O2(g2)}`);
|
|
276684
276684
|
else {
|
|
276685
|
-
const
|
|
276686
|
-
process.stdout.write(`${I2} ${l2}${
|
|
276685
|
+
const z6 = ".".repeat(Math.floor(w2)).slice(0, 3);
|
|
276686
|
+
process.stdout.write(`${I2} ${l2}${z6}`);
|
|
276687
276687
|
}
|
|
276688
276688
|
h2 = h2 + 1 < n.length ? h2 + 1 : 0, w2 = w2 < n.length ? w2 + 0.125 : 0;
|
|
276689
276689
|
}, r2);
|
|
@@ -276710,7 +276710,7 @@ init_cjs_shims();
|
|
|
276710
276710
|
|
|
276711
276711
|
// src/errors.ts
|
|
276712
276712
|
init_cjs_shims();
|
|
276713
|
-
var
|
|
276713
|
+
var import_zod4 = require("zod");
|
|
276714
276714
|
|
|
276715
276715
|
// src/errorCodes.ts
|
|
276716
276716
|
init_cjs_shims();
|
|
@@ -276786,7 +276786,7 @@ var ERROR_CODES = {
|
|
|
276786
276786
|
byo_role_unreadable: wire("permission", 403, false, "The direct Postgres connector role could not be introspected."),
|
|
276787
276787
|
byo_tenant_tables_unforced_rls: wire("permission", 403, false, "Tenant tables do not have RLS forced under the direct Postgres connector role."),
|
|
276788
276788
|
byo_host_not_allowed: wire("permission", 403, false, "The direct Postgres connector host resolves to a private, loopback, or link-local address and cannot be used."),
|
|
276789
|
-
// ── claim /
|
|
276789
|
+
// ── claim / claim conflict (409) ──────────────────────────────────
|
|
276790
276790
|
// Held-claim rejections are NOT queue-retryable (gRPC FAILED_PRECONDITION /
|
|
276791
276791
|
// ABORTED semantics; Replicache/Zero SETTLE a rejected mutation — reject the
|
|
276792
276792
|
// caller, roll back the optimistic effect — instead of resending it).
|
|
@@ -276799,17 +276799,17 @@ var ERROR_CODES = {
|
|
|
276799
276799
|
claim_conflict: wire("claim", 409, false, "The target entity is claimed by another participant."),
|
|
276800
276800
|
claim_lost: wire("claim", 409, false, "A previously held claim was lost before the write applied."),
|
|
276801
276801
|
entity_claimed: wire("claim", 409, false, "The target entity is currently claimed; write was blocked."),
|
|
276802
|
-
intent_conflict: wire("claim", 409, false, "An intent on the target conflicts with an active intent (server-internal alias of claim_conflict)."),
|
|
276803
276802
|
malformed_claim: wire("claim", 400, false, "The claim payload was malformed."),
|
|
276803
|
+
malformed_subscription: wire("validation", 400, false, "The update_subscription payload was malformed; expected { syncGroups: string[] }."),
|
|
276804
276804
|
model_claimed: wire("claim", 409, false, "The model instance is claimed by another participant."),
|
|
276805
276805
|
model_claimed_timeout: wire("claim", 409, false, "Timed out waiting for a model claim to clear."),
|
|
276806
|
-
model_claim_not_configured: client("claim", "Claiming
|
|
276806
|
+
model_claim_not_configured: client("claim", "Claiming requires the collaboration runtime, which the standard Ablo({ schema, apiKey }) client wires up for every model automatically \u2014 there is no per-model claim configuration to add. This appears only when a model proxy is constructed directly without that runtime (an internal/advanced path)."),
|
|
276807
276807
|
// ── stale context / idempotency (409) ──────────────────────────────
|
|
276808
276808
|
stale_context: wire("conflict", 409, true, "The write carried a readAt watermark that is now stale; re-read and retry."),
|
|
276809
276809
|
idempotency_conflict: wire("conflict", 409, false, "The same Idempotency-Key was reused with a different request body."),
|
|
276810
276810
|
idempotency_key_too_long: wire("validation", 400, false, "The supplied Idempotency-Key exceeds the maximum length."),
|
|
276811
276811
|
// ── validation (400 / 422) ─────────────────────────────────────────
|
|
276812
|
-
write_options_invalid: client("validation", "The write options (`idempotencyKey` / `label` / `wait` / `readAt` / `onStale` / `
|
|
276812
|
+
write_options_invalid: client("validation", "The write options (`idempotencyKey` / `label` / `wait` / `readAt` / `onStale` / `claim`) failed validation against the write-options schema."),
|
|
276813
276813
|
source_operation_id_required: client("validation", "A data-source operation arrived without the entity `id` it targets."),
|
|
276814
276814
|
source_adapter_misconfigured: client("validation", "The data-source ORM adapter could not map a schema model onto the backing client (missing delegate or model)."),
|
|
276815
276815
|
source_event_invalid: client("validation", "A data-source outbox event could not be built \u2014 the operation carries no entity id and none was supplied."),
|
|
@@ -276867,15 +276867,15 @@ var ERROR_CODES = {
|
|
|
276867
276867
|
required_field_added: client("schema", "Migration adds a new required field."),
|
|
276868
276868
|
enum_value_removed: client("schema", "Migration removes an enum value (destructive classification)."),
|
|
276869
276869
|
risky_cast: client("schema", "Migration would perform a risky column type cast."),
|
|
276870
|
-
// ──
|
|
276871
|
-
|
|
276872
|
-
|
|
276873
|
-
|
|
276874
|
-
|
|
276875
|
-
|
|
276876
|
-
grant_timeout: wire("
|
|
276877
|
-
slide_intent_missing_deck_id: wire("
|
|
276878
|
-
slide_intent_unknown_sibling: wire("
|
|
276870
|
+
// ── claim / lease (409 / transport) ───────────────────────────────
|
|
276871
|
+
claim_lease_unavailable: wire("claim", 503, true, "The claim-lease coordination subsystem is unavailable; retry."),
|
|
276872
|
+
claim_not_wired: client("claim", "Claim support was used but is not wired in this runtime."),
|
|
276873
|
+
claim_queued: wire("claim", 409, true, "The claim was queued behind an active lease holder."),
|
|
276874
|
+
claim_wait_aborted: wire("claim", 409, true, "Waiting for the claim lease was aborted."),
|
|
276875
|
+
claim_wait_poll_interval_required: client("claim", "A poll interval is required when waiting on an claim."),
|
|
276876
|
+
grant_timeout: wire("claim", 504, true, "Timed out waiting for a capability grant."),
|
|
276877
|
+
slide_intent_missing_deck_id: wire("claim", 400, false, "A slide claim was missing its deck id."),
|
|
276878
|
+
slide_intent_unknown_sibling: wire("claim", 400, false, "A slide claim referenced an unknown sibling slide."),
|
|
276879
276879
|
// ── bootstrap (transport) ──────────────────────────────────────────
|
|
276880
276880
|
bootstrap_fetch_timeout: wire("bootstrap", 504, true, "The bootstrap fetch timed out."),
|
|
276881
276881
|
bootstrap_offline: wire("bootstrap", 503, true, "Bootstrap could not run because the client is offline."),
|
|
@@ -276978,7 +276978,7 @@ var ERROR_CODES = {
|
|
|
276978
276978
|
upload_items_required: wire("validation", 400, false, "The request must include a non-empty items array."),
|
|
276979
276979
|
presigned_url_failed: wire("server", 500, true, "Failed to generate a presigned upload URL."),
|
|
276980
276980
|
task_id_required: wire("validation", 400, false, "A task id is required for this request."),
|
|
276981
|
-
|
|
276981
|
+
claim_id_required: wire("validation", 400, false, "An claim id is required for this request."),
|
|
276982
276982
|
commit_operation_action_required: wire("validation", 400, false, "A commit operation is missing its `action`."),
|
|
276983
276983
|
commit_operation_unsupported: wire("validation", 400, false, "A commit operation used an unsupported `action`."),
|
|
276984
276984
|
usage_invalid: wire("validation", 400, false, "The usage request was invalid."),
|
|
@@ -276993,12 +276993,210 @@ var ERROR_CODES = {
|
|
|
276993
276993
|
parent_turn_foreign_agent: wire("permission", 403, false, "The parent turn belongs to a different agent."),
|
|
276994
276994
|
turn_not_found: wire("not_found", 404, false, "The referenced turn does not exist."),
|
|
276995
276995
|
turn_foreign_agent: wire("permission", 403, false, "The turn belongs to a different agent."),
|
|
276996
|
-
invalid_intent: wire("validation", 400, false, "The
|
|
276996
|
+
invalid_intent: wire("validation", 400, false, "The claim request was invalid."),
|
|
276997
276997
|
schema_too_large: wire("validation", 413, false, "The submitted schema exceeds the maximum size."),
|
|
276998
276998
|
invalid_schema: wire("validation", 400, false, "The submitted schema could not be parsed."),
|
|
276999
276999
|
incompatible_change: wire("conflict", 409, false, "The schema change is incompatible with the current schema.")
|
|
277000
277000
|
};
|
|
277001
277001
|
|
|
277002
|
+
// src/coordination/schema.ts
|
|
277003
|
+
init_cjs_shims();
|
|
277004
|
+
var import_zod3 = require("zod");
|
|
277005
|
+
|
|
277006
|
+
// src/schema/roles.ts
|
|
277007
|
+
init_cjs_shims();
|
|
277008
|
+
var import_zod2 = require("zod");
|
|
277009
|
+
var syncGroupSchema = import_zod2.z.templateLiteral([import_zod2.z.string().regex(/^[a-z][a-z0-9_]*$/), ":", import_zod2.z.string().min(1)]).brand();
|
|
277010
|
+
var syncGroupInputSchema = import_zod2.z.union([import_zod2.z.literal("default"), syncGroupSchema]);
|
|
277011
|
+
var roleSourceSchema = import_zod2.z.object({
|
|
277012
|
+
/** The context field to read, e.g. `'organizationId'`, `'id'`, `'deckId'`. */
|
|
277013
|
+
field: import_zod2.z.string().regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "source must be a valid identifier"),
|
|
277014
|
+
/**
|
|
277015
|
+
* When `true`, `field` holds an array; every non-empty string element yields
|
|
277016
|
+
* one group. When `false` (default), `field` is a scalar; truthy → one group.
|
|
277017
|
+
*/
|
|
277018
|
+
multi: import_zod2.z.boolean()
|
|
277019
|
+
});
|
|
277020
|
+
var roleSchema = import_zod2.z.object({
|
|
277021
|
+
kind: import_zod2.z.string().regex(/^[a-z][a-z0-9_]*$/, 'kind must be a lowercase identifier, e.g. "deck"'),
|
|
277022
|
+
source: roleSourceSchema
|
|
277023
|
+
});
|
|
277024
|
+
var scopeSchema = import_zod2.z.union([
|
|
277025
|
+
import_zod2.z.boolean(),
|
|
277026
|
+
import_zod2.z.string().regex(/^[a-z][a-z0-9_]*$/, 'scope kind must be a lowercase identifier, e.g. "dataroom"')
|
|
277027
|
+
]);
|
|
277028
|
+
var grantsRefSchema = import_zod2.z.object({
|
|
277029
|
+
subject: import_zod2.z.string().regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "grants.subject must name a relation"),
|
|
277030
|
+
scope: import_zod2.z.string().regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "grants.scope must name a relation")
|
|
277031
|
+
});
|
|
277032
|
+
|
|
277033
|
+
// src/coordination/schema.ts
|
|
277034
|
+
var targetRangeSchema = import_zod3.z.object({
|
|
277035
|
+
startLine: import_zod3.z.number(),
|
|
277036
|
+
endLine: import_zod3.z.number(),
|
|
277037
|
+
startColumn: import_zod3.z.number().optional(),
|
|
277038
|
+
endColumn: import_zod3.z.number().optional()
|
|
277039
|
+
});
|
|
277040
|
+
var participantKindSchema = import_zod3.z.enum(["user", "agent", "system"]);
|
|
277041
|
+
var wireParticipantKindSchema = import_zod3.z.preprocess(
|
|
277042
|
+
(value) => value === "human" ? "user" : value,
|
|
277043
|
+
participantKindSchema
|
|
277044
|
+
);
|
|
277045
|
+
var targetRefSchema = import_zod3.z.object({
|
|
277046
|
+
entityType: import_zod3.z.string(),
|
|
277047
|
+
entityId: import_zod3.z.string(),
|
|
277048
|
+
path: import_zod3.z.string().optional(),
|
|
277049
|
+
range: targetRangeSchema.optional(),
|
|
277050
|
+
field: import_zod3.z.string().optional(),
|
|
277051
|
+
meta: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional()
|
|
277052
|
+
});
|
|
277053
|
+
var onStaleModeSchema = import_zod3.z.enum(["reject", "force", "flag", "merge"]);
|
|
277054
|
+
var writeGuardSchema = import_zod3.z.object({
|
|
277055
|
+
readAt: import_zod3.z.number().nullish(),
|
|
277056
|
+
onStale: onStaleModeSchema.nullish(),
|
|
277057
|
+
bypass: import_zod3.z.boolean().optional()
|
|
277058
|
+
});
|
|
277059
|
+
var claimStatusSchema = import_zod3.z.enum([
|
|
277060
|
+
"active",
|
|
277061
|
+
"committed",
|
|
277062
|
+
"expired",
|
|
277063
|
+
"canceled"
|
|
277064
|
+
]);
|
|
277065
|
+
var wireClaimBaseSchema = targetRefSchema.extend({
|
|
277066
|
+
claimId: import_zod3.z.string(),
|
|
277067
|
+
/** Verb the agent expects: 'update' | 'create' | 'editing' | 'reviewing' … */
|
|
277068
|
+
action: import_zod3.z.string(),
|
|
277069
|
+
/** Server-stamped declaration time (epoch ms). */
|
|
277070
|
+
declaredAt: import_zod3.z.number(),
|
|
277071
|
+
/** Server-computed TTL deadline (epoch ms). Readers treat as advisory. */
|
|
277072
|
+
expiresAt: import_zod3.z.number(),
|
|
277073
|
+
status: claimStatusSchema.optional()
|
|
277074
|
+
});
|
|
277075
|
+
var wireClaimSummarySchema = wireClaimBaseSchema.pick({
|
|
277076
|
+
claimId: true,
|
|
277077
|
+
action: true,
|
|
277078
|
+
declaredAt: true,
|
|
277079
|
+
expiresAt: true,
|
|
277080
|
+
entityType: true,
|
|
277081
|
+
entityId: true,
|
|
277082
|
+
field: true,
|
|
277083
|
+
meta: true
|
|
277084
|
+
});
|
|
277085
|
+
var claimErrorSchema = import_zod3.z.object({
|
|
277086
|
+
code: import_zod3.z.string(),
|
|
277087
|
+
message: import_zod3.z.string().optional(),
|
|
277088
|
+
/** Participant already holding the target (conflict rejections). */
|
|
277089
|
+
heldBy: import_zod3.z.string().optional(),
|
|
277090
|
+
heldByClaimId: import_zod3.z.string().optional(),
|
|
277091
|
+
heldByExpiresAt: import_zod3.z.number().optional(),
|
|
277092
|
+
/** Rich holder context for conflict rejections. Additive: older frames omit it. */
|
|
277093
|
+
heldByClaim: wireClaimSummarySchema.optional(),
|
|
277094
|
+
/** Optional conflict-policy explanation. Additive: older frames omit it. */
|
|
277095
|
+
policyReason: import_zod3.z.string().optional()
|
|
277096
|
+
});
|
|
277097
|
+
var wireClaimSchema = wireClaimBaseSchema.extend({
|
|
277098
|
+
error: claimErrorSchema.optional()
|
|
277099
|
+
});
|
|
277100
|
+
var claimRejectionSchema = import_zod3.z.object({
|
|
277101
|
+
claimId: import_zod3.z.string(),
|
|
277102
|
+
reason: import_zod3.z.string(),
|
|
277103
|
+
target: targetRefSchema.optional(),
|
|
277104
|
+
heldBy: import_zod3.z.string().optional(),
|
|
277105
|
+
heldByClaimId: import_zod3.z.string().optional(),
|
|
277106
|
+
heldByExpiresAt: import_zod3.z.number().optional(),
|
|
277107
|
+
heldByClaim: wireClaimSummarySchema.optional(),
|
|
277108
|
+
policyReason: import_zod3.z.string().optional()
|
|
277109
|
+
});
|
|
277110
|
+
var modelTargetSchema = import_zod3.z.object({
|
|
277111
|
+
model: import_zod3.z.string(),
|
|
277112
|
+
id: import_zod3.z.string(),
|
|
277113
|
+
path: import_zod3.z.string().optional(),
|
|
277114
|
+
range: targetRangeSchema.optional(),
|
|
277115
|
+
field: import_zod3.z.string().optional(),
|
|
277116
|
+
meta: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional()
|
|
277117
|
+
}).readonly();
|
|
277118
|
+
var modelClaimSchema = import_zod3.z.object({
|
|
277119
|
+
id: import_zod3.z.string(),
|
|
277120
|
+
actor: import_zod3.z.string(),
|
|
277121
|
+
participantKind: wireParticipantKindSchema,
|
|
277122
|
+
action: import_zod3.z.string(),
|
|
277123
|
+
description: import_zod3.z.string().optional(),
|
|
277124
|
+
field: import_zod3.z.string().optional(),
|
|
277125
|
+
status: import_zod3.z.enum(["active", "queued"]).optional(),
|
|
277126
|
+
position: import_zod3.z.number().optional(),
|
|
277127
|
+
expiresAt: import_zod3.z.number(),
|
|
277128
|
+
target: modelTargetSchema
|
|
277129
|
+
}).readonly();
|
|
277130
|
+
var claimBeginPayloadSchema = targetRefSchema.extend({
|
|
277131
|
+
claimId: import_zod3.z.string(),
|
|
277132
|
+
action: import_zod3.z.string(),
|
|
277133
|
+
/** Hint for `expiresAt`; the server caps it. */
|
|
277134
|
+
estimatedMs: import_zod3.z.number().optional(),
|
|
277135
|
+
/**
|
|
277136
|
+
* Opt into the fair wait queue: when the target is already held, the server
|
|
277137
|
+
* enqueues this claim (FIFO) and replies `claim_queued` → later
|
|
277138
|
+
* `claim_granted`, instead of `claim_rejected`. Clients that set this MUST
|
|
277139
|
+
* handle the grant.
|
|
277140
|
+
*/
|
|
277141
|
+
queue: import_zod3.z.boolean().optional()
|
|
277142
|
+
});
|
|
277143
|
+
var claimAbandonPayloadSchema = import_zod3.z.object({
|
|
277144
|
+
claimId: import_zod3.z.string(),
|
|
277145
|
+
entityType: import_zod3.z.string().optional(),
|
|
277146
|
+
entityId: import_zod3.z.string().optional()
|
|
277147
|
+
});
|
|
277148
|
+
var claimReorderPayloadSchema = import_zod3.z.object({
|
|
277149
|
+
entityType: import_zod3.z.string(),
|
|
277150
|
+
entityId: import_zod3.z.string(),
|
|
277151
|
+
order: import_zod3.z.array(import_zod3.z.object({ heldBy: import_zod3.z.string(), claimId: import_zod3.z.string() }))
|
|
277152
|
+
});
|
|
277153
|
+
var updateSubscriptionPayloadSchema = import_zod3.z.object({
|
|
277154
|
+
syncGroups: import_zod3.z.array(syncGroupInputSchema)
|
|
277155
|
+
});
|
|
277156
|
+
var subscriptionAckPayloadSchema = import_zod3.z.object({
|
|
277157
|
+
success: import_zod3.z.boolean(),
|
|
277158
|
+
syncGroups: import_zod3.z.array(import_zod3.z.string()),
|
|
277159
|
+
error: import_zod3.z.object({ code: import_zod3.z.string(), message: import_zod3.z.string() }).optional()
|
|
277160
|
+
});
|
|
277161
|
+
var commitOperationTypeSchema = import_zod3.z.enum([
|
|
277162
|
+
"CREATE",
|
|
277163
|
+
"UPDATE",
|
|
277164
|
+
"DELETE",
|
|
277165
|
+
"ARCHIVE",
|
|
277166
|
+
"UNARCHIVE"
|
|
277167
|
+
]);
|
|
277168
|
+
var commitOperationSchema = writeGuardSchema.extend({
|
|
277169
|
+
type: commitOperationTypeSchema,
|
|
277170
|
+
model: import_zod3.z.string(),
|
|
277171
|
+
id: import_zod3.z.string().nullish(),
|
|
277172
|
+
input: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).nullish(),
|
|
277173
|
+
/** Per-op client tx id, echoed on the broadcast delta. */
|
|
277174
|
+
transactionId: import_zod3.z.string().nullish()
|
|
277175
|
+
});
|
|
277176
|
+
var presenceKindSchema = import_zod3.z.enum(["enter", "update", "leave"]);
|
|
277177
|
+
var presenceActivitySchema = targetRefSchema.extend({
|
|
277178
|
+
action: import_zod3.z.string(),
|
|
277179
|
+
detail: import_zod3.z.string().optional()
|
|
277180
|
+
});
|
|
277181
|
+
var presenceUpdateFrameSchema = import_zod3.z.object({
|
|
277182
|
+
kind: presenceKindSchema,
|
|
277183
|
+
userId: import_zod3.z.string().optional(),
|
|
277184
|
+
syncGroups: import_zod3.z.array(import_zod3.z.string()).optional(),
|
|
277185
|
+
timestamp: import_zod3.z.number().optional(),
|
|
277186
|
+
status: import_zod3.z.string(),
|
|
277187
|
+
timezone: import_zod3.z.string().optional(),
|
|
277188
|
+
customStatus: import_zod3.z.string().optional(),
|
|
277189
|
+
activity: presenceActivitySchema.optional(),
|
|
277190
|
+
isAgent: import_zod3.z.boolean().optional(),
|
|
277191
|
+
/**
|
|
277192
|
+
* Server-stamped canonical kind. Additive — older servers omit it and
|
|
277193
|
+
* readers fall back to `isAgent` (see {@link participantKindFromWire}).
|
|
277194
|
+
*/
|
|
277195
|
+
participantKind: wireParticipantKindSchema.optional(),
|
|
277196
|
+
activeClaims: import_zod3.z.array(wireClaimSchema).optional(),
|
|
277197
|
+
delegatedFrom: import_zod3.z.string().nullish()
|
|
277198
|
+
});
|
|
277199
|
+
|
|
277002
277200
|
// src/errors.ts
|
|
277003
277201
|
var AbloError = class extends Error {
|
|
277004
277202
|
/** Discriminator string — matches the class name. Lets consumers
|
|
@@ -277068,35 +277266,43 @@ function docUrlForCode(code) {
|
|
|
277068
277266
|
var AbloValidationError = class extends AbloError {
|
|
277069
277267
|
type = "AbloValidationError";
|
|
277070
277268
|
};
|
|
277071
|
-
var OptionalWireStringSchema =
|
|
277269
|
+
var OptionalWireStringSchema = import_zod4.z.preprocess(
|
|
277072
277270
|
(value) => typeof value === "string" ? value : void 0,
|
|
277073
|
-
|
|
277271
|
+
import_zod4.z.string().optional()
|
|
277074
277272
|
);
|
|
277075
|
-
var RequiredCapabilityWireSchema =
|
|
277076
|
-
scope:
|
|
277077
|
-
constraints:
|
|
277273
|
+
var RequiredCapabilityWireSchema = import_zod4.z.object({
|
|
277274
|
+
scope: import_zod4.z.string(),
|
|
277275
|
+
constraints: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.union([import_zod4.z.array(import_zod4.z.string()), import_zod4.z.string()])).optional(),
|
|
277078
277276
|
issuer: OptionalWireStringSchema,
|
|
277079
|
-
ttlSeconds:
|
|
277277
|
+
ttlSeconds: import_zod4.z.preprocess((value) => typeof value === "number" ? value : void 0, import_zod4.z.number().optional()),
|
|
277080
277278
|
nonce: OptionalWireStringSchema
|
|
277081
277279
|
}).passthrough();
|
|
277082
|
-
var NestedErrorShapeSchema =
|
|
277280
|
+
var NestedErrorShapeSchema = import_zod4.z.object({
|
|
277083
277281
|
code: OptionalWireStringSchema,
|
|
277084
277282
|
message: OptionalWireStringSchema,
|
|
277085
277283
|
field: OptionalWireStringSchema,
|
|
277086
|
-
requiredCapability: RequiredCapabilityWireSchema.optional().catch(void 0)
|
|
277284
|
+
requiredCapability: RequiredCapabilityWireSchema.optional().catch(void 0),
|
|
277285
|
+
heldBy: OptionalWireStringSchema,
|
|
277286
|
+
policyReason: OptionalWireStringSchema,
|
|
277287
|
+
heldByClaim: wireClaimSummarySchema.optional().catch(void 0),
|
|
277288
|
+
claims: import_zod4.z.array(wireClaimSummarySchema).optional().catch(void 0)
|
|
277087
277289
|
}).passthrough();
|
|
277088
|
-
var ErrorFieldSchema =
|
|
277290
|
+
var ErrorFieldSchema = import_zod4.z.preprocess(
|
|
277089
277291
|
(value) => typeof value === "string" || typeof value === "object" && value !== null ? value : void 0,
|
|
277090
|
-
|
|
277292
|
+
import_zod4.z.union([import_zod4.z.string(), NestedErrorShapeSchema]).optional()
|
|
277091
277293
|
).catch(void 0);
|
|
277092
|
-
var ErrorBodyShapeSchema =
|
|
277294
|
+
var ErrorBodyShapeSchema = import_zod4.z.object({
|
|
277093
277295
|
/** Legacy: `error` was a flat code string on older endpoints. Newer
|
|
277094
277296
|
* endpoints (CommitReceipt) carry `error` as a nested object. */
|
|
277095
277297
|
error: ErrorFieldSchema,
|
|
277096
277298
|
code: OptionalWireStringSchema,
|
|
277097
277299
|
reason: OptionalWireStringSchema,
|
|
277098
277300
|
message: OptionalWireStringSchema,
|
|
277099
|
-
requiredCapability: RequiredCapabilityWireSchema.optional().catch(void 0)
|
|
277301
|
+
requiredCapability: RequiredCapabilityWireSchema.optional().catch(void 0),
|
|
277302
|
+
heldBy: OptionalWireStringSchema,
|
|
277303
|
+
policyReason: OptionalWireStringSchema,
|
|
277304
|
+
heldByClaim: wireClaimSummarySchema.optional().catch(void 0),
|
|
277305
|
+
claims: import_zod4.z.array(wireClaimSummarySchema).optional().catch(void 0)
|
|
277100
277306
|
}).passthrough();
|
|
277101
277307
|
|
|
277102
277308
|
// src/cli/migrate.ts
|
|
@@ -279404,7 +279610,7 @@ function readProjectDatabaseUrl(cwd = process.cwd()) {
|
|
|
279404
279610
|
}
|
|
279405
279611
|
|
|
279406
279612
|
// src/cli/migrate.ts
|
|
279407
|
-
var
|
|
279613
|
+
var import_schema3 = require("@abloatai/ablo/schema");
|
|
279408
279614
|
var import_source = require("@abloatai/ablo/source");
|
|
279409
279615
|
|
|
279410
279616
|
// src/cli/push.ts
|
|
@@ -279412,7 +279618,7 @@ init_cjs_shims();
|
|
|
279412
279618
|
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
279413
279619
|
var import_fs4 = require("fs");
|
|
279414
279620
|
var import_path3 = require("path");
|
|
279415
|
-
var
|
|
279621
|
+
var import_schema2 = require("@abloatai/ablo/schema");
|
|
279416
279622
|
|
|
279417
279623
|
// src/cli/config.ts
|
|
279418
279624
|
init_cjs_shims();
|
|
@@ -279577,7 +279783,7 @@ function fmtSignal(s) {
|
|
|
279577
279783
|
return ` \u2022 ${import_picocolors3.default.bold(where ?? "?")} \u2014 ${sig.detail ?? ""}`;
|
|
279578
279784
|
}
|
|
279579
279785
|
async function pushSchema(schema, args) {
|
|
279580
|
-
const schemaJson = JSON.parse((0,
|
|
279786
|
+
const schemaJson = JSON.parse((0, import_schema2.serializeSchema)(schema));
|
|
279581
279787
|
const res = await fetch(`${args.url}/api/schema`, {
|
|
279582
279788
|
method: "POST",
|
|
279583
279789
|
headers: {
|
|
@@ -279690,7 +279896,7 @@ async function push(argv) {
|
|
|
279690
279896
|
process.exit(1);
|
|
279691
279897
|
}
|
|
279692
279898
|
const schema = await loadSchema(args.schemaPath, args.exportName);
|
|
279693
|
-
const hash = (0,
|
|
279899
|
+
const hash = (0, import_schema2.schemaHash)(schema);
|
|
279694
279900
|
console.log(
|
|
279695
279901
|
` Pushing ${import_picocolors3.default.bold(args.schemaPath)} ${import_picocolors3.default.dim(`(${Object.keys(schema.models).length} models, hash ${hash})`)} \u2192 ${import_picocolors3.default.dim(args.url)}`
|
|
279696
279902
|
);
|
|
@@ -279736,6 +279942,14 @@ async function push(argv) {
|
|
|
279736
279942
|
}
|
|
279737
279943
|
|
|
279738
279944
|
// src/cli/migrate.ts
|
|
279945
|
+
var MIGRATE_USAGE = ` ablo migrate \u2014 provision your schema's tables in your own Postgres (DATABASE_URL)
|
|
279946
|
+
|
|
279947
|
+
Usage:
|
|
279948
|
+
npx ablo migrate Create the synced-model tables (with row-level security)
|
|
279949
|
+
npx ablo migrate --dry-run Print the SQL without executing it
|
|
279950
|
+
npx ablo migrate --output schema.sql Write the SQL to a file instead of applying
|
|
279951
|
+
npx ablo migrate --schema <path> Use a schema file other than ablo/schema.ts
|
|
279952
|
+
npx ablo migrate --export <name> Use a named export other than \`schema\``;
|
|
279739
279953
|
var DEFAULT_SCHEMA_PATH2 = "ablo/schema.ts";
|
|
279740
279954
|
var DEFAULT_EXPORT2 = "schema";
|
|
279741
279955
|
function parseMigrateArgs(argv) {
|
|
@@ -279769,8 +279983,8 @@ function parseMigrateArgs(argv) {
|
|
|
279769
279983
|
return { schemaPath, exportName, targetSchema, dryRun, outputFile };
|
|
279770
279984
|
}
|
|
279771
279985
|
function planFor(schema, targetSchema = "public") {
|
|
279772
|
-
const schemaJson = JSON.parse((0,
|
|
279773
|
-
const plan = (0,
|
|
279986
|
+
const schemaJson = JSON.parse((0, import_schema3.serializeSchema)(schema));
|
|
279987
|
+
const plan = (0, import_schema3.generateProvisionPlan)(schemaJson, targetSchema, {
|
|
279774
279988
|
foreignKeys: targetSchema === "public"
|
|
279775
279989
|
});
|
|
279776
279990
|
const adapterTables = (0, import_source.adapterTableMigrations)().map((m2) => m2.up);
|
|
@@ -279895,7 +280109,7 @@ init_cjs_shims();
|
|
|
279895
280109
|
var import_fs6 = require("fs");
|
|
279896
280110
|
var import_path4 = require("path");
|
|
279897
280111
|
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
279898
|
-
var
|
|
280112
|
+
var import_schema4 = require("@abloatai/ablo/schema");
|
|
279899
280113
|
var DEFAULT_SCHEMA_PATH3 = "ablo/schema.ts";
|
|
279900
280114
|
var DEFAULT_EXPORT3 = "schema";
|
|
279901
280115
|
var DEFAULT_OUT = "ablo/generated.ts";
|
|
@@ -279932,8 +280146,8 @@ async function generate(argv) {
|
|
|
279932
280146
|
let source;
|
|
279933
280147
|
try {
|
|
279934
280148
|
const schema = await loadSchema(args.schemaPath, args.exportName);
|
|
279935
|
-
const schemaJson = JSON.parse((0,
|
|
279936
|
-
source = (0,
|
|
280149
|
+
const schemaJson = JSON.parse((0, import_schema4.serializeSchema)(schema));
|
|
280150
|
+
source = (0, import_schema4.generateTypes)(schemaJson);
|
|
279937
280151
|
} catch (err) {
|
|
279938
280152
|
console.error(import_picocolors5.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
279939
280153
|
process.exit(1);
|
|
@@ -279949,7 +280163,7 @@ init_cjs_shims();
|
|
|
279949
280163
|
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
279950
280164
|
var import_fs7 = require("fs");
|
|
279951
280165
|
var import_path5 = require("path");
|
|
279952
|
-
var
|
|
280166
|
+
var import_schema5 = require("@abloatai/ablo/schema");
|
|
279953
280167
|
|
|
279954
280168
|
// src/cli/theme.ts
|
|
279955
280169
|
init_cjs_shims();
|
|
@@ -280115,7 +280329,7 @@ async function dev(argv) {
|
|
|
280115
280329
|
const schema = await loadSchema(args.schemaPath, args.exportName);
|
|
280116
280330
|
const modelCount = Object.keys(schema.models).length;
|
|
280117
280331
|
console.log(
|
|
280118
|
-
` ${import_picocolors6.default.dim("schema")} ${import_picocolors6.default.bold(args.schemaPath)} ${import_picocolors6.default.dim(`(${modelCount} models, hash ${(0,
|
|
280332
|
+
` ${import_picocolors6.default.dim("schema")} ${import_picocolors6.default.bold(args.schemaPath)} ${import_picocolors6.default.dim(`(${modelCount} models, hash ${(0, import_schema5.schemaHash)(schema)})`)}`
|
|
280119
280333
|
);
|
|
280120
280334
|
console.log(` ${import_picocolors6.default.dim("key")} ${args.apiKey.slice(0, 12)}\u2026`);
|
|
280121
280335
|
console.log(` ${import_picocolors6.default.dim("api")} ${args.url}
|
|
@@ -280272,7 +280486,10 @@ ${import_picocolors7.default.dim(url)}`, "Approve in your browser");
|
|
|
280272
280486
|
s.message("Provisioning a sandbox key\u2026");
|
|
280273
280487
|
const provRes = await fetch(`${AUTH_URL}/api/cli/provision-key`, {
|
|
280274
280488
|
method: "POST",
|
|
280275
|
-
headers: { authorization: `Bearer ${accessToken}
|
|
280489
|
+
headers: { authorization: `Bearer ${accessToken}`, "content-type": "application/json" },
|
|
280490
|
+
// Pass the device_code so the server can scope the minted keys to the
|
|
280491
|
+
// project the user picked at /cli (login project picker). Harmless if none.
|
|
280492
|
+
body: JSON.stringify({ device_code: code.device_code })
|
|
280276
280493
|
}).catch(() => null);
|
|
280277
280494
|
if (!provRes || !provRes.ok) {
|
|
280278
280495
|
s.stop("Could not provision a key.");
|
|
@@ -280500,6 +280717,39 @@ async function projects(argv) {
|
|
|
280500
280717
|
);
|
|
280501
280718
|
return;
|
|
280502
280719
|
}
|
|
280720
|
+
if (sub === "rename") {
|
|
280721
|
+
const ref = argv[1];
|
|
280722
|
+
const name = argv.slice(2).join(" ").trim();
|
|
280723
|
+
if (!ref || ref.startsWith("-") || !name) {
|
|
280724
|
+
console.error(import_picocolors9.default.red(" usage: ablo projects rename <slug|id> <new name>"));
|
|
280725
|
+
process.exit(1);
|
|
280726
|
+
}
|
|
280727
|
+
const all = await fetchProjects();
|
|
280728
|
+
const target = all.find((p2) => p2.slug === ref || p2.id === ref);
|
|
280729
|
+
if (!target) {
|
|
280730
|
+
console.error(import_picocolors9.default.red(` No project "${ref}".`) + import_picocolors9.default.dim(" Run ablo projects list."));
|
|
280731
|
+
process.exit(1);
|
|
280732
|
+
}
|
|
280733
|
+
if (target.default) {
|
|
280734
|
+
console.error(import_picocolors9.default.red(" The default project cannot be renamed."));
|
|
280735
|
+
process.exit(1);
|
|
280736
|
+
}
|
|
280737
|
+
const { status: status2, body } = await request(`/api/v1/projects/${target.id}`, requireKey(), {
|
|
280738
|
+
method: "PATCH",
|
|
280739
|
+
body: { name }
|
|
280740
|
+
});
|
|
280741
|
+
if (status2 !== 200) {
|
|
280742
|
+
console.error(
|
|
280743
|
+
import_picocolors9.default.red(` Rename failed (${status2}): ${String(body.message ?? body.code ?? "")}`)
|
|
280744
|
+
);
|
|
280745
|
+
process.exit(1);
|
|
280746
|
+
}
|
|
280747
|
+
const updated = body;
|
|
280748
|
+
console.log(
|
|
280749
|
+
` ${import_picocolors9.default.green("\u2713")} Renamed ${import_picocolors9.default.bold(updated.slug)} \u2192 ${import_picocolors9.default.bold(updated.name ?? updated.slug)} ${import_picocolors9.default.dim(`(${updated.id})`)}`
|
|
280750
|
+
);
|
|
280751
|
+
return;
|
|
280752
|
+
}
|
|
280503
280753
|
if (sub === "use") {
|
|
280504
280754
|
const ref = argv[1];
|
|
280505
280755
|
if (!ref) {
|
|
@@ -280527,7 +280777,9 @@ async function projects(argv) {
|
|
|
280527
280777
|
return;
|
|
280528
280778
|
}
|
|
280529
280779
|
console.error(
|
|
280530
|
-
import_picocolors9.default.red(` unknown subcommand: ${sub}`) + import_picocolors9.default.dim(
|
|
280780
|
+
import_picocolors9.default.red(` unknown subcommand: ${sub}`) + import_picocolors9.default.dim(
|
|
280781
|
+
` (expected ${import_picocolors9.default.bold("list")}, ${import_picocolors9.default.bold("create")}, ${import_picocolors9.default.bold("rename")}, or ${import_picocolors9.default.bold("use")})`
|
|
280782
|
+
)
|
|
280531
280783
|
);
|
|
280532
280784
|
process.exit(1);
|
|
280533
280785
|
}
|
|
@@ -280937,7 +281189,7 @@ async function webhooks(argv) {
|
|
|
280937
281189
|
// src/cli/check.ts
|
|
280938
281190
|
init_cjs_shims();
|
|
280939
281191
|
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
280940
|
-
var
|
|
281192
|
+
var import_schema6 = require("@abloatai/ablo/schema");
|
|
280941
281193
|
var DEFAULT_SCHEMA_PATH4 = "ablo/schema.ts";
|
|
280942
281194
|
var DEFAULT_EXPORT4 = "schema";
|
|
280943
281195
|
var BASE_COLUMNS = /* @__PURE__ */ new Set(["id", "organization_id", "created_by", "created_at", "updated_at"]);
|
|
@@ -280982,7 +281234,7 @@ async function check(argv) {
|
|
|
280982
281234
|
process.exit(1);
|
|
280983
281235
|
}
|
|
280984
281236
|
const schema = await loadSchema(args.schemaPath, args.exportName);
|
|
280985
|
-
const schemaJson = JSON.parse((0,
|
|
281237
|
+
const schemaJson = JSON.parse((0, import_schema6.serializeSchema)(schema));
|
|
280986
281238
|
const sql = src_default(dbUrl, { max: 1, prepare: false, onnotice: () => {
|
|
280987
281239
|
} });
|
|
280988
281240
|
let rows;
|
|
@@ -281024,7 +281276,7 @@ async function check(argv) {
|
|
|
281024
281276
|
const problems = [];
|
|
281025
281277
|
const warns = [];
|
|
281026
281278
|
if (!present.has("id")) problems.push('missing primary key "id"');
|
|
281027
|
-
const orgCol = (0,
|
|
281279
|
+
const orgCol = (0, import_schema6.tenancyColumn)((0, import_schema6.resolveTenancy)(model));
|
|
281028
281280
|
if (orgCol && !present.has(orgCol)) {
|
|
281029
281281
|
problems.push(
|
|
281030
281282
|
`missing "${orgCol}" \u2014 Ablo isolates tenants (RLS) and routes realtime by it, so a table without it has no safe boundary. Add the column, or use a Data Source endpoint.`
|
|
@@ -281202,8 +281454,8 @@ async function upgrade(argv) {
|
|
|
281202
281454
|
if (t === "drizzleDataSource" && call.getArguments().length === 2 && !import_ts_morph.Node.isIdentifier(call.getArguments()[1])) {
|
|
281203
281455
|
flag2(call, "drizzleDataSource(db, tables)", "now `drizzleDataSource(db, schema)` \u2014 pass your Ablo schema, drop the tables map.");
|
|
281204
281456
|
}
|
|
281205
|
-
if (/\.
|
|
281206
|
-
flag2(call, "ablo.
|
|
281457
|
+
if (/\.claims\b/.test(t) && /^(ablo|sync)\b/.test(t)) {
|
|
281458
|
+
flag2(call, "ablo.claims.*", "use `ablo.<model>.claim` (claim.state / claim.queue / `await using claim = await \u2026claim({ id })`).");
|
|
281207
281459
|
}
|
|
281208
281460
|
}
|
|
281209
281461
|
for (const jsx of sf.getDescendantsOfKind(import_ts_morph.SyntaxKind.JsxOpeningElement)) {
|
|
@@ -281924,8 +282176,18 @@ async function drizzlePull(argv) {
|
|
|
281924
282176
|
var LOGO = `
|
|
281925
282177
|
${brand("ablo")} ${import_picocolors18.default.dim("sync engine")}
|
|
281926
282178
|
`;
|
|
282179
|
+
var SUBCOMMAND_USAGE = {
|
|
282180
|
+
migrate: MIGRATE_USAGE
|
|
282181
|
+
};
|
|
281927
282182
|
async function main() {
|
|
281928
|
-
|
|
282183
|
+
let command = process.argv[2];
|
|
282184
|
+
if (command && process.argv.slice(3).some((a) => a === "--help" || a === "-h")) {
|
|
282185
|
+
if (SUBCOMMAND_USAGE[command]) {
|
|
282186
|
+
console.log(SUBCOMMAND_USAGE[command]);
|
|
282187
|
+
return;
|
|
282188
|
+
}
|
|
282189
|
+
command = void 0;
|
|
282190
|
+
}
|
|
281929
282191
|
if (command === "init") {
|
|
281930
282192
|
await init(process.argv.slice(3));
|
|
281931
282193
|
} else if (command === "login") {
|
|
@@ -281943,8 +282205,14 @@ async function main() {
|
|
|
281943
282205
|
} else if (command === "webhooks") {
|
|
281944
282206
|
await webhooks(process.argv.slice(3));
|
|
281945
282207
|
} else if (command === "dev") {
|
|
281946
|
-
|
|
281947
|
-
|
|
282208
|
+
const devArgs = process.argv.slice(3);
|
|
282209
|
+
const oneShot = devArgs.includes("--no-watch");
|
|
282210
|
+
console.log(
|
|
282211
|
+
import_picocolors18.default.dim(
|
|
282212
|
+
oneShot ? " `ablo dev --no-watch` is `ablo push` (push once, no watcher) \u2014 running that." : " `ablo dev` is now `ablo push --watch` \u2014 running that."
|
|
282213
|
+
)
|
|
282214
|
+
);
|
|
282215
|
+
await dev(oneShot ? devArgs : [...devArgs, "--watch"]);
|
|
281948
282216
|
} else if (command === "check") {
|
|
281949
282217
|
await check(process.argv.slice(3));
|
|
281950
282218
|
} else if (command === "pull") {
|
|
@@ -282002,6 +282270,8 @@ async function main() {
|
|
|
282002
282270
|
console.log(` npx ablo pull prisma [path] Generate schema.ts from a Prisma schema (keeps enums + relations)`);
|
|
282003
282271
|
console.log(` npx ablo pull drizzle <module> Generate schema.ts from a Drizzle schema (keeps enums + relations)`);
|
|
282004
282272
|
console.log(` npx ablo check Check your existing database fits the schema (read-only, creates no tables)`);
|
|
282273
|
+
console.log(` npx ablo migrate Provision your synced-model tables in your own Postgres (DATABASE_URL)`);
|
|
282274
|
+
console.log(` npx ablo migrate --dry-run Print the SQL without executing (preview)`);
|
|
282005
282275
|
console.log(` npx ablo push Upload your schema definition to Ablo (metadata only \u2014 rows stay in your DB)`);
|
|
282006
282276
|
console.log(` npx ablo push --force Allow destructive/unexecutable changes`);
|
|
282007
282277
|
console.log(` npx ablo push --rename a:b Treat model "a" as renamed to "b"`);
|
|
@@ -282079,6 +282349,10 @@ function detectOrm(override) {
|
|
|
282079
282349
|
}
|
|
282080
282350
|
return "none";
|
|
282081
282351
|
}
|
|
282352
|
+
function detectNextLayout() {
|
|
282353
|
+
const useSrc = (0, import_fs12.existsSync)((0, import_path7.join)("src", "app")) || !(0, import_fs12.existsSync)("app") && (0, import_fs12.existsSync)("src");
|
|
282354
|
+
return useSrc ? { appBase: (0, import_path7.join)("src", "app"), aliasBase: "src" } : { appBase: "app", aliasBase: "." };
|
|
282355
|
+
}
|
|
282082
282356
|
async function chooseOption(name, flagValue, fallback, allowed, interactive, prompt) {
|
|
282083
282357
|
if (flagValue !== void 0) {
|
|
282084
282358
|
if (!allowed.includes(flagValue)) {
|
|
@@ -282178,7 +282452,8 @@ async function init(args = []) {
|
|
|
282178
282452
|
"Non-interactive (no TTY / --yes)"
|
|
282179
282453
|
);
|
|
282180
282454
|
}
|
|
282181
|
-
const
|
|
282455
|
+
const layout = framework === "nextjs" ? detectNextLayout() : { appBase: "app", aliasBase: "." };
|
|
282456
|
+
const abloDir = (0, import_path7.join)(layout.aliasBase, "ablo");
|
|
282182
282457
|
(0, import_fs12.mkdirSync)(abloDir, { recursive: true });
|
|
282183
282458
|
const created = [];
|
|
282184
282459
|
let schemaSource = generateSchema();
|
|
@@ -282209,41 +282484,51 @@ async function init(args = []) {
|
|
|
282209
282484
|
created.push(`${abloDir}/schema.ts${schemaNote}`);
|
|
282210
282485
|
(0, import_fs12.writeFileSync)((0, import_path7.join)(abloDir, "index.ts"), generateSyncConfig(auth, storage));
|
|
282211
282486
|
created.push(`${abloDir}/index.ts`);
|
|
282487
|
+
(0, import_fs12.writeFileSync)((0, import_path7.join)(abloDir, "register.ts"), generateRegister());
|
|
282488
|
+
created.push(`${abloDir}/register.ts`);
|
|
282212
282489
|
const orm = detectOrm(opts.orm);
|
|
282213
282490
|
if (storage === "endpoint") {
|
|
282214
282491
|
(0, import_fs12.writeFileSync)((0, import_path7.join)(abloDir, "data-source.ts"), generateDataSource(orm));
|
|
282215
282492
|
created.push(`${abloDir}/data-source.ts${orm === "drizzle" ? " (Drizzle)" : " (Prisma)"}`);
|
|
282216
282493
|
}
|
|
282217
282494
|
const envFile = framework === "nextjs" ? ".env.local" : ".env";
|
|
282495
|
+
const resolvedKey = process.env.ABLO_API_KEY ? void 0 : resolveApiKey("sandbox");
|
|
282496
|
+
const wireRealKey = envFile === ".env.local" && Boolean(resolvedKey);
|
|
282497
|
+
const envBody = generateEnv(storage, { includeApiKey: !wireRealKey });
|
|
282218
282498
|
if (!(0, import_fs12.existsSync)(envFile)) {
|
|
282219
|
-
(0, import_fs12.writeFileSync)(envFile,
|
|
282499
|
+
(0, import_fs12.writeFileSync)(envFile, envBody);
|
|
282220
282500
|
created.push(envFile);
|
|
282221
282501
|
} else {
|
|
282222
282502
|
const existing = (0, import_fs12.readFileSync)(envFile, "utf-8");
|
|
282223
282503
|
if (!existing.includes("ABLO_")) {
|
|
282224
|
-
(0, import_fs12.writeFileSync)(envFile, existing + "\n" +
|
|
282504
|
+
(0, import_fs12.writeFileSync)(envFile, existing + "\n" + envBody);
|
|
282225
282505
|
created.push(`${envFile} ${import_picocolors18.default.dim("(appended)")}`);
|
|
282226
282506
|
} else {
|
|
282227
282507
|
created.push(`${envFile} ${import_picocolors18.default.dim("(already configured)")}`);
|
|
282228
282508
|
}
|
|
282229
282509
|
}
|
|
282510
|
+
if (wireRealKey && resolvedKey) {
|
|
282511
|
+
wireEnvLocal(resolvedKey);
|
|
282512
|
+
created.push(`.env.local ${import_picocolors18.default.dim("(ABLO_API_KEY set from your login)")}`);
|
|
282513
|
+
}
|
|
282230
282514
|
if (agent) {
|
|
282231
282515
|
(0, import_fs12.writeFileSync)((0, import_path7.join)(abloDir, "agent.ts"), generateAgent());
|
|
282232
282516
|
created.push(`${abloDir}/agent.ts`);
|
|
282233
282517
|
}
|
|
282234
282518
|
if (framework === "nextjs") {
|
|
282235
282519
|
if (storage === "endpoint") {
|
|
282236
|
-
const webhookDir = (0, import_path7.join)(
|
|
282520
|
+
const webhookDir = (0, import_path7.join)(layout.appBase, "api", "ablo", "webhooks");
|
|
282237
282521
|
(0, import_fs12.mkdirSync)(webhookDir, { recursive: true });
|
|
282238
282522
|
(0, import_fs12.writeFileSync)((0, import_path7.join)(webhookDir, "route.ts"), generateWebhookRoute(orm));
|
|
282239
282523
|
created.push(`${webhookDir}/route.ts${orm === "prisma" ? " (Prisma mirror)" : " (add your database write)"}`);
|
|
282240
282524
|
}
|
|
282241
|
-
|
|
282242
|
-
|
|
282243
|
-
|
|
282525
|
+
const providersPath = (0, import_path7.join)(layout.appBase, "providers.tsx");
|
|
282526
|
+
(0, import_fs12.writeFileSync)(providersPath, generateProviders());
|
|
282527
|
+
created.push(`${providersPath} ${import_picocolors18.default.dim(`(wrap ${(0, import_path7.join)(layout.appBase, "layout.tsx")} in <Providers>)`)}`);
|
|
282528
|
+
const sessionDir = (0, import_path7.join)(layout.appBase, "api", "ablo-session");
|
|
282244
282529
|
(0, import_fs12.mkdirSync)(sessionDir, { recursive: true });
|
|
282245
282530
|
(0, import_fs12.writeFileSync)((0, import_path7.join)(sessionDir, "route.ts"), generateSessionRoute());
|
|
282246
|
-
created.push(
|
|
282531
|
+
created.push(`${(0, import_path7.join)(sessionDir, "route.ts")} ${import_picocolors18.default.dim("(wire your auth)")}`);
|
|
282247
282532
|
}
|
|
282248
282533
|
if (framework !== "vanilla") {
|
|
282249
282534
|
(0, import_fs12.writeFileSync)((0, import_path7.join)(abloDir, "TaskList.tsx"), generateComponent());
|
|
@@ -282272,7 +282557,7 @@ async function init(args = []) {
|
|
|
282272
282557
|
`Provision your DB: ${import_picocolors18.default.bold("npx ablo migrate")} (creates your Ablo-model tables + the adapter tables; keep your own migrations for everything else), then mount ${import_picocolors18.default.bold(`${abloDir}/data-source.ts`)} at ${import_picocolors18.default.bold("/api/ablo/source")}`
|
|
282273
282558
|
],
|
|
282274
282559
|
...framework === "nextjs" ? [
|
|
282275
|
-
`Wrap ${import_picocolors18.default.bold("
|
|
282560
|
+
`Wrap ${import_picocolors18.default.bold((0, import_path7.join)(layout.appBase, "layout.tsx"))} in ${import_picocolors18.default.bold("<Providers>")} (${(0, import_path7.join)(layout.appBase, "providers.tsx")}) and add your auth to ${import_picocolors18.default.bold((0, import_path7.join)(layout.appBase, "api", "ablo-session", "route.ts"))}`
|
|
282276
282561
|
] : [],
|
|
282277
282562
|
`Run ${import_picocolors18.default.bold(`${pm} run dev`)} and open two browser tabs \u2014 changes sync in real-time`,
|
|
282278
282563
|
...agent ? [
|
|
@@ -282351,14 +282636,31 @@ export const sync = Ablo({
|
|
|
282351
282636
|
apiKey: process.env.ABLO_API_KEY,${databaseLine}${authLine}
|
|
282352
282637
|
schema,
|
|
282353
282638
|
});
|
|
282639
|
+
|
|
282640
|
+
// Name the client's type off the constructed value \u2014 the overload resolves at
|
|
282641
|
+
// this call site, so this carries the full typed surface. (Like tRPC's
|
|
282642
|
+
// \`typeof appRouter\`, Drizzle's \`typeof db\`.) Prefer this over \`ReturnType<typeof Ablo>\`.
|
|
282643
|
+
export type Sync = typeof sync;
|
|
282644
|
+
`;
|
|
282645
|
+
}
|
|
282646
|
+
function generateRegister() {
|
|
282647
|
+
return `import type { schema } from './schema';
|
|
282648
|
+
|
|
282649
|
+
declare module '@abloatai/ablo' {
|
|
282650
|
+
interface Register {
|
|
282651
|
+
Schema: typeof schema;
|
|
282652
|
+
}
|
|
282653
|
+
}
|
|
282654
|
+
|
|
282655
|
+
export {};
|
|
282354
282656
|
`;
|
|
282355
282657
|
}
|
|
282356
|
-
function generateEnv(storage) {
|
|
282658
|
+
function generateEnv(storage, opts = {}) {
|
|
282659
|
+
const { includeApiKey = true } = opts;
|
|
282357
282660
|
const databaseBlock = storage === "direct" ? "# Your Postgres \u2014 the system of record. The client registers this connection\n# (sent once over TLS, stored sealed) and every row lives HERE, never with Ablo.\n# Use a dedicated non-superuser role; the browser never sees this value.\nDATABASE_URL=postgres://user:password@host:5432/db\n" : "# Used by ablo/data-source.ts (your DB endpoint) + `ablo migrate` \u2014 NOT the client.\n# Ablo never sees it; the browser never sees it. Your DB stays in your app.\nDATABASE_URL=postgres://user:password@host:5432/db\n";
|
|
282358
282661
|
const webhookBlock = storage === "endpoint" ? "# Signing secret for the webhook receiver (app/api/ablo/webhooks/route.ts).\n# Ablo mints this when you register the endpoint's URL (POST /v1/webhook_endpoints\n# or the dashboard) and returns it once \u2014 paste it here.\nABLO_WEBHOOK_SECRET=whsec_your_endpoint_secret_here\n" : "";
|
|
282359
|
-
|
|
282360
|
-
|
|
282361
|
-
${webhookBlock}${databaseBlock}`;
|
|
282662
|
+
const apiKeyBlock = includeApiKey ? "# Ablo Sync Engine \u2014 use a sk_test_ key for local dev (`npx ablo push`)\nABLO_API_KEY=sk_test_your_key_here\n" : "";
|
|
282663
|
+
return `${apiKeyBlock}${webhookBlock}${databaseBlock}`;
|
|
282362
282664
|
}
|
|
282363
282665
|
function generateDataSource(orm) {
|
|
282364
282666
|
return orm === "drizzle" ? drizzleDataSourceScaffold() : prismaDataSourceScaffold();
|