2021-05-20 20:34:50 -04:00
|
|
|
import {
|
|
|
|
|
createAst,
|
|
|
|
|
DirectiveRule,
|
|
|
|
|
FunctionRule,
|
|
|
|
|
ImportRule,
|
|
|
|
|
LinkRule,
|
|
|
|
|
NamespaceRule,
|
|
|
|
|
Rule,
|
|
|
|
|
VariableRule
|
|
|
|
|
} from './createAst.js'
|
2021-05-11 19:38:55 -04:00
|
|
|
import path from 'path';
|
|
|
|
|
import debug from 'debug';
|
2021-05-16 20:41:45 -04:00
|
|
|
import { createRequire } from 'module';
|
|
|
|
|
import { pathToFileURL } from 'url';
|
2021-05-11 19:38:55 -04:00
|
|
|
const log = debug('vogue:module');
|
2021-05-02 17:42:04 -04:00
|
|
|
|
2021-05-20 20:34:50 -04:00
|
|
|
export type Link = {
|
2021-05-20 00:19:25 -04:00
|
|
|
name: string,
|
|
|
|
|
array: boolean,
|
|
|
|
|
required: boolean
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-02 17:42:04 -04:00
|
|
|
export default class Module {
|
2021-05-20 00:19:25 -04:00
|
|
|
links: Link[] = [];
|
2021-05-02 17:42:04 -04:00
|
|
|
globals = [];
|
2021-05-20 00:19:25 -04:00
|
|
|
functions: {
|
|
|
|
|
[name: string]: {
|
|
|
|
|
code: string,
|
2021-05-20 20:34:50 -04:00
|
|
|
async: boolean,
|
2021-05-20 00:19:25 -04:00
|
|
|
parameters: string[]
|
|
|
|
|
}
|
|
|
|
|
} = {};
|
2021-05-20 20:34:50 -04:00
|
|
|
identifiers: {
|
|
|
|
|
[name: string]: Rule["type"]
|
|
|
|
|
} = {};
|
2021-05-02 17:42:04 -04:00
|
|
|
name = {
|
|
|
|
|
space: '',
|
|
|
|
|
last: '',
|
|
|
|
|
full: ''
|
2021-05-06 23:05:36 -04:00
|
|
|
};
|
2021-05-20 20:34:50 -04:00
|
|
|
imports: {
|
|
|
|
|
[key: string]: any
|
|
|
|
|
} = {};
|
|
|
|
|
variables: any = {
|
2021-05-08 23:06:31 -04:00
|
|
|
cold: [],
|
|
|
|
|
warm: []
|
2021-05-20 00:19:25 -04:00
|
|
|
};
|
2021-05-20 20:34:50 -04:00
|
|
|
// directives
|
|
|
|
|
'singleton': boolean = false;
|
|
|
|
|
'keepalive': boolean = false;
|
|
|
|
|
'static': string = '';
|
|
|
|
|
// other stuff
|
2021-05-20 00:19:25 -04:00
|
|
|
rootDir: string = '';
|
2021-05-11 19:38:55 -04:00
|
|
|
|
2021-05-20 20:34:50 -04:00
|
|
|
async directive({ directive, value }: DirectiveRule): Promise<void> {
|
|
|
|
|
if (typeof this[directive] === 'boolean')
|
|
|
|
|
(this[directive] as boolean) = value as boolean;
|
|
|
|
|
else if (typeof this[directive] === 'string')
|
|
|
|
|
(this[directive] as string) = value as string;
|
|
|
|
|
// = value as string;
|
2021-05-11 19:38:55 -04:00
|
|
|
}
|
|
|
|
|
|
2021-05-20 20:34:50 -04:00
|
|
|
async link({ required, array, name }: LinkRule): Promise<void> {
|
2021-05-20 00:19:25 -04:00
|
|
|
this.links.push({
|
|
|
|
|
name,
|
|
|
|
|
required,
|
|
|
|
|
array
|
|
|
|
|
});
|
2021-05-11 19:38:55 -04:00
|
|
|
}
|
|
|
|
|
|
2021-05-20 20:34:50 -04:00
|
|
|
async namespace({ namespace }: NamespaceRule): Promise<void> {
|
2021-05-11 19:38:55 -04:00
|
|
|
this.name.space = namespace;
|
|
|
|
|
this.name.full = this.name.space + '.' + this.name.last;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-20 20:34:50 -04:00
|
|
|
async function({ name, block, parameters, async }: FunctionRule): Promise<void> {
|
2021-05-14 14:43:04 -04:00
|
|
|
this.functions[name] = {
|
|
|
|
|
code: block,
|
2021-05-20 20:34:50 -04:00
|
|
|
parameters,
|
|
|
|
|
async
|
2021-05-14 14:43:04 -04:00
|
|
|
};
|
2021-05-11 19:38:55 -04:00
|
|
|
}
|
|
|
|
|
|
2021-05-20 20:34:50 -04:00
|
|
|
async import({ importName, name }: ImportRule): Promise<void> {
|
2021-05-16 20:41:45 -04:00
|
|
|
const nodePath = path.resolve(this.rootDir, 'node_module');
|
|
|
|
|
log('#'.repeat(80));
|
|
|
|
|
log(nodePath);
|
|
|
|
|
const __require__ = createRequire(nodePath);
|
|
|
|
|
const imported = __require__(importName);
|
2021-05-20 20:34:50 -04:00
|
|
|
if ('default' in imported) this.imports[name] = imported.default;
|
2021-05-11 19:38:55 -04:00
|
|
|
else this.imports[name] = imported;
|
|
|
|
|
}
|
2021-05-10 23:13:17 -04:00
|
|
|
|
2021-05-20 20:34:50 -04:00
|
|
|
async variable({ persist, name }: VariableRule): Promise<void> {
|
2021-05-11 19:38:55 -04:00
|
|
|
this.variables[persist ? 'cold' : 'warm'].push(name);
|
2021-05-10 23:13:17 -04:00
|
|
|
}
|
|
|
|
|
|
2021-05-20 00:19:25 -04:00
|
|
|
static async create(location: string, rootDir: string) {
|
2021-05-10 23:13:17 -04:00
|
|
|
const module = new Module();
|
|
|
|
|
const ast = createAst(location);
|
2021-05-11 19:38:55 -04:00
|
|
|
const name = path.parse(location).name;
|
2021-05-10 23:13:17 -04:00
|
|
|
|
|
|
|
|
module.name.last = name;
|
|
|
|
|
module.name.full = name;
|
2021-05-16 20:41:45 -04:00
|
|
|
module.rootDir = rootDir;
|
2021-05-10 23:13:17 -04:00
|
|
|
|
2021-05-11 19:38:55 -04:00
|
|
|
for (const item of ast) {
|
|
|
|
|
if ('name' in item) {
|
2021-05-20 20:34:50 -04:00
|
|
|
if (item.name in module.identifiers)
|
2021-05-10 23:13:17 -04:00
|
|
|
throw new Error('Identifier ' + item.name + ' already declared!');
|
2021-05-20 20:34:50 -04:00
|
|
|
else {
|
|
|
|
|
module.identifiers[item.name] = item.type;
|
|
|
|
|
}
|
2021-05-11 19:38:55 -04:00
|
|
|
}
|
2021-05-10 23:13:17 -04:00
|
|
|
|
2021-05-20 20:34:50 -04:00
|
|
|
if (item.type in module) {
|
|
|
|
|
const func = module[item.type] as ((arg0: Rule) => Promise<void>)
|
|
|
|
|
func.call(module, item);
|
2021-05-10 23:13:17 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-11 19:38:55 -04:00
|
|
|
log('='.repeat(80));
|
|
|
|
|
log(location);
|
|
|
|
|
log(module);
|
|
|
|
|
|
|
|
|
|
return module;
|
2021-05-10 23:13:17 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|