1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-11-08 23:25:51 +01:00

feat: migrate yeoman generator to monorepo (#4683)

* feat: migrate geoman generator

* Create README.md
This commit is contained in:
Juan Picado 2024-06-15 19:59:11 +02:00 committed by GitHub
parent 117eb1ca42
commit a528af49bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 3257 additions and 304 deletions

@ -0,0 +1,5 @@
---
'generator-verdaccio-plugin': major
---
feat: migration to monorepo

3
.gitignore vendored

@ -53,3 +53,6 @@ e2e/ui/cypress/screenshots/**/*
# storybook # storybook
packages/ui-components/storybook-static packages/ui-components/storybook-static
# plugin generator
packages/tools/generator-verdaccio-plugin/generators/

@ -61,6 +61,9 @@
"@types/http-errors": "2.0.4", "@types/http-errors": "2.0.4",
"@types/jest": "29.5.11", "@types/jest": "29.5.11",
"@types/jsonwebtoken": "9.0.5", "@types/jsonwebtoken": "9.0.5",
"@types/yeoman-environment": "2.10.11",
"@types/yeoman-generator": "5.2.14",
"@types/yeoman-test": "4.0.6",
"@types/lodash": "4.14.202", "@types/lodash": "4.14.202",
"@types/mime": "3.0.4", "@types/mime": "3.0.4",
"@types/minimatch": "5.1.2", "@types/minimatch": "5.1.2",
@ -127,7 +130,7 @@
"verdaccio-auth-memory": "workspace:*", "verdaccio-auth-memory": "workspace:*",
"verdaccio-htpasswd": "workspace:*", "verdaccio-htpasswd": "workspace:*",
"verdaccio-memory": "workspace:*", "verdaccio-memory": "workspace:*",
"vitest": "0.34.6" "vitest": "1.6.0"
}, },
"scripts": { "scripts": {
"prepare": "husky install", "prepare": "husky install",

@ -0,0 +1,3 @@
{
"extends": "../../../.babelrc"
}

@ -0,0 +1,41 @@
# Plugin Generator
[![verdaccio (latest)](https://img.shields.io/npm/v/generator-verdaccio-plugin/latest.svg)](https://www.npmjs.com/package/generator-verdaccio-plugin)
[![verdaccio (downloads)](https://img.shields.io/npm/dy/generator-verdaccio-plugin.svg)](https://www.npmjs.com/package/generator-verdaccio-plugin)
[![docker pulls](https://img.shields.io/docker/pulls/verdaccio/verdaccio.svg?maxAge=43200)](https://verdaccio.org/docs/en/docker.html)
[![Backers](https://opencollective.com/verdaccio/tiers/backer/badge.svg?label=Backer&color=brightgreen)](https://opencollective.com/verdaccio)
[![Stackshare](https://img.shields.io/badge/Follow%20on-StackShare-blue.svg?logo=stackshare&style=flat)](https://stackshare.io/verdaccio)
[![Discord](https://img.shields.io/discord/388674437219745793?logo=discord)](http://chat.verdaccio.org/)
[![Twitter followers](https://img.shields.io/twitter/follow/verdaccio_npm.svg?style=social&label=Follow)](https://twitter.com/verdaccio_npm)
Verdaccio plugin generator based in [Yeoman](http://yeoman.io) aims to help to scaffold plugins development
## Installation
First, install [Yeoman](http://yeoman.io) and generator-verdaccio-plugin using [npm](https://www.npmjs.com/) (we assume you have pre-installed [node.js](https://nodejs.org/)).
```bash
npm install -g yo
npm install -g generator-verdaccio-plugin
```
Then generate your new project:
```bash
yo verdaccio-plugin
```
## Plugin Types Supported
- Authentication
- Storage
- Middleware
### Maintainers
- [Anix](https://github.com/anikethsaha)
- [Juan Picado](https://github.com/juanpicado)
## License
MIT © [Juan Picado <@jotadeveloper>]()

@ -0,0 +1,11 @@
const defaultConfigFiles = [
'jest.config.js',
'.editorconfig',
'.gitignore',
'package.json',
'README.md',
'.eslintrc',
'.npmignore',
];
module.exports = defaultConfigFiles;

@ -0,0 +1,3 @@
const config = require('../../../jest/config');
module.exports = Object.assign({}, config, {});

@ -0,0 +1,49 @@
{
"name": "generator-verdaccio-plugin",
"version": "4.1.0",
"description": "plugin generator for verdaccio",
"homepage": "https://github.com/verdaccio",
"author": {
"name": "Juan Picado <@jotadeveloper>",
"email": "juanpicado19@gmail.com",
"url": "https://github.com/verdaccio/generator-verdaccio-plugin"
},
"files": [
"generators"
],
"keywords": [
"verdaccio-plugin",
"yeoman-generator"
],
"dependencies": {
"chalk": "4.1.2",
"lodash": "4.17.21",
"yeoman-environment": "3.19.3",
"yeoman-generator": "5.9.0",
"yosay": "2.0.2",
"@verdaccio/core": "workspace:7.0.0-next-7.16",
"@verdaccio/config": "workspace:7.0.0-next-7.16"
},
"devDependencies": {
"@verdaccio/test-helper": "workspace:3.0.0-next-7.2",
"@verdaccio/types": "workspace:12.0.0-next-7.3",
"ts-jest": "29.1.0",
"yeoman-assert": "3.1.1",
"yeoman-test": "6.3.0"
},
"engines": {
"node": ">18.0.0"
},
"repository": {
"type": "git",
"url": "git://github.com/verdaccio/generator-verdaccio-plugin"
},
"scripts": {
"type-check": "tsc --noEmit -p tsconfig.build.json",
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
"build": "babel src/ --out-dir generators/ --copy-files --extensions \".ts,.tsx\" --source-maps --ignore src/app/templates",
"test": "vitest run --pool=forks",
"lint": "eslint --max-warnings 0 \"**/*.{js,ts}\""
},
"license": "MIT"
}

@ -0,0 +1,179 @@
import chalk from 'chalk';
import _ from 'lodash';
import { resolve } from 'path';
import Generator from 'yeoman-generator';
import yosay from 'yosay';
type propsTypes = {
name?: string;
pluginType?: string;
description?: string;
githubUsername?: string;
authorName?: string;
authorEmail?: string;
keywords?: string[];
};
class PluginGenerator extends Generator {
private props: propsTypes;
private projectName = 'verdaccio-';
private destinationPathName = 'verdaccio-';
constructor(args, opts) {
super(args, opts);
this.props = {};
}
prompting() {
this.log(yosay(`Welcome to ${chalk.red('generator-verdaccio-plugin')} plugin generator!`));
const prompts = [
{
type: 'list',
name: 'pluginType',
require: true,
message: 'What kind of plugin you want to create?',
store: true,
choices: [{ value: 'auth' }, { value: 'storage' }, { value: 'middleware' }],
},
{
type: 'input',
name: 'name',
require: true,
message: `What's the plugin name? The prefix (verdaccio-xxx) will be added automatically`,
default: 'customname',
validate: function (input: string) {
if (input.startsWith('verdaccio-')) {
return false;
} else if (input === '') {
return false;
}
return true;
},
},
{
type: 'input',
name: 'description',
message: 'Please, describe your plugin',
default: 'An amazing verdaccio plugin',
},
{
name: 'githubUsername',
message: 'GitHub username or Organization',
validate: function (input) {
return input !== '';
},
},
{
name: 'authorName',
message: "Author's Name",
store: true,
},
{
name: 'authorEmail',
message: "Author's Email",
store: true,
},
{
name: 'keywords',
message: 'Key your keywords (comma to split)',
filter: function (keywords) {
return _.uniq(_.words(keywords).concat(['verdaccio-']));
},
},
];
return this.prompt(prompts).then(
function (_props) {
// To access props later use this.props.someAnswer;
// @ts-ignore
this.props = _props;
const { name, githubUsername } = _props;
// @ts-ignore
this.props.license = 'MIT';
if (githubUsername) {
// @ts-ignore
this.props.repository = githubUsername + '/' + name;
}
// @ts-ignore
this.projectName = `verdaccio-${name}`;
// @ts-ignore
this.destinationPathName = resolve(this.projectName);
// @ts-ignore
this.props.name = this.projectName;
}.bind(this)
);
}
packageJSON() {
const { pluginType } = this.props;
const pkgJsonLocation = `${pluginType}/_package.json`;
this.fs.copyTpl(
this.templatePath(pkgJsonLocation),
this.destinationPath(resolve(this.destinationPathName, 'package.json')),
this.props
);
}
writing() {
this.fs.copy(
this.templatePath(`common/gitignore`),
this.destinationPath(resolve(this.destinationPathName, '.gitignore'))
);
this.fs.copy(
this.templatePath(`common/npmignore`),
this.destinationPath(resolve(this.destinationPathName, '.npmignore'))
);
this.fs.copy(
this.templatePath(`common/jest.config.js`),
this.destinationPath(resolve(this.destinationPathName, 'jest.config.js'))
);
this.fs.copyTpl(
this.templatePath(`common/README.md`),
this.destinationPath(resolve(this.destinationPathName, 'README.md')),
this.props
);
this.fs.copyTpl(
this.templatePath(`common/eslintrc`),
this.destinationPath(resolve(this.destinationPathName, '.eslintrc')),
this.props
);
this.fs.copyTpl(
this.templatePath(`common/eslintignore`),
this.destinationPath(resolve(this.destinationPathName, '.eslintignore')),
this.props
);
this.fs.copy(
this.templatePath(`${this.props.pluginType}/src`),
this.destinationPath(resolve(this.destinationPathName, 'src'))
);
this.fs.copy(
this.templatePath(`common/index.js`),
this.destinationPath(resolve(this.destinationPathName, `index.js`))
);
this.fs.copy(
this.templatePath(`common/tsconfig.json`),
this.destinationPath(resolve(this.destinationPathName, 'tsconfig.json'))
);
this.fs.copy(
this.templatePath(`${this.props.pluginType}/types`),
this.destinationPath(resolve(this.destinationPathName, 'types'))
);
this.fs.copy(
this.templatePath(`common/editorconfig`),
this.destinationPath(resolve(this.destinationPathName, '.editorconfig'))
);
}
install() {
process.chdir(this.projectName);
// this.installDependencies({ npm: true, bower: false });
}
}
export default PluginGenerator;

@ -0,0 +1,5 @@
{
"rules": {
"@typescript-eslint/no-unused-vars": 0
}
}

@ -0,0 +1,33 @@
{
"name": "<%= name %>",
"version": "0.0.1",
"description": "<%= description %>",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"engines": {
"node": ">=12"
},
"dependencies": {
"@verdaccio/commons-api": "10.2.0"
},
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "12.12.5",
"@types/express": "4.17.13",
"@typescript-eslint/eslint-plugin": "5.26.0",
"@typescript-eslint/parser": "5.26.0",
"@verdaccio/types": "10.5.2",
"eslint": "8.21.0",
"jest": "28.1.3",
"typescript": "4.7.4"
},
"keywords": ["<%= keywords %>]"],
"license": "<%= license %>",
"repository": "<%= repository %>",
"author": "<%= authorName %> <<%= authorEmail %>>",
"scripts": {
"build": "tsc",
"test": "jest .",
"lint": "eslint \"**/*.{js,ts}\""
}
}

@ -0,0 +1,92 @@
import { getInternalError } from '@verdaccio/commons-api';
import {
AuthAccessCallback,
AuthCallback,
IPluginAuth,
Logger,
PackageAccess,
PluginOptions,
RemoteUser,
} from '@verdaccio/types';
import { CustomConfig } from '../types/index';
/**
* Custom Verdaccio Authenticate Plugin.
*/
export default class AuthCustomPlugin implements IPluginAuth<CustomConfig> {
public logger: Logger;
private foo: string;
public constructor(config: CustomConfig, options: PluginOptions<CustomConfig>) {
this.logger = options.logger;
this.foo = config.foo;
return this;
}
/**
* Authenticate an user.
* @param user user to log
* @param password provided password
* @param cb callback function
*/
public authenticate(user: string, password: string, cb: AuthCallback): void {
/**
* This code is just an example for demostration purpose
if (this.foo) {
cb(null, ['group-foo', 'group-bar']);
} else {
cb(getInternalError("error, try again"), false);
}
*/
}
/**
* Triggered on each access request
* @param user
* @param pkg
* @param cb
*/
public allow_access(user: RemoteUser, pkg: PackageAccess, cb: AuthAccessCallback): void {
/**
* This code is just an example for demostration purpose
if (user.name === this.foo && pkg?.access?.includes[user.name]) {
this.logger.debug({name: user.name}, 'your package has been granted for @{name}');
cb(null, true)
} else {
this.logger.error({name: user.name}, '@{name} is not allowed to access this package');
cb(getInternalError("error, try again"), false);
}
*/
}
/**
* Triggered on each publish request
* @param user
* @param pkg
* @param cb
*/
public allow_publish(user: RemoteUser, pkg: PackageAccess, cb: AuthAccessCallback): void {
/**
* This code is just an example for demostration purpose
if (user.name === this.foo && pkg?.access?.includes[user.name]) {
this.logger.debug({name: user.name}, '@{name} has been granted to publish');
cb(null, true)
} else {
this.logger.error({name: user.name}, '@{name} is not allowed to publish this package');
cb(getInternalError("error, try again"), false);
}
*/
}
public allow_unpublish(user: RemoteUser, pkg: PackageAccess, cb: AuthAccessCallback): void {
/**
* This code is just an example for demostration purpose
if (user.name === this.foo && pkg?.access?.includes[user.name]) {
this.logger.debug({name: user.name}, '@{name} has been granted to unpublish');
cb(null, true)
} else {
this.logger.error({name: user.name}, '@{name} is not allowed to publish this package');
cb(getInternalError("error, try again"), false);
}
*/
}
}

@ -0,0 +1,5 @@
import { Config } from '@verdaccio/types';
export interface CustomConfig extends Config {
foo: string;
}

@ -0,0 +1,22 @@
# <%= name %>
<%- (description || '').split('\n').map(function (line) {
return '> ' + line
}).join('\n') %>
---
## development
See the [verdaccio contributing guide](https://github.com/verdaccio/verdaccio/blob/master/CONTRIBUTING.md) for instructions setting up your development environment.
Once you have completed that, use the following npm tasks.
- `npm run build`
Build a distributable archive
- `npm run test`
Run unit test
For more information about any of these commands run `npm run ${task} -- --help`.

@ -0,0 +1,12 @@
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# 2 space indentation
[{.,}*.{js,yml,yaml}]
indent_style = space
indent_size = 2

@ -0,0 +1,2 @@
node_modules
lib/

@ -0,0 +1,12 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
]
}

@ -0,0 +1,3 @@
npm-debug.log*
node_modules
/lib/

@ -0,0 +1,15 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
exports.default = void 0;
let _index = _interopRequireDefault(require('./lib/index'));
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
}
let _default = _index.default;
exports.default = _default;

@ -0,0 +1,4 @@
module.exports = {
name: 'verdaccio-<%= name %>',
preset: 'ts-jest',
};

@ -0,0 +1,2 @@
src/
.eslintrc

@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"declaration": true,
"allowJs": false,
"noImplicitAny": false,
"strict": true,
"outDir": "./lib",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
"include": ["src/*.ts", "types/*.ts"]
}

@ -0,0 +1,34 @@
{
"name": "<%= name %>",
"version": "0.0.1",
"description": "<%= description %>",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"engines": {
"node": ">=12"
},
"dependencies": {
"@verdaccio/commons-api": "10.2.0",
"express": "4.18.1"
},
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "12.12.5",
"@types/express": "4.17.13",
"@typescript-eslint/eslint-plugin": "5.26.0",
"@typescript-eslint/parser": "5.26.0",
"@verdaccio/types": "10.5.2",
"eslint": "8.21.0",
"jest": "28.1.3",
"typescript": "4.7.4"
},
"keywords": ["<%= keywords %>"],
"license": "<%= license %>",
"repository": "<%= repository %>",
"author": "<%= authorName %> <<%= authorEmail %>>",
"scripts": {
"build": "tsc",
"test": "jest .",
"lint": "eslint \"**/*.{js,ts}\""
}
}

@ -0,0 +1,42 @@
import { Application, NextFunction, Request, Response, Router } from 'express';
import {
IBasicAuth,
IPluginMiddleware,
IStorageManager,
Logger,
PluginOptions,
} from '@verdaccio/types';
import { CustomConfig } from '../types/index';
export default class VerdaccioMiddlewarePlugin implements IPluginMiddleware<CustomConfig> {
public logger: Logger;
public foo: string;
public constructor(config: CustomConfig, options: PluginOptions<CustomConfig>) {
this.foo = config.foo !== undefined ? config.strict_ssl : true;
this.logger = options.logger;
}
public register_middlewares(
app: Application,
auth: IBasicAuth<CustomConfig>,
/* eslint @typescript-eslint/no-unused-vars: off */
_storage: IStorageManager<CustomConfig>
): void {
/**
* This is just an example of implementation
// eslint new-cap:off
const router = Router();
router.post(
'/custom-endpoint',
(req: Request, res: Response & { report_error?: Function }, next: NextFunction): void => {
const encryptedString = auth.aesEncrypt(Buffer.from(this.foo, 'utf8'));
res.setHeader('X-Verdaccio-Token-Plugin', encryptedString.toString());
next();
}
);
app.use('/-/npm/something-new', router);
*/
}
}

@ -0,0 +1,5 @@
import { Config } from '@verdaccio/types';
export interface CustomConfig extends Config {
foo: string;
}

@ -0,0 +1,34 @@
{
"name": "<%= name %>",
"version": "0.0.1",
"description": "<%= description %>",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"engines": {
"node": ">=12"
},
"dependencies": {
"@verdaccio/commons-api": "10.2.0",
"@verdaccio/streams": "10.2.0"
},
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "12.12.5",
"@types/express": "4.17.13",
"@typescript-eslint/eslint-plugin": "5.32.0",
"@typescript-eslint/parser": "5.32.0",
"@verdaccio/types": "10.5.2",
"eslint": "8.21.0",
"jest": "28.1.3",
"typescript": "4.7.4"
},
"keywords": ["<%= keywords %>"],
"license": "<%= license %>",
"repository": "<%= repository %>",
"author": "<%= authorName %> <<%= authorEmail %>>",
"scripts": {
"build": "tsc",
"test": "jest .",
"lint": "eslint \"**/*.{js,ts}\""
}
}

@ -0,0 +1,175 @@
import { getConflict, getInternalError, getNotFound } from '@verdaccio/commons-api';
import { ReadTarball, UploadTarball } from '@verdaccio/streams';
import {
Callback,
CallbackAction,
ILocalPackageManager,
Logger,
Package,
PackageTransformer,
ReadPackageCallback,
StorageUpdateCallback,
StorageWriteCallback,
} from '@verdaccio/types';
import { CustomConfig } from '../types/index';
export default class StoragePluginManage implements ILocalPackageManager {
public logger: Logger;
public packageName: string;
public config: CustomConfig;
public constructor(config: CustomConfig, packageName: string, logger: Logger) {
this.logger = logger;
this.packageName = packageName;
this.config = config;
}
/**
* Handle a metadata update and
* @param name
* @param updateHandler
* @param onWrite
* @param transformPackage
* @param onEnd
*/
public updatePackage(
name: string,
updateHandler: StorageUpdateCallback,
onWrite: StorageWriteCallback,
transformPackage: PackageTransformer,
onEnd: CallbackAction
): void {
/**
* Example of implementation:
this.customStore.get().then((pkg: Package) => {
updateHandler(pkg, function onUpdateFinish(err) {
if (err) {
onEnd(err);
} else {
onWrite(name, pkg, onEnd);
}
})
});
*/
}
/**
* Delete a specific file (tarball or package.json)
* @param fileName
* @param callback
*/
public deletePackage(fileName: string, callback: CallbackAction): void {
/**
* Example of implementation:
this.customStore.delete(fileName, (err) => {
if (err) {
callback(err);
} else {
callback(null);
}
})
*/
}
/**
* Delete a package (folder, path)
* This happens after all versions ar tarballs have been removed.
* @param callback
*/
public removePackage(callback: CallbackAction): void {
/**
* Example of implementation:
this.customStore.removePackage((err) => {
if (err) {
callback(err);
} else {
callback(null);
}
})
*/
}
/**
* Publish a new package (version).
* @param name
* @param data
* @param callback
*/
public createPackage(name: string, data: Package, callback: CallbackAction): void {
/**
* Example of implementation:
* this.customStore.create(name, data).then(err => {
if (err.notFound) {
callback(getNotFound());
} else if (err.alreadyExist) {
callback(getConflict());
} else {
callback(null);
}
})
*/
}
/**
* Perform write anobject to the storage.
* Similar to updatePackage but without middleware handlers
* @param pkgName package name
* @param pkg package metadata
* @param callback
*/
public savePackage(pkgName: string, pkg: Package, callback: CallbackAction): void {
/*
Example of implementation:
this.cumstomStore.write(pkgName, pkgName).then(data => {
callback(null);
}).catch(err => {
callback(getInternalError(err.message));
})
*/
}
/**
* Read a package from storage
* @param pkgName package name
* @param callback
*/
public readPackage(pkgName: string, callback: ReadPackageCallback): void {
/**
* Example of implementation:
* this.customStorage.read(name, (err, pkg: Package) => {
if (err.fooError) {
callback(getInternalError(err))
} else if (err.barError) {
callback(getNotFound());
} else {
callback(null, pkg)
}
});
*/
}
/**
* Create writtable stream (write a tarball)
* @param name
*/
public writeTarball(name: string): UploadTarball {
/**
* Example of implementation:
* const stream = new UploadTarball({});
return stream;
*/
}
/**
* Create a readable stream (read a from a tarball)
* @param name
*/
public readTarball(name: string): ReadTarball {
/**
* Example of implementation:
* const stream = new ReadTarball({});
return stream;
*/
}
}

@ -0,0 +1 @@
export { default } from './plugin';

@ -0,0 +1,134 @@
import { getInternalError } from '@verdaccio/commons-api';
import {
Callback,
Config,
IPackageStorage,
IPluginStorage,
Logger,
PluginOptions,
Token,
TokenFilter,
onEndSearchPackage,
onSearchPackage,
onValidatePackage,
} from '@verdaccio/types';
import { CustomConfig } from '../types/index';
import PackageStorage from './PackageStorage';
export default class VerdaccioStoragePlugin implements IPluginStorage<CustomConfig> {
config: CustomConfig & Config;
version?: string;
public logger: Logger;
public constructor(config: CustomConfig, options: PluginOptions<CustomConfig>) {
this.config = config;
this.logger = options.logger;
}
/**
*
*/
public async getSecret(): Promise<string> {
/**
* return await resolveSecret();
*/
}
public async setSecret(secret: string): Promise<any> {
/**
* return await getYourSecret();
*/
}
/**
* Add a new element.
* @param {*} name
* @return {Error|*}
*/
public add(name: string, callback: Callback): void {}
/**
* Perform a search in your registry
* @param onPackage
* @param onEnd
* @param validateName
*/
public search(
onPackage: onSearchPackage,
onEnd: onEndSearchPackage,
validateName: onValidatePackage
): void {
/**
* Example of implementation:
* try {
* someApi.getPackages((items) => {
* items.map(() => {
* if (validateName(item.name)) {
* onPackage(item);
* }
* });
* onEnd();
* } catch(err) {
* onEnd(err);
* }
* });
*/
}
/**
* Remove an element from the database.
* @param {*} name
* @return {Error|*}
*/
public remove(name: string, callback: Callback): void {
/**
* Example of implementation
database.getPackage(name, (item, err) => {
if (err) {
callback(getInternalError('your own message here'));
}
// if all goes well we return nothing
callback(null);
}
*/
}
/**
* Return all database elements.
* @return {Array}
*/
public get(callback: Callback): void {
/*
Example of implementation
database.getAll((allItems, err) => {
callback(err, allItems);
})
*/
}
/**
* Create an instance of the `PackageStorage`
* @param packageInfo
*/
public getPackageStorage(packageInfo: string): IPackageStorage {
return new PackageStorage(this.config, packageInfo, this.logger);
}
/**
* All methods for npm token support
* more info here https://github.com/verdaccio/verdaccio/pull/1427
*/
public saveToken(token: Token): Promise<any> {
throw new Error('Method not implemented.');
}
public deleteToken(user: string, tokenKey: string): Promise<any> {
throw new Error('Method not implemented.');
}
public readTokens(filter: TokenFilter): Promise<Token[]> {
throw new Error('Method not implemented.');
}
}

@ -0,0 +1,5 @@
import { Config } from '@verdaccio/types';
export interface CustomConfig extends Config {
foo: string;
}

@ -0,0 +1,120 @@
import fs from 'fs';
import os from 'os';
import path from 'path';
import { beforeEach, describe, test } from 'vitest';
import assert from 'yeoman-assert';
import helpers from 'yeoman-test';
import constants from '../helpers/constants';
describe('template generator', function () {
// jest.setTimeout(10000);
const name = 'test';
const description = 'An amazing verdaccio plugin';
const githubUsername = 'testing';
const authorName = 'test';
const authorEmail = 'test';
const keywords = ['verdaccio, plugin, typescript'];
const license = 'MIT';
const repository = 'verdaccio/generator-test';
const getBuildAsset = (tempRoot, item) => {
const prefixPath = path.join(tempRoot, `/verdaccio-${name}`);
return `${prefixPath}/${item}`;
};
describe('generate app', function () {
let tempRoot;
beforeEach(() => {
tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'generator-app'));
});
const lang = 'typescript';
test('should check storage files', async function (done) {
helpers
.run(path.join(__dirname, '../src/app'))
.cd(tempRoot)
.withPrompts({
name,
lang,
pluginType: 'storage',
description,
githubUsername,
authorName,
authorEmail,
keywords,
license,
repository,
})
.then(function () {
assert.file([
...constants.map((item) => getBuildAsset(tempRoot, item)),
getBuildAsset(tempRoot, '/index.js'),
getBuildAsset(tempRoot, '/types/index.ts'),
getBuildAsset(tempRoot, '/tsconfig.json'),
getBuildAsset(tempRoot, '/src/index.ts'),
getBuildAsset(tempRoot, '/src/plugin.ts'),
getBuildAsset(tempRoot, '/src/PackageStorage.ts'),
]);
done();
});
});
test('should check auth files', function (done) {
helpers
.run(path.join(__dirname, '../src/app'))
.inDir(tempRoot)
.withPrompts({
name,
lang,
pluginType: 'auth',
description,
githubUsername,
authorName,
authorEmail,
keywords,
license,
repository,
})
.then(function () {
assert.file([
...constants.map((item) => getBuildAsset(tempRoot, item)),
getBuildAsset(tempRoot, '/src/index.ts'),
getBuildAsset(tempRoot, '/index.js'),
getBuildAsset(tempRoot, '/types/index.ts'),
getBuildAsset(tempRoot, '/tsconfig.json'),
]);
done();
});
});
test('should check middleware files', function (done) {
helpers
.run(path.join(__dirname, '../src/app'))
.inDir(tempRoot)
.withPrompts({
name,
lang,
pluginType: 'middleware',
description,
githubUsername,
authorName,
authorEmail,
keywords,
license,
repository,
})
.then(function () {
assert.file([
...constants.map((item) => getBuildAsset(tempRoot, item)),
getBuildAsset(tempRoot, '/src/index.ts'),
getBuildAsset(tempRoot, '/index.js'),
getBuildAsset(tempRoot, '/types/index.ts'),
getBuildAsset(tempRoot, '/tsconfig.json'),
]);
done();
});
});
});
});

@ -0,0 +1,10 @@
{
"extends": "../../../tsconfig.base",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./build",
"noImplicitAny": false
},
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.test.ts"]
}

@ -0,0 +1,17 @@
{
"extends": "../../../tsconfig.reference.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./build",
"noImplicitAny": false
},
"include": ["src/**/*.ts", "types/*.d.ts"],
"references": [
{
"path": "../config"
},
{
"path": "../utils"
}
]
}

2462
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff