mirror of
https://github.com/bpatrik/pigallery2.git
synced 2024-12-23 01:27:14 +02:00
Merge branches 'master' and 'bugfix/offset-or-ignore' of https://github.com/grasdk/pigallery2 into bugfix/offset-or-ignore
This commit is contained in:
commit
a44b7f8d15
@ -7,7 +7,7 @@ See sample extension at https://github.com/bpatrik/pigallery2-sample-extension.
|
|||||||
# Extension Usage
|
# Extension Usage
|
||||||
|
|
||||||
Extension folder can be set through config. For the docker-ised version,
|
Extension folder can be set through config. For the docker-ised version,
|
||||||
they live under the `config/extension` folder in their own subdirectory.
|
they live under the `config/extension` folder in their own subdirectory.
|
||||||
|
|
||||||
# Extension development
|
# Extension development
|
||||||
|
|
||||||
@ -21,16 +21,20 @@ You need at least a `server.js` in your extension folder that exports a `init(ex
|
|||||||
<path to the extension fodler>/myextension/package.js <- this is optional. You can add extra npm packages here
|
<path to the extension fodler>/myextension/package.js <- this is optional. You can add extra npm packages here
|
||||||
<path to the extension fodler>/myextension/server.js <- this is needed
|
<path to the extension fodler>/myextension/server.js <- this is needed
|
||||||
```
|
```
|
||||||
|
|
||||||
Where `<path to the extension fodler>` is what you set in the config and `myextension` is the name of your extension.
|
Where `<path to the extension fodler>` is what you set in the config and `myextension` is the name of your extension.
|
||||||
Note: you do not need to add your `node_modules` folder. The app will call `npm intall` when initializing your extension.
|
Note: you do not need to add your `node_modules` folder. The app will call `npm install` when initializing your extension.
|
||||||
|
|
||||||
## Extension environment
|
## Extension environment
|
||||||
|
|
||||||
The app runs the extension the following way:
|
The app runs the extension the following way:
|
||||||
* It reads all extensions in `<path to the extension fodler>/**` folder
|
|
||||||
* Checks if `package.js` is present. If yes installs the packages
|
- It reads all extensions in `<path to the extension fodler>/**` folder
|
||||||
* Checks if `server.js` is present. If yes, calls the `init` function.
|
- Checks if `package.js` is present. If yes installs the packages
|
||||||
|
- Checks if `server.js` is present. If yes, calls the `init` function.
|
||||||
|
|
||||||
### Init and cleanup lifecycle
|
### Init and cleanup lifecycle
|
||||||
|
|
||||||
There is also a `cleanUp` function that you can implement in your extension.
|
There is also a `cleanUp` function that you can implement in your extension.
|
||||||
The app can call your `init` and `cleanUp` functions any time.
|
The app can call your `init` and `cleanUp` functions any time.
|
||||||
Always calls the `init` first then `cleanUp` later.
|
Always calls the `init` first then `cleanUp` later.
|
||||||
@ -39,8 +43,7 @@ Main use-case: `init` is called on app startup. `cleanUp` and `init` called late
|
|||||||
## Extension interface
|
## Extension interface
|
||||||
|
|
||||||
The app calls the `init` and `cleanUp` function with a `IExtensionObject` object.
|
The app calls the `init` and `cleanUp` function with a `IExtensionObject` object.
|
||||||
See https://github.com/bpatrik/pigallery2/blob/master/src/backend/model/extension/IExtension.ts for details.
|
See https://github.com/bpatrik/pigallery2/blob/master/src/backend/model/extension/IExtension.ts for details.
|
||||||
|
|
||||||
|
|
||||||
`IExtensionObject` exposes lifecycle events, configs, RestAPis with some limitation.
|
`IExtensionObject` exposes lifecycle events, configs, RestAPis with some limitation.
|
||||||
Changes made during the these public apis you do not need to clean up in the `cleanUp` function.
|
Changes made during the these public apis you do not need to clean up in the `cleanUp` function.
|
||||||
@ -50,7 +53,7 @@ App also exposes private `_app` object to provide access to low level API. Any c
|
|||||||
|
|
||||||
See sample server.js at https://github.com/bpatrik/pigallery2-sample-extension.
|
See sample server.js at https://github.com/bpatrik/pigallery2-sample-extension.
|
||||||
|
|
||||||
It is recommended to do the development in `ts`, so creating a `server.ts`.
|
It is recommended to do the development in `ts`, so creating a `server.ts`.
|
||||||
Note: You need to manually transpile your `server.ts` file to `server.js` as the app does not do that for you.
|
Note: You need to manually transpile your `server.ts` file to `server.js` as the app does not do that for you.
|
||||||
This doc assumes you do the development in `ts`.
|
This doc assumes you do the development in `ts`.
|
||||||
|
|
||||||
@ -59,23 +62,23 @@ This doc assumes you do the development in `ts`.
|
|||||||
You can import package from both the main app package.json and from your extension package.json.
|
You can import package from both the main app package.json and from your extension package.json.
|
||||||
To import packages from the main app, you import as usual.
|
To import packages from the main app, you import as usual.
|
||||||
For packages from the extension, you always need to write relative path. i.e.: prefix with `./node_modules`
|
For packages from the extension, you always need to write relative path. i.e.: prefix with `./node_modules`
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// Including dev-kit interfaces. It is not necessary, only helps development with types.
|
// Including dev-kit interfaces. It is not necessary, only helps development with types.
|
||||||
// You need to prefix them with ./node_modules
|
// You need to prefix them with ./node_modules
|
||||||
import {IExtensionObject} from './node_modules/pigallery2-extension-kit';
|
import { IExtensionObject } from "./node_modules/pigallery2-extension-kit";
|
||||||
|
|
||||||
// Including prod extension packages. You need to prefix them with ./node_modules
|
// Including prod extension packages. You need to prefix them with ./node_modules
|
||||||
// lodash does not have types
|
// lodash does not have types
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import * as _ from './node_modules/lodash';
|
import * as _ from "./node_modules/lodash";
|
||||||
|
|
||||||
// Importing packages that are available in the main app (listed in the packages.json in pigallery2)
|
// Importing packages that are available in the main app (listed in the packages.json in pigallery2)
|
||||||
import {Column, Entity, Index, PrimaryGeneratedColumn} from 'typeorm';
|
import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm";
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### pigallery2 extension dev-kit
|
||||||
#### pigallery2 extension dev-kit
|
|
||||||
|
|
||||||
It is recommended to use the `pigallery2-extension-kit` node package.
|
It is recommended to use the `pigallery2-extension-kit` node package.
|
||||||
`npm install pigallery2-extension-kit --save` to your extension.
|
`npm install pigallery2-extension-kit --save` to your extension.
|
||||||
@ -87,17 +90,14 @@ You can then `import {IExtensionObject} from './node_modules/pigallery2-extensio
|
|||||||
|
|
||||||
See https://github.com/bpatrik/pigallery2/blob/master/src/backend/model/extension/IExtension.ts to understand what contains `IExtensionObject`.
|
See https://github.com/bpatrik/pigallery2/blob/master/src/backend/model/extension/IExtension.ts to understand what contains `IExtensionObject`.
|
||||||
|
|
||||||
NOTE: this is not needed to create an extension it only helps your IDE and your development. These type definitions are removed when you compile `ts` to `js`.
|
NOTE: this is not needed to create an extension it only helps your IDE and your development. These type definitions are removed when you compile `ts` to `js`.
|
||||||
|
|
||||||
#### `init` function
|
#### `init` function
|
||||||
|
|
||||||
You need to implement the `init` function for a working extension:
|
You need to implement the `init` function for a working extension:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
|
export const init = async (extension: IExtensionObject<void>): Promise<void> => {};
|
||||||
export const init = async (extension: IExtensionObject<void>): Promise<void> => {
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### pigallery2 lifecycle `events`
|
#### pigallery2 lifecycle `events`
|
||||||
@ -105,5 +105,4 @@ export const init = async (extension: IExtensionObject<void>): Promise<void> =>
|
|||||||
Tha app exposes multiple interfaces for the extensions to interact with the main app. `events` are one of the main interfaces.
|
Tha app exposes multiple interfaces for the extensions to interact with the main app. `events` are one of the main interfaces.
|
||||||
Here are their flow:
|
Here are their flow:
|
||||||
|
|
||||||
|
|
||||||
![events_lifecycle](events.png)
|
![events_lifecycle](events.png)
|
||||||
|
14
package-lock.json
generated
14
package-lock.json
generated
@ -27,7 +27,7 @@
|
|||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"sharp": "0.31.3",
|
"sharp": "0.31.3",
|
||||||
"ts-node-iptc": "1.0.11",
|
"ts-node-iptc": "1.0.11",
|
||||||
"typeconfig": "2.2.15",
|
"typeconfig": "2.3.1",
|
||||||
"typeorm": "0.3.12",
|
"typeorm": "0.3.12",
|
||||||
"xml2js": "0.6.2"
|
"xml2js": "0.6.2"
|
||||||
},
|
},
|
||||||
@ -20362,9 +20362,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typeconfig": {
|
"node_modules/typeconfig": {
|
||||||
"version": "2.2.15",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-2.2.15.tgz",
|
"resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-2.3.1.tgz",
|
||||||
"integrity": "sha512-aqiuT5BtV0/0MYMMG78c1IqeJrF85r1W1pJckkGolPjHpE0ajA3oOgnRtX5DRDHsn3YzsY5FKMxj1B3J+ISx1g==",
|
"integrity": "sha512-xBdsf0tK/PcXyZzWq/U2xLNDNrVFkRQ9d8V9x3B5eu1LG5GmeDDK7zLScz79zbl0dCZzhjnvx4RRggY6DZAAZA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimist": "1.2.8"
|
"minimist": "1.2.8"
|
||||||
}
|
}
|
||||||
@ -35283,9 +35283,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typeconfig": {
|
"typeconfig": {
|
||||||
"version": "2.2.15",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-2.2.15.tgz",
|
"resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-2.3.1.tgz",
|
||||||
"integrity": "sha512-aqiuT5BtV0/0MYMMG78c1IqeJrF85r1W1pJckkGolPjHpE0ajA3oOgnRtX5DRDHsn3YzsY5FKMxj1B3J+ISx1g==",
|
"integrity": "sha512-xBdsf0tK/PcXyZzWq/U2xLNDNrVFkRQ9d8V9x3B5eu1LG5GmeDDK7zLScz79zbl0dCZzhjnvx4RRggY6DZAAZA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "1.2.8"
|
"minimist": "1.2.8"
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"sharp": "0.31.3",
|
"sharp": "0.31.3",
|
||||||
"ts-node-iptc": "1.0.11",
|
"ts-node-iptc": "1.0.11",
|
||||||
"typeconfig": "2.2.15",
|
"typeconfig": "2.3.1",
|
||||||
"typeorm": "0.3.12",
|
"typeorm": "0.3.12",
|
||||||
"xml2js": "0.6.2"
|
"xml2js": "0.6.2"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import {Config} from '../common/config/private/Config';
|
import {PrivateConfigClass} from '../common/config/private/PrivateConfigClass';
|
||||||
|
|
||||||
export class ProjectPathClass {
|
export class ProjectPathClass {
|
||||||
public Root: string;
|
public Root: string;
|
||||||
@ -11,8 +11,10 @@ export class ProjectPathClass {
|
|||||||
public FrontendFolder: string;
|
public FrontendFolder: string;
|
||||||
public ExtensionFolder: string;
|
public ExtensionFolder: string;
|
||||||
public DBFolder: string;
|
public DBFolder: string;
|
||||||
|
private cfg: PrivateConfigClass;
|
||||||
|
|
||||||
constructor() {
|
init(cfg: PrivateConfigClass) {
|
||||||
|
this.cfg = cfg;
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,12 +33,12 @@ export class ProjectPathClass {
|
|||||||
reset(): void {
|
reset(): void {
|
||||||
this.Root = path.join(__dirname, '/../../');
|
this.Root = path.join(__dirname, '/../../');
|
||||||
this.FrontendFolder = path.join(this.Root, 'dist');
|
this.FrontendFolder = path.join(this.Root, 'dist');
|
||||||
this.ImageFolder = this.getAbsolutePath(Config.Media.folder);
|
this.ImageFolder = this.getAbsolutePath(this.cfg.Media.folder);
|
||||||
this.TempFolder = this.getAbsolutePath(Config.Media.tempFolder);
|
this.TempFolder = this.getAbsolutePath(this.cfg.Media.tempFolder);
|
||||||
this.TranscodedFolder = path.join(this.TempFolder, 'tc');
|
this.TranscodedFolder = path.join(this.TempFolder, 'tc');
|
||||||
this.FacesFolder = path.join(this.TempFolder, 'f');
|
this.FacesFolder = path.join(this.TempFolder, 'f');
|
||||||
this.DBFolder = this.getAbsolutePath(Config.Database.dbFolder);
|
this.DBFolder = this.getAbsolutePath(this.cfg.Database.dbFolder);
|
||||||
this.ExtensionFolder = this.getAbsolutePath(Config.Extensions.folder);
|
this.ExtensionFolder = this.getAbsolutePath(this.cfg.Extensions.folder);
|
||||||
|
|
||||||
// create thumbnail folder if not exist
|
// create thumbnail folder if not exist
|
||||||
if (!fs.existsSync(this.TempFolder)) {
|
if (!fs.existsSync(this.TempFolder)) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import {IExtensionConfig} from './IExtension';
|
import {IExtensionConfig} from './IExtension';
|
||||||
import {Config} from '../../../common/config/private/Config';
|
import {Config} from '../../../common/config/private/Config';
|
||||||
|
import {ServerExtensionsEntryConfig} from '../../../common/config/private/subconfigs/ServerExtensionsConfig';
|
||||||
|
|
||||||
export class ExtensionConfig<C> implements IExtensionConfig<C> {
|
export class ExtensionConfig<C> implements IExtensionConfig<C> {
|
||||||
|
|
||||||
@ -8,8 +9,7 @@ export class ExtensionConfig<C> implements IExtensionConfig<C> {
|
|||||||
|
|
||||||
|
|
||||||
public getConfig(): C {
|
public getConfig(): C {
|
||||||
const c = (Config.Extensions.extensions || [])
|
const c = Config.Extensions.extensions[this.extensionFolder] as ServerExtensionsEntryConfig;
|
||||||
.find(e => e.path === this.extensionFolder);
|
|
||||||
|
|
||||||
return c?.configs as C;
|
return c?.configs as C;
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,8 @@ import {PrivateConfigClass} from '../../../common/config/private/PrivateConfigCl
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {ServerExtensionsEntryConfig} from '../../../common/config/private/subconfigs/ServerExtensionsConfig';
|
import {ServerExtensionsEntryConfig} from '../../../common/config/private/subconfigs/ServerExtensionsConfig';
|
||||||
import * as child_process from 'child_process';
|
import {ProjectPath} from '../../ProjectPath';
|
||||||
|
|
||||||
const execSync = child_process.execSync;
|
|
||||||
|
|
||||||
const LOG_TAG = '[ExtensionConfigTemplateLoader]';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class decouples the extension management and the config.
|
* This class decouples the extension management and the config.
|
||||||
@ -16,7 +13,6 @@ const LOG_TAG = '[ExtensionConfigTemplateLoader]';
|
|||||||
export class ExtensionConfigTemplateLoader {
|
export class ExtensionConfigTemplateLoader {
|
||||||
|
|
||||||
private static instance: ExtensionConfigTemplateLoader;
|
private static instance: ExtensionConfigTemplateLoader;
|
||||||
private extensionsFolder: string;
|
|
||||||
|
|
||||||
private loaded = false;
|
private loaded = false;
|
||||||
private extensionList: string[] = [];
|
private extensionList: string[] = [];
|
||||||
@ -31,29 +27,26 @@ export class ExtensionConfigTemplateLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
init(extensionsFolder: string) {
|
|
||||||
this.extensionsFolder = extensionsFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public loadExtensionTemplates(config: PrivateConfigClass) {
|
public loadExtensionTemplates(config: PrivateConfigClass) {
|
||||||
if (!this.extensionsFolder) {
|
if (!ProjectPath.ExtensionFolder) {
|
||||||
throw new Error('Unknown extensions folder.');
|
throw new Error('Unknown extensions folder.');
|
||||||
}
|
}
|
||||||
// already loaded
|
// already loaded
|
||||||
if (!this.loaded) {
|
if (!this.loaded) {
|
||||||
|
|
||||||
this.extensionTemplates = [];
|
this.extensionTemplates = [];
|
||||||
if (fs.existsSync(this.extensionsFolder)) {
|
if (fs.existsSync(ProjectPath.ExtensionFolder)) {
|
||||||
this.extensionList = (fs
|
this.extensionList = (fs
|
||||||
.readdirSync(this.extensionsFolder))
|
.readdirSync(ProjectPath.ExtensionFolder))
|
||||||
.filter((f): boolean =>
|
.filter((f): boolean =>
|
||||||
fs.statSync(path.join(this.extensionsFolder, f)).isDirectory()
|
fs.statSync(path.join(ProjectPath.ExtensionFolder, f)).isDirectory()
|
||||||
);
|
);
|
||||||
this.extensionList.sort();
|
this.extensionList.sort();
|
||||||
|
|
||||||
for (let i = 0; i < this.extensionList.length; ++i) {
|
for (let i = 0; i < this.extensionList.length; ++i) {
|
||||||
const extFolder = this.extensionList[i];
|
const extFolder = this.extensionList[i];
|
||||||
const extPath = path.join(this.extensionsFolder, extFolder);
|
const extPath = path.join(ProjectPath.ExtensionFolder, extFolder);
|
||||||
const configExtPath = path.join(extPath, 'config.js');
|
const configExtPath = path.join(extPath, 'config.js');
|
||||||
const serverExtPath = path.join(extPath, 'server.js');
|
const serverExtPath = path.join(extPath, 'server.js');
|
||||||
|
|
||||||
@ -92,16 +85,20 @@ export class ExtensionConfigTemplateLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ePaths = this.extensionTemplates.map(et => et.folder);
|
const ePaths = this.extensionTemplates.map(et => et.folder);
|
||||||
|
|
||||||
// delete not existing extensions
|
// delete not existing extensions
|
||||||
config.Extensions.extensions = config.Extensions.extensions
|
for (const prop of config.Extensions.extensions.keys()) {
|
||||||
.filter(ec => ePaths.indexOf(ec.path) !== -1);
|
if (ePaths.indexOf(prop) > -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
config.Extensions.extensions.removeProperty(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (let i = 0; i < this.extensionTemplates.length; ++i) {
|
for (let i = 0; i < this.extensionTemplates.length; ++i) {
|
||||||
const ext = this.extensionTemplates[i];
|
const ext = this.extensionTemplates[i];
|
||||||
|
|
||||||
let c = (config.Extensions.extensions || [])
|
let c = config.Extensions.extensions[ext.folder];
|
||||||
.find(e => e.path === ext.folder);
|
|
||||||
|
|
||||||
// set the new structure with the new def values
|
// set the new structure with the new def values
|
||||||
if (!c) {
|
if (!c) {
|
||||||
@ -109,9 +106,7 @@ export class ExtensionConfigTemplateLoader {
|
|||||||
if (ext.template) {
|
if (ext.template) {
|
||||||
c.configs = new ext.template();
|
c.configs = new ext.template();
|
||||||
}
|
}
|
||||||
// TODO: this does not hold if the order of the extensions mixes up.
|
config.Extensions.extensions.addProperty(ext.folder, {type: ServerExtensionsEntryConfig}, c);
|
||||||
// TODO: experiment with a map instead of an array
|
|
||||||
config.Extensions.extensions.push(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import {SQLConnection} from '../database/SQLConnection';
|
|||||||
import {ExtensionObject} from './ExtensionObject';
|
import {ExtensionObject} from './ExtensionObject';
|
||||||
import {ExtensionDecoratorObject} from './ExtensionDecorator';
|
import {ExtensionDecoratorObject} from './ExtensionDecorator';
|
||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
|
import {ServerExtensionsEntryConfig} from '../../../common/config/private/subconfigs/ServerExtensionsConfig';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const exec = util.promisify(require('child_process').exec);
|
const exec = util.promisify(require('child_process').exec);
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ export class ExtensionManager implements IObjectManager {
|
|||||||
extList.sort();
|
extList.sort();
|
||||||
|
|
||||||
|
|
||||||
Logger.debug(LOG_TAG, 'Extensions found: ', JSON.stringify(Config.Extensions.extensions.map(ec => ec.path)));
|
Logger.debug(LOG_TAG, 'Extensions found: ', JSON.stringify(Config.Extensions.extensions.keys()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private createUniqueExtensionObject(name: string, folder: string): IExtensionObject<unknown> {
|
private createUniqueExtensionObject(name: string, folder: string): IExtensionObject<unknown> {
|
||||||
@ -99,11 +100,12 @@ export class ExtensionManager implements IObjectManager {
|
|||||||
|
|
||||||
private async initExtensions() {
|
private async initExtensions() {
|
||||||
|
|
||||||
for (let i = 0; i < Config.Extensions.extensions.length; ++i) {
|
for (const prop of Config.Extensions.extensions.keys()) {
|
||||||
const extFolder = Config.Extensions.extensions[i].path;
|
const extConf: ServerExtensionsEntryConfig = Config.Extensions.extensions[prop] as ServerExtensionsEntryConfig;
|
||||||
|
const extFolder = extConf.path;
|
||||||
let extName = extFolder;
|
let extName = extFolder;
|
||||||
|
|
||||||
if (Config.Extensions.extensions[i].enabled === false) {
|
if (extConf.enabled === false) {
|
||||||
Logger.silly(LOG_TAG, `Skipping ${extFolder} initiation. Extension is disabled.`);
|
Logger.silly(LOG_TAG, `Skipping ${extFolder} initiation. Extension is disabled.`);
|
||||||
}
|
}
|
||||||
const extPath = path.join(ProjectPath.ExtensionFolder, extFolder);
|
const extPath = path.join(ProjectPath.ExtensionFolder, extFolder);
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import {ExtensionConfigWrapper} from '../../../backend/model/extension/ExtensionConfigWrapper';
|
import {ExtensionConfigWrapper} from '../../../backend/model/extension/ExtensionConfigWrapper';
|
||||||
import {PrivateConfigClass} from './PrivateConfigClass';
|
import {PrivateConfigClass} from './PrivateConfigClass';
|
||||||
import {ConfigClassBuilder} from 'typeconfig/node';
|
import {ConfigClassBuilder} from 'typeconfig/node';
|
||||||
import {ExtensionConfigTemplateLoader} from '../../../backend/model/extension/ExtensionConfigTemplateLoader';
|
import {ProjectPath} from '../../../backend/ProjectPath';
|
||||||
import * as path from 'path';
|
|
||||||
|
|
||||||
// we need to know the location of the extensions to load the full config (including the extensions)
|
// we need to know the location of the extensions to load the full config (including the extensions)
|
||||||
const pre = ConfigClassBuilder.attachPrivateInterface(new PrivateConfigClass());
|
const pre = ConfigClassBuilder.attachPrivateInterface(new PrivateConfigClass());
|
||||||
@ -10,6 +9,9 @@ try {
|
|||||||
pre.loadSync({preventSaving: true});
|
pre.loadSync({preventSaving: true});
|
||||||
} catch (e) { /* empty */
|
} catch (e) { /* empty */
|
||||||
}
|
}
|
||||||
ExtensionConfigTemplateLoader.Instance.init(path.join(__dirname, '/../../../../', pre.Extensions.folder));
|
// load extension paths before full config load
|
||||||
|
ProjectPath.init(pre);
|
||||||
|
|
||||||
export const Config = ExtensionConfigWrapper.originalSync(true);
|
export const Config = ExtensionConfigWrapper.originalSync(true);
|
||||||
|
// set actual config
|
||||||
|
ProjectPath.init(Config);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-inferrable-types */
|
/* eslint-disable @typescript-eslint/no-inferrable-types */
|
||||||
import {ConfigProperty, SubConfigClass} from 'typeconfig/common';
|
import {ConfigMap, ConfigProperty, IConfigMap, SubConfigClass} from 'typeconfig/common';
|
||||||
import {ClientExtensionsConfig, ConfigPriority, TAGS} from '../../public/ClientConfig';
|
import {ClientExtensionsConfig, ConfigPriority, TAGS} from '../../public/ClientConfig';
|
||||||
import {GenericConfigType} from 'typeconfig/src/GenericConfigType';
|
import {GenericConfigType} from 'typeconfig/src/GenericConfigType';
|
||||||
|
|
||||||
@ -59,16 +59,14 @@ export class ServerExtensionsConfig extends ClientExtensionsConfig {
|
|||||||
})
|
})
|
||||||
folder: string = 'extensions';
|
folder: string = 'extensions';
|
||||||
|
|
||||||
// TODO: this does not hold if the order of the extensions mixes up.
|
|
||||||
// TODO: experiment with a map instead of an array
|
|
||||||
@ConfigProperty({
|
@ConfigProperty({
|
||||||
arrayType: ServerExtensionsEntryConfig,
|
type: ConfigMap,
|
||||||
tags: {
|
tags: {
|
||||||
name: $localize`Installed extensions`,
|
name: $localize`Installed extensions`,
|
||||||
priority: ConfigPriority.advanced
|
priority: ConfigPriority.advanced
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
extensions: ServerExtensionsEntryConfig[] = [];
|
extensions: IConfigMap<ServerExtensionsEntryConfig> = new ConfigMap();
|
||||||
|
|
||||||
|
|
||||||
@ConfigProperty({
|
@ConfigProperty({
|
||||||
|
Loading…
Reference in New Issue
Block a user