@certik/skynet 0.25.2 → 0.25.4

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/cli.js CHANGED
@@ -33,7 +33,11 @@ function detectBin() {
33
33
  const wd = detectDirectory(process.argv[1], "package.json");
34
34
  return process.argv[1].slice(wd.length + path.sep.length).replace(path.sep, "/");
35
35
  }
36
+ function getDeployBin(bin) {
37
+ return bin.endsWith(".ts") ? `bun ${bin}` : bin;
38
+ }
36
39
  export {
40
+ getDeployBin,
37
41
  getBinaryName,
38
42
  detectWorkingDirectory,
39
43
  detectSkynetDirectory,
package/dist/deploy.js CHANGED
@@ -1,3 +1,22 @@
1
+ // src/env.ts
2
+ function ensureAndGet(envName, defaultValue) {
3
+ return process.env[envName] || defaultValue;
4
+ }
5
+ function getEnvironment() {
6
+ return ensureAndGet("SKYNET_ENVIRONMENT", "dev");
7
+ }
8
+ function getEnvOrThrow(envName) {
9
+ if (!process.env[envName]) {
10
+ throw new Error(`Must set environment variable ${envName}`);
11
+ }
12
+ return process.env[envName];
13
+ }
14
+ function isProduction() {
15
+ return getEnvironment() === "prd";
16
+ }
17
+ function isDev() {
18
+ return getEnvironment() === "dev";
19
+ }
1
20
  // src/selector.ts
2
21
  function getSelectorDesc(selector) {
3
22
  return Object.keys(selector).map((name) => {
@@ -36,25 +55,6 @@ function getJobName(name, selectorFlags, mode) {
36
55
  }
37
56
  return jobName;
38
57
  }
39
- // src/env.ts
40
- function ensureAndGet(envName, defaultValue) {
41
- return process.env[envName] || defaultValue;
42
- }
43
- function getEnvironment() {
44
- return ensureAndGet("SKYNET_ENVIRONMENT", "dev");
45
- }
46
- function getEnvOrThrow(envName) {
47
- if (!process.env[envName]) {
48
- throw new Error(`Must set environment variable ${envName}`);
49
- }
50
- return process.env[envName];
51
- }
52
- function isProduction() {
53
- return getEnvironment() === "prd";
54
- }
55
- function isDev() {
56
- return getEnvironment() === "dev";
57
- }
58
58
  // src/cli.ts
59
59
  import path from "path";
60
60
  import fs from "fs";
@@ -90,6 +90,9 @@ function detectBin() {
90
90
  const wd = detectDirectory(process.argv[1], "package.json");
91
91
  return process.argv[1].slice(wd.length + path.sep.length).replace(path.sep, "/");
92
92
  }
93
+ function getDeployBin(bin) {
94
+ return bin.endsWith(".ts") ? `bun ${bin}` : bin;
95
+ }
93
96
  // src/deploy.ts
94
97
  import fs2 from "fs/promises";
95
98
  import fso from "fs";
package/dist/dynamodb.js CHANGED
@@ -1,3 +1,25 @@
1
+ // src/util.ts
2
+ function range(startAt, endAt, step) {
3
+ const arr = [];
4
+ for (let i = startAt;i <= endAt; i += step) {
5
+ arr.push([i, Math.min(endAt, i + step - 1)]);
6
+ }
7
+ return arr;
8
+ }
9
+ function arrayGroup(array, groupSize) {
10
+ const groups = [];
11
+ for (let i = 0;i < array.length; i += groupSize) {
12
+ groups.push(array.slice(i, i + groupSize));
13
+ }
14
+ return groups;
15
+ }
16
+ function fillRange(start, end) {
17
+ const result = [];
18
+ for (let i = start;i <= end; i++) {
19
+ result.push(i);
20
+ }
21
+ return result;
22
+ }
1
23
  // src/object-hash.ts
2
24
  import xh from "@node-rs/xxhash";
3
25
  function getHash(obj) {
@@ -124,28 +146,6 @@ function memoize(func, options) {
124
146
  }
125
147
  return pMemoize(func, options);
126
148
  }
127
- // src/util.ts
128
- function range(startAt, endAt, step) {
129
- const arr = [];
130
- for (let i = startAt;i <= endAt; i += step) {
131
- arr.push([i, Math.min(endAt, i + step - 1)]);
132
- }
133
- return arr;
134
- }
135
- function arrayGroup(array, groupSize) {
136
- const groups = [];
137
- for (let i = 0;i < array.length; i += groupSize) {
138
- groups.push(array.slice(i, i + groupSize));
139
- }
140
- return groups;
141
- }
142
- function fillRange(start, end) {
143
- const result = [];
144
- for (let i = start;i <= end; i++) {
145
- result.push(i);
146
- }
147
- return result;
148
- }
149
149
  // src/dynamodb.ts
150
150
  import {
151
151
  DynamoDBDocumentClient,
@@ -0,0 +1,9 @@
1
+ interface SendEmailOptions {
2
+ to: string | string[];
3
+ subject: string;
4
+ html: string;
5
+ from: string;
6
+ text?: string;
7
+ }
8
+ export declare function sendEmail({ to, subject, html, from, text }: SendEmailOptions): Promise<void>;
9
+ export {};
package/dist/email.js ADDED
@@ -0,0 +1,31 @@
1
+ // src/email.ts
2
+ import Mailgun from "mailgun.js";
3
+ import formData from "form-data";
4
+ async function sendEmail({ to, subject, html, from, text }) {
5
+ const apiKey = process.env.MAILGUN_API_KEY;
6
+ if (!apiKey) {
7
+ throw new Error("missing MAILGUN_API_KEY");
8
+ }
9
+ const domain = process.env.MAILGUN_DOMAIN;
10
+ if (!domain) {
11
+ throw new Error("missing MAILGUN_DOMAIN");
12
+ }
13
+ const mailgun = new Mailgun(formData);
14
+ const mg = mailgun.client({ username: "api", key: apiKey });
15
+ const recipients = Array.isArray(to) ? to : [to];
16
+ try {
17
+ await mg.messages.create(domain, {
18
+ from,
19
+ to: recipients,
20
+ subject,
21
+ ...text ? { text } : {},
22
+ html
23
+ });
24
+ } catch (error) {
25
+ console.error("failed to send email", error);
26
+ throw error;
27
+ }
28
+ }
29
+ export {
30
+ sendEmail
31
+ };
package/dist/indexer.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,63 +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(", ")}]`;
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)]);
65
25
  }
66
- if (isObject(o)) {
67
- return `{${Object.keys(o).map((k) => `${k}: ${o[k]}`).join(", ")}}`;
26
+ return arr;
27
+ }
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));
68
32
  }
69
- return `${o}`;
33
+ return groups;
70
34
  }
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");
35
+ function fillRange(start, end) {
36
+ const result = [];
37
+ for (let i = start;i <= end; i++) {
38
+ result.push(i);
75
39
  }
76
- return line.trim();
40
+ return result;
77
41
  }
78
- function timestamp() {
79
- return new Date().toISOString();
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];
80
46
  }
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
- }
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);
51
+ }
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`);
96
57
  }
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
- }
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)));
113
62
  }
114
- };
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]]);
69
+ }
115
70
  // src/object-hash.ts
116
71
  import xh from "@node-rs/xxhash";
117
72
  function getHash(obj) {
@@ -238,28 +193,63 @@ function memoize(func, options) {
238
193
  }
239
194
  return pMemoize(func, options);
240
195
  }
241
- // src/util.ts
242
- function range(startAt, endAt, step) {
243
- const arr = [];
244
- for (let i = startAt;i <= endAt; i += step) {
245
- arr.push([i, Math.min(endAt, i + step - 1)]);
246
- }
247
- return arr;
196
+ // src/log.ts
197
+ function isObject(a) {
198
+ return !!a && a.constructor === Object;
248
199
  }
249
- function arrayGroup(array, groupSize) {
250
- const groups = [];
251
- for (let i = 0;i < array.length; i += groupSize) {
252
- groups.push(array.slice(i, i + groupSize));
200
+ function print(o) {
201
+ if (Array.isArray(o)) {
202
+ return `[${o.map(print).join(", ")}]`;
253
203
  }
254
- return groups;
204
+ if (isObject(o)) {
205
+ return `{${Object.keys(o).map((k) => `${k}: ${o[k]}`).join(", ")}}`;
206
+ }
207
+ return `${o}`;
255
208
  }
256
- function fillRange(start, end) {
257
- const result = [];
258
- for (let i = start;i <= end; i++) {
259
- result.push(i);
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");
260
213
  }
261
- return result;
214
+ return line.trim();
262
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
+ }
234
+ }
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
+ }
251
+ }
252
+ };
263
253
  // src/dynamodb.ts
264
254
  import {
265
255
  DynamoDBDocumentClient,
@@ -574,6 +564,44 @@ async function deleteRecordsByHashKey(tableName, indexName, hashKeyValue, verbos
574
564
  }
575
565
  return totalDeleted;
576
566
  }
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
+ }
577
605
  // src/cli.ts
578
606
  import path from "path";
579
607
  import fs from "fs";
@@ -609,33 +637,8 @@ function detectBin() {
609
637
  const wd = detectDirectory(process.argv[1], "package.json");
610
638
  return process.argv[1].slice(wd.length + path.sep.length).replace(path.sep, "/");
611
639
  }
612
- // src/date.ts
613
- var MS_IN_A_DAY = 3600 * 24 * 1000;
614
- function getDateOnly(date) {
615
- return new Date(date).toISOString().split("T")[0];
616
- }
617
- function findDateAfter(date, n) {
618
- const d = new Date(date);
619
- const after = new Date(d.getTime() + MS_IN_A_DAY * n);
620
- return getDateOnly(after);
621
- }
622
- function daysInRange(from, to) {
623
- const fromTime = new Date(from).getTime();
624
- const toTime = new Date(to).getTime();
625
- if (fromTime > toTime) {
626
- throw new Error(`range to date couldn't be earlier than range from date`);
627
- }
628
- const daysBetween = Math.floor((toTime - fromTime) / MS_IN_A_DAY);
629
- const dates = [getDateOnly(new Date(fromTime))];
630
- for (let i = 1;i <= daysBetween; i += 1) {
631
- dates.push(getDateOnly(new Date(fromTime + i * MS_IN_A_DAY)));
632
- }
633
- return dates;
634
- }
635
- function dateRange(from, to, step) {
636
- const days = daysInRange(from, to);
637
- const windows = arrayGroup(days, step);
638
- return windows.map((w) => [w[0], w[w.length - 1]]);
640
+ function getDeployBin(bin) {
641
+ return bin.endsWith(".ts") ? `bun ${bin}` : bin;
639
642
  }
640
643
  // src/indexer.ts
641
644
  import meow from "meow";
package/examples/api.ts CHANGED
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@certik/skynet",
3
- "version": "0.25.2",
3
+ "version": "0.25.4",
4
4
  "description": "Skynet Shared JS library",
5
5
  "type": "module",
6
6
  "exports": {
@@ -44,6 +44,10 @@
44
44
  "import": "./dist/dynamodb.js",
45
45
  "types": "./dist/dynamodb.d.ts"
46
46
  },
47
+ "./email": {
48
+ "import": "./dist/email.js",
49
+ "types": "./dist/email.d.ts"
50
+ },
47
51
  "./env": {
48
52
  "import": "./dist/env.js",
49
53
  "types": "./dist/env.d.ts"
@@ -116,6 +120,8 @@
116
120
  "chalk": "^5.6.2",
117
121
  "execa": "^9.6.1",
118
122
  "express": "^5.2.1",
123
+ "form-data": "^4.0.5",
124
+ "mailgun.js": "^12.7.1",
119
125
  "meow": "^14.0.0",
120
126
  "p-memoize": "^8.0.0",
121
127
  "p-throttle": "^8.1.0",
package/src/app.ts CHANGED
@@ -5,7 +5,7 @@ import { createDeploy, createModeDeploy } from "./deploy";
5
5
  import type { Env } from "./deploy";
6
6
  import { startApiApp } from "./api.js";
7
7
  import type { Middleware } from "./api";
8
- import { getBinaryName, detectBin, detectWorkingDirectory } from "./cli.js";
8
+ import { getBinaryName, detectBin, detectWorkingDirectory, getDeployBin } from "./cli.js";
9
9
  import type { Selector } from "./selector";
10
10
  import type { Request, Response, Application } from "express";
11
11
 
@@ -203,13 +203,14 @@ function indexer<TSelector extends Selector>({
203
203
  },
204
204
  onDeploy: () => {
205
205
  const bin = detectBin();
206
+ const runBin = getDeployBin(bin);
206
207
  const needDoppler = Object.values(env).some((v) => v === SENSITIVE_VALUE);
207
208
 
208
209
  const { deploy } = createDeploy({
209
210
  binaryName: `${getBinaryName()} deploy`,
210
211
  name,
211
212
  workingDirectory: detectWorkingDirectory(),
212
- bin: needDoppler ? `doppler run -- ${bin} run` : `${bin} run`,
213
+ bin: needDoppler ? `doppler run -- ${runBin} run` : `${runBin} run`,
213
214
  selector,
214
215
  region,
215
216
  env,
@@ -313,13 +314,14 @@ function modeIndexer<T extends IndexerStateValue, TSelector extends Selector>({
313
314
  },
314
315
  onDeploy: () => {
315
316
  const bin = detectBin();
317
+ const runBin = getDeployBin(bin);
316
318
  const needDoppler = Object.values(env).some((v) => v === SENSITIVE_VALUE);
317
319
 
318
320
  const { deploy } = createModeDeploy({
319
321
  binaryName: `${getBinaryName()} deploy`,
320
322
  name,
321
323
  workingDirectory: detectWorkingDirectory(),
322
- bin: needDoppler ? `doppler run -- ${bin} run` : `${bin} run`,
324
+ bin: needDoppler ? `doppler run -- ${runBin} run` : `${runBin} run`,
323
325
  selector,
324
326
  region,
325
327
  env,
@@ -437,13 +439,14 @@ function api({
437
439
  },
438
440
  onDeploy: () => {
439
441
  const bin = detectBin();
442
+ const runBin = getDeployBin(bin);
440
443
  const needDoppler = Object.values(env).some((v) => v === SENSITIVE_VALUE);
441
444
 
442
445
  const { deploy } = createDeploy({
443
446
  binaryName: `${getBinaryName()} deploy`,
444
447
  name,
445
448
  workingDirectory: detectWorkingDirectory(),
446
- bin: needDoppler ? `doppler run -- ${bin} run` : `${bin} run`,
449
+ bin: needDoppler ? `doppler run -- ${runBin} run` : `${runBin} run`,
447
450
  selector,
448
451
  region,
449
452
  env,
package/src/cli.ts CHANGED
@@ -45,4 +45,9 @@ function detectBin() {
45
45
  return process.argv[1].slice(wd.length + path.sep.length).replace(path.sep, "/");
46
46
  }
47
47
 
48
- export { getBinaryName, detectSkynetDirectory, detectWorkingDirectory, detectBin };
48
+ // Run ts files via bun so Nomad/Doppler don't try to exec the file directly.
49
+ function getDeployBin(bin: string): string {
50
+ return bin.endsWith(".ts") ? `bun ${bin}` : bin;
51
+ }
52
+
53
+ export { getBinaryName, detectSkynetDirectory, detectWorkingDirectory, detectBin, getDeployBin };
package/src/email.ts ADDED
@@ -0,0 +1,40 @@
1
+ import Mailgun from "mailgun.js";
2
+ import formData from "form-data";
3
+
4
+ interface SendEmailOptions {
5
+ to: string | string[];
6
+ subject: string;
7
+ html: string;
8
+ from: string;
9
+ text?: string;
10
+ }
11
+
12
+ export async function sendEmail({ to, subject, html, from, text }: SendEmailOptions) {
13
+ const apiKey = process.env.MAILGUN_API_KEY;
14
+ if (!apiKey) {
15
+ throw new Error("missing MAILGUN_API_KEY");
16
+ }
17
+
18
+ const domain = process.env.MAILGUN_DOMAIN;
19
+ if (!domain) {
20
+ throw new Error("missing MAILGUN_DOMAIN");
21
+ }
22
+
23
+ const mailgun = new Mailgun(formData);
24
+ const mg = mailgun.client({ username: "api", key: apiKey });
25
+
26
+ const recipients = Array.isArray(to) ? to : [to];
27
+
28
+ try {
29
+ await mg.messages.create(domain, {
30
+ from,
31
+ to: recipients,
32
+ subject,
33
+ ...(text ? { text } : {}),
34
+ html,
35
+ });
36
+ } catch (error) {
37
+ console.error("failed to send email", error);
38
+ throw error;
39
+ }
40
+ }
@@ -1,5 +0,0 @@
1
- {
2
- "conventionalCommits.scopes": [
3
- "lib-skynet"
4
- ]
5
- }