Skip to content

Commit 90a8cab

Browse files
committed
refactor(ts): refactor plugin module to TS and fix tests
1 parent c008381 commit 90a8cab

File tree

3 files changed

+52
-54
lines changed

3 files changed

+52
-54
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"start": "concurrently \"npm run server\" \"npm run client\"",
1111
"build": "vite build",
1212
"build-ts": "tsc",
13-
"test": "NODE_ENV=test ts-mocha './test/*.js' --exit; mocha './test/plugin/*.js' --exit",
13+
"test": "NODE_ENV=test ts-mocha './test/*.js' --exit",
1414
"test-coverage": "nyc npm run test",
1515
"test-coverage-ci": "nyc --reporter=lcovonly --reporter=text npm run test",
1616
"prepare": "node ./scripts/prepare.js",

src/plugin.js renamed to src/plugin.ts

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Action } from './proxy/actions';
2+
13
const lpModule = import('load-plugin');
24
/* eslint-disable @typescript-eslint/no-unused-expressions */
35
('use strict');
@@ -8,7 +10,7 @@ const lpModule = import('load-plugin');
810
* @param {string} propertyName - The property name to check for. Default is 'isGitProxyPlugin'.
911
* @return {boolean} - True if the object or any of its prototypes has the 'isGitProxyPlugin' property set to true, false otherwise.
1012
*/
11-
function isCompatiblePlugin(obj, propertyName = 'isGitProxyPlugin') {
13+
function isCompatiblePlugin(obj: any, propertyName: string = 'isGitProxyPlugin'): boolean {
1214
// loop through the prototype chain to check if the object is a ProxyPlugin
1315
// valid plugin objects will have the appropriate property set to true
1416
// if the prototype chain is exhausted, return false
@@ -23,36 +25,24 @@ function isCompatiblePlugin(obj, propertyName = 'isGitProxyPlugin') {
2325
return false;
2426
}
2527

26-
/**
27-
* @typedef PluginTypeResult
28-
* @property {PushActionPlugin[]} pushAction - List of push action plugins
29-
* @property {PullActionPlugin[]} pullAction - List of pull action plugins
30-
*/
28+
interface PluginTypeResult {
29+
pushAction: PushActionPlugin[];
30+
pullAction: PullActionPlugin[];
31+
}
3132

3233
/**
3334
* Registers and loads plugins used by git-proxy
3435
*/
3536
class PluginLoader {
36-
constructor(targets) {
37-
/**
38-
* List of Node module specifiers to load as plugins. It can be a relative path, an
39-
* absolute path, or a module name (which can include scoped packages like '@bar/baz').
40-
* @type {string[]}
41-
* @public
42-
*/
37+
targets: string[];
38+
pushPlugins: PushActionPlugin[];
39+
pullPlugins: PullActionPlugin[];
40+
41+
constructor(targets: string[]) {
4342
this.targets = targets;
44-
/**
45-
* List of loaded PushActionPlugin objects.
46-
* @type {PushActionPlugin[]}
47-
* @public
48-
*/
4943
this.pushPlugins = [];
50-
/**
51-
* List of loaded PullActionPlugin objects.
52-
* @type {PullActionPlugin[]}
53-
* @public
54-
*/
5544
this.pullPlugins = [];
45+
5646
if (this.targets.length === 0) {
5747
console.log('No plugins configured'); // TODO: log.debug()
5848
}
@@ -63,7 +53,7 @@ class PluginLoader {
6353
* can be used to retrieve plugins.
6454
* @return {Promise<void>} A Promise that resolves when all plugins have been loaded.
6555
*/
66-
async load() {
56+
async load(): Promise<void> {
6757
try {
6858
const modulePromises = this.targets.map(target =>
6959
this._loadPluginModule(target).catch(error => {
@@ -74,7 +64,7 @@ class PluginLoader {
7464

7565
const moduleResults = await Promise.allSettled(modulePromises);
7666
const loadedModules = moduleResults
77-
.filter(result => result.status === 'fulfilled' && result.value !== null)
67+
.filter((result): result is PromiseFulfilledResult<any> => result.status === 'fulfilled' && result.value !== null)
7868
.map(result => result.value);
7969

8070
console.log(`Found ${loadedModules.length} plugin modules`); // TODO: log.debug()
@@ -91,7 +81,7 @@ class PluginLoader {
9181
* @type {PluginTypeResult[]} List of resolved PluginTypeResult objects
9282
*/
9383
const pluginTypeResults = settledPluginTypeResults
94-
.filter(result => result.status === 'fulfilled' && result.value !== null)
84+
.filter((result): result is PromiseFulfilledResult<any> => result.status === 'fulfilled' && result.value !== null)
9585
.map(result => result.value);
9686

9787
for (const result of pluginTypeResults) {
@@ -113,7 +103,7 @@ class PluginLoader {
113103
* @param {string} target The module specifier to load
114104
* @return {Promise<Module>} A resolved & loaded Module
115105
*/
116-
async _loadPluginModule(target) {
106+
private async _loadPluginModule(target: string): Promise<any> {
117107
const lp = await lpModule;
118108
const resolvedModuleFile = await lp.resolvePlugin(target);
119109
return await lp.loadPlugin(resolvedModuleFile);
@@ -124,13 +114,13 @@ class PluginLoader {
124114
* @param {Module} pluginModule The module to extract plugins from
125115
* @return {Promise<PluginTypeResult>} An object containing the loaded plugins classified by their type.
126116
*/
127-
async _getPluginObjects(pluginModule) {
128-
const plugins = {
117+
private async _getPluginObjects(pluginModule: any): Promise<PluginTypeResult> {
118+
const plugins: PluginTypeResult = {
129119
pushAction: [],
130120
pullAction: [],
131121
};
132122

133-
function handlePlugin(potentialModule) {
123+
function handlePlugin(potentialModule: any) {
134124
if (isCompatiblePlugin(potentialModule, 'isGitProxyPushActionPlugin')) {
135125
console.log('found push plugin', potentialModule.constructor.name);
136126
plugins.pushAction.push(potentialModule);
@@ -165,6 +155,8 @@ class PluginLoader {
165155
* ProxyPlugin to be loaded by PluginLoader.
166156
*/
167157
class ProxyPlugin {
158+
isGitProxyPlugin: boolean;
159+
168160
constructor() {
169161
this.isGitProxyPlugin = true;
170162
}
@@ -174,21 +166,24 @@ class ProxyPlugin {
174166
* A plugin which executes a function when receiving a git push request.
175167
*/
176168
class PushActionPlugin extends ProxyPlugin {
177-
/**
178-
* Wrapper class which contains at least one function executed as part of the action chain for git push operations.
179-
* The function must be called `exec` and take in two parameters: an Express Request (req) and the current Action
180-
* executed in the chain (action). This function should return a Promise that resolves to an Action.
181-
*
182-
* Optionally, child classes which extend this can simply define the `exec` function as their own property.
183-
* This is the preferred implementation when a custom plugin (subclass) has its own state or additional methods
184-
* that are required.
185-
*
186-
* @param {function} exec - A function that:
187-
* - Takes in an Express Request object as the first parameter (`req`).
188-
* - Takes in an Action object as the second parameter (`action`).
189-
* - Returns a Promise that resolves to an Action.
190-
*/
191-
constructor(exec) {
169+
isGitProxyPushActionPlugin: boolean;
170+
exec: (req: any, action: Action) => Promise<any>;
171+
172+
/**
173+
* Wrapper class which contains at least one function executed as part of the action chain for git push operations.
174+
* The function must be called `exec` and take in two parameters: an Express Request (req) and the current Action
175+
* executed in the chain (action). This function should return a Promise that resolves to an Action.
176+
*
177+
* Optionally, child classes which extend this can simply define the `exec` function as their own property.
178+
* This is the preferred implementation when a custom plugin (subclass) has its own state or additional methods
179+
* that are required.
180+
*
181+
* @param {function} exec - A function that:
182+
* - Takes in an Express Request object as the first parameter (`req`).
183+
* - Takes in an Action object as the second parameter (`action`).
184+
* - Returns a Promise that resolves to an Action.
185+
*/
186+
constructor(exec: (req: any, action: Action) => Promise<any>) {
192187
super();
193188
this.isGitProxyPushActionPlugin = true;
194189
this.exec = exec;
@@ -199,6 +194,9 @@ class PushActionPlugin extends ProxyPlugin {
199194
* A plugin which executes a function when receiving a git fetch request.
200195
*/
201196
class PullActionPlugin extends ProxyPlugin {
197+
isGitProxyPullActionPlugin: boolean;
198+
exec: (req: any, action: Action) => Promise<any>;
199+
202200
/**
203201
* Wrapper class which contains at least one function executed as part of the action chain for git pull operations.
204202
* The function must be called `exec` and take in two parameters: an Express Request (req) and the current Action
@@ -213,14 +211,14 @@ class PullActionPlugin extends ProxyPlugin {
213211
* - Takes in an Action object as the second parameter (`action`).
214212
* - Returns a Promise that resolves to an Action.
215213
*/
216-
constructor(exec) {
214+
constructor(exec: (req: any, action: Action) => Promise<any>) {
217215
super();
218216
this.isGitProxyPullActionPlugin = true;
219217
this.exec = exec;
220218
}
221219
}
222220

223-
module.exports = {
221+
export {
224222
PluginLoader,
225223
PushActionPlugin,
226224
PullActionPlugin,

test/plugin/plugin.test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
const chai = require('chai');
2-
const {
1+
import chai from 'chai';
2+
import { spawnSync } from 'child_process';
3+
import { rmSync } from 'fs';
4+
import { join } from 'path';
5+
import {
36
isCompatiblePlugin,
47
PullActionPlugin,
58
PushActionPlugin,
69
PluginLoader,
7-
} = require('../../src/plugin');
8-
const { spawnSync } = require('child_process');
9-
const { rmSync } = require('fs');
10-
const { join } = require('path');
10+
} from '../../src/plugin.ts';
1111

1212
chai.should();
1313

0 commit comments

Comments
 (0)