UNPKG

bit-bin

Version:

<a href="https://opensource.org/licenses/Apache-2.0"><img alt="apache" src="https://img.shields.io/badge/License-Apache%202.0-blue.svg"></a> <a href="https://github.com/teambit/bit/blob/master/CONTRIBUTING.md"><img alt="prs" src="https://img.shields.io/b

430 lines (334 loc) 10.4 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; function _defineProperty2() { const data = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); _defineProperty2 = function () { return data; }; return data; } function path() { const data = _interopRequireWildcard(require("path")); path = function () { return data; }; return data; } function semver() { const data = _interopRequireWildcard(require("semver")); semver = function () { return data; }; return data; } function _decamelize() { const data = _interopRequireDefault(require("decamelize")); _decamelize = function () { return data; }; return data; } function _ramda() { const data = _interopRequireDefault(require("ramda")); _ramda = function () { return data; }; return data; } function _exceptions() { const data = require("./exceptions"); _exceptions = function () { return data; }; return data; } function _constants() { const data = require("../constants"); _constants = function () { return data; }; return data; } function _isValidIdChunk() { const data = _interopRequireDefault(require("../utils/is-valid-id-chunk")); _isValidIdChunk = function () { return data; }; return data; } function _isValidScopeName() { const data = _interopRequireDefault(require("../utils/is-valid-scope-name")); _isValidScopeName = function () { return data; }; return data; } function _generalError() { const data = _interopRequireDefault(require("../error/general-error")); _generalError = function () { return data; }; return data; } function _versionParser() { const data = _interopRequireDefault(require("../version/version-parser")); _versionParser = function () { return data; }; return data; } class BitId { constructor({ scope, box, name, version }) { (0, _defineProperty2().default)(this, "scope", void 0); (0, _defineProperty2().default)(this, "box", void 0); (0, _defineProperty2().default)(this, "name", void 0); (0, _defineProperty2().default)(this, "version", void 0); // don't validate the id parts using isValidIdChunk here. we instance this class tons of times // and running regex so many times impact the performance if (!name) throw new (_exceptions().InvalidName)(name); this.scope = scope || null; this.box = undefined; this.name = box ? `${box}/${name}` : name; this.version = version || undefined; Object.freeze(this); } clone() { return new BitId(this); } changeScope(newScope) { return new BitId({ scope: newScope, name: this.name, version: this.version }); } changeVersion(newVersion) { return new BitId({ scope: this.scope, name: this.name, version: newVersion }); } isLocal(scopeName) { return !this.scope || Boolean(scopeName && scopeName === this.scope); } getVersion() { return (0, _versionParser().default)(this.version); } hasVersion() { return Boolean(this.version && this.version !== _constants().LATEST_BIT_VERSION); } hasScope() { return Boolean(this.scope); } hasSameName(id) { return this.name === id.name; } hasSameScope(id) { if (this.hasScope() && id.hasScope()) return this.scope === id.scope; if (!this.hasScope() && !id.hasScope()) return true; return false; // one has scope but not the other } hasSameVersion(id) { if (this.hasVersion() && id.hasVersion()) return this.version === id.version; if (!this.hasVersion() && !id.hasVersion()) return true; return false; // one has version but not the other } toString(ignoreScope = false, ignoreVersion = false) { const { name, version } = this; const scope = this.scope; const componentStr = ignoreScope || !scope ? name : [scope, name].join('/'); // when there is no scope and the version is latest, omit the version. if (ignoreVersion || !this.hasVersion()) return componentStr; // $FlowFixMe version here is a string because this.hasVersion() is true return componentStr.concat(`${_constants().VERSION_DELIMITER}${version}`); } toStringWithoutScope() { return this.toString(true); } toStringWithoutVersion() { return this.toString(false, true); } toStringWithoutScopeAndVersion() { return this.toString(true, true); } isEqual(bitId) { return this.hasSameName(bitId) && this.hasSameScope(bitId) && this.hasSameVersion(bitId); } isEqualWithoutVersion(bitId) { return this.hasSameName(bitId) && this.hasSameScope(bitId); } isEqualWithoutScopeAndVersion(bitId) { return this.hasSameName(bitId); } serialize() { const obj = { scope: this.scope, name: this.name, version: this.version }; if (!this.hasVersion()) delete obj.version; if (!this.hasScope()) delete obj.scope; return obj; } toObject() { const key = this.scope ? [this.scope, this.name].join('/') : this.name; const value = this.version; return { [key]: value }; } toFullPath() { if (!this.scope || !this.version) { throw new Error('BitId.toFullPath is unable to generate a path without a scope or a version'); } return path().join(this.name, this.scope, this.version); } /** * Get a string id and return a string without the version part * @param {string} id * @return {string} id - id without version */ static getStringWithoutVersion(id) { const splitted = id.split(_constants().VERSION_DELIMITER); let res = splitted[0]; // the delimiter is @. now with the new owner prefix // many times the id starts with the @ sign as part of the @owner prefix // do not treat this @ at the beginning as the version delimiter if (id.startsWith(_constants().VERSION_DELIMITER)) { res = `${_constants().VERSION_DELIMITER}${splitted[1]}`; } return res; } static getVersionOnlyFromString(id) { return id.split(_constants().VERSION_DELIMITER)[1]; } static parse(id, hasScope = true, version = _constants().LATEST_BIT_VERSION) { if (!_ramda().default.is(String, id)) { throw new TypeError(`BitId.parse expects to get "id" as a string, instead, got ${typeof id}`); } if (id.includes(_constants().VERSION_DELIMITER)) { const [newId, newVersion] = id.split(_constants().VERSION_DELIMITER); id = newId; version = newVersion; } const getScopeAndName = () => { if (hasScope) { const delimiterIndex = id.indexOf('/'); if (delimiterIndex < 0) throw new (_exceptions().InvalidBitId)(); const scope = id.substring(0, delimiterIndex); const name = id.substring(delimiterIndex + 1); return { scope, name }; } return { scope: undefined, name: id }; }; const { scope, name } = getScopeAndName(); if (!(0, _isValidIdChunk().default)(name)) throw new (_exceptions().InvalidName)(name); if (scope && !(0, _isValidScopeName().default)(scope)) throw new (_exceptions().InvalidScopeName)(scope); return new BitId({ scope, name, version }); } static parseObsolete(id, version = _constants().LATEST_BIT_VERSION) { if (id.includes(_constants().VERSION_DELIMITER)) { const [newId, newVersion] = id.split(_constants().VERSION_DELIMITER); id = newId; version = newVersion; } const idSplit = id.split('/'); if (idSplit.length === 3) { const [scope, box, name] = idSplit; if (!(0, _isValidIdChunk().default)(name, false) || !(0, _isValidIdChunk().default)(box, false) || !(0, _isValidScopeName().default)(scope)) { throw new (_exceptions().InvalidIdChunk)(`${scope}/${box}/${name}`); } // $FlowFixMe (in this case the realScopeName is not undefined) return new BitId({ scope, box, name, version }); } if (idSplit.length === 2) { const [box, name] = idSplit; if (!(0, _isValidIdChunk().default)(name, false) || !(0, _isValidIdChunk().default)(box, false)) { throw new (_exceptions().InvalidIdChunk)(`${box}/${name}`); } return new BitId({ box, name, version }); } if (idSplit.length === 1) { const [name] = idSplit; if (!(0, _isValidIdChunk().default)(name)) { throw new (_exceptions().InvalidIdChunk)(name); } return new BitId({ name, version }); } throw new (_exceptions().InvalidBitId)(); } /** * before version 13.0.3 bitmap and component-dependencies ids were written as strings (e.g. scope/box/name@version) * since that version the ids are written as objects ({ scope: scopeName, name: compName, version: 0.0.1 }) */ static parseBackwardCompatible(id) { return typeof id === 'string' ? BitId.parseObsolete(id) : new BitId(id); } static getValidScopeName(scope) { const suggestedName = scope.toLowerCase(); let cleanName = suggestedName.split('').map(char => { if (/^[$\-_!.a-z0-9]+$/.test(char)) return char; return ''; }).join(''); // allow only one dot const nameSplitByDot = cleanName.split('.'); if (nameSplitByDot.length > 1) { cleanName = `${_ramda().default.head(nameSplitByDot)}.${_ramda().default.tail(nameSplitByDot).join('')}`; } if (!cleanName) { throw new (_generalError().default)('scope name created by directory name have to contains at least one character or number'); } return cleanName; } static getValidIdChunk(chunk) { if (!(0, _isValidIdChunk().default)(chunk)) { chunk = chunk.replace(/\./g, ''); chunk = (0, _decamelize().default)(chunk, '-'); } return chunk; } static getValidBitId(box, name) { return new BitId({ name: BitId.getValidIdChunk(name), box: box ? BitId.getValidIdChunk(box) : undefined }); } static isValidVersion(version) { return Boolean(semver().valid(version)); } } exports.default = BitId;