Repository: svtslv/webdav-cli
Branch: master
Commit: df1c73ce5ba8
Files: 21
Total size: 19.1 KB
Directory structure:
gitextract_2f2cjv2a/
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── README.md
├── certs/
│ ├── self-signed.cert.pem
│ └── self-signed.key.pem
├── index.d.ts
├── index.js
├── index.ts
├── package.json
├── src/
│ ├── index.ts
│ ├── webdav-cli.cli.ts
│ ├── webdav-cli.constants.ts
│ ├── webdav-cli.interfaces.ts
│ ├── webdav-cli.server.ts
│ └── webdav-cli.utils.ts
├── test/
│ ├── index.spec.ts
│ └── jest.config.json
├── tsconfig.build.json
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintignore
================================================
index.js
index.ts
index.d.ts
================================================
FILE: .eslintrc.js
================================================
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/@typescript-eslint',
],
root: true,
env: {
node: true,
jest: true,
},
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'semi': ['error', 'always'],
},
};
================================================
FILE: .gitignore
================================================
# compiled output
/dist
/node_modules
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# OS
.DS_Store
# Tests
/coverage
/.nyc_output
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
================================================
FILE: .prettierrc
================================================
{
"singleQuote": true,
"trailingComma": "all"
}
================================================
FILE: README.md
================================================
# WebDAV CLI
<a href="https://www.npmjs.com/package/webdav-cli"><img src="https://img.shields.io/npm/v/webdav-cli.svg" alt="NPM Version" /></a>
<a href="https://www.npmjs.com/package/webdav-cli"><img src="https://img.shields.io/npm/l/webdav-cli.svg" alt="Package License" /></a>
## Table of Contents
- [Description](#description)
- [Installation](#installation)
- [Examples](#examples)
- [TLS/SSL](#tlsssl)
- [License](#license)
## Description
A simple zero-configuration command-line webdav server
## Installation
#### Globally via `npm`
```bash
npm install --global webdav-cli
```
#### Running on-demand:
```bash
npx webdav-cli [options]
```
## Examples
```bash
npx webdav-cli --help
```
```bash
'usage: webdav-cli [options]',
'',
'options:',
' --path Path to folder [process.cwd()]',
' --host Host to use [127.0.0.1]',
' --port Port to use [1900]',
' --digest Enable digest authentication [basic]',
' --username Username for basic/digest authentication [random]',
' --password Password for basic/digest authentication [random]',
' --directory Show directory listings [false]',
' --autoIndex Display autoIndex [false]',
' --ssl Enable https [false]',
' --sslKey Path to ssl key file [self-signed]',
' --sslCert Path to ssl cert file [self-signed]',
' --help Print this list and exit',
' --version Print the version and exit.',
' --rights Comma separated values without spaces [all]', `
'all', 'canCreate', 'canDelete', 'canMove', 'canRename',
'canAppend', 'canWrite', 'canRead', 'canSource',
'canGetMimeType', 'canGetSize', 'canListLocks',
'canSetLock', 'canRemoveLock', 'canGetAvailableLocks',
'canGetLock', 'canAddChild', 'canRemoveChild',
'canGetChildren', 'canSetProperty', 'canGetProperty',
'canGetProperties', 'canRemoveProperty', 'canGetCreationDate',
'canGetLastModifiedDate', 'canGetWebName', 'canGetType'`,
'env:',
' WEBDAV_CLI_PATH, WEBDAV_CLI_HOST, WEBDAV_CLI_PORT,',
' WEBDAV_CLI_USERNAME, WEBDAV_CLI_PASSWORD, WEBDAV_CLI_DIGEST,',
' WEBDAV_CLI_SSL, WEBDAV_CLI_SSL_KEY, WEBDAV_CLI_SSL_CERT,',
' WEBDAV_CLI_DIRECTORY, WEBDAV_CLI_AUTO_INDEX, WEBDAV_CLI_RIGHTS',
' WEBDAV_CLI_DISABLE_AUTHENTICATION',
```
## TLS/SSL
First, you need to make sure that openssl is installed correctly, and you have `key.pem` and `cert.pem` files. You can generate them using this command:
```bash
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
```
Use `127.0.0.1` as value for `Common name` if you want to be able to install the certificate in your OS's root certificate store or browser so that it is trusted.
Then you need to run the server with `--ssl` for enabling SSL and `--sslKey=key.pem --sslCert=cert.pem` for your certificate files.
## License
MIT
================================================
FILE: certs/self-signed.cert.pem
================================================
-----BEGIN CERTIFICATE-----
MIIDOzCCAiOgAwIBAgIUMeTYKq547CQcDyNj5Sj5ZwcxDN8wDQYJKoZIhvcNAQEL
BQAwLTELMAkGA1UEBhMCVUExDTALBgNVBAgMBEt5aXYxDzANBgNVBAoMBnN2dHNs
djAeFw0yMDAzMDIyMjUxNDBaFw0zMDAyMjgyMjUxNDBaMC0xCzAJBgNVBAYTAlVB
MQ0wCwYDVQQIDARLeWl2MQ8wDQYDVQQKDAZzdnRzbHYwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDBxLjsrteSkjSsT+NnlDM8hJxDI7YGEMOwyJodTNT1
8raXt3iD0LKViqDCxHn5szuwdPo/YlY9o2g5z1xJn7QlzVdRAqtMoxFz9sj8vAqY
sAv/jvkJYlcwIamgJhYYmAZM0Lban2x2bDo5oeyUGjk8gtk0V6Y4sfgPm7uJpoE4
pNoFfTA7fN+JQZetaKLfsXazYvUjUn9QFS0AsLZX7mhx7t5ASDCuOmlVRqmD9xiX
x6oo8/qGC/sMTEnWeJzpGzyIKXpwMrN/oKxn3/JCgFcDKt+iIEhDQ6YJN23DVBIp
mayZ/PWuQ5g1cCWXqZQ7nEMGgW3cSo7xzKb4QNwDLgm/AgMBAAGjUzBRMB0GA1Ud
DgQWBBQz4DMPb30ovUO0zd+ECY4M5r1T9zAfBgNVHSMEGDAWgBQz4DMPb30ovUO0
zd+ECY4M5r1T9zAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBN
pE0Z3Jf3TSVCxygjh/ylrVLnXuUi3QbrXgKhXVA6a4qHIUnmcAzZCF2YKwZb2p4p
27+DDPGEvVd9nulN8hDQ561B4mggch1KuTZTW7X028AEFIns/+BQJj9v2YnAwn8L
IVnmhcqxaerLgKq4KRobLIPIxKeIPBcEcgBlDL244cMDnwOnYp7v5BYxN/s1L5OU
5wCGs6FEt6Nzcw8x777xvVxvAe6TRen0Y0PheCHkoELsJ1Q0UGZHFnXxUP3c3THD
WgGG3DuSoc4VNbSGz3yr+08YY2VgNJpYhSQUrBpNEjgeKHTtht1Vi20pb9inSxLj
kYXUCOt+RRoAqiulwFLy
-----END CERTIFICATE-----
================================================
FILE: certs/self-signed.key.pem
================================================
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBxLjsrteSkjSs
T+NnlDM8hJxDI7YGEMOwyJodTNT18raXt3iD0LKViqDCxHn5szuwdPo/YlY9o2g5
z1xJn7QlzVdRAqtMoxFz9sj8vAqYsAv/jvkJYlcwIamgJhYYmAZM0Lban2x2bDo5
oeyUGjk8gtk0V6Y4sfgPm7uJpoE4pNoFfTA7fN+JQZetaKLfsXazYvUjUn9QFS0A
sLZX7mhx7t5ASDCuOmlVRqmD9xiXx6oo8/qGC/sMTEnWeJzpGzyIKXpwMrN/oKxn
3/JCgFcDKt+iIEhDQ6YJN23DVBIpmayZ/PWuQ5g1cCWXqZQ7nEMGgW3cSo7xzKb4
QNwDLgm/AgMBAAECggEAbQFCFsP1OdtODnGSuD5C5JSlY4+/YoIj1FvFdx4133Z/
CbKI9X5+OGoYLflhtPsDZS0pambjpSE8DOl+PVy+d1Wg/U3HGAHUW6xFPQh73ZGL
7mR77K+J5OXLCvDiFUvQn336n9p3pdcUmj9hW5+0+zmQ/0UfmV1k80LkqXcl0rrP
wEWp8jY5+SzbM6btuPF2JF4vVtGp4sEBDO4ypCC2bypUbdM4FkoNzP9+rBoHFk1q
TqXa2o1eh3+Qmw3y+a/AXUR6pzYIxB3jLj6DOaHhz/BaKTccm+1PMEFyMIvx3Uy2
BzHD/db5V4gsIyMMiIeYjmBXc3aCfmNRpHg1Ywf6AQKBgQDmY4zfxZKAmYG2kud6
vT4k1iY2joesi4ei1n4BW50TjLOIus9NW1n5GAPdnCSOuCzn1Pyhqf11EqVW6nhf
mDHVmSDGSgj6gX2WuL1EWtBj7AAj30xVcL2VK23ZANpCvSEvkEaxxiKiQNdK3UZa
NuYAWTRXHqXdv1HJuv9BYsXQwQKBgQDXTwVvfGLF7fPJqHltBFINTarRYLUnczxw
UiS2ItFpOjeddPn4yHzru4QY5maqwajrhHzSe4KWKXAe7Tup1af6cDyBEsyYEI+i
I+OJfcZBrjDpolKWulipCI5gR4CK80V/pkCBg5BCinWOExP8zkXD3xhU9SbGjLw+
7LJUMe/6fwKBgQDOfb0+twMW1f8nl0V3gfQX6gR384lwweJAtcRcDTOc2Qf07ZJt
wAnFM5wLXS566GH/K6t+bjCoZJziaOaYr31C96sjbinb9IGOvGeOw2JxnI2HmVT+
YzzYXQNoctYs6Py8d7CVF4PlLv6HsAmlQ/0jpNA/oU2CkT6J81tizFeGQQKBgGFx
JeiaxqkFU/vD/5BTED9tEw3HUrUT9hpvUqYLg/K3okvkkO0C72ZQayxJudU16BkO
0N8Bfswu3MtiWko2o9s3yGox894uQJME4wlqnrtC9mgGSpJkq5N0h9sTAR3hk2Z9
+1uiCzvSJfmysK0NPY2z/fMVMANT1i40OVDZeN5JAoGBAMgeJgeP8+K7Z0ecd4TL
QONJ9j27mLsHCjSpxdaM98xM7Dw82KxQ4SJ74ZB0LPbSLtkhJhorRmXsAMCDih4Q
BGyGnC11c8h1qRCuu2evXkXn6gK8OLcZxZJGTe/3vNR/hn1HCYlAX/sjEyaVVCbL
bluIUqnVB577qS3yfxP9dWhu
-----END PRIVATE KEY-----
================================================
FILE: index.d.ts
================================================
export * from './dist';
================================================
FILE: index.js
================================================
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
exports.__esModule = true;
__export(require("./dist"));
================================================
FILE: index.ts
================================================
export * from './dist';
================================================
FILE: package.json
================================================
{
"name": "webdav-cli",
"version": "2.0.0",
"description": "A simple zero-configuration command-line webdav server",
"author": "Sviatoslav H",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/svtslv/webdav-cli"
},
"keywords": [
"cli",
"command",
"webdav",
"server"
],
"files": [
"dist",
"certs",
"index.js",
"index.d.ts"
],
"bin": {
"webdav-cli": "./dist/webdav-cli.cli.js"
},
"preferGlobal": true,
"main": "dist/index.js",
"scripts": {
"fix": "rm -rf node_modules && rm package-lock.json && npm install",
"build": "rm -rf dist && tsc -p tsconfig.build.json",
"format": "prettier --write \"**/*.ts\"",
"lint": "eslint 'lib/**/*.ts' --fix",
"test": "jest --config ./test/jest.config.json --runInBand",
"prepublish:npm": "npm run build",
"publish:npm": "npm publish --access public",
"prepublish:test": "npm run build",
"publish:test": "npm publish --access public --tag test",
"prerelease": "npm run build",
"release": "release-it"
},
"dependencies": {
"chalk": "^4.0.0",
"figlet": "^1.3.0",
"minimist": "^1.2.5",
"webdav-server": "^2.6.2"
},
"devDependencies": {
"@types/figlet": "^1.2.0",
"@types/jest": "^26.0.5",
"@types/minimist": "^1.2.0",
"@types/node": "^13.9.1",
"@types/supertest": "^2.0.8",
"@typescript-eslint/eslint-plugin": "^2.24.0",
"@typescript-eslint/parser": "^2.24.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.1",
"jest": "^26.1.0",
"prettier": "^1.19.1",
"reflect-metadata": "^0.1.13",
"release-it": "^15.5.0",
"supertest": "^4.0.2",
"ts-jest": "^26.1.3",
"ts-loader": "^9.4.2",
"ts-node": "^8.6.2",
"tsconfig-paths": "^3.9.0",
"typescript": "^3.8.3"
}
}
================================================
FILE: src/index.ts
================================================
export * from './webdav-cli.constants';
export * from './webdav-cli.interfaces';
export * from './webdav-cli.server';
export * from './webdav-cli.utils';
================================================
FILE: src/webdav-cli.cli.ts
================================================
#!/usr/bin/env node
import * as chalk from 'chalk';
import * as figlet from 'figlet';
import * as minimist from 'minimist';
import { WebdavCli } from './webdav-cli.server';
import { HOMEPAGE } from './webdav-cli.constants';
const argv = minimist(process.argv.slice(2));
console.log(chalk.green(figlet.textSync('webdav-cli', { horizontalLayout: 'full' })));
console.log(chalk.green(`Homepage: ${ HOMEPAGE }\n`));
if (argv.help) {
console.log([
'usage: webdav-cli [options]',
'',
'options:',
' --path Path to folder [process.cwd()]',
' --host Host to use [127.0.0.1]',
' --port Port to use [1900]',
' --digest Enable digest authentication [basic]',
' --username Username for basic/digest authentication [random]',
' --password Password for basic/digest authentication [random]',
' --directory Show directory listings [false]',
' --autoIndex Display autoIndex [false]',
' --ssl Enable https [false]',
' --sslKey Path to ssl key file [self-signed]',
' --sslCert Path to ssl cert file [self-signed]',
' --help Print this list and exit',
' --version Print the version and exit.',
' --rights Comma separated values without spaces [all]', `
'all', 'canCreate', 'canDelete', 'canMove', 'canRename',
'canAppend', 'canWrite', 'canRead', 'canSource',
'canGetMimeType', 'canGetSize', 'canListLocks',
'canSetLock', 'canRemoveLock', 'canGetAvailableLocks',
'canGetLock', 'canAddChild', 'canRemoveChild',
'canGetChildren', 'canSetProperty', 'canGetProperty',
'canGetProperties', 'canRemoveProperty', 'canGetCreationDate',
'canGetLastModifiedDate', 'canGetWebName', 'canGetType'`,
'',
'env:',
' WEBDAV_CLI_PATH, WEBDAV_CLI_HOST, WEBDAV_CLI_PORT,',
' WEBDAV_CLI_USERNAME, WEBDAV_CLI_PASSWORD, WEBDAV_CLI_DIGEST,',
' WEBDAV_CLI_SSL, WEBDAV_CLI_SSL_KEY, WEBDAV_CLI_SSL_CERT,',
' WEBDAV_CLI_DIRECTORY, WEBDAV_CLI_AUTO_INDEX, WEBDAV_CLI_RIGHTS',
' WEBDAV_CLI_DISABLE_AUTHENTICATION',
'',
].join('\n'));
process.exit();
}
if (argv.version) {
console.log('Version: ' + require('../package.json').version, '\n');
process.exit();
}
const argvRights = argv.rights && typeof argv.rights === 'string' ? argv.rights.split(',') : undefined;
const envRights = process.env.WEBDAV_CLI_RIGHTS ? process.env.WEBDAV_CLI_RIGHTS.split(',') : undefined;
const config = {
path: argv.path || process.env.WEBDAV_CLI_PATH,
host: argv.host || process.env.WEBDAV_CLI_HOST,
port: argv.port || parseInt(process.env.WEBDAV_CLI_PORT),
digest: argv.digest || Boolean(process.env.WEBDAV_CLI_DIGEST),
username: argv.username || process.env.WEBDAV_CLI_USERNAME,
password: argv.password || process.env.WEBDAV_CLI_PASSWORD,
directory: argv.directory || process.env.WEBDAV_CLI_DIRECTORY,
autoIndex: argv.autoIndex || process.env.WEBDAV_CLI_AUTO_INDEX,
ssl: argv.ssl || Boolean(process.env.WEBDAV_CLI_SSL),
sslKey: argv.sslKey || process.env.WEBDAV_CLI_SSL_KEY,
sslCert: argv.sslCert || process.env.WEBDAV_CLI_SSL_CERT,
disableAuthentication: argv.disableAuthentication || process.env.WEBDAV_CLI_DISABLE_AUTHENTICATION,
rights: (argvRights || envRights) as any,
};
const run = async() => {
const webdavCli = new WebdavCli(config);
const webdavCliServer = await webdavCli.start();
webdavCliServer.on('log', (ctx, fs, path, log) => console.log(log));
};
run();
================================================
FILE: src/webdav-cli.constants.ts
================================================
import { WebdavCliRights } from './webdav-cli.interfaces';
export const HOMEPAGE = 'https://github.com/svtslv/webdav-cli';
export const RIGHTS: WebdavCliRights = [
'all', 'canCreate', 'canDelete', 'canMove', 'canRename',
'canAppend', 'canWrite', 'canRead', 'canSource',
'canGetMimeType', 'canGetSize', 'canListLocks',
'canSetLock', 'canRemoveLock', 'canGetAvailableLocks',
'canGetLock', 'canAddChild', 'canRemoveChild',
'canGetChildren', 'canSetProperty', 'canGetProperty',
'canGetProperties', 'canRemoveProperty', 'canGetCreationDate',
'canGetLastModifiedDate', 'canGetWebName', 'canGetType',
];
================================================
FILE: src/webdav-cli.interfaces.ts
================================================
import { BasicPrivilege, v2 as webdav } from 'webdav-server';
export type WebdavCliRights = BasicPrivilege[];
export interface WebdavCliConfig {
path: string,
host: string,
port: number,
digest: boolean,
username: string,
password: string,
ssl: boolean,
sslKey: string,
sslCert: string,
rights: WebdavCliRights,
disableAuthentication?: boolean,
url?: string,
directory?: boolean,
autoIndex?: boolean,
}
export interface WebdavCliServer extends webdav.WebDAVServer {
config: WebdavCliConfig,
}
================================================
FILE: src/webdav-cli.server.ts
================================================
import * as fs from 'fs';
import { join } from 'path';
import { v2 as webdav } from 'webdav-server';
import { getRandomString } from './webdav-cli.utils';
import { RIGHTS } from './webdav-cli.constants';
import { WebdavCliServer, WebdavCliConfig, WebdavCliRights } from './webdav-cli.interfaces';
export class WebdavCli {
config: WebdavCliConfig;
constructor(config: Partial<WebdavCliConfig>) {
this.config = this.getConfig(config);
}
getConfig(config: Partial<WebdavCliConfig>): WebdavCliConfig {
const selfSignedKey = join(__dirname, '/../certs/self-signed.key.pem');
const selfSignedCert = join(__dirname, '/../certs/self-signed.cert.pem');
const path = config.path || process.cwd();
const host = config.host || '127.0.0.1';
const port = config.port || 1900;
const digest = Boolean(config.digest);
let username = (config.username || getRandomString(16)).toString();
let password = (config.password || getRandomString(16)).toString();
const ssl = Boolean(config.ssl);
const sslKey = ssl ? fs.readFileSync(config.sslKey || selfSignedKey).toString() : '';
const sslCert = ssl ? fs.readFileSync(config.sslCert || selfSignedCert).toString() : '';
const disableAuthentication = Boolean(config.disableAuthentication);
if(disableAuthentication) {
config.rights = config.rights || ['canRead'];
username = '';
password = '';
}
const rights = (config.rights || ['all']).filter((item: WebdavCliRights[number]) => RIGHTS.includes(item));
const url = `${ ssl ? 'https' : 'http' }://${ host }:${ port }`;
const directory = Boolean(config.directory);
const autoIndex = Boolean(config.autoIndex);
return {
host, path, port, username, digest, password, ssl, sslCert,
sslKey, rights, url, disableAuthentication, directory, autoIndex,
};
}
async start(): Promise<WebdavCliServer> {
const config = this.config;
const userManager = new webdav.SimpleUserManager();
const user = userManager.addUser(config.username, config.password, false);
const privilegeManager = new webdav.SimplePathPrivilegeManager();
privilegeManager.setRights(user, '/', config.rights);
const authentication = config.digest ? 'HTTPDigestAuthentication' : 'HTTPBasicAuthentication';
const server = new webdav.WebDAVServer({
httpAuthentication: config.disableAuthentication ? {
askForAuthentication: () => ({}),
getUser: (ctx, gotUserCallback) => {
userManager.getDefaultUser((defaultUser) => {
privilegeManager.setRights(defaultUser, '/', config.rights);
gotUserCallback(null, defaultUser);
});
}
} : new webdav[authentication](userManager, 'Default realm'),
privilegeManager: privilegeManager,
https: config.ssl ? { cert: config.sslCert, key: config.sslKey } : null,
port: config.port,
hostname: config.host,
}) as WebdavCliServer;
server.config = config;
server.beforeRequest(async (ctx, next) => {
if (config.directory) {
const isBrowser = ctx.request.headers['user-agent'].search('Mozilla/5.0') !== -1;
if(isBrowser) {
try {
const resource = await server.getResourceAsync(ctx, ctx.requested.uri);
const list = await resource.readDirAsync();
const uri = ctx.requested.uri.slice(-1) === '/' ? ctx.requested.uri : ctx.requested.uri + '/';
if(config.autoIndex && list.includes('index.html')) {
ctx.requested.path = `${uri}index.html` as any;
} else {
const up = `<a href="${ uri.split('/').slice(0, -2).join('/') || '/' }">..</a><br/>`;
const html = up + list.map(item => `<a href="${ uri + item }">${ item }</a><br/>`).join('');
// ctx.response.setHeader('Content-Type', 'text/html;charset=UTF-8');
ctx.response.end(`<html><head><meta charset="UTF-8"></head><body>${html}</body></html>`);
}
} catch {}
}
}
next();
});
server.afterRequest((arg, next) => {
const log = `>> ${ arg.request.method } ${ arg.requested.uri } > ${ arg.response.statusCode } ${ arg.response.statusMessage }`;
server.emit('log', null, null, '/', log);
next();
});
await server.setFileSystemAsync('/', new webdav.PhysicalFileSystem(config.path));
await server.startAsync(config.port);
const logs = [
`Server running at ${ config.url }`,
`[rights]: ${ config.rights }`,
`[digest]: ${ config.digest }`,
`username: ${ config.username }`,
`password: ${ config.password }`,
'Hit CTRL-C to stop the server',
'Run with --help to print help'
];
console.log(logs.join('\n'));
return server;
}
}
================================================
FILE: src/webdav-cli.utils.ts
================================================
export function getRandomString(length: number) {
return [...Array(Math.ceil(length / 8))].map(() => Math.random().toString(36).slice(-8)).join('').slice(-length);
}
================================================
FILE: test/index.spec.ts
================================================
import * as index from '../src/index';
describe('Index', () => {
test('should return 4 exports', () => {
expect(Object.keys(index)).toHaveLength(4);
});
});
================================================
FILE: test/jest.config.json
================================================
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
}
}
================================================
FILE: tsconfig.build.json
================================================
{
"extends": "./tsconfig.json",
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
}
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2017",
"sourceMap": false,
"outDir": "./dist",
"baseUrl": "./",
"skipLibCheck": true
},
"include": ["src/**/*", "test/**/*"],
"exclude": ["node_modules", "dist"]
}
gitextract_2f2cjv2a/ ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── README.md ├── certs/ │ ├── self-signed.cert.pem │ └── self-signed.key.pem ├── index.d.ts ├── index.js ├── index.ts ├── package.json ├── src/ │ ├── index.ts │ ├── webdav-cli.cli.ts │ ├── webdav-cli.constants.ts │ ├── webdav-cli.interfaces.ts │ ├── webdav-cli.server.ts │ └── webdav-cli.utils.ts ├── test/ │ ├── index.spec.ts │ └── jest.config.json ├── tsconfig.build.json └── tsconfig.json
SYMBOL INDEX (11 symbols across 5 files)
FILE: index.js
function __export (line 2) | function __export(m) {
FILE: src/webdav-cli.constants.ts
constant HOMEPAGE (line 3) | const HOMEPAGE = 'https://github.com/svtslv/webdav-cli';
constant RIGHTS (line 5) | const RIGHTS: WebdavCliRights = [
FILE: src/webdav-cli.interfaces.ts
type WebdavCliRights (line 3) | type WebdavCliRights = BasicPrivilege[];
type WebdavCliConfig (line 5) | interface WebdavCliConfig {
type WebdavCliServer (line 22) | interface WebdavCliServer extends webdav.WebDAVServer {
FILE: src/webdav-cli.server.ts
class WebdavCli (line 8) | class WebdavCli {
method constructor (line 11) | constructor(config: Partial<WebdavCliConfig>) {
method getConfig (line 15) | getConfig(config: Partial<WebdavCliConfig>): WebdavCliConfig {
method start (line 51) | async start(): Promise<WebdavCliServer> {
FILE: src/webdav-cli.utils.ts
function getRandomString (line 1) | function getRandomString(length: number) {
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (21K chars).
[
{
"path": ".eslintignore",
"chars": 28,
"preview": "index.js\nindex.ts\nindex.d.ts"
},
{
"path": ".eslintrc.js",
"chars": 632,
"preview": "module.exports = {\n parser: '@typescript-eslint/parser',\n parserOptions: {\n project: 'tsconfig.json',\n sourceTyp"
},
{
"path": ".gitignore",
"chars": 375,
"preview": "# compiled output\n/dist\n/node_modules\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*"
},
{
"path": ".prettierrc",
"chars": 51,
"preview": "{\n \"singleQuote\": true,\n \"trailingComma\": \"all\"\n}"
},
{
"path": "README.md",
"chars": 2945,
"preview": "# WebDAV CLI\n\n<a href=\"https://www.npmjs.com/package/webdav-cli\"><img src=\"https://img.shields.io/npm/v/webdav-cli.svg\" "
},
{
"path": "certs/self-signed.cert.pem",
"chars": 1180,
"preview": "-----BEGIN CERTIFICATE-----\nMIIDOzCCAiOgAwIBAgIUMeTYKq547CQcDyNj5Sj5ZwcxDN8wDQYJKoZIhvcNAQEL\nBQAwLTELMAkGA1UEBhMCVUExDTA"
},
{
"path": "certs/self-signed.key.pem",
"chars": 1704,
"preview": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBxLjsrteSkjSs\nT+NnlDM8hJxDI7YGEMOwyJodTNT"
},
{
"path": "index.d.ts",
"chars": 24,
"preview": "export * from './dist';\n"
},
{
"path": "index.js",
"chars": 167,
"preview": "\"use strict\";\nfunction __export(m) {\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\n}\nexports._"
},
{
"path": "index.ts",
"chars": 24,
"preview": "export * from './dist';\n"
},
{
"path": "package.json",
"chars": 1875,
"preview": "{\n \"name\": \"webdav-cli\",\n \"version\": \"2.0.0\",\n \"description\": \"A simple zero-configuration command-line webdav server"
},
{
"path": "src/index.ts",
"chars": 153,
"preview": "export * from './webdav-cli.constants';\nexport * from './webdav-cli.interfaces';\nexport * from './webdav-cli.server';\nex"
},
{
"path": "src/webdav-cli.cli.ts",
"chars": 3465,
"preview": "#!/usr/bin/env node\n\nimport * as chalk from 'chalk';\nimport * as figlet from 'figlet';\nimport * as minimist from 'minimi"
},
{
"path": "src/webdav-cli.constants.ts",
"chars": 614,
"preview": "import { WebdavCliRights } from './webdav-cli.interfaces';\n\nexport const HOMEPAGE = 'https://github.com/svtslv/webdav-cl"
},
{
"path": "src/webdav-cli.interfaces.ts",
"chars": 525,
"preview": "import { BasicPrivilege, v2 as webdav } from 'webdav-server';\n\nexport type WebdavCliRights = BasicPrivilege[];\n\nexport i"
},
{
"path": "src/webdav-cli.server.ts",
"chars": 4814,
"preview": "import * as fs from 'fs';\nimport { join } from 'path';\nimport { v2 as webdav } from 'webdav-server';\nimport { getRandomS"
},
{
"path": "src/webdav-cli.utils.ts",
"chars": 167,
"preview": "export function getRandomString(length: number) {\n return [...Array(Math.ceil(length / 8))].map(() => Math.random().toS"
},
{
"path": "test/index.spec.ts",
"chars": 165,
"preview": "import * as index from '../src/index';\n\ndescribe('Index', () => {\n test('should return 4 exports', () => {\n expect(O"
},
{
"path": "test/jest.config.json",
"chars": 178,
"preview": "{\n \"moduleFileExtensions\": [\"js\", \"json\", \"ts\"],\n \"rootDir\": \".\",\n \"testEnvironment\": \"node\",\n \"testRegex\": \".spec.t"
},
{
"path": "tsconfig.build.json",
"chars": 97,
"preview": "{\n \"extends\": \"./tsconfig.json\",\n \"exclude\": [\"node_modules\", \"test\", \"dist\", \"**/*spec.ts\"]\n}\n"
},
{
"path": "tsconfig.json",
"chars": 378,
"preview": "{\n \"compilerOptions\": {\n \"module\": \"commonjs\",\n \"declaration\": true,\n \"removeComments\": true,\n \"emitDecorat"
}
]
About this extraction
This page contains the full source code of the svtslv/webdav-cli GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 21 files (19.1 KB), approximately 7.0k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.