@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.
Files changed (51) hide show
  1. package/Action/BackupAction.js +4 -8
  2. package/Action/ConfigAction.d.ts +1 -0
  3. package/Action/ConfigAction.js +8 -7
  4. package/Action/CopyAction.js +1 -1
  5. package/Action/RestoreAction.js +1 -1
  6. package/CHANGELOG.md +22 -0
  7. package/Command/BackupCommand.d.ts +1 -1
  8. package/Command/CleanCacheCommand.d.ts +1 -1
  9. package/Command/CommandAbstract.d.ts +2 -1
  10. package/Command/CommandAbstract.js +3 -1
  11. package/Command/CopyCommand.d.ts +1 -1
  12. package/Command/RestoreCommand.d.ts +1 -1
  13. package/Command/StartServerCommand.js +31 -8
  14. package/Config/Config.d.ts +7 -1
  15. package/Config/Config.js +79 -26
  16. package/Config/RepositoryConfig.d.ts +1 -0
  17. package/Config/RepositoryConfig.js +6 -1
  18. package/Factory/CommandFactory.d.ts +1 -1
  19. package/Factory/CommandFactory.js +2 -2
  20. package/JsonSchema/backup-def.d.ts +30 -0
  21. package/JsonSchema/backup-def.js +18 -0
  22. package/JsonSchema/copy-def.d.ts +24 -0
  23. package/JsonSchema/copy-def.js +15 -0
  24. package/Task/ScriptTask.d.ts +2 -11
  25. package/Task/ScriptTask.js +27 -33
  26. package/cli.js +1 -1
  27. package/config.schema.json +227 -40
  28. package/package.json +5 -4
  29. package/pkg.d.ts +6 -0
  30. package/pkg.js +10 -0
  31. package/utils/cli.d.ts +4 -1
  32. package/utils/cli.js +23 -3
  33. package/utils/datatruck/client.js +3 -3
  34. package/utils/datatruck/cron-server.d.ts +23 -0
  35. package/utils/datatruck/cron-server.js +59 -0
  36. package/utils/datatruck/paths.js +4 -6
  37. package/utils/datatruck/{server.d.ts → repository-server.d.ts} +12 -5
  38. package/utils/datatruck/{server.js → repository-server.js} +48 -26
  39. package/utils/fs.js +19 -18
  40. package/utils/http.d.ts +8 -2
  41. package/utils/http.js +12 -14
  42. package/utils/object.d.ts +1 -1
  43. package/utils/object.js +6 -6
  44. package/utils/schema.d.ts +34 -0
  45. package/utils/schema.js +36 -0
  46. package/utils/steps.d.ts +10 -10
  47. package/utils/steps.js +22 -8
  48. package/utils/string.d.ts +0 -3
  49. package/utils/string.js +22 -42
  50. package/utils/ObjectVault.d.ts +0 -13
  51. 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 DatatruckServerOptions = {
8
- path?: string;
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 createDatatruckServer(options: DatatruckServerOptions): import("node:http").Server<typeof IncomingMessage, typeof import("node:http").ServerResponse>;
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.createDatatruckServer = exports.headerKey = void 0;
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
- function parseUrl(inUrl) {
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 (typeof inParams === "string") {
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
- exports.headerKey = {
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
- return (options.users?.some((user) => user.name === name && user.password === password) || false);
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 createDatatruckServer(options) {
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
- else if (!validateRequest(req, options)) {
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: options.path ?? ".",
81
+ backend: backend.path,
62
82
  });
63
- const { action, params } = parseUrl(req.url);
64
- if (action === "upload") {
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(`<${action}`);
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(`<${req.url}`, 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.createDatatruckServer = createDatatruckServer;
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, path_2.join)(path, file);
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 crated: ${path}`);
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, path_3.isAbsolute)(path))
92
- path = (0, path_2.join)(process.cwd(), path);
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 require(`${path_1.rootPath}/package.json`);
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, path_2.join)(sourcePath, baseName) + "." + ext;
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, path_2.join)(dirPath, file);
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, path_2.join)(outDir, `.gitignore`);
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, path_2.dirname)(value.toString());
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, path_2.normalize)(rawEntryPath);
294
- const entrySourcePath = (0, path_2.resolve)((0, path_2.join)(basePath, rawEntryPath));
295
- const entryTargetPath = (0, path_2.resolve)((0, path_2.join)(options.outPath, rawEntryPath));
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, path_2.dirname)(entryTargetPath);
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, path_2.join)(options.path, options.onStreamPath ? options.onStreamPath(key) : key)),
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, path_2.join)(dir, "contents.txt");
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 declare function fetchJson<T = any>(url: string, options?: {
6
+ export type FetchOptions = {
7
7
  headers?: Record<string, string>;
8
8
  query?: Record<string, string>;
9
- }): Promise<T>;
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 fetchJson(url, options = {}) {
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
- if (data === undefined) {
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 push<T>(map: Record<string, T[]>, key: string, object: T): void;
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.push = exports.merge = void 0;
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 push(map, key, object) {
17
- if (!map[key])
18
- map[key] = [];
19
- map[key].push(object);
16
+ function omitProp(object, name) {
17
+ const result = { ...object };
18
+ delete result[name];
19
+ return result;
20
20
  }
21
- exports.push = push;
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 {};
@@ -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
- process?: {
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, options.process?.vars || {})), {
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.node?.tempDir) {
34
- tempDir = await options.node.tempDir();
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 vars = {
41
+ const nodeVars = {
41
42
  ...step.config.vars,
42
- ...options.node?.vars,
43
+ ...vars,
43
44
  };
44
- const varKeys = Object.keys(vars);
45
- const varJson = JSON.stringify(vars);
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 ?? `{TEXT}`, options.telegram?.vars || {}),
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 {};