triangle-utils 1.3.3 → 1.4.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 (44) hide show
  1. package/dist/src/UtilsBedrock.d.ts +8 -0
  2. package/dist/src/{Utils_Bedrock.js → UtilsBedrock.js} +7 -4
  3. package/dist/src/UtilsBee.d.ts +8 -0
  4. package/dist/src/{Utils_Bee.js → UtilsBee.js} +13 -8
  5. package/dist/src/UtilsCognito.d.ts +12 -0
  6. package/dist/src/UtilsCognito.js +110 -0
  7. package/dist/src/{Utils_DynamoDB.d.ts → UtilsDynamoDB.d.ts} +8 -10
  8. package/dist/src/{Utils_DynamoDB.js → UtilsDynamoDB.js} +22 -22
  9. package/dist/src/UtilsMisc.d.ts +32 -0
  10. package/dist/src/UtilsMisc.js +156 -0
  11. package/dist/src/{Utils_S3.d.ts → UtilsS3.d.ts} +5 -7
  12. package/dist/src/{Utils_S3.js → UtilsS3.js} +3 -3
  13. package/dist/src/{Utils_S3Vectors.d.ts → UtilsS3Vectors.d.ts} +6 -9
  14. package/dist/src/{Utils_S3Vectors.js → UtilsS3Vectors.js} +4 -4
  15. package/dist/src/UtilsYoutube.d.ts +6 -0
  16. package/dist/src/{Utils_Youtube.js → UtilsYoutube.js} +8 -7
  17. package/dist/src/index.d.ts +28 -0
  18. package/dist/src/index.js +36 -0
  19. package/dist/src/types/{Config.d.ts → TriangleUtilsConfig.d.ts} +1 -3
  20. package/package.json +8 -8
  21. package/src/{Utils_Bedrock.ts → UtilsBedrock.ts} +10 -8
  22. package/src/{Utils_Bee.ts → UtilsBee.ts} +21 -15
  23. package/src/UtilsCognito.ts +116 -0
  24. package/src/{Utils_DynamoDB.ts → UtilsDynamoDB.ts} +32 -30
  25. package/src/UtilsMisc.ts +188 -0
  26. package/src/{Utils_S3.ts → UtilsS3.ts} +4 -5
  27. package/src/{Utils_S3Vectors.ts → UtilsS3Vectors.ts} +6 -7
  28. package/src/{Utils_Youtube.ts → UtilsYoutube.ts} +9 -9
  29. package/src/index.ts +43 -0
  30. package/src/types/TriangleUtilsConfig.ts +6 -0
  31. package/test/Utils.test.ts +135 -24
  32. package/tsconfig.json +1 -1
  33. package/vite.config.ts +10 -0
  34. package/dist/src/Utils.d.ts +0 -17
  35. package/dist/src/Utils.js +0 -24
  36. package/dist/src/Utils_Bedrock.d.ts +0 -10
  37. package/dist/src/Utils_Bee.d.ts +0 -11
  38. package/dist/src/Utils_Misc.d.ts +0 -30
  39. package/dist/src/Utils_Misc.js +0 -627
  40. package/dist/src/Utils_Youtube.d.ts +0 -8
  41. package/src/Utils.ts +0 -28
  42. package/src/Utils_Misc.ts +0 -655
  43. package/src/types/Config.ts +0 -9
  44. /package/dist/src/types/{Config.js → TriangleUtilsConfig.js} +0 -0
@@ -0,0 +1,188 @@
1
+ import * as nodemailer from "nodemailer"
2
+ import * as crypto from "crypto"
3
+
4
+ import { TriangleUtilsConfig } from "./types/TriangleUtilsConfig"
5
+
6
+ interface Encryption {
7
+ iv : string,
8
+ ciphertext : string
9
+ }
10
+
11
+ export class UtilsMisc {
12
+
13
+ readonly config : TriangleUtilsConfig
14
+ readonly transporter
15
+
16
+ constructor(config : TriangleUtilsConfig) {
17
+ this.config = config
18
+ if (config.google_email !== undefined && config.google_app_password !== undefined) {
19
+ this.transporter = nodemailer.createTransport({
20
+ service: "Gmail",
21
+ host: "smtp.gmail.com",
22
+ port: 465,
23
+ secure: true,
24
+ auth: {
25
+ user: config.google_email,
26
+ pass: config.google_app_password,
27
+ }
28
+ })
29
+ }
30
+ }
31
+
32
+ async send_email(recipient : string, subject : string, text : string) : Promise<boolean> {
33
+ if (this.transporter === undefined) {
34
+ return false
35
+ }
36
+ for (let i = 0; i < 3; i++) {
37
+ try {
38
+ await this.transporter.sendMail({
39
+ from: this.config.alerts_email,
40
+ to: recipient,
41
+ subject: subject,
42
+ text: text
43
+ })
44
+ return true
45
+ } catch (error) {
46
+ console.log("EMAIL ERROR", error)
47
+ }
48
+ }
49
+ return false
50
+ }
51
+
52
+ async admin_alert(text : string) : Promise<boolean> {
53
+ console.log("ADMIN ALERT:", text)
54
+ return await this.send_email(this.config.google_email, "ADMIN ALERT", text)
55
+ }
56
+
57
+ async safe_run(f : () => Promise<any>) : Promise<void> {
58
+ try {
59
+ await f()
60
+ } catch (error) {
61
+ if (!(error instanceof Error)) {
62
+ return
63
+ }
64
+ if (error.stack !== undefined) {
65
+ await this.admin_alert(error.stack.toString())
66
+ } else {
67
+ await this.admin_alert(error.toString())
68
+ }
69
+ }
70
+ }
71
+
72
+ async iterate<T>(inputs : T[], f : (input : T) => Promise<any>, concurrency : number = 1, print_indices : boolean = false) {
73
+ let index = 0
74
+ let iterators = []
75
+ for (let i = 0; i < concurrency; i++) {
76
+ iterators.push((async () => {
77
+ while (index < inputs.length) {
78
+ index += 1
79
+ if (print_indices) {
80
+ console.log(i + ":" + (index - 1) + "/" + inputs.length)
81
+ }
82
+ await this.safe_run(() => f(inputs[index - 1]))
83
+ }
84
+ })())
85
+ }
86
+ await Promise.all(iterators)
87
+ }
88
+
89
+
90
+ static async wait(duration : number) {
91
+ return new Promise(resolve => setTimeout(resolve, duration))
92
+ }
93
+
94
+ static get_current_time() {
95
+ return (new Date()).toISOString()
96
+ }
97
+
98
+ static get_current_milliseconds() {
99
+ return (new Date()).getTime()
100
+ }
101
+
102
+ static async sha256(input : string) : Promise<string> {
103
+ const text_encoder = new TextEncoder()
104
+ const input_buffer = text_encoder.encode(input);
105
+
106
+ const hash_buffer = await crypto.subtle.digest("SHA-256", input_buffer)
107
+
108
+ const hash_array = Array.from(new Uint8Array(hash_buffer))
109
+
110
+ const hash = hash_array.map(b => b.toString(16).padStart(2, "0")).join("")
111
+ return hash
112
+ }
113
+
114
+ static encrypt(secret_key : string, text : string) : Encryption {
115
+ const iv = crypto.randomBytes(16)
116
+ const cipher = crypto.createCipheriv("aes-256-cbc", Buffer.from(secret_key, "hex"), iv)
117
+ let ciphertext = cipher.update(text, "utf8", "hex")
118
+ ciphertext += cipher.final("hex")
119
+ return {
120
+ iv: iv.toString("hex"),
121
+ ciphertext: ciphertext
122
+ }
123
+ }
124
+
125
+ static decrypt(secret_key : string, encryption : Encryption) : string {
126
+ const iv = encryption.iv
127
+ const ciphertext = encryption.ciphertext
128
+ const decipher = crypto.createDecipheriv("aes-256-cbc", Buffer.from(secret_key, "hex"), Buffer.from(iv, "hex"))
129
+ let text = decipher.update(ciphertext, "hex", "utf8")
130
+ text += decipher.final("utf8")
131
+ return text
132
+ }
133
+
134
+ static get_secret_hash(username : string, cognito_client_id : string, cognito_client_secret : string) : string {
135
+ const secret_hash = crypto.createHmac("sha256", cognito_client_secret)
136
+ .update(username + cognito_client_id)
137
+ .digest("base64")
138
+ return secret_hash
139
+ }
140
+
141
+ static get_chunk_indices(text_length : number, max_length = 2500, overlap = 50) : [number, number][] {
142
+ const num_chunks = Math.ceil((text_length + overlap) / max_length)
143
+ const chunk_length = Math.ceil((text_length - overlap) / num_chunks + overlap)
144
+ const chunk_indices : [number, number][] = []
145
+ for (let i = 0; i < num_chunks; i++) {
146
+ chunk_indices.push([
147
+ (chunk_length - overlap) * i,
148
+ (chunk_length - overlap) * i + chunk_length
149
+ ])
150
+ }
151
+ return chunk_indices
152
+ }
153
+
154
+ static chunkify(text : string, max_length = 2500, overlap = 50) : {
155
+ chunk_index : [number, number],
156
+ chunk_text : string
157
+ }[] {
158
+ const chunk_indices = this.get_chunk_indices(text.length, max_length, overlap)
159
+ const chunks = chunk_indices.map(chunk_index => ({
160
+ chunk_index : chunk_index,
161
+ chunk_text : text.substring(...chunk_index)
162
+ }))
163
+ return chunks
164
+ }
165
+
166
+ static chunkify_lined(text : string, max_length = 2500, overlap = 50) : {
167
+ chunk_index : [number, number],
168
+ chunk_text : string
169
+ }[] {
170
+ const chunk_indices : [number, number][] = this.get_chunk_indices(text.length, max_length, overlap)
171
+ const lined_chunk_indices : [number, number][] = []
172
+ for (const chunk_index of chunk_indices) {
173
+ const lined_chunk_index : [number, number] = [
174
+ text.lastIndexOf("\n", chunk_index[0]) + 1,
175
+ text.indexOf("\n", chunk_index[1]) + 1
176
+ ]
177
+ if (lined_chunk_index[1] < lined_chunk_index[0]) {
178
+ lined_chunk_index[1] += text.length
179
+ }
180
+ lined_chunk_indices.push(lined_chunk_index)
181
+ }
182
+ return lined_chunk_indices.map(chunk_index => ({
183
+ chunk_index : chunk_index,
184
+ chunk_text : text.substring(...chunk_index)
185
+ }))
186
+ }
187
+
188
+ }
@@ -1,6 +1,5 @@
1
1
  import { S3, NoSuchKey, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3"
2
2
  import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
3
- import { Config } from "./types/Config"
4
3
 
5
4
  interface S3Key {
6
5
  Bucket : string,
@@ -17,12 +16,12 @@ function parse_s3_filename(s3_filename : string) : S3Key | undefined {
17
16
  return { Bucket : bucket, Key : filename }
18
17
  }
19
18
 
20
- export class Utils_S3 {
19
+ export class UtilsS3 {
21
20
 
22
- readonly s3 : S3
21
+ private readonly s3 : S3
23
22
 
24
- constructor(config : Config) {
25
- this.s3 = new S3({ region : config.region })
23
+ constructor(region : string) {
24
+ this.s3 = new S3({ region : region })
26
25
  }
27
26
 
28
27
  async file_exists(s3_filename : string) {
@@ -1,18 +1,17 @@
1
1
  import { ListVectorsCommandInput, S3Vectors } from "@aws-sdk/client-s3vectors"
2
- import { Config } from "./types/Config"
3
2
 
4
- interface Vector {
3
+ export interface Vector {
5
4
  key : string,
6
5
  data : number[],
7
6
  metadata : any
8
7
  }
9
8
 
10
- export class Utils_S3Vectors {
9
+ export class UtilsS3Vectors {
11
10
 
12
- readonly s3vectors : S3Vectors
11
+ private readonly s3vectors : S3Vectors
13
12
 
14
- constructor(config : Config) {
15
- this.s3vectors = new S3Vectors({ region : config.region })
13
+ constructor(region : string) {
14
+ this.s3vectors = new S3Vectors({ region : region })
16
15
  }
17
16
 
18
17
  async scan(vector_bucket : string, vector_index : string) : Promise<string[]> {
@@ -134,7 +133,7 @@ export class Utils_S3Vectors {
134
133
  }
135
134
  }
136
135
 
137
- async query(vector_bucket : string, vector_index : string, data : number[], num_vectors : number, filters : Record<string, any> = {}) {
136
+ async query(vector_bucket : string, vector_index : string, data : number[], num_vectors : number, filters : Record<string, any> | undefined = undefined) {
138
137
  const response = await this.s3vectors.queryVectors({
139
138
  vectorBucketName : vector_bucket,
140
139
  indexName : vector_index,
@@ -1,19 +1,19 @@
1
1
  import { youtube_v3 } from "googleapis"
2
- import { Config } from "./types/Config"
3
2
 
4
- export class Utils_Youtube {
3
+ export class UtilsYoutube {
5
4
 
6
- readonly config : Config
7
- readonly youtube : youtube_v3.Youtube
5
+ readonly youtube : youtube_v3.Youtube | undefined
8
6
 
9
- constructor(config : Config) {
10
- this.config = config
11
- this.youtube = new youtube_v3.Youtube({
12
- auth: config.youtube_api_key
13
- })
7
+ constructor(youtube_api_key : string | undefined) {
8
+ this.youtube = youtube_api_key !== undefined ? new youtube_v3.Youtube({
9
+ auth: youtube_api_key
10
+ }) : undefined
14
11
  }
15
12
 
16
13
  async batch_get_videos(video_ids : string[], attributes : string[] = ["snippet", "contentDetails"]) {
14
+ if (this.youtube === undefined) {
15
+ return undefined
16
+ }
17
17
  for (let i = 0; i < 3; i++) {
18
18
  try {
19
19
  const response = await this.youtube.videos.list({
package/src/index.ts ADDED
@@ -0,0 +1,43 @@
1
+ import { TriangleUtilsConfig } from "./types/TriangleUtilsConfig"
2
+ import { UtilsDynamoDB } from "./UtilsDynamoDB"
3
+ import { UtilsS3 } from "./UtilsS3"
4
+ import { UtilsBedrock } from "./UtilsBedrock"
5
+ import { UtilsBee } from "./UtilsBee"
6
+ import { UtilsS3Vectors } from "./UtilsS3Vectors"
7
+ import { UtilsCognito } from "./UtilsCognito"
8
+ import { UtilsMisc } from "./UtilsMisc"
9
+ import { UtilsYoutube } from "./UtilsYoutube"
10
+
11
+
12
+
13
+ export class TriangleUtils extends UtilsMisc {
14
+
15
+ readonly dynamodb : UtilsDynamoDB
16
+ readonly s3 : UtilsS3
17
+ readonly s3vectors : UtilsS3Vectors
18
+ readonly bedrock : UtilsBedrock
19
+ readonly cognito : UtilsCognito
20
+ readonly bee : UtilsBee
21
+ readonly youtube : UtilsYoutube
22
+
23
+ constructor(config : TriangleUtilsConfig) {
24
+ super(config)
25
+ this.dynamodb = new UtilsDynamoDB(config.region)
26
+ this.s3 = new UtilsS3(config.region)
27
+ this.s3vectors = new UtilsS3Vectors(config.region)
28
+ this.bedrock = new UtilsBedrock(config.region)
29
+ this.cognito = new UtilsCognito(config.region)
30
+ this.bee = new UtilsBee(config.scraping_bee_api_key)
31
+ this.youtube = new UtilsYoutube(config.youtube_api_key)
32
+ }
33
+ }
34
+
35
+ export * from "./types/TriangleUtilsConfig"
36
+ export * from "./UtilsMisc"
37
+ export * from "./UtilsDynamoDB"
38
+ export * from "./UtilsS3"
39
+ export * from "./UtilsBedrock"
40
+ export * from "./UtilsBee"
41
+ export * from "./UtilsS3Vectors"
42
+ export * from "./UtilsCognito"
43
+ export * from "./UtilsYoutube"
@@ -0,0 +1,6 @@
1
+ export interface TriangleUtilsConfig {
2
+ region : string,
3
+ scraping_bee_api_key? : string,
4
+ youtube_api_key? : string,
5
+ [key : string]: any
6
+ }
@@ -1,50 +1,57 @@
1
- import { Config } from "../src/types/Config.ts"
2
- import { Utils } from "../src/Utils.ts"
3
1
  import { SecretsManager } from "@aws-sdk/client-secrets-manager"
4
2
 
3
+ import { beforeAll, test, describe, expect } from "vitest"
4
+
5
+ import { TriangleUtils, TriangleUtilsConfig, UtilsMisc } from "../src"
6
+
5
7
  const region = "us-east-1"
6
8
 
7
- let config : Config = { region : region }
9
+ let config : TriangleUtilsConfig = { region : region }
8
10
 
9
11
  beforeAll(async () => {
10
- // const secret_name = "api_keys"
12
+ const secret_name = "api_keys"
11
13
 
12
- // const secrets_manager = new SecretsManager({ region: "us-east-1" })
14
+ const secrets_manager = new SecretsManager({ region: "us-east-1" })
15
+
16
+ const response = await secrets_manager.getSecretValue({
17
+ SecretId: secret_name
18
+ })
13
19
 
14
- // const api_keys = await secrets_manager.getSecretValue({
15
- // SecretId: secret_name
16
- // }).then(response => JSON.parse(response.SecretString))
20
+ if (response === undefined || response.SecretString === undefined) {
21
+ return
22
+ }
23
+ const api_keys = JSON.parse(response.SecretString)
17
24
 
18
- // config = {
19
- // google_email : "louishou@triangleanalytics.com",
20
- // alerts_email : "alerts@triangleanalytics.com",
21
- // region : "us-east-1",
22
- // ...api_keys
23
- // }
25
+ config = {
26
+ google_email : "louishou@triangleanalytics.com",
27
+ alerts_email : "alerts@triangleanalytics.com",
28
+ region : "us-east-1",
29
+ ...api_keys
30
+ }
24
31
 
25
32
  })
26
33
 
27
34
  describe("Testing Utils", () => {
28
35
  describe("Testing Misc", () => {
29
36
  test("email", async () => {
30
- const utils = new Utils(config)
31
- await utils.admin_alert("Testing Admin Alert.")
37
+ const utils = new TriangleUtils(config)
38
+ const success = await utils.admin_alert("Testing Admin Alert.")
39
+ expect(success).toBeTruthy()
32
40
  })
33
41
  test("sha256", async () => {
34
- const utils = new Utils(config)
35
- const hash = await utils.sha256("Triangle Analytics")
42
+ const hash = await UtilsMisc.sha256("Triangle Analytics")
36
43
  expect(hash).toEqual("7f6f79a3fdee7c38bb3b0381211575a35ffcfcf5867d6045b07b4181e6f24153")
37
44
  })
38
45
  })
39
46
  describe("Testing DynamoDB", () => {
40
47
  test("scan", async () => {
41
- const utils = new Utils(config)
48
+ const utils = new TriangleUtils(config)
42
49
  const candidates = await utils.dynamodb.scan("candidates")
43
50
  expect(candidates).toBeDefined()
44
51
  expect(candidates.length).toBeGreaterThan(3000)
45
- })
52
+ }, 20000)
46
53
  test("get; single key", async () => {
47
- const utils = new Utils(config)
54
+ const utils = new TriangleUtils(config)
48
55
  const candidate = await utils.dynamodb.get("candidates", { candidate_id : "S6MI00392" })
49
56
  expect(candidate).toBeDefined()
50
57
  if (candidate === undefined) {
@@ -53,7 +60,7 @@ describe("Testing Utils", () => {
53
60
  expect(candidate.fec_name).toBeDefined()
54
61
  })
55
62
  test("get; composite key", async () => {
56
- const utils = new Utils(config)
63
+ const utils = new TriangleUtils(config)
57
64
  const candidate_article = await utils.dynamodb.get("candidate_articles", { candidate_id : "S6MI00392", article_id : "2025-08-1674855ce5e59c2b6a19a165037dffa5627b1cee071def07a614acb1c28d0e2eff" })
58
65
  expect(candidate_article).toBeDefined()
59
66
  if (candidate_article === undefined) {
@@ -62,7 +69,7 @@ describe("Testing Utils", () => {
62
69
  expect(candidate_article.url).toBeDefined()
63
70
  })
64
71
  test("get_max", async () => {
65
- const utils = new Utils(config)
72
+ const utils = new TriangleUtils(config)
66
73
  const candidate_article = await utils.dynamodb.get_max("candidate_articles", { candidate_id : "S6MI00392" })
67
74
  expect(candidate_article).toBeDefined()
68
75
  if (candidate_article === undefined) {
@@ -73,7 +80,7 @@ describe("Testing Utils", () => {
73
80
  expect(candidate_article.article_id.localeCompare("2025-08-1674855ce5e59c2b6a19a165037dffa5627b1cee071def07a614acb1c28d0e2eff") > 0).toBeTruthy()
74
81
  })
75
82
  test("query", async () => {
76
- const utils = new Utils(config)
83
+ const utils = new TriangleUtils(config)
77
84
  const candidate_articles = await utils.dynamodb.query("candidate_articles", { candidate_id : "S6MI00392" })
78
85
  expect(candidate_articles).toBeDefined()
79
86
  if (candidate_articles === undefined) {
@@ -81,5 +88,109 @@ describe("Testing Utils", () => {
81
88
  }
82
89
  expect(candidate_articles.length).toBeGreaterThan(400)
83
90
  })
91
+ test("query_prefix", async () => {
92
+ const utils = new TriangleUtils(config)
93
+ const candidate_articles = await utils.dynamodb.query_prefix("candidate_articles", { candidate_id : "S6MI00392" }, { article_id : "2025-08-16"})
94
+ expect(candidate_articles).toBeDefined()
95
+ if (candidate_articles === undefined) {
96
+ return
97
+ }
98
+ expect(candidate_articles.length).toBeGreaterThan(2)
99
+ expect(!candidate_articles.map(candidate_article => candidate_article.article_id.substring(0, 10) === "2025-08-16").includes(false)).toBeTruthy()
100
+ })
101
+ test("query_range", async () => {
102
+ const utils = new TriangleUtils(config)
103
+ const candidate_articles = await utils.dynamodb.query_range("candidate_articles", { candidate_id : "S6MI00392" }, { article_id : ["2025-08-01", "2025-08-31"] })
104
+ expect(candidate_articles).toBeDefined()
105
+ if (candidate_articles === undefined) {
106
+ return
107
+ }
108
+ expect(candidate_articles.length).toBeGreaterThan(10)
109
+ expect(!candidate_articles.map(candidate_article => candidate_article.article_id.substring(0, 7) === "2025-08").includes(false)).toBeTruthy()
110
+ })
111
+ })
112
+ describe("Testing S3", () => {
113
+ test("exists, get, create, delete, download_url, upload_url", async () => {
114
+ const utils = new TriangleUtils(config)
115
+ const s3_filename = "s3://triangleanalytics-raw-scrapes/test_file.txt"
116
+ await utils.s3.delete_file(s3_filename)
117
+ const file_exists_0 = await utils.s3.file_exists(s3_filename)
118
+ expect(file_exists_0).toBeFalsy()
119
+ await utils.s3.create_file(s3_filename, "test file contents.")
120
+ const file_exists_1 = await utils.s3.file_exists(s3_filename)
121
+ expect(file_exists_1).toBeTruthy()
122
+ const text = await utils.s3.get_file(s3_filename)
123
+ expect(text).toEqual("test file contents.")
124
+ const download_url = await utils.s3.generate_download_url(s3_filename)
125
+ expect(download_url).toBeDefined()
126
+ if (download_url === undefined) {
127
+ return
128
+ }
129
+ expect(download_url.includes("https://triangleanalytics-raw-scrapes.s3.us-east-1.amazonaws.com/test_file.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&")).toBeDefined()
130
+ const upload_url = await utils.s3.generate_upload_url(s3_filename)
131
+ expect(upload_url).toBeDefined()
132
+ await utils.s3.delete_file(s3_filename)
133
+ if (upload_url === undefined) {
134
+ return
135
+ }
136
+ expect(upload_url.includes("https://triangleanalytics-raw-scrapes.s3.us-east-1.amazonaws.com/test_file.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&")).toBeDefined()
137
+ const file_exists_2 = await utils.s3.file_exists(s3_filename)
138
+ expect(file_exists_2).toBeFalsy()
139
+
140
+ })
141
+ })
142
+ // describe("Testing Bee", () => {
143
+ // test("bee get page text", async () => {
144
+ // const utils = new Utils(config)
145
+ // const text = await utils.bee.get("https://marieforcongress.com/", { render_js : false, return_page_text : true })
146
+ // expect(text).toBeDefined()
147
+ // if (text === undefined) {
148
+ // return
149
+ // }
150
+ // expect(text.includes("Marie Gluesenkamp Perez’s working class roots run deep in Washington State.")).toBeTruthy()
151
+ // })
152
+ // test("bee google search", async () => {
153
+ // const utils = new Utils(config)
154
+ // const results = await utils.bee.google_search("Marie Gluesenkamp Perez", true)
155
+ // expect(results).toBeDefined()
156
+ // if (results === undefined) {
157
+ // return
158
+ // }
159
+ // expect(results.length).toBeGreaterThan(1)
160
+ // for (const result of results) {
161
+ // expect(result.link).toBeDefined()
162
+ // expect(result.date).toBeDefined()
163
+ // expect(result.title).toBeDefined()
164
+ // expect(result.source).toBeDefined()
165
+ // }
166
+ // })
167
+ // test("bee youtube search", async () => {
168
+ // const utils = new Utils(config)
169
+ // const results = await utils.bee.youtube_search("Marie Gluesenkamp Perez", true)
170
+ // expect(results).toBeDefined()
171
+ // if (results === undefined) {
172
+ // return
173
+ // }
174
+ // expect(results.length).toBeGreaterThan(1)
175
+ // for (const result of results) {
176
+ // expect(result.videoId).toBeDefined()
177
+ // }
178
+ // })
179
+ // })
180
+ describe("Testing Youtube", () => {
181
+ test("batch_get_videos", async () => {
182
+ const utils = new TriangleUtils(config)
183
+ const videos = await utils.youtube.batch_get_videos(["N4dyOzjjYYk", "rUyg3P1R5NQ"])
184
+ expect(videos).toBeDefined()
185
+ if (videos === undefined) {
186
+ return
187
+ }
188
+ expect(videos.length).toEqual(2)
189
+ for (const video of videos) {
190
+ expect(video.snippet !== undefined)
191
+ expect(video.contentDetails !== undefined)
192
+ }
193
+
194
+ })
84
195
  })
85
196
  })
package/tsconfig.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "declaration": true,
15
15
  // Allow JS files to be imported from TS and vice versa
16
16
  "allowJs": true,
17
-
17
+ "strict" : true,
18
18
  // Use correct ESM import behavior
19
19
  "esModuleInterop": true,
20
20
  "resolveJsonModule": true,
package/vite.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { configDefaults, defineConfig } from "vitest/config"
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ exclude: [
6
+ ...configDefaults.exclude,
7
+ "dist/**"
8
+ ],
9
+ },
10
+ })
@@ -1,17 +0,0 @@
1
- import { Utils_Misc } from "./Utils_Misc.js";
2
- import { Utils_DynamoDB } from "./Utils_DynamoDB.js";
3
- import { Utils_S3 } from "./Utils_S3.js";
4
- import { Utils_Bedrock } from "./Utils_Bedrock.js";
5
- import { Utils_Bee } from "./Utils_Bee.js";
6
- import { Utils_S3Vectors } from "./Utils_S3Vectors.js";
7
- import { Utils_Youtube } from "./Utils_Youtube.js";
8
- import { Config } from "./types/Config.js";
9
- export declare class Utils extends Utils_Misc {
10
- readonly dynamodb: Utils_DynamoDB;
11
- readonly s3: Utils_S3;
12
- readonly s3vectors: Utils_S3Vectors;
13
- readonly bedrock: Utils_Bedrock;
14
- readonly bee: Utils_Bee;
15
- readonly youtube: Utils_Youtube;
16
- constructor(config: Config);
17
- }
package/dist/src/Utils.js DELETED
@@ -1,24 +0,0 @@
1
- import { Utils_Misc } from "./Utils_Misc.js";
2
- import { Utils_DynamoDB } from "./Utils_DynamoDB.js";
3
- import { Utils_S3 } from "./Utils_S3.js";
4
- import { Utils_Bedrock } from "./Utils_Bedrock.js";
5
- import { Utils_Bee } from "./Utils_Bee.js";
6
- import { Utils_S3Vectors } from "./Utils_S3Vectors.js";
7
- import { Utils_Youtube } from "./Utils_Youtube.js";
8
- export class Utils extends Utils_Misc {
9
- dynamodb;
10
- s3;
11
- s3vectors;
12
- bedrock;
13
- bee;
14
- youtube;
15
- constructor(config) {
16
- super(config);
17
- this.dynamodb = new Utils_DynamoDB(config);
18
- this.s3 = new Utils_S3(config);
19
- this.s3vectors = new Utils_S3Vectors(config);
20
- this.bedrock = new Utils_Bedrock(config);
21
- this.bee = new Utils_Bee(config);
22
- this.youtube = new Utils_Youtube(config);
23
- }
24
- }
@@ -1,10 +0,0 @@
1
- import { BedrockRuntime } from "@aws-sdk/client-bedrock-runtime";
2
- import { Config } from "./types/Config.js";
3
- export declare class Utils_Bedrock {
4
- readonly bedrock: BedrockRuntime;
5
- readonly text_decoder: TextDecoder;
6
- constructor(config: Config);
7
- llama_invoke(model_id: string, prompt: string, temperature?: number, max_gen_len?: number, top_p?: number): Promise<string | undefined>;
8
- gpt_converse(model_id: string, prompt: string, temperature?: number, max_gen_len?: number, top_p?: number): Promise<string | undefined>;
9
- titan_invoke(text: string): Promise<string | undefined>;
10
- }
@@ -1,11 +0,0 @@
1
- import { ScrapingBeeClient } from "scrapingbee";
2
- import { Config } from "./types/Config.js";
3
- export declare class Utils_Bee {
4
- readonly config: Config;
5
- readonly bee: ScrapingBeeClient | undefined;
6
- readonly text_decoder: TextDecoder;
7
- constructor(config: Config);
8
- get(url: string, params?: Record<string, string>): Promise<string>;
9
- google_search(query: string, news?: boolean): Promise<any>;
10
- youtube_search(query: string, options?: {}): Promise<any>;
11
- }
@@ -1,30 +0,0 @@
1
- import * as nodemailer from "nodemailer";
2
- import { Config } from "./types/Config.js";
3
- interface Encryption {
4
- iv: string;
5
- ciphertext: string;
6
- }
7
- export declare class Utils_Misc {
8
- readonly config: Config;
9
- readonly text_encoder: TextEncoder;
10
- readonly transporter: nodemailer.Transporter<import("nodemailer/lib/smtp-transport").SentMessageInfo, import("nodemailer/lib/smtp-transport").Options>;
11
- constructor(config: Config);
12
- wait(duration: number): Promise<unknown>;
13
- get_current_time(): string;
14
- get_current_milliseconds(): number;
15
- send_email(recipient: string, subject: string, text: string): Promise<void>;
16
- admin_alert(text: string): Promise<void>;
17
- safe_run(f: () => Promise<any>): Promise<void>;
18
- iterate<T>(inputs: T[], f: (input: T) => Promise<any>, concurrency?: number, print_indices?: boolean): Promise<void>;
19
- sha256(input: string): Promise<string>;
20
- encrypt(text: string): Encryption;
21
- decrypt(encryption: Encryption): string;
22
- get_secret_hash(username: string): string;
23
- get_election_id(year: string, office: string, state: string, district: string): string | undefined;
24
- get_chunk_indices(text_length: number, max_length?: number, overlap?: number): [number, number][];
25
- chunkify(text: string, max_length?: number, overlap?: number): {
26
- chunk_index: [number, number];
27
- chunk_text: string;
28
- }[];
29
- }
30
- export {};