@certik/skynet 0.18.9 → 0.19.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 (72) hide show
  1. package/.vscode/settings.json +5 -0
  2. package/CHANGELOG.md +9 -0
  3. package/README.md +2 -2
  4. package/{abi.js → abi.ts} +5 -132
  5. package/{address.js → address.ts} +4 -4
  6. package/{api.js → api.ts} +79 -19
  7. package/{app.js → app.ts} +138 -25
  8. package/{availability.js → availability.ts} +18 -21
  9. package/bun.lockb +0 -0
  10. package/{cli.js → cli.ts} +1 -1
  11. package/{const.js → const.ts} +42 -3
  12. package/databricks.ts +82 -0
  13. package/{date.js → date.ts} +5 -5
  14. package/{deploy.js → deploy.ts} +157 -44
  15. package/{dynamodb.js → dynamodb.ts} +159 -186
  16. package/env.ts +25 -0
  17. package/eslint.config.mjs +7 -0
  18. package/examples/{api.js → api.ts} +7 -6
  19. package/examples/{indexer.js → indexer.ts} +9 -10
  20. package/examples/{mode-indexer.js → mode-indexer.ts} +18 -10
  21. package/graphql.ts +43 -0
  22. package/{indexer.js → indexer.ts} +228 -109
  23. package/{log.js → log.ts} +6 -6
  24. package/{opsgenie.js → opsgenie.ts} +29 -6
  25. package/package.json +17 -11
  26. package/{s3.js → s3.ts} +29 -19
  27. package/search.ts +37 -0
  28. package/selector.ts +72 -0
  29. package/{slack.js → slack.ts} +19 -12
  30. package/snowflake.ts +51 -0
  31. package/tsconfig.json +26 -0
  32. package/util.ts +35 -0
  33. package/web3.ts +41 -0
  34. package/.eslintignore +0 -1
  35. package/.eslintrc.json +0 -20
  36. package/abi.d.ts +0 -20
  37. package/address.d.ts +0 -2
  38. package/api.d.ts +0 -12
  39. package/app.d.ts +0 -118
  40. package/availability.d.ts +0 -18
  41. package/cli.d.ts +0 -4
  42. package/const.d.ts +0 -42
  43. package/databricks.js +0 -82
  44. package/deploy.d.ts +0 -51
  45. package/dns.d.ts +0 -1
  46. package/dns.js +0 -27
  47. package/dynamodb.d.ts +0 -63
  48. package/env.d.ts +0 -6
  49. package/env.js +0 -42
  50. package/examples/consumer.js +0 -30
  51. package/examples/producer.js +0 -63
  52. package/graphql.d.ts +0 -3
  53. package/graphql.js +0 -22
  54. package/indexer.d.ts +0 -32
  55. package/log.d.ts +0 -8
  56. package/opsgenie.d.ts +0 -8
  57. package/proxy.d.ts +0 -9
  58. package/proxy.js +0 -154
  59. package/s3.d.ts +0 -36
  60. package/search.d.ts +0 -5
  61. package/search.js +0 -29
  62. package/selector.d.ts +0 -19
  63. package/selector.js +0 -71
  64. package/slack.d.ts +0 -10
  65. package/snowflake.d.ts +0 -4
  66. package/snowflake.js +0 -33
  67. package/sqs.d.ts +0 -3
  68. package/sqs.js +0 -5
  69. package/util.d.ts +0 -5
  70. package/util.js +0 -61
  71. package/web3.d.ts +0 -25
  72. package/web3.js +0 -113
@@ -1,31 +1,28 @@
1
- export async function wait(time) {
1
+ export async function wait(time: number) {
2
2
  return new Promise((resolve) => {
3
3
  setTimeout(resolve, time);
4
4
  });
5
5
  }
6
6
 
7
- export async function retry(times, verbose, func) {
8
- try {
9
- await func();
10
- } catch (err) {
11
- if (times <= 1) {
12
- console.log("failed to retry", err);
13
- throw err;
14
- } else {
15
- if (verbose) {
16
- console.log("retry catch error", err);
17
- console.log("retrying remaining times=", times - 1);
18
- }
19
- await wait(5000);
20
- await retry(times - 1, verbose, func);
21
- }
22
- }
23
- }
24
-
25
- export async function exponentialRetry(func, { maxRetry, initialDuration, growFactor, test, verbose }) {
7
+ export async function exponentialRetry<T>(
8
+ func: () => Promise<T>,
9
+ {
10
+ maxRetry,
11
+ initialDuration,
12
+ growFactor,
13
+ test,
14
+ verbose,
15
+ }: {
16
+ maxRetry: number;
17
+ initialDuration?: number;
18
+ growFactor?: number;
19
+ test: (result: T) => boolean;
20
+ verbose?: boolean;
21
+ },
22
+ ) {
26
23
  let retries = maxRetry;
27
24
  let duration = initialDuration || 5000;
28
- let growFactorFinal = growFactor || 2;
25
+ const growFactorFinal = growFactor || 2;
29
26
 
30
27
  let result = await func();
31
28
 
package/bun.lockb CHANGED
Binary file
@@ -19,7 +19,7 @@ function detectWorkingDirectory() {
19
19
  return wd.slice(skynetd.length + path.sep.length).replace(path.sep, "/");
20
20
  }
21
21
 
22
- function detectDirectory(fullBinPath, sentinel = "package.json") {
22
+ function detectDirectory(fullBinPath: string, sentinel = "package.json") {
23
23
  let parentFolder = path.dirname(fullBinPath);
24
24
 
25
25
  while (parentFolder) {
@@ -1,6 +1,41 @@
1
- import { getNodeRealApiKey, ensureAndGet } from "./env.js";
1
+ import { ensureAndGet } from "./env.ts";
2
2
 
3
- const PROTOCOLS = {
3
+ type Protocol = {
4
+ nativeTokenName: string;
5
+ nativeTokenSymbol: string;
6
+ nativeTokenDecimals: number;
7
+ nativeTokenAddress: string;
8
+ nativeTokenLogo?: string;
9
+ nativeTokenCoinGeckoId?: string;
10
+ nativeTokenCmcId?: number;
11
+ endpoint: string;
12
+ backupEndpoint?: string;
13
+ archiveEndpoint?: string;
14
+ tokenStandard: string;
15
+ scanApi?: {
16
+ endpoint: string;
17
+ key?: string;
18
+ };
19
+ multiCallProvider?: string;
20
+ scanUrl?: string;
21
+ chainId: number;
22
+ };
23
+
24
+ type TimeIntervals = {
25
+ SECOND: number;
26
+ MINUTE: number;
27
+ HOUR: number;
28
+ DAY: number;
29
+ WEEK: number;
30
+ YEAR: number;
31
+ };
32
+
33
+ function getNodeRealApiKey(identifier: string) {
34
+ // NodeReal API keys are different for each NodeReal app
35
+ return ensureAndGet(`SKYNET_NODEREAL_API_${identifier.toUpperCase()}_KEY`) ?? ensureAndGet("SKYNET_NODEREAL_API_KEY");
36
+ }
37
+
38
+ const PROTOCOLS: Record<string, Protocol> = {
4
39
  eth: {
5
40
  nativeTokenName: "Ethereum",
6
41
  nativeTokenSymbol: "ETH",
@@ -114,10 +149,14 @@ const PROTOCOLS = {
114
149
  nativeTokenCmcId: 4030,
115
150
  endpoint: "https://algo-node.certik-skynet.com/",
116
151
  tokenStandard: "ASA",
152
+ chainId: 1300,
117
153
  },
118
154
  };
119
155
 
120
- const TIME = {
156
+ const TIME: {
157
+ BY_MS: TimeIntervals;
158
+ BY_S: TimeIntervals;
159
+ } = {
121
160
  BY_MS: {
122
161
  SECOND: 1000,
123
162
  MINUTE: 1000 * 60,
package/databricks.ts ADDED
@@ -0,0 +1,82 @@
1
+ import { DBSQLClient, DBSQLParameter } from "@databricks/sql";
2
+ import { getEnvOrThrow } from "./env.js";
3
+ import { exponentialRetry } from "./availability.js";
4
+ import type IDBSQLSession from "@databricks/sql/dist/contracts/IDBSQLSession.js";
5
+ import type { DBSQLParameterValue } from "@databricks/sql/dist/DBSQLParameter.js";
6
+
7
+ let client: DBSQLClient | null = null;
8
+
9
+ let session: IDBSQLSession | null = null;
10
+
11
+ async function initSession() {
12
+ if (!client) {
13
+ client = new DBSQLClient();
14
+ await client.connect({
15
+ authType: "access-token",
16
+ token: getEnvOrThrow("SKYNET_DATABRICKS_TOKEN"),
17
+ host: getEnvOrThrow("SKYNET_DATABRICKS_SERVER_HOSTNAME"),
18
+ path: getEnvOrThrow("SKYNET_DATABRICKS_HTTP_PATH"),
19
+ });
20
+ }
21
+ if (!session) {
22
+ session = await client.openSession();
23
+ }
24
+ }
25
+
26
+ async function executeSql<T>(sql: string, bindings: Record<string, DBSQLParameterValue>) {
27
+ // retry sql query to avoid socket hang up error
28
+ const results = await exponentialRetry(
29
+ async () => {
30
+ let queryOperation;
31
+ try {
32
+ await initSession();
33
+ if (!session) throw new Error("Session is not initialized");
34
+ queryOperation = await session.executeStatement(sql, {
35
+ runAsync: true,
36
+ namedParameters: objToParameter(bindings),
37
+ });
38
+
39
+ const result = await queryOperation.fetchAll();
40
+ return result;
41
+ } catch (err) {
42
+ // If the error is not a Databricks error, throw it
43
+ if (!checkIsDatabricksError(err)) {
44
+ throw err;
45
+ }
46
+ return err;
47
+ } finally {
48
+ await queryOperation?.close();
49
+ }
50
+ },
51
+ {
52
+ maxRetry: 3,
53
+ initialDuration: 500,
54
+ test: (result) => {
55
+ return !checkIsDatabricksError(result);
56
+ },
57
+ },
58
+ );
59
+
60
+ if (checkIsDatabricksError(results)) {
61
+ // still error after retry, throw it
62
+ throw results;
63
+ }
64
+ return results as T[];
65
+ }
66
+
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ function checkIsDatabricksError(err: any) {
69
+ return err?.errno === "ECONNRESET" || err?.message?.includes("java.lang.NullPointerException");
70
+ }
71
+
72
+ function objToParameter(obj: Record<string, DBSQLParameterValue>) {
73
+ return Object.entries(obj).reduce(
74
+ (acc, [key, value]) => {
75
+ acc[key] = new DBSQLParameter({ value });
76
+ return acc;
77
+ },
78
+ {} as Record<string, DBSQLParameter>,
79
+ );
80
+ }
81
+
82
+ export { executeSql };
@@ -1,19 +1,19 @@
1
- import { arrayGroup } from "./util.js";
1
+ import { arrayGroup } from "./util.ts";
2
2
 
3
3
  const MS_IN_A_DAY = 3600 * 24 * 1000;
4
4
 
5
- function getDateOnly(date) {
5
+ function getDateOnly(date: number | string | Date) {
6
6
  return new Date(date).toISOString().split("T")[0];
7
7
  }
8
8
 
9
- function findDateAfter(date, n) {
9
+ function findDateAfter(date: number | string | Date, n: number) {
10
10
  const d = new Date(date);
11
11
  const after = new Date(d.getTime() + MS_IN_A_DAY * n);
12
12
 
13
13
  return getDateOnly(after);
14
14
  }
15
15
 
16
- function daysInRange(from, to) {
16
+ function daysInRange(from: number | string | Date, to: number | string | Date) {
17
17
  const fromTime = new Date(from).getTime();
18
18
  const toTime = new Date(to).getTime();
19
19
 
@@ -32,7 +32,7 @@ function daysInRange(from, to) {
32
32
  return dates;
33
33
  }
34
34
 
35
- function dateRange(from, to, step) {
35
+ function dateRange(from: number | string | Date, to: number | string | Date, step: number): [string, string][] {
36
36
  const days = daysInRange(from, to);
37
37
 
38
38
  const windows = arrayGroup(days, step);
@@ -4,11 +4,43 @@ import { execa } from "execa";
4
4
  import meow from "meow";
5
5
  import chalk from "chalk";
6
6
  import which from "which";
7
- import { getJobName, getSelectorFlags, getSelectorDesc } from "./selector.js";
8
- import { getEnvOrThrow } from "./env.js";
9
- import { getBinaryName, detectSkynetDirectory } from "./cli.js";
7
+ import { getJobName, getSelectorDesc, getSelectorFlags } from "./selector.ts";
8
+ import type { Selector } from "./selector.ts";
9
+ import { getEnvOrThrow } from "./env.ts";
10
+ import { getBinaryName, detectSkynetDirectory } from "./cli.ts";
11
+ import type { Writable } from "stream";
12
+
13
+ export type Env = {
14
+ [key: string]: string | null;
15
+ };
16
+
17
+ type Service = {
18
+ prefix: string;
19
+ port: number;
20
+ };
21
+
22
+ type Schedule = string | ((jobName: string) => string);
23
+
24
+ type Check = {
25
+ func: ({ protocol, state, verbose }: { protocol: string; state: string; verbose: boolean }) => {
26
+ type: string;
27
+ message: string;
28
+ };
29
+ schedule: Schedule;
30
+ slackChannel: string;
31
+ killTimeout?: string;
32
+ cpu: number;
33
+ mem: number;
34
+ };
35
+
36
+ type Restart = {
37
+ attempts: number;
38
+ mode: string;
39
+ interval: string;
40
+ delay: string;
41
+ };
10
42
 
11
- const INTERVAL_ALIASES = {
43
+ const INTERVAL_ALIASES: Record<string, string> = {
12
44
  secondly: "*/1 * * * * * *",
13
45
  "@secondly": "*/1 * * * * * *",
14
46
  minutely: "0 * * * * * *",
@@ -32,10 +64,25 @@ const genConfig = ({
32
64
  cpu,
33
65
  mem,
34
66
  service,
35
- additionalEnv = [],
67
+ additionalEnv = {},
36
68
  type = "batch",
37
69
  region = "skynet-dc1",
38
70
  isProduction,
71
+ }: {
72
+ jobName: string;
73
+ workingDirectory: string;
74
+ cmd: string;
75
+ cron?: string;
76
+ count?: number;
77
+ restart?: Restart;
78
+ killTimeout?: string;
79
+ cpu: number;
80
+ mem: number;
81
+ service?: Service;
82
+ additionalEnv?: Env;
83
+ type?: string;
84
+ region?: string;
85
+ isProduction?: boolean;
39
86
  }) => `job "${jobName}" {
40
87
  datacenters = ["${region}"]
41
88
 
@@ -179,7 +226,7 @@ const genConfig = ({
179
226
  }
180
227
  }`;
181
228
 
182
- async function prepareNomad(isProduction) {
229
+ async function prepareNomad(isProduction: boolean) {
183
230
  if (isProduction) {
184
231
  console.log("Deploy to Production");
185
232
  } else {
@@ -197,16 +244,8 @@ async function prepareNomad(isProduction) {
197
244
  }
198
245
  }
199
246
 
200
- async function getNomadAddr(isProduction) {
201
- let nomadAddr;
202
-
203
- if (isProduction) {
204
- nomadAddr = getEnvOrThrow("NOMAD_ADDR");
205
- } else {
206
- nomadAddr = "http://127.0.0.1:4646";
207
- }
208
-
209
- return nomadAddr;
247
+ function getNomadAddr(isProduction: boolean) {
248
+ return isProduction ? getEnvOrThrow("NOMAD_ADDR") : "http://127.0.0.1:4646";
210
249
  }
211
250
 
212
251
  async function getNomadPath() {
@@ -217,13 +256,21 @@ async function getNomadPath() {
217
256
  `Deploy requires ${chalk.bold("nomad")} binary, please follow ${chalk.underline(
218
257
  "https://learn.hashicorp.com/tutorials/nomad/get-started-install",
219
258
  )} for installation`,
259
+ missingNomad,
220
260
  );
221
261
 
222
262
  throw new Error("missing nomad binary");
223
263
  }
224
264
  }
225
265
 
226
- async function runNomadJob(nomadPath, nomadAddr, jobName, nomadJobDefinition, isStop, isDryRun) {
266
+ async function runNomadJob(
267
+ nomadPath: string,
268
+ nomadAddr: string,
269
+ jobName: string,
270
+ nomadJobDefinition: string,
271
+ isStop?: boolean,
272
+ isDryRun?: boolean,
273
+ ) {
227
274
  try {
228
275
  if (isStop) {
229
276
  const nomad = execa(nomadPath, ["job", "stop", jobName], {
@@ -231,7 +278,7 @@ async function runNomadJob(nomadPath, nomadAddr, jobName, nomadJobDefinition, is
231
278
  NOMAD_ADDR: nomadAddr,
232
279
  },
233
280
  });
234
- nomad.stdout.pipe(process.stdout);
281
+ nomad.stdout.pipe(process.stdout as Writable);
235
282
  await nomad;
236
283
 
237
284
  console.log(chalk.green(`Stopped nomad job ${jobName} in ${nomadAddr}`));
@@ -249,15 +296,17 @@ async function runNomadJob(nomadPath, nomadAddr, jobName, nomadJobDefinition, is
249
296
  NOMAD_ADDR: nomadAddr,
250
297
  },
251
298
  });
252
- nomad.stdout.pipe(process.stdout);
299
+ nomad.stdout.pipe(process.stdout as Writable);
253
300
  await nomad;
254
301
 
255
302
  console.log(chalk.green(`Deployed nomad job ${jobName} to ${nomadAddr}`));
256
303
  }
257
304
  } catch (nomadExecErr) {
258
- console.log("Nomad Execution Error:");
259
- console.log(nomadExecErr.message);
260
- console.log("");
305
+ if (nomadExecErr instanceof Error) {
306
+ console.log("Nomad Execution Error:");
307
+ console.log(nomadExecErr.message);
308
+ console.log("");
309
+ }
261
310
 
262
311
  console.log(
263
312
  `Failed to run ${chalk.bold("nomad")} commands, please ensure nomad server is accessible at ${chalk.bold(
@@ -274,7 +323,7 @@ function createModeDeploy({
274
323
  name,
275
324
  workingDirectory,
276
325
  bin = "bin/indexer",
277
- selector = {},
326
+ selector = {} as Selector,
278
327
  env = {},
279
328
  region = "skynet-dc1",
280
329
  deltaSchedule,
@@ -288,6 +337,26 @@ function createModeDeploy({
288
337
  validateKillTimeout,
289
338
  validateCpu,
290
339
  validateMem,
340
+ }: {
341
+ binaryName: string;
342
+ name: string;
343
+ workingDirectory: string;
344
+ bin?: string;
345
+ selector?: Selector;
346
+ env?: Env;
347
+ region?: string;
348
+ check?: Check;
349
+ deltaSchedule?: Schedule;
350
+ validateSchedule?: Schedule;
351
+ deltaKillTimeout?: string;
352
+ deltaCpu: number;
353
+ deltaMem: number;
354
+ rebuildKillTimeout?: string;
355
+ rebuildCpu?: number;
356
+ rebuildMem?: number;
357
+ validateKillTimeout?: string;
358
+ validateCpu?: number;
359
+ validateMem?: number;
291
360
  }) {
292
361
  async function deployMode({
293
362
  mode,
@@ -299,6 +368,15 @@ function createModeDeploy({
299
368
  verbose,
300
369
  schedule: cmdSchedule,
301
370
  ...selectorFlags
371
+ }: {
372
+ mode: string;
373
+ from: number;
374
+ to: number;
375
+ stop: boolean;
376
+ production: boolean;
377
+ dryRun: boolean;
378
+ verbose: boolean;
379
+ schedule?: string;
302
380
  }) {
303
381
  if (mode === "delta") {
304
382
  // delta mode will ignore from/to flags
@@ -310,9 +388,9 @@ function createModeDeploy({
310
388
 
311
389
  const jobName = getJobName(name, selectorFlags, mode);
312
390
 
313
- const selectorCmdPart = Object.keys(selectorFlags)
391
+ const selectorCmdPart = Object.entries(selectorFlags)
314
392
  .sort()
315
- .map((name) => `--${name} ${selectorFlags[name]}`)
393
+ .map(([name, value]) => `--${name} ${value}`)
316
394
  .join(" ");
317
395
  let args = `--mode ${mode} ${selectorCmdPart}`;
318
396
 
@@ -330,7 +408,7 @@ function createModeDeploy({
330
408
  rangeArgs += ` --to ${to}`;
331
409
  }
332
410
 
333
- const modeResouces = {
411
+ const modeResouces: Record<string, { cpu?: number; mem?: number; killTimeout?: string }> = {
334
412
  rebuild: { cpu: rebuildCpu, mem: rebuildMem, killTimeout: rebuildKillTimeout },
335
413
  "resume-rebuild": { cpu: rebuildCpu, mem: rebuildMem, killTimeout: rebuildKillTimeout },
336
414
  validate: {
@@ -342,7 +420,9 @@ function createModeDeploy({
342
420
  };
343
421
 
344
422
  // by default use delta cpu/mem settings
345
- const { cpu, mem, killTimeout } = modeResouces[mode] || modeResouces.delta;
423
+ const cpu = modeResouces[mode]?.cpu || deltaCpu;
424
+ const mem = modeResouces[mode]?.mem || deltaMem;
425
+ const killTimeout = modeResouces[mode]?.killTimeout || deltaKillTimeout;
346
426
 
347
427
  let deltaCron = typeof deltaSchedule === "function" ? deltaSchedule(jobName) : deltaSchedule;
348
428
 
@@ -356,14 +436,14 @@ function createModeDeploy({
356
436
  validateCron = cmdSchedule;
357
437
  }
358
438
 
359
- const modeIntervals = {
360
- delta: INTERVAL_ALIASES[deltaCron] || deltaCron,
361
- validate: INTERVAL_ALIASES[validateCron] || validateCron,
439
+ const modeIntervals: Record<string, string | undefined> = {
440
+ delta: deltaCron ? INTERVAL_ALIASES[deltaCron] || deltaCron : undefined,
441
+ validate: validateCron ? INTERVAL_ALIASES[validateCron] || validateCron : undefined,
362
442
  };
363
443
 
364
444
  const mainJobDefinition = genConfig({
365
445
  jobName,
366
- cron: isPeriodic && modeIntervals[mode],
446
+ cron: isPeriodic ? modeIntervals[mode] : undefined,
367
447
  workingDirectory,
368
448
  additionalEnv: env,
369
449
  region,
@@ -376,12 +456,12 @@ function createModeDeploy({
376
456
 
377
457
  const nomadPath = await getNomadPath();
378
458
  await prepareNomad(production);
379
- const nomadAddr = await getNomadAddr(production);
459
+ const nomadAddr = getNomadAddr(production);
380
460
 
381
461
  await runNomadJob(nomadPath, nomadAddr, jobName, mainJobDefinition, stop, dryRun);
382
462
  }
383
463
 
384
- function deploy() {
464
+ async function deploy() {
385
465
  if (!binaryName) {
386
466
  binaryName = getBinaryName();
387
467
  }
@@ -452,10 +532,12 @@ ${getSelectorDesc(selector)}
452
532
  },
453
533
  );
454
534
 
455
- return deployMode(cli.flags).catch((err) => {
535
+ try {
536
+ return deployMode(cli.flags);
537
+ } catch (err) {
456
538
  console.error(err);
457
539
  process.exit(1);
458
- });
540
+ }
459
541
  }
460
542
 
461
543
  return { deploy };
@@ -477,13 +559,42 @@ function createDeploy({
477
559
  cpu,
478
560
  mem,
479
561
  service,
562
+ }: {
563
+ binaryName: string;
564
+ name: string;
565
+ workingDirectory: string;
566
+ bin?: string;
567
+ selector?: Selector;
568
+ env?: Env;
569
+ region?: string;
570
+ type?: string;
571
+ count?: number;
572
+ schedule?: Schedule;
573
+ restart?: Restart;
574
+ killTimeout?: string;
575
+ cpu: number;
576
+ mem: number;
577
+ service?: Service;
480
578
  }) {
481
- async function deployModeless({ production, stop, dryRun, verbose, schedule: cmdSchedule, ...selectorFlags }) {
482
- const jobName = getJobName(name, selectorFlags, null);
579
+ async function deployModeless({
580
+ production,
581
+ stop,
582
+ dryRun,
583
+ verbose,
584
+ schedule: cmdSchedule,
585
+ ...selectorFlags
586
+ }: {
587
+ production: boolean;
588
+ stop: boolean;
589
+ dryRun: boolean;
590
+ verbose: boolean;
591
+ schedule?: string;
592
+ }) {
593
+ const jobName = getJobName(name, selectorFlags);
483
594
 
484
- const selectorCmdPart = Object.keys(selectorFlags)
595
+ const selectorCmdPart = Object.entries(selectorFlags)
485
596
  .sort()
486
- .map((name) => `--${name} ${selectorFlags[name]}`)
597
+ .map(([name, value]) => `--${name} ${value}`)
487
598
  .join(" ");
488
599
  let args = `${selectorCmdPart}`;
489
600
 
@@ -500,7 +611,7 @@ function createDeploy({
500
611
 
501
612
  const nomadJobDefinition = genConfig({
502
613
  jobName,
503
- cron: INTERVAL_ALIASES[cron] || cron,
614
+ cron: cron ? INTERVAL_ALIASES[cron] || cron : undefined,
504
615
  count,
505
616
  restart,
506
617
  workingDirectory,
@@ -517,12 +628,12 @@ function createDeploy({
517
628
 
518
629
  const nomadPath = await getNomadPath();
519
630
  await prepareNomad(production);
520
- const nomadAddr = await getNomadAddr(production);
631
+ const nomadAddr = getNomadAddr(production);
521
632
 
522
633
  await runNomadJob(nomadPath, nomadAddr, jobName, nomadJobDefinition, stop, dryRun);
523
634
  }
524
635
 
525
- function deploy() {
636
+ async function deploy() {
526
637
  if (!binaryName) {
527
638
  binaryName = getBinaryName();
528
639
  }
@@ -571,10 +682,12 @@ ${getSelectorDesc(selector)}
571
682
  },
572
683
  );
573
684
 
574
- return deployModeless(cli.flags).catch((err) => {
685
+ try {
686
+ return deployModeless(cli.flags);
687
+ } catch (err) {
575
688
  console.error(err);
576
689
  process.exit(1);
577
- });
690
+ }
578
691
  }
579
692
 
580
693
  return { deploy };