@platform/cell.schema
Version:
URI and database schemas for the `cell.os`.
174 lines (173 loc) • 7.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var common_1 = require("../common");
var ALLOW = { NS: [] };
exports.DEFAULT = { ALLOW: ALLOW };
var Uri = (function () {
function Uri() {
}
Uri.parse = function (input) {
var text = (input || '').trim().split('?')[0];
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 (\"" + 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 \"" + 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 '" + (type || '<empty>') + "' not found");
setError(!ns, "Coordinate namespace of '" + (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 = !Boolean(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.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); },
};
Uri.is = {
uri: function (input) { return Uri.parse(input).ok; },
type: function (type, input) {
var uri = Uri.parse(input);
return uri.parts.type === type && (type === 'UNKNOWN' ? true : uri.ok);
},
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);
});
},
},
};
return Uri;
}());
exports.Uri = Uri;
var alphaNumeric = new RegExp(/^[a-z0-9]+$/i);
function trimPrefix(prefix, input) {
var regex = new RegExp("^" + 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 \"" + prefix + "\" URI was not supplied with a namespace identifier. (\"" + id + "\")");
}
if (!Uri.is.valid.ns(id)) {
var err = "URI contains an invalid \"" + prefix + "\" identifier, must be an alpha-numeric cuid. (\"" + id + "\")";
throw new Error(err);
}
if (typeof suffix === 'string') {
suffix = (suffix || '').trim().replace(/^\:*/, '');
if (!suffix) {
throw new Error("The \"" + 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 (\"" + suffix + "\").";
throw new Error(err);
}
suffix = ":" + 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 \"" + prefix + ":\" URI was not supplied with a valid " + type + " key (given key \"" + key + "\").";
throw new Error(err);
}
suffix = ":" + suffix;
}
}
return prefix + ":" + id + (suffix || '');
}
function isCuid(input) {
return input.length === 25 && input[0] === 'c' && alphaNumeric.test(input);
}