UNPKG

3.14 kBJavaScriptView Raw
1var json0 = require('ot-json0').type;
2var ShareDBError = require('./error');
3
4var ERROR_CODE = ShareDBError.CODES;
5
6exports.projectSnapshot = projectSnapshot;
7exports.projectSnapshots = projectSnapshots;
8exports.projectOp = projectOp;
9exports.isSnapshotAllowed = isSnapshotAllowed;
10exports.isOpAllowed = isOpAllowed;
11
12
13// Project a snapshot in place to only include specified fields
14function projectSnapshot(fields, snapshot) {
15 // Only json0 supported right now
16 if (snapshot.type && snapshot.type !== json0.uri) {
17 throw new Error(ERROR_CODE.ERR_TYPE_CANNOT_BE_PROJECTED, 'Cannot project snapshots of type ' + snapshot.type);
18 }
19 snapshot.data = projectData(fields, snapshot.data);
20}
21
22function projectSnapshots(fields, snapshots) {
23 for (var i = 0; i < snapshots.length; i++) {
24 var snapshot = snapshots[i];
25 projectSnapshot(fields, snapshot);
26 }
27}
28
29function projectOp(fields, op) {
30 if (op.create) {
31 projectSnapshot(fields, op.create);
32 }
33 if (op.op) {
34 op.op = projectEdit(fields, op.op);
35 }
36}
37
38function projectEdit(fields, op) {
39 // So, we know the op is a JSON op
40 var result = [];
41
42 for (var i = 0; i < op.length; i++) {
43 var c = op[i];
44 var path = c.p;
45
46 if (path.length === 0) {
47 var newC = {p: []};
48
49 if (c.od !== undefined || c.oi !== undefined) {
50 if (c.od !== undefined) {
51 newC.od = projectData(fields, c.od);
52 }
53 if (c.oi !== undefined) {
54 newC.oi = projectData(fields, c.oi);
55 }
56 result.push(newC);
57 }
58 } else {
59 // The path has a first element. Just check it against the fields.
60 if (fields[path[0]]) {
61 result.push(c);
62 }
63 }
64 }
65 return result;
66}
67
68function isOpAllowed(knownType, fields, op) {
69 if (op.create) {
70 return isSnapshotAllowed(fields, op.create);
71 }
72 if (op.op) {
73 if (knownType && knownType !== json0.uri) return false;
74 return isEditAllowed(fields, op.op);
75 }
76 // Noop and del are both ok.
77 return true;
78}
79
80// Basically, would the projected version of this data be the same as the original?
81function isSnapshotAllowed(fields, snapshot) {
82 if (snapshot.type && snapshot.type !== json0.uri) {
83 return false;
84 }
85 if (snapshot.data == null) {
86 return true;
87 }
88 // Data must be an object if not null
89 if (typeof snapshot.data !== 'object' || Array.isArray(snapshot.data)) {
90 return false;
91 }
92 for (var k in snapshot.data) {
93 if (!fields[k]) return false;
94 }
95 return true;
96}
97
98function isEditAllowed(fields, op) {
99 for (var i = 0; i < op.length; i++) {
100 var c = op[i];
101 if (c.p.length === 0) {
102 return false;
103 } else if (!fields[c.p[0]]) {
104 return false;
105 }
106 }
107 return true;
108}
109
110function projectData(fields, data) {
111 // Return back null or undefined
112 if (data == null) {
113 return data;
114 }
115 // If data is not an object, the projected version just looks like null.
116 if (typeof data !== 'object' || Array.isArray(data)) {
117 return null;
118 }
119 // Shallow copy of each field
120 var result = {};
121 for (var key in fields) {
122 if (data.hasOwnProperty(key)) {
123 result[key] = data[key];
124 }
125 }
126 return result;
127}