@datatruck/cli 0.30.1 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Action/BackupAction.js +4 -8
- package/Action/ConfigAction.d.ts +1 -0
- package/Action/ConfigAction.js +8 -7
- package/Action/CopyAction.js +1 -1
- package/Action/RestoreAction.js +1 -1
- package/CHANGELOG.md +22 -0
- package/Command/BackupCommand.d.ts +1 -1
- package/Command/CleanCacheCommand.d.ts +1 -1
- package/Command/CommandAbstract.d.ts +2 -1
- package/Command/CommandAbstract.js +3 -1
- package/Command/CopyCommand.d.ts +1 -1
- package/Command/RestoreCommand.d.ts +1 -1
- package/Command/StartServerCommand.js +31 -8
- package/Config/Config.d.ts +7 -1
- package/Config/Config.js +79 -26
- package/Config/RepositoryConfig.d.ts +1 -0
- package/Config/RepositoryConfig.js +6 -1
- package/Factory/CommandFactory.d.ts +1 -1
- package/Factory/CommandFactory.js +2 -2
- package/JsonSchema/backup-def.d.ts +30 -0
- package/JsonSchema/backup-def.js +18 -0
- package/JsonSchema/copy-def.d.ts +24 -0
- package/JsonSchema/copy-def.js +15 -0
- package/Task/ScriptTask.d.ts +2 -11
- package/Task/ScriptTask.js +27 -33
- package/cli.js +1 -1
- package/config.schema.json +227 -40
- package/package.json +5 -4
- package/pkg.d.ts +6 -0
- package/pkg.js +10 -0
- package/utils/cli.d.ts +4 -1
- package/utils/cli.js +23 -3
- package/utils/datatruck/client.js +3 -3
- package/utils/datatruck/cron-server.d.ts +23 -0
- package/utils/datatruck/cron-server.js +59 -0
- package/utils/datatruck/paths.js +4 -6
- package/utils/datatruck/{server.d.ts → repository-server.d.ts} +12 -5
- package/utils/datatruck/{server.js → repository-server.js} +48 -26
- package/utils/fs.js +19 -18
- package/utils/http.d.ts +8 -2
- package/utils/http.js +12 -14
- package/utils/object.d.ts +1 -1
- package/utils/object.js +6 -6
- package/utils/schema.d.ts +34 -0
- package/utils/schema.js +36 -0
- package/utils/steps.d.ts +10 -10
- package/utils/steps.js +22 -8
- package/utils/string.d.ts +0 -3
- package/utils/string.js +22 -42
- package/utils/ObjectVault.d.ts +0 -13
- package/utils/ObjectVault.js +0 -29
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { IncomingMessage } from "http";
|
|
3
3
|
type User = {
|
|
4
|
+
enabled?: boolean;
|
|
4
5
|
name: string;
|
|
5
6
|
password: string;
|
|
6
7
|
};
|
|
7
|
-
export type
|
|
8
|
-
|
|
9
|
-
log?: boolean;
|
|
8
|
+
export type DatatruckRepositoryServerOptions = {
|
|
9
|
+
enabled?: boolean;
|
|
10
10
|
listen?: {
|
|
11
11
|
port?: number;
|
|
12
12
|
address?: string;
|
|
13
13
|
};
|
|
14
|
-
users?: User[];
|
|
15
14
|
trustProxy?: true | {
|
|
16
15
|
remoteAddressHeader: string;
|
|
17
16
|
};
|
|
@@ -22,10 +21,18 @@ export type DatatruckServerOptions = {
|
|
|
22
21
|
enabled?: boolean;
|
|
23
22
|
remoteAddresses?: string[];
|
|
24
23
|
};
|
|
24
|
+
backends?: {
|
|
25
|
+
name: string;
|
|
26
|
+
path: string;
|
|
27
|
+
users?: User[];
|
|
28
|
+
}[];
|
|
25
29
|
};
|
|
26
30
|
export declare const headerKey: {
|
|
27
31
|
user: string;
|
|
28
32
|
password: string;
|
|
29
33
|
};
|
|
30
|
-
export declare function
|
|
34
|
+
export declare function createDatatruckRepositoryServer(inOptions: Omit<DatatruckRepositoryServerOptions, "listen">, config?: {
|
|
35
|
+
log?: boolean;
|
|
36
|
+
configPath?: string;
|
|
37
|
+
}): import("node:http").Server<typeof IncomingMessage, typeof import("node:http").ServerResponse>;
|
|
31
38
|
export {};
|
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.createDatatruckRepositoryServer = exports.headerKey = void 0;
|
|
4
|
+
const ConfigAction_1 = require("../../Action/ConfigAction");
|
|
4
5
|
const http_1 = require("../http");
|
|
5
6
|
const virtual_fs_1 = require("../virtual-fs");
|
|
6
7
|
const fs_1 = require("fs");
|
|
7
8
|
const promises_1 = require("fs/promises");
|
|
8
9
|
const http_2 = require("http");
|
|
9
|
-
|
|
10
|
+
exports.headerKey = {
|
|
11
|
+
user: "x-dtt-user",
|
|
12
|
+
password: "x-dtt-password",
|
|
13
|
+
};
|
|
14
|
+
function parseUrl(inUrl, repositoryPrefix = "repo") {
|
|
10
15
|
const url = new URL(`http://127.0.0.1${inUrl}`);
|
|
11
16
|
const inParams = url.searchParams.get("params");
|
|
12
|
-
const action = url.pathname.slice(1);
|
|
13
|
-
if (
|
|
17
|
+
const [prefix, repository, action] = url.pathname.slice(1).split("/");
|
|
18
|
+
if (prefix !== repositoryPrefix) {
|
|
19
|
+
return { repository: undefined, action: undefined, params: [] };
|
|
20
|
+
}
|
|
21
|
+
else if (typeof inParams === "string") {
|
|
14
22
|
const params = JSON.parse(inParams);
|
|
15
23
|
if (!Array.isArray(params))
|
|
16
24
|
throw new Error(`Invalid params`);
|
|
17
|
-
return { action, params };
|
|
25
|
+
return { repository, action, params };
|
|
18
26
|
}
|
|
19
27
|
else {
|
|
20
|
-
return { action, params: [] };
|
|
28
|
+
return { repository, action, params: [] };
|
|
21
29
|
}
|
|
22
30
|
}
|
|
23
|
-
|
|
24
|
-
user: "x-dtt-user",
|
|
25
|
-
password: "x-dtt-password",
|
|
26
|
-
};
|
|
27
|
-
function validateRequest(req, options) {
|
|
31
|
+
function findRepositoryBackend(req, repository, options) {
|
|
28
32
|
const list = options.allowlist;
|
|
29
33
|
if (list && (list.enabled ?? true) && list.remoteAddresses) {
|
|
30
34
|
const remoteAddress = getRemoteAddress(req, options);
|
|
@@ -35,7 +39,15 @@ function validateRequest(req, options) {
|
|
|
35
39
|
const password = req.headers[exports.headerKey.password]?.toString().trim();
|
|
36
40
|
if (!name?.length || !password?.length)
|
|
37
41
|
return;
|
|
38
|
-
|
|
42
|
+
const backend = options.backends?.find((e) => e.name === repository);
|
|
43
|
+
if (!backend)
|
|
44
|
+
return;
|
|
45
|
+
const user = backend.users?.find((user) => user.name === name && user.password === password);
|
|
46
|
+
if (!user)
|
|
47
|
+
return;
|
|
48
|
+
if (!(user.enabled ?? true))
|
|
49
|
+
return;
|
|
50
|
+
return backend;
|
|
39
51
|
}
|
|
40
52
|
const getRemoteAddress = (req, options) => {
|
|
41
53
|
return ((options.trustProxy
|
|
@@ -44,24 +56,34 @@ const getRemoteAddress = (req, options) => {
|
|
|
44
56
|
: req.headers[options.trustProxy.remoteAddressHeader]?.toString()
|
|
45
57
|
: undefined) ?? req.socket.remoteAddress);
|
|
46
58
|
};
|
|
47
|
-
function
|
|
48
|
-
const log = options.log ?? true;
|
|
59
|
+
function createDatatruckRepositoryServer(inOptions, config = {}) {
|
|
49
60
|
return (0, http_2.createServer)(async (req, res) => {
|
|
50
61
|
try {
|
|
51
|
-
if (req.url === "/" || req.url === "/favicon.ico")
|
|
62
|
+
if (req.url === "/" || req.url === "/favicon.ico")
|
|
63
|
+
return res.end();
|
|
64
|
+
const { repository, action, params } = parseUrl(req.url);
|
|
65
|
+
if (!repository || !action) {
|
|
66
|
+
res.statusCode = 404;
|
|
52
67
|
return res.end();
|
|
53
68
|
}
|
|
54
|
-
|
|
69
|
+
const fileOptions = config.configPath
|
|
70
|
+
? (await ConfigAction_1.ConfigAction.parseFile(config.configPath)).server?.repository
|
|
71
|
+
: undefined;
|
|
72
|
+
const options = fileOptions ?? inOptions;
|
|
73
|
+
const backend = findRepositoryBackend(req, repository, options);
|
|
74
|
+
if (!backend) {
|
|
55
75
|
res.statusCode = 401;
|
|
56
76
|
return res.end();
|
|
57
77
|
}
|
|
58
|
-
if (log)
|
|
59
|
-
console.info(`> ${req.url}`);
|
|
78
|
+
if (config.log)
|
|
79
|
+
console.info(`> [repository] ${repository} - ${req.url}`);
|
|
60
80
|
const fs = new virtual_fs_1.LocalFs({
|
|
61
|
-
backend:
|
|
81
|
+
backend: backend.path,
|
|
62
82
|
});
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
if (action === "comcheck") {
|
|
84
|
+
res.write(JSON.stringify({ success: true }));
|
|
85
|
+
}
|
|
86
|
+
else if (action === "upload") {
|
|
65
87
|
const [target] = params;
|
|
66
88
|
const path = fs.resolvePath(target);
|
|
67
89
|
const file = (0, fs_1.createWriteStream)(path);
|
|
@@ -99,17 +121,17 @@ function createDatatruckServer(options) {
|
|
|
99
121
|
if (json !== undefined)
|
|
100
122
|
res.write(JSON.stringify(json));
|
|
101
123
|
}
|
|
102
|
-
if (log)
|
|
103
|
-
console.info(
|
|
124
|
+
if (config.log)
|
|
125
|
+
console.info(`< [repository] ${repository} - ${action}`);
|
|
104
126
|
res.end();
|
|
105
127
|
}
|
|
106
128
|
catch (error) {
|
|
107
|
-
if (log)
|
|
108
|
-
console.error(
|
|
129
|
+
if (config.log)
|
|
130
|
+
console.error(`< [repository] ${req.url}`, error);
|
|
109
131
|
res.statusCode = 500;
|
|
110
132
|
res.statusMessage = error.message;
|
|
111
133
|
res.end();
|
|
112
134
|
}
|
|
113
135
|
});
|
|
114
136
|
}
|
|
115
|
-
exports.
|
|
137
|
+
exports.createDatatruckRepositoryServer = createDatatruckRepositoryServer;
|
package/utils/fs.js
CHANGED
|
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.asFile = exports.groupFiles = exports.ensureFreeDiskSpace = exports.checkFreeDiskSpace = exports.fetchDiskStats = exports.initEmptyDir = exports.tryRm = exports.safeRename = exports.fetchData = exports.countFileLines = exports.createWriteStreamPool = exports.createFileScanner = exports.createProgress = exports.cpy = exports.isNotFoundError = exports.updateFileStats = exports.copyFileWithStreams = exports.waitForClose = exports.writeGitIgnoreList = exports.fastglobToGitIgnore = exports.forEachFile = exports.readDir = exports.readPartialFile = exports.fastFolderSizeAsync = exports.findFile = exports.parsePackageFile = exports.parseFile = exports.parseFileExtensions = exports.writeJSONFile = exports.existsFile = exports.existsDir = exports.safeStat = exports.ensureExistsDir = exports.ensureSingleFile = exports.ensureEmptyDir = exports.mkdirIfNotExists = exports.isLocalDir = exports.isEmptyDir = exports.isWSLSystem = void 0;
|
|
7
|
+
const pkg_1 = require("../pkg");
|
|
7
8
|
const bytes_1 = require("./bytes");
|
|
8
9
|
const math_1 = require("./math");
|
|
9
|
-
const path_1 = require("./path");
|
|
10
10
|
const string_1 = require("./string");
|
|
11
11
|
const temp_1 = require("./temp");
|
|
12
12
|
const async_1 = require("async");
|
|
@@ -16,8 +16,8 @@ const fs_1 = require("fs");
|
|
|
16
16
|
const fs_2 = require("fs");
|
|
17
17
|
const promises_1 = require("fs/promises");
|
|
18
18
|
const os_1 = require("os");
|
|
19
|
+
const path_1 = require("path");
|
|
19
20
|
const path_2 = require("path");
|
|
20
|
-
const path_3 = require("path");
|
|
21
21
|
const readline_1 = require("readline");
|
|
22
22
|
const util_1 = require("util");
|
|
23
23
|
exports.isWSLSystem = (0, os_1.release)().includes("microsoft-standard-WSL");
|
|
@@ -59,12 +59,12 @@ async function ensureSingleFile(path) {
|
|
|
59
59
|
if (files.length !== 1)
|
|
60
60
|
throw new Error(`Dir has not one file: ${files.length}`);
|
|
61
61
|
const [file] = files;
|
|
62
|
-
return (0,
|
|
62
|
+
return (0, path_1.join)(path, file);
|
|
63
63
|
}
|
|
64
64
|
exports.ensureSingleFile = ensureSingleFile;
|
|
65
65
|
async function ensureExistsDir(path) {
|
|
66
66
|
if (!(await existsDir(path)))
|
|
67
|
-
throw new Error(`Dir is not
|
|
67
|
+
throw new Error(`Dir is not created: ${path}`);
|
|
68
68
|
}
|
|
69
69
|
exports.ensureExistsDir = ensureExistsDir;
|
|
70
70
|
async function safeStat(path) {
|
|
@@ -88,10 +88,11 @@ async function writeJSONFile(path, json) {
|
|
|
88
88
|
exports.writeJSONFile = writeJSONFile;
|
|
89
89
|
exports.parseFileExtensions = ["json", "js", "ts", "yaml", "yml"];
|
|
90
90
|
async function parseFile(path, jsKey) {
|
|
91
|
-
if (!(0,
|
|
92
|
-
path = (0,
|
|
91
|
+
if (!(0, path_2.isAbsolute)(path))
|
|
92
|
+
path = (0, path_1.join)(process.cwd(), path);
|
|
93
|
+
const $require = require;
|
|
93
94
|
if (path.endsWith(".ts"))
|
|
94
|
-
require("ts-node").register();
|
|
95
|
+
$require("ts-node").register();
|
|
95
96
|
if (path.endsWith(".yaml") || path.endsWith("yml")) {
|
|
96
97
|
const contents = await (0, promises_1.readFile)(path);
|
|
97
98
|
return require("yaml").parse(contents.toString());
|
|
@@ -107,7 +108,7 @@ async function parseFile(path, jsKey) {
|
|
|
107
108
|
}
|
|
108
109
|
exports.parseFile = parseFile;
|
|
109
110
|
function parsePackageFile() {
|
|
110
|
-
return
|
|
111
|
+
return pkg_1.pkg;
|
|
111
112
|
}
|
|
112
113
|
exports.parsePackageFile = parsePackageFile;
|
|
113
114
|
async function findFile(sourcePath, baseName, extensions, errorMessage = "Path not found") {
|
|
@@ -115,7 +116,7 @@ async function findFile(sourcePath, baseName, extensions, errorMessage = "Path n
|
|
|
115
116
|
let path;
|
|
116
117
|
if (info.isDirectory()) {
|
|
117
118
|
for (const ext of extensions) {
|
|
118
|
-
const extPath = (0,
|
|
119
|
+
const extPath = (0, path_1.join)(sourcePath, baseName) + "." + ext;
|
|
119
120
|
if (await existsFile(extPath)) {
|
|
120
121
|
path = extPath;
|
|
121
122
|
break;
|
|
@@ -183,7 +184,7 @@ exports.readDir = readDir;
|
|
|
183
184
|
async function forEachFile(dirPath, cb, includeDir) {
|
|
184
185
|
const files = await readDir(dirPath);
|
|
185
186
|
for (const file of files) {
|
|
186
|
-
const filePath = (0,
|
|
187
|
+
const filePath = (0, path_1.join)(dirPath, file);
|
|
187
188
|
if ((await (0, promises_1.stat)(filePath)).isDirectory()) {
|
|
188
189
|
if (includeDir)
|
|
189
190
|
cb(filePath, true);
|
|
@@ -206,12 +207,12 @@ function fastglobToGitIgnore(patterns, baseDir) {
|
|
|
206
207
|
exports.fastglobToGitIgnore = fastglobToGitIgnore;
|
|
207
208
|
async function writeGitIgnoreList(options) {
|
|
208
209
|
const { outDir } = options;
|
|
209
|
-
const path = (0,
|
|
210
|
+
const path = (0, path_1.join)(outDir, `.gitignore`);
|
|
210
211
|
const stream = (0, fs_2.createWriteStream)(path);
|
|
211
212
|
const dirs = new Set();
|
|
212
213
|
stream.write("*\n");
|
|
213
214
|
for await (const value of options.paths) {
|
|
214
|
-
const dir = (0,
|
|
215
|
+
const dir = (0, path_1.dirname)(value.toString());
|
|
215
216
|
if (dir !== ".") {
|
|
216
217
|
let parentPath;
|
|
217
218
|
for (const value of dir.split("/")) {
|
|
@@ -290,9 +291,9 @@ async function cpy(options) {
|
|
|
290
291
|
const task = async (rawEntryPath, basePath) => {
|
|
291
292
|
[rawEntryPath] = rawEntryPath.split(":");
|
|
292
293
|
const isDir = rawEntryPath.endsWith("/");
|
|
293
|
-
const entryPath = (0,
|
|
294
|
-
const entrySourcePath = (0,
|
|
295
|
-
const entryTargetPath = (0,
|
|
294
|
+
const entryPath = (0, path_1.normalize)(rawEntryPath);
|
|
295
|
+
const entrySourcePath = (0, path_1.resolve)((0, path_1.join)(basePath, rawEntryPath));
|
|
296
|
+
const entryTargetPath = (0, path_1.resolve)((0, path_1.join)(options.outPath, rawEntryPath));
|
|
296
297
|
const onPathResult = await options?.onPath?.({
|
|
297
298
|
isDir,
|
|
298
299
|
entryPath,
|
|
@@ -307,7 +308,7 @@ async function cpy(options) {
|
|
|
307
308
|
await makeRecursiveDir(entryTargetPath);
|
|
308
309
|
}
|
|
309
310
|
else {
|
|
310
|
-
const dir = (0,
|
|
311
|
+
const dir = (0, path_1.dirname)(entryTargetPath);
|
|
311
312
|
await makeRecursiveDir(dir);
|
|
312
313
|
await options.onProgress?.({
|
|
313
314
|
current: stats.files,
|
|
@@ -447,7 +448,7 @@ function createWriteStreamPool(options) {
|
|
|
447
448
|
const item = {
|
|
448
449
|
key,
|
|
449
450
|
lines: 0,
|
|
450
|
-
stream: (0, fs_2.createWriteStream)((0,
|
|
451
|
+
stream: (0, fs_2.createWriteStream)((0, path_1.join)(options.path, options.onStreamPath ? options.onStreamPath(key) : key)),
|
|
451
452
|
finished: false,
|
|
452
453
|
};
|
|
453
454
|
item.stream
|
|
@@ -612,7 +613,7 @@ exports.groupFiles = groupFiles;
|
|
|
612
613
|
async function asFile(input) {
|
|
613
614
|
if (typeof input === "string") {
|
|
614
615
|
const dir = await (0, temp_1.mkTmpDir)("text-as-file");
|
|
615
|
-
const path = (0,
|
|
616
|
+
const path = (0, path_1.join)(dir, "contents.txt");
|
|
616
617
|
await (0, promises_1.writeFile)(path, input);
|
|
617
618
|
return [
|
|
618
619
|
path,
|
package/utils/http.d.ts
CHANGED
|
@@ -3,10 +3,16 @@ import { BasicProgress } from "./progress";
|
|
|
3
3
|
import { IncomingMessage, Server } from "http";
|
|
4
4
|
export declare function closeServer(server: Server): Promise<void>;
|
|
5
5
|
export declare function readRequestData(req: IncomingMessage): Promise<string | undefined>;
|
|
6
|
-
export
|
|
6
|
+
export type FetchOptions = {
|
|
7
7
|
headers?: Record<string, string>;
|
|
8
8
|
query?: Record<string, string>;
|
|
9
|
-
|
|
9
|
+
statusError?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function fetch(url: string, options?: FetchOptions): Promise<{
|
|
12
|
+
data: string | undefined;
|
|
13
|
+
status: number | undefined;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function fetchJson<T = any>(url: string, options?: FetchOptions): Promise<T | undefined>;
|
|
10
16
|
export declare function post(url: string, data: string, options?: {
|
|
11
17
|
headers?: Record<string, string>;
|
|
12
18
|
query?: Record<string, string>;
|
package/utils/http.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.uploadFile = exports.downloadFile = exports.post = exports.fetchJson = exports.readRequestData = exports.closeServer = void 0;
|
|
3
|
+
exports.uploadFile = exports.downloadFile = exports.post = exports.fetchJson = exports.fetch = exports.readRequestData = exports.closeServer = void 0;
|
|
4
4
|
const math_1 = require("./math");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const promises_1 = require("fs/promises");
|
|
@@ -37,14 +37,15 @@ function readRequestData(req) {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
exports.readRequestData = readRequestData;
|
|
40
|
-
async function
|
|
40
|
+
async function fetch(url, options = {}) {
|
|
41
|
+
const throwStatusCodeError = options.statusError ?? true;
|
|
41
42
|
return new Promise((resolve, reject) => {
|
|
42
43
|
let data;
|
|
43
44
|
request(href(url, options.query), {
|
|
44
45
|
method: "GET",
|
|
45
46
|
headers: options.headers,
|
|
46
47
|
}, (res) => {
|
|
47
|
-
if (res.statusCode !== 200)
|
|
48
|
+
if (throwStatusCodeError && res.statusCode !== 200)
|
|
48
49
|
return reject(new Error(`GET failed: ${res.statusCode} ${res.statusMessage}`));
|
|
49
50
|
res
|
|
50
51
|
.on("data", (chunk) => {
|
|
@@ -54,23 +55,20 @@ async function fetchJson(url, options = {}) {
|
|
|
54
55
|
})
|
|
55
56
|
.on("error", reject)
|
|
56
57
|
.on("close", () => {
|
|
57
|
-
|
|
58
|
-
resolve(undefined);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
try {
|
|
62
|
-
resolve(JSON.parse(data));
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
reject(error);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
58
|
+
resolve({ data, status: res.statusCode });
|
|
68
59
|
});
|
|
69
60
|
})
|
|
70
61
|
.on("error", reject)
|
|
71
62
|
.end();
|
|
72
63
|
});
|
|
73
64
|
}
|
|
65
|
+
exports.fetch = fetch;
|
|
66
|
+
async function fetchJson(url, options = {}) {
|
|
67
|
+
const res = await fetch(url, options);
|
|
68
|
+
if (res.data === undefined)
|
|
69
|
+
return;
|
|
70
|
+
return JSON.parse(res.data);
|
|
71
|
+
}
|
|
74
72
|
exports.fetchJson = fetchJson;
|
|
75
73
|
async function post(url, data, options = {}) {
|
|
76
74
|
await new Promise((resolve, reject) => {
|
package/utils/object.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare function merge<T extends Record<string, unknown>>(target: T, ...sources: Record<string, unknown>[]): T;
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function omitProp<T extends Record<string, any>, N extends keyof T>(object: T, name: N): Omit<T, N>;
|
|
3
3
|
export declare function getErrorProperties(error: Error): Record<string, string>;
|
|
4
4
|
type GroupByKeyParamType<TItem> = ((item: TItem) => string[] | string) | (keyof TItem)[] | keyof TItem;
|
|
5
5
|
export declare function groupBy<TItem>(items: TItem[], keyOrCb: GroupByKeyParamType<TItem>): Record<string, TItem[]>;
|
package/utils/object.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.groupBy = exports.getErrorProperties = exports.
|
|
3
|
+
exports.groupBy = exports.getErrorProperties = exports.omitProp = exports.merge = void 0;
|
|
4
4
|
function merge(target, ...sources) {
|
|
5
5
|
const isObject = (o) => typeof o === "object" && o !== null;
|
|
6
6
|
for (const source of sources)
|
|
@@ -13,12 +13,12 @@ function merge(target, ...sources) {
|
|
|
13
13
|
return target;
|
|
14
14
|
}
|
|
15
15
|
exports.merge = merge;
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
function omitProp(object, name) {
|
|
17
|
+
const result = { ...object };
|
|
18
|
+
delete result[name];
|
|
19
|
+
return result;
|
|
20
20
|
}
|
|
21
|
-
exports.
|
|
21
|
+
exports.omitProp = omitProp;
|
|
22
22
|
function getErrorProperties(error) {
|
|
23
23
|
const alt = {};
|
|
24
24
|
for (const key of Object.getOwnPropertyNames(error)) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { JSONSchema7 } from "json-schema";
|
|
2
|
+
export declare function omitPropertySchema<T extends {
|
|
3
|
+
properties: Record<string, any>;
|
|
4
|
+
}, N extends keyof T["properties"]>(object: T, name: N): Omit<T, "properties"> & {
|
|
5
|
+
properties: Omit<T["properties"], N>;
|
|
6
|
+
};
|
|
7
|
+
type IfSchema<KType extends string, KValue extends string, T extends string, V extends JSONSchema7> = {
|
|
8
|
+
if: {
|
|
9
|
+
type: "object";
|
|
10
|
+
properties: {
|
|
11
|
+
[k in KType]: {
|
|
12
|
+
const: T;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
then: {
|
|
17
|
+
type: "object";
|
|
18
|
+
properties: {
|
|
19
|
+
[k in KValue]: V;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
else: false;
|
|
23
|
+
};
|
|
24
|
+
export declare function createCaseSchema<KType extends string, KValue extends string, V extends {
|
|
25
|
+
[K in KType]: JSONSchema7;
|
|
26
|
+
}>(keys: {
|
|
27
|
+
type: KType;
|
|
28
|
+
value: KValue;
|
|
29
|
+
}, value: V): IfSchema<KType, KValue, string, JSONSchema7>[];
|
|
30
|
+
export declare function createIfSchema<KType extends string, KValue extends string, T extends string, V extends JSONSchema7>(keys: {
|
|
31
|
+
type: KType;
|
|
32
|
+
value: KValue;
|
|
33
|
+
}, type: T, value: V): IfSchema<KType, KValue, T, V>;
|
|
34
|
+
export {};
|
package/utils/schema.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createIfSchema = exports.createCaseSchema = exports.omitPropertySchema = void 0;
|
|
4
|
+
const object_1 = require("./object");
|
|
5
|
+
function omitPropertySchema(object, name) {
|
|
6
|
+
return {
|
|
7
|
+
...object,
|
|
8
|
+
properties: (0, object_1.omitProp)(object.properties, name),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
exports.omitPropertySchema = omitPropertySchema;
|
|
12
|
+
function createCaseSchema(keys, value) {
|
|
13
|
+
return Object.entries(value).reduce((schemas, [type, value]) => {
|
|
14
|
+
schemas.push(createIfSchema(keys, type, value));
|
|
15
|
+
return schemas;
|
|
16
|
+
}, []);
|
|
17
|
+
}
|
|
18
|
+
exports.createCaseSchema = createCaseSchema;
|
|
19
|
+
function createIfSchema(keys, type, value) {
|
|
20
|
+
return {
|
|
21
|
+
if: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {
|
|
24
|
+
[keys.type]: { const: type },
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
then: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
[keys.value]: value,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
else: false,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
exports.createIfSchema = createIfSchema;
|
package/utils/steps.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ export type TelegramMessageStepConfig = {
|
|
|
14
14
|
chatId: number;
|
|
15
15
|
text?: string;
|
|
16
16
|
};
|
|
17
|
+
export type NtfyStepConfig = {
|
|
18
|
+
token: string;
|
|
19
|
+
topic?: string;
|
|
20
|
+
text?: string;
|
|
21
|
+
};
|
|
17
22
|
export type Step = {
|
|
18
23
|
type: "process";
|
|
19
24
|
config: ProcessStepConfig;
|
|
@@ -23,20 +28,15 @@ export type Step = {
|
|
|
23
28
|
} | {
|
|
24
29
|
type: "telegram-message";
|
|
25
30
|
config: TelegramMessageStepConfig;
|
|
31
|
+
} | {
|
|
32
|
+
type: "ntfy";
|
|
33
|
+
config: NtfyStepConfig;
|
|
26
34
|
};
|
|
27
35
|
export type StepOptions = {
|
|
28
36
|
env?: Record<string, string | undefined>;
|
|
29
|
-
|
|
30
|
-
vars?: Record<string, string | undefined>;
|
|
31
|
-
};
|
|
32
|
-
node?: {
|
|
33
|
-
vars?: Record<string, any>;
|
|
34
|
-
tempDir?: () => Promise<string>;
|
|
35
|
-
};
|
|
36
|
-
telegram?: {
|
|
37
|
-
vars?: Record<string, string>;
|
|
38
|
-
};
|
|
37
|
+
vars?: Record<string, any>;
|
|
39
38
|
cwd?: string;
|
|
39
|
+
tempDir?: () => Promise<string>;
|
|
40
40
|
onLine?: (p: string) => any;
|
|
41
41
|
verbose?: boolean;
|
|
42
42
|
};
|
package/utils/steps.js
CHANGED
|
@@ -9,9 +9,10 @@ const promises_1 = require("fs/promises");
|
|
|
9
9
|
const path_1 = require("path");
|
|
10
10
|
async function runSteps(input, options) {
|
|
11
11
|
const steps = Array.isArray(input) ? input : [input];
|
|
12
|
+
const vars = options?.vars || {};
|
|
12
13
|
for (const step of steps) {
|
|
13
14
|
if (step.type === "process") {
|
|
14
|
-
await (0, process_1.exec)(step.config.command, (step.config.args || []).map((v) => (0, string_1.render)(v,
|
|
15
|
+
await (0, process_1.exec)(step.config.command, (step.config.args || []).map((v) => (0, string_1.render)(v, vars)), {
|
|
15
16
|
cwd: options.cwd,
|
|
16
17
|
env: {
|
|
17
18
|
...process.env,
|
|
@@ -30,19 +31,19 @@ async function runSteps(input, options) {
|
|
|
30
31
|
}
|
|
31
32
|
else if (step.type === "node") {
|
|
32
33
|
let tempDir;
|
|
33
|
-
if (options
|
|
34
|
-
tempDir = await options.
|
|
34
|
+
if (options?.tempDir) {
|
|
35
|
+
tempDir = await options.tempDir();
|
|
35
36
|
}
|
|
36
37
|
else {
|
|
37
38
|
tempDir = await (0, temp_1.mkTmpDir)("node-step");
|
|
38
39
|
}
|
|
39
40
|
const scriptPath = (0, path_1.join)(tempDir, "script.js");
|
|
40
|
-
const
|
|
41
|
+
const nodeVars = {
|
|
41
42
|
...step.config.vars,
|
|
42
|
-
...
|
|
43
|
+
...vars,
|
|
43
44
|
};
|
|
44
|
-
const varKeys = Object.keys(
|
|
45
|
-
const varJson = JSON.stringify(
|
|
45
|
+
const varKeys = Object.keys(nodeVars);
|
|
46
|
+
const varJson = JSON.stringify(nodeVars);
|
|
46
47
|
const code = Array.isArray(step.config.code)
|
|
47
48
|
? [...step.config.code].join(";\n")
|
|
48
49
|
: step.config.code;
|
|
@@ -67,7 +68,7 @@ async function runSteps(input, options) {
|
|
|
67
68
|
else if (step.type === "telegram-message") {
|
|
68
69
|
await (0, http_1.post)(`https://api.telegram.org/bot${step.config.bot}/sendMessage`, JSON.stringify({
|
|
69
70
|
chat_id: step.config.chatId.toString(),
|
|
70
|
-
text: (0, string_1.render)(step.config.text ?? `{
|
|
71
|
+
text: (0, string_1.render)(step.config.text ?? `{dtt.text}`, vars),
|
|
71
72
|
disable_notification: true,
|
|
72
73
|
}), {
|
|
73
74
|
headers: {
|
|
@@ -75,6 +76,19 @@ async function runSteps(input, options) {
|
|
|
75
76
|
},
|
|
76
77
|
});
|
|
77
78
|
}
|
|
79
|
+
else if (step.type === "ntfy") {
|
|
80
|
+
const topic = [step.config.token, step.config.topic]
|
|
81
|
+
.filter(Boolean)
|
|
82
|
+
.join("-");
|
|
83
|
+
if (topic.length < 32)
|
|
84
|
+
throw new Error(`Topic is less than 32 characters: ${topic}`);
|
|
85
|
+
await (0, http_1.post)(`https://ntfy.sh/${topic}`, (0, string_1.render)(step.config.text ?? `{dtt.text}`, vars), {
|
|
86
|
+
headers: {
|
|
87
|
+
Title: (0, string_1.render)("{dtt.title}", vars),
|
|
88
|
+
Priority: vars.success ? "default" : "high",
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
78
92
|
else {
|
|
79
93
|
throw new Error(`Invalid step type: ${step.type}`);
|
|
80
94
|
}
|
package/utils/string.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export declare function serialize(message: string, data?: Object): string;
|
|
2
1
|
export declare function snakeCase(value: string, char?: string): string;
|
|
3
2
|
export declare function render(subject: string, vars: Record<string, string | undefined>): string;
|
|
4
3
|
type NoInfer<T> = [T][T extends any ? 0 : never];
|
|
@@ -12,12 +11,10 @@ export type UriType = {
|
|
|
12
11
|
path?: string;
|
|
13
12
|
};
|
|
14
13
|
export declare function formatUri(input: UriType, hidePassword?: boolean): string;
|
|
15
|
-
export declare function formatSeconds(seconds: number): string;
|
|
16
14
|
export declare function makePathPatterns(values: string[] | undefined): string[] | undefined;
|
|
17
15
|
export declare function match(path: string, include?: string[], exclude?: string[]): boolean;
|
|
18
16
|
export declare function endsWith(input: string, patterns: string[]): boolean;
|
|
19
17
|
export declare function createMatchFilter(include?: string[], exclude?: string[]): (input: string) => boolean;
|
|
20
18
|
export declare function checkMatch(subject: string | undefined, patterns: string[]): boolean;
|
|
21
|
-
export declare function formatDateTime(datetime: string): string;
|
|
22
19
|
export declare function undefIfEmpty(input: string): string | undefined;
|
|
23
20
|
export {};
|