beyond
Version:
The Full Stack Universal Typescript Framework
204 lines (176 loc) • 4.85 kB
JavaScript
const TSConfig = require('./tsconfig');
require('colors');
const { join, sep } = require('path');
module.exports = class Module extends require('../../file-manager') {
/**
* @deprecated
* @type {string}
* @private
*/
_fileName = 'module.json';
_reserved = ['reserved', 'bundles'];
_platforms = [];
skeleton = [
'name',
'description',
'compilation',
'transpilation',
'static',
{ name: 'platforms', type: ['string'] },
];
_templates = {
page: './modules/templates/page',
server_page: './modules/templates/page',
mobile_login: './modules/templates/code',
};
/**
* Contains the value of the file in case that it exists.
* @private _originalContent
*/
_originalContent;
_loaded;
get id() {
return this._id;
}
get properties() {
const props = {};
this.skeleton.forEach(property => {
if (this[property]) props[property] = this[property];
});
return props;
}
get path() {
return this.file.file;
}
#bundlesManager;
get bundles() {
return this.#bundlesManager;
}
constructor(path) {
super(path, 'module.json');
//the name cannot have spaces or special characters.
}
/**
* Loads the content of the file
*
* This method is used by the constructor and checks if the route
* has a file for the instantiated object and gets its content.
* @private
*/
async _load() {
const content = this.validate() ? await this.file.readJSON(this.file.file) : undefined;
if (!this.#bundlesManager) {
/**
* The bundle Manager represents the container folder, so the basename must be passed as empty.
*/
this.#bundlesManager = new (require('./bundles/manager'))(this.file.dirname, '', content);
}
if (!content) return;
this._checkProperties(content);
this._originalContent = content;
try {
await this.#bundlesManager.load(content);
this._loaded = true;
} catch (e) {
console.error('error', e);
}
}
load = this._load;
/**
* that method uses the parent process method and additionally
* checks if the specs has a bundle configuration.
*
* @param specs
* @private
*/
_process(specs) {
this._checkProperties(specs);
for (let bundle of this._BUNDLES) {
specs.hasOwnProperty(bundle) && this.#bundlesManager.get(bundle, specs[bundle]);
}
}
/**
* TODO: doc it.
* @param specs
* @returns {{}}
*/
cleanSpecs(specs) {
const props = {};
for (const property in specs) {
if (!this.hasOwnProperty(`_${property}`) || property === 'id') {
props[`${property}`] = specs[property];
}
}
return props;
}
/**
* Create a new bundle
*
* @returns {Promise<void>}
*/
async create(specs = {}) {
this._checkProperties(specs);
this.#bundlesManager.add(specs);
if (!this.#bundlesManager.items.size) throw Error('The module type cannot be undefined');
try {
await this._fs.mkdir(this.file.dirname, { recursive: true });
const json = Object.assign(this.properties, this.#bundlesManager.properties);
// add platforms if module have bundle bridge
if (specs.bundles.includes('bridge')) {
json.platforms = ['*'];
}
await this.#bundlesManager.build(specs);
await this.file.writeJSON(json);
/**
* .tsconfig file is used by IDEs to identify dependencies
// * @type {module.TsConfig}
*/
let { dirname } = this.file;
// ts and bridge bundles have no processors, the tsconfig file must be in the same folder as the bundle
if (specs.bundles.includes('ts') || specs.bundles.includes('bridge')) {
dirname = join(dirname, specs.bundles[0]);
}
const tsconfig = new TSConfig(dirname);
await tsconfig.create();
} catch (exc) {
console.error(exc);
}
}
getProperties() {
let properties = super.getProperties();
if (this.#bundlesManager.items.size === 1) {
this.#bundlesManager.items.forEach(item => {
properties = { ...properties, bundle: bundle.type, ...item.getProperties() };
});
} else {
if (this.#bundlesManager?.items) {
this.#bundlesManager?.items.forEach(bundle => {
properties[bundle.type] = bundle.getProperties();
});
}
}
return properties;
}
/**
* Updates the module.json file
*
* @param params
* @returns {Promise<boolean|object>}
*/
async save(params = {}) {
try {
await this.load();
this._checkProperties(params);
const data = this.getProperties();
this.#bundlesManager.check(params);
this.#bundlesManager.items.forEach(bundle => {
data[bundle.type] = bundle.getProperties();
});
await this.file.writeJSON(data);
return true;
} catch (e) {
console.error(e);
return { error: e.message };
}
}
};