Initial import
This commit is contained in:
125
src/service/Canonical.ts
Normal file
125
src/service/Canonical.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Base type for a canonical definition.
|
||||
*/
|
||||
import {Canon} from "./Canon";
|
||||
import {universalPath, UniversalPath} from "@extollo/util";
|
||||
import {Logging} from "./Logging";
|
||||
import {Inject} from "@extollo/di";
|
||||
import * as nodePath from 'path'
|
||||
import {Unit} from "../lifecycle/Unit";
|
||||
|
||||
export interface CanonicalDefinition {
|
||||
canonicalName: string,
|
||||
originalName: string,
|
||||
imported: any,
|
||||
}
|
||||
|
||||
/**
|
||||
* Base type for a canonical name reference.
|
||||
*/
|
||||
export interface CanonicalReference {
|
||||
resource?: string,
|
||||
item: string,
|
||||
particular?: string,
|
||||
}
|
||||
|
||||
export abstract class Canonical<T> extends Unit {
|
||||
@Inject()
|
||||
protected readonly logging!: Logging
|
||||
|
||||
@Inject()
|
||||
protected readonly canon!: Canon
|
||||
|
||||
/**
|
||||
* The base path directory where the canonical definitions reside.
|
||||
* @type string
|
||||
*/
|
||||
protected appPath: string[] = []
|
||||
|
||||
/**
|
||||
* The file suffix of files in the base path that should be loaded.
|
||||
* @type string
|
||||
*/
|
||||
protected suffix: string = '.js'
|
||||
|
||||
/**
|
||||
* The singular, programmatic name of one of these canonical items.
|
||||
* @example middleware
|
||||
* @type string
|
||||
*/
|
||||
protected canonicalItem: string = ''
|
||||
|
||||
/**
|
||||
* Object mapping canonical names to loaded file references.
|
||||
* @type object
|
||||
*/
|
||||
protected loadedItems: { [key: string]: T } = {}
|
||||
|
||||
/**
|
||||
* Resolve a canonical reference from its string form to a CanonicalReference.
|
||||
* @param {string} reference
|
||||
* @return CanonicalReference
|
||||
*/
|
||||
public static resolve(reference: string): CanonicalReference {
|
||||
const rscParts = reference.split('::')
|
||||
const resource = rscParts.length > 1 ? rscParts[0] + 's' : undefined
|
||||
const rsc_less = rscParts.length > 1 ? rscParts[1] : rscParts[0]
|
||||
const prtParts = rsc_less.split('.')
|
||||
const item = prtParts[0]
|
||||
const particular = prtParts.length > 1 ? prtParts.slice(1).join('.') : undefined
|
||||
|
||||
return {
|
||||
resource, item, particular
|
||||
}
|
||||
}
|
||||
|
||||
public all(): string[] {
|
||||
return Object.keys(this.loadedItems)
|
||||
}
|
||||
|
||||
public get path(): UniversalPath {
|
||||
return this.app().appPath(...this.appPath)
|
||||
}
|
||||
|
||||
public get canonicalItems() {
|
||||
return `${this.canonicalItem}s`
|
||||
}
|
||||
|
||||
public get(key: string): T | undefined {
|
||||
return this.loadedItems[key]
|
||||
}
|
||||
|
||||
public async up() {
|
||||
for await ( const entry of this.path.walk() ) {
|
||||
if ( !entry.endsWith(this.suffix) ) {
|
||||
this.logging.debug(`Skipping file with invalid suffix: ${entry}`)
|
||||
continue
|
||||
}
|
||||
|
||||
const definition = await this.buildCanonicalDefinition(entry)
|
||||
this.logging.verbose(`Registering canonical ${this.canonicalItem} "${definition.canonicalName}" from ${entry}`)
|
||||
this.loadedItems[definition.canonicalName] = await this.initCanonicalItem(definition)
|
||||
}
|
||||
|
||||
this.canon.registerCanonical(this)
|
||||
}
|
||||
|
||||
public async initCanonicalItem(definition: CanonicalDefinition): Promise<T> {
|
||||
return definition.imported.default
|
||||
}
|
||||
|
||||
protected async buildCanonicalDefinition(filePath: string): Promise<CanonicalDefinition> {
|
||||
const originalName = filePath.replace(this.path.toLocal, '').substr(1)
|
||||
const pathRegex = new RegExp(nodePath.sep, 'g')
|
||||
const canonicalName = originalName.replace(pathRegex, ':')
|
||||
.split('').reverse().join('')
|
||||
.substr(this.suffix.length)
|
||||
.split('').reverse().join('')
|
||||
|
||||
const fullUniversalPath = universalPath(filePath)
|
||||
this.logging.verbose(`Importing from: ${fullUniversalPath}`)
|
||||
|
||||
const imported = await import(fullUniversalPath.toLocal)
|
||||
return { canonicalName, originalName, imported }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user