cojson 0.1.12 → 0.2.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.
- package/dist/coValue.d.ts +1 -1
- package/dist/coValueCore.d.ts +4 -3
- package/dist/coValueCore.js +5 -4
- package/dist/coValueCore.js.map +1 -1
- package/dist/coValues/coList.js +2 -1
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.d.ts +7 -12
- package/dist/coValues/coMap.js +2 -1
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.d.ts +10 -1
- package/dist/coValues/coStream.js +43 -5
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/crypto.d.ts +8 -0
- package/dist/crypto.js +10 -3
- package/dist/crypto.js.map +1 -1
- package/dist/group.d.ts +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/jsonStringify.d.ts +6 -0
- package/dist/{fastJsonStableStringify.js → jsonStringify.js} +10 -6
- package/dist/jsonStringify.js.map +1 -0
- package/dist/jsonValue.d.ts +1 -1
- package/dist/media.d.ts +8 -0
- package/dist/media.js +2 -0
- package/dist/media.js.map +1 -0
- package/dist/node.js +1 -1
- package/dist/permissions.js +4 -2
- package/dist/permissions.js.map +1 -1
- package/dist/sync.js +1 -2
- package/dist/sync.js.map +1 -1
- package/package.json +2 -2
- package/src/coValue.ts +1 -1
- package/src/coValueCore.test.ts +11 -10
- package/src/coValueCore.ts +9 -6
- package/src/coValues/coList.ts +2 -1
- package/src/coValues/coMap.ts +11 -12
- package/src/coValues/coStream.ts +54 -6
- package/src/crypto.ts +22 -4
- package/src/group.ts +1 -1
- package/src/index.ts +5 -1
- package/src/{fastJsonStableStringify.ts → jsonStringify.ts} +23 -11
- package/src/jsonValue.ts +1 -1
- package/src/media.ts +9 -0
- package/src/node.ts +1 -1
- package/src/permissions.ts +5 -2
- package/src/sync.test.ts +16 -18
- package/src/sync.ts +1 -2
- package/dist/fastJsonStableStringify.d.ts +0 -1
- package/dist/fastJsonStableStringify.js.map +0 -1
package/src/index.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { AnonymousControlledAccount, ControlledAccount } from "./account.js";
|
|
|
25
25
|
import { rawCoIDtoBytes, rawCoIDfromBytes } from "./ids.js";
|
|
26
26
|
import { Group, expectGroupContent } from "./group.js";
|
|
27
27
|
import { base64URLtoBytes, bytesToBase64url } from "./base64url.js";
|
|
28
|
+
import { parseJSON } from "./jsonStringify.js";
|
|
28
29
|
|
|
29
30
|
import type { SessionID, AgentID } from "./ids.js";
|
|
30
31
|
import type { CoID, CoValueImpl } from "./coValue.js";
|
|
@@ -34,6 +35,7 @@ import type { SyncMessage, Peer } from "./sync.js";
|
|
|
34
35
|
import type { AgentSecret } from "./crypto.js";
|
|
35
36
|
import type { AccountID, Profile } from "./account.js";
|
|
36
37
|
import type { InviteSecret } from "./group.js";
|
|
38
|
+
import type * as Media from "./media.js";
|
|
37
39
|
|
|
38
40
|
type Value = JsonValue | CoValueImpl;
|
|
39
41
|
|
|
@@ -53,7 +55,8 @@ export const cojsonInternals = {
|
|
|
53
55
|
shortHashLength,
|
|
54
56
|
expectGroupContent,
|
|
55
57
|
base64URLtoBytes,
|
|
56
|
-
bytesToBase64url
|
|
58
|
+
bytesToBase64url,
|
|
59
|
+
parseJSON
|
|
57
60
|
};
|
|
58
61
|
|
|
59
62
|
export {
|
|
@@ -90,6 +93,7 @@ export type {
|
|
|
90
93
|
AgentSecret,
|
|
91
94
|
InviteSecret,
|
|
92
95
|
SyncMessage,
|
|
96
|
+
Media
|
|
93
97
|
};
|
|
94
98
|
|
|
95
99
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
// adapted from fast-json-stable-stringify (https://github.com/epoberezkin/fast-json-stable-stringify)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
export type Stringified<T> = string & { __type: T };
|
|
4
|
+
|
|
5
|
+
export function stableStringify<T>(data: T): Stringified<T>
|
|
6
|
+
export function stableStringify(data: undefined): undefined
|
|
7
|
+
export function stableStringify<T>(data: T | undefined): Stringified<T> | undefined {
|
|
5
8
|
const cycles = false;
|
|
6
9
|
|
|
7
10
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
11
|
const seen: any[] = [];
|
|
9
|
-
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
let node = data as any;
|
|
10
14
|
|
|
11
15
|
if (node && node.toJSON && typeof node.toJSON === "function") {
|
|
12
16
|
node = node.toJSON();
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
if (node === undefined) return;
|
|
16
|
-
if (typeof node == "number")
|
|
20
|
+
if (typeof node == "number")
|
|
21
|
+
return (isFinite(node) ? "" + node : "null") as Stringified<T>;
|
|
17
22
|
if (typeof node !== "object") {
|
|
18
|
-
if (
|
|
19
|
-
|
|
23
|
+
if (
|
|
24
|
+
typeof node === "string" &&
|
|
25
|
+
(node.startsWith("encrypted_U") || node.startsWith("binary_U"))
|
|
26
|
+
) {
|
|
27
|
+
return `"${node}"` as Stringified<T>;
|
|
20
28
|
}
|
|
21
|
-
return JSON.stringify(node)
|
|
29
|
+
return JSON.stringify(node) as Stringified<T>;
|
|
22
30
|
}
|
|
23
31
|
|
|
24
32
|
let i, out;
|
|
@@ -28,13 +36,13 @@ export function stableStringify(data: any): string | undefined {
|
|
|
28
36
|
if (i) out += ",";
|
|
29
37
|
out += stableStringify(node[i]) || "null";
|
|
30
38
|
}
|
|
31
|
-
return out + "]"
|
|
39
|
+
return (out + "]") as Stringified<T>;
|
|
32
40
|
}
|
|
33
41
|
|
|
34
|
-
if (node === null) return "null"
|
|
42
|
+
if (node === null) return "null" as Stringified<T>;
|
|
35
43
|
|
|
36
44
|
if (seen.indexOf(node) !== -1) {
|
|
37
|
-
if (cycles) return JSON.stringify("__cycle__")
|
|
45
|
+
if (cycles) return JSON.stringify("__cycle__") as Stringified<T>;
|
|
38
46
|
throw new TypeError("Converting circular structure to JSON");
|
|
39
47
|
}
|
|
40
48
|
|
|
@@ -50,5 +58,9 @@ export function stableStringify(data: any): string | undefined {
|
|
|
50
58
|
out += JSON.stringify(key) + ":" + value;
|
|
51
59
|
}
|
|
52
60
|
seen.splice(seenIndex, 1);
|
|
53
|
-
return "{" + out + "}"
|
|
61
|
+
return ("{" + out + "}") as Stringified<T>;
|
|
54
62
|
}
|
|
63
|
+
|
|
64
|
+
export function parseJSON<T>(json: Stringified<T>): T {
|
|
65
|
+
return JSON.parse(json);
|
|
66
|
+
}
|
package/src/jsonValue.ts
CHANGED
|
@@ -3,4 +3,4 @@ import { RawCoID } from './ids.js';
|
|
|
3
3
|
export type JsonAtom = string | number | boolean | null;
|
|
4
4
|
export type JsonValue = JsonAtom | JsonArray | JsonObject | RawCoID;
|
|
5
5
|
export type JsonArray = JsonValue[];
|
|
6
|
-
export type JsonObject = { [key: string]: JsonValue; };
|
|
6
|
+
export type JsonObject = { [key: string]: JsonValue | undefined; };
|
package/src/media.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CoMap } from './coValues/coMap.js'
|
|
2
|
+
import { CoID } from './coValue.js'
|
|
3
|
+
import { BinaryCoStream } from './coValues/coStream.js'
|
|
4
|
+
|
|
5
|
+
export type ImageDefinition = CoMap<{
|
|
6
|
+
originalSize: [number, number];
|
|
7
|
+
placeholderDataURL?: string;
|
|
8
|
+
[res: `${number}x${number}`]: CoID<BinaryCoStream>;
|
|
9
|
+
}>;
|
package/src/node.ts
CHANGED
package/src/permissions.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
AccountID,
|
|
16
16
|
Profile,
|
|
17
17
|
} from "./account.js";
|
|
18
|
+
import { parseJSON } from "./jsonStringify.js";
|
|
18
19
|
|
|
19
20
|
export type PermissionsDef =
|
|
20
21
|
| { type: "group"; initialAdmin: AccountID | AgentID }
|
|
@@ -76,11 +77,13 @@ export function determineValidTransactions(
|
|
|
76
77
|
// console.log("before", { memberState, validTransactions });
|
|
77
78
|
const transactor = accountOrAgentIDfromSessionID(sessionID);
|
|
78
79
|
|
|
79
|
-
const
|
|
80
|
+
const changes = parseJSON(tx.changes)
|
|
81
|
+
|
|
82
|
+
const change = changes[0] as
|
|
80
83
|
| MapOpPayload<AccountID | AgentID, Role>
|
|
81
84
|
| MapOpPayload<"readKey", JsonValue>
|
|
82
85
|
| MapOpPayload<"profile", CoID<Profile>>;
|
|
83
|
-
if (
|
|
86
|
+
if (changes.length !== 1) {
|
|
84
87
|
console.warn("Group transaction must have exactly one change");
|
|
85
88
|
continue;
|
|
86
89
|
}
|
package/src/sync.test.ts
CHANGED
|
@@ -8,12 +8,10 @@ import {
|
|
|
8
8
|
randomAnonymousAccountAndSessionID,
|
|
9
9
|
shouldNotResolve,
|
|
10
10
|
} from "./testUtils.js";
|
|
11
|
-
import {
|
|
12
|
-
connectedPeers,
|
|
13
|
-
newStreamPair
|
|
14
|
-
} from "./streamUtils.js";
|
|
11
|
+
import { connectedPeers, newStreamPair } from "./streamUtils.js";
|
|
15
12
|
import { AccountID } from "./account.js";
|
|
16
13
|
import { cojsonReady } from "./index.js";
|
|
14
|
+
import { stableStringify } from "./jsonStringify.js";
|
|
17
15
|
|
|
18
16
|
beforeEach(async () => {
|
|
19
17
|
await cojsonReady;
|
|
@@ -84,13 +82,13 @@ test("Node replies with initial tx and header to empty subscribe", async () => {
|
|
|
84
82
|
privacy: "trusting" as const,
|
|
85
83
|
madeAt: map.core.sessions[node.currentSessionID]!
|
|
86
84
|
.transactions[0]!.madeAt,
|
|
87
|
-
changes: [
|
|
85
|
+
changes: stableStringify([
|
|
88
86
|
{
|
|
89
87
|
op: "set",
|
|
90
88
|
key: "hello",
|
|
91
89
|
value: "world",
|
|
92
90
|
} satisfies MapOpPayload<string, string>,
|
|
93
|
-
],
|
|
91
|
+
]),
|
|
94
92
|
},
|
|
95
93
|
],
|
|
96
94
|
lastSignature:
|
|
@@ -162,13 +160,13 @@ test("Node replies with only new tx to subscribe with some known state", async (
|
|
|
162
160
|
privacy: "trusting" as const,
|
|
163
161
|
madeAt: map.core.sessions[node.currentSessionID]!
|
|
164
162
|
.transactions[1]!.madeAt,
|
|
165
|
-
changes: [
|
|
163
|
+
changes: stableStringify([
|
|
166
164
|
{
|
|
167
165
|
op: "set",
|
|
168
166
|
key: "goodbye",
|
|
169
167
|
value: "world",
|
|
170
168
|
} satisfies MapOpPayload<string, string>,
|
|
171
|
-
],
|
|
169
|
+
]),
|
|
172
170
|
},
|
|
173
171
|
],
|
|
174
172
|
lastSignature:
|
|
@@ -251,13 +249,13 @@ test("After subscribing, node sends own known state and new txs to peer", async
|
|
|
251
249
|
privacy: "trusting" as const,
|
|
252
250
|
madeAt: map.core.sessions[node.currentSessionID]!
|
|
253
251
|
.transactions[0]!.madeAt,
|
|
254
|
-
changes: [
|
|
252
|
+
changes: stableStringify([
|
|
255
253
|
{
|
|
256
254
|
op: "set",
|
|
257
255
|
key: "hello",
|
|
258
256
|
value: "world",
|
|
259
257
|
} satisfies MapOpPayload<string, string>,
|
|
260
|
-
],
|
|
258
|
+
]),
|
|
261
259
|
},
|
|
262
260
|
],
|
|
263
261
|
lastSignature:
|
|
@@ -283,13 +281,13 @@ test("After subscribing, node sends own known state and new txs to peer", async
|
|
|
283
281
|
privacy: "trusting" as const,
|
|
284
282
|
madeAt: map.core.sessions[node.currentSessionID]!
|
|
285
283
|
.transactions[1]!.madeAt,
|
|
286
|
-
changes: [
|
|
284
|
+
changes: stableStringify([
|
|
287
285
|
{
|
|
288
286
|
op: "set",
|
|
289
287
|
key: "goodbye",
|
|
290
288
|
value: "world",
|
|
291
289
|
} satisfies MapOpPayload<string, string>,
|
|
292
|
-
],
|
|
290
|
+
]),
|
|
293
291
|
},
|
|
294
292
|
],
|
|
295
293
|
lastSignature:
|
|
@@ -362,13 +360,13 @@ test("Client replies with known new content to tellKnownState from server", asyn
|
|
|
362
360
|
privacy: "trusting" as const,
|
|
363
361
|
madeAt: map.core.sessions[node.currentSessionID]!
|
|
364
362
|
.transactions[0]!.madeAt,
|
|
365
|
-
changes: [
|
|
363
|
+
changes: stableStringify([
|
|
366
364
|
{
|
|
367
365
|
op: "set",
|
|
368
366
|
key: "hello",
|
|
369
367
|
value: "world",
|
|
370
368
|
} satisfies MapOpPayload<string, string>,
|
|
371
|
-
],
|
|
369
|
+
]),
|
|
372
370
|
},
|
|
373
371
|
],
|
|
374
372
|
lastSignature:
|
|
@@ -465,13 +463,13 @@ test("No matter the optimistic known state, node respects invalid known state me
|
|
|
465
463
|
privacy: "trusting" as const,
|
|
466
464
|
madeAt: map.core.sessions[node.currentSessionID]!
|
|
467
465
|
.transactions[1]!.madeAt,
|
|
468
|
-
changes: [
|
|
466
|
+
changes: stableStringify([
|
|
469
467
|
{
|
|
470
468
|
op: "set",
|
|
471
469
|
key: "goodbye",
|
|
472
470
|
value: "world",
|
|
473
471
|
} satisfies MapOpPayload<string, string>,
|
|
474
|
-
],
|
|
472
|
+
]),
|
|
475
473
|
},
|
|
476
474
|
],
|
|
477
475
|
lastSignature:
|
|
@@ -568,13 +566,13 @@ test("If we add a server peer, all updates to all coValues are sent to it, even
|
|
|
568
566
|
privacy: "trusting" as const,
|
|
569
567
|
madeAt: map.core.sessions[node.currentSessionID]!
|
|
570
568
|
.transactions[0]!.madeAt,
|
|
571
|
-
changes: [
|
|
569
|
+
changes: stableStringify([
|
|
572
570
|
{
|
|
573
571
|
op: "set",
|
|
574
572
|
key: "hello",
|
|
575
573
|
value: "world",
|
|
576
574
|
} satisfies MapOpPayload<string, string>,
|
|
577
|
-
],
|
|
575
|
+
]),
|
|
578
576
|
},
|
|
579
577
|
],
|
|
580
578
|
lastSignature:
|
package/src/sync.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
WritableStreamDefaultWriter,
|
|
10
10
|
} from "isomorphic-streams";
|
|
11
11
|
import { RawCoID, SessionID } from "./ids.js";
|
|
12
|
-
import { stableStringify } from "./
|
|
12
|
+
import { stableStringify } from "./jsonStringify.js";
|
|
13
13
|
|
|
14
14
|
export type CoValueKnownState = {
|
|
15
15
|
id: RawCoID;
|
|
@@ -269,7 +269,6 @@ export class SyncManager {
|
|
|
269
269
|
);
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
|
-
console.log("DONE!!!");
|
|
273
272
|
} catch (e) {
|
|
274
273
|
console.error(`Error reading from peer ${peer.id}`, e);
|
|
275
274
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function stableStringify(data: any): string | undefined;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fastJsonStableStringify.js","sourceRoot":"","sources":["../src/fastJsonStableStringify.ts"],"names":[],"mappings":"AAAA,sGAAsG;AAEtG,8DAA8D;AAC9D,MAAM,UAAU,eAAe,CAAC,IAAS;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC;IAErB,8DAA8D;IAC9D,MAAM,IAAI,GAAU,EAAE,CAAC;IACvB,IAAI,IAAI,GAAG,IAAI,CAAC;IAEhB,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE;QAC1D,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;KACxB;IAED,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO;IAC/B,IAAI,OAAO,IAAI,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IACxE,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QAC1B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE;YAC7F,OAAO,IAAI,IAAI,GAAG,CAAC;SACtB;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;KAC/B;IAED,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACrB,GAAG,GAAG,GAAG,CAAC;QACV,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC9B,IAAI,CAAC;gBAAE,GAAG,IAAI,GAAG,CAAC;YAClB,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;SAC7C;QACD,OAAO,GAAG,GAAG,GAAG,CAAC;KACpB;IAED,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAEjC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE;QAC3B,IAAI,MAAM;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAC;KAChE;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,GAAG,GAAG,EAAE,CAAC;IACT,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACrB,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAEzC,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,GAAG;YAAE,GAAG,IAAI,GAAG,CAAC;QACpB,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC;KAC5C;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IAC1B,OAAO,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAC3B,CAAC"}
|