@optimizely-opal/opal-tool-ocp-sdk 0.0.0-dev.1 → 0.0.0-dev.3
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/README.md +154 -21
- package/dist/function/ToolFunction.d.ts +10 -1
- package/dist/function/ToolFunction.d.ts.map +1 -1
- package/dist/function/ToolFunction.js +12 -0
- package/dist/function/ToolFunction.js.map +1 -1
- package/dist/function/ToolFunction.test.js +24 -2
- package/dist/function/ToolFunction.test.js.map +1 -1
- package/package.json +8 -3
- package/src/function/ToolFunction.test.ts +29 -2
- package/src/function/ToolFunction.ts +12 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# OPAL
|
|
1
|
+
# OPAL TOOL OCP SDK
|
|
2
2
|
|
|
3
3
|
> **Optimizely Connect Platform (OCP) SDK for OPAL Tool**
|
|
4
4
|
|
|
@@ -34,11 +34,6 @@ Create a tool function class by extending `ToolFunction` and registering your to
|
|
|
34
34
|
import { ToolFunction, tool, interaction, ParameterType, InteractionResult, OptiIdAuthData } from '@optimizely-opal/opal-tool-ocp-sdk';
|
|
35
35
|
|
|
36
36
|
export class MyToolFunction extends ToolFunction {
|
|
37
|
-
// Implement required bearer token validation method
|
|
38
|
-
validateBearerToken(token: string): boolean {
|
|
39
|
-
const expectedToken = process.env.OPAL_TOOL_TOKEN;
|
|
40
|
-
return token === expectedToken;
|
|
41
|
-
}
|
|
42
37
|
|
|
43
38
|
// Register a simple tool without authentication
|
|
44
39
|
@tool({
|
|
@@ -181,16 +176,18 @@ The SDK automatically extracts Bearer tokens from the `authorization` header for
|
|
|
181
176
|
**Token Validation:**
|
|
182
177
|
- Bearer tokens are extracted from the `authorization: Bearer <token>` header
|
|
183
178
|
- Empty strings and `undefined` tokens are treated as missing (no validation performed)
|
|
184
|
-
-
|
|
179
|
+
- **Optionally override** the `validateBearerToken(token: string): boolean` method to implement custom validation logic
|
|
180
|
+
- The default implementation returns `true` (accepts all tokens) - override if you need custom authorization
|
|
181
|
+
- If validation fails, returns HTTP 403 Forbidden before reaching your handler methods
|
|
185
182
|
|
|
186
183
|
```typescript
|
|
187
184
|
export class MyToolFunction extends ToolFunction {
|
|
188
|
-
//
|
|
189
|
-
validateBearerToken(token: string): boolean {
|
|
190
|
-
// If you don't need bearer token validation,
|
|
191
|
-
//
|
|
185
|
+
// Optional: Override this method to implement custom bearer token validation
|
|
186
|
+
protected override validateBearerToken(token: string): boolean {
|
|
187
|
+
// If you don't need bearer token validation, don't override this method
|
|
188
|
+
// The default implementation returns true
|
|
192
189
|
|
|
193
|
-
// For
|
|
190
|
+
// For custom validation, compare against expected token
|
|
194
191
|
const expectedToken = process.env.OPAL_TOOL_TOKEN;
|
|
195
192
|
return token === expectedToken;
|
|
196
193
|
}
|
|
@@ -222,7 +219,8 @@ export class MyToolFunction extends ToolFunction {
|
|
|
222
219
|
- Set by users when registering tools in Opal
|
|
223
220
|
- Used to authorize tool requests from Opal instances
|
|
224
221
|
- Validates that requests are coming from trusted Opal sources
|
|
225
|
-
-
|
|
222
|
+
- **Optionally override** the `validateBearerToken(token: string): boolean` method for custom authorization
|
|
223
|
+
- Default implementation accepts all tokens - override for security
|
|
226
224
|
- If validation fails, returns HTTP 403 Forbidden before reaching your handler methods
|
|
227
225
|
|
|
228
226
|
|
|
@@ -280,11 +278,11 @@ Abstract base class for OCP functions:
|
|
|
280
278
|
```typescript
|
|
281
279
|
export abstract class ToolFunction extends Function {
|
|
282
280
|
public async perform(): Promise<Response>;
|
|
283
|
-
protected
|
|
281
|
+
protected validateBearerToken(token: string): boolean;
|
|
284
282
|
}
|
|
285
283
|
```
|
|
286
284
|
|
|
287
|
-
Extend this class and implement your OCP function. The `perform` method automatically routes requests to registered tools and handles bearer token validation. You
|
|
285
|
+
Extend this class and implement your OCP function. The `perform` method automatically routes requests to registered tools and handles bearer token validation. **You can optionally override the `validateBearerToken` method** to define custom bearer token authorization for your tools.
|
|
288
286
|
|
|
289
287
|
### Models
|
|
290
288
|
|
|
@@ -389,12 +387,8 @@ yarn lint
|
|
|
389
387
|
import { ToolFunction, tool, interaction, ParameterType, OptiIdAuthData, InteractionResult } from '@optimizely-opal/opal-ocp-sdk';
|
|
390
388
|
|
|
391
389
|
export class AuthenticatedFunction extends ToolFunction {
|
|
392
|
-
//
|
|
393
|
-
validateBearerToken(token: string): boolean {
|
|
394
|
-
// If you don't need bearer token validation, simply return true
|
|
395
|
-
// return true;
|
|
396
|
-
|
|
397
|
-
// For actual validation, compare against expected token
|
|
390
|
+
// Optional: Override this method for custom bearer token validation
|
|
391
|
+
protected override validateBearerToken(token: string): boolean {
|
|
398
392
|
const expectedToken = process.env.OPAL_TOOL_TOKEN;
|
|
399
393
|
return token === expectedToken;
|
|
400
394
|
}
|
|
@@ -435,3 +429,142 @@ export class AuthenticatedFunction extends ToolFunction {
|
|
|
435
429
|
}
|
|
436
430
|
}
|
|
437
431
|
```
|
|
432
|
+
|
|
433
|
+
### Organizing Tools in Separate Files
|
|
434
|
+
|
|
435
|
+
For larger projects, you can organize your tools in separate files and import them into your main ToolFunction class:
|
|
436
|
+
|
|
437
|
+
**Project Structure:**
|
|
438
|
+
```
|
|
439
|
+
src/
|
|
440
|
+
├── tools/
|
|
441
|
+
│ ├── index.ts
|
|
442
|
+
│ ├── TaskTool.ts
|
|
443
|
+
│ └── NotificationTool.ts
|
|
444
|
+
└── MyToolFunction.ts
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**tools/TaskTool.ts:**
|
|
448
|
+
```typescript
|
|
449
|
+
import { tool, ParameterType, OptiIdAuthData } from '@optimizely-opal/opal-ocp-sdk';
|
|
450
|
+
|
|
451
|
+
export class TaskTool {
|
|
452
|
+
@tool({
|
|
453
|
+
name: 'create_task',
|
|
454
|
+
description: 'Creates a new task in the system',
|
|
455
|
+
endpoint: '/create-task',
|
|
456
|
+
parameters: [
|
|
457
|
+
{
|
|
458
|
+
name: 'title',
|
|
459
|
+
type: ParameterType.String,
|
|
460
|
+
description: 'The task title',
|
|
461
|
+
required: true
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
name: 'priority',
|
|
465
|
+
type: ParameterType.String,
|
|
466
|
+
description: 'Task priority level',
|
|
467
|
+
required: false
|
|
468
|
+
}
|
|
469
|
+
]
|
|
470
|
+
})
|
|
471
|
+
async createTask(params: { title: string; priority?: string }, authData?: OptiIdAuthData) {
|
|
472
|
+
return {
|
|
473
|
+
id: '123',
|
|
474
|
+
title: params.title,
|
|
475
|
+
priority: params.priority || 'medium'
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
@tool({
|
|
480
|
+
name: 'delete_task',
|
|
481
|
+
description: 'Deletes a task from the system',
|
|
482
|
+
endpoint: '/delete-task',
|
|
483
|
+
parameters: [
|
|
484
|
+
{
|
|
485
|
+
name: 'taskId',
|
|
486
|
+
type: ParameterType.String,
|
|
487
|
+
description: 'The task ID to delete',
|
|
488
|
+
required: true
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
})
|
|
492
|
+
async deleteTask(params: { taskId: string }, authData?: OptiIdAuthData) {
|
|
493
|
+
return { success: true, deletedTaskId: params.taskId };
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
**tools/NotificationTool.ts:**
|
|
499
|
+
```typescript
|
|
500
|
+
import { tool, interaction, ParameterType, InteractionResult, OptiIdAuthData } from '@optimizely-opal/opal-ocp-sdk';
|
|
501
|
+
|
|
502
|
+
export class NotificationTool {
|
|
503
|
+
@tool({
|
|
504
|
+
name: 'send_notification',
|
|
505
|
+
description: 'Sends a notification to users',
|
|
506
|
+
endpoint: '/send-notification',
|
|
507
|
+
parameters: [
|
|
508
|
+
{
|
|
509
|
+
name: 'message',
|
|
510
|
+
type: ParameterType.String,
|
|
511
|
+
description: 'The notification message',
|
|
512
|
+
required: true
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
name: 'userId',
|
|
516
|
+
type: ParameterType.String,
|
|
517
|
+
description: 'Target user ID',
|
|
518
|
+
required: true
|
|
519
|
+
}
|
|
520
|
+
]
|
|
521
|
+
})
|
|
522
|
+
async sendNotification(params: { message: string; userId: string }, authData?: OptiIdAuthData) {
|
|
523
|
+
return {
|
|
524
|
+
notificationId: '456',
|
|
525
|
+
message: params.message,
|
|
526
|
+
userId: params.userId,
|
|
527
|
+
sent: true
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
@interaction({
|
|
532
|
+
name: 'notification_webhook',
|
|
533
|
+
endpoint: '/webhook/notification'
|
|
534
|
+
})
|
|
535
|
+
async handleNotificationWebhook(data: any): Promise<InteractionResult> {
|
|
536
|
+
return new InteractionResult(
|
|
537
|
+
`Notification ${data.notificationId} was delivered`,
|
|
538
|
+
`https://app.example.com/notifications/${data.notificationId}`
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
**tools/index.ts:**
|
|
545
|
+
```typescript
|
|
546
|
+
export * from './TaskTool';
|
|
547
|
+
export * from './NotificationTool';
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
**MyToolFunction.ts:**
|
|
551
|
+
```typescript
|
|
552
|
+
import { ToolFunction } from '@optimizely-opal/opal-ocp-sdk';
|
|
553
|
+
import * from './tools';
|
|
554
|
+
|
|
555
|
+
export class MyToolFunction extends ToolFunction {
|
|
556
|
+
|
|
557
|
+
// Optional: Override this method for custom bearer token validation
|
|
558
|
+
protected override validateBearerToken(token: string): boolean {
|
|
559
|
+
const expectedToken = process.env.OPAL_TOOL_TOKEN;
|
|
560
|
+
return token === expectedToken;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
This approach provides several benefits:
|
|
566
|
+
- **Better organization**: Each tool has its own file with related methods
|
|
567
|
+
- **Maintainability**: Easier to find and modify specific tools
|
|
568
|
+
- **Reusability**: Tools can be shared across different ToolFunction classes
|
|
569
|
+
- **Team collaboration**: Different developers can work on different tool files
|
|
570
|
+
- **Testing**: Each tool class can be unit tested independently
|
|
@@ -10,6 +10,15 @@ export declare abstract class ToolFunction extends Function {
|
|
|
10
10
|
* @returns Response as the HTTP response
|
|
11
11
|
*/
|
|
12
12
|
perform(): Promise<Response>;
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Validates the bearer token for authorization.
|
|
15
|
+
*
|
|
16
|
+
* This method provides a default implementation that accepts all tokens.
|
|
17
|
+
* Subclasses can override this method to implement custom bearer token validation logic.
|
|
18
|
+
*
|
|
19
|
+
* @param _bearerToken - The bearer token extracted from the Authorization header
|
|
20
|
+
* @returns true if the token is valid and the request should proceed, false to return 403 Forbidden
|
|
21
|
+
*/
|
|
22
|
+
protected validateBearerToken(_bearerToken: string): boolean;
|
|
14
23
|
}
|
|
15
24
|
//# sourceMappingURL=ToolFunction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolFunction.d.ts","sourceRoot":"","sources":["../../src/function/ToolFunction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGvD;;;GAGG;AACH,8BAAsB,YAAa,SAAQ,QAAQ;IAEjD;;;;OAIG;IACU,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;IASzC,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"ToolFunction.d.ts","sourceRoot":"","sources":["../../src/function/ToolFunction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGvD;;;GAGG;AACH,8BAAsB,YAAa,SAAQ,QAAQ;IAEjD;;;;OAIG;IACU,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;IASzC;;;;;;;;OAQG;IACH,SAAS,CAAC,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;CAG7D"}
|
|
@@ -20,6 +20,18 @@ class ToolFunction extends app_sdk_1.Function {
|
|
|
20
20
|
}
|
|
21
21
|
return Service_1.toolsService.processRequest(this.request);
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Validates the bearer token for authorization.
|
|
25
|
+
*
|
|
26
|
+
* This method provides a default implementation that accepts all tokens.
|
|
27
|
+
* Subclasses can override this method to implement custom bearer token validation logic.
|
|
28
|
+
*
|
|
29
|
+
* @param _bearerToken - The bearer token extracted from the Authorization header
|
|
30
|
+
* @returns true if the token is valid and the request should proceed, false to return 403 Forbidden
|
|
31
|
+
*/
|
|
32
|
+
validateBearerToken(_bearerToken) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
23
35
|
}
|
|
24
36
|
exports.ToolFunction = ToolFunction;
|
|
25
37
|
//# sourceMappingURL=ToolFunction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolFunction.js","sourceRoot":"","sources":["../../src/function/ToolFunction.ts"],"names":[],"mappings":";;;AAAA,+CAAuD;AACvD,gDAAkD;AAElD;;;GAGG;AACH,MAAsB,YAAa,SAAQ,kBAAQ;IAEjD;;;;OAIG;IACI,KAAK,CAAC,OAAO;QAClB,MAAM,WAAW,GAAG,sBAAY,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,WAAW,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC;YAC1D,OAAO,IAAI,kBAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,sBAAY,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACnD,CAAC;
|
|
1
|
+
{"version":3,"file":"ToolFunction.js","sourceRoot":"","sources":["../../src/function/ToolFunction.ts"],"names":[],"mappings":";;;AAAA,+CAAuD;AACvD,gDAAkD;AAElD;;;GAGG;AACH,MAAsB,YAAa,SAAQ,kBAAQ;IAEjD;;;;OAIG;IACI,KAAK,CAAC,OAAO;QAClB,MAAM,WAAW,GAAG,sBAAY,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,WAAW,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC;YAC1D,OAAO,IAAI,kBAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,sBAAY,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;;;OAQG;IACO,mBAAmB,CAAC,YAAoB;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA5BD,oCA4BC"}
|
|
@@ -34,10 +34,9 @@ class TestToolFunction extends ToolFunction_1.ToolFunction {
|
|
|
34
34
|
super(request || {}); // Pass the request parameter properly
|
|
35
35
|
// Set the request directly without defaulting to empty object
|
|
36
36
|
this.request = request;
|
|
37
|
-
// Create a mock implementation of the abstract method
|
|
38
37
|
this.mockValidateBearerToken = jest.fn().mockReturnValue(true);
|
|
39
38
|
}
|
|
40
|
-
//
|
|
39
|
+
// Override the concrete method with mock implementation for testing
|
|
41
40
|
validateBearerToken(bearerToken) {
|
|
42
41
|
return this.mockValidateBearerToken(bearerToken);
|
|
43
42
|
}
|
|
@@ -174,6 +173,29 @@ describe('ToolFunction', () => {
|
|
|
174
173
|
expect(mockProcessRequest).toHaveBeenCalledWith(mockRequest);
|
|
175
174
|
expect(result).toBe(mockResponse);
|
|
176
175
|
});
|
|
176
|
+
it('should use default validateBearerToken implementation when not overridden', async () => {
|
|
177
|
+
// Create a class that doesn't override validateBearerToken
|
|
178
|
+
class DefaultToolFunction extends ToolFunction_1.ToolFunction {
|
|
179
|
+
constructor(request) {
|
|
180
|
+
super(request || {});
|
|
181
|
+
this.request = request;
|
|
182
|
+
}
|
|
183
|
+
getRequest() {
|
|
184
|
+
return this.request;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Arrange
|
|
188
|
+
const defaultToolFunction = new DefaultToolFunction(mockRequest);
|
|
189
|
+
const bearerToken = 'any-token';
|
|
190
|
+
mockExtractBearerToken.mockReturnValue(bearerToken);
|
|
191
|
+
mockProcessRequest.mockResolvedValue(mockResponse);
|
|
192
|
+
// Act
|
|
193
|
+
const result = await defaultToolFunction.perform();
|
|
194
|
+
// Assert - Default implementation should return true and allow request to proceed
|
|
195
|
+
expect(mockExtractBearerToken).toHaveBeenCalledWith(mockRequest.headers);
|
|
196
|
+
expect(mockProcessRequest).toHaveBeenCalledWith(mockRequest);
|
|
197
|
+
expect(result).toBe(mockResponse);
|
|
198
|
+
});
|
|
177
199
|
});
|
|
178
200
|
describe('inheritance', () => {
|
|
179
201
|
it('should be an instance of Function', () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolFunction.test.js","sourceRoot":"","sources":["../../src/function/ToolFunction.test.ts"],"names":[],"mappings":";;AAAA,iDAA8C;AAC9C,gDAAkD;AAClD,+CAA6C;AAE7C,wBAAwB;AACxB,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC;IACrC,YAAY,EAAE;QACZ,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE;QACzB,kBAAkB,EAAE,IAAI,CAAC,EAAE,EAAE;KAC9B;CACF,CAAC,CAAC,CAAC;AAEJ,gEAAgE;AAChE,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;IACpC,QAAQ,EAAE;QACE,OAAO,CAAM;QACvB,YAAmB,KAAc;YAC/B,wDAAwD;YACxD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QACpB,CAAC;KACF;IACD,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACjD,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QACxD,MAAM;QACN,IAAI;QACJ,QAAQ,EAAE,IAAI;QACd,aAAa,EAAE,IAAI,UAAU,EAAE;KAChC,CAAC,CAAC;CACJ,CAAC,CAAC,CAAC;AAEJ,+CAA+C;AAC/C,MAAM,gBAAiB,SAAQ,2BAAY;IACjC,uBAAuB,CAAkD;IAEjF,YAAmB,OAAa;QAC9B,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,sCAAsC;QAC5D,8DAA8D;QAC7D,IAAY,CAAC,OAAO,GAAG,OAAO,CAAC;QAEhC,
|
|
1
|
+
{"version":3,"file":"ToolFunction.test.js","sourceRoot":"","sources":["../../src/function/ToolFunction.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optimizely-opal/opal-tool-ocp-sdk",
|
|
3
|
-
"version": "0.0.0-dev.
|
|
3
|
+
"version": "0.0.0-dev.3",
|
|
4
4
|
"description": "OCP SDK for Opal tool",
|
|
5
5
|
"scripts": {
|
|
6
|
+
"validate-deps": "node scripts/validate-deps.js",
|
|
7
|
+
"prebuild": "yarn run validate-deps",
|
|
6
8
|
"build": "yarn tsc",
|
|
7
9
|
"build-watch": "tsc -w",
|
|
8
10
|
"lint": "npx eslint 'src/**/*.ts'",
|
|
@@ -49,10 +51,13 @@
|
|
|
49
51
|
"rimraf": "^6.0.1",
|
|
50
52
|
"ts-jest": "^29.3.2",
|
|
51
53
|
"tslint": "^6.1.3",
|
|
52
|
-
"typescript": "^5.8.2"
|
|
54
|
+
"typescript": "^5.8.2",
|
|
55
|
+
"@zaiusinc/app-sdk": "2.2.1"
|
|
53
56
|
},
|
|
54
57
|
"dependencies": {
|
|
55
|
-
"@zaiusinc/app-sdk": "2.2.2",
|
|
56
58
|
"reflect-metadata": "^0.2.2"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"@zaiusinc/app-sdk": "2.2.1"
|
|
57
62
|
}
|
|
58
63
|
}
|
|
@@ -37,11 +37,10 @@ class TestToolFunction extends ToolFunction {
|
|
|
37
37
|
// Set the request directly without defaulting to empty object
|
|
38
38
|
(this as any).request = request;
|
|
39
39
|
|
|
40
|
-
// Create a mock implementation of the abstract method
|
|
41
40
|
this.mockValidateBearerToken = jest.fn().mockReturnValue(true);
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
//
|
|
43
|
+
// Override the concrete method with mock implementation for testing
|
|
45
44
|
protected validateBearerToken(bearerToken: string): boolean {
|
|
46
45
|
return this.mockValidateBearerToken(bearerToken);
|
|
47
46
|
}
|
|
@@ -208,6 +207,34 @@ describe('ToolFunction', () => {
|
|
|
208
207
|
expect(mockProcessRequest).toHaveBeenCalledWith(mockRequest);
|
|
209
208
|
expect(result).toBe(mockResponse);
|
|
210
209
|
});
|
|
210
|
+
|
|
211
|
+
it('should use default validateBearerToken implementation when not overridden', async () => {
|
|
212
|
+
// Create a class that doesn't override validateBearerToken
|
|
213
|
+
class DefaultToolFunction extends ToolFunction {
|
|
214
|
+
public constructor(request?: any) {
|
|
215
|
+
super(request || {});
|
|
216
|
+
(this as any).request = request;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public getRequest() {
|
|
220
|
+
return (this as any).request;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Arrange
|
|
225
|
+
const defaultToolFunction = new DefaultToolFunction(mockRequest);
|
|
226
|
+
const bearerToken = 'any-token';
|
|
227
|
+
mockExtractBearerToken.mockReturnValue(bearerToken);
|
|
228
|
+
mockProcessRequest.mockResolvedValue(mockResponse);
|
|
229
|
+
|
|
230
|
+
// Act
|
|
231
|
+
const result = await defaultToolFunction.perform();
|
|
232
|
+
|
|
233
|
+
// Assert - Default implementation should return true and allow request to proceed
|
|
234
|
+
expect(mockExtractBearerToken).toHaveBeenCalledWith(mockRequest.headers);
|
|
235
|
+
expect(mockProcessRequest).toHaveBeenCalledWith(mockRequest);
|
|
236
|
+
expect(result).toBe(mockResponse);
|
|
237
|
+
});
|
|
211
238
|
});
|
|
212
239
|
|
|
213
240
|
describe('inheritance', () => {
|
|
@@ -21,5 +21,16 @@ export abstract class ToolFunction extends Function {
|
|
|
21
21
|
return toolsService.processRequest(this.request);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Validates the bearer token for authorization.
|
|
26
|
+
*
|
|
27
|
+
* This method provides a default implementation that accepts all tokens.
|
|
28
|
+
* Subclasses can override this method to implement custom bearer token validation logic.
|
|
29
|
+
*
|
|
30
|
+
* @param _bearerToken - The bearer token extracted from the Authorization header
|
|
31
|
+
* @returns true if the token is valid and the request should proceed, false to return 403 Forbidden
|
|
32
|
+
*/
|
|
33
|
+
protected validateBearerToken(_bearerToken: string): boolean {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
25
36
|
}
|