@certik/skynet 0.22.3 → 0.24.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/dist/app.js CHANGED
@@ -1,3 +1,41 @@
1
+ // src/selector.ts
2
+ function getSelectorDesc(selector) {
3
+ return Object.keys(selector).map((name) => {
4
+ return ` --${name.padEnd(14)}${selector[name].desc || selector[name].description || ""}`;
5
+ }).join(`
6
+ `);
7
+ }
8
+ function getSelectorFlags(selector) {
9
+ return Object.keys(selector).reduce((acc, name) => {
10
+ const flag = {
11
+ type: selector[name].type || "string",
12
+ ...selector[name]
13
+ };
14
+ if (!selector[name].optional && selector[name].isRequired !== false) {
15
+ flag.isRequired = true;
16
+ }
17
+ return { ...acc, [name]: flag };
18
+ }, {});
19
+ }
20
+ function toSelectorString(selectorFlags, delim = ",") {
21
+ return Object.keys(selectorFlags).sort().map((flag) => {
22
+ return `${flag}=${selectorFlags[flag]}`;
23
+ }).join(delim);
24
+ }
25
+ function normalizeSelectorValue(v) {
26
+ return v.replace(/[^A-Za-z0-9]+/g, "-");
27
+ }
28
+ function getJobName(name, selectorFlags, mode) {
29
+ const selectorNamePart = Object.keys(selectorFlags).sort().map((name2) => selectorFlags[name2]).join("-");
30
+ let jobName = name;
31
+ if (mode) {
32
+ jobName += `-${mode}`;
33
+ }
34
+ if (selectorNamePart.length > 0) {
35
+ jobName += `-${normalizeSelectorValue(selectorNamePart)}`;
36
+ }
37
+ return jobName;
38
+ }
1
39
  // src/env.ts
2
40
  function ensureAndGet(envName, defaultValue) {
3
41
  return process.env[envName] || defaultValue;
@@ -17,56 +55,207 @@ function isProduction() {
17
55
  function isDev() {
18
56
  return getEnvironment() === "dev";
19
57
  }
20
- // src/util.ts
21
- function range(startAt, endAt, step) {
22
- const arr = [];
23
- for (let i = startAt;i <= endAt; i += step) {
24
- arr.push([i, Math.min(endAt, i + step - 1)]);
25
- }
26
- return arr;
58
+ // src/log.ts
59
+ function isObject(a) {
60
+ return !!a && a.constructor === Object;
27
61
  }
28
- function arrayGroup(array, groupSize) {
29
- const groups = [];
30
- for (let i = 0;i < array.length; i += groupSize) {
31
- groups.push(array.slice(i, i + groupSize));
62
+ function print(o) {
63
+ if (Array.isArray(o)) {
64
+ return `[${o.map(print).join(", ")}]`;
32
65
  }
33
- return groups;
66
+ if (isObject(o)) {
67
+ return `{${Object.keys(o).map((k) => `${k}: ${o[k]}`).join(", ")}}`;
68
+ }
69
+ return `${o}`;
34
70
  }
35
- function fillRange(start, end) {
36
- const result = [];
37
- for (let i = start;i <= end; i++) {
38
- result.push(i);
71
+ function getLine(params) {
72
+ let line = "";
73
+ for (let i = 0, l = params.length;i < l; i++) {
74
+ line += `${print(params[i])} `.replace(/\n/gm, "\t");
39
75
  }
40
- return result;
76
+ return line.trim();
41
77
  }
42
- // src/date.ts
43
- var MS_IN_A_DAY = 3600 * 24 * 1000;
44
- function getDateOnly(date) {
45
- return new Date(date).toISOString().split("T")[0];
78
+ function timestamp() {
79
+ return new Date().toISOString();
46
80
  }
47
- function findDateAfter(date, n) {
48
- const d = new Date(date);
49
- const after = new Date(d.getTime() + MS_IN_A_DAY * n);
50
- return getDateOnly(after);
81
+ var inline = {
82
+ debug: function(...args) {
83
+ if (true) {
84
+ console.log(`${timestamp()} ${getLine(args)}`);
85
+ }
86
+ },
87
+ log: function(...args) {
88
+ if (true) {
89
+ console.log(`${timestamp()} ${getLine(args)}`);
90
+ }
91
+ },
92
+ error: function(...args) {
93
+ if (true) {
94
+ console.error(`${timestamp()} ${getLine(args)}`);
95
+ }
96
+ }
97
+ };
98
+ var logger = {
99
+ debug: function(...args) {
100
+ if (true) {
101
+ console.log(`[${timestamp()}]`, ...args);
102
+ }
103
+ },
104
+ log: function(...args) {
105
+ if (true) {
106
+ console.log(`[${timestamp()}]`, ...args);
107
+ }
108
+ },
109
+ error: function(...args) {
110
+ if (true) {
111
+ console.error(`[${timestamp()}]`, ...args);
112
+ }
113
+ }
114
+ };
115
+ // src/api.ts
116
+ import osModule from "os";
117
+ import express from "express";
118
+ import meow from "meow";
119
+ async function logStartMiddleware(_, res, next) {
120
+ const start = new Date;
121
+ res.set("x-requested-at", start.toISOString());
122
+ next();
51
123
  }
52
- function daysInRange(from, to) {
53
- const fromTime = new Date(from).getTime();
54
- const toTime = new Date(to).getTime();
55
- if (fromTime > toTime) {
56
- throw new Error(`range to date couldn't be earlier than range from date`);
124
+ async function contextMiddleware(_, res, next) {
125
+ res.set("x-instance-id", osModule.hostname());
126
+ next();
127
+ }
128
+ async function logEndMiddleware(req, res, next) {
129
+ const requestedAt = res.get("x-requested-at");
130
+ if (!requestedAt) {
131
+ inline.log("missing x-requested-at header");
132
+ next();
133
+ return;
57
134
  }
58
- const daysBetween = Math.floor((toTime - fromTime) / MS_IN_A_DAY);
59
- const dates = [getDateOnly(new Date(fromTime))];
60
- for (let i = 1;i <= daysBetween; i += 1) {
61
- dates.push(getDateOnly(new Date(fromTime + i * MS_IN_A_DAY)));
135
+ const start = new Date(requestedAt).getTime();
136
+ const end = new Date().getTime();
137
+ const logInfo = {
138
+ start,
139
+ end,
140
+ elapsed: `${end - start}ms`,
141
+ endpoint: req.path,
142
+ host: req.hostname,
143
+ status: res.statusCode
144
+ };
145
+ if (res.statusMessage) {
146
+ logInfo.errorMessage = res.statusMessage;
62
147
  }
63
- return dates;
148
+ inline.log(JSON.stringify(logInfo));
149
+ next();
64
150
  }
65
- function dateRange(from, to, step) {
66
- const days = daysInRange(from, to);
67
- const windows = arrayGroup(days, step);
68
- return windows.map((w) => [w[0], w[w.length - 1]]);
151
+ var apiKeyMiddleware = (key) => {
152
+ async function requireAPIKey(req, res, next) {
153
+ try {
154
+ const apiKey = req.get("x-api-key") || req.query["api-key"];
155
+ if (!apiKey) {
156
+ inline.log("request without api key");
157
+ res.status(400).send("require x-api-key header");
158
+ return;
159
+ }
160
+ if (typeof key === "string") {
161
+ if (apiKey !== key) {
162
+ inline.log("request has an invalid api key");
163
+ res.status(400).send("invalid api key");
164
+ return;
165
+ }
166
+ inline.log(`requested by valid key ${key.slice(0, 6)}`);
167
+ } else {
168
+ const name = key[apiKey];
169
+ if (!name) {
170
+ inline.log("request has an invalid api key");
171
+ res.status(400).send("invalid api key");
172
+ return;
173
+ }
174
+ inline.log(`requested by authorized user ${name}`);
175
+ }
176
+ next();
177
+ } catch (err) {
178
+ inline.log("check api key error", err);
179
+ res.status(500).send("internal error");
180
+ }
181
+ }
182
+ return requireAPIKey;
183
+ };
184
+ async function startApiApp({
185
+ binaryName,
186
+ name,
187
+ selector = {},
188
+ routes,
189
+ serve,
190
+ beforeListen
191
+ }) {
192
+ const app = express();
193
+ app.use(express.json({ limit: "20mb" }));
194
+ const cli = meow(`
195
+ Usage
196
+ $ ${binaryName} <options>
197
+
198
+ Options
199
+ ${getSelectorDesc(selector)}
200
+ --verbose Output debug messages
201
+ `, {
202
+ importMeta: import.meta,
203
+ description: false,
204
+ flags: {
205
+ ...getSelectorFlags(selector),
206
+ verbose: {
207
+ type: "boolean",
208
+ default: false
209
+ }
210
+ }
211
+ });
212
+ const { verbose, ...selectorFlags } = cli.flags;
213
+ for (const route of routes) {
214
+ const method = route.method ? route.method.toLowerCase() : "get";
215
+ const middlewares = route.middlewares || [];
216
+ if (route.protected) {
217
+ if (!serve.apiKey) {
218
+ throw new Error("serve.apiKey is required for protected route");
219
+ }
220
+ middlewares.unshift(apiKeyMiddleware(serve.apiKey));
221
+ }
222
+ if (app[method]) {
223
+ if (verbose) {
224
+ inline.log(`registering ${method} ${route.path}`);
225
+ }
226
+ app[method](route.path, contextMiddleware, logStartMiddleware, ...middlewares, async (req, res, next) => {
227
+ try {
228
+ await route.handler({ req, res, ...selectorFlags });
229
+ } catch (routeErr) {
230
+ if (routeErr instanceof Error) {
231
+ inline.log("caught route err", routeErr, routeErr.stack);
232
+ res.status(500).send(`internal server error: ${routeErr.message}`);
233
+ } else {
234
+ inline.log("caught route err", routeErr);
235
+ res.status(500).send("internal server error");
236
+ }
237
+ }
238
+ next();
239
+ }, logEndMiddleware);
240
+ }
241
+ }
242
+ if (!routes.some((r) => r.path === "/" && r.method?.toUpperCase() === "GET")) {
243
+ app.get("/", (_, res) => {
244
+ res.send("ok");
245
+ });
246
+ }
247
+ if (beforeListen) {
248
+ await beforeListen({ app });
249
+ }
250
+ app.listen(serve.port, () => {
251
+ if (isProduction()) {
252
+ inline.log(`${name} listening at https://api.wf.corp.certik.com${serve.prefix}`);
253
+ } else {
254
+ inline.log(`${name} listening at http://localhost:${serve.port}`);
255
+ }
256
+ });
69
257
  }
258
+
70
259
  // src/object-hash.ts
71
260
  import xh from "@node-rs/xxhash";
72
261
  function getHash(obj) {
@@ -191,65 +380,30 @@ function memoize(func, options) {
191
380
  if (!options.cacheKey) {
192
381
  options.cacheKey = (args) => getHash(args);
193
382
  }
194
- return pMemoize(func, options);
195
- }
196
- // src/log.ts
197
- function isObject(a) {
198
- return !!a && a.constructor === Object;
199
- }
200
- function print(o) {
201
- if (Array.isArray(o)) {
202
- return `[${o.map(print).join(", ")}]`;
203
- }
204
- if (isObject(o)) {
205
- return `{${Object.keys(o).map((k) => `${k}: ${o[k]}`).join(", ")}}`;
206
- }
207
- return `${o}`;
208
- }
209
- function getLine(params) {
210
- let line = "";
211
- for (let i = 0, l = params.length;i < l; i++) {
212
- line += `${print(params[i])} `.replace(/\n/gm, "\t");
213
- }
214
- return line.trim();
215
- }
216
- function timestamp() {
217
- return new Date().toISOString();
218
- }
219
- var inline = {
220
- debug: function(...args) {
221
- if (true) {
222
- console.log(`${timestamp()} ${getLine(args)}`);
223
- }
224
- },
225
- log: function(...args) {
226
- if (true) {
227
- console.log(`${timestamp()} ${getLine(args)}`);
228
- }
229
- },
230
- error: function(...args) {
231
- if (true) {
232
- console.error(`${timestamp()} ${getLine(args)}`);
233
- }
383
+ return pMemoize(func, options);
384
+ }
385
+ // src/util.ts
386
+ function range(startAt, endAt, step) {
387
+ const arr = [];
388
+ for (let i = startAt;i <= endAt; i += step) {
389
+ arr.push([i, Math.min(endAt, i + step - 1)]);
234
390
  }
235
- };
236
- var logger = {
237
- debug: function(...args) {
238
- if (true) {
239
- console.log(`[${timestamp()}]`, ...args);
240
- }
241
- },
242
- log: function(...args) {
243
- if (true) {
244
- console.log(`[${timestamp()}]`, ...args);
245
- }
246
- },
247
- error: function(...args) {
248
- if (true) {
249
- console.error(`[${timestamp()}]`, ...args);
250
- }
391
+ return arr;
392
+ }
393
+ function arrayGroup(array, groupSize) {
394
+ const groups = [];
395
+ for (let i = 0;i < array.length; i += groupSize) {
396
+ groups.push(array.slice(i, i + groupSize));
251
397
  }
252
- };
398
+ return groups;
399
+ }
400
+ function fillRange(start, end) {
401
+ const result = [];
402
+ for (let i = start;i <= end; i++) {
403
+ result.push(i);
404
+ }
405
+ return result;
406
+ }
253
407
  // src/dynamodb.ts
254
408
  import {
255
409
  DynamoDBDocumentClient,
@@ -564,44 +718,6 @@ async function deleteRecordsByHashKey(tableName, indexName, hashKeyValue, verbos
564
718
  }
565
719
  return totalDeleted;
566
720
  }
567
- // src/selector.ts
568
- function getSelectorDesc(selector) {
569
- return Object.keys(selector).map((name) => {
570
- return ` --${name.padEnd(14)}${selector[name].desc || selector[name].description || ""}`;
571
- }).join(`
572
- `);
573
- }
574
- function getSelectorFlags(selector) {
575
- return Object.keys(selector).reduce((acc, name) => {
576
- const flag = {
577
- type: selector[name].type || "string",
578
- ...selector[name]
579
- };
580
- if (!selector[name].optional && selector[name].isRequired !== false) {
581
- flag.isRequired = true;
582
- }
583
- return { ...acc, [name]: flag };
584
- }, {});
585
- }
586
- function toSelectorString(selectorFlags, delim = ",") {
587
- return Object.keys(selectorFlags).sort().map((flag) => {
588
- return `${flag}=${selectorFlags[flag]}`;
589
- }).join(delim);
590
- }
591
- function normalizeSelectorValue(v) {
592
- return v.replace(/[^A-Za-z0-9]+/g, "-");
593
- }
594
- function getJobName(name, selectorFlags, mode) {
595
- const selectorNamePart = Object.keys(selectorFlags).sort().map((name2) => selectorFlags[name2]).join("-");
596
- let jobName = name;
597
- if (mode) {
598
- jobName += `-${mode}`;
599
- }
600
- if (selectorNamePart.length > 0) {
601
- jobName += `-${normalizeSelectorValue(selectorNamePart)}`;
602
- }
603
- return jobName;
604
- }
605
721
  // src/cli.ts
606
722
  import path from "path";
607
723
  import fs from "fs";
@@ -637,8 +753,36 @@ function detectBin() {
637
753
  const wd = detectDirectory(process.argv[1], "package.json");
638
754
  return process.argv[1].slice(wd.length + path.sep.length).replace(path.sep, "/");
639
755
  }
756
+ // src/date.ts
757
+ var MS_IN_A_DAY = 3600 * 24 * 1000;
758
+ function getDateOnly(date) {
759
+ return new Date(date).toISOString().split("T")[0];
760
+ }
761
+ function findDateAfter(date, n) {
762
+ const d = new Date(date);
763
+ const after = new Date(d.getTime() + MS_IN_A_DAY * n);
764
+ return getDateOnly(after);
765
+ }
766
+ function daysInRange(from, to) {
767
+ const fromTime = new Date(from).getTime();
768
+ const toTime = new Date(to).getTime();
769
+ if (fromTime > toTime) {
770
+ throw new Error(`range to date couldn't be earlier than range from date`);
771
+ }
772
+ const daysBetween = Math.floor((toTime - fromTime) / MS_IN_A_DAY);
773
+ const dates = [getDateOnly(new Date(fromTime))];
774
+ for (let i = 1;i <= daysBetween; i += 1) {
775
+ dates.push(getDateOnly(new Date(fromTime + i * MS_IN_A_DAY)));
776
+ }
777
+ return dates;
778
+ }
779
+ function dateRange(from, to, step) {
780
+ const days = daysInRange(from, to);
781
+ const windows = arrayGroup(days, step);
782
+ return windows.map((w) => [w[0], w[w.length - 1]]);
783
+ }
640
784
  // src/indexer.ts
641
- import meow from "meow";
785
+ import meow2 from "meow";
642
786
  var STATE_TABLE_NAME = "skynet-" + getEnvironment() + "-indexer-state";
643
787
  async function getIndexerLatestId(name, selectorFlags) {
644
788
  const record = await getRecordByKey(STATE_TABLE_NAME, {
@@ -981,7 +1125,7 @@ function createModeIndexerApp({
981
1125
  if (!binaryName) {
982
1126
  binaryName = getBinaryName();
983
1127
  }
984
- const cli = meow(`
1128
+ const cli = meow2(`
985
1129
  Usage
986
1130
 
987
1131
  $ ${binaryName} <options>
@@ -996,7 +1140,6 @@ ${selector ? getSelectorDesc(selector) : ""}
996
1140
  `, {
997
1141
  importMeta: import.meta,
998
1142
  description: false,
999
- version: false,
1000
1143
  flags: {
1001
1144
  ...getSelectorFlags(selector),
1002
1145
  mode: {
@@ -1040,7 +1183,7 @@ function createIndexerApp({
1040
1183
  if (!binaryName) {
1041
1184
  binaryName = getBinaryName();
1042
1185
  }
1043
- const cli = meow(`
1186
+ const cli = meow2(`
1044
1187
  Usage
1045
1188
  $ ${binaryName} <options>
1046
1189
 
@@ -1050,7 +1193,6 @@ ${selector ? getSelectorDesc(selector) : ""}
1050
1193
  `, {
1051
1194
  importMeta: import.meta,
1052
1195
  description: false,
1053
- version: false,
1054
1196
  flags: {
1055
1197
  ...getSelectorFlags(selector),
1056
1198
  verbose: {
@@ -1098,7 +1240,7 @@ ${selector ? getSelectorDesc(selector) : ""}
1098
1240
  import fs2 from "fs/promises";
1099
1241
  import fso from "fs";
1100
1242
  import { execa } from "execa";
1101
- import meow2 from "meow";
1243
+ import meow3 from "meow";
1102
1244
  import chalk from "chalk";
1103
1245
  import which from "which";
1104
1246
  var INTERVAL_ALIASES = {
@@ -1405,7 +1547,7 @@ function createModeDeploy({
1405
1547
  if (!binaryName) {
1406
1548
  binaryName = getBinaryName();
1407
1549
  }
1408
- const cli = meow2(`
1550
+ const cli = meow3(`
1409
1551
  Usage
1410
1552
 
1411
1553
  $ ${binaryName} <options>
@@ -1428,7 +1570,6 @@ ${getSelectorDesc(selector)}
1428
1570
  `, {
1429
1571
  importMeta: import.meta,
1430
1572
  description: false,
1431
- version: false,
1432
1573
  flags: {
1433
1574
  ...getSelectorFlags(selector),
1434
1575
  mode: {
@@ -1536,7 +1677,7 @@ function createDeploy({
1536
1677
  if (!binaryName) {
1537
1678
  binaryName = getBinaryName();
1538
1679
  }
1539
- const cli = meow2(`
1680
+ const cli = meow3(`
1540
1681
  Usage
1541
1682
 
1542
1683
  $ ${binaryName} <options>
@@ -1551,7 +1692,6 @@ ${getSelectorDesc(selector)}
1551
1692
  `, {
1552
1693
  importMeta: import.meta,
1553
1694
  description: false,
1554
- version: false,
1555
1695
  flags: {
1556
1696
  ...getSelectorFlags(selector),
1557
1697
  schedule: {
@@ -1585,151 +1725,6 @@ ${getSelectorDesc(selector)}
1585
1725
  }
1586
1726
  return { deploy };
1587
1727
  }
1588
- // src/api.ts
1589
- import osModule from "os";
1590
- import express from "express";
1591
- import meow3 from "meow";
1592
- async function logStartMiddleware(_, res, next) {
1593
- const start = new Date;
1594
- res.set("x-requested-at", start.toISOString());
1595
- next();
1596
- }
1597
- async function contextMiddleware(_, res, next) {
1598
- res.set("x-instance-id", osModule.hostname());
1599
- next();
1600
- }
1601
- async function logEndMiddleware(req, res, next) {
1602
- const requestedAt = res.get("x-requested-at");
1603
- if (!requestedAt) {
1604
- inline.log("missing x-requested-at header");
1605
- next();
1606
- return;
1607
- }
1608
- const start = new Date(requestedAt).getTime();
1609
- const end = new Date().getTime();
1610
- const logInfo = {
1611
- start,
1612
- end,
1613
- elapsed: `${end - start}ms`,
1614
- endpoint: req.path,
1615
- host: req.hostname,
1616
- status: res.statusCode
1617
- };
1618
- if (res.statusMessage) {
1619
- logInfo.errorMessage = res.statusMessage;
1620
- }
1621
- inline.log(JSON.stringify(logInfo));
1622
- next();
1623
- }
1624
- var apiKeyMiddleware = (key) => {
1625
- async function requireAPIKey(req, res, next) {
1626
- try {
1627
- const apiKey = req.get("x-api-key") || req.query["api-key"];
1628
- if (!apiKey) {
1629
- inline.log("request without api key");
1630
- res.status(400).send("require x-api-key header");
1631
- return;
1632
- }
1633
- if (typeof key === "string") {
1634
- if (apiKey !== key) {
1635
- inline.log("request has an invalid api key");
1636
- res.status(400).send("invalid api key");
1637
- return;
1638
- }
1639
- inline.log(`requested by valid key ${key.slice(0, 6)}`);
1640
- } else {
1641
- const name = key[apiKey];
1642
- if (!name) {
1643
- inline.log("request has an invalid api key");
1644
- res.status(400).send("invalid api key");
1645
- return;
1646
- }
1647
- inline.log(`requested by authorized user ${name}`);
1648
- }
1649
- next();
1650
- } catch (err) {
1651
- inline.log("check api key error", err);
1652
- res.status(500).send("internal error");
1653
- }
1654
- }
1655
- return requireAPIKey;
1656
- };
1657
- async function startApiApp({
1658
- binaryName,
1659
- name,
1660
- selector = {},
1661
- routes,
1662
- serve,
1663
- beforeListen
1664
- }) {
1665
- const app = express();
1666
- app.use(express.json({ limit: "20mb" }));
1667
- const cli = meow3(`
1668
- Usage
1669
- $ ${binaryName} <options>
1670
-
1671
- Options
1672
- ${getSelectorDesc(selector)}
1673
- --verbose Output debug messages
1674
- `, {
1675
- importMeta: import.meta,
1676
- description: false,
1677
- version: false,
1678
- flags: {
1679
- ...getSelectorFlags(selector),
1680
- verbose: {
1681
- type: "boolean",
1682
- default: false
1683
- }
1684
- }
1685
- });
1686
- const { verbose, ...selectorFlags } = cli.flags;
1687
- for (const route of routes) {
1688
- const method = route.method ? route.method.toLowerCase() : "get";
1689
- const middlewares = route.middlewares || [];
1690
- if (route.protected) {
1691
- if (!serve.apiKey) {
1692
- throw new Error("serve.apiKey is required for protected route");
1693
- }
1694
- middlewares.unshift(apiKeyMiddleware(serve.apiKey));
1695
- }
1696
- if (app[method]) {
1697
- if (verbose) {
1698
- inline.log(`registering ${method} ${route.path}`);
1699
- }
1700
- app[method](route.path, contextMiddleware, logStartMiddleware, ...middlewares, async (req, res, next) => {
1701
- try {
1702
- await route.handler({ req, res, ...selectorFlags });
1703
- } catch (routeErr) {
1704
- if (routeErr instanceof Error) {
1705
- inline.log("caught route err", routeErr, routeErr.stack);
1706
- res.status(500).send(`internal server error: ${routeErr.message}`);
1707
- } else {
1708
- inline.log("caught route err", routeErr);
1709
- res.status(500).send("internal server error");
1710
- }
1711
- }
1712
- next();
1713
- }, logEndMiddleware);
1714
- }
1715
- }
1716
- if (!routes.some((r) => r.path === "/" && r.method?.toUpperCase() === "GET")) {
1717
- app.get("/", (_, res) => {
1718
- res.send("ok");
1719
- });
1720
- }
1721
- if (beforeListen) {
1722
- await beforeListen({ app });
1723
- }
1724
- app.listen(serve.port, () => {
1725
- if (isProduction()) {
1726
- inline.log(`${name} listening at https://api.wf.corp.certik.com${serve.prefix}`);
1727
- } else {
1728
- inline.log(`${name} listening at http://localhost:${serve.port}`);
1729
- }
1730
- });
1731
- }
1732
-
1733
1728
  // src/app.ts
1734
1729
  import { EOL } from "os";
1735
1730
  function printAppHelp() {