@ara-web/sds
Version:
Write code faster without worry about future debts or scalability in the future
195 lines (167 loc) • 5.66 kB
text/typescript
import type { PurlQualifiers } from "packageurl-js";
import { ArrayTraits, type WithGetTextMethod } from "@ara-web/p-hintjens";
import { ModuleLink, type ModuleURL } from "./module-link.js";
import path from "path";
export const NpmProtocol = "npm";
export type AraURL =
`ara:` |
`sever:` |
`reflect:` |
`http://${string}` |
`https://${string}` |
`ws://${string}` | ModuleURL |
`this`;
export class AraLink<T> {
private _protocol: string;
private _slugs: string[];
private _resource: string|T;
private _properties: object;
constructor (protocol: string, resource: string|T, slugs: string[], properties?: object) {
this._protocol = protocol;
this._resource = resource;
if (slugs !== undefined) {
this._slugs = slugs;
} else {
this._slugs = [];
}
if (properties !== undefined) {
this._properties = properties;
} else {
this._properties = {}
}
return this;
}
public copyWithProperties = (properties: object): AraLink<T> => {
const araLink = new AraLink(this._protocol, this._resource, this._slugs, properties);
return araLink;
}
public isEmpty = (): boolean => {
if (this._resource === undefined || this._resource === null) {
return true;
}
let resourceStr = this._resource.toString();
if (resourceStr.length === 0) {
return true;
}
return false;
}
public get protocol(): string {
return this._protocol;
}
public get slugs(): string[] {
return this._slugs;
}
public get resource(): (typeof this._resource) {
return this._resource;
}
public get properties(): object {
return this._properties;
}
public isPropertyExist(property: string): boolean {
if (this._properties === undefined) {
return false;
}
if (property in this._properties) {
return true;
}
return false;
}
public property = (property: string): object|undefined => {
if (!this.isPropertyExist(property)) {
return undefined;
}
return (this._properties as any)[property]
}
public toString = () : string => {
let resourceUrl: string = "";
if (typeof this.resource === "string") {
resourceUrl = this.resource.toString();
} else {
if ((this.resource as WithGetTextMethod)["getText"] !== undefined &&
(this.resource as WithGetTextMethod)["getText"] !== null) {
resourceUrl = (this.resource as WithGetTextMethod).getText();
} else {
resourceUrl = (this.resource as any).toString();
}
}
let url = `${this._protocol}:${this.slugs.join('/')}/${resourceUrl}`
let properties: string = "";
for (let key in this._properties) {
if (properties.length > 0 && properties[properties.length - 1] !== "&") {
properties += "&"
}
properties += `${key}=${(this._properties as any)[key]}`
}
if (properties.length > 0) {
properties = "?" + properties;
}
return url + properties;
}
public toModuleLink = (): ModuleLink => {
const schema = this._protocol;
const namespace = this._slugs.length === 0 ? "" : this._slugs[0]
const name: string = this._resource as string;
let subPath: string = "";
if (this._slugs !== undefined && this._slugs.length > 1) {
subPath = this.slugs.filter((_, index) => (index > 0)).join(path.sep)
}
const qualifiers: PurlQualifiers = {
...this._properties
}
const pkgUrl = ModuleLink.newPackageLink(
namespace,
name,
subPath,
qualifiers,
schema
);
return pkgUrl;
}
public static fromModuleLink = (moduleLink: ModuleLink): AraLink<string> => {
if (moduleLink.isFileURL) {
const filePath = moduleLink.toAbsFilePath;
const resource = path.basename(filePath);
const slugs = path.dirname(filePath).split(path.sep);
return new AraLink<string>("file", resource, slugs);
}
const pkgURL = moduleLink.toPackageURL;
const protocol = pkgURL.type;
const slugs: string[] = [];
if (pkgURL.namespace) {
slugs.push(pkgURL.namespace);
}
if (pkgURL.subpath) {
slugs.push(...pkgURL.subpath.split(path.sep))
}
const resource = pkgURL.name;
const araLink = new AraLink<string>(protocol, resource, slugs);
if (pkgURL.qualifiers !== undefined) {
araLink._properties = pkgURL.qualifiers;
}
return araLink;
}
public lastSlug = (): string|undefined => {
if (this._slugs.length === 0) {
return undefined;
}
return this._slugs[this._slugs.length - 1];
}
/**
* Returns true if the link is following the protocol and in the slugs path
* @param protocol
* @param slugs
* @returns
*/
public isCorrectPath = (protocol: string, slugs: string[]): boolean => {
if (this.protocol !== protocol) {
return false;
}
if (this.slugs.length === 0) {
return false;
}
if (!ArrayTraits.isEqualArray(this.slugs, slugs)) {
return false;
}
return true;
}
}