First Commit
This commit is contained in:
commit
21d6ba5733
179
.gitignore
vendored
Normal file
179
.gitignore
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
|
||||||
|
logs
|
||||||
|
_.log
|
||||||
|
npm-debug.log_
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Caches
|
||||||
|
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
|
||||||
|
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
|
||||||
|
pids
|
||||||
|
_.pid
|
||||||
|
_.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
|
||||||
|
.temp
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
|
||||||
|
# IntelliJ based IDEs
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Finder (MacOS) folder config
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
/test
|
||||||
|
/lib-node
|
||||||
|
/dump
|
57
README.md
Normal file
57
README.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# Turbo Sync
|
||||||
|
|
||||||
|
A no-nonsense file/folder synchronization application
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Turbo sync requires **node js** and **rsync**
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --registry="https://git.tben.me/api/packages/Moduletrace/npm/" -g turbo-sync
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
turbo-sync ./turbosync.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Config File
|
||||||
|
|
||||||
|
The config file is a json file that contains all the information needed to run turbo-sync. Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Sync Files",
|
||||||
|
"files": [
|
||||||
|
"/home/user/file1.txt",
|
||||||
|
"/home/user/file2.txt",
|
||||||
|
{
|
||||||
|
"path": "/home/user/file3",
|
||||||
|
"user": "root",
|
||||||
|
"host": "5.34.75.236",
|
||||||
|
"ssh_key": "/home/user/.ssh/key"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Sync Folders",
|
||||||
|
"options": {
|
||||||
|
"delete": true
|
||||||
|
},
|
||||||
|
"folders": [
|
||||||
|
"/home/user/folder1",
|
||||||
|
"/home/user/folder2",
|
||||||
|
{
|
||||||
|
"path": "/home/user/folder3",
|
||||||
|
"user": "user",
|
||||||
|
"host": "5.39.67.76",
|
||||||
|
"ssh_key": "/home/user/.ssh/key"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
90
index.js
Normal file
90
index.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const { execSync, spawn, ChildProcess } = require("child_process");
|
||||||
|
|
||||||
|
/** @type {string[]} */
|
||||||
|
let dirs = [];
|
||||||
|
|
||||||
|
console.log("Running Folder Sync ...");
|
||||||
|
|
||||||
|
const defaultConfigFilePath = path.resolve(
|
||||||
|
process.cwd(),
|
||||||
|
"turbosync.config.json"
|
||||||
|
);
|
||||||
|
|
||||||
|
const confFileProvidedPath = process.argv[process.argv.length - 1];
|
||||||
|
const confFileComputedPath =
|
||||||
|
typeof confFileProvidedPath == "string" &&
|
||||||
|
confFileProvidedPath.endsWith(".json")
|
||||||
|
? path.resolve(process.cwd(), confFileProvidedPath)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (!fs.existsSync(defaultConfigFilePath) && !confFileComputedPath) {
|
||||||
|
console.log(
|
||||||
|
"Please Provide the path to a config file or add a config file named `turbosync.config.json` to the path you're running this program"
|
||||||
|
);
|
||||||
|
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!defaultConfigFilePath &&
|
||||||
|
confFileComputedPath &&
|
||||||
|
!fs.existsSync(confFileComputedPath)
|
||||||
|
) {
|
||||||
|
console.log("Config File does not exist");
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// /** @type {ChildProcess[]} */
|
||||||
|
// const childProcesses = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const configJSON = fs.existsSync(defaultConfigFilePath)
|
||||||
|
? fs.readFileSync(defaultConfigFilePath, "utf8")
|
||||||
|
: confFileComputedPath
|
||||||
|
? fs.readFileSync(confFileComputedPath, "utf8")
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (!configJSON)
|
||||||
|
throw new Error(
|
||||||
|
"Config JSON could not be resolved. Please check your files."
|
||||||
|
);
|
||||||
|
|
||||||
|
/** @type {TurboSyncConfigArray} */
|
||||||
|
const configArray = JSON.parse(configJSON);
|
||||||
|
|
||||||
|
for (let i = 0; i < configArray.length; i++) {
|
||||||
|
const config = configArray[i];
|
||||||
|
console.log(`Syncing \`${config.title} ...\``);
|
||||||
|
|
||||||
|
const childProcess = spawn(
|
||||||
|
"node",
|
||||||
|
[
|
||||||
|
path.resolve(__dirname, "./lib/sync.js"),
|
||||||
|
`${JSON.stringify(config)}`,
|
||||||
|
],
|
||||||
|
{
|
||||||
|
stdio: "inherit",
|
||||||
|
detached: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Process Error =>`, error.message);
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
console.log("Turbo Sync Running ...");
|
||||||
|
}, 60000);
|
||||||
|
|
||||||
|
// process.on("exit", () => {
|
||||||
|
// for (let i = 0; i < childProcesses.length; i++) {
|
||||||
|
// const childProcess = childProcesses[i];
|
||||||
|
// childProcess.kill("SIGTERM");
|
||||||
|
// }
|
||||||
|
// });
|
216
lib/sync.js
Normal file
216
lib/sync.js
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const { execSync, spawn } = require("child_process");
|
||||||
|
|
||||||
|
const confFileProvidedJSON = process.argv[process.argv.length - 1];
|
||||||
|
|
||||||
|
try {
|
||||||
|
/** @type {TurboSyncConfigObject} */
|
||||||
|
const configFileObject = JSON.parse(confFileProvidedJSON);
|
||||||
|
|
||||||
|
console.log(`Running '${configFileObject.title}' ...`);
|
||||||
|
|
||||||
|
if (
|
||||||
|
Array.isArray(configFileObject.files) &&
|
||||||
|
Array.isArray(configFileObject.folders)
|
||||||
|
) {
|
||||||
|
throw new Error("Choose wither `files` or `folders`. Not both");
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = configFileObject?.files;
|
||||||
|
const firstFile = files?.[0];
|
||||||
|
const folders = configFileObject?.folders;
|
||||||
|
const firstFolder = folders?.[0];
|
||||||
|
|
||||||
|
const options = configFileObject.options;
|
||||||
|
|
||||||
|
if (firstFile && files) {
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
const file = files[i];
|
||||||
|
const filePath =
|
||||||
|
typeof file == "string" ? file : file?.path ? file.path : null;
|
||||||
|
const interval = typeof file == "object" ? file.interval : null;
|
||||||
|
if (!filePath) continue;
|
||||||
|
|
||||||
|
if (typeof file == "string" && !fs.existsSync(filePath))
|
||||||
|
throw new Error("File Doesn't exist");
|
||||||
|
if (typeof file == "string" && !fs.statSync(filePath).isFile()) {
|
||||||
|
throw new Error(`'${filePath}' is not a File!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof file == "object" && file.host) {
|
||||||
|
// TODO Handle SSH
|
||||||
|
} else if (typeof file == "string") {
|
||||||
|
fs.watchFile(
|
||||||
|
filePath,
|
||||||
|
{
|
||||||
|
interval: interval || 500,
|
||||||
|
},
|
||||||
|
(curr, prev) => {
|
||||||
|
let cmdArray = ["rsync", "-avh"];
|
||||||
|
|
||||||
|
if (options?.delete) {
|
||||||
|
cmdArray.push("--delete");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.exclude?.[0]) {
|
||||||
|
options.exclude.forEach((excl) => {
|
||||||
|
cmdArray.push(`--exclude '${excl}'`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const destFiles = files.filter((fl) => {
|
||||||
|
if (typeof fl == "string") return fl !== filePath;
|
||||||
|
if (fl?.path) return fl.path !== filePath;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let j = 0; j < destFiles.length; j++) {
|
||||||
|
const dstFl = destFiles[j];
|
||||||
|
if (typeof dstFl == "string") {
|
||||||
|
if (!fs.existsSync(dstFl)) continue;
|
||||||
|
cmdArray.push(filePath, dstFl);
|
||||||
|
const cmd = cmdArray.join(" ");
|
||||||
|
execSync(cmd, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
} else if (dstFl.path) {
|
||||||
|
if (!dstFl.host && !fs.existsSync(dstFl.path))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (dstFl.host && dstFl.ssh_key && dstFl.user) {
|
||||||
|
cmdArray.push(
|
||||||
|
"-e",
|
||||||
|
`'ssh -i ${dstFl.ssh_key}'`
|
||||||
|
);
|
||||||
|
cmdArray.push(
|
||||||
|
filePath,
|
||||||
|
`${dstFl.user}@${dstFl.host}:${dstFl.path}`
|
||||||
|
);
|
||||||
|
const cmd = cmdArray.join(" ");
|
||||||
|
execSync(cmd, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cmdArray.push(filePath, dstFl.path);
|
||||||
|
const cmd = cmdArray.join(" ");
|
||||||
|
execSync(cmd, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (firstFolder && folders?.[0]) {
|
||||||
|
const dirs = folders;
|
||||||
|
|
||||||
|
for (let i = 0; i < dirs.length; i++) {
|
||||||
|
const dir = dirs[i];
|
||||||
|
|
||||||
|
if (!dir) continue;
|
||||||
|
|
||||||
|
const dirPath = typeof dir == "string" ? dir : dir.path;
|
||||||
|
|
||||||
|
if (typeof dir == "string") {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof dir == "string" && !fs.existsSync(dirPath)) {
|
||||||
|
fs.mkdirSync(dirPath, {
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof dir == "string") {
|
||||||
|
fs.watch(dirPath, { recursive: true }, (evt, fileName) => {
|
||||||
|
let cmdArray = ["rsync", "-avh"];
|
||||||
|
|
||||||
|
if (options?.delete) {
|
||||||
|
cmdArray.push("--delete");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.exclude?.[0]) {
|
||||||
|
options.exclude.forEach((excl) => {
|
||||||
|
cmdArray.push(`--exclude '${excl}'`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const dstDirs = dirs.filter((dr) => {
|
||||||
|
if (typeof dr == "string") return dr !== dirPath;
|
||||||
|
if (dr?.path) return dr.path !== dirPath;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let j = 0; j < dstDirs.length; j++) {
|
||||||
|
const dstDr = dstDirs[j];
|
||||||
|
if (typeof dstDr == "string") {
|
||||||
|
if (!fs.existsSync(dstDr)) continue;
|
||||||
|
cmdArray.push(
|
||||||
|
path.normalize(dirPath) + "/",
|
||||||
|
path.normalize(dstDr) + "/"
|
||||||
|
);
|
||||||
|
const cmd = cmdArray.join(" ");
|
||||||
|
execSync(cmd, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
} else if (dstDr.path) {
|
||||||
|
if (!dstDr.host && !fs.existsSync(dstDr.path))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (dstDr.host && dstDr.ssh_key && dstDr.user) {
|
||||||
|
cmdArray.push(
|
||||||
|
"-e",
|
||||||
|
`'ssh -i ${dstDr.ssh_key}'`
|
||||||
|
);
|
||||||
|
cmdArray.push(
|
||||||
|
path.normalize(dirPath) + "/",
|
||||||
|
`${dstDr.user}@${dstDr.host}:${dstDr.path}/`
|
||||||
|
);
|
||||||
|
const cmd = cmdArray.join(" ");
|
||||||
|
execSync(cmd, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cmdArray.push(
|
||||||
|
path.normalize(dirPath),
|
||||||
|
path.normalize(dstDr.path)
|
||||||
|
);
|
||||||
|
const cmd = cmdArray.join(" ");
|
||||||
|
execSync(cmd, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on("exit", (code) => {
|
||||||
|
if (code == 1) {
|
||||||
|
const args = process.argv;
|
||||||
|
const cmd = args.shift();
|
||||||
|
if (cmd) {
|
||||||
|
spawn(cmd, args, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
});
|
17
package-lock.json
generated
Normal file
17
package-lock.json
generated
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "turbo-sync",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "turbo-sync",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"turbo-sync": "index.js",
|
||||||
|
"turbosync": "index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
package.json
Normal file
18
package.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "turbo-sync",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"module": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node index.ts",
|
||||||
|
"build": "tsc",
|
||||||
|
"dev": "node index.js --watch"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"turbo-sync": "./index.js",
|
||||||
|
"turbosync": "./index.js"
|
||||||
|
},
|
||||||
|
"description": "To install dependencies:",
|
||||||
|
"main": "index.js",
|
||||||
|
"author": "Benjamin Toby",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
27
tsconfig.json
Normal file
27
tsconfig.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2015",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "dump/dist",
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
},
|
||||||
|
"include": ["index.ts", "index.d.ts", "**/*.ts"],
|
||||||
|
"exclude": ["dump"]
|
||||||
|
}
|
28
types.js
Normal file
28
types.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {TurboSyncConfigObject[]} TurboSyncConfigArray
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} TurboSyncConfigObject
|
||||||
|
* @property {string} [title]
|
||||||
|
* @property {string[] | TurboSyncFileObject[]} [files]
|
||||||
|
* @property {string[] | TurboSyncFileObject[]} [folders]
|
||||||
|
* @property {TurboSyncOptions} [options]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} TurboSyncFileObject
|
||||||
|
* @property {string} path
|
||||||
|
* @property {string} [host]
|
||||||
|
* @property {string} [user]
|
||||||
|
* @property {string} [ssh_key]
|
||||||
|
* @property {number} [interval]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} TurboSyncOptions
|
||||||
|
* @property {boolean} [delete] - Should files removed be deleted in all destinations?
|
||||||
|
* @property {string[]} [exclude] - Patterns that should be ignored. Eg "*.log"
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user