tablinum 0.0.1 → 0.1.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/README.md +77 -1
- package/dist/crud/collection-handle.d.ts +21 -0
- package/dist/crud/query-builder.d.ts +42 -0
- package/dist/crud/watch.d.ts +25 -0
- package/dist/db/create-tablinum.d.ts +12 -0
- package/dist/db/database-handle.d.ts +13 -0
- package/dist/db/identity.d.ts +8 -0
- package/dist/errors.d.ts +58 -0
- package/{src/index.ts → dist/index.d.ts} +4 -24
- package/dist/index.js +1833 -0
- package/dist/main.d.ts +1 -0
- package/dist/schema/collection.d.ts +12 -0
- package/dist/schema/field.d.ts +17 -0
- package/{src/schema/types.ts → dist/schema/types.d.ts} +5 -10
- package/dist/schema/validate.d.ts +13 -0
- package/dist/storage/events-store.d.ts +6 -0
- package/dist/storage/giftwraps-store.d.ts +6 -0
- package/dist/storage/idb.d.ts +35 -0
- package/dist/storage/lww.d.ts +10 -0
- package/dist/storage/records-store.d.ts +12 -0
- package/dist/svelte/collection.svelte.d.ts +20 -0
- package/dist/svelte/database.svelte.d.ts +15 -0
- package/dist/svelte/index.svelte.d.ts +16 -0
- package/dist/svelte/index.svelte.js +2050 -0
- package/dist/svelte/live-query.svelte.d.ts +8 -0
- package/dist/svelte/query.svelte.d.ts +39 -0
- package/dist/sync/gift-wrap.d.ts +9 -0
- package/dist/sync/negentropy.d.ts +9 -0
- package/dist/sync/publish-queue.d.ts +10 -0
- package/dist/sync/relay.d.ts +17 -0
- package/dist/sync/sync-service.d.ts +14 -0
- package/dist/sync/sync-status.d.ts +7 -0
- package/dist/utils/uuid.d.ts +2 -0
- package/package.json +22 -1
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.context/attachments/pasted_text_2026-03-07_14-02-40.txt +0 -571
- package/.context/attachments/pasted_text_2026-03-07_15-48-27.txt +0 -498
- package/.context/notes.md +0 -0
- package/.context/plans/add-changesets-to-douala-v4.md +0 -48
- package/.context/plans/dexie-js-style-query-language-for-localstr.md +0 -115
- package/.context/plans/dexie-js-style-query-language-with-per-collection-.md +0 -336
- package/.context/plans/implementation-plan-localstr-v0-2.md +0 -263
- package/.context/plans/project-init-effect-v4-bun-oxlint-oxfmt-vitest.md +0 -71
- package/.context/plans/revise-localstr-prd-v0-2.md +0 -132
- package/.context/plans/svelte-5-runes-bindings-for-localstr.md +0 -233
- package/.context/todos.md +0 -0
- package/.github/workflows/release.yml +0 -36
- package/.oxlintrc.json +0 -8
- package/bun.lock +0 -705
- package/examples/svelte/bun.lock +0 -261
- package/examples/svelte/package.json +0 -21
- package/examples/svelte/src/app.html +0 -11
- package/examples/svelte/src/lib/db.ts +0 -44
- package/examples/svelte/src/routes/+page.svelte +0 -322
- package/examples/svelte/svelte.config.js +0 -16
- package/examples/svelte/tsconfig.json +0 -6
- package/examples/svelte/vite.config.ts +0 -6
- package/examples/vanilla/app.ts +0 -219
- package/examples/vanilla/index.html +0 -144
- package/examples/vanilla/serve.ts +0 -42
- package/prds/localstr-v0.2.md +0 -221
- package/prek.toml +0 -10
- package/scripts/validate.ts +0 -392
- package/src/crud/collection-handle.ts +0 -189
- package/src/crud/query-builder.ts +0 -414
- package/src/crud/watch.ts +0 -78
- package/src/db/create-localstr.ts +0 -217
- package/src/db/database-handle.ts +0 -16
- package/src/db/identity.ts +0 -49
- package/src/errors.ts +0 -37
- package/src/main.ts +0 -10
- package/src/schema/collection.ts +0 -53
- package/src/schema/field.ts +0 -25
- package/src/schema/validate.ts +0 -111
- package/src/storage/events-store.ts +0 -24
- package/src/storage/giftwraps-store.ts +0 -23
- package/src/storage/idb.ts +0 -244
- package/src/storage/lww.ts +0 -17
- package/src/storage/records-store.ts +0 -76
- package/src/svelte/collection.svelte.ts +0 -87
- package/src/svelte/database.svelte.ts +0 -83
- package/src/svelte/index.svelte.ts +0 -52
- package/src/svelte/live-query.svelte.ts +0 -29
- package/src/svelte/query.svelte.ts +0 -101
- package/src/sync/gift-wrap.ts +0 -33
- package/src/sync/negentropy.ts +0 -83
- package/src/sync/publish-queue.ts +0 -61
- package/src/sync/relay.ts +0 -239
- package/src/sync/sync-service.ts +0 -183
- package/src/sync/sync-status.ts +0 -17
- package/src/utils/uuid.ts +0 -22
- package/src/vendor/negentropy.js +0 -616
- package/tests/db/create-localstr.test.ts +0 -174
- package/tests/db/identity.test.ts +0 -33
- package/tests/main.test.ts +0 -9
- package/tests/schema/collection.test.ts +0 -27
- package/tests/schema/field.test.ts +0 -41
- package/tests/schema/validate.test.ts +0 -85
- package/tests/setup.ts +0 -1
- package/tests/storage/idb.test.ts +0 -144
- package/tests/storage/lww.test.ts +0 -33
- package/tests/sync/gift-wrap.test.ts +0 -56
- package/tsconfig.json +0 -18
- package/vitest.config.ts +0 -8
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FieldDef } from "./field.ts";
|
|
2
|
+
export type CollectionFields = Record<string, FieldDef<unknown>>;
|
|
3
|
+
export interface CollectionDef<out F extends CollectionFields = CollectionFields> {
|
|
4
|
+
readonly _tag: "CollectionDef";
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly fields: F;
|
|
7
|
+
readonly indices: ReadonlyArray<string>;
|
|
8
|
+
}
|
|
9
|
+
export interface CollectionOptions<F extends CollectionFields> {
|
|
10
|
+
readonly indices?: ReadonlyArray<string & keyof F>;
|
|
11
|
+
}
|
|
12
|
+
export declare function collection<F extends CollectionFields>(name: string, fields: F, options?: CollectionOptions<F>): CollectionDef<F>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type FieldKind = "string" | "number" | "boolean" | "json";
|
|
2
|
+
export interface FieldDef<out T = unknown> {
|
|
3
|
+
readonly _tag: "FieldDef";
|
|
4
|
+
readonly kind: FieldKind;
|
|
5
|
+
readonly isOptional: boolean;
|
|
6
|
+
readonly isArray: boolean;
|
|
7
|
+
/** Phantom type carrier — never read at runtime. */
|
|
8
|
+
readonly _T?: T;
|
|
9
|
+
}
|
|
10
|
+
export declare const field: {
|
|
11
|
+
string: () => FieldDef<string>;
|
|
12
|
+
number: () => FieldDef<number>;
|
|
13
|
+
boolean: () => FieldDef<boolean>;
|
|
14
|
+
json: () => FieldDef<unknown>;
|
|
15
|
+
optional: <T>(inner: FieldDef<T>) => FieldDef<T | undefined>;
|
|
16
|
+
array: <T>(inner: FieldDef<T>) => FieldDef<ReadonlyArray<T>>;
|
|
17
|
+
};
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import type { CollectionDef, CollectionFields } from "./collection.ts";
|
|
2
2
|
import type { FieldDef } from "./field.ts";
|
|
3
|
-
|
|
4
3
|
/** Extract the TypeScript type from a FieldDef phantom. */
|
|
5
4
|
export type InferFieldType<F> = F extends FieldDef<infer T> ? T : never;
|
|
6
|
-
|
|
7
5
|
/** Infer the full record type from a CollectionDef, including the auto-injected `id`. */
|
|
8
|
-
export type InferRecord<C> =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
: never;
|
|
14
|
-
|
|
6
|
+
export type InferRecord<C> = C extends CollectionDef<infer F> ? {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
} & {
|
|
9
|
+
readonly [K in keyof F]: InferFieldType<F[K]>;
|
|
10
|
+
} : never;
|
|
15
11
|
/** A schema configuration mapping collection names to their definitions. */
|
|
16
12
|
export type SchemaConfig = Record<string, CollectionDef<CollectionFields>>;
|
|
17
|
-
|
|
18
13
|
/** Extract indexed field names from a CollectionDef. */
|
|
19
14
|
export type IndexedFields<C> = C extends CollectionDef<infer _F> ? C["indices"][number] : never;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { CollectionDef, CollectionFields } from "./collection.ts";
|
|
3
|
+
import { ValidationError } from "../errors.ts";
|
|
4
|
+
export type RecordValidator<F extends CollectionFields> = (input: unknown) => Effect.Effect<{
|
|
5
|
+
readonly id: string;
|
|
6
|
+
} & {
|
|
7
|
+
readonly [K in keyof F]: unknown;
|
|
8
|
+
}, ValidationError>;
|
|
9
|
+
export declare function buildValidator<F extends CollectionFields>(collectionName: string, def: CollectionDef<F>): RecordValidator<F>;
|
|
10
|
+
export type PartialValidator<F extends CollectionFields> = (input: unknown) => Effect.Effect<{
|
|
11
|
+
readonly [K in keyof F]?: unknown;
|
|
12
|
+
}, ValidationError>;
|
|
13
|
+
export declare function buildPartialValidator<F extends CollectionFields>(collectionName: string, def: CollectionDef<F>): PartialValidator<F>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { IDBStorageHandle, StoredEvent } from "./idb.ts";
|
|
3
|
+
import type { StorageError } from "../errors.ts";
|
|
4
|
+
export declare function putEvent(storage: IDBStorageHandle, event: StoredEvent): Effect.Effect<void, StorageError>;
|
|
5
|
+
export declare function getEventsByRecord(storage: IDBStorageHandle, collection: string, recordId: string): Effect.Effect<ReadonlyArray<StoredEvent>, StorageError>;
|
|
6
|
+
export declare function getAllEvents(storage: IDBStorageHandle): Effect.Effect<ReadonlyArray<StoredEvent>, StorageError>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { IDBStorageHandle, StoredGiftWrap } from "./idb.ts";
|
|
3
|
+
import type { StorageError } from "../errors.ts";
|
|
4
|
+
export declare function putGiftWrap(storage: IDBStorageHandle, gw: StoredGiftWrap): Effect.Effect<void, StorageError>;
|
|
5
|
+
export declare function getGiftWrap(storage: IDBStorageHandle, id: string): Effect.Effect<StoredGiftWrap | undefined, StorageError>;
|
|
6
|
+
export declare function getAllGiftWraps(storage: IDBStorageHandle): Effect.Effect<ReadonlyArray<StoredGiftWrap>, StorageError>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Effect, Scope } from "effect";
|
|
2
|
+
import { StorageError } from "../errors.ts";
|
|
3
|
+
import type { SchemaConfig } from "../schema/types.ts";
|
|
4
|
+
export interface StoredEvent {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly collection: string;
|
|
7
|
+
readonly recordId: string;
|
|
8
|
+
readonly kind: "create" | "update" | "delete";
|
|
9
|
+
readonly data: Record<string, unknown> | null;
|
|
10
|
+
readonly createdAt: number;
|
|
11
|
+
}
|
|
12
|
+
export interface StoredGiftWrap {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly event: Record<string, unknown>;
|
|
15
|
+
readonly createdAt: number;
|
|
16
|
+
}
|
|
17
|
+
export interface IDBStorageHandle {
|
|
18
|
+
readonly putRecord: (collection: string, record: Record<string, unknown>) => Effect.Effect<void, StorageError>;
|
|
19
|
+
readonly getRecord: (collection: string, id: string) => Effect.Effect<Record<string, unknown> | undefined, StorageError>;
|
|
20
|
+
readonly getAllRecords: (collection: string) => Effect.Effect<ReadonlyArray<Record<string, unknown>>, StorageError>;
|
|
21
|
+
readonly countRecords: (collection: string) => Effect.Effect<number, StorageError>;
|
|
22
|
+
readonly clearRecords: (collection: string) => Effect.Effect<void, StorageError>;
|
|
23
|
+
readonly getByIndex: (collection: string, indexName: string, value: IDBValidKey) => Effect.Effect<ReadonlyArray<Record<string, unknown>>, StorageError>;
|
|
24
|
+
readonly getByIndexRange: (collection: string, indexName: string, range: IDBKeyRange) => Effect.Effect<ReadonlyArray<Record<string, unknown>>, StorageError>;
|
|
25
|
+
readonly getAllSorted: (collection: string, indexName: string, direction?: "next" | "prev") => Effect.Effect<ReadonlyArray<Record<string, unknown>>, StorageError>;
|
|
26
|
+
readonly putEvent: (event: StoredEvent) => Effect.Effect<void, StorageError>;
|
|
27
|
+
readonly getEvent: (id: string) => Effect.Effect<StoredEvent | undefined, StorageError>;
|
|
28
|
+
readonly getAllEvents: () => Effect.Effect<ReadonlyArray<StoredEvent>, StorageError>;
|
|
29
|
+
readonly getEventsByRecord: (collection: string, recordId: string) => Effect.Effect<ReadonlyArray<StoredEvent>, StorageError>;
|
|
30
|
+
readonly putGiftWrap: (gw: StoredGiftWrap) => Effect.Effect<void, StorageError>;
|
|
31
|
+
readonly getGiftWrap: (id: string) => Effect.Effect<StoredGiftWrap | undefined, StorageError>;
|
|
32
|
+
readonly getAllGiftWraps: () => Effect.Effect<ReadonlyArray<StoredGiftWrap>, StorageError>;
|
|
33
|
+
readonly close: () => Effect.Effect<void>;
|
|
34
|
+
}
|
|
35
|
+
export declare function openIDBStorage(dbName: string | undefined, schema: SchemaConfig): Effect.Effect<IDBStorageHandle, StorageError, Scope.Scope>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface EventMeta {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly createdAt: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Last-write-wins resolution.
|
|
7
|
+
* Higher `createdAt` wins. Ties broken by lowest event ID (lexicographic).
|
|
8
|
+
* Returns the winner.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveWinner<T extends EventMeta>(existing: T | null, incoming: T): T;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { IDBStorageHandle, StoredEvent } from "./idb.ts";
|
|
3
|
+
import type { StorageError } from "../errors.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Apply an event to the records store using LWW resolution.
|
|
6
|
+
* Returns true if the incoming event won and the record was updated.
|
|
7
|
+
*/
|
|
8
|
+
export declare function applyEvent(storage: IDBStorageHandle, event: StoredEvent): Effect.Effect<boolean, StorageError>;
|
|
9
|
+
/**
|
|
10
|
+
* Rebuild the records store by clearing it and replaying all events.
|
|
11
|
+
*/
|
|
12
|
+
export declare function rebuild(storage: IDBStorageHandle, collections: ReadonlyArray<string>): Effect.Effect<void, StorageError>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CollectionDef, CollectionFields } from "../schema/collection.ts";
|
|
2
|
+
import type { InferRecord } from "../schema/types.ts";
|
|
3
|
+
import type { CollectionHandle } from "../crud/collection-handle.ts";
|
|
4
|
+
import { type SvelteWhereClause, type SvelteOrderByBuilder } from "./query.svelte.ts";
|
|
5
|
+
export declare class Collection<C extends CollectionDef<CollectionFields>> {
|
|
6
|
+
#private;
|
|
7
|
+
items: any;
|
|
8
|
+
error: any;
|
|
9
|
+
constructor(handle: CollectionHandle<C>);
|
|
10
|
+
add: (data: Omit<InferRecord<C>, "id">) => Promise<string>;
|
|
11
|
+
update: (id: string, data: Partial<Omit<InferRecord<C>, "id">>) => Promise<void>;
|
|
12
|
+
delete: (id: string) => Promise<void>;
|
|
13
|
+
get: (id: string) => Promise<InferRecord<C>>;
|
|
14
|
+
first: () => Promise<InferRecord<C> | null>;
|
|
15
|
+
count: () => Promise<number>;
|
|
16
|
+
where: (field: string & keyof Omit<InferRecord<C>, "id">) => SvelteWhereClause<InferRecord<C>>;
|
|
17
|
+
orderBy: (field: string & keyof Omit<InferRecord<C>, "id">) => SvelteOrderByBuilder<InferRecord<C>>;
|
|
18
|
+
/** @internal Called by Database.close() */
|
|
19
|
+
_destroy(): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Scope } from "effect";
|
|
2
|
+
import type { SchemaConfig } from "../schema/types.ts";
|
|
3
|
+
import type { DatabaseHandle } from "../db/database-handle.ts";
|
|
4
|
+
import { Collection } from "./collection.svelte.ts";
|
|
5
|
+
export declare class Database<S extends SchemaConfig> {
|
|
6
|
+
#private;
|
|
7
|
+
status: any;
|
|
8
|
+
error: any;
|
|
9
|
+
constructor(handle: DatabaseHandle<S>, scope: Scope.Closeable);
|
|
10
|
+
collection<K extends string & keyof S>(name: K): Collection<S[K]>;
|
|
11
|
+
exportKey(): string;
|
|
12
|
+
close: () => Promise<void>;
|
|
13
|
+
sync: () => Promise<void>;
|
|
14
|
+
rebuild: () => Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SchemaConfig } from "../schema/types.ts";
|
|
2
|
+
import { type TablinumConfig } from "../db/create-tablinum.ts";
|
|
3
|
+
import { Database } from "./database.svelte.ts";
|
|
4
|
+
export { field } from "../schema/field.ts";
|
|
5
|
+
export { collection } from "../schema/collection.ts";
|
|
6
|
+
export type { CollectionDef, CollectionFields } from "../schema/collection.ts";
|
|
7
|
+
export type { FieldDef, FieldKind } from "../schema/field.ts";
|
|
8
|
+
export type { InferRecord, SchemaConfig } from "../schema/types.ts";
|
|
9
|
+
export type { TablinumConfig } from "../db/create-tablinum.ts";
|
|
10
|
+
export type { SyncStatus } from "../db/database-handle.ts";
|
|
11
|
+
export { ValidationError, StorageError, CryptoError, RelayError, SyncError, NotFoundError, ClosedError, } from "../errors.ts";
|
|
12
|
+
export { Database } from "./database.svelte.ts";
|
|
13
|
+
export { Collection } from "./collection.svelte.ts";
|
|
14
|
+
export { LiveQuery } from "./live-query.svelte.ts";
|
|
15
|
+
export type { SvelteQueryBuilder, SvelteWhereClause, SvelteOrderByBuilder, } from "./query.svelte.ts";
|
|
16
|
+
export declare function createTablinum<S extends SchemaConfig>(config: TablinumConfig<S>): Promise<Database<S>>;
|