urns
Version:
An RFC 8141 compliant URN library with some interesting type related functionality
114 lines (113 loc) • 5.02 kB
TypeScript
import { ComponentMaps } from "./parser";
import { BaseURN, FullURN, ParsedURN } from "./types";
/**
* The `URNSpace` class allows you to define a space of URNs defined
* by a common namespace identifier (NID). You can further restrict
* this space by providing your own subtype of string for the
* namespace specific string (NSS) as well. Furthermore, via the
* `options` you can provide your own functions for validating
* the NSS (see `is` functionality) and potentially providing
* further semantic parsing of the NSS (see `transform` functionality).
*
* With an instance of `URNSpace` in hand, it becomes very easy to
* create new URNs and validate/parse existing URNs that belong
* to the space.
*/
export declare class URNSpace<NID extends string, NSS extends string, R> {
protected nid: NID;
protected options?: Partial<SpaceOptions<NSS, R>> | undefined;
/**
* Create a new URNSpace with the specifid NID
* @param nid Namespace identifer (NID)
* @param options
*/
constructor(nid: NID, options?: Partial<SpaceOptions<NSS, R>> | undefined);
protected _parseURN<NSS extends string>(s: string): ParsedURN<NID, NSS>;
protected _createURN<NSS extends string>(nid: NID, nss: NSS): `urn:${NID}:${NSS}`;
protected _createFullURN<NSS extends string>(nid: NID, nss: NSS, components?: ComponentMaps): `urn:${NID}:${NSS}${string}`;
/**
* Create a new URN in this namespace. The type parameter `N` here
* can be a subtype of the `NSS` type parameter of the `URNSpace` itself.
* This allows you to deliberately create URNs that are part of a
* more narrow subspace.
*/
urn<N extends NSS>(nss: N | R): BaseURN<NID, N>;
/**
* This creates a URN that will no longer conform to the BaseURN type (which assumes no components).
* But it is still useful to create full URNs (with components) within a space.
**/
fullUrn<N extends NSS>(nss: N | R, components: ComponentMaps): FullURN<NID, N, string>;
/**
* This is the main benefit of a `URNSpace`, it allows you to perform a runtime
* check that narrows the scope of an ordinary string down to that of a member
* of this URNSpace. This is useful if, for example, you are deserializing
* content (e.g., from a JSON payload) and you want to ensure that a given
* string is in fact of the (URN) type you expect.
*
* NB - This confirms that the URN is a base URN (no components). If you are
* dealing with a full URN, use isFull
* @param s
* @returns
*/
is(s: string): s is BaseURN<NID, NSS>;
/**
* Check if this string qualifies as a full URN belonging to this URN space.
*
* @param s A string which may be a full URN in this space, or it may not
* @returns
*/
isFull(s: string): s is FullURN<NID, NSS, string>;
/**
* This function is like `is`, but it assumes the result will be true. This can save you some
* condition handling. You should use this when you have a high degree of confidence that the
* string does actually conform this URNSpace because it will throw an exception if it doesn't.
* @param s
* @returns
*/
assume(s: string): BaseURN<NID, NSS>;
/**
* This function parses the provided URN and also invokes the optional `decode` function (if provided).
* @param urn
* @returns
*/
parse(urn: FullURN<NID, NSS, string>): ParsedURN<NID, NSS> & {
decoded: R;
};
/**
* This helper function is for the use case where you simply want to extract the NSS value
* of a provided string.
* @param urn
* @returns Namespace specific string
*/
nss(urn: FullURN<NID, NSS, string>): NSS;
/**
* This is another helper function that provides the result of the optional `transform`
* function if provided. Otherwise, it simply returns `{}`.
*/
decode(urn: FullURN<NID, NSS, string>): R;
}
/**
* A type that indicates the options that can be passed when creating a `URNSpace`.
*/
export interface SpaceOptions<NSS extends string, R> {
pred?: (nss: string) => nss is NSS;
encode?: (val: R) => string;
decode?: (nss: string) => R;
skipVerification?: boolean;
}
/**
* A special conditional type that can be used to extract the type
* associated with URNs in that `URNSpace`
*
* For example, `URNFrom<typeof s>` will return the type for URNs
* that belong to the `URNSpace` `s`.
*/
export declare type URNFrom<S extends URNSpace<string, string, any>> = S extends URNSpace<infer NID, infer NSS, infer R> ? BaseURN<NID, NSS> : never;
/**
* A special conditional type that can be used to extract the type
* associated with URNs in that `URNSpace`
*
* For example, `URNFrom<typeof s>` will return the type for URNs
* that belong to the `URNSpace` `s`.
*/
export declare type FullURNFrom<S extends URNSpace<string, string, any>> = S extends URNSpace<infer NID, infer NSS, infer R> ? FullURN<NID, NSS, string> : never;