@platform/cell.schema
Version:
URI and database schemas for the `cell.os`.
307 lines (306 loc) • 12.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Uri = exports.DEFAULT = void 0;
var tslib_1 = require("tslib");
var common_1 = require("../common");
var ALLOW = { NS: [] };
exports.DEFAULT = { ALLOW: ALLOW };
var stripQuotes = function (text) {
return text.trim().replace(/^"/, '').replace(/"$/, '').replace(/^'/, '').replace(/'$/, '').trim();
};
var Uri = (function () {
function Uri() {
}
Uri.clean = function (input) {
var text = stripQuotes(input || '');
text = text.replace(/^=/, '').trim();
text = stripQuotes(text);
text = text.split('?')[0].trim();
return text;
};
Uri.parse = function (input) {
var text = Uri.clean(input);
var data = { type: 'UNKNOWN' };
var error;
var toString = function () { return text; };
var setError = function (isError, message) {
if (!error && isError) {
error = { type: 'URI', message: message, uri: text };
}
};
setError(!text, 'URI not specified');
var index = text.indexOf(':');
setError(index < 0, 'Not a valid multi-part URI');
if (!error) {
var left = text.substring(0, index);
var right = text.substring(index + 1).trim();
if (left === 'ns') {
var id = right;
setError(!id, 'Namespace URI identifier not found');
setError(!Uri.is.valid.ns(id), "URI contains an invalid \"ns\" identifier (\"".concat(id, "\")"));
var uri = { type: 'NS', id: id, toString: toString };
data = uri;
}
else if (left === 'file') {
var id = right;
setError(!id, 'File URI identifier not found');
var parts = id.split(':');
var ns = (parts[0] || '').trim();
var file = (parts[1] || '').trim();
setError(!file, "File identifier within namespace \"".concat(ns, "\" not found"));
var uri = { type: 'FILE', id: id, ns: ns, file: file, toString: toString };
data = uri;
}
else if (left === 'cell') {
var id = right || '';
setError(!id, "ID of 'cell' not found");
var type = 'CELL';
var key = '';
var ns = '';
if (!id.includes(':')) {
setError(true, "The 'cell' URI does not have a coordinate address, eg. \":A1\" in \"cell:foo:A1\"");
}
else {
var bang = id.replace(/:/g, '!');
var parts = common_1.coord.cell.toCell(bang);
type = common_1.coord.cell.toType(bang);
key = parts.key;
ns = parts.ns;
setError(!key, "Coordinate key of '".concat(type || '<empty>', "' not found"));
setError(!ns, "Coordinate namespace of '".concat(type || '<empty>', "' not found"));
if (!error) {
text = toUri('cell', type, ns, key);
}
}
data = { type: type, id: id, ns: ns, key: key, toString: toString };
}
}
var ok = !error && data.type !== 'UNKNOWN';
var res = {
ok: ok,
uri: text,
type: data.type,
parts: data,
toString: toString,
};
return error ? tslib_1.__assign(tslib_1.__assign({}, res), { error: error }) : res;
};
Uri.ns = function (input, throwError) {
input = typeof input === 'string' && !input.includes(':') ? "ns:".concat(input.trim()) : input;
return parseOrThrow(input, 'NS', throwError);
};
Uri.cell = function (input, throwError) {
return parseOrThrow(input, 'CELL', throwError);
};
Uri.row = function (input, throwError) {
return parseOrThrow(input, 'ROW', throwError);
};
Uri.column = function (input, throwError) {
return parseOrThrow(input, 'COLUMN', throwError);
};
Uri.file = function (input, throwError) {
return parseOrThrow(input, 'FILE', throwError);
};
Uri.eq = function (a, b) {
var toString = function (input) {
input = input === undefined || input === null ? '' : input;
var text = input.toString().trim();
return !text.includes(':') ? "ns:".concat(text) : text;
};
return toString(a) === toString(b);
};
Uri.toNs = function (input) {
if (input === undefined) {
return Uri.ns((0, common_1.cuid)());
}
if (typeof input === 'string') {
input = Uri.clean(input);
}
if (typeof input === 'string' && !input.includes(':')) {
return Uri.ns(input);
}
var obj = typeof input === 'string' ? Uri.parse(input).parts : input;
if (obj.type === 'NS') {
return obj;
}
if (obj.type === 'CELL' || obj.type === 'COLUMN' || obj.type === 'ROW') {
return Uri.ns(obj.ns);
}
if (obj.type === 'FILE') {
return Uri.ns(obj.ns);
}
throw new Error("A namespace cannot be derived from the uri (".concat(input.toString(), ")"));
};
Uri.toRowIndex = function (input) {
var uri = typeof input === 'object' ? input : Uri.parse(input).parts;
if (uri.type === 'CELL' || uri.type === 'COLUMN' || uri.type === 'ROW') {
return common_1.coord.cell.toRowIndex(uri.key);
}
else {
return -1;
}
};
Uri.toColumnIndex = function (input) {
var uri = typeof input === 'object' ? input : Uri.parse(input).parts;
if (uri.type === 'CELL' || uri.type === 'COLUMN' || uri.type === 'ROW') {
return common_1.coord.cell.toColumnIndex(uri.key);
}
else {
return -1;
}
};
Uri.cuid = common_1.cuid;
Uri.slug = common_1.slug;
Uri.ALLOW = tslib_1.__assign({}, exports.DEFAULT.ALLOW);
Uri.create = {
ns: function (id) { return toUri('ns', 'NS', id); },
cell: function (ns, key) { return toUri('cell', 'CELL', ns, key); },
row: function (ns, key) { return toUri('cell', 'ROW', ns, key); },
column: function (ns, key) { return toUri('cell', 'COLUMN', ns, key); },
file: function (ns, fileid) { return toUri('file', 'FILE', ns, fileid); },
A1: function () { return Uri.create.cell((0, common_1.cuid)(), 'A1'); },
};
Uri.is = {
uri: function (input) {
try {
return Uri.parse(input).ok;
}
catch (error) {
return false;
}
},
type: function (type, input) {
try {
var uri_1 = Uri.parse(input);
var types = Array.isArray(type) ? type : [type];
return types.some(function (type) {
return uri_1.parts.type === type && (type === 'UNKNOWN' ? true : uri_1.ok);
});
}
catch (error) {
return false;
}
},
ns: function (input) { return Uri.is.type('NS', input); },
file: function (input) { return Uri.is.type('FILE', input); },
cell: function (input) { return Uri.is.type('CELL', input); },
row: function (input) { return Uri.is.type('ROW', input); },
column: function (input) { return Uri.is.type('COLUMN', input); },
valid: {
ns: function (input) {
var value = (input || '').replace(/^ns:/, '');
if (!value) {
return false;
}
if (isCuid(value)) {
return true;
}
var matchLegal = value.match(/^[A-Za-z0-9.]*$/);
if (!matchLegal || (matchLegal && matchLegal[0] !== value)) {
return false;
}
return Uri.ALLOW.NS.some(function (pattern) {
return typeof pattern === 'string'
? pattern.includes('*')
? common_1.wildcard.isMatch(value, pattern)
: pattern === value
: pattern(value);
});
},
},
};
Uri.strip = {
ns: function (input) { return stripPrefix(input, 'ns'); },
cell: function (input) { return stripPrefix(input, 'cell'); },
file: function (input) { return stripPrefix(input, 'file'); },
};
return Uri;
}());
exports.Uri = Uri;
var alphaNumeric = new RegExp(/^[a-z0-9]+$/i);
function trimPrefix(prefix, input) {
var regex = new RegExp("^".concat(prefix, ":+"));
return input.trim().replace(regex, '');
}
function toUri(prefix, type, id, suffix) {
id = (id || '').trim();
id = id === ':' ? '' : id;
if (id) {
['ns', 'cell', 'file'].forEach(function (prefix) { return (id = trimPrefix(prefix, id)); });
}
if (!id) {
throw new Error("The \"".concat(prefix, "\" URI was not supplied with a namespace identifier. (\"").concat(id, "\")"));
}
if (!Uri.is.valid.ns(id)) {
var err = "URI contains an invalid \"".concat(prefix, "\" identifier, must be an alpha-numeric cuid. (\"").concat(id, "\")");
throw new Error(err);
}
if (typeof suffix === 'string') {
suffix = (suffix || '').trim().replace(/^:*/, '');
if (!suffix) {
throw new Error("The \"".concat(prefix, "\" URI was not supplied with a suffix key."));
}
if (prefix === 'file') {
if (!alphaNumeric.test(suffix)) {
var err = "The \"file\" URI contains an invalid file-identifier, must be alpha-numeric (\"".concat(suffix, "\").");
throw new Error(err);
}
suffix = ":".concat(suffix);
}
else {
if (suffix === 'undefined') {
var err = "The suffix \"undefined\" (string) was given - this it likely an upstream error where an [undefined] value has been converted into a string.";
throw new Error(err);
}
suffix = suffix || '';
var suffixType = common_1.coord.cell.toType(suffix) || '';
if (suffixType !== type) {
var key = suffix || '';
var err = "The \"".concat(prefix, ":\" URI was not supplied with a valid ").concat(type, " key (given key \"").concat(key, "\").");
throw new Error(err);
}
suffix = ":".concat(suffix);
}
}
return "".concat(prefix, ":").concat(id).concat(suffix || '');
}
function isCuid(input) {
return input.length === 25 && input[0] === 'c' && alphaNumeric.test(input);
}
function parseOrThrow(input, type, throwError) {
if (typeof input === 'object') {
return input;
}
else {
var parsed = Uri.parse(input);
var isTypeMismatch = type && parsed.type !== type;
var hasError = Boolean(parsed.error) || isTypeMismatch;
throwError = throwError === undefined ? true : throwError;
if (hasError) {
var text = (input === null || input === void 0 ? void 0 : input.toString()) || '';
if (!parsed.error && isTypeMismatch) {
parsed.ok = false;
parsed.error = {
uri: text,
message: "The uri (".concat(text, ") is not of type ").concat(type),
type: 'URI',
};
}
if (typeof throwError === 'function') {
throwError(parsed);
}
if (throwError === true) {
if (parsed.error) {
throw new Error(parsed.error.message);
}
}
}
return parsed.parts;
}
}
function stripPrefix(input, prefix) {
var left = "".concat(prefix, ":");
input = (input || '').trim();
input = input.startsWith(left) ? input.substring(left.length) : input;
return input;
}