Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/sync/editor/db/util.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45// Well-defined JSON.stringify...6const json_stable = require("json-stable-stringify");7import * as immutable from "immutable";8import { isEqual } from "lodash";910export function to_key(s: any): string {11if (immutable.Map.isMap(s)) {12s = s.toJS();13}14// NOTE: s is not undefined.15return json_stable(s) as string;16}1718/* TODO/worry: I change to json_stable from misc.to_json19and misc.from_json, so the string is canonical. However,20Date objects will be treated differently. This is fine21by me, in that probably we should just ensure no date22objects are ever used with db-doc... or have a special23column type (like string_cols) for them.24I think right now all our applications (e.g., task lists, jupyter)25just use ms since epoch explicitly.26*/2728export function to_str(obj: any[]): string {29const v = obj.map((x) => json_stable(x));30/* NOTE: It is *VERY* important to sort v! Otherwise, the hash31of this document, which is used by32syncstring, isn't stable in terms of the value of the33document. This can in theory34cause massive trouble with file saves, e.g., of jupyter35notebooks, courses, etc. (They save fine, but36they appear not to for the user...).37*/38v.sort();39return v.join("\n");40}4142// Create an object change such that merge_set(obj1, change) produces obj2.43// Thus for each key, value1 of obj1 and key, value2 of obj2:44// If value1 is the same as value2, do nothing.45// If value1 exists but value2 does not, do change[key] = null46// If value2 exists but value1 does not, do change[key] = value247export function map_merge_patch(obj1, obj2) {48let val2;49const change = {};50for (var key in obj1) {51const val1 = obj1[key];52val2 = obj2[key];53if (isEqual(val1, val2)) {54// nothing to do55} else if (val2 == null) {56change[key] = null;57} else {58change[key] = val2;59}60}61for (key in obj2) {62val2 = obj2[key];63if (obj1[key] != null) {64continue;65}66change[key] = val2;67}68return change;69}7071// obj and change are both immutable.js Maps. Do the following:72// - for each value of change that is null or undefined, we delete that key from obj73// - we set the other vals of obj, accordingly.74// So this is a shallow merge with the ability to *delete* keys.75export function merge_set(76obj: immutable.Map<any, any>,77change: immutable.Map<any, any>78): immutable.Map<any, any> {79change.forEach(function (v, k) {80if (v === null || v == null) {81obj = obj.delete(k);82} else {83obj = obj.set(k, v);84}85});86return obj;87}8889export function nonnull_cols(90f: immutable.Map<any, any>91): immutable.Map<any, any> {92// Yes, "!==" not "!=" below!93return immutable.Map(f.filter((v, _) => v !== null));94}959697