@korajs/core 1.0.0-beta.0 → 1.0.0-beta.10

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/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { R as RandomSource, A as AtomicOpType, a as AtomicOp, F as FieldBuilder, C as CustomResolver, M as MigrationDefinition, S as SchemaDefinition, b as CollectionDefinition, c as RelationDefinition, O as OperationType, E as EnumFieldBuilder, d as ArrayFieldBuilder, e as FieldKind, f as Operation, V as VersionVector, g as MigrationStep, h as StateMachineConstraint, T as TransitionMap, i as TransitionValidationResult } from './events-BynBOsO3.cjs';
2
- export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp, K as KoraEvent, o as KoraEventByType, p as KoraEventEmitter, q as KoraEventListener, r as KoraEventType, s as MERGE_STRATEGIES, t as MergeStrategy, u as MergeTrace, v as MigrationBuilder, w as OnDeleteAction, x as OperationInput, y as RelationType, z as RollbackBuilder, B as SequenceConfig, D as StateMachineDefinition, G as SyncDiagnosticsSnapshot, I as SyncRuleDefinition, J as TimeSource, L as migrate, N as t } from './events-BynBOsO3.cjs';
3
- export { H as HybridLogicalClock, M as MAX_LOGICAL, c as createOperation, i as isValidOperation, v as verifyOperationIntegrity } from './operation-BpZlYSpe.cjs';
4
- export { S as ScopeMap, b as buildScopeMap } from './build-scope-map-BIeawJzC.cjs';
1
+ import { R as RandomSource, B as BlobRef, C as CollectionDefinition, A as AtomicOpType, a as AtomicOp, F as FieldBuilder, b as CustomResolver, M as MigrationDefinition, S as SchemaDefinition, c as RelationDefinition, O as OperationType, E as EnumFieldBuilder, J as JsonFieldBuilder, d as ArrayFieldBuilder, e as FieldKind, f as Operation, V as VersionVector, g as MigrationStep, h as StateMachineConstraint, T as TransitionMap, i as TransitionValidationResult } from './events-3z0Tema3.cjs';
2
+ export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp, K as KoraEvent, o as KoraEventByType, p as KoraEventEmitter, q as KoraEventListener, r as KoraEventType, s as MERGE_STRATEGIES, t as MergeStrategy, u as MergeTrace, v as MigrationBuilder, w as OnDeleteAction, x as OperationInput, y as RelationType, z as RollbackBuilder, D as SecretMode, G as SequenceConfig, I as StateMachineDefinition, L as SyncDiagnosticsSnapshot, N as SyncRuleDefinition, P as TimeSource, Q as migrate, U as t } from './events-3z0Tema3.cjs';
3
+ export { H as HybridLogicalClock, M as MAX_LOGICAL, c as createOperation, i as isValidOperation, v as verifyOperationIntegrity } from './operation-BvBgl-4c.cjs';
4
+ export { S as ScopeMap, b as buildScopeMap } from './build-scope-map-B8dpCt6P.cjs';
5
5
 
6
6
  /**
7
7
  * Base error class for all Kora errors.
@@ -161,6 +161,137 @@ declare function extractTimestamp(uuid: string): number;
161
161
  */
162
162
  declare function isValidUUIDv7(uuid: string): boolean;
163
163
 
164
+ /**
165
+ * Compute the hex-encoded SHA-256 content hash of a byte buffer.
166
+ *
167
+ * This is the content address of a blob: identical bytes always hash to the same
168
+ * value, which is what lets the blob store deduplicate content and lets a peer
169
+ * skip transferring bytes it already holds.
170
+ *
171
+ * @param bytes - The binary content to hash
172
+ * @returns The hex-encoded SHA-256 hash
173
+ */
174
+ declare function hashBlob(bytes: Uint8Array): Promise<string>;
175
+ /** Optional metadata carried alongside a blob reference. */
176
+ interface BlobRefMetadata {
177
+ mimeType?: string;
178
+ filename?: string;
179
+ }
180
+ /**
181
+ * Create a content-addressed {@link BlobRef} for a byte buffer.
182
+ *
183
+ * @param bytes - The binary content
184
+ * @param metadata - Optional MIME type and filename
185
+ * @returns A reference carrying the content hash, size, and metadata
186
+ */
187
+ declare function createBlobRef(bytes: Uint8Array, metadata?: BlobRefMetadata): Promise<BlobRef>;
188
+ /**
189
+ * Type guard: whether a value is a structurally valid {@link BlobRef}.
190
+ *
191
+ * Validates the shape only (a non-empty hex hash and a non-negative size); it
192
+ * does not verify that the bytes behind the hash exist or match. Integrity
193
+ * verification against the actual bytes happens in the blob store on read.
194
+ */
195
+ declare function isBlobRef(value: unknown): value is BlobRef;
196
+
197
+ /**
198
+ * Field-level cryptography for `secret` fields.
199
+ *
200
+ * Two protection modes, matching the two ways secrets are used:
201
+ * - `encrypted`: reversible AES-256-GCM (tokens, API keys — decrypt to use).
202
+ * - `hashed`: one-way PBKDF2-SHA-256 with a random salt (passwords — verify only).
203
+ *
204
+ * These primitives use only the standard WebCrypto API so they live in
205
+ * `@korajs/core` with no dependency on `@korajs/auth`; a `secret` field is
206
+ * therefore self-contained. Higher-level key management composes on top.
207
+ */
208
+ /**
209
+ * Encrypt a secret's plaintext with AES-256-GCM under a key derived from
210
+ * `secretKey`. The returned string bundles the salt, IV, and ciphertext (all hex,
211
+ * dot-separated) so it is self-describing and safe to store and sync.
212
+ *
213
+ * @param plaintext - The secret value to protect
214
+ * @param secretKey - The key material (from a key provider), never stored
215
+ * @returns An opaque `v1.salt.iv.ciphertext` string
216
+ */
217
+ declare function encryptSecret(plaintext: string, secretKey: string): Promise<string>;
218
+ /**
219
+ * Decrypt a value produced by {@link encryptSecret} with the same key.
220
+ *
221
+ * @param encrypted - The `v1.salt.iv.ciphertext` string
222
+ * @param secretKey - The key material used to encrypt
223
+ * @returns The original plaintext
224
+ * @throws If the format is invalid or the key is wrong (GCM auth failure)
225
+ */
226
+ declare function decryptSecret(encrypted: string, secretKey: string): Promise<string>;
227
+ /**
228
+ * One-way hash a secret (a password) with PBKDF2-SHA-256 and a random salt.
229
+ * The result bundles the salt and hash so {@link verifySecret} needs nothing
230
+ * else. There is no way to recover the plaintext from the result.
231
+ *
232
+ * @param plaintext - The secret value to hash
233
+ * @returns An opaque `v1.salt.hash` string
234
+ */
235
+ declare function hashSecret(plaintext: string): Promise<string>;
236
+ /**
237
+ * Verify a plaintext against a value produced by {@link hashSecret}, in constant
238
+ * time with respect to the stored hash.
239
+ *
240
+ * @param plaintext - The candidate secret
241
+ * @param stored - The `v1.salt.hash` string
242
+ * @returns Whether the plaintext matches
243
+ */
244
+ declare function verifySecret(plaintext: string, stored: string): Promise<boolean>;
245
+
246
+ /**
247
+ * Provider of the key material used to encrypt reversible (`encrypted`) secret
248
+ * fields. Called at write and reveal time so the key can be loaded lazily (for
249
+ * example derived from a user passphrase after unlock). Returns undefined when
250
+ * no key is available.
251
+ */
252
+ type SecretKeyProvider = () => string | undefined | Promise<string | undefined>;
253
+ /** Thrown when an `encrypted` secret field is written or read without a key. */
254
+ declare class MissingSecretKeyError extends Error {
255
+ readonly field: string;
256
+ constructor(field: string);
257
+ }
258
+ /**
259
+ * Transform the secret fields of a record's write payload into their at-rest
260
+ * form BEFORE the operation is created, so plaintext never enters the operation
261
+ * log, the store, or the sync stream.
262
+ *
263
+ * - `hashed` fields become a one-way salted hash.
264
+ * - `encrypted` fields become ciphertext (requires a key).
265
+ *
266
+ * Non-secret fields, and secret fields not present in `data`, are passed through
267
+ * untouched. Null/undefined secret values are left as-is (nothing to protect).
268
+ *
269
+ * @param data - The validated write payload (plaintext secret values)
270
+ * @param collectionDef - The collection definition (for field kinds/modes)
271
+ * @param keyProvider - Supplies the encryption key for `encrypted` fields
272
+ * @returns A new payload with secret fields replaced by their at-rest form
273
+ */
274
+ declare function transformSecretFieldsForWrite(data: Record<string, unknown>, collectionDef: CollectionDefinition, keyProvider?: SecretKeyProvider): Promise<Record<string, unknown>>;
275
+ /**
276
+ * Reveal the plaintext of an `encrypted` secret field's stored value. Throws for
277
+ * `hashed` fields, which are one-way and cannot be revealed.
278
+ *
279
+ * @param storedValue - The at-rest value (ciphertext)
280
+ * @param mode - The field's secret mode
281
+ * @param keyProvider - Supplies the decryption key
282
+ * @param field - Field name (for error messages)
283
+ * @returns The decrypted plaintext
284
+ */
285
+ declare function revealSecret(storedValue: string, mode: 'hashed' | 'encrypted', keyProvider: SecretKeyProvider | undefined, field?: string): Promise<string>;
286
+ /**
287
+ * Verify a plaintext candidate against a `hashed` secret field's stored value.
288
+ *
289
+ * @param candidate - The plaintext to check (for example a login password)
290
+ * @param storedValue - The stored one-way hash
291
+ * @returns Whether the candidate matches
292
+ */
293
+ declare function verifySecretValue(candidate: string, storedValue: string): Promise<boolean>;
294
+
164
295
  /**
165
296
  * Outcome of applying a single operation to materialized storage (local or remote).
166
297
  */
@@ -228,6 +359,20 @@ interface AtomicOpSentinel {
228
359
  * @returns true if the value is an AtomicOpSentinel
229
360
  */
230
361
  declare function isAtomicOp(value: unknown): value is AtomicOpSentinel;
362
+ /**
363
+ * Apply a plain atomic op (`{ type, value }`) to a current value, producing the
364
+ * concrete result. This is the single source of truth for atomic-op semantics:
365
+ * {@link resolveAtomicOp} (sentinel form, used on the write path) delegates here,
366
+ * and the server's materialization replays stored atomic ops through it, so the
367
+ * server's materialized view composes concurrent atomic writes identically to the
368
+ * client. Folding this over a field's writes in HLC order yields, for a same-type
369
+ * atomic chain, exactly the composed intent (sum of increments, max of maxes, ...).
370
+ *
371
+ * @param currentValue - The current value of the field
372
+ * @param atomicOp - The atomic op to apply (type + operand)
373
+ * @returns The resulting concrete value
374
+ */
375
+ declare function applyAtomicOp(currentValue: unknown, atomicOp: AtomicOp): unknown;
231
376
  /**
232
377
  * Resolve an atomic op sentinel against a current value to produce a concrete result.
233
378
  *
@@ -306,6 +451,40 @@ declare const op: {
306
451
  */
307
452
  declare function toAtomicOp(sentinel: AtomicOpSentinel): AtomicOp;
308
453
 
454
+ /** One operation's contribution to a record's materialized state. */
455
+ interface ReplayOperation {
456
+ type: string;
457
+ data: Record<string, unknown> | null;
458
+ /**
459
+ * Atomic-op intents carried by this operation, per field. When present, a field
460
+ * is composed (rather than overwritten) if the previous writer on that field was
461
+ * an atomic op of the same type. Absent means every field resolves by
462
+ * last-write-wins.
463
+ */
464
+ atomicOps?: Record<string, AtomicOp> | null;
465
+ }
466
+ /**
467
+ * Replay a list of operations (MUST be pre-sorted in HLC total order —
468
+ * wallTime, then logical, then nodeId) to produce the current state of a single
469
+ * record, composing atomic-op intents.
470
+ *
471
+ * Per field, an atomic op composes onto the running value only when the field's
472
+ * previous writer was an atomic op of the SAME type (a same-type atomic chain:
473
+ * concurrent increments sum, maxes take the max, appends accumulate); any other
474
+ * write, including the first atomic write after a plain set, resolves by
475
+ * last-write-wins on the resolved value. Because operations are folded in HLC order,
476
+ * the current op always wins that last-write-wins comparison, so the result is
477
+ * deterministic and identical on every replica that folds the same operation set.
478
+ *
479
+ * This is the single definition of atomic materialization shared by the client
480
+ * (`@korajs/store` apply pipeline) and the server (`@korajs/server` materialization),
481
+ * so both converge to the same value for any number of concurrent atomic writers.
482
+ *
483
+ * Returns the record field data (without `id`) or null if the record was deleted
484
+ * or never inserted.
485
+ */
486
+ declare function replayOperationsForRecord(ops: ReplayOperation[]): Record<string, unknown> | null;
487
+
309
488
  /**
310
489
  * Canonical JSON-safe encoding of binary bytes stored inside `op.data` /
311
490
  * `op.previousData` (currently richtext field values). A raw Uint8Array
@@ -474,6 +653,38 @@ declare function generateSQL(collectionName: string, collection: CollectionDefin
474
653
  */
475
654
  declare function generateFullDDL(schema: SchemaDefinition): string[];
476
655
 
656
+ /**
657
+ * Quote a SQL identifier (table or column name) for safe interpolation into
658
+ * generated SQL.
659
+ *
660
+ * Uses standard double-quote quoting, which both SQLite and PostgreSQL honor,
661
+ * and doubles any embedded double-quote per the SQL standard. Quoting is what
662
+ * lets a valid JavaScript identifier — camelCase (`formResponses`), PascalCase
663
+ * (`UserProfiles`), or a word that happens to be a SQL keyword (`order`,
664
+ * `select`) — round-trip through generated DDL and queries without ever
665
+ * producing invalid or ambiguous SQL.
666
+ *
667
+ * Schema validation (see `validateCollectionName` / `validateFieldName`)
668
+ * already restricts identifiers to `[A-Za-z][A-Za-z0-9_]*`, so the escape here
669
+ * never actually fires in practice; it is defense in depth so this helper is
670
+ * correct for any input rather than only for pre-validated names.
671
+ *
672
+ * Consistency is the contract: every path that emits an identifier for a
673
+ * user-defined collection or field MUST go through this helper, because a
674
+ * quoted `CREATE TABLE "order"` paired with an unquoted `SELECT ... FROM order`
675
+ * would reintroduce the exact keyword-collision bug this guards against.
676
+ *
677
+ * @param name - The raw identifier (collection name, field/column name).
678
+ * @returns The identifier wrapped in double quotes, ready to splice into SQL.
679
+ *
680
+ * @example
681
+ * ```typescript
682
+ * quoteIdent('formResponses') // => '"formResponses"'
683
+ * quoteIdent('order') // => '"order"'
684
+ * ```
685
+ */
686
+ declare function quoteIdent(name: string): string;
687
+
477
688
  /**
478
689
  * Validates a record's data against a collection's field definitions.
479
690
  * Applies defaults, rejects auto fields, and type-checks each value.
@@ -508,12 +719,16 @@ interface FieldKindToType {
508
719
  richtext: string;
509
720
  enum: string;
510
721
  array: unknown[];
722
+ object: Record<string, unknown>;
723
+ json: unknown;
724
+ blob: BlobRef;
725
+ secret: string;
511
726
  }
512
727
  /**
513
728
  * Infers the TypeScript type for a single field descriptor or builder.
514
729
  * Supports both FieldBuilder (class instances) and FieldDescriptor (compiled objects).
515
730
  */
516
- type InferFieldType<F> = F extends EnumFieldBuilder<infer V, any, any> ? V[number] : F extends ArrayFieldBuilder<infer K, any, any> ? FieldKindToType[K][] : F extends FieldBuilder<infer K, any, any> ? K extends keyof FieldKindToType ? FieldKindToType[K] : unknown : F extends {
731
+ type InferFieldType<F> = F extends EnumFieldBuilder<infer V, any, any> ? V[number] : F extends JsonFieldBuilder<infer T, any, any> ? T : F extends ArrayFieldBuilder<infer K, any, any> ? FieldKindToType[K][] : F extends FieldBuilder<infer K, any, any> ? K extends keyof FieldKindToType ? FieldKindToType[K] : unknown : F extends {
517
732
  kind: 'enum';
518
733
  enumValues: infer V;
519
734
  } ? V extends readonly (infer S)[] ? S : string : F extends {
@@ -719,7 +934,7 @@ declare function migrationStepsToSQL(steps: readonly MigrationStep[]): string[];
719
934
  *
720
935
  * const rollbackSQL = rollbackStepsToSQL(migration)
721
936
  * // ['DROP INDEX IF EXISTS idx_todos_priority',
722
- * // 'ALTER TABLE todos DROP COLUMN priority']
937
+ * // 'ALTER TABLE "todos" DROP COLUMN "priority"']
723
938
  * ```
724
939
  */
725
940
  declare function rollbackStepsToSQL(migration: MigrationDefinition): string[];
@@ -910,4 +1125,4 @@ interface ProtoOutput {
910
1125
  */
911
1126
  declare function generateProtoDefinitions(schema: SchemaDefinition): ProtoOutput;
912
1127
 
913
- export { APPLY_FAILURE_CODES, APPLY_RESULTS, AppNotReadyError, type ApplyFailureReason, type ApplyResult, ArrayFieldBuilder, AtomicOp, type AtomicOpSentinel, AtomicOpType, CausalTracker, ClockDriftError, CollectionDefinition, type CollectionInput, type ConstraintInput, CustomResolver, EnumFieldBuilder, FieldBuilder, FieldKind, type FieldKindToType, type InferFieldType, type InferInsertInput, type InferRecord, type InferUpdateInput, InvalidTimestampError, KORA_ERROR_FIX_SUGGESTIONS, type KoraBytesValue, KoraError, MergeConflictError, MigrationDefinition, MigrationRollbackError, MigrationStep, Operation, OperationError, type OperationLog, type OperationTransform, OperationType, type ProtoOutput, RandomSource, RelationDefinition, type RelationInput, RemoteClockDriftError, type ReversibleMigration, SchemaDefinition, type SchemaInput, SchemaValidationError, StateMachineConstraint, type StateMachineInput, StorageError, SyncError, TransitionMap, TransitionValidationResult, type TypedSchemaDefinition, VersionVector, advanceVector, applyOperationTransforms, base64ToBytes, buildStateMachineConstraints, bytesToBase64, canAutoRollback, collectSchemaScopeFields, collectSchemaScopeValueKeys, computeDelta, createReversibleMigration, createVersionVector, decodeBytesFromOpData, defaultApplyFailureReason, defaultSequenceFormat, defineSchema, deserializeVector, dominates, encodeBytesForOpData, extractScopeValuesFromClaims, extractTimestamp, formatSequenceValue, generateFullDDL, generateProtoDefinitions, generateRollbackSteps, generateSQL, generateUUIDv7, getCollectionScopeBindings, getKoraErrorFix, getTransitionMap, hasSchemaSyncRules, isApplyFailure, isAtomicOp, isCollectionSyncScoped, isKoraBytesValue, isLegacyNumericByteObject, isValidUUIDv7, mergeVectors, migrationStepsToSQL, op, resolveAtomicOp, rollbackStepsToSQL, serializeVector, toAtomicOp, validateRecord, validateTransition, vectorsEqual };
1128
+ export { APPLY_FAILURE_CODES, APPLY_RESULTS, AppNotReadyError, type ApplyFailureReason, type ApplyResult, ArrayFieldBuilder, AtomicOp, type AtomicOpSentinel, AtomicOpType, BlobRef, type BlobRefMetadata, CausalTracker, ClockDriftError, CollectionDefinition, type CollectionInput, type ConstraintInput, CustomResolver, EnumFieldBuilder, FieldBuilder, FieldKind, type FieldKindToType, type InferFieldType, type InferInsertInput, type InferRecord, type InferUpdateInput, InvalidTimestampError, KORA_ERROR_FIX_SUGGESTIONS, type KoraBytesValue, KoraError, MergeConflictError, MigrationDefinition, MigrationRollbackError, MigrationStep, MissingSecretKeyError, Operation, OperationError, type OperationLog, type OperationTransform, OperationType, type ProtoOutput, RandomSource, RelationDefinition, type RelationInput, RemoteClockDriftError, type ReplayOperation, type ReversibleMigration, SchemaDefinition, type SchemaInput, SchemaValidationError, type SecretKeyProvider, StateMachineConstraint, type StateMachineInput, StorageError, SyncError, TransitionMap, TransitionValidationResult, type TypedSchemaDefinition, VersionVector, advanceVector, applyAtomicOp, applyOperationTransforms, base64ToBytes, buildStateMachineConstraints, bytesToBase64, canAutoRollback, collectSchemaScopeFields, collectSchemaScopeValueKeys, computeDelta, createBlobRef, createReversibleMigration, createVersionVector, decodeBytesFromOpData, decryptSecret, defaultApplyFailureReason, defaultSequenceFormat, defineSchema, deserializeVector, dominates, encodeBytesForOpData, encryptSecret, extractScopeValuesFromClaims, extractTimestamp, formatSequenceValue, generateFullDDL, generateProtoDefinitions, generateRollbackSteps, generateSQL, generateUUIDv7, getCollectionScopeBindings, getKoraErrorFix, getTransitionMap, hasSchemaSyncRules, hashBlob, hashSecret, isApplyFailure, isAtomicOp, isBlobRef, isCollectionSyncScoped, isKoraBytesValue, isLegacyNumericByteObject, isValidUUIDv7, mergeVectors, migrationStepsToSQL, op, quoteIdent, replayOperationsForRecord, resolveAtomicOp, revealSecret, rollbackStepsToSQL, serializeVector, toAtomicOp, transformSecretFieldsForWrite, validateRecord, validateTransition, vectorsEqual, verifySecret, verifySecretValue };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { R as RandomSource, A as AtomicOpType, a as AtomicOp, F as FieldBuilder, C as CustomResolver, M as MigrationDefinition, S as SchemaDefinition, b as CollectionDefinition, c as RelationDefinition, O as OperationType, E as EnumFieldBuilder, d as ArrayFieldBuilder, e as FieldKind, f as Operation, V as VersionVector, g as MigrationStep, h as StateMachineConstraint, T as TransitionMap, i as TransitionValidationResult } from './events-BynBOsO3.js';
2
- export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp, K as KoraEvent, o as KoraEventByType, p as KoraEventEmitter, q as KoraEventListener, r as KoraEventType, s as MERGE_STRATEGIES, t as MergeStrategy, u as MergeTrace, v as MigrationBuilder, w as OnDeleteAction, x as OperationInput, y as RelationType, z as RollbackBuilder, B as SequenceConfig, D as StateMachineDefinition, G as SyncDiagnosticsSnapshot, I as SyncRuleDefinition, J as TimeSource, L as migrate, N as t } from './events-BynBOsO3.js';
3
- export { H as HybridLogicalClock, M as MAX_LOGICAL, c as createOperation, i as isValidOperation, v as verifyOperationIntegrity } from './operation-D5WOZYvy.js';
4
- export { S as ScopeMap, b as buildScopeMap } from './build-scope-map-DOf4JLTh.js';
1
+ import { R as RandomSource, B as BlobRef, C as CollectionDefinition, A as AtomicOpType, a as AtomicOp, F as FieldBuilder, b as CustomResolver, M as MigrationDefinition, S as SchemaDefinition, c as RelationDefinition, O as OperationType, E as EnumFieldBuilder, J as JsonFieldBuilder, d as ArrayFieldBuilder, e as FieldKind, f as Operation, V as VersionVector, g as MigrationStep, h as StateMachineConstraint, T as TransitionMap, i as TransitionValidationResult } from './events-3z0Tema3.js';
2
+ export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp, K as KoraEvent, o as KoraEventByType, p as KoraEventEmitter, q as KoraEventListener, r as KoraEventType, s as MERGE_STRATEGIES, t as MergeStrategy, u as MergeTrace, v as MigrationBuilder, w as OnDeleteAction, x as OperationInput, y as RelationType, z as RollbackBuilder, D as SecretMode, G as SequenceConfig, I as StateMachineDefinition, L as SyncDiagnosticsSnapshot, N as SyncRuleDefinition, P as TimeSource, Q as migrate, U as t } from './events-3z0Tema3.js';
3
+ export { H as HybridLogicalClock, M as MAX_LOGICAL, c as createOperation, i as isValidOperation, v as verifyOperationIntegrity } from './operation-ClhEbhoV.js';
4
+ export { S as ScopeMap, b as buildScopeMap } from './build-scope-map-CDpIGOsf.js';
5
5
 
6
6
  /**
7
7
  * Base error class for all Kora errors.
@@ -161,6 +161,137 @@ declare function extractTimestamp(uuid: string): number;
161
161
  */
162
162
  declare function isValidUUIDv7(uuid: string): boolean;
163
163
 
164
+ /**
165
+ * Compute the hex-encoded SHA-256 content hash of a byte buffer.
166
+ *
167
+ * This is the content address of a blob: identical bytes always hash to the same
168
+ * value, which is what lets the blob store deduplicate content and lets a peer
169
+ * skip transferring bytes it already holds.
170
+ *
171
+ * @param bytes - The binary content to hash
172
+ * @returns The hex-encoded SHA-256 hash
173
+ */
174
+ declare function hashBlob(bytes: Uint8Array): Promise<string>;
175
+ /** Optional metadata carried alongside a blob reference. */
176
+ interface BlobRefMetadata {
177
+ mimeType?: string;
178
+ filename?: string;
179
+ }
180
+ /**
181
+ * Create a content-addressed {@link BlobRef} for a byte buffer.
182
+ *
183
+ * @param bytes - The binary content
184
+ * @param metadata - Optional MIME type and filename
185
+ * @returns A reference carrying the content hash, size, and metadata
186
+ */
187
+ declare function createBlobRef(bytes: Uint8Array, metadata?: BlobRefMetadata): Promise<BlobRef>;
188
+ /**
189
+ * Type guard: whether a value is a structurally valid {@link BlobRef}.
190
+ *
191
+ * Validates the shape only (a non-empty hex hash and a non-negative size); it
192
+ * does not verify that the bytes behind the hash exist or match. Integrity
193
+ * verification against the actual bytes happens in the blob store on read.
194
+ */
195
+ declare function isBlobRef(value: unknown): value is BlobRef;
196
+
197
+ /**
198
+ * Field-level cryptography for `secret` fields.
199
+ *
200
+ * Two protection modes, matching the two ways secrets are used:
201
+ * - `encrypted`: reversible AES-256-GCM (tokens, API keys — decrypt to use).
202
+ * - `hashed`: one-way PBKDF2-SHA-256 with a random salt (passwords — verify only).
203
+ *
204
+ * These primitives use only the standard WebCrypto API so they live in
205
+ * `@korajs/core` with no dependency on `@korajs/auth`; a `secret` field is
206
+ * therefore self-contained. Higher-level key management composes on top.
207
+ */
208
+ /**
209
+ * Encrypt a secret's plaintext with AES-256-GCM under a key derived from
210
+ * `secretKey`. The returned string bundles the salt, IV, and ciphertext (all hex,
211
+ * dot-separated) so it is self-describing and safe to store and sync.
212
+ *
213
+ * @param plaintext - The secret value to protect
214
+ * @param secretKey - The key material (from a key provider), never stored
215
+ * @returns An opaque `v1.salt.iv.ciphertext` string
216
+ */
217
+ declare function encryptSecret(plaintext: string, secretKey: string): Promise<string>;
218
+ /**
219
+ * Decrypt a value produced by {@link encryptSecret} with the same key.
220
+ *
221
+ * @param encrypted - The `v1.salt.iv.ciphertext` string
222
+ * @param secretKey - The key material used to encrypt
223
+ * @returns The original plaintext
224
+ * @throws If the format is invalid or the key is wrong (GCM auth failure)
225
+ */
226
+ declare function decryptSecret(encrypted: string, secretKey: string): Promise<string>;
227
+ /**
228
+ * One-way hash a secret (a password) with PBKDF2-SHA-256 and a random salt.
229
+ * The result bundles the salt and hash so {@link verifySecret} needs nothing
230
+ * else. There is no way to recover the plaintext from the result.
231
+ *
232
+ * @param plaintext - The secret value to hash
233
+ * @returns An opaque `v1.salt.hash` string
234
+ */
235
+ declare function hashSecret(plaintext: string): Promise<string>;
236
+ /**
237
+ * Verify a plaintext against a value produced by {@link hashSecret}, in constant
238
+ * time with respect to the stored hash.
239
+ *
240
+ * @param plaintext - The candidate secret
241
+ * @param stored - The `v1.salt.hash` string
242
+ * @returns Whether the plaintext matches
243
+ */
244
+ declare function verifySecret(plaintext: string, stored: string): Promise<boolean>;
245
+
246
+ /**
247
+ * Provider of the key material used to encrypt reversible (`encrypted`) secret
248
+ * fields. Called at write and reveal time so the key can be loaded lazily (for
249
+ * example derived from a user passphrase after unlock). Returns undefined when
250
+ * no key is available.
251
+ */
252
+ type SecretKeyProvider = () => string | undefined | Promise<string | undefined>;
253
+ /** Thrown when an `encrypted` secret field is written or read without a key. */
254
+ declare class MissingSecretKeyError extends Error {
255
+ readonly field: string;
256
+ constructor(field: string);
257
+ }
258
+ /**
259
+ * Transform the secret fields of a record's write payload into their at-rest
260
+ * form BEFORE the operation is created, so plaintext never enters the operation
261
+ * log, the store, or the sync stream.
262
+ *
263
+ * - `hashed` fields become a one-way salted hash.
264
+ * - `encrypted` fields become ciphertext (requires a key).
265
+ *
266
+ * Non-secret fields, and secret fields not present in `data`, are passed through
267
+ * untouched. Null/undefined secret values are left as-is (nothing to protect).
268
+ *
269
+ * @param data - The validated write payload (plaintext secret values)
270
+ * @param collectionDef - The collection definition (for field kinds/modes)
271
+ * @param keyProvider - Supplies the encryption key for `encrypted` fields
272
+ * @returns A new payload with secret fields replaced by their at-rest form
273
+ */
274
+ declare function transformSecretFieldsForWrite(data: Record<string, unknown>, collectionDef: CollectionDefinition, keyProvider?: SecretKeyProvider): Promise<Record<string, unknown>>;
275
+ /**
276
+ * Reveal the plaintext of an `encrypted` secret field's stored value. Throws for
277
+ * `hashed` fields, which are one-way and cannot be revealed.
278
+ *
279
+ * @param storedValue - The at-rest value (ciphertext)
280
+ * @param mode - The field's secret mode
281
+ * @param keyProvider - Supplies the decryption key
282
+ * @param field - Field name (for error messages)
283
+ * @returns The decrypted plaintext
284
+ */
285
+ declare function revealSecret(storedValue: string, mode: 'hashed' | 'encrypted', keyProvider: SecretKeyProvider | undefined, field?: string): Promise<string>;
286
+ /**
287
+ * Verify a plaintext candidate against a `hashed` secret field's stored value.
288
+ *
289
+ * @param candidate - The plaintext to check (for example a login password)
290
+ * @param storedValue - The stored one-way hash
291
+ * @returns Whether the candidate matches
292
+ */
293
+ declare function verifySecretValue(candidate: string, storedValue: string): Promise<boolean>;
294
+
164
295
  /**
165
296
  * Outcome of applying a single operation to materialized storage (local or remote).
166
297
  */
@@ -228,6 +359,20 @@ interface AtomicOpSentinel {
228
359
  * @returns true if the value is an AtomicOpSentinel
229
360
  */
230
361
  declare function isAtomicOp(value: unknown): value is AtomicOpSentinel;
362
+ /**
363
+ * Apply a plain atomic op (`{ type, value }`) to a current value, producing the
364
+ * concrete result. This is the single source of truth for atomic-op semantics:
365
+ * {@link resolveAtomicOp} (sentinel form, used on the write path) delegates here,
366
+ * and the server's materialization replays stored atomic ops through it, so the
367
+ * server's materialized view composes concurrent atomic writes identically to the
368
+ * client. Folding this over a field's writes in HLC order yields, for a same-type
369
+ * atomic chain, exactly the composed intent (sum of increments, max of maxes, ...).
370
+ *
371
+ * @param currentValue - The current value of the field
372
+ * @param atomicOp - The atomic op to apply (type + operand)
373
+ * @returns The resulting concrete value
374
+ */
375
+ declare function applyAtomicOp(currentValue: unknown, atomicOp: AtomicOp): unknown;
231
376
  /**
232
377
  * Resolve an atomic op sentinel against a current value to produce a concrete result.
233
378
  *
@@ -306,6 +451,40 @@ declare const op: {
306
451
  */
307
452
  declare function toAtomicOp(sentinel: AtomicOpSentinel): AtomicOp;
308
453
 
454
+ /** One operation's contribution to a record's materialized state. */
455
+ interface ReplayOperation {
456
+ type: string;
457
+ data: Record<string, unknown> | null;
458
+ /**
459
+ * Atomic-op intents carried by this operation, per field. When present, a field
460
+ * is composed (rather than overwritten) if the previous writer on that field was
461
+ * an atomic op of the same type. Absent means every field resolves by
462
+ * last-write-wins.
463
+ */
464
+ atomicOps?: Record<string, AtomicOp> | null;
465
+ }
466
+ /**
467
+ * Replay a list of operations (MUST be pre-sorted in HLC total order —
468
+ * wallTime, then logical, then nodeId) to produce the current state of a single
469
+ * record, composing atomic-op intents.
470
+ *
471
+ * Per field, an atomic op composes onto the running value only when the field's
472
+ * previous writer was an atomic op of the SAME type (a same-type atomic chain:
473
+ * concurrent increments sum, maxes take the max, appends accumulate); any other
474
+ * write, including the first atomic write after a plain set, resolves by
475
+ * last-write-wins on the resolved value. Because operations are folded in HLC order,
476
+ * the current op always wins that last-write-wins comparison, so the result is
477
+ * deterministic and identical on every replica that folds the same operation set.
478
+ *
479
+ * This is the single definition of atomic materialization shared by the client
480
+ * (`@korajs/store` apply pipeline) and the server (`@korajs/server` materialization),
481
+ * so both converge to the same value for any number of concurrent atomic writers.
482
+ *
483
+ * Returns the record field data (without `id`) or null if the record was deleted
484
+ * or never inserted.
485
+ */
486
+ declare function replayOperationsForRecord(ops: ReplayOperation[]): Record<string, unknown> | null;
487
+
309
488
  /**
310
489
  * Canonical JSON-safe encoding of binary bytes stored inside `op.data` /
311
490
  * `op.previousData` (currently richtext field values). A raw Uint8Array
@@ -474,6 +653,38 @@ declare function generateSQL(collectionName: string, collection: CollectionDefin
474
653
  */
475
654
  declare function generateFullDDL(schema: SchemaDefinition): string[];
476
655
 
656
+ /**
657
+ * Quote a SQL identifier (table or column name) for safe interpolation into
658
+ * generated SQL.
659
+ *
660
+ * Uses standard double-quote quoting, which both SQLite and PostgreSQL honor,
661
+ * and doubles any embedded double-quote per the SQL standard. Quoting is what
662
+ * lets a valid JavaScript identifier — camelCase (`formResponses`), PascalCase
663
+ * (`UserProfiles`), or a word that happens to be a SQL keyword (`order`,
664
+ * `select`) — round-trip through generated DDL and queries without ever
665
+ * producing invalid or ambiguous SQL.
666
+ *
667
+ * Schema validation (see `validateCollectionName` / `validateFieldName`)
668
+ * already restricts identifiers to `[A-Za-z][A-Za-z0-9_]*`, so the escape here
669
+ * never actually fires in practice; it is defense in depth so this helper is
670
+ * correct for any input rather than only for pre-validated names.
671
+ *
672
+ * Consistency is the contract: every path that emits an identifier for a
673
+ * user-defined collection or field MUST go through this helper, because a
674
+ * quoted `CREATE TABLE "order"` paired with an unquoted `SELECT ... FROM order`
675
+ * would reintroduce the exact keyword-collision bug this guards against.
676
+ *
677
+ * @param name - The raw identifier (collection name, field/column name).
678
+ * @returns The identifier wrapped in double quotes, ready to splice into SQL.
679
+ *
680
+ * @example
681
+ * ```typescript
682
+ * quoteIdent('formResponses') // => '"formResponses"'
683
+ * quoteIdent('order') // => '"order"'
684
+ * ```
685
+ */
686
+ declare function quoteIdent(name: string): string;
687
+
477
688
  /**
478
689
  * Validates a record's data against a collection's field definitions.
479
690
  * Applies defaults, rejects auto fields, and type-checks each value.
@@ -508,12 +719,16 @@ interface FieldKindToType {
508
719
  richtext: string;
509
720
  enum: string;
510
721
  array: unknown[];
722
+ object: Record<string, unknown>;
723
+ json: unknown;
724
+ blob: BlobRef;
725
+ secret: string;
511
726
  }
512
727
  /**
513
728
  * Infers the TypeScript type for a single field descriptor or builder.
514
729
  * Supports both FieldBuilder (class instances) and FieldDescriptor (compiled objects).
515
730
  */
516
- type InferFieldType<F> = F extends EnumFieldBuilder<infer V, any, any> ? V[number] : F extends ArrayFieldBuilder<infer K, any, any> ? FieldKindToType[K][] : F extends FieldBuilder<infer K, any, any> ? K extends keyof FieldKindToType ? FieldKindToType[K] : unknown : F extends {
731
+ type InferFieldType<F> = F extends EnumFieldBuilder<infer V, any, any> ? V[number] : F extends JsonFieldBuilder<infer T, any, any> ? T : F extends ArrayFieldBuilder<infer K, any, any> ? FieldKindToType[K][] : F extends FieldBuilder<infer K, any, any> ? K extends keyof FieldKindToType ? FieldKindToType[K] : unknown : F extends {
517
732
  kind: 'enum';
518
733
  enumValues: infer V;
519
734
  } ? V extends readonly (infer S)[] ? S : string : F extends {
@@ -719,7 +934,7 @@ declare function migrationStepsToSQL(steps: readonly MigrationStep[]): string[];
719
934
  *
720
935
  * const rollbackSQL = rollbackStepsToSQL(migration)
721
936
  * // ['DROP INDEX IF EXISTS idx_todos_priority',
722
- * // 'ALTER TABLE todos DROP COLUMN priority']
937
+ * // 'ALTER TABLE "todos" DROP COLUMN "priority"']
723
938
  * ```
724
939
  */
725
940
  declare function rollbackStepsToSQL(migration: MigrationDefinition): string[];
@@ -910,4 +1125,4 @@ interface ProtoOutput {
910
1125
  */
911
1126
  declare function generateProtoDefinitions(schema: SchemaDefinition): ProtoOutput;
912
1127
 
913
- export { APPLY_FAILURE_CODES, APPLY_RESULTS, AppNotReadyError, type ApplyFailureReason, type ApplyResult, ArrayFieldBuilder, AtomicOp, type AtomicOpSentinel, AtomicOpType, CausalTracker, ClockDriftError, CollectionDefinition, type CollectionInput, type ConstraintInput, CustomResolver, EnumFieldBuilder, FieldBuilder, FieldKind, type FieldKindToType, type InferFieldType, type InferInsertInput, type InferRecord, type InferUpdateInput, InvalidTimestampError, KORA_ERROR_FIX_SUGGESTIONS, type KoraBytesValue, KoraError, MergeConflictError, MigrationDefinition, MigrationRollbackError, MigrationStep, Operation, OperationError, type OperationLog, type OperationTransform, OperationType, type ProtoOutput, RandomSource, RelationDefinition, type RelationInput, RemoteClockDriftError, type ReversibleMigration, SchemaDefinition, type SchemaInput, SchemaValidationError, StateMachineConstraint, type StateMachineInput, StorageError, SyncError, TransitionMap, TransitionValidationResult, type TypedSchemaDefinition, VersionVector, advanceVector, applyOperationTransforms, base64ToBytes, buildStateMachineConstraints, bytesToBase64, canAutoRollback, collectSchemaScopeFields, collectSchemaScopeValueKeys, computeDelta, createReversibleMigration, createVersionVector, decodeBytesFromOpData, defaultApplyFailureReason, defaultSequenceFormat, defineSchema, deserializeVector, dominates, encodeBytesForOpData, extractScopeValuesFromClaims, extractTimestamp, formatSequenceValue, generateFullDDL, generateProtoDefinitions, generateRollbackSteps, generateSQL, generateUUIDv7, getCollectionScopeBindings, getKoraErrorFix, getTransitionMap, hasSchemaSyncRules, isApplyFailure, isAtomicOp, isCollectionSyncScoped, isKoraBytesValue, isLegacyNumericByteObject, isValidUUIDv7, mergeVectors, migrationStepsToSQL, op, resolveAtomicOp, rollbackStepsToSQL, serializeVector, toAtomicOp, validateRecord, validateTransition, vectorsEqual };
1128
+ export { APPLY_FAILURE_CODES, APPLY_RESULTS, AppNotReadyError, type ApplyFailureReason, type ApplyResult, ArrayFieldBuilder, AtomicOp, type AtomicOpSentinel, AtomicOpType, BlobRef, type BlobRefMetadata, CausalTracker, ClockDriftError, CollectionDefinition, type CollectionInput, type ConstraintInput, CustomResolver, EnumFieldBuilder, FieldBuilder, FieldKind, type FieldKindToType, type InferFieldType, type InferInsertInput, type InferRecord, type InferUpdateInput, InvalidTimestampError, KORA_ERROR_FIX_SUGGESTIONS, type KoraBytesValue, KoraError, MergeConflictError, MigrationDefinition, MigrationRollbackError, MigrationStep, MissingSecretKeyError, Operation, OperationError, type OperationLog, type OperationTransform, OperationType, type ProtoOutput, RandomSource, RelationDefinition, type RelationInput, RemoteClockDriftError, type ReplayOperation, type ReversibleMigration, SchemaDefinition, type SchemaInput, SchemaValidationError, type SecretKeyProvider, StateMachineConstraint, type StateMachineInput, StorageError, SyncError, TransitionMap, TransitionValidationResult, type TypedSchemaDefinition, VersionVector, advanceVector, applyAtomicOp, applyOperationTransforms, base64ToBytes, buildStateMachineConstraints, bytesToBase64, canAutoRollback, collectSchemaScopeFields, collectSchemaScopeValueKeys, computeDelta, createBlobRef, createReversibleMigration, createVersionVector, decodeBytesFromOpData, decryptSecret, defaultApplyFailureReason, defaultSequenceFormat, defineSchema, deserializeVector, dominates, encodeBytesForOpData, encryptSecret, extractScopeValuesFromClaims, extractTimestamp, formatSequenceValue, generateFullDDL, generateProtoDefinitions, generateRollbackSteps, generateSQL, generateUUIDv7, getCollectionScopeBindings, getKoraErrorFix, getTransitionMap, hasSchemaSyncRules, hashBlob, hashSecret, isApplyFailure, isAtomicOp, isBlobRef, isCollectionSyncScoped, isKoraBytesValue, isLegacyNumericByteObject, isValidUUIDv7, mergeVectors, migrationStepsToSQL, op, quoteIdent, replayOperationsForRecord, resolveAtomicOp, revealSecret, rollbackStepsToSQL, serializeVector, toAtomicOp, transformSecretFieldsForWrite, validateRecord, validateTransition, vectorsEqual, verifySecret, verifySecretValue };