mirror of
https://github.com/bpatrik/pigallery2.git
synced 2024-12-25 02:04:15 +02:00
Adding package.json support with dependency #753
This commit is contained in:
parent
3cf45c56b5
commit
9f5257626f
23
package-lock.json
generated
23
package-lock.json
generated
@ -22,6 +22,7 @@
|
||||
"fluent-ffmpeg": "2.1.2",
|
||||
"image-size": "1.0.2",
|
||||
"locale": "0.1.0",
|
||||
"logger": "file:extensions/logger",
|
||||
"node-geocoder": "4.2.0",
|
||||
"nodemailer": "6.9.4",
|
||||
"reflect-metadata": "0.1.13",
|
||||
@ -131,6 +132,12 @@
|
||||
"mysql": "2.18.1"
|
||||
}
|
||||
},
|
||||
"extensions/logger": {
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"lodash": "4.17.21"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
|
||||
@ -15585,8 +15592,7 @@
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.21",
|
||||
@ -15843,6 +15849,10 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/logger": {
|
||||
"resolved": "extensions/logger",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/loupe": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz",
|
||||
@ -35932,8 +35942,7 @@
|
||||
"lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"lodash-es": {
|
||||
"version": "4.17.21",
|
||||
@ -36137,6 +36146,12 @@
|
||||
"streamroller": "^3.0.6"
|
||||
}
|
||||
},
|
||||
"logger": {
|
||||
"version": "file:extensions/logger",
|
||||
"requires": {
|
||||
"lodash": "4.17.21"
|
||||
}
|
||||
},
|
||||
"loupe": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz",
|
||||
|
@ -48,6 +48,7 @@
|
||||
"fluent-ffmpeg": "2.1.2",
|
||||
"image-size": "1.0.2",
|
||||
"locale": "0.1.0",
|
||||
"logger": "file:extensions/logger",
|
||||
"node-geocoder": "4.2.0",
|
||||
"nodemailer": "6.9.4",
|
||||
"reflect-metadata": "0.1.13",
|
||||
|
@ -11,6 +11,9 @@ import * as express from 'express';
|
||||
import {SQLConnection} from '../database/SQLConnection';
|
||||
import {ExtensionObject} from './ExtensionObject';
|
||||
import {ExtensionDecoratorObject} from './ExtensionDecorator';
|
||||
import * as util from 'util';
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const exec = util.promisify(require('child_process').exec);
|
||||
|
||||
const LOG_TAG = '[ExtensionManager]';
|
||||
|
||||
@ -68,43 +71,60 @@ export class ExtensionManager implements IObjectManager {
|
||||
}
|
||||
|
||||
Config.Extensions.list = fs
|
||||
.readdirSync(ProjectPath.ExtensionFolder)
|
||||
.filter((f): boolean =>
|
||||
fs.statSync(path.join(ProjectPath.ExtensionFolder, f)).isDirectory()
|
||||
);
|
||||
.readdirSync(ProjectPath.ExtensionFolder)
|
||||
.filter((f): boolean =>
|
||||
fs.statSync(path.join(ProjectPath.ExtensionFolder, f)).isDirectory()
|
||||
);
|
||||
Config.Extensions.list.sort();
|
||||
Logger.debug(LOG_TAG, 'Extensions found ', JSON.stringify(Config.Extensions.list));
|
||||
}
|
||||
|
||||
private async callServerFN(fn: (ext: IServerExtension<unknown>, extName: string) => Promise<void>) {
|
||||
for (let i = 0; i < Config.Extensions.list.length; ++i) {
|
||||
const extName = Config.Extensions.list[i];
|
||||
const extPath = path.join(ProjectPath.ExtensionFolder, extName);
|
||||
const serverExt = path.join(extPath, 'server.js');
|
||||
if (!fs.existsSync(serverExt)) {
|
||||
Logger.silly(LOG_TAG, `Skipping ${extName} server initiation. server.js does not exists`);
|
||||
continue;
|
||||
private createUniqueExtensionObject(name: string, folder: string): IExtensionObject<unknown> {
|
||||
let id = name;
|
||||
if (this.extObjects[id]) {
|
||||
let i = 0;
|
||||
while (this.extObjects[`${name}_${++i}`]) { /* empty */
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const ext = require(serverExt);
|
||||
await fn(ext, extName);
|
||||
id = `${name}_${++i}`;
|
||||
}
|
||||
}
|
||||
|
||||
private createExtensionObject(name: string): IExtensionObject<unknown> {
|
||||
if (!this.extObjects[name]) {
|
||||
this.extObjects[name] = new ExtensionObject(name, this.router, this.events);
|
||||
if (!this.extObjects[id]) {
|
||||
this.extObjects[id] = new ExtensionObject(id, name, folder, this.router, this.events);
|
||||
}
|
||||
return this.extObjects[name];
|
||||
return this.extObjects[id];
|
||||
}
|
||||
|
||||
private async initExtensions() {
|
||||
await this.callServerFN(async (ext, extName) => {
|
||||
if (typeof ext?.init === 'function') {
|
||||
Logger.debug(LOG_TAG, 'Running init on extension: ' + extName);
|
||||
await ext?.init(this.createExtensionObject(extName));
|
||||
|
||||
for (let i = 0; i < Config.Extensions.list.length; ++i) {
|
||||
const extFolder = Config.Extensions.list[i];
|
||||
let extName = extFolder;
|
||||
const extPath = path.join(ProjectPath.ExtensionFolder, extFolder);
|
||||
const serverExtPath = path.join(extPath, 'server.js');
|
||||
const packageJsonPath = path.join(extPath, 'package.json');
|
||||
if (!fs.existsSync(serverExtPath)) {
|
||||
Logger.silly(LOG_TAG, `Skipping ${extFolder} server initiation. server.js does not exists`);
|
||||
continue;
|
||||
}
|
||||
});
|
||||
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
Logger.silly(LOG_TAG, `Running: "npm install --omit=dev" in ${extPath}`);
|
||||
await exec('npm install --omit=dev' ,{
|
||||
cwd:extPath
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const pkg = require(packageJsonPath);
|
||||
if (pkg.name) {
|
||||
extName = pkg.name;
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const ext = require(serverExtPath);
|
||||
if (typeof ext?.init === 'function') {
|
||||
Logger.debug(LOG_TAG, 'Running init on extension: ' + extFolder);
|
||||
await ext?.init(this.createUniqueExtensionObject(extName, extPath));
|
||||
}
|
||||
}
|
||||
if (Config.Extensions.cleanUpUnusedTables) {
|
||||
// Clean up tables after all Extension was initialized.
|
||||
await SQLConnection.removeUnusedTables();
|
||||
@ -112,12 +132,15 @@ export class ExtensionManager implements IObjectManager {
|
||||
}
|
||||
|
||||
private async cleanUpExtensions() {
|
||||
await this.callServerFN(async (ext, extName) => {
|
||||
for (const extObj of Object.values(this.extObjects)) {
|
||||
const serverExt = path.join(extObj.folder, 'server.js');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const ext = require(serverExt);
|
||||
if (typeof ext?.cleanUp === 'function') {
|
||||
Logger.debug(LOG_TAG, 'Running Init on extension:' + extName);
|
||||
await ext?.cleanUp(this.createExtensionObject(extName));
|
||||
Logger.debug(LOG_TAG, 'Running Init on extension:' + extObj.extensionName);
|
||||
await ext?.cleanUp(ext);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,7 +17,11 @@ export class ExtensionObject<C> implements IExtensionObject<C> {
|
||||
public readonly events;
|
||||
public readonly RESTApi;
|
||||
|
||||
constructor(public readonly extensionId: string, extensionRouter: express.Router, events: IExtensionEvents) {
|
||||
constructor(public readonly extensionId: string,
|
||||
public readonly extensionName: string,
|
||||
public readonly folder: string,
|
||||
extensionRouter: express.Router,
|
||||
events: IExtensionEvents) {
|
||||
const logger = createLoggerWrapper(`[Extension][${extensionId}]`);
|
||||
this._app = new ExtensionApp();
|
||||
this.config = new ExtensionConfig<C>(extensionId);
|
||||
|
@ -117,6 +117,16 @@ export interface IExtensionConfig<C> {
|
||||
}
|
||||
|
||||
export interface IExtensionObject<C> {
|
||||
/**
|
||||
* ID of the extension that is internally used. By default the name and ID matches if there is no collision.
|
||||
*/
|
||||
extensionId: string,
|
||||
|
||||
/**
|
||||
* Name of the extension
|
||||
*/
|
||||
extensionName: string,
|
||||
|
||||
/**
|
||||
* Inner functionality of the app. Use this with caution.
|
||||
* If you want to go deeper than the standard exposed APIs, you can try doing so here.
|
||||
|
Loading…
Reference in New Issue
Block a user