Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Model} from '../../../../json-crdt/model';
import {ChunkSlice} from '../ChunkSlice';

const setup = () => {
const model = Model.withLogicalClock().setSchema(s.str('Hello world'));
const model = Model.withLogicalClock().setSchema(s.str('Hello world'), false);
const node = model.root.node();
const chunk = node.first()!;
return {
Expand Down
2 changes: 1 addition & 1 deletion src/json-crdt-patch/clock/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface ITimestampStruct {
* Session ID (or actor ID, site ID, process ID, etc.), a random identifier
* randomly assigned to each editing session.
*/
readonly sid: number;
sid: number;

/**
* Logical time (or sequence number, tick, etc.), a monotonically increasing
Expand Down
18 changes: 16 additions & 2 deletions src/json-crdt/model/Model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,24 @@ export class Model<N extends JsonNode = JsonNode<any>> implements Printable {
* the document is empty.
*
* @param schema The schema to set for this model.
* @param sid Session ID to use for setting the default value of the document.
* Defaults to `SESSION.GLOBAL` (2), which is the default session ID
* for all operations operations that are not attributed to a specific
* session.
* @returns Strictly typed model.
*/
public setSchema<S extends NodeBuilder>(schema: S): Model<SchemaToJsonNode<S>> {
if (this.clock.time < 2) this.api.root(schema);
public setSchema<S extends NodeBuilder>(schema: S, useGlobalSession: boolean = true): Model<SchemaToJsonNode<S>> {
const c = this.clock;
const isNewDocument = c.time === 1;
if (isNewDocument) {
const oldSid = c.sid;
if (useGlobalSession) c.sid = SESSION.GLOBAL;
this.api.root(schema);
if (useGlobalSession) {
c.sid = oldSid;
c.observe(new clock.Timestamp(SESSION.GLOBAL, c.time - 1), 1);
}
}
return <any>this;
}

Expand Down
29 changes: 0 additions & 29 deletions src/json-crdt/model/__tests__/Model.schema.spec.ts

This file was deleted.

67 changes: 67 additions & 0 deletions src/json-crdt/model/__tests__/Model.setSchema.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {nodes, s} from '../../../json-crdt-patch';
import {SESSION} from '../../../json-crdt-patch/constants';
import {Model} from '../Model';

test('can set object schema', () => {
const model = Model.withLogicalClock().setSchema(
s.obj({
str: s.str('asdf'),
con: s.con(123),
}),
);
expect(model.s.str.toApi().view()).toBe('asdf');
expect(model.s.con.toApi().view()).toBe(123);
});

test('can set map schema', () => {
const model = Model.withLogicalClock().setSchema(
s.map<nodes.str | nodes.con<number>>({
str: s.str('asdf'),
con1: s.con(123),
}),
);
expect(model.s.str.toApi().view()).toBe('asdf');
expect(model.s.con1.toApi().view()).toBe(123);
expect(model.view().str).toBe('asdf');
expect(model.view().con1).toBe(123);
expect(model.view().anyKeyAllowed).toBe(undefined);
});

test('uses global session ID by default', () => {
const model = Model.withLogicalClock().setSchema(
s.obj({
id: s.str<string>('asdf'),
num: s.con(123),
}),
);
expect(model.api.r.get().node.id.sid).toBe(SESSION.GLOBAL);
expect(model.api.r.get().get('id').node.id.sid).toBe(SESSION.GLOBAL);
expect(model.api.r.get().get('num').node.id.sid).toBe(SESSION.GLOBAL);
});

test('allows to specify custom session ID', () => {
const schema = s.obj({
id: s.str<string>('asdf'),
num: s.con(123),
});
const model = Model.withLogicalClock().setSchema(schema, false);
expect(model.api.r.get().node.id.sid).toBe(model.clock.sid);
expect(model.api.r.get().get('id').node.id.sid).toBe(model.clock.sid);
expect(model.api.r.get().get('num').node.id.sid).toBe(model.clock.sid);
});

test('resets session ID to user specified', () => {
const model = Model.withLogicalClock().setSchema(
s.obj({
id: s.str<string>('asdf'),
num: s.con(123),
}),
);
expect(model.view().num).toBe(123);
expect(model.api.r.get().get('num').node.id.sid).toBe(SESSION.GLOBAL);
model.api.r.get().set({
num: 456,
});
expect(model.view().num).toBe(456);
expect(model.api.r.get().get('num').node.id.sid).not.toBe(SESSION.GLOBAL);
});