opticedge-cloud-utils 1.0.5 → 1.0.7

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/.eslintignore ADDED
@@ -0,0 +1,2 @@
1
+ # Ignore compiled output
2
+ dist/
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export * from './auth/verify';
2
- export * from './utils/secrets';
3
2
  export * from './db/mongo';
3
+ export * from './utils/env';
4
+ export * from './utils/secrets';
5
+ export * from './utils/task';
package/dist/index.js CHANGED
@@ -15,5 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./auth/verify"), exports);
18
- __exportStar(require("./utils/secrets"), exports);
19
18
  __exportStar(require("./db/mongo"), exports);
19
+ __exportStar(require("./utils/env"), exports);
20
+ __exportStar(require("./utils/secrets"), exports);
21
+ __exportStar(require("./utils/task"), exports);
@@ -0,0 +1 @@
1
+ export declare function getEnv(name: string): string;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getEnv = getEnv;
4
+ function getEnv(name) {
5
+ const value = process.env[name];
6
+ if (!value) {
7
+ throw new Error(`Missing env var: ${name}`);
8
+ }
9
+ return value;
10
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // src/utils/env.test.ts
4
+ const env_1 = require("./env");
5
+ describe('getEnv', () => {
6
+ it('should return the value of an existing env var', () => {
7
+ process.env.TEST_KEY = 'test-value';
8
+ expect((0, env_1.getEnv)('TEST_KEY')).toBe('test-value');
9
+ });
10
+ it('should throw an error if the env var is not set', () => {
11
+ delete process.env.MISSING_KEY;
12
+ expect(() => (0, env_1.getEnv)('MISSING_KEY')).toThrow('Missing env var: MISSING_KEY');
13
+ });
14
+ });
@@ -0,0 +1 @@
1
+ export declare function createTask(projectId: string, region: string, queueId: string, data: unknown, serviceAccount: string, audience: string): Promise<string>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTask = createTask;
4
+ const tasks_1 = require("@google-cloud/tasks");
5
+ const tasksClient = new tasks_1.CloudTasksClient();
6
+ async function createTask(projectId, region, queueId, data, serviceAccount, audience) {
7
+ if (!projectId || !region || !queueId || !serviceAccount || !audience) {
8
+ throw new Error('Missing required parameters for Cloud Tasks setup');
9
+ }
10
+ const parent = tasksClient.queuePath(projectId, region, queueId);
11
+ const task = {
12
+ httpRequest: {
13
+ httpMethod: tasks_1.protos.google.cloud.tasks.v2.HttpMethod.POST,
14
+ url: audience,
15
+ headers: {
16
+ 'Content-Type': 'application/json'
17
+ },
18
+ body: Buffer.from(JSON.stringify(data)).toString('base64'),
19
+ oidcToken: {
20
+ serviceAccountEmail: serviceAccount,
21
+ audience
22
+ }
23
+ }
24
+ };
25
+ const [response] = await tasksClient.createTask({ parent, task });
26
+ if (!response.name) {
27
+ throw new Error('Failed to create task: no name returned');
28
+ }
29
+ return response.name;
30
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const mockCreateTask = jest.fn();
4
+ const mockQueuePath = jest.fn((projectId, region, queueId) => `projects/${projectId}/locations/${region}/queues/${queueId}`);
5
+ jest.mock('@google-cloud/tasks', () => {
6
+ return {
7
+ CloudTasksClient: jest.fn(() => ({
8
+ createTask: mockCreateTask,
9
+ queuePath: mockQueuePath
10
+ })),
11
+ protos: {
12
+ google: {
13
+ cloud: {
14
+ tasks: {
15
+ v2: {
16
+ HttpMethod: {
17
+ POST: 'POST'
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }
23
+ }
24
+ };
25
+ });
26
+ const task_1 = require("./task");
27
+ describe('createTask', () => {
28
+ beforeEach(() => {
29
+ mockCreateTask.mockReset();
30
+ });
31
+ it('throws error if any required parameter is missing', async () => {
32
+ // Missing projectId
33
+ await expect((0, task_1.createTask)('', 'region', 'queue', {}, 'serviceAccount', 'audience')).rejects.toThrow('Missing required parameters for Cloud Tasks setup');
34
+ // Missing region
35
+ await expect((0, task_1.createTask)('project', '', 'queue', {}, 'serviceAccount', 'audience')).rejects.toThrow('Missing required parameters for Cloud Tasks setup');
36
+ // Missing queueId
37
+ await expect((0, task_1.createTask)('project', 'region', '', {}, 'serviceAccount', 'audience')).rejects.toThrow('Missing required parameters for Cloud Tasks setup');
38
+ // Missing serviceAccount
39
+ await expect((0, task_1.createTask)('project', 'region', 'queue', {}, '', 'audience')).rejects.toThrow('Missing required parameters for Cloud Tasks setup');
40
+ // Missing audience
41
+ await expect((0, task_1.createTask)('project', 'region', 'queue', {}, 'serviceAccount', '')).rejects.toThrow('Missing required parameters for Cloud Tasks setup');
42
+ });
43
+ it('should create a task and return task name', async () => {
44
+ const mockTaskName = 'projects/test-project/locations/us-central1/queues/test-queue/tasks/task-123';
45
+ mockCreateTask.mockResolvedValue([{ name: mockTaskName }]);
46
+ const result = await (0, task_1.createTask)('test-project', 'us-central1', 'test-queue', { test: 'data' }, 'test-sa@test.iam.gserviceaccount.com', 'https://run-url');
47
+ expect(result).toBe(mockTaskName);
48
+ expect(mockCreateTask).toHaveBeenCalledTimes(1);
49
+ });
50
+ it('should throw error if task name is missing', async () => {
51
+ mockCreateTask.mockResolvedValue([{}]); // Simulate missing name
52
+ await expect((0, task_1.createTask)('test-project', 'us-central1', 'test-queue', { foo: 'bar' }, 'test@project.iam.gserviceaccount.com', 'https://example.com')).rejects.toThrow('Failed to create task: no name returned');
53
+ });
54
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opticedge-cloud-utils",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Common utilities for cloud functions",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -16,6 +16,7 @@
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
18
  "@google-cloud/secret-manager": "^6.0.1",
19
+ "@google-cloud/tasks": "^6.1.0",
19
20
  "google-auth-library": "^9.15.1",
20
21
  "mongodb": "^6.16.0"
21
22
  },
package/src/index.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export * from './auth/verify'
2
- export * from './utils/secrets'
3
2
  export * from './db/mongo'
3
+ export * from './utils/env'
4
+ export * from './utils/secrets'
5
+ export * from './utils/task'
@@ -0,0 +1,14 @@
1
+ // src/utils/env.test.ts
2
+ import { getEnv } from './env'
3
+
4
+ describe('getEnv', () => {
5
+ it('should return the value of an existing env var', () => {
6
+ process.env.TEST_KEY = 'test-value'
7
+ expect(getEnv('TEST_KEY')).toBe('test-value')
8
+ })
9
+
10
+ it('should throw an error if the env var is not set', () => {
11
+ delete process.env.MISSING_KEY
12
+ expect(() => getEnv('MISSING_KEY')).toThrow('Missing env var: MISSING_KEY')
13
+ })
14
+ })
@@ -0,0 +1,7 @@
1
+ export function getEnv(name: string): string {
2
+ const value = process.env[name]
3
+ if (!value) {
4
+ throw new Error(`Missing env var: ${name}`)
5
+ }
6
+ return value
7
+ }
@@ -0,0 +1,94 @@
1
+ const mockCreateTask = jest.fn()
2
+ const mockQueuePath = jest.fn(
3
+ (projectId, region, queueId) => `projects/${projectId}/locations/${region}/queues/${queueId}`
4
+ )
5
+
6
+ jest.mock('@google-cloud/tasks', () => {
7
+ return {
8
+ CloudTasksClient: jest.fn(() => ({
9
+ createTask: mockCreateTask,
10
+ queuePath: mockQueuePath
11
+ })),
12
+ protos: {
13
+ google: {
14
+ cloud: {
15
+ tasks: {
16
+ v2: {
17
+ HttpMethod: {
18
+ POST: 'POST'
19
+ }
20
+ }
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
26
+ })
27
+
28
+ import { createTask } from './task'
29
+
30
+ describe('createTask', () => {
31
+ beforeEach(() => {
32
+ mockCreateTask.mockReset()
33
+ })
34
+
35
+ it('throws error if any required parameter is missing', async () => {
36
+ // Missing projectId
37
+ await expect(
38
+ createTask('', 'region', 'queue', {}, 'serviceAccount', 'audience')
39
+ ).rejects.toThrow('Missing required parameters for Cloud Tasks setup')
40
+
41
+ // Missing region
42
+ await expect(
43
+ createTask('project', '', 'queue', {}, 'serviceAccount', 'audience')
44
+ ).rejects.toThrow('Missing required parameters for Cloud Tasks setup')
45
+
46
+ // Missing queueId
47
+ await expect(
48
+ createTask('project', 'region', '', {}, 'serviceAccount', 'audience')
49
+ ).rejects.toThrow('Missing required parameters for Cloud Tasks setup')
50
+
51
+ // Missing serviceAccount
52
+ await expect(createTask('project', 'region', 'queue', {}, '', 'audience')).rejects.toThrow(
53
+ 'Missing required parameters for Cloud Tasks setup'
54
+ )
55
+
56
+ // Missing audience
57
+ await expect(
58
+ createTask('project', 'region', 'queue', {}, 'serviceAccount', '')
59
+ ).rejects.toThrow('Missing required parameters for Cloud Tasks setup')
60
+ })
61
+
62
+ it('should create a task and return task name', async () => {
63
+ const mockTaskName =
64
+ 'projects/test-project/locations/us-central1/queues/test-queue/tasks/task-123'
65
+ mockCreateTask.mockResolvedValue([{ name: mockTaskName }])
66
+
67
+ const result = await createTask(
68
+ 'test-project',
69
+ 'us-central1',
70
+ 'test-queue',
71
+ { test: 'data' },
72
+ 'test-sa@test.iam.gserviceaccount.com',
73
+ 'https://run-url'
74
+ )
75
+
76
+ expect(result).toBe(mockTaskName)
77
+ expect(mockCreateTask).toHaveBeenCalledTimes(1)
78
+ })
79
+
80
+ it('should throw error if task name is missing', async () => {
81
+ mockCreateTask.mockResolvedValue([{}]) // Simulate missing name
82
+
83
+ await expect(
84
+ createTask(
85
+ 'test-project',
86
+ 'us-central1',
87
+ 'test-queue',
88
+ { foo: 'bar' },
89
+ 'test@project.iam.gserviceaccount.com',
90
+ 'https://example.com'
91
+ )
92
+ ).rejects.toThrow('Failed to create task: no name returned')
93
+ })
94
+ })
@@ -0,0 +1,39 @@
1
+ import { CloudTasksClient, protos } from '@google-cloud/tasks'
2
+
3
+ const tasksClient = new CloudTasksClient()
4
+
5
+ export async function createTask(
6
+ projectId: string,
7
+ region: string,
8
+ queueId: string,
9
+ data: unknown,
10
+ serviceAccount: string,
11
+ audience: string
12
+ ): Promise<string> {
13
+ if (!projectId || !region || !queueId || !serviceAccount || !audience) {
14
+ throw new Error('Missing required parameters for Cloud Tasks setup')
15
+ }
16
+
17
+ const parent = tasksClient.queuePath(projectId, region, queueId)
18
+
19
+ const task: protos.google.cloud.tasks.v2.ITask = {
20
+ httpRequest: {
21
+ httpMethod: protos.google.cloud.tasks.v2.HttpMethod.POST,
22
+ url: audience,
23
+ headers: {
24
+ 'Content-Type': 'application/json'
25
+ },
26
+ body: Buffer.from(JSON.stringify(data)).toString('base64'),
27
+ oidcToken: {
28
+ serviceAccountEmail: serviceAccount,
29
+ audience
30
+ }
31
+ }
32
+ }
33
+
34
+ const [response] = await tasksClient.createTask({ parent, task })
35
+ if (!response.name) {
36
+ throw new Error('Failed to create task: no name returned')
37
+ }
38
+ return response.name
39
+ }