@korajs/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,401 @@
1
+ import { R as RandomSource, F as FieldKind, a as FieldDescriptor, C as CustomResolver, S as SchemaDefinition, b as CollectionDefinition, c as RelationDefinition, O as OperationType, d as Operation, V as VersionVector } from './events-D_kDPDC9.js';
2
+ export { e as CONNECTION_QUALITIES, f as ConnectionQuality, g as Constraint, H as HLCTimestamp, h as HybridLogicalClock, K as KoraEvent, i as KoraEventByType, j as KoraEventEmitter, k as KoraEventListener, l as KoraEventType, M as MERGE_STRATEGIES, m as MergeStrategy, n as MergeTrace, o as OnDeleteAction, p as OperationInput, q as RelationType, T as TimeSource, r as createOperation, s as isValidOperation, v as verifyOperationIntegrity } from './events-D_kDPDC9.js';
3
+
4
+ /**
5
+ * Base error class for all Kora errors.
6
+ * Every error includes a machine-readable code and optional context for debugging.
7
+ */
8
+ declare class KoraError extends Error {
9
+ readonly code: string;
10
+ readonly context?: Record<string, unknown> | undefined;
11
+ constructor(message: string, code: string, context?: Record<string, unknown> | undefined);
12
+ }
13
+ /**
14
+ * Thrown when schema validation fails during defineSchema() or at app initialization.
15
+ */
16
+ declare class SchemaValidationError extends KoraError {
17
+ constructor(message: string, context?: Record<string, unknown>);
18
+ }
19
+ /**
20
+ * Thrown when an operation is invalid or cannot be created.
21
+ */
22
+ declare class OperationError extends KoraError {
23
+ constructor(message: string, context?: Record<string, unknown>);
24
+ }
25
+ /**
26
+ * Thrown when a merge conflict cannot be automatically resolved.
27
+ */
28
+ declare class MergeConflictError extends KoraError {
29
+ readonly operationA: {
30
+ id: string;
31
+ collection: string;
32
+ };
33
+ readonly operationB: {
34
+ id: string;
35
+ collection: string;
36
+ };
37
+ readonly field: string;
38
+ constructor(operationA: {
39
+ id: string;
40
+ collection: string;
41
+ }, operationB: {
42
+ id: string;
43
+ collection: string;
44
+ }, field: string);
45
+ }
46
+ /**
47
+ * Thrown when a sync error occurs.
48
+ */
49
+ declare class SyncError extends KoraError {
50
+ constructor(message: string, context?: Record<string, unknown>);
51
+ }
52
+ /**
53
+ * Thrown when a storage operation fails.
54
+ */
55
+ declare class StorageError extends KoraError {
56
+ constructor(message: string, context?: Record<string, unknown>);
57
+ }
58
+ /**
59
+ * Thrown when the HLC detects excessive clock drift.
60
+ * Drift > 60s: warning. Drift > 5min: this error is thrown, refusing to generate timestamps.
61
+ */
62
+ declare class ClockDriftError extends KoraError {
63
+ readonly currentHlcTime: number;
64
+ readonly physicalTime: number;
65
+ constructor(currentHlcTime: number, physicalTime: number);
66
+ }
67
+
68
+ /**
69
+ * Generates a UUID v7 per RFC 9562.
70
+ * UUID v7 encodes a Unix timestamp in milliseconds in the most significant 48 bits,
71
+ * making UUIDs time-sortable while remaining globally unique.
72
+ *
73
+ * @param timestamp - Unix timestamp in milliseconds (defaults to Date.now())
74
+ * @param randomSource - Injectable random source for deterministic testing
75
+ * @returns A UUID v7 string in standard 8-4-4-4-12 format
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * const id = generateUUIDv7()
80
+ * // "018f3a5c-7e00-7123-abcd-1234567890ab"
81
+ * ```
82
+ */
83
+ declare function generateUUIDv7(timestamp?: number, randomSource?: RandomSource): string;
84
+ /**
85
+ * Extracts the Unix timestamp in milliseconds from a UUID v7.
86
+ *
87
+ * @param uuid - A UUID v7 string
88
+ * @returns The encoded Unix timestamp in milliseconds
89
+ */
90
+ declare function extractTimestamp(uuid: string): number;
91
+ /**
92
+ * Validates whether a string is a valid UUID v7.
93
+ * Checks format, version (7), and variant (10xx).
94
+ *
95
+ * @param uuid - String to validate
96
+ * @returns true if the string is a valid UUID v7
97
+ */
98
+ declare function isValidUUIDv7(uuid: string): boolean;
99
+
100
+ /**
101
+ * Base field builder implementing the builder pattern for schema field definitions.
102
+ * Each builder is immutable — modifier methods return new builder instances.
103
+ *
104
+ * Type parameters track field metadata at the type level for inference:
105
+ * - Kind: the field kind ('string', 'number', etc.)
106
+ * - Req: whether the field is required (true = required on insert)
107
+ * - Auto: whether the field is auto-populated (true = excluded from insert input)
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * t.string() // required string field
112
+ * t.string().optional() // optional string field
113
+ * t.string().default('hello') // string with default value
114
+ * t.timestamp().auto() // auto-populated timestamp
115
+ * ```
116
+ */
117
+ declare class FieldBuilder<Kind extends FieldKind = FieldKind, Req extends boolean = true, Auto extends boolean = false> {
118
+ protected readonly _kind: Kind;
119
+ protected readonly _required: boolean;
120
+ protected readonly _defaultValue: unknown;
121
+ protected readonly _auto: boolean;
122
+ constructor(kind: Kind, required?: Req, defaultValue?: unknown, auto?: Auto);
123
+ /** Mark this field as optional (not required on insert) */
124
+ optional(): FieldBuilder<Kind, false, Auto>;
125
+ /** Set a default value for this field. Implicitly makes the field optional. */
126
+ default(value: unknown): FieldBuilder<Kind, false, Auto>;
127
+ /** Mark this field as auto-populated (e.g., createdAt timestamps). Developers cannot set auto fields. */
128
+ auto(): FieldBuilder<Kind, false, true>;
129
+ /** @internal Build the final FieldDescriptor. Used by defineSchema(). */
130
+ _build(): FieldDescriptor;
131
+ }
132
+ /**
133
+ * Field builder for enum fields with constrained string values.
134
+ * Preserves the literal enum tuple type for inference.
135
+ */
136
+ declare class EnumFieldBuilder<Values extends readonly string[] = readonly string[], Req extends boolean = true, Auto extends boolean = false> extends FieldBuilder<'enum', Req, Auto> {
137
+ private readonly _enumValues;
138
+ constructor(values: Values, required?: Req, defaultValue?: unknown, auto?: Auto);
139
+ optional(): EnumFieldBuilder<Values, false, Auto>;
140
+ default(value: Values[number]): EnumFieldBuilder<Values, false, Auto>;
141
+ auto(): EnumFieldBuilder<Values, false, true>;
142
+ _build(): FieldDescriptor;
143
+ }
144
+ /**
145
+ * Field builder for array fields with a typed item kind.
146
+ * Preserves the item kind type parameter for inference.
147
+ */
148
+ declare class ArrayFieldBuilder<ItemKind extends FieldKind = FieldKind, Req extends boolean = true, Auto extends boolean = false> extends FieldBuilder<'array', Req, Auto> {
149
+ private readonly _itemKind;
150
+ constructor(itemBuilder: FieldBuilder<ItemKind>, required?: Req, defaultValue?: unknown, auto?: Auto);
151
+ optional(): ArrayFieldBuilder<ItemKind, false, Auto>;
152
+ default(value: unknown[]): ArrayFieldBuilder<ItemKind, false, Auto>;
153
+ auto(): ArrayFieldBuilder<ItemKind, false, true>;
154
+ _build(): FieldDescriptor;
155
+ }
156
+ /**
157
+ * Type builder namespace. The developer's primary interface for defining field types.
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * import { t } from '@korajs/core'
162
+ *
163
+ * const fields = {
164
+ * title: t.string(),
165
+ * count: t.number(),
166
+ * active: t.boolean().default(true),
167
+ * notes: t.richtext(),
168
+ * tags: t.array(t.string()).default([]),
169
+ * priority: t.enum(['low', 'medium', 'high']).default('medium'),
170
+ * createdAt: t.timestamp().auto(),
171
+ * }
172
+ * ```
173
+ */
174
+ declare const t: {
175
+ string(): FieldBuilder<"string", true, false>;
176
+ number(): FieldBuilder<"number", true, false>;
177
+ boolean(): FieldBuilder<"boolean", true, false>;
178
+ timestamp(): FieldBuilder<"timestamp", true, false>;
179
+ richtext(): FieldBuilder<"richtext", true, false>;
180
+ enum<const V extends readonly string[]>(values: V): EnumFieldBuilder<V, true, false>;
181
+ array<K extends FieldKind>(itemBuilder: FieldBuilder<K>): ArrayFieldBuilder<K, true, false>;
182
+ };
183
+
184
+ /**
185
+ * Input shape for defineSchema() — what the developer writes.
186
+ */
187
+ interface SchemaInput {
188
+ version: number;
189
+ collections: Record<string, CollectionInput>;
190
+ relations?: Record<string, RelationInput>;
191
+ }
192
+ interface CollectionInput {
193
+ fields: Record<string, FieldBuilder<any, any, any>>;
194
+ indexes?: string[];
195
+ constraints?: ConstraintInput[];
196
+ resolve?: Record<string, CustomResolver>;
197
+ }
198
+ interface ConstraintInput {
199
+ type: 'unique' | 'capacity' | 'referential';
200
+ fields: string[];
201
+ where?: Record<string, unknown>;
202
+ onConflict: 'first-write-wins' | 'last-write-wins' | 'priority-field' | 'server-decides' | 'custom';
203
+ priorityField?: string;
204
+ resolve?: (local: unknown, remote: unknown, base: unknown) => unknown;
205
+ }
206
+ interface RelationInput {
207
+ from: string;
208
+ to: string;
209
+ type: 'one-to-one' | 'one-to-many' | 'many-to-one' | 'many-to-many';
210
+ field: string;
211
+ onDelete: 'cascade' | 'set-null' | 'restrict' | 'no-action';
212
+ }
213
+ /**
214
+ * Validates and builds a SchemaDefinition from developer input.
215
+ * This is the primary developer-facing function for defining a schema.
216
+ *
217
+ * @param input - The schema definition using type builders
218
+ * @returns A validated SchemaDefinition ready for use by the framework
219
+ * @throws {SchemaValidationError} If the schema is invalid
220
+ *
221
+ * @example
222
+ * ```typescript
223
+ * import { defineSchema, t } from '@korajs/core'
224
+ *
225
+ * const schema = defineSchema({
226
+ * version: 1,
227
+ * collections: {
228
+ * todos: {
229
+ * fields: {
230
+ * title: t.string(),
231
+ * completed: t.boolean().default(false),
232
+ * }
233
+ * }
234
+ * }
235
+ * })
236
+ * ```
237
+ */
238
+ /**
239
+ * Schema definition with a phantom type brand preserving the original input shape.
240
+ * The `__input` property exists only at the type level for inference — no runtime cost.
241
+ */
242
+ type TypedSchemaDefinition<T extends SchemaInput = SchemaInput> = SchemaDefinition & {
243
+ readonly __input: T;
244
+ };
245
+ declare function defineSchema<const T extends SchemaInput>(input: T): TypedSchemaDefinition<T>;
246
+
247
+ /**
248
+ * Generate CREATE TABLE and CREATE INDEX SQL for a single collection.
249
+ *
250
+ * @param collectionName - The collection name
251
+ * @param collection - The collection definition
252
+ * @param relations - Optional relations for FK references
253
+ * @returns An array of SQL statements (CREATE TABLE + CREATE INDEX)
254
+ */
255
+ declare function generateSQL(collectionName: string, collection: CollectionDefinition, relations?: Record<string, RelationDefinition>): string[];
256
+ /**
257
+ * Generate the full DDL for all collections plus metadata tables.
258
+ *
259
+ * @param schema - The complete schema definition
260
+ * @returns An array of all SQL statements needed to initialize the database
261
+ */
262
+ declare function generateFullDDL(schema: SchemaDefinition): string[];
263
+
264
+ /**
265
+ * Validates a record's data against a collection's field definitions.
266
+ * Applies defaults, rejects auto fields, and type-checks each value.
267
+ *
268
+ * @param collection - The collection name (for error messages)
269
+ * @param collectionDef - The collection definition from the schema
270
+ * @param data - The record data to validate
271
+ * @param operationType - The operation type ('insert', 'update', 'delete')
272
+ * @returns The validated and normalized data (with defaults applied)
273
+ * @throws {SchemaValidationError} If validation fails
274
+ */
275
+ declare function validateRecord(collection: string, collectionDef: CollectionDefinition, data: Record<string, unknown>, operationType: OperationType): Record<string, unknown>;
276
+
277
+ /**
278
+ * Type-level inference utilities for Kora schemas.
279
+ *
280
+ * These mapped types convert FieldBuilder type parameters into concrete
281
+ * TypeScript types, enabling full autocomplete and type checking from
282
+ * defineSchema() through createApp() to collection methods.
283
+ *
284
+ * Zero runtime cost — these are purely compile-time constructs.
285
+ */
286
+
287
+ /**
288
+ * Maps a FieldKind string literal to its corresponding TypeScript type.
289
+ */
290
+ interface FieldKindToType {
291
+ string: string;
292
+ number: number;
293
+ boolean: boolean;
294
+ timestamp: number;
295
+ richtext: Uint8Array;
296
+ enum: string;
297
+ array: unknown[];
298
+ }
299
+ /**
300
+ * Infers the TypeScript type for a single FieldBuilder.
301
+ * Handles base fields, enums (with literal union), and arrays (with typed items).
302
+ */
303
+ type InferFieldType<F> = F extends EnumFieldBuilder<infer V, infer _Req, infer _Auto> ? V[number] : F extends ArrayFieldBuilder<infer K, infer _Req, infer _Auto> ? FieldKindToType[K][] : F extends FieldBuilder<infer K, infer _Req, infer _Auto> ? FieldKindToType[K] : unknown;
304
+ /**
305
+ * Infers the full record type returned from queries.
306
+ * Includes `id`, `createdAt`, `updatedAt` metadata fields.
307
+ * Optional/defaulted fields include `| null` in their type.
308
+ */
309
+ type InferRecord<Fields extends Record<string, FieldBuilder<any, any, any>>> = {
310
+ readonly id: string;
311
+ readonly createdAt: number;
312
+ readonly updatedAt: number;
313
+ } & {
314
+ readonly [K in keyof Fields]: Fields[K] extends FieldBuilder<any, true, any> ? InferFieldType<Fields[K]> : InferFieldType<Fields[K]> | null;
315
+ };
316
+ /**
317
+ * Helper: extract keys where the field is required and not auto.
318
+ */
319
+ type RequiredInsertKeys<Fields extends Record<string, FieldBuilder<any, any, any>>> = {
320
+ [K in keyof Fields]: Fields[K] extends FieldBuilder<any, any, true> ? never : Fields[K] extends FieldBuilder<any, true, false> ? K : never;
321
+ }[keyof Fields];
322
+ /**
323
+ * Helper: extract keys where the field is optional (not required) and not auto.
324
+ */
325
+ type OptionalInsertKeys<Fields extends Record<string, FieldBuilder<any, any, any>>> = {
326
+ [K in keyof Fields]: Fields[K] extends FieldBuilder<any, any, true> ? never : Fields[K] extends FieldBuilder<any, true, false> ? never : K;
327
+ }[keyof Fields];
328
+ /**
329
+ * Infers the insert input type.
330
+ * - Required non-auto fields are required keys
331
+ * - Optional/defaulted non-auto fields are optional keys
332
+ * - Auto fields are excluded entirely
333
+ */
334
+ type InferInsertInput<Fields extends Record<string, FieldBuilder<any, any, any>>> = {
335
+ [K in RequiredInsertKeys<Fields> & string]: InferFieldType<Fields[K]>;
336
+ } & {
337
+ [K in OptionalInsertKeys<Fields> & string]?: InferFieldType<Fields[K]>;
338
+ };
339
+ /**
340
+ * Helper: extract keys where the field is not auto.
341
+ */
342
+ type NonAutoKeys<Fields extends Record<string, FieldBuilder<any, any, any>>> = {
343
+ [K in keyof Fields]: Fields[K] extends FieldBuilder<any, any, true> ? never : K;
344
+ }[keyof Fields];
345
+ /**
346
+ * Infers the update input type.
347
+ * All non-auto fields are optional (partial update semantics).
348
+ */
349
+ type InferUpdateInput<Fields extends Record<string, FieldBuilder<any, any, any>>> = {
350
+ [K in NonAutoKeys<Fields> & string]?: InferFieldType<Fields[K]>;
351
+ };
352
+
353
+ /**
354
+ * Create an empty version vector.
355
+ */
356
+ declare function createVersionVector(): VersionVector;
357
+ /**
358
+ * Merge two version vectors by taking the max sequence number for each node.
359
+ * This is commutative, associative, and idempotent.
360
+ */
361
+ declare function mergeVectors(a: VersionVector, b: VersionVector): VersionVector;
362
+ /**
363
+ * Advance a version vector for a specific node to a new sequence number.
364
+ * Only advances forward — if the current value is higher, no change is made.
365
+ */
366
+ declare function advanceVector(vector: VersionVector, nodeId: string, seq: number): VersionVector;
367
+ /**
368
+ * Returns true if vector `a` dominates vector `b` — meaning `a` has seen
369
+ * everything `b` has seen. Formally: for every nodeId in b, a[nodeId] >= b[nodeId].
370
+ */
371
+ declare function dominates(a: VersionVector, b: VersionVector): boolean;
372
+ /**
373
+ * Returns true if two version vectors are exactly equal.
374
+ */
375
+ declare function vectorsEqual(a: VersionVector, b: VersionVector): boolean;
376
+ /**
377
+ * Operation log interface for computing deltas.
378
+ */
379
+ interface OperationLog {
380
+ getRange(nodeId: string, fromSeq: number, toSeq: number): Operation[];
381
+ }
382
+ /**
383
+ * Compute the operations that `local` has but `remote` does not.
384
+ * Returns operations in causal (topological) order.
385
+ *
386
+ * @param localVector - The local version vector
387
+ * @param remoteVector - The remote version vector
388
+ * @param operationLog - The operation log to fetch operations from
389
+ * @returns Operations sorted in causal order
390
+ */
391
+ declare function computeDelta(localVector: VersionVector, remoteVector: VersionVector, operationLog: OperationLog): Operation[];
392
+ /**
393
+ * Serialize a version vector to a JSON-compatible string.
394
+ */
395
+ declare function serializeVector(vector: VersionVector): string;
396
+ /**
397
+ * Deserialize a version vector from its serialized string form.
398
+ */
399
+ declare function deserializeVector(s: string): VersionVector;
400
+
401
+ export { ArrayFieldBuilder, ClockDriftError, CollectionDefinition, type CollectionInput, type ConstraintInput, CustomResolver, EnumFieldBuilder, FieldBuilder, FieldDescriptor, FieldKind, type FieldKindToType, type InferFieldType, type InferInsertInput, type InferRecord, type InferUpdateInput, KoraError, MergeConflictError, Operation, OperationError, type OperationLog, OperationType, RandomSource, RelationDefinition, type RelationInput, SchemaDefinition, type SchemaInput, SchemaValidationError, StorageError, SyncError, type TypedSchemaDefinition, VersionVector, advanceVector, computeDelta, createVersionVector, defineSchema, deserializeVector, dominates, extractTimestamp, generateFullDDL, generateSQL, generateUUIDv7, isValidUUIDv7, mergeVectors, serializeVector, t, validateRecord, vectorsEqual };