UNPKG

urns

Version:

An RFC 8141 compliant URN library with some interesting type related functionality

183 lines (182 loc) 8.71 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var map_fields_1 = require("./map-fields"); var space_1 = require("./space"); var CachedURNSpace = /** @class */ (function (_super) { __extends(CachedURNSpace, _super); function CachedURNSpace() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.cache = new Map(); return _this; } CachedURNSpace.prototype._createURN = function (nid, nss) { var key = nid + ":" + nss; var res = this.cache.get(key) || _super.prototype._createURN.call(this, nid, nss); this.cache.set(key, (res + "CACHED")); return res; }; return CachedURNSpace; }(space_1.URNSpace)); describe("Should test derived class", function () { it("should create a simple space", function () { /** Create a simple URN space that always uses the namespace identifier "example" */ var space = new CachedURNSpace("example"); /** * Create a URN inside the "example" space with a "namespace specific string" (NSS) of "a" * * NB - We are creating this URN with a narrowed set of possible NSS values ("a" | "b") */ var a = space.urn("a"); var aCached = space.urn("a"); expect(aCached).toEqual(a + "CACHED"); }); }); describe("Test usage of urnSpace", function () { it("should create a simple space", function () { /** Create a simple URN space that always uses the namespace identifier "example" */ var space = new space_1.URNSpace("example"); /** * Create a URN inside the "example" space with a "namespace specific string" (NSS) of "a" * * NB - We are creating this URN with a narrowed set of possible NSS values ("a" | "b") */ var a = space.urn("a"); /** Now create a URN where the only possible value of the NSS is "b" */ var b = space.urn("b"); /** * This assignement should work since the domain of `b` is a proper subset * of the domain of `a` (the reverse is not true) */ a = b; /** Create a URN "by hand" and the check that it passes the `is` test */ var ex1 = "urn:example:c"; expect(space.is(ex1)).toEqual(true); /** Create a URN by hand that is no part of this URN space and ensure it fails the `is` test */ expect(space.is("urn:other:a")).toEqual(false); }); it("should create a space with encoder if provided", function () { var space = new space_1.URNSpace("example", { // encode to v^2 encode: function (v) { return (v * v).toString(); }, }); expect(space.urn(2)).toEqual("urn:example:4"); }); it("should create a space with an NSS constraint", function () { /** * In this case, return type of the `pred` function provides an additional * constraint on the potential values for the NSS in this space. This is * picked up by TypeScripts type analysis (and, thus, allows us to detect * deviations from that type in string literals). **/ var space = new space_1.URNSpace("example", { pred: function (s) { return s === "a" || s === "b"; }, }); expect(space.is("urn:example:b")).toEqual(true); expect(space.is("urn:example:c")).toEqual(false); expect(function () { return space.assume("urn:example:d"); }).toThrow("Assumption that 'urn:example:d' belongs to the specified URNSpace('example') is faulty"); }); it("should not create invalid urns with an NSS constraint", function () { /** * In this case, return type of the `pred` function provides an additional * constraint on the potential values for the NSS in this space. This is * picked up by TypeScripts type analysis (and, thus, allows us to detect * deviations from that type in string literals). **/ var space = new space_1.URNSpace("example", { pred: function (s) { return s === "a" || s === "b"; }, }); expect(space.is("urn:example:b")).toEqual(true); expect(space.is("urn:example:c")).toEqual(false); expect(function () { return space.urn("d"); }).toThrow("Assumption that 'urn:example:d' belongs to the specified URNSpace('example') is faulty"); expect(function () { return space.assume("urn:example:d"); }).toThrow("Assumption that 'urn:example:d' belongs to the specified URNSpace('example') is faulty"); }); it("should create a space with a decoder", function () { /** Now we create a URNSpace with a transform function. */ var space = new space_1.URNSpace("example", { decode: map_fields_1.mapFields(["id", "sub"]), }); /** Now, when we parse a URN like this one, */ var un = space.parse("urn:example:a:b"); /** We get our NSS parsed for us (in this case into specified fields). */ expect(un.decoded.id).toEqual("a"); expect(un.decoded.sub).toEqual("b"); /** We can even invoke this directly and skip the parse step... */ expect(space.nss("urn:example:a:b")).toEqual("a:b"); expect(space.decode("urn:example:a:b")).toEqual({ id: "a", sub: "b" }); /** One additional check to make sure it parsed everything else as expected. */ expect(un).toEqual({ nid: "example", nss: "a:b", nss_encoded: "a:b", fragment: null, qcomponent: null, rcomponent: null, decoded: { id: "a", sub: "b", }, }); /** Finally, the transform function also provides additional levels of validation. */ expect(space.is("urn:example:a:b:c")).toEqual(false); expect(space.is("urn:example:a:b")).toEqual(true); }); it("should creation and querying of full URNs (URNs with components)", function () { var space = new space_1.URNSpace("ref"); var ex1 = space.fullUrn("foo", { q: { x: "5" } }); expect(ex1).toEqual("urn:ref:foo?=x=5"); expect(space.is(ex1)).toEqual(false); expect(space.isFull(ex1)).toEqual(true); expect(space.nss(ex1)).toEqual("foo"); }); it("should create a space with an alternative transform", function () { var space = new space_1.URNSpace("customer", { decode: function (nss) { var v = parseInt(nss); if (Number.isNaN(v)) throw new Error("NSS (" + nss + ") is not a number!"); return v; }, }); expect(space.decode("urn:customer:25")).toEqual(25); expect(function () { return space.decode("urn:customer:twenty-five"); }).toThrow("Assumption that 'urn:customer:twenty-five' belongs to the specified URNSpace('customer') fails in decoding: NSS (twenty-five) is not a number!"); }); it("should create a space without a transformer", function () { /** A very ordinary URNSpace without transform or predicate */ var space = new space_1.URNSpace("example"); var un = space.parse("urn:example:a:b"); expect(un).toEqual({ nid: "example", nss: "a:b", nss_encoded: "a:b", fragment: null, qcomponent: null, rcomponent: null, decoded: {}, }); }); it("should throw if parts don't match", function () { /** Create a URNSpace with a transform function */ var space = new space_1.URNSpace("example", { decode: map_fields_1.mapFields(["id", "sub"]), }); /** Now give it a URN that doesn't match the expected structure of the NSS. */ expect(function () { return space.parse("urn:example:a"); }).toThrow(); }); });