@certik/skynet 0.25.5 → 0.25.6

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,41 +1,3 @@
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
- }
39
1
  // src/env.ts
40
2
  function ensureAndGet(envName, defaultValue) {
41
3
  return process.env[envName] || defaultValue;
@@ -55,207 +17,56 @@ function isProduction() {
55
17
  function isDev() {
56
18
  return getEnvironment() === "dev";
57
19
  }
58
- // src/log.ts
59
- function isObject(a) {
60
- return !!a && a.constructor === Object;
61
- }
62
- function print(o) {
63
- if (Array.isArray(o)) {
64
- return `[${o.map(print).join(", ")}]`;
65
- }
66
- if (isObject(o)) {
67
- return `{${Object.keys(o).map((k) => `${k}: ${o[k]}`).join(", ")}}`;
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)]);
68
25
  }
69
- return `${o}`;
26
+ return arr;
70
27
  }
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");
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));
75
32
  }
76
- return line.trim();
77
- }
78
- function timestamp() {
79
- return new Date().toISOString();
33
+ return groups;
80
34
  }
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
- }
35
+ function fillRange(start, end) {
36
+ const result = [];
37
+ for (let i = start;i <= end; i++) {
38
+ result.push(i);
113
39
  }
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();
40
+ return result;
123
41
  }
124
- async function contextMiddleware(_, res, next) {
125
- res.set("x-instance-id", osModule.hostname());
126
- next();
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];
127
46
  }
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;
134
- }
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;
147
- }
148
- inline.log(JSON.stringify(logInfo));
149
- next();
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);
150
51
  }
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
- });
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`);
246
57
  }
247
- if (beforeListen) {
248
- await beforeListen({ app });
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)));
249
62
  }
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
- });
63
+ return dates;
64
+ }
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]]);
257
69
  }
258
-
259
70
  // src/object-hash.ts
260
71
  import xh from "@node-rs/xxhash";
261
72
  function getHash(obj) {
@@ -382,28 +193,63 @@ function memoize(func, options) {
382
193
  }
383
194
  return pMemoize(func, options);
384
195
  }
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)]);
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(", ")}]`;
390
203
  }
391
- return arr;
204
+ if (isObject(o)) {
205
+ return `{${Object.keys(o).map((k) => `${k}: ${o[k]}`).join(", ")}}`;
206
+ }
207
+ return `${o}`;
392
208
  }
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));
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
+ }
397
234
  }
398
- return groups;
399
- }
400
- function fillRange(start, end) {
401
- const result = [];
402
- for (let i = start;i <= end; i++) {
403
- result.push(i);
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
+ }
404
251
  }
405
- return result;
406
- }
252
+ };
407
253
  // src/dynamodb.ts
408
254
  import {
409
255
  DynamoDBDocumentClient,
@@ -718,6 +564,58 @@ async function deleteRecordsByHashKey(tableName, indexName, hashKeyValue, verbos
718
564
  }
719
565
  return totalDeleted;
720
566
  }
567
+ function destroyDynamoDB() {
568
+ if (_dynamoDB) {
569
+ _dynamoDB.destroy();
570
+ }
571
+ }
572
+ // src/selector.ts
573
+ function getSelectorDesc(selector) {
574
+ return Object.keys(selector).map((name) => {
575
+ return ` --${name.padEnd(14)}${selector[name].desc || selector[name].description || ""}`;
576
+ }).join(`
577
+ `);
578
+ }
579
+ function getSelectorFlags(selector) {
580
+ return Object.keys(selector).reduce((acc, name) => {
581
+ const flag = {
582
+ type: selector[name].type || "string",
583
+ ...selector[name]
584
+ };
585
+ if (!selector[name].optional && selector[name].isRequired !== false) {
586
+ flag.isRequired = true;
587
+ }
588
+ return { ...acc, [name]: flag };
589
+ }, {});
590
+ }
591
+ function toSelectorString(selectorFlags, delim = ",") {
592
+ return Object.keys(selectorFlags).sort().map((flag) => {
593
+ return `${flag}=${selectorFlags[flag]}`;
594
+ }).join(delim);
595
+ }
596
+ function normalizeSelectorValue(v) {
597
+ return v.replace(/[^A-Za-z0-9]+/g, "-");
598
+ }
599
+ function includeSelectorValueInJobName(value) {
600
+ if (value === false)
601
+ return false;
602
+ if (value === undefined || value === null)
603
+ return false;
604
+ if (value === "")
605
+ return false;
606
+ return true;
607
+ }
608
+ function getJobName(name, selectorFlags, mode) {
609
+ const selectorNamePart = Object.keys(selectorFlags).sort().map((key) => selectorFlags[key]).filter(includeSelectorValueInJobName).map((value) => String(value)).join("-");
610
+ let jobName = name;
611
+ if (mode) {
612
+ jobName += `-${mode}`;
613
+ }
614
+ if (selectorNamePart.length > 0) {
615
+ jobName += `-${normalizeSelectorValue(selectorNamePart)}`;
616
+ }
617
+ return jobName;
618
+ }
721
619
  // src/cli.ts
722
620
  import path from "path";
723
621
  import fs from "fs";
@@ -753,36 +651,11 @@ function detectBin() {
753
651
  const wd = detectDirectory(process.argv[1], "package.json");
754
652
  return process.argv[1].slice(wd.length + path.sep.length).replace(path.sep, "/");
755
653
  }
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]]);
654
+ function getDeployBin(bin) {
655
+ return bin.endsWith(".ts") ? `bun ${bin}` : bin;
783
656
  }
784
657
  // src/indexer.ts
785
- import meow2 from "meow";
658
+ import meow from "meow";
786
659
  var STATE_TABLE_NAME = "skynet-" + getEnvironment() + "-indexer-state";
787
660
  async function getIndexerLatestId(name, selectorFlags) {
788
661
  const record = await getRecordByKey(STATE_TABLE_NAME, {
@@ -884,6 +757,7 @@ function createModeIndexerApp({
884
757
  inline.log(`[MODE INDEXER] mode=${mode}, env=${getEnvironment()}, ${toSelectorString(selectorFlags, ", ")}`);
885
758
  if (mode === "reset") {
886
759
  await runReset(selectorFlags);
760
+ process.exit(0);
887
761
  } else if (mode === "rebuild") {
888
762
  const rebuildFrom = from || await finalState.getMinId(selectorFlags);
889
763
  const rebuildTo = to || await finalState.getMaxId(selectorFlags);
@@ -995,6 +869,7 @@ function createModeIndexerApp({
995
869
  }
996
870
  }
997
871
  inline.log(`[MODE INDEXER] validated ${offsetRange(from, to)} ${finalState.type} successfully in ${Date.now() - startTime}ms`);
872
+ process.exit(0);
998
873
  }
999
874
  async function execBuild(selectorFlags, from, to, verbose, shouldSaveState = false) {
1000
875
  let failedIds = [];
@@ -1070,7 +945,7 @@ function createModeIndexerApp({
1070
945
  const startTime = Date.now();
1071
946
  if (to < from) {
1072
947
  inline.log(`[MODE INDEXER] skip delta, there're no more items need to be processed, from=${from}, to=${to}, ${toSelectorString(selectorFlags, ", ")}`);
1073
- return;
948
+ process.exit(0);
1074
949
  }
1075
950
  inline.log(`[MODE INDEXER] starting delta, from=${from}, to=${to}, ${toSelectorString(selectorFlags, ", ")}, batchSize=${buildBatchSize}, concurrency=${buildConcurrency}`);
1076
951
  try {
@@ -1125,7 +1000,7 @@ function createModeIndexerApp({
1125
1000
  if (!binaryName) {
1126
1001
  binaryName = getBinaryName();
1127
1002
  }
1128
- const cli = meow2(`
1003
+ const cli = meow(`
1129
1004
  Usage
1130
1005
 
1131
1006
  $ ${binaryName} <options>
@@ -1169,6 +1044,8 @@ ${selector ? getSelectorDesc(selector) : ""}
1169
1044
  } catch (err) {
1170
1045
  inline.error(err);
1171
1046
  process.exit(1);
1047
+ } finally {
1048
+ destroyDynamoDB();
1172
1049
  }
1173
1050
  }
1174
1051
  return { run };
@@ -1183,7 +1060,7 @@ function createIndexerApp({
1183
1060
  if (!binaryName) {
1184
1061
  binaryName = getBinaryName();
1185
1062
  }
1186
- const cli = meow2(`
1063
+ const cli = meow(`
1187
1064
  Usage
1188
1065
  $ ${binaryName} <options>
1189
1066
 
@@ -1228,6 +1105,7 @@ ${selector ? getSelectorDesc(selector) : ""}
1228
1105
  throw new Error(`[INDEXER] Build failed due to critical errors`);
1229
1106
  }
1230
1107
  inline.log(`[INDEXER] build successfully in ${Date.now() - startTime}ms`);
1108
+ process.exit(0);
1231
1109
  }
1232
1110
  return runBuild(cli.flags).catch((err) => {
1233
1111
  inline.error(err);
@@ -1240,7 +1118,7 @@ ${selector ? getSelectorDesc(selector) : ""}
1240
1118
  import fs2 from "fs/promises";
1241
1119
  import fso from "fs";
1242
1120
  import { execa } from "execa";
1243
- import meow3 from "meow";
1121
+ import meow2 from "meow";
1244
1122
  import chalk from "chalk";
1245
1123
  import which from "which";
1246
1124
  var INTERVAL_ALIASES = {
@@ -1547,7 +1425,7 @@ function createModeDeploy({
1547
1425
  if (!binaryName) {
1548
1426
  binaryName = getBinaryName();
1549
1427
  }
1550
- const cli = meow3(`
1428
+ const cli = meow2(`
1551
1429
  Usage
1552
1430
 
1553
1431
  $ ${binaryName} <options>
@@ -1677,7 +1555,7 @@ function createDeploy({
1677
1555
  if (!binaryName) {
1678
1556
  binaryName = getBinaryName();
1679
1557
  }
1680
- const cli = meow3(`
1558
+ const cli = meow2(`
1681
1559
  Usage
1682
1560
 
1683
1561
  $ ${binaryName} <options>
@@ -1725,6 +1603,150 @@ ${getSelectorDesc(selector)}
1725
1603
  }
1726
1604
  return { deploy };
1727
1605
  }
1606
+ // src/api.ts
1607
+ import osModule from "os";
1608
+ import express from "express";
1609
+ import meow3 from "meow";
1610
+ async function logStartMiddleware(_, res, next) {
1611
+ const start = new Date;
1612
+ res.set("x-requested-at", start.toISOString());
1613
+ next();
1614
+ }
1615
+ async function contextMiddleware(_, res, next) {
1616
+ res.set("x-instance-id", osModule.hostname());
1617
+ next();
1618
+ }
1619
+ async function logEndMiddleware(req, res, next) {
1620
+ const requestedAt = res.get("x-requested-at");
1621
+ if (!requestedAt) {
1622
+ inline.log("missing x-requested-at header");
1623
+ next();
1624
+ return;
1625
+ }
1626
+ const start = new Date(requestedAt).getTime();
1627
+ const end = new Date().getTime();
1628
+ const logInfo = {
1629
+ start,
1630
+ end,
1631
+ elapsed: `${end - start}ms`,
1632
+ endpoint: req.path,
1633
+ host: req.hostname,
1634
+ status: res.statusCode
1635
+ };
1636
+ if (res.statusMessage) {
1637
+ logInfo.errorMessage = res.statusMessage;
1638
+ }
1639
+ inline.log(JSON.stringify(logInfo));
1640
+ next();
1641
+ }
1642
+ var apiKeyMiddleware = (key) => {
1643
+ async function requireAPIKey(req, res, next) {
1644
+ try {
1645
+ const apiKey = req.get("x-api-key") || req.query["api-key"];
1646
+ if (!apiKey) {
1647
+ inline.log("request without api key");
1648
+ res.status(400).send("require x-api-key header");
1649
+ return;
1650
+ }
1651
+ if (typeof key === "string") {
1652
+ if (apiKey !== key) {
1653
+ inline.log("request has an invalid api key");
1654
+ res.status(400).send("invalid api key");
1655
+ return;
1656
+ }
1657
+ inline.log(`requested by valid key ${key.slice(0, 6)}`);
1658
+ } else {
1659
+ const name = key[apiKey];
1660
+ if (!name) {
1661
+ inline.log("request has an invalid api key");
1662
+ res.status(400).send("invalid api key");
1663
+ return;
1664
+ }
1665
+ inline.log(`requested by authorized user ${name}`);
1666
+ }
1667
+ next();
1668
+ } catch (err) {
1669
+ inline.log("check api key error", err);
1670
+ res.status(500).send("internal error");
1671
+ }
1672
+ }
1673
+ return requireAPIKey;
1674
+ };
1675
+ async function startApiApp({
1676
+ binaryName,
1677
+ name,
1678
+ selector = {},
1679
+ routes,
1680
+ serve,
1681
+ beforeListen
1682
+ }) {
1683
+ const app = express();
1684
+ app.use(express.json({ limit: "20mb" }));
1685
+ const cli = meow3(`
1686
+ Usage
1687
+ $ ${binaryName} <options>
1688
+
1689
+ Options
1690
+ ${getSelectorDesc(selector)}
1691
+ --verbose Output debug messages
1692
+ `, {
1693
+ importMeta: import.meta,
1694
+ description: false,
1695
+ flags: {
1696
+ ...getSelectorFlags(selector),
1697
+ verbose: {
1698
+ type: "boolean",
1699
+ default: false
1700
+ }
1701
+ }
1702
+ });
1703
+ const { verbose, ...selectorFlags } = cli.flags;
1704
+ for (const route of routes) {
1705
+ const method = route.method ? route.method.toLowerCase() : "get";
1706
+ const middlewares = route.middlewares || [];
1707
+ if (route.protected) {
1708
+ if (!serve.apiKey) {
1709
+ throw new Error("serve.apiKey is required for protected route");
1710
+ }
1711
+ middlewares.unshift(apiKeyMiddleware(serve.apiKey));
1712
+ }
1713
+ if (app[method]) {
1714
+ if (verbose) {
1715
+ inline.log(`registering ${method} ${route.path}`);
1716
+ }
1717
+ app[method](route.path, contextMiddleware, logStartMiddleware, ...middlewares, async (req, res, next) => {
1718
+ try {
1719
+ await route.handler({ req, res, ...selectorFlags });
1720
+ } catch (routeErr) {
1721
+ if (routeErr instanceof Error) {
1722
+ inline.log("caught route err", routeErr, routeErr.stack);
1723
+ res.status(500).send(`internal server error: ${routeErr.message}`);
1724
+ } else {
1725
+ inline.log("caught route err", routeErr);
1726
+ res.status(500).send("internal server error");
1727
+ }
1728
+ }
1729
+ next();
1730
+ }, logEndMiddleware);
1731
+ }
1732
+ }
1733
+ if (!routes.some((r) => r.path === "/" && r.method?.toUpperCase() === "GET")) {
1734
+ app.get("/", (_, res) => {
1735
+ res.send("ok");
1736
+ });
1737
+ }
1738
+ if (beforeListen) {
1739
+ await beforeListen({ app });
1740
+ }
1741
+ app.listen(serve.port, () => {
1742
+ if (isProduction()) {
1743
+ inline.log(`${name} listening at https://api.wf.corp.certik.com${serve.prefix}`);
1744
+ } else {
1745
+ inline.log(`${name} listening at http://localhost:${serve.port}`);
1746
+ }
1747
+ });
1748
+ }
1749
+
1728
1750
  // src/app.ts
1729
1751
  import { EOL } from "os";
1730
1752
  function printAppHelp() {
@@ -1834,12 +1856,13 @@ function indexer({
1834
1856
  },
1835
1857
  onDeploy: () => {
1836
1858
  const bin = detectBin();
1859
+ const runBin = getDeployBin(bin);
1837
1860
  const needDoppler = Object.values(env).some((v) => v === SENSITIVE_VALUE);
1838
1861
  const { deploy } = createDeploy({
1839
1862
  binaryName: `${getBinaryName()} deploy`,
1840
1863
  name,
1841
1864
  workingDirectory: detectWorkingDirectory(),
1842
- bin: needDoppler ? `doppler run -- ${bin} run` : `${bin} run`,
1865
+ bin: needDoppler ? `doppler run -- ${runBin} run` : `${runBin} run`,
1843
1866
  selector,
1844
1867
  region,
1845
1868
  env,
@@ -1917,12 +1940,13 @@ function modeIndexer({
1917
1940
  },
1918
1941
  onDeploy: () => {
1919
1942
  const bin = detectBin();
1943
+ const runBin = getDeployBin(bin);
1920
1944
  const needDoppler = Object.values(env).some((v) => v === SENSITIVE_VALUE);
1921
1945
  const { deploy } = createModeDeploy({
1922
1946
  binaryName: `${getBinaryName()} deploy`,
1923
1947
  name,
1924
1948
  workingDirectory: detectWorkingDirectory(),
1925
- bin: needDoppler ? `doppler run -- ${bin} run` : `${bin} run`,
1949
+ bin: needDoppler ? `doppler run -- ${runBin} run` : `${runBin} run`,
1926
1950
  selector,
1927
1951
  region,
1928
1952
  env,
@@ -2012,12 +2036,13 @@ function api({
2012
2036
  },
2013
2037
  onDeploy: () => {
2014
2038
  const bin = detectBin();
2039
+ const runBin = getDeployBin(bin);
2015
2040
  const needDoppler = Object.values(env).some((v) => v === SENSITIVE_VALUE);
2016
2041
  const { deploy } = createDeploy({
2017
2042
  binaryName: `${getBinaryName()} deploy`,
2018
2043
  name,
2019
2044
  workingDirectory: detectWorkingDirectory(),
2020
- bin: needDoppler ? `doppler run -- ${bin} run` : `${bin} run`,
2045
+ bin: needDoppler ? `doppler run -- ${runBin} run` : `${runBin} run`,
2021
2046
  selector,
2022
2047
  region,
2023
2048
  env,