music-codes
Version:
Small library for music codes (ISRC, ISWC, UPC)
112 lines • 4.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GTIN = exports.GtinLengthToFormat = exports.GtinFormatToLength = exports.GtinFormats = void 0;
exports.getGtinFromPrefix = getGtinFromPrefix;
const errors_js_1 = require("./errors.js");
const utils_js_1 = require("./utils.js");
exports.GtinFormats = ['GTIN-8', 'GTIN-12', 'GTIN-13', 'GTIN-14', 'GSIN', 'SSCC'];
exports.GtinFormatToLength = Object.freeze({
'GTIN-8': 8,
'GTIN-12': 12,
'GTIN-13': 13,
'GTIN-14': 14,
GSIN: 17,
SSCC: 18,
});
exports.GtinLengthToFormat = Object.fromEntries(Object.entries(exports.GtinFormatToLength).map(([f, l]) => [l, f]));
class GTIN {
constructor(gtin, prefix = undefined, verify = true) {
if (!/^\d+$/.test(gtin)) {
throw new errors_js_1.ParseError(`Invalid GTIN: ${gtin}`);
}
if (!exports.GtinLengthToFormat[gtin.length]) {
throw new errors_js_1.ParseError(`Unsupported GTIN length: ${gtin.length}`);
}
if (prefix && !gtin.startsWith(prefix)) {
throw new errors_js_1.ParseError(`Invalid prefix '${prefix}' for '${gtin}'`);
}
this.length = gtin.length;
this.code = BigInt(gtin.slice(0, -1));
this.check = Number.parseInt(gtin.slice(-1), 10);
this.prefix = prefix;
if (verify && this.check !== (0, utils_js_1.getLuhnCheckDigit)(this.code)) {
throw new errors_js_1.ParseError(`Invalid check digit: ${gtin}`);
}
}
get gtinFormat() {
return exports.GtinLengthToFormat[this.length] ?? (0, utils_js_1.raise)(`Unsupported GTIN length: ${this.length}`);
}
get realGtinFormat() {
let trueLength = `${this.code}${this.check}`.length;
while (trueLength < this.length) {
const maybeFormat = exports.GtinLengthToFormat[trueLength];
if (maybeFormat)
return maybeFormat;
trueLength++;
}
return exports.GtinLengthToFormat[this.length] ?? (0, utils_js_1.raise)(`Unsupported GTIN length: ${this.length}`);
}
first() {
const code = (this.prefix ?? '1').padEnd(this.length - 1, '0');
const checkDigit = (0, utils_js_1.getLuhnCheckDigit)(code);
return new GTIN(`${code}${checkDigit}`, this.prefix, false);
}
last() {
const code = (this.prefix ?? '9').padEnd(this.length - 1, '9');
const checkDigit = (0, utils_js_1.getLuhnCheckDigit)(code);
return new GTIN(`${code}${checkDigit}`, this.prefix, false);
}
previous() {
const checkDigit = (0, utils_js_1.getLuhnCheckDigit)(this.code - 1n);
const prevCode = `${this.code - 1n}${checkDigit}`.padStart(this.length, '0');
if (this.code === 1n || this.code === BigInt(10n ** BigInt(this.length - 2))) {
throw new errors_js_1.BoundaryError(`GTIN boundary reached: ${prevCode}`);
}
if (this.prefix && !prevCode.startsWith(this.prefix)) {
throw new errors_js_1.BoundaryError(`GTIN prefix overflow: ${this.prefix}`);
}
return new GTIN(prevCode, this.prefix, false);
}
next() {
const checkDigit = (0, utils_js_1.getLuhnCheckDigit)(this.code + 1n);
const nextCode = `${this.code + 1n}${checkDigit}`.padStart(this.length, '0');
if (nextCode.length > this.length) {
throw new errors_js_1.BoundaryError(`GTIN boundary reached: ${nextCode}`);
}
if (this.prefix && !nextCode.startsWith(this.prefix)) {
throw new errors_js_1.BoundaryError(`GTIN prefix overflow: ${this.prefix}`);
}
return new GTIN(nextCode, this.prefix, false);
}
*iterate(up = true) {
let gtin = this;
while (true) {
yield gtin;
try {
gtin = up ? gtin.next() : gtin.previous();
}
catch {
break;
}
}
}
toString() {
return `${this.code}${this.check}`.padStart(this.length, '0');
}
}
exports.GTIN = GTIN;
function getGtinFromPrefix(prefix, length) {
if (!exports.GtinLengthToFormat[length]) {
throw new errors_js_1.ParseError(`Unsupported GTIN length: ${length}`);
}
if (prefix.length < 1) {
throw new errors_js_1.ParseError(`Prefix is too short: ${prefix}`);
}
if (prefix.length > length - 1) {
throw new errors_js_1.ParseError(`Prefix is too long: ${prefix}`);
}
const code = prefix.padEnd(length - 1, '0');
const checkDigit = (0, utils_js_1.getLuhnCheckDigit)(code);
return new GTIN(`${code}${checkDigit}`, prefix, false);
}
//# sourceMappingURL=gtin.js.map