@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
@@ -0,0 +1,5 @@
1
+ {
2
+ "conventionalCommits.scopes": [
3
+ "lib-skynet"
4
+ ]
5
+ }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.0
4
+
5
+ - BREAKING: remove multicall from web3 module
6
+ - BREAKING: remove retry from util module
7
+ - BREAKING: remove createTableIfNotExist from dynamodb module
8
+ - BREAKING: remove transactWrite from dynamodb module
9
+ - BREAKING: remove sqs module
10
+ - Updated: Typescript rewrite
11
+
3
12
  ## 0.18.9
4
13
 
5
14
  - Added options for `executeSql` function in `databricks` library
package/README.md CHANGED
@@ -13,11 +13,11 @@ const { scanWholeTable } = require("@certik/skynet/dynamodb");
13
13
  ## Test
14
14
 
15
15
  ```bash
16
- bun run test
16
+ bun test
17
17
  ```
18
18
 
19
19
  ## Publish
20
20
 
21
21
  ```bash
22
- bun run pub
22
+ bun publish --access public
23
23
  ```
@@ -1,4 +1,6 @@
1
- export const ERC20 = [
1
+ import type { AbiFunctionFragment } from "web3";
2
+
3
+ export const ERC20: AbiFunctionFragment[] = [
2
4
  {
3
5
  constant: true,
4
6
  inputs: [],
@@ -171,12 +173,12 @@ export const ERC20 = [
171
173
  type: "function",
172
174
  },
173
175
  {
176
+ name: "Approval",
174
177
  payable: true,
175
178
  stateMutability: "payable",
176
179
  type: "fallback",
177
180
  },
178
181
  {
179
- anonymous: false,
180
182
  inputs: [
181
183
  {
182
184
  indexed: true,
@@ -198,7 +200,6 @@ export const ERC20 = [
198
200
  type: "event",
199
201
  },
200
202
  {
201
- anonymous: false,
202
203
  inputs: [
203
204
  {
204
205
  indexed: true,
@@ -221,9 +222,8 @@ export const ERC20 = [
221
222
  },
222
223
  ];
223
224
 
224
- export const ERC721 = [
225
+ export const ERC721: AbiFunctionFragment[] = [
225
226
  {
226
- anonymous: false,
227
227
  inputs: [
228
228
  {
229
229
  indexed: true,
@@ -248,7 +248,6 @@ export const ERC721 = [
248
248
  type: "event",
249
249
  },
250
250
  {
251
- anonymous: false,
252
251
  inputs: [
253
252
  {
254
253
  indexed: true,
@@ -273,7 +272,6 @@ export const ERC721 = [
273
272
  type: "event",
274
273
  },
275
274
  {
276
- anonymous: false,
277
275
  inputs: [
278
276
  {
279
277
  indexed: true,
@@ -568,129 +566,4 @@ export const ERC721 = [
568
566
  },
569
567
  ];
570
568
 
571
- export const MULTICALL = [
572
- {
573
- inputs: [{ internalType: "address", name: "_addr", type: "address" }],
574
- name: "callBalanceOf",
575
- outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
576
- stateMutability: "view",
577
- type: "function",
578
- },
579
- {
580
- inputs: [],
581
- name: "callBlockNumber",
582
- outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
583
- stateMutability: "view",
584
- type: "function",
585
- },
586
- {
587
- inputs: [{ internalType: "uint256", name: "_i", type: "uint256" }],
588
- name: "callBlockhash",
589
- outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
590
- stateMutability: "view",
591
- type: "function",
592
- },
593
- {
594
- inputs: [],
595
- name: "callChainId",
596
- outputs: [{ internalType: "uint256", name: "id", type: "uint256" }],
597
- stateMutability: "pure",
598
- type: "function",
599
- },
600
- {
601
- inputs: [{ internalType: "address", name: "_addr", type: "address" }],
602
- name: "callCode",
603
- outputs: [{ internalType: "bytes", name: "code", type: "bytes" }],
604
- stateMutability: "view",
605
- type: "function",
606
- },
607
- {
608
- inputs: [{ internalType: "address", name: "_addr", type: "address" }],
609
- name: "callCodeHash",
610
- outputs: [{ internalType: "bytes32", name: "codeHash", type: "bytes32" }],
611
- stateMutability: "view",
612
- type: "function",
613
- },
614
- {
615
- inputs: [{ internalType: "address", name: "_addr", type: "address" }],
616
- name: "callCodeSize",
617
- outputs: [{ internalType: "uint256", name: "size", type: "uint256" }],
618
- stateMutability: "view",
619
- type: "function",
620
- },
621
- {
622
- inputs: [],
623
- name: "callCoinbase",
624
- outputs: [{ internalType: "address", name: "", type: "address" }],
625
- stateMutability: "view",
626
- type: "function",
627
- },
628
- {
629
- inputs: [],
630
- name: "callDifficulty",
631
- outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
632
- stateMutability: "view",
633
- type: "function",
634
- },
635
- {
636
- inputs: [],
637
- name: "callGasLeft",
638
- outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
639
- stateMutability: "view",
640
- type: "function",
641
- },
642
- {
643
- inputs: [],
644
- name: "callGasLimit",
645
- outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
646
- stateMutability: "view",
647
- type: "function",
648
- },
649
- {
650
- inputs: [],
651
- name: "callGasPrice",
652
- outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
653
- stateMutability: "view",
654
- type: "function",
655
- },
656
- {
657
- inputs: [],
658
- name: "callOrigin",
659
- outputs: [{ internalType: "address", name: "", type: "address" }],
660
- stateMutability: "view",
661
- type: "function",
662
- },
663
- {
664
- inputs: [],
665
- name: "callTimestamp",
666
- outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
667
- stateMutability: "view",
668
- type: "function",
669
- },
670
- {
671
- inputs: [
672
- {
673
- components: [
674
- { internalType: "bool", name: "delegateCall", type: "bool" },
675
- { internalType: "bool", name: "revertOnError", type: "bool" },
676
- { internalType: "uint256", name: "gasLimit", type: "uint256" },
677
- { internalType: "address", name: "target", type: "address" },
678
- { internalType: "uint256", name: "value", type: "uint256" },
679
- { internalType: "bytes", name: "data", type: "bytes" },
680
- ],
681
- internalType: "struct IModuleCalls.Transaction[]",
682
- name: "_txs",
683
- type: "tuple[]",
684
- },
685
- ],
686
- name: "multiCall",
687
- outputs: [
688
- { internalType: "bool[]", name: "_successes", type: "bool[]" },
689
- { internalType: "bytes[]", name: "_results", type: "bytes[]" },
690
- ],
691
- stateMutability: "payable",
692
- type: "function",
693
- },
694
- ];
695
-
696
569
  export const BEP20 = ERC20;
@@ -1,9 +1,9 @@
1
- export function parseAddress(address) {
1
+ export function parseAddress(address: string) {
2
2
  // in case of address has multiple colons, we only split the first one
3
3
  const separatorIndex = address.indexOf(":");
4
4
 
5
- let protocolPart;
6
- let addressPart;
5
+ let protocolPart: string;
6
+ let addressPart: string;
7
7
 
8
8
  if (separatorIndex === -1) {
9
9
  // if there is no colon, we assume it is an ethereum address
@@ -21,6 +21,6 @@ export function parseAddress(address) {
21
21
  return [protocolPart, addressPart];
22
22
  }
23
23
 
24
- export function composeAddress(protocol, addr) {
24
+ export function composeAddress(protocol: string, addr: string) {
25
25
  return `${protocol}:${addr}`;
26
26
  }
@@ -1,11 +1,29 @@
1
1
  import osModule from "os";
2
2
  import express from "express";
3
+ import type { Request, Response, NextFunction } from "express";
3
4
  import meow from "meow";
4
- import { getSelectorFlags, getSelectorDesc } from "./selector.js";
5
- import { isProduction } from "./env.js";
6
- import { inline } from "./log.js";
5
+ import { getSelectorDesc, getSelectorFlags } from "./selector.ts";
6
+ import { isProduction } from "./env.ts";
7
+ import { inline } from "./log.ts";
8
+ import type { Selector } from "./selector.ts";
9
+
10
+ export type Middleware = (req: Request, res: Response, next: NextFunction) => Promise<void>;
11
+
12
+ type Route = {
13
+ method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
14
+ path: string;
15
+ middlewares?: Middleware[];
16
+ handler: (args: { req: Request; res: Response; verbose?: boolean }) => Promise<void>;
17
+ protected?: boolean;
18
+ };
19
+
20
+ type Serve = {
21
+ prefix: string;
22
+ port: number;
23
+ apiKey?: string;
24
+ };
7
25
 
8
- async function logStartMiddleware(req, res, next) {
26
+ async function logStartMiddleware(req: Request, res: Response, next: NextFunction) {
9
27
  const start = new Date();
10
28
 
11
29
  res.set("x-requested-at", start.toISOString());
@@ -13,17 +31,36 @@ async function logStartMiddleware(req, res, next) {
13
31
  next();
14
32
  }
15
33
 
16
- async function contextMiddleware(req, res, next) {
34
+ async function contextMiddleware(req: Request, res: Response, next: NextFunction) {
17
35
  res.set("x-instance-id", osModule.hostname());
18
36
 
19
37
  next();
20
38
  }
21
39
 
22
- async function logEndMiddleware(req, res, next) {
23
- const start = new Date(res.get("x-requested-at"));
24
- const end = new Date();
40
+ type LogInfo = {
41
+ start: number;
42
+ end: number;
43
+ elapsed: string;
44
+ endpoint: string;
45
+ host: string;
46
+ status: number;
47
+ errorMessage?: string;
48
+ };
25
49
 
26
- const logInfo = {
50
+ async function logEndMiddleware(req: Request, res: Response, next: NextFunction) {
51
+ const requestedAt = res.get("x-requested-at");
52
+
53
+ if (!requestedAt) {
54
+ inline.log("missing x-requested-at header");
55
+
56
+ next();
57
+ return;
58
+ }
59
+
60
+ const start = new Date(requestedAt).getTime();
61
+ const end = new Date().getTime();
62
+
63
+ const logInfo: LogInfo = {
27
64
  start,
28
65
  end,
29
66
  elapsed: `${end - start}ms`,
@@ -31,6 +68,7 @@ async function logEndMiddleware(req, res, next) {
31
68
  host: req.hostname,
32
69
  status: res.statusCode,
33
70
  };
71
+
34
72
  if (res.statusMessage) {
35
73
  logInfo.errorMessage = res.statusMessage;
36
74
  }
@@ -39,10 +77,10 @@ async function logEndMiddleware(req, res, next) {
39
77
  next();
40
78
  }
41
79
 
42
- const apiKeyMiddleware = (key) => {
43
- async function requireAPIKey(req, res, next) {
80
+ const apiKeyMiddleware = (key: string | Record<string, string>) => {
81
+ async function requireAPIKey(req: Request, res: Response, next: NextFunction) {
44
82
  try {
45
- const apiKey = req.get("x-api-key") || req.query["api-key"]; // api key present either in header or query string
83
+ const apiKey = req.get("x-api-key") || (req.query["api-key"] as string); // api key present either in header or query string
46
84
 
47
85
  if (!apiKey) {
48
86
  inline.log("request without api key");
@@ -88,7 +126,21 @@ const apiKeyMiddleware = (key) => {
88
126
  return requireAPIKey;
89
127
  };
90
128
 
91
- export async function startApiApp({ binaryName, name, selector = {}, routes, serve, beforeListen }) {
129
+ export async function startApiApp({
130
+ binaryName,
131
+ name,
132
+ selector = {},
133
+ routes,
134
+ serve,
135
+ beforeListen,
136
+ }: {
137
+ binaryName: string;
138
+ name: string;
139
+ selector?: Selector;
140
+ routes: Route[];
141
+ serve: Serve;
142
+ beforeListen?: (args: { app: ReturnType<typeof express> }) => Promise<void>;
143
+ }) {
92
144
  const app = express();
93
145
  app.use(express.json({ limit: "20mb" }));
94
146
 
@@ -118,10 +170,14 @@ ${getSelectorDesc(selector)}
118
170
  const { verbose, ...selectorFlags } = cli.flags;
119
171
 
120
172
  for (const route of routes) {
121
- const method = route.method ? route.method.toLowerCase() : "get";
173
+ const method = route.method ? (route.method.toLowerCase() as "get" | "post" | "put" | "patch" | "delete") : "get";
122
174
  const middlewares = route.middlewares || [];
123
175
 
124
176
  if (route.protected) {
177
+ if (!serve.apiKey) {
178
+ throw new Error("serve.apiKey is required for protected route");
179
+ }
180
+
125
181
  middlewares.unshift(apiKeyMiddleware(serve.apiKey));
126
182
  }
127
183
 
@@ -135,13 +191,17 @@ ${getSelectorDesc(selector)}
135
191
  contextMiddleware,
136
192
  logStartMiddleware,
137
193
  ...middlewares,
138
- async (req, res, next) => {
194
+ async (req: Request, res: Response, next: NextFunction) => {
139
195
  try {
140
196
  await route.handler({ req, res, ...selectorFlags });
141
197
  } catch (routeErr) {
142
- inline.log("caught route err", routeErr, routeErr.stack);
143
-
144
- res.status(500).send(`internal server error: ${routeErr.message}`);
198
+ if (routeErr instanceof Error) {
199
+ inline.log("caught route err", routeErr, routeErr.stack);
200
+ res.status(500).send(`internal server error: ${routeErr.message}`);
201
+ } else {
202
+ inline.log("caught route err", routeErr);
203
+ res.status(500).send("internal server error");
204
+ }
145
205
  }
146
206
 
147
207
  next();
@@ -151,7 +211,7 @@ ${getSelectorDesc(selector)}
151
211
  }
152
212
  }
153
213
 
154
- if (!routes.some((r) => r.path === "/" && r.method.toUpperCase() === "GET")) {
214
+ if (!routes.some((r) => r.path === "/" && r.method?.toUpperCase() === "GET")) {
155
215
  // for health check
156
216
  app.get("/", (req, res) => {
157
217
  res.send("ok");
@@ -1,8 +1,64 @@
1
1
  import { EOL } from "os";
2
- import { createIndexerApp, createModeIndexerApp } from "./indexer.js";
3
- import { createDeploy, createModeDeploy } from "./deploy.js";
2
+ import { createIndexerApp, createModeIndexerApp } from "./indexer.ts";
3
+ import type {
4
+ IndexerStateValue,
5
+ State,
6
+ ModeBuildFunction,
7
+ StatelessBuildFunction,
8
+ ValidateFunction,
9
+ } from "./indexer.ts";
10
+ import { createDeploy, createModeDeploy } from "./deploy.ts";
11
+ import type { Env } from "./deploy.ts";
4
12
  import { startApiApp } from "./api.js";
13
+ import type { Middleware } from "./api.ts";
5
14
  import { getBinaryName, detectBin, detectWorkingDirectory } from "./cli.js";
15
+ import type { Selector } from "./selector.ts";
16
+ import type { Request, Response, Application } from "express";
17
+
18
+ type RouteDefinition = {
19
+ method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
20
+ path: string;
21
+ middlewares?: Middleware[];
22
+ handler: (args: { req: Request; res: Response; verbose?: boolean }) => Promise<void>;
23
+ protected?: boolean;
24
+ };
25
+
26
+ type ServeDefinition = {
27
+ prefix: string;
28
+ port: number;
29
+ apiKey?: string;
30
+ killTimeout?: string;
31
+ cpu: number;
32
+ mem: number;
33
+ instances?: number;
34
+ };
35
+
36
+ type BuildDefinition<TFunc> = {
37
+ func: TFunc;
38
+ killTimeout?: string;
39
+ maxRetry?: number;
40
+ cpu: number;
41
+ mem: number;
42
+ schedule: string;
43
+ restart?: {
44
+ attempts: number;
45
+ mode: string;
46
+ interval: string;
47
+ delay: string;
48
+ };
49
+ batchSize?: number;
50
+ concurrency?: number;
51
+ };
52
+
53
+ type ValidateDefinition<TFunc> = {
54
+ func: TFunc;
55
+ batchSize: number;
56
+ killTimeout?: string;
57
+ cpu: number;
58
+ mem: number;
59
+ concurrency?: number;
60
+ schedule: string;
61
+ };
6
62
 
7
63
  function printAppHelp() {
8
64
  console.log(`
@@ -14,14 +70,14 @@ function printAppHelp() {
14
70
  `);
15
71
  }
16
72
 
17
- function isDeleteCommand(command) {
73
+ function isDeleteCommand(command: string) {
18
74
  return ["delete", "stop", "remove"].includes(command);
19
75
  }
20
76
 
21
- function checkAndSetEnv(env) {
22
- const missingEnvs = [];
77
+ function checkAndSetEnv(env: Env) {
78
+ const missingEnvs: string[] = [];
23
79
 
24
- for (let key of Object.keys(env)) {
80
+ for (const key of Object.keys(env)) {
25
81
  if (env[key]) {
26
82
  process.env[key] = env[key];
27
83
  } else if (!process.env[key]) {
@@ -36,7 +92,17 @@ function checkAndSetEnv(env) {
36
92
  }
37
93
  }
38
94
 
39
- function createApp({ parameterErrors, env, onRun, onDeploy }) {
95
+ function createApp({
96
+ parameterErrors,
97
+ env,
98
+ onRun,
99
+ onDeploy,
100
+ }: {
101
+ parameterErrors: string[];
102
+ env: Env;
103
+ onRun: () => Promise<void>;
104
+ onDeploy: () => Promise<void>;
105
+ }) {
40
106
  if (parameterErrors.length > 0) {
41
107
  console.log(`Parameter Validation Failed:${EOL}- ${parameterErrors.join(EOL + "- ")}`);
42
108
 
@@ -65,8 +131,8 @@ function createApp({ parameterErrors, env, onRun, onDeploy }) {
65
131
  };
66
132
  }
67
133
 
68
- function checkEnvParameter(env) {
69
- const errors = [];
134
+ function checkEnvParameter(env: Env) {
135
+ const errors: string[] = [];
70
136
 
71
137
  const envKeys = Object.keys(env);
72
138
 
@@ -79,8 +145,10 @@ function checkEnvParameter(env) {
79
145
  return errors;
80
146
  }
81
147
 
82
- function checkIndexerBuildParameter(build) {
83
- const errors = [];
148
+ function checkIndexerBuildParameter<TSelector extends Selector>(
149
+ build: BuildDefinition<StatelessBuildFunction<TSelector>>,
150
+ ) {
151
+ const errors: string[] = [];
84
152
 
85
153
  if (!build?.func) {
86
154
  errors.push("must define build.func");
@@ -97,8 +165,8 @@ function checkIndexerBuildParameter(build) {
97
165
  return errors;
98
166
  }
99
167
 
100
- function checkStateParameter(state) {
101
- const errors = [];
168
+ function checkStateParameter<T extends IndexerStateValue, TSelector extends Selector>(state: State<T, TSelector>) {
169
+ const errors: string[] = [];
102
170
 
103
171
  if (!state?.type) {
104
172
  errors.push("must define state.type");
@@ -111,14 +179,25 @@ function checkStateParameter(state) {
111
179
  return errors;
112
180
  }
113
181
 
114
- function indexer({ name, selector, build, env = {}, region = "skynet-dc1" }) {
182
+ function indexer<TSelector extends Selector>({
183
+ name,
184
+ selector,
185
+ build,
186
+ env = {},
187
+ region = "skynet-dc1",
188
+ }: {
189
+ name: string;
190
+ selector: TSelector;
191
+ build: BuildDefinition<StatelessBuildFunction<TSelector>>;
192
+ env?: Env;
193
+ region?: string;
194
+ }) {
115
195
  return createApp({
116
196
  parameterErrors: [...checkIndexerBuildParameter(build), ...checkEnvParameter(env)],
117
197
  env,
118
198
  onRun: () => {
119
199
  const { run } = createIndexerApp({
120
200
  binaryName: `${getBinaryName()} run`,
121
- name,
122
201
  selector,
123
202
  build: build.func,
124
203
  maxRetry: build.maxRetry,
@@ -152,8 +231,10 @@ function indexer({ name, selector, build, env = {}, region = "skynet-dc1" }) {
152
231
  });
153
232
  }
154
233
 
155
- function checkModeIndexerBuildParameter(build) {
156
- const errors = [];
234
+ function checkModeIndexerBuildParameter<T extends IndexerStateValue, TSelector extends Selector>(
235
+ build: BuildDefinition<ModeBuildFunction<T, TSelector>>,
236
+ ) {
237
+ const errors: string[] = [];
157
238
 
158
239
  if (!build?.func) {
159
240
  errors.push("must define build.func");
@@ -170,8 +251,10 @@ function checkModeIndexerBuildParameter(build) {
170
251
  return errors;
171
252
  }
172
253
 
173
- function checkModeIndexerValidateParameter(validate) {
174
- const errors = [];
254
+ function checkModeIndexerValidateParameter<TSelector extends Selector>(
255
+ validate?: ValidateDefinition<ValidateFunction<TSelector>>,
256
+ ) {
257
+ const errors: string[] = [];
175
258
 
176
259
  if (validate) {
177
260
  if (!validate.func) {
@@ -190,7 +273,23 @@ function checkModeIndexerValidateParameter(validate) {
190
273
  return errors;
191
274
  }
192
275
 
193
- function modeIndexer({ name, selector, state, build, validate, env = {}, region = "skynet-dc1" }) {
276
+ function modeIndexer<T extends IndexerStateValue, TSelector extends Selector>({
277
+ name,
278
+ selector,
279
+ state,
280
+ build,
281
+ validate,
282
+ env = {},
283
+ region = "skynet-dc1",
284
+ }: {
285
+ name: string;
286
+ selector: TSelector;
287
+ state: State<T, TSelector>;
288
+ build: BuildDefinition<ModeBuildFunction<T, TSelector>>;
289
+ validate?: ValidateDefinition<ValidateFunction<TSelector>>;
290
+ env?: Env;
291
+ region?: string;
292
+ }) {
194
293
  return createApp({
195
294
  parameterErrors: [
196
295
  ...checkModeIndexerBuildParameter(build),
@@ -251,8 +350,8 @@ function modeIndexer({ name, selector, state, build, validate, env = {}, region
251
350
  });
252
351
  }
253
352
 
254
- function checkApiServeParameter(serve, routes) {
255
- const errors = [];
353
+ function checkApiServeParameter(serve: ServeDefinition, routes: RouteDefinition[]) {
354
+ const errors: string[] = [];
256
355
 
257
356
  if (!serve?.prefix) {
258
357
  errors.push("must define serve.prefix");
@@ -279,8 +378,8 @@ function checkApiServeParameter(serve, routes) {
279
378
  return errors;
280
379
  }
281
380
 
282
- function checkApiRoutesParameter(routes) {
283
- const errors = [];
381
+ function checkApiRoutesParameter(routes: RouteDefinition[]) {
382
+ const errors: string[] = [];
284
383
 
285
384
  if (!Array.isArray(routes)) {
286
385
  errors.push("routes must be an array");
@@ -305,7 +404,21 @@ function checkApiRoutesParameter(routes) {
305
404
  return errors;
306
405
  }
307
406
 
308
- function api({ name, routes, serve, beforeListen, env = {}, region = "skynet-dc1" }) {
407
+ function api({
408
+ name,
409
+ routes,
410
+ serve,
411
+ beforeListen,
412
+ env = {},
413
+ region = "skynet-dc1",
414
+ }: {
415
+ name: string;
416
+ routes: RouteDefinition[];
417
+ serve: ServeDefinition;
418
+ beforeListen?: ({ app }: { app: Application }) => Promise<void>;
419
+ env?: Env;
420
+ region?: string;
421
+ }) {
309
422
  // do not support selector for now
310
423
  const selector = {};
311
424