triangle-utils 1.3.4 → 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 (43) 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} +6 -8
  8. package/dist/src/{Utils_DynamoDB.js → UtilsDynamoDB.js} +18 -18
  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} +3 -5
  12. package/dist/src/{Utils_S3.js → UtilsS3.js} +3 -3
  13. package/dist/src/{Utils_S3Vectors.d.ts → UtilsS3Vectors.d.ts} +5 -8
  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} +22 -23
  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/vite.config.ts +10 -0
  33. package/dist/src/Utils.d.ts +0 -17
  34. package/dist/src/Utils.js +0 -24
  35. package/dist/src/Utils_Bedrock.d.ts +0 -10
  36. package/dist/src/Utils_Bee.d.ts +0 -11
  37. package/dist/src/Utils_Misc.d.ts +0 -30
  38. package/dist/src/Utils_Misc.js +0 -627
  39. package/dist/src/Utils_Youtube.d.ts +0 -8
  40. package/src/Utils.ts +0 -28
  41. package/src/Utils_Misc.ts +0 -678
  42. package/src/types/Config.ts +0 -9
  43. /package/dist/src/types/{Config.js → TriangleUtilsConfig.js} +0 -0
@@ -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/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 | undefined>;
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> | undefined;
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 {};