Compare commits

...

1 Commits

Author SHA1 Message Date
Guido D'Orsi
4828d3a10b feat: a new CoValue to manage fast append-only lists 2024-12-16 10:04:38 +01:00
4 changed files with 130 additions and 1 deletions

View File

@@ -3,6 +3,7 @@ import { RawProfile as Profile, RawAccount } from "./coValues/account.js";
import { RawCoList } from "./coValues/coList.js";
import { RawCoMap } from "./coValues/coMap.js";
import { RawBinaryCoStream, RawCoStream } from "./coValues/coStream.js";
import { RawCoStreamLite } from "./coValues/coStreamLite.js";
import { RawGroup } from "./coValues/group.js";
import { RawCoID } from "./ids.js";
import { JsonObject, JsonValue } from "./jsonValue.js";
@@ -41,7 +42,8 @@ export type AnyRawCoValue =
| Profile
| RawCoList
| RawCoStream
| RawBinaryCoStream;
| RawBinaryCoStream
| RawCoStreamLite;
export function expectMap(content: RawCoValue): RawCoMap {
if (content.type !== "comap") {

View File

@@ -0,0 +1,98 @@
import { CoID } from "../coValue.js";
import { RawCoValue } from "../coValue.js";
import { CoValueCore } from "../coValueCore.js";
import { JsonObject, JsonValue } from "../jsonValue.js";
import { CoValueKnownState } from "../sync.js";
import { isCoValue } from "../typeUtils/isCoValue.js";
import { CoStreamItem } from "./coStream.js";
import { RawGroup } from "./group.js";
export class RawCoStreamLiteView<
Item extends JsonValue = JsonValue,
Meta extends JsonObject | null = JsonObject | null,
> implements RawCoValue
{
id: CoID<this>;
type = "costream" as const;
core: CoValueCore;
items: CoStreamItem<Item>[];
knownTransactions: CoValueKnownState["sessions"];
readonly _item!: Item;
constructor(core: CoValueCore) {
this.id = core.id as CoID<this>;
this.core = core;
this.items = [];
this.knownTransactions = {};
this.processNewTransactions();
}
/** @category 6. Meta */
get headerMeta(): Meta {
return this.core.header.meta as Meta;
}
/** @category 6. Meta */
get group(): RawGroup {
return this.core.getGroup();
}
/** Returns an immutable JSON presentation of this `CoValue` */
toJSON() {
return this.items;
}
/** Not yet implemented */
atTime(_time: number): this {
throw new Error("Not yet implemented");
}
/** @internal */
protected processNewTransactions() {
const { items } = this;
for (const { txID, madeAt, changes } of this.core.getValidTransactions({
ignorePrivateTransactions: false,
knownTransactions: this.knownTransactions,
})) {
for (const changeUntyped of changes) {
const change = changeUntyped as Item;
items.push({ value: change, madeAt, tx: txID });
}
this.knownTransactions[txID.sessionID] = Math.max(
this.knownTransactions[txID.sessionID] ?? 0,
txID.txIndex,
);
}
}
subscribe(listener: (coStream: this) => void): () => void {
return this.core.subscribe((content) => {
listener(content as this);
});
}
}
export class RawCoStreamLite<
Item extends JsonValue = JsonValue,
Meta extends JsonObject | null = JsonObject | null,
>
extends RawCoStreamLiteView<Item, Meta>
implements RawCoValue
{
push(item: Item, privacy: "private" | "trusting" = "private"): void {
this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
this.processNewTransactions();
}
pushItems(items: Item[], privacy: "private" | "trusting" = "private"): void {
this.core.makeTransaction(
items.map((item) => (isCoValue(item) ? item.id : item)),
privacy,
);
this.processNewTransactions();
}
}

View File

@@ -23,6 +23,7 @@ import {
import { RawCoList } from "./coList.js";
import { RawCoMap } from "./coMap.js";
import { RawBinaryCoStream, RawCoStream } from "./coStream.js";
import { RawCoStreamLite } from "./coStreamLite.js";
export const EVERYONE = "everyone" as const;
export type Everyone = "everyone";
@@ -521,6 +522,31 @@ export class RawGroup<
.getCurrentContent() as C;
}
/**
* Creates a new `CoStreamLite` within this group, with the specified specialized
* `CoStreamLite` type `L` and optional static metadata.
*
* @category 3. Value creation
*/
createStreamLite<L extends RawCoStreamLite>(
meta: L["headerMeta"] = { type: "lite" },
uniqueness: CoValueUniqueness = this.core.crypto.createdNowUnique(),
): L {
const list = this.core.node
.createCoValue({
type: "costream",
ruleset: {
type: "ownedByGroup",
group: this.id,
},
meta: meta || null,
...uniqueness,
})
.getCurrentContent() as L;
return list;
}
/** @category 3. Value creation */
createBinaryStream<C extends RawBinaryCoStream>(
meta: C["headerMeta"] = { type: "binary" },

View File

@@ -4,6 +4,7 @@ import { RawCoList } from "./coValues/coList.js";
import { RawCoMap } from "./coValues/coMap.js";
import { RawCoStream } from "./coValues/coStream.js";
import { RawBinaryCoStream } from "./coValues/coStream.js";
import { RawCoStreamLite } from "./coValues/coStreamLite.js";
import { RawGroup } from "./coValues/group.js";
export function coreToCoValue(
@@ -32,6 +33,8 @@ export function coreToCoValue(
} else if (core.header.type === "costream") {
if (core.header.meta && core.header.meta.type === "binary") {
return new RawBinaryCoStream(core);
} else if (core.header.meta && core.header.meta.type === "lite") {
return new RawCoStreamLite(core);
} else {
return new RawCoStream(core);
}