@platform/cell.typesystem
Version:
The 'strongly typed sheets' system of the CellOS.
322 lines (321 loc) • 15.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypedSheetRow = void 0;
var tslib_1 = require("tslib");
var operators_1 = require("rxjs/operators");
var TypeSystem_core_1 = require("../../TypeSystem.core");
var common_1 = require("./common");
var TypedSheetRef_1 = require("./TypedSheetRef");
var TypedSheetRefs_1 = require("./TypedSheetRefs");
var TypedSheetRow = (function () {
function TypedSheetRow(args) {
var _this = this;
this._columns = [];
this._prop = {};
this._refs = {};
this._data = {};
this._isLoaded = false;
this._status = 'INIT';
this._loading = {};
this.typename = args.typename;
this.uri = common_1.Uri.row(args.uri);
this.index = Number.parseInt(this.uri.key, 10) - 1;
this._columns = args.columns;
this._ctx = args.ctx;
this._sheet = args.sheet;
var event$ = this._ctx.event$;
var cellChange$ = event$.pipe((0, operators_1.filter)(function (e) { return e.type === 'TypedSheet/change'; }), (0, operators_1.map)(function (e) { return e.payload; }), (0, operators_1.filter)(function (e) { return e.kind === 'CELL'; }), (0, operators_1.filter)(function (e) { return _this.isThisSheet(e.ns); }), (0, operators_1.filter)(function (e) { return _this.isThisRow(e.key); }), (0, operators_1.map)(function (_a) {
var to = _a.to, ns = _a.ns, key = _a.key;
return ({ key: key, to: to, uri: common_1.Uri.parse(common_1.Uri.create.cell(ns, key)) });
}), (0, operators_1.filter)(function (_a) {
var uri = _a.uri;
return uri.ok && uri.type === 'CELL';
}), (0, operators_1.map)(function (e) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, e), { uri: e.uri.parts, index: common_1.coord.cell.toRowIndex(e.key) })); }), (0, operators_1.filter)(function (e) { return e.index === _this.index; }));
cellChange$
.pipe((0, operators_1.map)(function (e) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, e), { columnDef: _this.findColumnByKey(e.uri.key) })); }), (0, operators_1.filter)(function (e) { return Boolean(e.columnDef); }), (0, operators_1.map)(function (e) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, e), { target: TypeSystem_core_1.TypeTarget.parse(e.columnDef.target) })); }), (0, operators_1.filter)(function (e) { return e.target.isValid && e.target.isInline; }))
.subscribe(function (e) { return _this.setData(e.columnDef, e.to); });
common_1.rx.payload(event$, 'TypedSheet/sync')
.pipe((0, operators_1.filter)(function (e) { return _this.isThisSheet(e.changes.uri); }), (0, operators_1.filter)(function (e) { return Boolean(e.changes.cells); }))
.subscribe(function (e) {
var data = e.changes.cells || {};
Object.keys(data)
.filter(function (key) { return _this.isThisRow(key); })
.map(function (key) { return ({ key: key, value: data[key], columnDef: _this.findColumnByKey(key) }); })
.filter(function (_a) {
var columnDef = _a.columnDef;
return Boolean(columnDef);
})
.forEach(function (e) { return _this.setData(e.columnDef, e.value.to); });
});
}
TypedSheetRow.create = function (args) {
return new TypedSheetRow(args);
};
TypedSheetRow.load = function (args) {
return TypedSheetRow.create(args).load();
};
Object.defineProperty(TypedSheetRow.prototype, "status", {
get: function () {
return this._status;
},
enumerable: false,
configurable: true
});
Object.defineProperty(TypedSheetRow.prototype, "isLoaded", {
get: function () {
return this._isLoaded;
},
enumerable: false,
configurable: true
});
Object.defineProperty(TypedSheetRow.prototype, "types", {
get: function () {
if (!this._types) {
var map_1;
var list_1;
var columns_1 = this._columns;
var row_1 = this.uri;
var types_1 = (this._types = {
get list() {
if (!list_1) {
list_1 = columns_1.map(function (type) {
var uri;
return (0, tslib_1.__assign)((0, tslib_1.__assign)({}, type), { get uri() {
return (uri || (uri = common_1.Uri.cell(common_1.Uri.create.cell(row_1.ns, "" + type.column + row_1.key))));
} });
});
}
return list_1;
},
get map() {
if (!map_1) {
map_1 = types_1.list.reduce(function (acc, type) {
acc[type.prop] = type;
return acc;
}, {});
}
return map_1;
},
});
}
return this._types;
},
enumerable: false,
configurable: true
});
Object.defineProperty(TypedSheetRow.prototype, "props", {
get: function () {
var _this = this;
if (!this._props) {
var props_1 = {};
this._columns.forEach(function (typeDef) {
var name = typeDef.prop;
Object.defineProperty(props_1, name, {
get: function () { return _this.prop(name).get(); },
set: function (value) { return _this.prop(name).set(value); },
});
});
this._props = props_1;
}
return this._props;
},
enumerable: false,
configurable: true
});
TypedSheetRow.prototype.toString = function () {
return this.uri.toString();
};
TypedSheetRow.prototype.load = function (options) {
if (options === void 0) { options = {}; }
return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
var self, props, cacheKey, promise;
var _this = this;
return (0, tslib_1.__generator)(this, function (_a) {
self = this;
if (this.isLoaded && !options.force) {
return [2, self];
}
props = options.props;
cacheKey = props ? "load:" + props.join(',') : 'load';
if (!options.force && this._loading[cacheKey]) {
return [2, this._loading[cacheKey]];
}
promise = new Promise(function (resolve, reject) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
var ns, index, sheet, query;
var _this = this;
return (0, tslib_1.__generator)(this, function (_a) {
switch (_a.label) {
case 0:
this._status = 'LOADING';
ns = this.uri.ns;
index = this.index;
sheet = this._sheet;
this.fire({ type: 'TypedSheet/row/loading', payload: { sheet: sheet, index: index } });
query = this.uri.key + ":" + this.uri.key;
return [4, Promise.all(this._columns
.filter(function (columnDef) { return (!props ? true : props.includes(columnDef.prop)); })
.map(function (columnDef) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
var res, key;
return (0, tslib_1.__generator)(this, function (_a) {
switch (_a.label) {
case 0: return [4, this._ctx.fetch.getCells({ ns: ns, query: query })];
case 1:
res = _a.sent();
key = "" + columnDef.column + (this.index + 1);
this.setData(columnDef, (res.cells || {})[key] || {});
return [2];
}
});
}); }))];
case 1:
_a.sent();
this._status = 'LOADED';
this._isLoaded = true;
this.fire({ type: 'TypedSheet/row/loaded', payload: { sheet: sheet, index: index } });
delete this._loading[cacheKey];
resolve(self);
return [2];
}
});
}); });
this._loading[cacheKey] = promise;
return [2, promise];
});
});
};
TypedSheetRow.prototype.toObject = function () {
var _this = this;
return this._columns.reduce(function (acc, typeDef) {
var prop = typeDef.prop;
acc[prop] = _this.prop(prop).get();
return acc;
}, {});
};
TypedSheetRow.prototype.type = function (prop) {
var typeDef = this.findColumnByProp(prop);
if (!typeDef) {
var err = "The property '" + prop + "' is not defined by a column on [" + this.uri + "]";
throw new Error(err);
}
return typeDef;
};
TypedSheetRow.prototype.prop = function (name) {
var propname = name;
if (this._prop[propname]) {
return this._prop[propname];
}
var self = this;
var columnDef = this.findColumnByProp(name);
var target = TypeSystem_core_1.TypeTarget.parse(columnDef.target);
var typename = columnDef.type.typename;
if (!target.isValid) {
var err = "Property '" + name + "' (column " + columnDef.column + ") has an invalid target '" + columnDef.target + "'.";
throw new Error(err);
}
var api = {
get: function () {
var done = function (result) {
if (result === undefined && TypeSystem_core_1.TypeDefault.isTypeDefaultValue(columnDef.default)) {
result = columnDef.default.value;
}
if (result === undefined && columnDef.type.isArray) {
result = [];
}
return result;
};
if (!target.isValid) {
var err = "Cannot read property '" + columnDef.prop + "' (column " + columnDef.column + ") because the target '" + columnDef.target + "' is invalid.";
throw new Error(err);
}
var cell = self._data[columnDef.column] || {};
if (target.isInline) {
return done(TypeSystem_core_1.TypeTarget.inline(columnDef).read(cell));
}
if (target.isRef) {
if (self._refs[propname]) {
return done(self._refs[propname]);
}
var links = cell.links;
var typeDef = columnDef;
var res = self.getOrCreateRef({ typename: typename, typeDef: typeDef, links: links });
self._refs[propname] = res.ref;
return done(res.ref);
}
throw new Error("Failed to read property '" + name + "' (column " + columnDef.column + ").");
},
set: function (value) {
if (target.isInline) {
var isChanged = !common_1.R.equals(api.get(), value);
if (isChanged) {
var cell = self._data[columnDef.column] || {};
var data = TypeSystem_core_1.TypeTarget.inline(columnDef).write({ cell: cell, data: value });
self.fireChange(columnDef, data);
}
}
if (target.isRef) {
var err = "Cannot write to property '" + name + "' (column " + columnDef.column + ") because it is a REF target.";
throw new Error(err);
}
return self;
},
clear: function () {
if (target.isInline) {
api.set(undefined);
}
return self;
},
};
this._prop[name] = api;
return api;
};
TypedSheetRow.prototype.fire = function (e) {
this._ctx.event$.next(e);
};
TypedSheetRow.prototype.isThisSheet = function (ns) {
return common_1.Uri.strip.ns(ns) === this.uri.ns;
};
TypedSheetRow.prototype.isThisRow = function (key) {
return common_1.coord.cell.toRowIndex(key) === this.index;
};
TypedSheetRow.prototype.findColumnByKey = function (key) {
var columnKey = common_1.Schema.coord.cell.toColumnKey(key);
return this._columns.find(function (def) { return def.column === columnKey; });
};
TypedSheetRow.prototype.findColumnByProp = function (prop) {
var res = this._columns.find(function (def) { return def.prop === prop; });
if (!res) {
var err = "Column-definition for the property '" + prop + "' not found.";
throw new Error(err);
}
return res;
};
TypedSheetRow.prototype.fireChange = function (columnDef, to) {
var key = "" + columnDef.column + (this.index + 1);
var ns = common_1.Uri.create.ns(this.uri.ns);
this._ctx.event$.next({
type: 'TypedSheet/change',
payload: { kind: 'CELL', ns: ns, key: key, to: to },
});
};
TypedSheetRow.prototype.setData = function (columnDef, data) {
this._data[columnDef.column] = data;
};
TypedSheetRow.prototype.getOrCreateRef = function (args) {
var typename = args.typename, typeDef = args.typeDef, _a = args.links, links = _a === void 0 ? {} : _a;
var ctx = this._ctx;
var isArray = typeDef.type.isArray;
var link = TypedSheetRefs_1.TypedSheetRefs.refLink({ typeDef: typeDef, links: links }).link;
var exists = Boolean(link);
var uri = common_1.Uri.create.cell(this.uri.ns, "" + typeDef.column + (this.index + 1));
var parent = {
cell: common_1.Uri.cell(uri),
sheet: this._sheet,
};
var ref = isArray
? TypedSheetRefs_1.TypedSheetRefs.create({ typename: typename, typeDef: typeDef, ctx: ctx, parent: parent })
: TypedSheetRef_1.TypedSheetRef.create({ typename: typename, typeDef: typeDef, ctx: ctx });
return { ref: ref, exists: exists };
};
return TypedSheetRow;
}());
exports.TypedSheetRow = TypedSheetRow;